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

--- Comment #32 from rguenther at suse dot de <rguenther at suse dot de> ---
On Tue, 7 Mar 2017, redi at gcc dot gnu.org wrote:

> https://gcc.gnu.org/bugzilla/show_bug.cgi?id=79671
> 
> Jonathan Wakely <redi at gcc dot gnu.org> changed:
> 
>            What    |Removed                     |Added
> ----------------------------------------------------------------------------
>          Resolution|INVALID                     |FIXED
> 
> --- Comment #30 from Jonathan Wakely <redi at gcc dot gnu.org> ---
> The code in comment 20 still fails even with attribute((may_alias)), so I'm 
> not
> sure how the boost code can be fixed:
> 
> inline void* operator new(__SIZE_TYPE__, void *p) { return p; }
> struct A { A (float x) : f (x) {} float f; };
> static_assert(sizeof(A) == sizeof(float), "");
> struct B
> {
>   int x;
>   union __attribute__((__may_alias__)) U
>   {
>     int a;
>     char b[sizeof (float)];
>   } u;
>   int y;
> };
> 
> __attribute__((noinline, noclone)) void
> bar (B &x, B &y)
> {
>   if (x.x != 0)
>     __builtin_abort ();
>   if (x.y != 3)
>     __builtin_abort ();
>   if (y.x != 0)
>     __builtin_abort ();
>   if (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)) 
> B *
> baz (B &x)
> {
>   return &x;
> }
> 
> __attribute__((noinline, noclone)) void
> foo (float x)
> {
>   B b { 0, {}, 3 }, c;
>   B *p = baz (b);
>   new (b.u.b) A (x);

The issue is that while operator new takes a ref-all pointer here
it just returns void * which is then passed as this to A::A and thus
construction happens via a non-ref-all pointer.

That is, C++ abstraction comes in the way of may_alias (basically
casting that away again).

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

Reply via email to