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?
> }

Reply via email to