diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc index 95b89f1281b..8f35fa702a2 100644 --- a/gcc/cp/pt.cc +++ b/gcc/cp/pt.cc @@ -22675,7 +22675,7 @@ instantiate_template (tree tmpl, tree orig_args, tsubst_flags_t complain) FUNCTION_DECL which is the desired context for access checking is not built yet. We solve this chicken-and-egg problem by deferring all checks until we have the FUNCTION_DECL. */ - push_deferring_access_checks (dk_deferred); + deferring_access_check_sentinel dacs (dk_deferred); /* Instantiation of the function happens in the context of the function template, not the context of the overload resolution we're doing. */ @@ -22733,10 +22733,13 @@ instantiate_template (tree tmpl, tree orig_args, tsubst_flags_t complain) pop_from_top_level (); if (fndecl == error_mark_node) - { - pop_deferring_access_checks (); - return error_mark_node; - } + 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))) + return spec; /* The DECL_TI_TEMPLATE should always be the immediate parent template, not the most general template. */ @@ -22771,7 +22774,6 @@ instantiate_template (tree tmpl, tree orig_args, tsubst_flags_t complain) access_ok = false; pop_access_scope (fndecl); } - pop_deferring_access_checks (); /* If we've just instantiated the main entry point for a function, instantiate all the alternate entry points as well. We do this 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;