This is the mail archive of the gcc-bugs@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[Bug c++/78495] New: [7 regression][new inheriting ctors] variant members lead to uninitialized parameter


https://gcc.gnu.org/bugzilla/show_bug.cgi?id=78495

            Bug ID: 78495
           Summary: [7 regression][new inheriting ctors] variant members
                    lead to uninitialized parameter
           Product: gcc
           Version: 7.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: c++
          Assignee: unassigned at gcc dot gnu.org
          Reporter: lucdanton at free dot fr
  Target Milestone: ---

I noticed an std::unique_ptr<int> destructor was being called on a bogus
pointer in an own::optional<std::unique_ptr<int>> testcase of mine (not
std::optional/libstdc++-related). I managed to reduce to a minimal test and in
the debugger it looks like when the inherited constructor is entered the val
parameter contains garbage. Then upon leaving the constructor the
destructor for the parameter is run on that garbage.

Whatever the exact rundown of events, the regression is that the program used
to return 0 whereas it returns 1 now. The change in behaviour appeared with
r241765. From then on, compiling the testcase with -fnew-inheriting-ctors
gives the new behaviour while -fno-new-inheriting-ctors gives the old for both
-std=c++1z and -std=c++14.

//----------
int counter = 0;

struct canary {
    canary() {}

    bool active = false;

    canary(canary const&) = delete;
    canary(canary&& other): active(other.active) { other.active = false; }

    ~canary()
    { if(active) ++counter; }
};

struct optional_base {
    union {
        unsigned char empty {};
        canary val;
    };
    bool active = false;

    optional_base(canary val)
        : val(static_cast<canary&&>(val))
        , active(true)
    {}

    ~optional_base()
    {
        if(active) {
            val.~canary();
        }
    }
};

struct optional: optional_base {
    using optional_base::optional_base;
};

int main()
{
    {
        // N.B. inactive from the start
        canary c;
        //assert( !c.active );

        optional o(static_cast<canary&&>(c));

        //assert( !c.active );
        // may fire if -O level above 0
        //assert( !o.val.active );
    }

    return counter;
}

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]