Re: [PATCH 2/2] c++: is_const_eval init folding inside lambda scope [PR126483]

Jason Merrill <[email protected]>
Newsgroups gmane.comp.gcc.patches
Message-ID <[email protected]>
On 8/6/26 10:59 AM, Patrick Palka wrote:
> Bootstrapped and regtested on x86_64-pc-linux-gnu, does this look
> OK for trunk/backports?

OK.
> -- >8 --
> 
> Here when processing a's copy-initialization we overeagerly fold its
> initializer as if the lambda scope is not constexpr, and thus assume
> is_const_eval() is false.  Subsequent constant evaluation of the lambda
> gives the wrong answer due to this premature folding.
> 
> The culprit cp_fully_fold_init call is guarded by DECL_DECLARED_CONSTEXPR_P
> but that isn't set on maybe-constexpr lambdas until the lambda is fully
> parsed and its body is checked as a whole for constexpr suitability.
> The call needs to instead be guarded by maybe_constexpr_fn which considers
> such lambdas (although it considers all lambdas to be maybe-constexpr
> even fully parsed ones that have been deemed non-constexpr).
> 
> This however means we no longer fold a's copy-init even for the runtime
> version of the lambda body, hence the is_constant_evaluated3b xfail.
> Making maybe_constexpr_fn distinguish between fully parsed constexpr and
> non-constexpr lambdas doesn't help because we don't hit this code path
> again and cp_fold_function can't seem to fold the copy-init form:
> 
> struct A a1;
> <<cleanup_point <<< Unknown tree: expr_stmt
>    (void) (a1 = <<< Unknown tree: aggr_init_expr
>      5
>      __ct_comp
>      D.3052
>      (struct A *) <<< Unknown tree: void_cst >>>
>      42 >>>) >>>>>;
> 
> whereas (after r14-6506) it does fold direct-init etc which is expressed
> as:
> 
> struct A a3;
> <<cleanup_point <<< Unknown tree: expr_stmt
>    A::A (&a3, NON_LVALUE_EXPR <42>) >>>>>;
> 
> Marek's prvalue folding patch r15-6052 doesn't seem to help because
> naturally it looks for TARGET_EXPR and we don't have one here.  It
> should be possible to have cp_fold_function fold this but I haven't
> looked into it.  It would fix the xfail in is_constant_evaluated3{a,b}.
> 
> 	PR c++/126483
> 
> gcc/cp/ChangeLog:
> 
> 	* typeck2.cc (store_init_value): Check maybe_constexpr_fn
> 	instead of DECL_DECLARED_CONSTEXPR_P.
> 
> gcc/testsuite/ChangeLog:
> 
> 	* gcc/testsuite/g++.dg/opt/is_constant_evaluated3b.C: xfail
> 	a1 initializer folding.
> 	* g++.dg/cpp2a/is-constant-evaluated16.C: New test.
> ---
>   gcc/cp/typeck2.cc                             |  2 +-
>   .../g++.dg/cpp2a/is-constant-evaluated16.C    | 20 +++++++++++++++++++
>   .../g++.dg/opt/is_constant_evaluated3b.C      |  2 +-
>   3 files changed, 22 insertions(+), 2 deletions(-)
>   create mode 100644 gcc/testsuite/g++.dg/cpp2a/is-constant-evaluated16.C
> 
> diff --git a/gcc/cp/typeck2.cc b/gcc/cp/typeck2.cc
> index 6c4ed50cb94e..62f583dcf405 100644
> --- a/gcc/cp/typeck2.cc
> +++ b/gcc/cp/typeck2.cc
> @@ -1129,7 +1129,7 @@ store_init_value (tree decl, tree init, vec<tree, va_gc>** cleanups, int flags)
>        that might fold away something that needs to be diagnosed at constexpr
>        evaluation time.  */
>     if (!current_function_decl
> -      || !DECL_DECLARED_CONSTEXPR_P (current_function_decl)
> +      || !maybe_constexpr_fn (current_function_decl)
>         || TREE_STATIC (decl))
>       value = cp_fully_fold_init (value);
>   
> diff --git a/gcc/testsuite/g++.dg/cpp2a/is-constant-evaluated16.C b/gcc/testsuite/g++.dg/cpp2a/is-constant-evaluated16.C
> new file mode 100644
> index 000000000000..c727967673e3
> --- /dev/null
> +++ b/gcc/testsuite/g++.dg/cpp2a/is-constant-evaluated16.C
> @@ -0,0 +1,20 @@
> +// PR c++/126483
> +// { dg-do compile { target c++17 } }
> +
> +struct A {
> +  int m;
> +  constexpr A(int n) : m(__builtin_is_constant_evaluated() ? 42 : n) { }
> +};
> +
> +constexpr auto v = [] {
> +  A a = 0;
> +  return a.m;
> +};
> +static_assert(v() == 42);
> +
> +template<class>
> +constexpr auto vt = [] {
> +  A a = 0;
> +  return a.m;
> +};
> +static_assert(vt<void>() == 42);
> diff --git a/gcc/testsuite/g++.dg/opt/is_constant_evaluated3b.C b/gcc/testsuite/g++.dg/opt/is_constant_evaluated3b.C
> index ff708e23832b..ac6d21d632e1 100644
> --- a/gcc/testsuite/g++.dg/opt/is_constant_evaluated3b.C
> +++ b/gcc/testsuite/g++.dg/opt/is_constant_evaluated3b.C
> @@ -17,7 +17,7 @@ auto f = [] {
>     A a5{};
>   };
>   
> -// { dg-final { scan-tree-dump "a1 = {\\.n=42, \\.m=0}" "original" } }
> +// { dg-final { scan-tree-dump "a1 = {\\.n=42, \\.m=0}" "original" { xfail *-*-* } } }
>   // { dg-final { scan-tree-dump "a2 = {\\.n=42, \\.m=0}" "original" } }
>   // { dg-final { scan-tree-dump "a3 = {\\.n=42, \\.m=0}" "original" } }
>   // { dg-final { scan-tree-dump "a4 = {\\.n=42, \\.m=0}" "original" } }
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.