On Tue, Mar 7, 2017 at 12:10 PM, Marek Polacek <pola...@redhat.com> wrote: > In this testcase we have > C c = bar (X{1}); > which store_init_value sees as > c = TARGET_EXPR <D.2332, bar (TARGET_EXPR <D.2298, {.i=1, > .n=(&<PLACEHOLDER_EXPR struct X>)->i}>)> > i.e. we're initializing "c" with a TARGET_EXPR. We call replace_placeholders > that walks the whole tree to substitute the placeholders. Eventually we find > the nested <PLACEHOLDER_EXPR struct X> but that's for another object, so we > crash. Seems that we shouldn't have stepped into the second TARGET_EXPR at > all; it has nothing to with "c", it's bar's argument. > > It occurred to me that we shouldn't step into CALL_EXPRs and leave the > placeholders in function arguments to cp_gimplify_init_expr which calls > replace_placeholders for constructors. Not sure if it's enough to handle > CALL_EXPRs like this, anything else?
Hmm, we might have a DMI containing a call with an argument referring to *this, i.e. struct A { int i; int j = frob (this->i); }; The TARGET_EXPR seems like a more likely barrier, but even there we could have something like struct A { int i; }; struct B { int i; A a = A{this->i}; }; I think we need replace_placeholders to keep a stack of objects, so that when we see a TARGET_EXPR we add it to the stack and therefore can properly replace a PLACEHOLDER_EXPR of its type. Jason