diff --git a/CheckClass.cpp b/CheckClass.cpp index a95b34d89..fda3b41f1 100644 --- a/CheckClass.cpp +++ b/CheckClass.cpp @@ -597,7 +597,8 @@ void CheckClass::CheckMemset() } } } -} +} +//--------------------------------------------------------------------------- @@ -615,6 +616,54 @@ void CheckClass::CheckOperatorEq1() ostr << _tokenizer->fileLine(tok) << ": 'operator=' should return something"; _errorLogger->reportErr(ostr.str()); } +} +//--------------------------------------------------------------------------- + + + + +//--------------------------------------------------------------------------- +// A destructor in a base class should be virtual +//--------------------------------------------------------------------------- + +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 (base && 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) << ": The destructor for the base class " << baseName[0] << " is not virtual"; + _errorLogger->reportErr(errmsg.str()); + } + + derived = TOKEN::findmatch(derived->next, "class %var% : public %var%"); + } } - +//--------------------------------------------------------------------------- diff --git a/CheckClass.h b/CheckClass.h index 2f3192467..ff455c856 100644 --- a/CheckClass.h +++ b/CheckClass.h @@ -38,6 +38,9 @@ public: void CheckMemset(); void CheckOperatorEq1(); // Warning upon "void operator=(.." + + // The destructor in a base class should be virtual + void virtualDestructor(); private: struct VAR diff --git a/cppcheck.cpp b/cppcheck.cpp index 7862fe79c..92d6fed71 100644 --- a/cppcheck.cpp +++ b/cppcheck.cpp @@ -261,6 +261,9 @@ void CppCheck::checkFile(const std::string &code, const char FileName[]) // Check that all class constructors are ok. checkClass.CheckConstructors(); + // Check that all base classes have virtual destructors + checkClass.virtualDestructor(); + if (_settings._showAll) { // Check for "if (a=b)"