]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
c++: self-dependent alias template [PR117530]
authorJason Merrill <jason@redhat.com>
Mon, 7 Apr 2025 18:35:14 +0000 (14:35 -0400)
committerJason Merrill <jason@redhat.com>
Thu, 10 Apr 2025 20:42:34 +0000 (16:42 -0400)
Here, instantiating B<short> means instantiating A<short>, which means
instantiating B<short>.  And then when we go to register the initial
instantiation, it conflicts with the inner one.  Fixed by checking after
tsubst whether there's already something in the hash table.  We already did
something much like this in tsubst_decl, but that doesn't handle this case.

PR c++/117530

gcc/cp/ChangeLog:

* pt.cc (instantiate_template): Check retrieve_specialization after
tsubst.

gcc/testsuite/ChangeLog:

* g++.dg/cpp2a/lambda-uneval27.C: New test.

(cherry picked from commit d034c78c7be613db3c25fddec1dd50222327117b)

gcc/cp/pt.cc
gcc/testsuite/g++.dg/cpp2a/lambda-uneval27.C [new file with mode: 0644]

index d41df4f230ceef81f882b61ef670249b214ae432..3a5ffd8b683ed8ac4f716320a4bbda4d420b74c7 100644 (file)
@@ -22258,6 +22258,15 @@ instantiate_template (tree tmpl, tree orig_args, tsubst_flags_t complain)
       return error_mark_node;
     }
 
+  /* Substituting the type might have recursively instantiated this
+     same alias (c++/117530).  */
+  if (DECL_ALIAS_TEMPLATE_P (gen_tmpl)
+      && (spec = retrieve_specialization (gen_tmpl, targ_ptr, hash)))
+    {
+      pop_deferring_access_checks ();
+      return spec;
+    }
+
   /* The DECL_TI_TEMPLATE should always be the immediate parent
      template, not the most general template.  */
   DECL_TI_TEMPLATE (fndecl) = tmpl;
diff --git a/gcc/testsuite/g++.dg/cpp2a/lambda-uneval27.C b/gcc/testsuite/g++.dg/cpp2a/lambda-uneval27.C
new file mode 100644 (file)
index 0000000..941fe63
--- /dev/null
@@ -0,0 +1,10 @@
+// PR c++/117530
+// { dg-do compile { target c++20 } }
+
+template <class> struct A;
+template <class T> using B = decltype([]() -> A<T>::X { return 0; });
+template <class T> struct A {
+  typedef int X;
+  typedef B<T> U;
+};
+B<short> b;