On Tue, Jul 8, 2014 at 2:50 PM, Jan Hubicka <hubi...@ucw.cz> wrote: >> On 07/02/2014 01:18 PM, Jan Hubicka wrote: >> >We propagate types from places we know instances are created across pointers >> >passed to functions. Once non-POD type is created at a given memory >> >location, >> >one can not change its type by placement_new into something else. >> >> Hmm. If the memory location is untyped (i.e. from malloc) or a >> character array, or a union, you can indeed destroy an object of one >> type and create an object of a different type in that location. >> >> >Jason, this assumes that one can not destroy the type and re-construct same >> >type at the same spot. >> >> That is an invalid assumption; you can destroy one object and >> construct a new one in the same location. Doing it within a method >> would be unusual, but I don't think there's a rule against it. >> > Jason, > I am looking into tracking dynamic types now. Obviously I need to set very > exact rules about when these may change. Can you take a few minutes and tell > me > what of these sequences are valid? > > I think b variants are invalid, currently we also assume t1 to be invalid, but > t2 to be valid. > With placement news, I wonder if we can arrange them to do before return: > ptr = __builtin_placement_new (ptr) > this builtin would be folded away after IPA wwhen we no longer need to track > types same way as builtin_constant. That way I won't get two different dynamic > types mixed at one pointer location, since these will look as two pointers > until after inlining. But given that C++ makes placement new to be written by > hand, perhaps this is not possible? > > #include <stdio.h> > inline void* operator new(__SIZE_TYPE__, void* __p) throw() { return __p;} > > struct A > { > virtual void foo() {printf ("A\n");} > }; > struct B: A > { > virtual void foo() {printf ("B\n");} > }; > struct C: A > { > virtual void foo() {printf ("C\n");} > }; > > struct A * > type(struct B *a) > { > struct C *b; > ((struct B *)a)->~B(); > b = new (a) C; > return b; > } > struct A * > type_back(struct A *a) > { > struct B *b; > ((struct C *)a)->~C(); > b = new (a) B; > return b; > } > > void > t1() > { > struct B a; > struct A *b; > a.foo(); > b=type(&a); > b->foo(); > b=type_back (b); > a.foo(); > } > void > t1b() > { > struct B a; > a.foo(); > type(&a); > ((struct A *)&a)->foo(); > type_back (&a); > ((struct A *)&a)->foo(); > } > void > t2() > { > struct B *a = new (B); > struct A *b; > a->foo(); > b=type(a); > b->foo(); > } > void > t2b() > { > struct B *a = new (B); > struct A *b; > a->foo(); > type(a); > ((struct A *)a)->foo(); > } > main() > { > t1(); > t1b(); > t2(); > t2b(); > }
Hi, Below test also fails on arm-none-linux-gnueabi(hf): NA->FAIL: g++.dg/ipa/imm-devirt-2.C -std=gnu++11 scan-tree-dump einline "C NA->FAIL: g++.dg/ipa/imm-devirt-2.C -std=gnu++1y scan-tree-dump einline "C NA->FAIL: g++.dg/ipa/imm-devirt-2.C -std=gnu++98 scan-tree-dump einline "C Reported at https://gcc.gnu.org/bugzilla/show_bug.cgi?id=61748 Thanks, bin