https://gcc.gnu.org/bugzilla/show_bug.cgi?id=95349
--- Comment #22 from Richard Biener <rguenth at gcc dot gnu.org> --- (In reply to Richard Smith from comment #20) > (In reply to Andrew Downing from comment #19) > > Not that it would make a difference in this particular situation, but is the > > intent of P0593R6 to only allow implicitly creating an object in the > > relevant storage location where one hasn't already been implicitly or > > explicitly created? > > No, the new objects are allowed to replace existing objects. For example, > this implementation would also be correct: > > std::uint64_t* s3(double* p) { > std::memmove(p, p, sizeof(double)); > return std::launder(reinterpret_cast<std::uint64_t*>(p)); > } > > ... on the basis that it has defined behavior if the memmove implicitly > creates an 'uint64_t' object in the underlying storage after it (notionally) > copies the contents elsewhere and before it (notionally) copies the contents > back again. (The 'launder' is necessary in order to form a pointer to the > implicitly-created uint64_t object, because p doesn't point to that object.) Note that in GCCs view if there's a memcpy in the IL the memcpy destination has indetermine type and accesses using any effective type lvalue are well-defined. The issue with the testcase at hand is that GCC elides the memcpy (and the temporary object) completely - which was desired by the testcase author. But that loses this "barrier" from the IL. Note that GCC both implements the C and the C++ language and performs inter-CU optimization across language barriers and thus we need to find common grounds of semantics - such as memcpy. So for GCC the argument "this is C++, we don't care for C semantics" isn't productive. Note GCC also elides memcpy and memmove with identical source/destination even though this technically has barrier semantics. So IMHO std::start_lifetime_as would need first-class compiler support and be appropriately represented in the IL. Which also means it will have a non-zero overhead but less overhead than for example keeping a memmove (p, p, N) in the IL. Which leads me towards the suggestion to work on memcpy semantics since IMHO the C semantics provide the reason for what GCC does to the testcase and I find it extremely odd (and bad for general optimization that doesn't try to emulate std::start_lifetime_in_as) to require different semantics. Note we're already allowing dynamic type changes of objects with a declared type in C since that's also used in practice. Note we're already pessimizing C++ for re-using parts of objects. So IMHO no GCC bug to see here. And yes, GCC doesn't seem to be able to implement std::start_lifetime_as without larger overhead at the moment.