https://gcc.gnu.org/bugzilla/show_bug.cgi?id=98665
--- Comment #2 from Jonathan Wakely <redi at gcc dot gnu.org> --- If you make everything constexpr then Clang will correctly diagnose the UB, but GCC fails to: constexpr int IntSize() { return sizeof(int); } #include <cassert> // - template<typename T> class Maybe { bool mIsSome = false; T mVal = {}; public: Maybe() = default; constexpr Maybe(const T& rhs) : mIsSome(true), mVal(rhs) {} constexpr T& operator*() { assert(mIsSome); return mVal; } }; // - struct Int { int val = {}; Int() = default; constexpr Int(int x) : val(x) {} }; struct Even : public Int { public: constexpr static Maybe<Even> From(const Int x) { if (x.val & 1) return {}; return Even{x.val}; } Even() = default; private: constexpr Even(int x) : Int(x) { assert((val & 1) == 0); } }; constexpr int Oops(const Int i) { const auto& e = *Even::From(i); // lvalue ref lifetime extension of sub-object // of temporary? return e.val + 9; // or UB access? } int main() { constexpr int i = Oops({}); } GCC should not compile this.