https://gcc.gnu.org/bugzilla/show_bug.cgi?id=79671

--- Comment #46 from Bernd Edlinger <bernd.edlinger at hotmail dot de> ---
(In reply to Jonathan Wakely from comment #45)
> (In reply to rguent...@suse.de from comment #32)
> > So you need to place may-alias at a point to make the following
> > stmt safe:
> > 
> > >   c = *p;
> > 
> > which means placing it on B, not only on the union (p is a B).
> > 
> > Thus do
> > 
> > struct B
> > {
> >   int x;
> >   union U
> >     {
> >       int a;
> >       char b[sizeof (float)];
> >     } u;
> >   int y;
> > } __attribute__((may_alias));
> 
> In the real code there is no B, there is just the union, and it is assigned
> directly, so it's more like:
> 
> union function_buffer_members {
>   void* p;
>   void(*fp)();
> };
> 
> union function_buffer {
>   function_buffer_members members;
>   char data[sizeof(function_buffer_members)];
> };
> 
> struct function_base {
>   mutable function_buffer functor;
> };
> 
> struct function : function_base {
>   void func(const function& f) {
>     this->functor = f.functor;
>   }
> };
> 
> So it should only be necessary to put __attribute__((may_alias)) on union
> function_buffer, right? That doesn't fix the problem though.

Yes, it seems, the __attribute__((may_alias)) does not propagate from
structure members to enclosing structure:

If B has the may_alias, but it is a member of C
then the test case fails again:

inline void* operator new(__SIZE_TYPE__, void *p) { return p; }
struct A { A (float x) : f (x) {} float f; };
struct B
{
  int x;
  union U
  {
    int a;
    char b[sizeof (float)];
  } u;
  int y;
} __attribute__((may_alias));

struct C
{
  struct B b;
};

__attribute__((noinline, noclone)) void
bar (B &x, B &y)
{
  if (x.x != 0 || x.y != 3 || y.x != 0 || y.y != 3)
    __builtin_abort ();
  float f;
  __builtin_memcpy (&f, x.u.b, sizeof (float));
  if (f != 3.5f)
    __builtin_abort ();
  __builtin_memcpy (&f, y.u.b, sizeof (float));
  if (f != 3.5f)
    __builtin_abort ();
}

__attribute__((noinline, noclone))
C *
baz (C &x)
{
  return &x;
}

__attribute__((noinline, noclone)) void
foo (float x)
{
  C b { 0, {}, 3 }, c;
  C *p = baz (b);
  new (b.b.u.b) A (x);
  c.b = p->b;
  bar (p->b, c.b);
}

int
main ()
{
  foo (3.5f);
}

Reply via email to