diff options
author | Jason Merrill <jason@redhat.com> | 2025-07-24 14:07:11 -0400 |
---|---|---|
committer | Jason Merrill <jason@redhat.com> | 2025-07-24 14:07:11 -0400 |
commit | eb59e58dcc4cdf36b8b2d4e1654fe4fa062b5bef (patch) | |
tree | ac3d039b70b65cd8e7a6e7179bfa4729a54d7d46 | |
parent | 44e32178031e89399710c3ee7444891631a9c8ec (diff) | |
download | gcc-eb59e58dcc4cdf36b8b2d4e1654fe4fa062b5bef.zip gcc-eb59e58dcc4cdf36b8b2d4e1654fe4fa062b5bef.tar.gz gcc-eb59e58dcc4cdf36b8b2d4e1654fe4fa062b5bef.tar.bz2 |
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.
-rw-r--r-- | gcc/cp/lambda.cc | 4 | ||||
-rw-r--r-- | gcc/cp/pt.cc | 11 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp23/explicit-obj-lambda18.C | 12 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp23/static-operator-call7.C | 12 |
4 files changed, 31 insertions, 8 deletions
diff --git a/gcc/cp/lambda.cc b/gcc/cp/lambda.cc index 525e8ef..ecf55eb 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 d63fa68..8e17533 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 0000000..d54a93d --- /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 0000000..7c381e6 --- /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; +} |