https://gcc.gnu.org/bugzilla/show_bug.cgi?id=70526
--- Comment #2 from Marc Glisse <glisse at gcc dot gnu.org> --- (In reply to Markus Trippelsdorf from comment #1) > -Wstrict-aliasing=2 warns: > > markus@x4 tmp % g++ -O2 -Wstrict-aliasing=2 test_fire.cpp > test_fire.cpp: In instantiation of ‘const T* AlignedStorage2<T>::addr() > const [with T = Register]’: > test_fire.cpp:41:52: required from here > test_fire.cpp:13:34: warning: dereferencing type-punned pointer will break > strict-aliasing rules [-Wstrict-aliasing] > const T* addr() const { return reinterpret_cast<const T*>(u.mBytes); } > > -fno-strict-aliasing fixes the issue, thus invalid. Isn't that a bit fast? -Wstrict-aliasing=3 doesn't warn, the read and the write are both done in type Register. Reducing a bit: typedef unsigned uint32_t; template<typename T> struct AlignedStorage2 { char mBytes[sizeof(T)]; const T* addr() const { return reinterpret_cast<const T*>(mBytes); } T* addr() { return reinterpret_cast<T*>(mBytes); } }; struct Register { uint32_t reg_; }; class TypedOrValueRegister { AlignedStorage2<Register> typed; __attribute__((noinline)) Register& dataTyped() { return *typed.addr(); } public: TypedOrValueRegister(Register reg) { dataTyped() = reg; } Register typedReg() const { return *typed.addr(); } }; int main() { Register reg = { 10u }; if (TypedOrValueRegister(reg).typedReg().reg_ != 10) __builtin_abort(); return 0; }