Tested x86_64-pc-linux-gnu, applying to trunk.

-- 8< --

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.
---
 gcc/cp/pt.cc | 36 +++++++++---------------------------
 1 file changed, 9 insertions(+), 27 deletions(-)

diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index 3f1cf139bbd..471fc20bc5b 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, we've
+                already substituted its type.  */
+             if (CLASS_TYPE_P (t)
+                 && CLASSTYPE_IS_TEMPLATE (t))
+               continue;
 
-             /* 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;
              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);

base-commit: f9861511a1fa0f9e386f3f7bcee84b6e3ca3c579
-- 
2.31.1

Reply via email to