Search code examples
c++language-lawyerc++17destructorcompiler-generated

Does this code result in a materialized base prvalue, and should it compile?


The following code compiles in gcc 9.1 godbolt but not clang 8 godbolt:

class A {
protected:
    ~A() = default;
};

class B final : public A {
};

int main() {
    auto b = B{};
}

Clang's error:

<source>:10:16: error: temporary of type 'A' has protected destructor
    auto b = B{};
               ^
<source>:3:5: note: declared protected here
    ~A() = default;
    ^

Which is correct and why?


Solution

  • Yes, Clang is correct in rejecting the code.

    In auto b = B{}; we have an aggregate initialization, which happens directly in main function. So this function must be able to call destructors of B subtypes in case of exception occurrence during the initialization.

    A quotation from N4861 (the last C++20 draft), [dcl.init.aggr]/8:

    The destructor for each element of class type is potentially invoked from the context where the aggregate initialization occurs. [ Note: This provision ensures that destructors can be called for fully-constructed subobjects in case an exception is thrown. — end note ]

    Just to be complete, a quote from [class.dtor]/15:

    [...] A program is ill-formed if a destructor that is potentially invoked is deleted or not accessible from the context of the invocation.