Virtual Destructors: Base class must have virtual destructor no matter if derived class has a destructor or not. There is UB according to paragraph 3 in [expr.delete].

This commit is contained in:
Daniel Marjamäki 2019-09-27 09:55:39 +02:00
parent b823064cce
commit 7f64faae99
2 changed files with 18 additions and 15 deletions

View File

@ -1639,7 +1639,7 @@ void CheckClass::virtualDestructor()
{
// This error should only be given if:
// * base class doesn't have virtual destructor
// * derived class has non-empty destructor
// * derived class has non-empty destructor (only c++03, in c++11 it's UB see paragraph 3 in [expr.delete])
// * base class is deleted
// unless inconclusive in which case:
// * base class has virtual members but doesn't have virtual destructor
@ -1665,16 +1665,19 @@ void CheckClass::virtualDestructor()
continue;
}
// Find the destructor
const Function *destructor = scope->getDestructor();
// Check if destructor is empty and non-empty ..
if (mSettings->standards.cpp <= Standards::CPP03) {
// Find the destructor
const Function *destructor = scope->getDestructor();
// Check for destructor with implementation
if (!destructor || !destructor->hasBody())
continue;
// Check for destructor with implementation
if (!destructor || !destructor->hasBody())
continue;
// Empty destructor
if (destructor->token->linkAt(3) == destructor->token->tokAt(4))
continue;
// Empty destructor
if (destructor->token->linkAt(3) == destructor->token->tokAt(4))
continue;
}
const Token *derived = scope->classDef;
const Token *derivedClass = derived->next();

View File

@ -2497,35 +2497,35 @@ private:
}
void virtualDestructor4() {
// Derived class doesn't have a destructor => no error
// Derived class doesn't have a destructor => undefined behaviour according to paragraph 3 in [expr.delete]
checkVirtualDestructor("class Base { public: ~Base(); };\n"
"class Derived : public Base { };"
"Base *base = new Derived;\n"
"delete base;");
ASSERT_EQUALS("", errout.str());
ASSERT_EQUALS("[test.cpp:1]: (error) Class 'Base' which is inherited by class 'Derived' does not have a virtual destructor.\n", errout.str());
checkVirtualDestructor("class Base { public: ~Base(); };\n"
"class Derived : private Fred, public Base { };"
"Base *base = new Derived;\n"
"delete base;");
ASSERT_EQUALS("", errout.str());
ASSERT_EQUALS("[test.cpp:1]: (error) Class 'Base' which is inherited by class 'Derived' does not have a virtual destructor.\n", errout.str());
}
void virtualDestructor5() {
// Derived class has empty destructor => no error
// Derived class has empty destructor => undefined behaviour according to paragraph 3 in [expr.delete]
checkVirtualDestructor("class Base { public: ~Base(); };\n"
"class Derived : public Base { public: ~Derived() {} };"
"Base *base = new Derived;\n"
"delete base;");
ASSERT_EQUALS("", errout.str());
ASSERT_EQUALS("[test.cpp:1]: (error) Class 'Base' which is inherited by class 'Derived' does not have a virtual destructor.\n", errout.str());
checkVirtualDestructor("class Base { public: ~Base(); };\n"
"class Derived : public Base { public: ~Derived(); }; Derived::~Derived() {}"
"Base *base = new Derived;\n"
"delete base;");
ASSERT_EQUALS("", errout.str());
ASSERT_EQUALS("[test.cpp:1]: (error) Class 'Base' which is inherited by class 'Derived' does not have a virtual destructor.\n", errout.str());
}
void virtualDestructor6() {