https://gcc.gnu.org/bugzilla/show_bug.cgi?id=100252

--- Comment #9 from Marek Polacek <mpolacek at gcc dot gnu.org> ---
When we are cp_parser_late_parsing_nsdmi for "int y = A{x}.y;" we perform
finish_compound_literal on type=A, compound_literal={((struct B *) this)->x}. 
When digesting this initializer, we call get_nsdmi which creates a
PLACEHOLDER_EXPR for A -- we don't have any object to refer to yet.  After
digesting, we have

  {.x=((struct B *) this)->x, .y=(&<PLACEHOLDER_EXPR struct A>)->x}

and since we've created a PLACEHOLDER_EXPR inside it, we marked the whole ctor
CONSTRUCTOR_PLACEHOLDER_BOUNDARY.  f_c_l creates a TARGET_EXPR and returns

  TARGET_EXPR <D.2384, {.x=((struct B *) this)->x, .y=(&<PLACEHOLDER_EXPR
struct A>)->x}>

(*)

Then we get to

  B b = {};

and call store_init_value, which digest the {}, which produces

  {.x=NON_LVALUE_EXPR <0>, .y=(TARGET_EXPR <D.2395, {.x=(&<PLACEHOLDER_EXPR
struct B>)->x, .y=(&<PLACEHOLDER_EXPR struct A>)->x}>).y}

The call to replace_placeholders in store_init_value will not do anything:
we've marked the inner { } CONSTRUCTOR_PLACEHOLDER_BOUNDARY, and it's only a
sub-expression, so replace_placeholders does nothing, so the <PLACEHOLDER_EXPR
struct B> stays even though now it was the perfect time to replace it because
we have an object for it: 'b'.

Later, in cp_gimplify_init_expr the *expr_p is

  D.2395 = {.x=(&<PLACEHOLDER_EXPR struct B>)->x, .y=(&<PLACEHOLDER_EXPR struct
A>)->x}

where D.2395 is of type A, but we crash because we hit <PLACEHOLDER_EXPR struct
B>, which has a different type.


Now here's an idea how we could fix this: at the (*) point in
finish_compound_literal we could replace <PLACEHOLDER_EXPR struct A> with
D.2384 because now we have an object!  Then clear
CONSTRUCTOR_PLACEHOLDER_BOUNDARY, because we no longer have a PLACEHOLDER_EXPR
in the {}.  Then store_init_value will be able to replace <PLACEHOLDER_EXPR
struct B> with 'b', and we should be good to go.

Reply via email to