On Thu, 7 Mar 2024, Patrick Palka wrote:

> On Wed, 6 Mar 2024, Jason Merrill wrote:
> 
> > On 3/4/24 17:26, Patrick Palka wrote:
> > > Bootstrapped and regtested on x86_64-pc-linux-gnu, does this look
> > > OK for trunk?
> > > 
> > > -- >8 --
> > > 
> > > Alias templates are weird in that their specializations can appear in
> > > both decl_specializations and type_specializations.  They appear in the
> > > latter only at parse time via finish_template_type.  This should probably
> > > be revisited in GCC 15 since it seems sufficient to store them only in
> > > decl_specializations.
> > 
> > It looks like most all of lookup_template_class is wrong for alias 
> > templates.
> > 
> > Can we move the alias template handling up higher and unconditionally return
> > the result of tsubst?
> 
> This works nicely (although we have to use instantiate_alias_template
> directly instead of tsubst since tsubst would first substitute the
> uncoerced arguments into the generic DECL_TI_ARGS which breaks for
> for parameter packs).  And it allows for some nice simplifications in
> the modules code which had to handle alias template specializations
> specially.
> 
> Bootstrapped and regtested on x86_64-pc-linux-gnu.
> 
> -- >8 --
> 
> Subject: [PATCH] c++/modules: member alias tmpl partial inst [PR103994]
> 
> Alias templates are weird in that their specializations can appear in
> both decl_specializations and type_specializations.  They appear in the
> type table only at parse time via finish_template_type.  There seems
> to be no good reason for this, and the code paths end up stepping over
> each other in particular for a partial alias template instantiation such
> as A<B>::key_arg<T> in the below modules testcase: the type code path
> (lookup_template_class) wants to set TI_TEMPLATE to the most general
> template whereas the decl code path (tsubst_template_decl called during
> instantiation of A<B>) already set TI_TEMPLATE to the partially
> instantiated TEMPLATE_DECL.  This ends up confusing modules which
> decides to stream the logically equivalent TYPE_DECL and TEMPLATE_DECL
> for this partial alias template instantiation separately.
> 
> This patch fixes this by making lookup_template_class dispatch to
> instantiatie_alias_template early for alias template specializations.
> In turn we now only add such specializations to the decl table and
> not also the type table.  This admits some nice simplification in
> the modules code which otherwise has to cope with such specializations
> appearing in both tables.
> 
>       PR c++/103994
> 
> gcc/cp/ChangeLog:
> 
>       * cp-tree.h (add_mergeable_specialization): Remove is_alias
>       parameter.
>       * module.cc (depset::disc_bits::DB_ALIAS_SPEC_BIT): Remove.
>       (depset::is_alias): Remove.
>       (merge_kind::MK_tmpl_alias_mask): Remove.
>       (merge_kind::MK_alias_spec): Remove.
>       (merge_kind_name): Remove entries for alias specializations.
>       (trees_in::decl_value): Adjust add_mergeable_specialization
>       calls.
>       (trees_out::get_merge_kind) <case depset::EK_SPECIALIZATION>:
>       Use MK_decl_spec for alias template specializations.
>       (trees_out::key_mergeable): Simplify after MK_tmpl_alias_mask
>       removal.
>       (specialization_add): Don't allow alias templates when !decl_p.
>       (depset::hash::add_specializations): Remove now-dead code
>       accomodating alias template specializations in the type table.
>       * pt.cc (lookup_template_class): Dispatch early to
>       instantiate_alias_template for alias templates.  Simplify
>       accordingly.
>       (add_mergeable_specialization): Remove alias_p parameter and
>       simplify accordingly.
> 
> gcc/testsuite/ChangeLog:
> 
>       * g++.dg/modules/pr99425-1_b.H: s/alias/decl in dump scan.
>       * g++.dg/modules/tpl-alias-1_a.H: Likewise.
>       * g++.dg/modules/tpl-alias-2_a.H: New test.
>       * g++.dg/modules/tpl-alias-2_b.C: New test.
> ---
>  gcc/cp/cp-tree.h                             |  3 +-
>  gcc/cp/module.cc                             | 50 ++----------
>  gcc/cp/pt.cc                                 | 84 ++++++++------------
>  gcc/testsuite/g++.dg/modules/pr99425-1_b.H   |  2 +-
>  gcc/testsuite/g++.dg/modules/tpl-alias-1_a.H |  2 +-
>  gcc/testsuite/g++.dg/modules/tpl-alias-2_a.H | 15 ++++
>  gcc/testsuite/g++.dg/modules/tpl-alias-2_b.C |  9 +++
>  7 files changed, 69 insertions(+), 96 deletions(-)
>  create mode 100644 gcc/testsuite/g++.dg/modules/tpl-alias-2_a.H
>  create mode 100644 gcc/testsuite/g++.dg/modules/tpl-alias-2_b.C
> 
> diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
> index 4469d965ef0..14895bc6585 100644
> --- a/gcc/cp/cp-tree.h
> +++ b/gcc/cp/cp-tree.h
> @@ -7642,8 +7642,7 @@ extern void walk_specializations                (bool,
>                                                void *);
>  extern tree match_mergeable_specialization   (bool is_decl, spec_entry *);
>  extern unsigned get_mergeable_specialization_flags (tree tmpl, tree spec);
> -extern void add_mergeable_specialization        (bool is_decl, bool is_alias,
> -                                              spec_entry *,
> +extern void add_mergeable_specialization        (bool is_decl, spec_entry *,
>                                                tree outer, unsigned);
>  extern tree add_to_template_args             (tree, tree);
>  extern tree add_outermost_template_args              (tree, tree);
> diff --git a/gcc/cp/module.cc b/gcc/cp/module.cc
> index 4ecd6d7c813..cc038ee9cba 100644
> --- a/gcc/cp/module.cc
> +++ b/gcc/cp/module.cc
> @@ -2306,10 +2306,7 @@ private:
>      /* The following bits are not independent, but enumerating them is
>         awkward.  */
>      DB_ALIAS_TMPL_INST_BIT,  /* An alias template instantiation. */

It seems we don't need DB_ALIAS_TMPL_INST_BIT anymore either, so the
updated patch below removes it too.

-- >8 --

        PR c++/103994

gcc/cp/ChangeLog:

        * cp-tree.h (add_mergeable_specialization): Remove is_alias
        parameter.
        * module.cc (depset::disc_bits::DB_ALIAS_TMPL_INST_BIT): Remove.
        (depset::disc_bits::DB_ALIAS_SPEC_BIT): Remove.
        (depset::is_alias_tmpl_inst): Remove.
        (depset::is_alias): Remove.
        (merge_kind::MK_tmpl_alias_mask): Remove.
        (merge_kind::MK_alias_spec): Remove.
        (merge_kind_name): Remove entries for alias specializations.
        (trees_out::core_vals) <case TEMPLATE_DECL>: Adjust after
        removing is_alias_tmpl_inst.
        (trees_in::decl_value): Adjust add_mergeable_specialization
        calls.
        (trees_out::get_merge_kind) <case depset::EK_SPECIALIZATION>:
        Use MK_decl_spec for alias template specializations.
        (trees_out::key_mergeable): Simplify after MK_tmpl_alias_mask
        removal.
        (depset::hash::make_dependency): Adjust after removing
        DB_ALIAS_TMPL_INST_BIT.
        (specialization_add): Don't allow alias templates when !decl_p.
        (depset::hash::add_specializations): Remove now-dead code
        accomodating alias template specializations in the type table.
        * pt.cc (lookup_template_class): Dispatch early to
        instantiate_alias_template for alias templates.  Simplify
        accordingly.
        (add_mergeable_specialization): Remove alias_p parameter and
        simplify accordingly.

gcc/testsuite/ChangeLog:

        * g++.dg/modules/pr99425-1_b.H: s/alias/decl in dump scan.
        * g++.dg/modules/tpl-alias-1_a.H: Likewise.
        * g++.dg/modules/tpl-alias-2_a.H: New test.
        * g++.dg/modules/tpl-alias-2_b.C: New test.
---
 gcc/cp/cp-tree.h                             |  3 +-
 gcc/cp/module.cc                             | 86 ++++----------------
 gcc/cp/pt.cc                                 | 84 ++++++++-----------
 gcc/testsuite/g++.dg/modules/pr99425-1_b.H   |  2 +-
 gcc/testsuite/g++.dg/modules/tpl-alias-1_a.H |  2 +-
 gcc/testsuite/g++.dg/modules/tpl-alias-2_a.H | 15 ++++
 gcc/testsuite/g++.dg/modules/tpl-alias-2_b.C |  9 ++
 7 files changed, 78 insertions(+), 123 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/modules/tpl-alias-2_a.H
 create mode 100644 gcc/testsuite/g++.dg/modules/tpl-alias-2_b.C

diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 4469d965ef0..14895bc6585 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -7642,8 +7642,7 @@ extern void walk_specializations          (bool,
                                                 void *);
 extern tree match_mergeable_specialization     (bool is_decl, spec_entry *);
 extern unsigned get_mergeable_specialization_flags (tree tmpl, tree spec);
-extern void add_mergeable_specialization        (bool is_decl, bool is_alias,
-                                                spec_entry *,
+extern void add_mergeable_specialization        (bool is_decl, spec_entry *,
                                                 tree outer, unsigned);
 extern tree add_to_template_args               (tree, tree);
 extern tree add_outermost_template_args                (tree, tree);
diff --git a/gcc/cp/module.cc b/gcc/cp/module.cc
index 4ecd6d7c813..dfe4536c0ae 100644
--- a/gcc/cp/module.cc
+++ b/gcc/cp/module.cc
@@ -2305,11 +2305,7 @@ private:
     DB_HIDDEN_BIT,             /* A hidden binding.  */
     /* The following bits are not independent, but enumerating them is
        awkward.  */
-    DB_ALIAS_TMPL_INST_BIT,    /* An alias template instantiation. */
-    DB_ALIAS_SPEC_BIT,         /* Specialization of an alias template
-                                  (in both spec tables).  */
-    DB_TYPE_SPEC_BIT,          /* Specialization in the type table.
-                                  */
+    DB_TYPE_SPEC_BIT,          /* Specialization in the type table.  */
     DB_FRIEND_SPEC_BIT,                /* An instantiated template friend.  */
   };
 
@@ -2400,14 +2396,6 @@ public:
   {
     return get_flag_bit<DB_UNREACHED_BIT> ();
   }
-  bool is_alias_tmpl_inst () const
-  {
-    return get_flag_bit<DB_ALIAS_TMPL_INST_BIT> ();
-  }
-  bool is_alias () const
-  {
-    return get_flag_bit<DB_ALIAS_SPEC_BIT> ();
-  }
   bool is_hidden () const
   {
     return get_flag_bit<DB_HIDDEN_BIT> ();
@@ -2782,13 +2770,11 @@ enum merge_kind
   MK_template_mask = 0x10,  /* A template specialization.  */
 
   MK_tmpl_decl_mask = 0x4, /* In decl table.  */
-  MK_tmpl_alias_mask = 0x2, /* Also in type table  */
 
   MK_tmpl_tmpl_mask = 0x1, /* We want TEMPLATE_DECL.  */
 
   MK_type_spec = MK_template_mask,
   MK_decl_spec = MK_template_mask | MK_tmpl_decl_mask,
-  MK_alias_spec = MK_decl_spec | MK_tmpl_alias_mask,
 
   MK_hwm = 0x20
 };
@@ -2806,7 +2792,7 @@ static char const *const merge_kind_name[MK_hwm] =
     NULL, NULL,
 
     "decl spec", "decl tmpl spec",     /* 20,21 decl (template).  */
-    "alias spec", "alias tmpl spec",   /* 22,23 alias (template). */
+    NULL, NULL,
     NULL, NULL, NULL, NULL,
     NULL, NULL, NULL, NULL,
   };
