On Tue, 19 Jan 2021, Jason Merrill wrote: > On 1/18/21 12:31 AM, Patrick Palka wrote: > > Here after resolving the address of a template-id inside decltype, we > > end up instantiating the chosen specialization from the call to > > mark_used in resolve_nondeduced_context, even though only its type is > > needed. > > > > Bootstrapped and regtested on x86_64-pc-linux-gnu, does this look for > > trunk? > > > > gcc/cp/ChangeLog: > > > > PR c++/71879 > > * semantics.c (finish_decltype_type): Temporarily increment > > cp_unevaluated_operand during call to resolve_nondeduced_context. > > > > gcc/testsuite/ChangeLog: > > > > PR c++/71879 > > * g++.dg/cpp0x/decltype-71879.C: New test. > > --- > > gcc/cp/semantics.c | 2 ++ > > gcc/testsuite/g++.dg/cpp0x/decltype-71879.C | 5 +++++ > > 2 files changed, 7 insertions(+) > > create mode 100644 gcc/testsuite/g++.dg/cpp0x/decltype-71879.C > > > > diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c > > index c8a6283b120..cad55665ce8 100644 > > --- a/gcc/cp/semantics.c > > +++ b/gcc/cp/semantics.c > > @@ -10098,7 +10098,9 @@ finish_decltype_type (tree expr, bool > > id_expression_or_member_access_p, > > /* The type denoted by decltype(e) is defined as follows: */ > > + ++cp_unevaluated_operand; > > expr = resolve_nondeduced_context (expr, complain); > > + --cp_unevaluated_operand; > > Hmm, is there a reason not to have cp_unevaluated_operand set through the > whole function? We might stick 'cp_unevaluated u;' at the top of the function > and remove the existing messing with cp_unevaluated_operand. Or assert that > it's set and fix the callers to leave it set longer.
That makes sense to me. AFAICT the only parts of finish_decltype_type tha are sensitive to cp_unevaluated_operand are resolve_nondeduced_context and instantiate_nondependent_expr_sfinae, but it makes sense to have cp_unevaluated_operand set throughout the function. The following passes limited testing, does it look OK for trunk after a full bootstrap+regtest? -- >8 -- Subject: [PATCH] c++: Fix excessive instantiation inside decltype [PR71879] Here after resolving the address of a template-id inside decltype, we end up instantiating the chosen specialization (from the call to mark_used in resolve_nondeduced_context), even though only its type is needed. This patch sets cp_unevaluated_operand throughout finish_decltype_type, so that in particular it's set during the call to resolve_nondeduced_context within. gcc/cp/ChangeLog: PR c++/71879 * semantics.c (finish_decltype_type): Set up a cp_unevaluated sentinel at the start of the function. Remove a now-redundant manual adjustment of cp_unevaluated_operand. gcc/testsuite/ChangeLog: PR c++/71879 * g++.dg/cpp0x/decltype-71879.C: New test. --- gcc/cp/semantics.c | 5 +++-- gcc/testsuite/g++.dg/cpp0x/decltype-71879.C | 5 +++++ 2 files changed, 8 insertions(+), 2 deletions(-) create mode 100644 gcc/testsuite/g++.dg/cpp0x/decltype-71879.C diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c index 244fc70d02d..834885616db 100644 --- a/gcc/cp/semantics.c +++ b/gcc/cp/semantics.c @@ -10080,6 +10080,9 @@ finish_decltype_type (tree expr, bool id_expression_or_member_access_p, return error_mark_node; } + /* The operand of decltype is an unevaluated expression. */ + cp_unevaluated u; + /* Depending on the resolution of DR 1172, we may later need to distinguish instantiation-dependent but not type-dependent expressions so that, say, A<decltype(sizeof(T))>::U doesn't require 'typename'. */ @@ -10095,9 +10098,7 @@ finish_decltype_type (tree expr, bool id_expression_or_member_access_p, } else if (processing_template_decl) { - ++cp_unevaluated_operand; expr = instantiate_non_dependent_expr_sfinae (expr, complain); - --cp_unevaluated_operand; if (expr == error_mark_node) return error_mark_node; } diff --git a/gcc/testsuite/g++.dg/cpp0x/decltype-71879.C b/gcc/testsuite/g++.dg/cpp0x/decltype-71879.C new file mode 100644 index 00000000000..9da4d40ca70 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/decltype-71879.C @@ -0,0 +1,5 @@ +// PR c++/71879 +// { dg-do compile { target c++11 } } + +template <class T> void f(T x) { x.fail(); } +using R = decltype(&f<int>); -- 2.30.0.155.g66e871b664