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.