@@ -6356,8 +6342,7 @@ trees_out::core_vals (tree t)
       gcc_checking_assert
        (TREE_VISITED (((lang_tree_node *)t)->template_decl.arguments));
       gcc_checking_assert
-       (TREE_VISITED (((lang_tree_node *)t)->template_decl.result)
-        || dep_hash->find_dependency (t)->is_alias_tmpl_inst ());
+       (TREE_VISITED (((lang_tree_node *)t)->template_decl.result));
       if (DECL_UNINSTANTIATED_TEMPLATE_FRIEND_P (t))
        WT (DECL_CHAIN (t));
       break;
@@ -8306,16 +8291,13 @@ trees_in::decl_value ()
        {
          bool is_type = TREE_CODE (inner) == TYPE_DECL;
          spec.spec = is_type ? type : inner;
-         add_mergeable_specialization (!is_type, false,
-                                       &spec, decl, spec_flags);
+         add_mergeable_specialization (!is_type, &spec, decl, spec_flags);
        }
       else if (mk & MK_template_mask)
        {
          bool is_type = !(mk & MK_tmpl_decl_mask);
          spec.spec = is_type ? type : mk & MK_tmpl_tmpl_mask ? inner : decl;
-         add_mergeable_specialization (!is_type,
-                                       !is_type && mk & MK_tmpl_alias_mask,
-                                       &spec, decl, spec_flags);
+         add_mergeable_specialization (!is_type, &spec, decl, spec_flags);
        }
 
       if (NAMESPACE_SCOPE_P (decl)
@@ -8392,7 +8374,7 @@ trees_in::decl_value ()
       if (!e)
        {
          spec.spec = inner;
-         add_mergeable_specialization (true, false, &spec, decl, spec_flags);
+         add_mergeable_specialization (true, &spec, decl, spec_flags);
        }
       else if (e != existing)
        set_overrun ();
@@ -10620,8 +10602,6 @@ trees_out::get_merge_kind (tree decl, depset *dep)
          mk = MK_friend_spec;
        else if (dep->is_type_spec ())
          mk = MK_type_spec;
-       else if (dep->is_alias ())
-         mk = MK_alias_spec;
        else
          mk = MK_decl_spec;
 
@@ -10732,11 +10712,6 @@ trees_out::key_mergeable (int tag, merge_kind mk, tree 
decl, tree inner,
          gcc_assert (existing);
          if (mk & MK_tmpl_decl_mask)
            {
-             if (mk & MK_tmpl_alias_mask)
-               /* It should be in both tables.  */
-               gcc_checking_assert
-                 (same_type_p (match_mergeable_specialization (false, entry),
-                               TREE_TYPE (existing)));
              if (mk & MK_tmpl_tmpl_mask)
                existing = DECL_TI_TEMPLATE (existing);
            }
@@ -12830,17 +12805,12 @@ depset::hash::make_dependency (tree decl, entity_kind 
ek)
         bindings.  */
       *slot = dep = make_entity (decl, ek, has_def);
 
-      if (TREE_CODE (decl) == TEMPLATE_DECL)
-       {
-         if (DECL_ALIAS_TEMPLATE_P (decl) && DECL_TEMPLATE_INFO (decl))
-           dep->set_flag_bit<DB_ALIAS_TMPL_INST_BIT> ();
-         else if (CHECKING_P)
-           /* The template_result should otherwise not be in the
-              table, or be an empty redirect (created above).  */
-           if (auto *eslot = entity_slot (DECL_TEMPLATE_RESULT (decl), false))
-             gcc_checking_assert ((*eslot)->get_entity_kind () == EK_REDIRECT
-                                  && !(*eslot)->deps.length ());
-       }
+      if (CHECKING_P && TREE_CODE (decl) == TEMPLATE_DECL)
+       /* The template_result should otherwise not be in the
+          table, or be an empty redirect (created above).  */
+       if (auto *eslot = entity_slot (DECL_TEMPLATE_RESULT (decl), false))
+         gcc_checking_assert ((*eslot)->get_entity_kind () == EK_REDIRECT
+                              && !(*eslot)->deps.length ());
 
       if (ek != EK_USING)
        {
@@ -13228,16 +13198,11 @@ specialization_add (bool decl_p, spec_entry *entry, 
void *data_)
         heuristic.  We don't attempt to replicate that algorithm, but
         observe its behaviour and reproduce it upon read back.  */
 
-       gcc_checking_assert (DECL_ALIAS_TEMPLATE_P (entry->tmpl)
-                          || TREE_CODE (entry->spec) == ENUMERAL_TYPE
+       gcc_checking_assert (TREE_CODE (entry->spec) == ENUMERAL_TYPE
                           || DECL_CLASS_TEMPLATE_P (entry->tmpl));
 
-       /* Only alias templates can appear in both tables (and
-         if they're in the type table they must also be in the decl
-         table).  */
        gcc_checking_assert
-        (!match_mergeable_specialization (true, entry)
-         == !DECL_ALIAS_TEMPLATE_P (entry->tmpl));
+        (!match_mergeable_specialization (true, entry));
     }
   else if (VAR_OR_FUNCTION_DECL_P (entry->spec))
     gcc_checking_assert (!DECL_LOCAL_DECL_P (entry->spec));
@@ -13293,7 +13258,6 @@ depset::hash::add_specializations (bool decl_p)
       spec_entry *entry = data.pop ();
       tree spec = entry->spec;
       int use_tpl = 0;
-      bool is_alias = false;
       bool is_friend = false;
 
       if (decl_p && DECL_UNINSTANTIATED_TEMPLATE_FRIEND_P (entry->tmpl))
@@ -13301,13 +13265,7 @@ depset::hash::add_specializations (bool decl_p)
           instantiation.  */
        is_friend = true;
 
-      if (!decl_p && DECL_ALIAS_TEMPLATE_P (entry->tmpl))
-       {
-         spec = TYPE_NAME (spec);
-         is_alias = true;
-       }
-
-      if (decl_p || is_alias)
+      if (decl_p)
        {
          if (tree ti = DECL_TEMPLATE_INFO (spec))
            {
@@ -13392,20 +13350,10 @@ depset::hash::add_specializations (bool decl_p)
       gcc_checking_assert (!TREE_VISITED (spec));
       depset *dep = make_dependency (spec, depset::EK_SPECIALIZATION);
       if (dep->is_special ())
-       {
-         /* An already located specialization, this must be the TYPE
-            corresponding to an alias_decl we found in the decl
-            table.  */
-         spec_entry *other = reinterpret_cast <spec_entry *> (dep->deps[0]);
-         gcc_checking_assert (!decl_p && is_alias && !dep->is_type_spec ());
-         gcc_checking_assert (other->tmpl == entry->tmpl
-                              && template_args_equal (other->args, entry->args)
-                              && TREE_TYPE (other->spec) == entry->spec);
-         dep->set_flag_bit<DB_ALIAS_SPEC_BIT> ();
-       }
+       gcc_unreachable ();
       else
        {
-         gcc_checking_assert (decl_p || !is_alias);
+         gcc_checking_assert (decl_p);
          if (dep->get_entity_kind () == depset::EK_REDIRECT)
            dep = dep->deps[0];
          else if (dep->get_entity_kind () == depset::EK_SPECIALIZATION)
diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index d73f6d93485..99aa64b1cc3 100644
--- a/gcc/cp/pt.cc
+++ b/gcc/cp/pt.cc
@@ -10055,6 +10055,32 @@ lookup_template_class (tree d1, tree arglist, tree 
in_decl, tree context,
       /* Now we should have enough arguments.  */
       gcc_assert (parm_depth == arg_depth);
 
+      if (DECL_ALIAS_TEMPLATE_P (gen_tmpl))
+       {
+         /* The user referred to a specialization of an alias
+           template represented by GEN_TMPL.
+
+           [temp.alias]/2 says:
+
+               When a template-id refers to the specialization of an
+               alias template, it is equivalent to the associated
+               type obtained by substitution of its
+               template-arguments for the template-parameters in the
+               type-id of the alias template.  */
+
+         t = instantiate_alias_template (gen_tmpl, arglist, complain);
+         /* Note that the call above (by indirectly calling
+            register_specialization in tsubst_decl) registers the
+            TYPE_DECL representing the specialization of the alias
+            template.  So next time someone substitutes ARGLIST for
+            the template parms into the alias template (GEN_TMPL),
+            she'll get that TYPE_DECL back.  */
+
+         if (t == error_mark_node)
+           return error_mark_node;
+         return TREE_TYPE (t);
+       }
+
       /* From here on, we're only interested in the most general
         template.  */
 
@@ -10120,7 +10146,6 @@ lookup_template_class (tree d1, tree arglist, tree 
in_decl, tree context,
          lookup. This prevents redundant checks on previously
          instantiated specializations. */
       if (flag_concepts
-         && !DECL_ALIAS_TEMPLATE_P (gen_tmpl)
          && !constraints_satisfied_p (gen_tmpl, arglist))
         {
           if (complain & tf_error)
@@ -10189,31 +10214,7 @@ lookup_template_class (tree d1, tree arglist, tree 
in_decl, tree context,
        context = global_namespace;
 
       /* Create the type.  */
-      if (DECL_ALIAS_TEMPLATE_P (gen_tmpl))
-       {
-         /* The user referred to a specialization of an alias
-           template represented by GEN_TMPL.
-
-           [temp.alias]/2 says:
-
-               When a template-id refers to the specialization of an
-               alias template, it is equivalent to the associated
-               type obtained by substitution of its
-               template-arguments for the template-parameters in the
-               type-id of the alias template.  */
-
-         t = tsubst (TREE_TYPE (gen_tmpl), arglist, complain, in_decl);
-         /* Note that the call above (by indirectly calling
-            register_specialization in tsubst_decl) registers the
-            TYPE_DECL representing the specialization of the alias
-            template.  So next time someone substitutes ARGLIST for
-            the template parms into the alias template (GEN_TMPL),
-            she'll get that TYPE_DECL back.  */
-
-         if (t == error_mark_node)
-           return t;
-       }
-      else if (TREE_CODE (template_type) == ENUMERAL_TYPE)
+      if (TREE_CODE (template_type) == ENUMERAL_TYPE)
        {
          if (!is_dependent_type)
            {
@@ -10301,8 +10302,7 @@ lookup_template_class (tree d1, tree arglist, tree 
in_decl, tree context,
            }
        }
 
-      if (OVERLOAD_TYPE_P (t)
-         && !DECL_ALIAS_TEMPLATE_P (gen_tmpl))
+      if (OVERLOAD_TYPE_P (t))
        {
          static const char *tags[] = {"abi_tag", "may_alias"};
 
@@ -10369,7 +10369,7 @@ lookup_template_class (tree d1, tree arglist, tree 
in_decl, tree context,
        {
          TREE_VEC_LENGTH (arglist)--;
          ++processing_template_decl;
-         tree tinfo = TYPE_TEMPLATE_INFO_MAYBE_ALIAS (TREE_TYPE (gen_tmpl));
+         tree tinfo = TYPE_TEMPLATE_INFO (TREE_TYPE (gen_tmpl));
          tree partial_inst_args =
            tsubst (INNERMOST_TEMPLATE_ARGS (TI_ARGS (tinfo)),
                    arglist, complain, NULL_TREE);
@@ -10407,17 +10407,9 @@ lookup_template_class (tree d1, tree arglist, tree 
in_decl, tree context,
             TEMPLATE_PARM_LEVEL.  */
          found = tsubst (gen_tmpl, arglist, tf_none, NULL_TREE);
          TREE_VEC_LENGTH (arglist)++;
-         /* FOUND is either a proper class type, or an alias
-            template specialization.  In the later case, it's a
-            TYPE_DECL, resulting from the substituting of arguments
-            for parameters in the TYPE_DECL of the alias template
-            done earlier.  So be careful while getting the template
-            of FOUND.  */
          found = (TREE_CODE (found) == TEMPLATE_DECL
                   ? found
-                  : (TREE_CODE (found) == TYPE_DECL
-                     ? DECL_TI_TEMPLATE (found)
-                     : CLASSTYPE_TI_TEMPLATE (found)));
+                  : CLASSTYPE_TI_TEMPLATE (found));
 
          if (DECL_CLASS_TEMPLATE_P (found)
              && CLASSTYPE_TEMPLATE_SPECIALIZATION (TREE_TYPE (found)))
@@ -10447,8 +10439,7 @@ lookup_template_class (tree d1, tree arglist, tree 
in_decl, tree context,
                     DECL_TEMPLATE_INSTANTIATIONS (found));
 
       if (TREE_CODE (template_type) == ENUMERAL_TYPE
-         && !uses_template_parms (current_nonlambda_scope ())
-         && !DECL_ALIAS_TEMPLATE_P (gen_tmpl))
+         && !uses_template_parms (current_nonlambda_scope ()))
        /* Now that the type has been registered on the instantiations
           list, we set up the enumerators.  Because the enumeration
           constants may involve the enumeration type itself, we make
@@ -31578,8 +31569,8 @@ get_mergeable_specialization_flags (tree tmpl, tree 
decl)
    get_mergeable_specialization_flags.  */
 
 void
-add_mergeable_specialization (bool decl_p, bool alias_p, spec_entry *elt,
-                             tree decl, unsigned flags)
+add_mergeable_specialization (bool decl_p, spec_entry *elt, tree decl,
+                             unsigned flags)
 {
   hashval_t hash = spec_hasher::hash (elt);
   if (decl_p)
@@ -31590,15 +31581,8 @@ add_mergeable_specialization (bool decl_p, bool 
alias_p, spec_entry *elt,
       auto entry = ggc_alloc<spec_entry> ();
       *entry = *elt;
       *slot = entry;
-
-      if (alias_p)
-       {
-         elt->spec = TREE_TYPE (elt->spec);
-         gcc_checking_assert (elt->spec);
-       }
     }
-
-  if (!decl_p || alias_p)
+  else
     {
       auto *slot = type_specializations->find_slot_with_hash (elt, hash, 
INSERT);
 
diff --git a/gcc/testsuite/g++.dg/modules/pr99425-1_b.H 
b/gcc/testsuite/g++.dg/modules/pr99425-1_b.H
index 53d28b4ef5e..e75b3129dd3 100644
--- a/gcc/testsuite/g++.dg/modules/pr99425-1_b.H
+++ b/gcc/testsuite/g++.dg/modules/pr99425-1_b.H
@@ -15,5 +15,5 @@ inline void widget (Cont parm)
   ssize (parm);
 }
 
-// { dg-final { scan-lang-dump {Read:-[0-9]*'s alias spec merge key \(new\) 
type_decl:'::make_signed_t'\n  ...  Read:-[0-9]*'s type spec merge key \(new\) 
type_decl:'::make_signed'\n  Read:-[0-9]*'s named merge key \(matched\) 
template_decl:'::template ssize'} module } }
+// { dg-final { scan-lang-dump {Read:-[0-9]*'s decl spec merge key \(new\) 
type_decl:'::make_signed_t'\n  ...  Read:-[0-9]*'s type spec merge key \(new\) 
type_decl:'::make_signed'\n  Read:-[0-9]*'s named merge key \(matched\) 
template_decl:'::template ssize'} module } }
 
diff --git a/gcc/testsuite/g++.dg/modules/tpl-alias-1_a.H 
b/gcc/testsuite/g++.dg/modules/tpl-alias-1_a.H
index 37002ee9ae1..14a25be586f 100644
--- a/gcc/testsuite/g++.dg/modules/tpl-alias-1_a.H
+++ b/gcc/testsuite/g++.dg/modules/tpl-alias-1_a.H
@@ -6,4 +6,4 @@
 // { dg-final { scan-lang-dump {Writing decl tmpl spec:-[0-9]* 
template_decl:'::allocator_traits<::allocator<long int>>::template 
rebind_alloc<_Up>'} module } }
 // { dg-final { scan-lang-dump {Writing decl tmpl spec:-[0-9]* 
type_decl:'::allocator_traits<::allocator<long int>>::template 
rebind_alloc<_Up>'} module } }
 
-// { dg-final { scan-lang-dump {Writing:-[0-9]*'s alias spec merge key 
\(specialization\) type_decl:'::allocator_traits<::allocator<long 
int>>::rebind_alloc<long int>'} module } }
+// { dg-final { scan-lang-dump {Writing:-[0-9]*'s decl spec merge key 
\(specialization\) type_decl:'::allocator_traits<::allocator<long 
int>>::rebind_alloc<long int>'} module } }
diff --git a/gcc/testsuite/g++.dg/modules/tpl-alias-2_a.H 
b/gcc/testsuite/g++.dg/modules/tpl-alias-2_a.H
new file mode 100644
index 00000000000..76917f778e0
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/tpl-alias-2_a.H
@@ -0,0 +1,15 @@
+// PR c++/103994
+// { dg-additional-options -fmodule-header }
+// { dg-module-cmi {} }
+
+template<class>
+struct A {
+  template<class> using key_arg = int;
+};
+
+struct B {
+  template<class T>
+  void f() {
+    using type = A<B>::key_arg<T>;
+  }
+};
diff --git a/gcc/testsuite/g++.dg/modules/tpl-alias-2_b.C 
b/gcc/testsuite/g++.dg/modules/tpl-alias-2_b.C
new file mode 100644
index 00000000000..44fa5f42757
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/tpl-alias-2_b.C
@@ -0,0 +1,9 @@
+// PR c++/103994
+// { dg-additional-options -fmodules-ts }
+
+import "tpl-alias-2_a.H";
+
+int main() {
+  B b;
+  b.f<int>();
+}
-- 
2.44.0.117.g43072b4ca1

Reply via email to