This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: Strenghten assumption about dynamic type changes (placement new)


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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]