On Thu, 24 Jul 2025, Jason Merrill wrote: > Tested x86_64-pc-linux-gnu, applying to trunk. > > -- 8< -- > > The lambda conversion was ICEing for two C++23 features, static op() and > explicit object parameters. The issue with the former seems like a more > general issue: tsubst_function_decl recursing to substitute the parameters > was affected by cp_unevaluated_operand from the decltype that refers to the > declaration. Various places already make a point of clearing > cp_unevaluated_operand ahead of PARM_DECL tsubsting; doing it here makes the > PR101233 fix redundant.
Shall we also partially revert r9-5971-g60378a964a2a6b by moving down the cp_evaluated in tsubst_lambda_expr to just before tsubsting the body of the lambda so that it better reflects its comment? > > For explicit object lambdas, we want to implement CWG2561 and > just not declare the conversion. > > PR c++/114632 > PR c++/101233 > > gcc/cp/ChangeLog: > > * lambda.cc (maybe_add_lambda_conv_op): Not for xobj lambda. > * pt.cc (tsubst_function_decl): Add cp_evaluated. > (alias_ctad_tweaks): Revert PR101233 fix. > > gcc/testsuite/ChangeLog: > > * g++.dg/cpp23/explicit-obj-lambda18.C: New test. > * g++.dg/cpp23/static-operator-call7.C: New test. > --- > gcc/cp/lambda.cc | 4 +++- > gcc/cp/pt.cc | 11 ++++------- > gcc/testsuite/g++.dg/cpp23/explicit-obj-lambda18.C | 12 ++++++++++++ > gcc/testsuite/g++.dg/cpp23/static-operator-call7.C | 12 ++++++++++++ > 4 files changed, 31 insertions(+), 8 deletions(-) > create mode 100644 gcc/testsuite/g++.dg/cpp23/explicit-obj-lambda18.C > create mode 100644 gcc/testsuite/g++.dg/cpp23/static-operator-call7.C > > diff --git a/gcc/cp/lambda.cc b/gcc/cp/lambda.cc > index 525e8ef4b34..ecf55eb94d0 100644 > --- a/gcc/cp/lambda.cc > +++ b/gcc/cp/lambda.cc > @@ -1143,7 +1143,9 @@ maybe_add_lambda_conv_op (tree type) > tree lam = CLASSTYPE_LAMBDA_EXPR (type); > > if (LAMBDA_EXPR_CAPTURE_LIST (lam) != NULL_TREE > - || LAMBDA_EXPR_DEFAULT_CAPTURE_MODE (lam) != CPLD_NONE) > + || LAMBDA_EXPR_DEFAULT_CAPTURE_MODE (lam) != CPLD_NONE > + /* CWG2561 ...and no explicit object parameter. */ > + || DECL_XOBJ_MEMBER_FUNCTION_P (callop)) > return; > > if (processing_template_decl) > diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc > index d63fa68058b..8e175337b71 100644 > --- a/gcc/cp/pt.cc > +++ b/gcc/cp/pt.cc > @@ -14916,6 +14916,9 @@ tsubst_function_decl (tree t, tree args, > tsubst_flags_t complain, > argvec = NULL_TREE; > } > > + /* Make sure tsubst_decl substitutes all the parameters. */ > + cp_evaluated ev; > + > tree closure = (lambda_fntype ? TYPE_METHOD_BASETYPE (lambda_fntype) > : NULL_TREE); > tree ctx = closure ? closure : DECL_CONTEXT (t); > @@ -31214,14 +31217,8 @@ alias_ctad_tweaks (tree tmpl, tree uguides) > /* Substitute the deduced arguments plus the rewritten template > parameters into f to get g. This covers the type, copyness, > guideness, and explicit-specifier. */ > - tree g; > - { > - /* Parms are to have DECL_CHAIN tsubsted, which would be skipped > - if cp_unevaluated_operand. */ > - cp_evaluated ev; > - g = tsubst_decl (DECL_TEMPLATE_RESULT (f), targs, complain, > + tree g = tsubst_decl (DECL_TEMPLATE_RESULT (f), targs, complain, > /*use_spec_table=*/false); > - } > if (g == error_mark_node) > continue; > DECL_NAME (g) = name; > diff --git a/gcc/testsuite/g++.dg/cpp23/explicit-obj-lambda18.C > b/gcc/testsuite/g++.dg/cpp23/explicit-obj-lambda18.C > new file mode 100644 > index 00000000000..d54a93d1de1 > --- /dev/null > +++ b/gcc/testsuite/g++.dg/cpp23/explicit-obj-lambda18.C > @@ -0,0 +1,12 @@ > +// PR c++/114632 > +// { dg-do compile { target c++23 } } > + > +struct S {}; > + > +auto lambda = [](this auto& self, const int x) /* -> void */ {}; > + > +int main() > +{ > + void (*func)(S&, int) = lambda; // { dg-error "" } > + return 0; > +} > diff --git a/gcc/testsuite/g++.dg/cpp23/static-operator-call7.C > b/gcc/testsuite/g++.dg/cpp23/static-operator-call7.C > new file mode 100644 > index 00000000000..7c381e69416 > --- /dev/null > +++ b/gcc/testsuite/g++.dg/cpp23/static-operator-call7.C > @@ -0,0 +1,12 @@ > +// PR c++/114632 > +// { dg-do compile { target c++23 } } > + > +struct S {}; > + > +auto lambda = [](auto, const int x) static /* -> void */ {}; > + > +int main() > +{ > + void (*func)(int, int) = lambda; > + return 0; > +} > > base-commit: 44e32178031e89399710c3ee7444891631a9c8ec > -- > 2.50.1 > >