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:
parent
b823064cce
commit
7f64faae99
|
@ -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();
|
||||
|
|
|
@ -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() {
|
||||
|
|
Loading…
Reference in New Issue