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

--- Comment #6 from Jakub Jelinek <jakub at gcc dot gnu.org> ---
Still need to add further testcase coverage and finish cookie support, but I
ran into something that looks like a bug in the C++ standard.

[dcl.constexpr]/3 says:
if the function is a constructor or destructor, its class shall not have any
virtual base classes;
[dcl.constexpr]/5 says:
The definition of a constexpr destructor whose function-body is not = delete
shall additionally satisfy the following requirement:
- for every subobject of class type or (possibly multi-dimensional) array
thereof, that class type shall have a constexpr destructor.
[class.dtor]/8 says:
A destructor is trivial if it is not user-provided and if:
- the destructor is not virtual,
- all of the direct base classes of its class have trivial destructors, and
- for all of the non-static data members of its class that are of class type
(or array thereof), each such class has a trivial destructor.
[class.dtor]/9 says:
A defaulted destructor is a constexpr destructor if it satisfies the
requirements for a constexpr destructor ([dcl.constexpr]).
[ Note: In particular, a trivial destructor is a constexpr destructor.
— end note ]

Now, consider the g++.old-deja/g++.mike/p12306a.C or g++.dg/abi/empty7.C
testcases in -std=c++2a modes, let's say the first one:

class a {
public:
    int i;
};

class g : virtual public a {
};

class b : virtual public a {
    int j;
};

class c : public g, public b {
};

class d {
public:
    virtual class b* get() {return 0;}
};

class f : public d {
public:
    virtual class b* get() {return &_c;}
    c _c;
};

int main(void) {
    f D;
    b* bp=D.get();
    D._c.i = 42;
    return &D._c.i != &bp->i;
}

The patch ICEs on this, because the implicit f::~f () is considered trivial
(there are no virtual destructors in the testcase, nor any user-provided
destructors),
but it isn't a constexpr destructor, because while f doesn't have virtual
bases, a non-static data member of f (_c) has virtual bases and thus c::~c ()
is not a constexpr destructor and because of that f::~f () can't be a constexpr
destructor either.

So, is the [class.dtor]/9 note just incorrect and should be removed, or
clarified somehow?  I believe it shouldn't affect what actually is a literal
type or not, because
the constructor of a class without virtual bases which has a non-static data
member that has virtual bases can't be constexpr either.

On the compiler side, it would mean the trivial destructor quick bail-out
checks wouldn't actually work for when we ask whether the destructor is
constexpr, though we could keep it perhaps in the literal_type_p checking, at
least as long as a subobject with virtual bases really always forces
non-constexpr constructors.

Reply via email to