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