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.

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

Reply via email to