On Fri, 6 May 2022, Jason Merrill wrote: > On 5/6/22 14:00, Patrick Palka wrote: > > On Fri, 6 May 2022, Patrick Palka wrote: > > > > > On Fri, 6 May 2022, Jason Merrill wrote: > > > > > > > On 5/6/22 11:22, Patrick Palka wrote: > > > > > Here ever since r10-7313-gb599bf9d6d1e18, > > > > > reduced_constant_expression_p > > > > > in C++11/14 is rejecting the marked sub-aggregate initializer (of type > > > > > S) > > > > > > > > > > W w = {.D.2445={.s={.D.2387={.m=0}, .b=0}}} > > > > > ^ > > > > > > > > > > ultimately because said initializer has CONSTRUCTOR_NO_CLEARING set, > > > > > and > > > > > so the function proceeds to verify that all fields of S are > > > > > initialized. > > > > > And before C++17 we don't expect to see base class fields (since > > > > > next_initializable_field skips over the), so the base class > > > > > initializer > > > > > causes r_c_e_p to return false. > > > > > > > > That seems like the primary bug. I guess r_c_e_p shouldn't be using > > > > next_initializable_field. Really that function should only be used for > > > > aggregates. > > > > > > I see, I'll try replacing it in r_c_e_p. Would that be in addition to > > > or instead of the clear_no_implicit_zero approach? > > > > I'm testing the following, which uses a custom predicate instead of > > next_initializable_field in r_c_e_p. > > Let's make it a public predicate, not internal to r_c_e_p. Maybe it could be > next_subobject_field, and the current next_initializable_field change to > next_aggregate_field?
Will do. > > > Looks like the inner initializer {.D.2387={.m=0}, .b=0} is formed during > > the subobject constructor call: > > > > V::V (&((struct S *) this)->D.2120); > > > > after the evaluation of which, 'result' in cxx_eval_call_expression is NULL > > (presumably because it's a CALL_EXPR, not AGGR_INIT_EXPR?): > > > > /* This can be null for a subobject constructor call, in > > which case what we care about is the initialization > > side-effects rather than the value. We could get at the > > value by evaluating *this, but we don't bother; there's > > no need to put such a call in the hash table. */ > > result = lval ? ctx->object : ctx->ctor; > > > > so we end up not calling clear_no_implicit_zero for the inner initializer > > directly. We only call clear_no_implicit_zero after evaluating the > > AGGR_INIT_EXPR for outermost initializer (of type W). > > Maybe for constructors we could call it on ctx->ctor instead of result, or > call r_c_e_p in C++20+? But both ctx->ctor and ->object are NULL during a subobject constructor call (since we apparently clear these fields when entering a STATEMENT_LIST): So I tried instead obtaining the constructor by evaluating new_obj via --- a/gcc/cp/constexpr.cc +++ b/gcc/cp/constexpr.cc @@ -2993,6 +2988,9 @@ cxx_eval_call_expression (const constexpr_ctx *ctx, tree t, in order to detect reading an unitialized object in constexpr instead of value-initializing it. (reduced_constant_expression_p is expected to take care of clearing the flag.) */ + if (new_obj && DECL_CONSTRUCTOR_P (fun)) + result = cxx_eval_constant_expression (ctx, new_obj, /*lval=*/false, + non_constant_p, overflow_p); if (TREE_CODE (result) == CONSTRUCTOR && (cxx_dialect < cxx20 || !DECL_CONSTRUCTOR_P (fun))) but that seems to break e.g. g++.dg/cpp2a/constexpr-init12.C because after the subobject constructor call S::S (&((struct W *) this)->s, NON_LVALUE_EXPR <8>); the constructor for the subobject a.s in new_obj is still completely missing (I suppose because S::S doesn't initialize any of its members) so trying to obtain it causes us to complain too soon from cxx_eval_component_reference: constexpr-init12.C:16:24: in ‘constexpr’ expansion of ‘W(42)’ constexpr-init12.C:10:22: in ‘constexpr’ expansion of ‘((W*)this)->W::s.S::S(8)’ constexpr-init12.C:16:24: error: accessing uninitialized member ‘W::s’ 16 | constexpr auto a = W(42); // { dg-error "not a constant expression" } | ^ > > It does seem dubious that we would clear the flag on an outer ctor when it's > still set on an inner ctor, should probably add an assert somewhere. Makes sense, not sure where the best place would be.. > > Jason > >