aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJason Merrill <jason@redhat.com>2023-05-02 14:54:46 -0400
committerJason Merrill <jason@redhat.com>2023-05-02 18:53:06 -0400
commitc912fe765a1378f1b09d1095ab4e093d5205122a (patch)
tree3a318562d74fe869684247b630226e3a16d5c51c
parent33020780a9699f1146eeed61783cec89fde337a0 (diff)
downloadgcc-c912fe765a1378f1b09d1095ab4e093d5205122a.zip
gcc-c912fe765a1378f1b09d1095ab4e093d5205122a.tar.gz
gcc-c912fe765a1378f1b09d1095ab4e093d5205122a.tar.bz2
c++: simplify member template substitution
I noticed that for member class templates of a class template we were unnecessarily substituting both the template and its type. Avoiding that duplication speeds compilation of this silly testcase from ~12s to ~9s on my laptop. It's unlikely to make a difference on any real code, but the simplification is also nice. We still need to clear CLASSTYPE_USE_TEMPLATE on the partial instantiation of the template class, but it makes more sense to do that in tsubst_template_decl anyway. #define NC(X) \ template <class U> struct X##1; \ template <class U> struct X##2; \ template <class U> struct X##3; \ template <class U> struct X##4; \ template <class U> struct X##5; \ template <class U> struct X##6; #define NC2(X) NC(X##a) NC(X##b) NC(X##c) NC(X##d) NC(X##e) NC(X##f) #define NC3(X) NC2(X##A) NC2(X##B) NC2(X##C) NC2(X##D) NC2(X##E) template <int I> struct A { NC3(am) }; template <class...Ts> void sink(Ts...); template <int...Is> void g() { sink(A<Is>()...); } template <int I> void f() { g<__integer_pack(I)...>(); } int main() { f<1000>(); } gcc/cp/ChangeLog: * pt.cc (instantiate_class_template): Skip the RECORD_TYPE of a class template. (tsubst_template_decl): Clear CLASSTYPE_USE_TEMPLATE.
-rw-r--r--gcc/cp/pt.cc38
1 files changed, 10 insertions, 28 deletions
diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index 3f1cf13..471fc20 100644
--- a/gcc/cp/pt.cc
+++ b/gcc/cp/pt.cc
@@ -12285,21 +12285,13 @@ instantiate_class_template (tree type)
Ignore it; it will be regenerated when needed. */
continue;
- bool class_template_p = (TREE_CODE (t) != ENUMERAL_TYPE
- && TYPE_LANG_SPECIFIC (t)
- && CLASSTYPE_IS_TEMPLATE (t));
-
- /* If the member is a class template, then -- even after
- substitution -- there may be dependent types in the
- template argument list for the class. We increment
- PROCESSING_TEMPLATE_DECL so that dependent_type_p, as
- that function will assume that no types are dependent
- when outside of a template. */
- if (class_template_p)
- ++processing_template_decl;
+ /* If the member is a class template, we've
+ already substituted its type. */
+ if (CLASS_TYPE_P (t)
+ && CLASSTYPE_IS_TEMPLATE (t))
+ continue;
+
tree newtag = tsubst (t, args, tf_error, NULL_TREE);
- if (class_template_p)
- --processing_template_decl;
if (newtag == error_mark_node)
continue;
@@ -12307,19 +12299,6 @@ instantiate_class_template (tree type)
{
tree name = TYPE_IDENTIFIER (t);
- if (class_template_p)
- /* Unfortunately, lookup_template_class sets
- CLASSTYPE_IMPLICIT_INSTANTIATION for a partial
- instantiation (i.e., for the type of a member
- template class nested within a template class.)
- This behavior is required for
- maybe_process_partial_specialization to work
- correctly, but is not accurate in this case;
- the TAG is not an instantiation of anything.
- (The corresponding TEMPLATE_DECL is an
- instantiation, but the TYPE is not.) */
- CLASSTYPE_USE_TEMPLATE (newtag) = 0;
-
/* Now, install the tag. We don't use pushtag
because that does too much work -- creating an
implicit typedef, which we've already done. */
@@ -14750,7 +14729,10 @@ tsubst_template_decl (tree t, tree args, tsubst_flags_t complain,
/* For a partial specialization, we need to keep pointing to
the primary template. */
if (!DECL_TEMPLATE_SPECIALIZATION (t))
- CLASSTYPE_TI_TEMPLATE (inner) = r;
+ {
+ CLASSTYPE_TI_TEMPLATE (inner) = r;
+ CLASSTYPE_USE_TEMPLATE (inner) = 0;
+ }
DECL_TI_ARGS (r) = CLASSTYPE_TI_ARGS (inner);
inner = TYPE_MAIN_DECL (inner);