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