aboutsummaryrefslogtreecommitdiff
path: root/gcc/cp/typeck.cc
diff options
context:
space:
mode:
authorPatrick Palka <ppalka@redhat.com>2022-05-24 09:27:39 -0400
committerPatrick Palka <ppalka@redhat.com>2022-05-24 09:27:39 -0400
commitd0ef9e06197d14d7ba60404e37bd27c21791ba3d (patch)
tree6fb336ae02fc1c1ac897dea02c55f1a7e8332343 /gcc/cp/typeck.cc
parent442cf0977a2993940a81aac08134fcdde4fb3035 (diff)
downloadgcc-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.cc2
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;
}