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)
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;
--- /dev/null
+// 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;