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

Reply via email to