On 2/26/26 6:23 AM, Marek Polacek wrote:
On Wed, Feb 25, 2026 at 11:00:50AM +0900, Jason Merrill wrote:
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

Argh, true.  I've opened <https://gcc.gnu.org/PR124249> for this.

What do you think about merging v1 and v2?  Or should I push v1 only?

I guess just v1, with a comment pointing to that PR.

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

I did it there because convert_to_void is where we may discard expressions
and so it's our last chance to diagnose out-of-consteval-uses.  But as you
point out, it shouldn't check initializers.  For those, we should probably
wait till cp_finish_decl, after store_init_value's fold_non_dependent_init,
I would guess.

Seems like we need to stop discarding expressions when we support consteval-only. We might just stop discarding them there entirely, that seems like a remnant of early folding that we've mostly gotten away from.

Jason

Reply via email to