Virtual destructors : Handle inheritance where

"private|protected|public" is not defined
This commit is contained in:
Daniel Marjamäki 2008-12-07 06:31:54 +00:00
parent 5a80bcc352
commit 057d6f1f18
2 changed files with 185 additions and 163 deletions

View File

@ -670,18 +670,30 @@ void CheckClass::CheckOperatorEq1()
void CheckClass::virtualDestructor() void CheckClass::virtualDestructor()
{ {
const TOKEN *derived = TOKEN::findmatch(_tokenizer->tokens(), "class %var% : public|protected|private %var%"); const char pattern_classdecl[] = "class %var% : %var%";
const TOKEN *derived = TOKEN::findmatch(_tokenizer->tokens(), pattern_classdecl);
while (derived) while (derived)
{ {
// Iterate through each base class... // Iterate through each base class...
for ( derived = derived->tokAt(3); TOKEN::Match(derived, "public|protected|private %var%"); derived = derived->tokAt(3) ) derived = derived->tokAt(3);
while ( TOKEN::Match(derived, "%var%") )
{ {
// What kind of inheritance is it.. public|protected|private
if ( TOKEN::Match( derived, "public|protected|private" ) )
derived = derived->next;
// Name of base class.. // Name of base class..
const char *baseName[2]; const char *baseName[2];
baseName[0] = derived->strAt(1); baseName[0] = derived->strAt(0);
baseName[1] = 0; baseName[1] = 0;
// Find the destructor for the base class. // Update derived so it's ready for the next loop.
derived = derived->next;
if ( TOKEN::Match(derived, ",") )
derived = derived->next;
// Find the destructor declaration for the base class.
const TOKEN *base = TOKEN::findmatch(_tokenizer->tokens(), "%any% ~ %var1% (", baseName); const TOKEN *base = TOKEN::findmatch(_tokenizer->tokens(), "%any% ~ %var1% (", baseName);
while (TOKEN::Match(base, "::")) while (TOKEN::Match(base, "::"))
base = TOKEN::findmatch(base->next, "%any% ~ %var1% (", baseName); base = TOKEN::findmatch(base->next, "%any% ~ %var1% (", baseName);
@ -708,7 +720,8 @@ void CheckClass::virtualDestructor()
} }
} }
derived = TOKEN::findmatch(derived, "class %var% : public %var%"); // Goto next class
derived = TOKEN::findmatch(derived, pattern_classdecl);
} }
} }
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------

View File

@ -36,10 +36,9 @@ private:
void run() void run()
{ {
TEST_CASE( virtualDestructor1 ); TEST_CASE( virtualDestructor1 ); // Base class not found => no error
TEST_CASE( virtualDestructor2 ); TEST_CASE( virtualDestructor2 ); // Base class doesn't have a destructor
TEST_CASE( virtualDestructor3 ); TEST_CASE( virtualDestructor3 ); // Base class has a destructor, but it's not virtual
TEST_CASE( virtualDestructor4 );
} }
// Check that base classes have virtual destructors // Check that base classes have virtual destructors
@ -63,26 +62,36 @@ private:
void virtualDestructor1() void virtualDestructor1()
{ {
// Base class not found
checkVirtualDestructor("class Derived : public Base { };"); checkVirtualDestructor("class Derived : public Base { };");
ASSERT_EQUALS( std::string(""), errout.str() ); ASSERT_EQUALS( std::string(""), errout.str() );
checkVirtualDestructor("class Derived : Base { };");
ASSERT_EQUALS( std::string(""), errout.str() );
} }
void virtualDestructor2() void virtualDestructor2()
{ {
// Base class doesn't have a destructor
checkVirtualDestructor("class Base { };\n" checkVirtualDestructor("class Base { };\n"
"class Derived : public Base { };"); "class Derived : public Base { };");
ASSERT_EQUALS( std::string("[test.cpp:1]: Base class Base doesn't have a virtual destructor\n"), errout.str() ); ASSERT_EQUALS( std::string("[test.cpp:1]: Base class Base doesn't have a virtual destructor\n"), errout.str() );
checkVirtualDestructor("class Base { };\n"
"class Derived : Base { };");
ASSERT_EQUALS( std::string("[test.cpp:1]: Base class Base doesn't have a virtual destructor\n"), errout.str() );
} }
void virtualDestructor3() void virtualDestructor3()
{ {
// Base class has a destructor, but it's not virtual
checkVirtualDestructor("class Base { public: ~Base(); };\n" checkVirtualDestructor("class Base { public: ~Base(); };\n"
"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" checkVirtualDestructor("class Base { public: ~Base(); };\n"
"class Derived : private Fred, public Base { };"); "class Derived : private Fred, 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() );