Bootstrapped and regtested on x86_64-pc-linux-gnu, does this look OK
for trunk?

-- >8 --

This patch makes tsubst_template_decl use use_spec_table=false also in
the non-class non-function template case, to avoid computing 'argvec' and
doing a hash table lookup from tsubst_decl (when partially instantiating
a member variable or alias template).

This change reveals that for function templates, tsubst_template_decl
registers the partially instantiated TEMPLATE_DECL, whereas for other
non-class templates it registers the corresponding DECL_TEMPLATE_RESULT
which is an interesting inconsistency that I decided to preserve for now.
Trying to consistently register the TEMPLATE_DECL (or FUNCTION_DECL)
causes modules crashes, but I haven't looked into why.

In passing, I noticed in tsubst_function_decl that its 'argvec' goes
unused when 'lambda_fntype' is set (since lambdas aren't recorded in the
specializations table), so we can avoid computing it in that case.

gcc/cp/ChangeLog:

        * pt.cc (tsubst_function_decl): Don't bother computing 'argvec'
        when 'lambda_fntype' is set.
        (tsubst_template_decl): Make sure we return a TEMPLATE_DECL
        after specialization lookup.  In the non-class non-function
        template case, use tsubst_decl directly with use_spec_table=false,
        update DECL_TI_ARGS and call register_specialization like
        tsubst_decl would have done if use_spec_table=true.
---
 gcc/cp/pt.cc | 39 +++++++++++++++++++++------------------
 1 file changed, 21 insertions(+), 18 deletions(-)

diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index 777ff592789..cc8ba21d6fd 100644
--- a/gcc/cp/pt.cc
+++ b/gcc/cp/pt.cc
@@ -14370,7 +14370,7 @@ tsubst_function_decl (tree t, tree args, tsubst_flags_t 
complain,
 
       /* Calculate the complete set of arguments used to
         specialize R.  */
-      if (use_spec_table)
+      if (use_spec_table && !lambda_fntype)
        {
          argvec = tsubst_template_args (DECL_TI_ARGS
                                         (DECL_TEMPLATE_RESULT
@@ -14380,14 +14380,11 @@ tsubst_function_decl (tree t, tree args, 
tsubst_flags_t complain,
            return error_mark_node;
 
          /* Check to see if we already have this specialization.  */
-         if (!lambda_fntype)
-           {
-             hash = spec_hasher::hash (gen_tmpl, argvec);
-             if (tree spec = retrieve_specialization (gen_tmpl, argvec, hash))
-               /* The spec for these args might be a partial instantiation of 
the
-                  template, but here what we want is the FUNCTION_DECL.  */
-               return STRIP_TEMPLATE (spec);
-           }
+         hash = spec_hasher::hash (gen_tmpl, argvec);
+         if (tree spec = retrieve_specialization (gen_tmpl, argvec, hash))
+           /* The spec for these args might be a partial instantiation of the
+              template, but here what we want is the FUNCTION_DECL.  */
+           return STRIP_TEMPLATE (spec);
        }
       else
        argvec = args;
@@ -14704,6 +14701,8 @@ tsubst_template_decl (tree t, tree args, tsubst_flags_t 
complain,
            /* Type partial instantiations are stored as the type by
               lookup_template_class_1, not here as the template.  */
            spec = CLASSTYPE_TI_TEMPLATE (spec);
+         else if (TREE_CODE (spec) != TEMPLATE_DECL)
+           spec = DECL_TI_TEMPLATE (spec);
          return spec;
        }
     }
@@ -14754,7 +14753,7 @@ tsubst_template_decl (tree t, tree args, tsubst_flags_t 
complain,
        inner = tsubst_aggr_type (inner, args, complain,
                                  in_decl, /*entering*/1);
       else
-       inner = tsubst (inner, args, complain, in_decl);
+       inner = tsubst_decl (inner, args, complain, /*use_spec_table=*/false);
     }
   --processing_template_decl;
   if (inner == error_mark_node)
@@ -14780,12 +14779,11 @@ tsubst_template_decl (tree t, tree args, 
tsubst_flags_t complain,
     }
   else
     {
-      if (TREE_CODE (inner) == FUNCTION_DECL)
-       /* Set DECL_TI_ARGS to the full set of template arguments, which
-          tsubst_function_decl didn't do due to use_spec_table=false.  */
-       DECL_TI_ARGS (inner) = full_args;
-
       DECL_TI_TEMPLATE (inner) = r;
+      /* Set DECL_TI_ARGS to the full set of template arguments,
+        which tsubst_function_decl / tsubst_decl didn't do due to
+        use_spec_table=false.  */
+      DECL_TI_ARGS (inner) = full_args;
       DECL_TI_ARGS (r) = DECL_TI_ARGS (inner);
     }
 
@@ -14813,9 +14811,14 @@ tsubst_template_decl (tree t, tree args, 
tsubst_flags_t complain,
   if (PRIMARY_TEMPLATE_P (t))
     DECL_PRIMARY_TEMPLATE (r) = r;
 
-  if (TREE_CODE (decl) == FUNCTION_DECL && !lambda_fntype)
-    /* Record this non-type partial instantiation.  */
-    register_specialization (r, t, full_args, false, hash);
+  if (!lambda_fntype && !class_p)
+    {
+      /* Record this non-type partial instantiation.  */
+      if (TREE_CODE (inner) == FUNCTION_DECL)
+       register_specialization (r, t, full_args, false, hash);
+      else
+       register_specialization (inner, t, full_args, false, hash);
+    }
 
   return r;
 }
-- 
2.42.0.216.gbda494f404

Reply via email to