From 984cd47aac8e57a0f04ab4236fc4c7b5d8eba720 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Marjam=C3=A4ki?= Date: Sat, 6 Dec 2008 19:26:13 +0000 Subject: [PATCH] virtual destructor : iterate through base classes for a derived class to check that the destructor in each base class i virtual --- CheckClass.cpp | 54 +++++++++++++++++++++++++++----------------------- testclass.cpp | 8 ++++++++ 2 files changed, 37 insertions(+), 25 deletions(-) diff --git a/CheckClass.cpp b/CheckClass.cpp index f18665e20..4d93bcb6e 100644 --- a/CheckClass.cpp +++ b/CheckClass.cpp @@ -673,38 +673,42 @@ void CheckClass::virtualDestructor() const TOKEN *derived = TOKEN::findmatch(_tokenizer->tokens(), "class %var% : public %var%"); while (derived) { - // Name of base class.. - const char *baseName[2]; - 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 ) + // Iterate through each base class... + for ( derived = derived->tokAt(3); TOKEN::Match(derived, "public %var%"); derived = derived->tokAt(3) ) { - // Is the class declaration available? - base = TOKEN::findmatch(_tokenizer->tokens(), "class %var1% :|{", baseName); - if ( base ) + // Name of base class.. + const char *baseName[2]; + 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; - 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()); } } - // There is a destructor. Check that it's virtual.. - 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%"); + derived = TOKEN::findmatch(derived, "class %var% : public %var%"); } } //--------------------------------------------------------------------------- diff --git a/testclass.cpp b/testclass.cpp index b3e7f6054..d4a6a800a 100644 --- a/testclass.cpp +++ b/testclass.cpp @@ -39,6 +39,7 @@ private: TEST_CASE( virtualDestructor1 ); TEST_CASE( virtualDestructor2 ); TEST_CASE( virtualDestructor3 ); + TEST_CASE( virtualDestructor4 ); } // Check that base classes have virtual destructors @@ -79,6 +80,13 @@ private: "class Derived : public Base { };"); 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 )