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:
parent
8a06b71949
commit
984cd47aac
|
@ -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%");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|
|
@ -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 )
|
||||||
|
|
Loading…
Reference in New Issue