On 2/25/26 1:38 AM, Marek Polacek wrote:
On Tue, Feb 24, 2026 at 10:54:55PM +0900, Jason Merrill wrote:
On 2/24/26 5:44 AM, Marek Polacek wrote:
Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk?

-- >8 --
This patch fixes a very annoying problem where we emit a bogus
check_out_of_consteval_use error.  The error is provoked while
processing

    [: std::meta::reflect_constant_array (data) :]

The argument of a [: :] is a constant-expression = a manifestly
constant-evaluated context, so any consteval-only exprs in it
are OK.  But in eval_reflect_constant_array we do get_template_parm_object
which does push_to_top_level -- so we have no scope_chain, therefore
any in_consteval_if_p and current_function_decl are cleared, so we're
not in an immediate context.

Since we're initializing a constexpr variable (the template parameter
object), we should be in MCE for that regardless of the splice expression.
Maybe check_initializer should set that up?

Yeah, that sounds right, thanks.

I think that my change is also right, but not necessary anymore.

Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk?

-- >8 --
This patch fixes a very annoying problem where we emit a bogus
check_out_of_consteval_use error.  The error is provoked while
processing

   [: std::meta::reflect_constant_array (data) :]

The argument of a [: :] is a constant-expression = a manifestly
constant-evaluated context, so any consteval-only exprs in it
are OK.  But in eval_reflect_constant_array we do get_template_parm_object
which does push_to_top_level -- so we have no scope_chain, therefore
any in_consteval_if_p and current_function_decl are cleared, so we're
not in an immediate context.  As part of this get_template_parm_object,
we call cp_finish_decl -> check_initializer -> build_aggr_init ->
-> build_vec_init.

Here in build_vec_init try_const is true, but we still generate code
for the initializer like

   <<< Unknown tree: expr_stmt
   (void)  ++D.67757 >>>;
<<< Unknown tree: expr_stmt
   (void)  --D.67758 >>>;

etc.  We add ++D.67757 with finish_expr_stmt which calls
convert_to_void -> check_out_of_consteval_use which causes the error
because ++D.67757's type is consteval-only.  Note that what we end up using
is the simple

   _ZTAX... = {{.name=<<< Unknown tree: reflect_expr _ZTAXtlA2_KcLS_95EEE >>>, 
.none=1}}

because we didn't see anything non-const in the initializer.

When initializing a constexpr variable, we are in a manifestly
constant-evaluated context, so fix check_initializer to that effect.

        PR c++/123662
        PR c++/123611

gcc/cp/ChangeLog:

        * decl.cc (check_initializer): Set in_consteval_if_p when initializing
        a constexpr variable.

Hmm, this doesn't address more ambiguously MCE variables that aren't declared constexpr (or constinit) but have constant initialization.

So I think I was wrong and your first patch was better, it improves the issue of checking out-of-consteval-use when we're still mce_unknown. But it doesn't completely fix it:

int i = (^^i, 42); // OK, MCE

Fundamentally the problem is that convert_to_void is too soon to diagnose this in general.

Jason

Reply via email to