https://gcc.gnu.org/bugzilla/show_bug.cgi?id=70526
--- Comment #25 from Jonathan Wakely <redi at gcc dot gnu.org> --- std::aligned_storage has no equivalent of the addr() member function that would need adjusting, it's just the union U part of the AlignedStorage2 type in comment 23, where sizeof(T) is a template parameter, rather than T. __gnu_cxx::__aligned_buffer<T> and __gnu_cxx::__aligned_membuf<T> are similar to the class template discussed above, but if I understand the issue correctly, they don't need adjusting because we don't misuse them. We create objects in them with placement new, and we don't attempt to use the aggregate copy (because that would obviously do the wrong thing). In fact I don't think we ever try to copy those objects. The closest we get to copying them would do something like: void f(__gnu_cxx::__aligned_buffer<X> buf) { __gnu_cxx::__aligned_buffer<X> buf2; X* x = ::new (buf2.addr()) X(*buf.ptr()); // use x x->~X(); } i.e. we create copies of the stored object using placement new, but don't copy the aligned buffer objects themselves. (In reply to Richard Biener from comment #20) > (In reply to Jan de Mooij from comment #17) > > So IIUC it's wrong to store to |typed| in the constructor, by doing this: > > > > *typed.addr() = reg; > > > > Why is that? Any suggestions on how to fix this on our end? > > No, it's valid to do that. It's only valid because Register is a trivial type. Otherwise you'd be assigning to an object which was never constructed, i.e. it's lifetime never started. In the general case the safe way to construct that object is with placement new: ::new ((void*)typed.addr()) Register(reg); This begins the lifetime of a Register object at the desired location.