diff options
author | Patrick Palka <ppalka@redhat.com> | 2022-05-24 09:27:39 -0400 |
---|---|---|
committer | Patrick Palka <ppalka@redhat.com> | 2022-05-24 09:27:39 -0400 |
commit | d0ef9e06197d14d7ba60404e37bd27c21791ba3d (patch) | |
tree | 6fb336ae02fc1c1ac897dea02c55f1a7e8332343 /gcc/cp/typeck.cc | |
parent | 442cf0977a2993940a81aac08134fcdde4fb3035 (diff) | |
download | gcc-d0ef9e06197d14d7ba60404e37bd27c21791ba3d.zip gcc-d0ef9e06197d14d7ba60404e37bd27c21791ba3d.tar.gz gcc-d0ef9e06197d14d7ba60404e37bd27c21791ba3d.tar.bz2 |
c++: set TYPE_CANONICAL for more template types
When forming a class template specialization, lookup_template_class
uses structural equality for the specialized type whenever one of its
template arguments uses structural equality. This is the sensible thing
to do in a vacuum, but given that we already effectively deduplicate class
specializations via the type_specializations table, we ought to be able
to safely assume that each class specialization is unique and therefore
canonical, regardless of the canonicity of the template arguments.
To that end this patch makes us use the canonical type machinery for all
type specializations, except for the case where a PARM_DECL appears in
the template arguments (this special case was recently added by
r12-3766-g72394d38d929c7).
Additionally, this patch makes us use the canonical type machinery for
TEMPLATE_TEMPLATE_PARMs and BOUND_TEMPLATE_TEMPLATE_PARMs, by extending
canonical_type_parameter appropriately. A comment in tsubst says it's
unsafe to set TYPE_CANONICAL for a lowered TEMPLATE_TEMPLATE_PARM, but
I'm not sure this is true anymore. According to Jason, this comment
(from r120341) became obsolete when later that year r129844 started to
substitute the template parms of ttps. Note that r10-7817-ga6f400239d792d
recently changed process_template_parm to clear TYPE_CANONICAL for
TEMPLATE_TEMPLATE_PARM consistent with the tsubst comment; this patch
changes both functions to set instead of clear TYPE_CANONICAL for ttps.
These changes improve compile time of template-heavy code by around 10%
for me (with a release compiler). For instance, compile time for the
libstdc++ test std/ranges/adaptors/all.cc drops from 1.45s to 1.25s, and
for the range-v3 test test/view/zip.cpp from 5.38s to 4.88s. The total
number of calls to structural_comptypes for the latter test drops from
10.5M to 1.8M. Memory use is unaffected (as expected).
The new testcase verifies we check the r12-3766 PARM_DECL special case
in bind_template_template_parm too.
gcc/cp/ChangeLog:
* cp-tree.h (any_template_arguments_need_structural_equality_p):
Declare.
* pt.cc (struct ctp_hasher): Define.
(ctp_table): Define.
(canonical_type_parameter): Use it.
(process_template_parm): Set TYPE_CANONICAL for
TEMPLATE_TEMPLATE_PARM too.
(lookup_template_class_1): Remove now outdated comment for the
any_template_arguments_need_structural_equality_p test.
(tsubst) <case TEMPLATE_TEMPLATE_PARM, etc>: Don't specifically
clear TYPE_CANONICAL for ttps. Set TYPE_CANONICAL on the
substituted type later.
(any_template_arguments_need_structural_equality_p): Return
true for any_targ_node. Don't return true just because a
template argument uses structural equality. Add comment for
the PARM_DECL special case.
(rewrite_template_parm): Set TYPE_CANONICAL on the rewritten
parm's type later.
* tree.cc (bind_template_template_parm): Set TYPE_CANONICAL
when safe to do so.
* typeck.cc (structural_comptypes) [check_alias]: Increment
processing_template_decl before checking
dependent_alias_template_spec_p.
gcc/testsuite/ChangeLog:
* g++.dg/cpp0x/constexpr-52830a.C: New test.
Diffstat (limited to 'gcc/cp/typeck.cc')
-rw-r--r-- | gcc/cp/typeck.cc | 2 |
1 files changed, 2 insertions, 0 deletions
diff --git a/gcc/cp/typeck.cc b/gcc/cp/typeck.cc index 6ecdd97..385cdf4 100644 --- a/gcc/cp/typeck.cc +++ b/gcc/cp/typeck.cc @@ -1511,8 +1511,10 @@ structural_comptypes (tree t1, tree t2, int strict) substitute into the specialization arguments at instantiation time. And aliases can't be equivalent without being ==, so we don't need to look any deeper. */ + ++processing_template_decl; tree dep1 = dependent_alias_template_spec_p (t1, nt_transparent); tree dep2 = dependent_alias_template_spec_p (t2, nt_transparent); + --processing_template_decl; if ((dep1 || dep2) && dep1 != dep2) return false; } |