c++: alias template template_info setting
authorNathan Sidwell <nathan@acm.org>
Tue, 18 Aug 2020 21:48:58 +0000 (14:48 -0700)
committerNathan Sidwell <nathan@acm.org>
Tue, 18 Aug 2020 21:52:22 +0000 (14:52 -0700)
During the construction of alias templates we can alter its
template_info.  This is really weird, because that's morally immutable
data.  In this case it's ok, but let's not create a duplicate
template_info, and add asserts to make sure it is changing in exactly
the way we expect.

gcc/cp/
* cp-tree.h (SET_TYPE_TEMPLTE_INFO): Do not deal with ALIAS templates.
* pt.c (lookup_template_class_1): Special-case alias template
template_info setting.

gcc/cp/cp-tree.h
gcc/cp/pt.c

index 5ba82ee..44531cd 100644 (file)
@@ -3485,13 +3485,12 @@ struct GTY(()) lang_decl {
    ? TYPE_ALIAS_TEMPLATE_INFO (NODE)                                   \
    : TYPE_TEMPLATE_INFO (NODE))
 
-/* Set the template information for an ENUMERAL_, RECORD_, or
-   UNION_TYPE to VAL.  */
+/* Set the template information for a non-alias n ENUMERAL_, RECORD_,
+   or UNION_TYPE to VAL.  ALIAS's are dealt with separately.  */
 #define SET_TYPE_TEMPLATE_INFO(NODE, VAL)                              \
-  (TREE_CODE (NODE) == ENUMERAL_TYPE                                   \
-   || (CLASS_TYPE_P (NODE) && !TYPE_ALIAS_P (NODE))                    \
-   ? (TYPE_LANG_SLOT_1 (NODE) = (VAL))                         \
-   : (DECL_TEMPLATE_INFO (TYPE_NAME (NODE)) = (VAL)))
+  (gcc_checking_assert (TREE_CODE (NODE) == ENUMERAL_TYPE              \
+                       || (CLASS_TYPE_P (NODE) && !TYPE_ALIAS_P (NODE))), \
+   (TYPE_LANG_SLOT_1 (NODE) = (VAL)))                                  \
 
 #define TI_TEMPLATE(NODE) \
   ((struct tree_template_info*)TEMPLATE_INFO_CHECK (NODE))->tmpl
index 8ad91b3..edaefcf 100644 (file)
@@ -10088,8 +10088,26 @@ lookup_template_class_1 (tree d1, tree arglist, tree in_decl, tree context,
            }
        }
 
-      // Build template info for the new specialization.
-      SET_TYPE_TEMPLATE_INFO (t, build_template_info (found, arglist));
+      /* Build template info for the new specialization.  */
+      if (TYPE_ALIAS_P (t))
+       {
+         /* This is constructed during instantiation of the alias
+            decl.  But for member templates of template classes, that
+            is not correct as we need to refer to the partially
+            instantiated template, not the most general template.
+            The incorrect knowledge will not have escaped this
+            instantiation process, so we're good just updating the
+            template_info we made then.  */
+         tree ti = DECL_TEMPLATE_INFO (TYPE_NAME (t));
+         gcc_checking_assert (template_args_equal (TI_ARGS (ti), arglist));
+         if (TI_TEMPLATE (ti) != found)
+           {
+             gcc_checking_assert (DECL_TI_TEMPLATE (found) == TI_TEMPLATE (ti));
+             TI_TEMPLATE (ti) = found;
+           }
+       }
+      else
+       SET_TYPE_TEMPLATE_INFO (t, build_template_info (found, arglist));
 
       elt.spec = t;
       slot = type_specializations->find_slot_with_hash (&elt, hash, INSERT);