> 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(); }