User account creation filtered due to spam.

Bug 71786 - Constructor never called
Summary: Constructor never called
Status: RESOLVED INVALID
Alias: None
Product: gcc
Classification: Unclassified
Component: c++ (show other bugs)
Version: unknown
: P3 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2016-07-07 01:37 UTC by Guille
Modified: 2016-07-07 21:29 UTC (History)
0 users

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Guille 2016-07-07 01:37:29 UTC
The following two assertions fail:

#include <set>
#include <cassert>
#include <experimental/optional>

std::set<std::uintptr_t> all;

struct A
{
    A()
    {
        all.insert((std::uintptr_t)this);
    }
    ~A()
    {
        assert(!all.empty());                                       // FAILS
        assert(all.find((std::uintptr_t)this) != all.end());        // FAILS
        all.erase((std::uintptr_t)this);
    }
};

static std::experimental::optional<A> f()
{
    A a;
    return a;
}

int main()
{
    auto a = f();
    return 0;
}

I'm using 'gcc version 7.0.0 20160605', A's constructor seems to never be called, since the first assertion fails. 
I don't get this error when 'f' is declared 'static A f()' instead.
Comment 1 Guille 2016-07-07 01:38:43 UTC
I should note, the destructor *is* called, but not the constructor.
Comment 2 Guille 2016-07-07 01:47:33 UTC
I added some printing-code to it. This is what I get:

A() -> INSERT: 0x7fff5c44cb2f
~A() -> ERASE: 0x7fff5c44cb2f
~A() -> ERASE: 0x7fff5c44cb40
Assertion failed: (!all.empty()), function ~A, file gcc_bug.c, line 20.

So the constructor for 'A a;' seems to be called, but 'std::experimental::optional' may be missing calling a constructor. 

This may be a libstdc++ bug, I wasn't sure where to post it.
Comment 3 Marc Glisse 2016-07-07 07:40:16 UTC
The second A is constructed by a copy/move constructor, which is generated by default. You need to write one yourself and register the pointer there.
Comment 4 Guille 2016-07-07 18:52:46 UTC
Hi Marc, 

Thank you for your clarification. 

I realized my initial problem arose in a slightly more complicated case (below).
 
In this case a copy/move ctor of A is used, but this default-generated ctor does not construct the base case B. Shouldn't default ctors automatically construct base classes?

std::set<std::uintptr_t> all;

struct B
{
    B()
    {
        all.insert((std::uintptr_t)this);
    }
    ~B()
    {
        assert(all.find((std::uintptr_t)this) != all.end());        // FAILS
        all.erase((std::uintptr_t)this);
    }
};
struct A : B
{
    A() : B() {}
//  A(const A&) : B() {}
    ~A() {}
};

static std::experimental::optional<A> f()
{
    A a;
    return a;
}

int main()
{
    auto a = f();
    return 0;
}
Comment 5 Guille 2016-07-07 21:29:25 UTC
Sorry for the confusion, I'll post as a separate report for clarity.