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

lucdanton at free dot fr gcc-bugzilla@gcc.gnu.org
Wed Nov 23 14:26:00 GMT 2016


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


More information about the Gcc-bugs mailing list