virtual destructor : iterate through base classes for a derived class to check that the destructor in each base class i virtual

This commit is contained in:
Daniel Marjamäki 2008-12-06 19:26:13 +00:00
parent 8a06b71949
commit 984cd47aac
2 changed files with 37 additions and 25 deletions

View File

@ -673,38 +673,42 @@ void CheckClass::virtualDestructor()
const TOKEN *derived = TOKEN::findmatch(_tokenizer->tokens(), "class %var% : public %var%"); const TOKEN *derived = TOKEN::findmatch(_tokenizer->tokens(), "class %var% : public %var%");
while (derived) while (derived)
{ {
// Name of base class.. // Iterate through each base class...
const char *baseName[2]; for ( derived = derived->tokAt(3); TOKEN::Match(derived, "public %var%"); derived = derived->tokAt(3) )
baseName[0] = derived->strAt( 4 );
baseName[1] = 0;
// Find the destructor for the base class.
const TOKEN *base = TOKEN::findmatch(_tokenizer->tokens(), "%any% ~ %var1% (", baseName);
while (TOKEN::Match(base, "::"))
base = TOKEN::findmatch(base->next, "%any% ~ %var1% (", baseName);
// Check that there is a destructor..
if ( ! base )
{ {
// Is the class declaration available? // Name of base class..
base = TOKEN::findmatch(_tokenizer->tokens(), "class %var1% :|{", baseName); const char *baseName[2];
if ( base ) baseName[0] = derived->strAt(1);
baseName[1] = 0;
// Find the destructor for the base class.
const TOKEN *base = TOKEN::findmatch(_tokenizer->tokens(), "%any% ~ %var1% (", baseName);
while (TOKEN::Match(base, "::"))
base = TOKEN::findmatch(base->next, "%any% ~ %var1% (", baseName);
// Check that there is a destructor..
if ( ! base )
{
// Is the class declaration available?
base = TOKEN::findmatch(_tokenizer->tokens(), "class %var1% :|{", baseName);
if ( base )
{
std::ostringstream errmsg;
errmsg << _tokenizer->fileLine(base) << ": Base class " << baseName[0] << " doesn't have a virtual destructor";
_errorLogger->reportErr(errmsg.str());
}
}
// There is a destructor. Check that it's virtual..
else if ( ! TOKEN::Match(base, "virtual") )
{ {
std::ostringstream errmsg; std::ostringstream errmsg;
errmsg << _tokenizer->fileLine(base) << ": Base class " << baseName[0] << " doesn't have a virtual destructor"; errmsg << _tokenizer->fileLine(base) << ": The destructor for the base class " << baseName[0] << " is not virtual";
_errorLogger->reportErr(errmsg.str()); _errorLogger->reportErr(errmsg.str());
} }
} }
// There is a destructor. Check that it's virtual.. derived = TOKEN::findmatch(derived, "class %var% : public %var%");
else if ( ! TOKEN::Match(base, "virtual") )
{
std::ostringstream errmsg;
errmsg << _tokenizer->fileLine(base) << ": The destructor for the base class " << baseName[0] << " is not virtual";
_errorLogger->reportErr(errmsg.str());
}
derived = TOKEN::findmatch(derived->next, "class %var% : public %var%");
} }
} }
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------

View File

@ -39,6 +39,7 @@ private:
TEST_CASE( virtualDestructor1 ); TEST_CASE( virtualDestructor1 );
TEST_CASE( virtualDestructor2 ); TEST_CASE( virtualDestructor2 );
TEST_CASE( virtualDestructor3 ); TEST_CASE( virtualDestructor3 );
TEST_CASE( virtualDestructor4 );
} }
// Check that base classes have virtual destructors // Check that base classes have virtual destructors
@ -79,6 +80,13 @@ private:
"class Derived : public Base { };"); "class Derived : public Base { };");
ASSERT_EQUALS( std::string("[test.cpp:1]: The destructor for the base class Base is not virtual\n"), errout.str() ); ASSERT_EQUALS( std::string("[test.cpp:1]: The destructor for the base class Base is not virtual\n"), errout.str() );
} }
void virtualDestructor4()
{
checkVirtualDestructor("class Base { public: ~Base(); };\n"
"class Derived : public Fred, public Base { };");
ASSERT_EQUALS( std::string("[test.cpp:1]: The destructor for the base class Base is not virtual\n"), errout.str() );
}
}; };
REGISTER_TEST( TestClass ) REGISTER_TEST( TestClass )