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?

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

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.

Jason

Reply via email to