https://gcc.gnu.org/bugzilla/show_bug.cgi?id=95349
--- Comment #30 from Richard Biener <rguenth at gcc dot gnu.org> --- (In reply to Andrew Downing from comment #29) > So I think this sort of equivalent example in C shows what's going wrong in > the C++ example. https://godbolt.org/z/ZMz4Cp > > gcc knows that if the object mem points to is modified inside pun() its > effective type will change to the type of the value that is assigned because > the object mem points to has no declared type. If the argument to pun has a > declared type, the code doesn't work, like in the c++ example. As said earlier the issue is that pun() is completely elided and GCC doesn't see anything else than a simple pointer cast of its argument at the caller side (after inlining). > So for this c++ example https://godbolt.org/z/NeAJ5d could a solution be for > gcc to treat placement new as if it were a modifying access and as if it's > parameter had no declared type. So it would change the effective type of d > in f1 to uint64_t, or at least insert IL instructions to simulate that? The main issue with placement new is that it is not necessary to use placement new! In C++, for POD (or some bigger set of) types you can simply start using storage in a new type, no need for a placement new. This is why GCC treats _every_ _store_ as possibly altering the dynamic type of the stored to object. So everything is fine - until all stores [possibly altering the dynamic type] are optimized away. So with your argument we'd have to insert extra magic instructions at _every_ store and we'd have to keep those (while we could elide the actual stores). While in the high-level IL this might be feasible things get tricky in RTL land where we'd have the choice to either not do TBAA anymore or also represent these "fake" memory state affecting instructions. In the end I'd rather not venture there but indeed that removing of stores has proven an issue in the past (PR93946 for example).