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.

Reply via email to