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?
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.