https://gcc.gnu.org/bugzilla/show_bug.cgi?id=98665
Bug ID: 98665 Summary: lvalue ref lifetime extension missing for via sub-object of temporary expression Product: gcc Version: unknown Status: UNCONFIRMED Keywords: wrong-code Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: jgilbert at mozilla dot com Target Milestone: --- This is like bug 81420. Taking an lvalue ref of a sub-object expression should extend the lifetimes of the needed sub-objects to the lifetime of the lvalue ref. I believe that apples to this case, and clang and msvc seem to compile it that way. (which doesn't mean it's not UB, of course) It's possible that this example is past some complexity limit where the lvalue ref rule becomes impossible to handle, but this seems suspect enough (especially given bug 81420 which we've had trouble with before) that I'm filing this bug. In the example below, GCC compile Oops() into `return 9`: https://godbolt.org/z/MYPhaW > #include <cassert> > > // - > > template<typename T> > class Maybe { > bool mIsSome = false; > T mVal = {}; > > public: > Maybe() = default; > Maybe(const T& rhs) : mIsSome(true), mVal(rhs) {} > > T& operator*() { > assert(mIsSome); > return mVal; > } > }; > > // - > > struct Int { > int val = {}; > > Int() = default; > Int(int x) : val(x) {} > }; > > struct Even : public Int { > public: > static Maybe<Even> From(const Int x) { > if (x.val & 1) return {}; > return Even{x.val}; > } > > Even() = default; > private: > Even(int x) : Int(x) { > assert((val & 1) == 0); > } > }; > > // - > > 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? > }