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

Reply via email to