From: Jason Merrill Date: Mon, 7 Apr 2025 18:35:14 +0000 (-0400) Subject: c++: self-dependent alias template [PR117530] X-Git-Tag: releases/gcc-14.3.0~208 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=708c393774188d74399ec75ef20a522444b09f92;p=thirdparty%2Fgcc.git c++: self-dependent alias template [PR117530] Here, instantiating B means instantiating A, which means instantiating B. 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) --- diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc index d41df4f230c..3a5ffd8b683 100644 --- a/gcc/cp/pt.cc +++ b/gcc/cp/pt.cc @@ -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 index 00000000000..941fe636f6d --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp2a/lambda-uneval27.C @@ -0,0 +1,10 @@ +// PR c++/117530 +// { dg-do compile { target c++20 } } + +template struct A; +template using B = decltype([]() -> A::X { return 0; }); +template struct A { + typedef int X; + typedef B U; +}; +B b;