https://gcc.gnu.org/bugzilla/show_bug.cgi?id=95349
--- Comment #34 from Richard Biener <rguenth at gcc dot gnu.org> --- (In reply to Andrew Downing from comment #33) > Those are all perfectly good arguments, but the problem ended up not having > anything to do with std::launder or new implicit object creation rules or > anything else introduced in the most recent standards right? This should be > well defined in c++11 and on https://godbolt.org/z/w5FoZN. It compiles > correctly until gcc 5.1, and in all versions of the other major compilers > I've tried that will actually compile on godbolt.org. As far as I can tell, > it should also be well defined in c++98 and on if you use different types > and check the size and alignment some other way. GCC assumes that memcpy transfers the dynamic type as it does in C which makes the testcase invalid without the new implicit object creation rules (which then must rely on that memcpy behavior). Citing your new example here: #include <new> #include <cstring> #include <cstdlib> #include <cstdint> static_assert(sizeof(double) == sizeof(std::uint64_t), ""); static_assert(alignof(double) == alignof(std::uint64_t), ""); std::uint64_t *pun(void *p) { char storage[sizeof(double)]; std::memcpy(storage, p, sizeof(storage)); std::uint64_t *u = new(p) std::uint64_t; std::memcpy(u,storage, sizeof(storage)); return u; } std::uint64_t f1(std::uint64_t *maybe) { double d = 3.14159; std::uint64_t *u = pun(&d); if(rand() == 0) { u = maybe; } return *u; } In particular in C++14 3.9/4 refers to footnote 44 which says "The intent is that the memory model of C++ is compatible with that of ISO/IEC 9899 Programming Language C" which is a laudable goal. But I see that information about the memory model and the impact of language features on it is scattered across many places in the C++ standard and some wordings sound contradictory. And I always fail to remember where all the relevant points were. But I did a thorough research of C and C++ standards when implementing what GCC does in the GCC 5 timeframe (where it was C++11 and C++14 draft state IIRC). IMHO you cannot elide memcpy if it implicitely creates an object of a type that is only determined later by (the first?) access. It would also be an extremely bad choice of semantics. Making it so that memcpy does not alter the type of the destination object is bad as well if you consider re-use of allocated storage where the last access to the old object is visible which determines the dynamic type. So what C specifies is the only viable semantics for memcpy. C has the additional restriction of declared objects which does not apply to C++ and thus GCC does not use that for C either.