c++: lambda convop in C++23 [PR114632]

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.

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.
This commit is contained in:
Jason Merrill
2025-07-24 14:07:11 -04:00
parent 44e3217803
commit eb59e58dcc
4 changed files with 31 additions and 8 deletions

View File

@@ -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)

View File

@@ -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;

View File

@@ -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;
}

View File

@@ -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;
}