aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJason Merrill <jason@redhat.com>2025-07-24 14:07:11 -0400
committerJason Merrill <jason@redhat.com>2025-07-24 14:07:11 -0400
commiteb59e58dcc4cdf36b8b2d4e1654fe4fa062b5bef (patch)
treeac3d039b70b65cd8e7a6e7179bfa4729a54d7d46
parent44e32178031e89399710c3ee7444891631a9c8ec (diff)
downloadgcc-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.cc4
-rw-r--r--gcc/cp/pt.cc11
-rw-r--r--gcc/testsuite/g++.dg/cpp23/explicit-obj-lambda18.C12
-rw-r--r--gcc/testsuite/g++.dg/cpp23/static-operator-call7.C12
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;
+}