Virtual destructors : Handle inheritance where
"private|protected|public" is not defined
This commit is contained in:
parent
5a80bcc352
commit
057d6f1f18
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|
|
@ -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() );
|
||||||
|
|
Loading…
Reference in New Issue