From 51e9d98a5fe7d2947037cd316a4c91cb0ebfefd5 Mon Sep 17 00:00:00 2001 From: Reijo Tomperi Date: Thu, 20 Nov 2008 22:19:26 +0000 Subject: [PATCH] Refactoring: Errors are no longer logged via global functions to a global stream. Instead callback function is used via interface. ErrorLogger interface was added and taken into use. --- CheckBufferOverrun.cpp | 12 +++++---- CheckBufferOverrun.h | 6 +++-- CheckClass.cpp | 15 ++++++----- CheckClass.h | 4 ++- CheckHeaders.cpp | 10 ++++--- CheckHeaders.h | 6 +++-- CheckMemoryLeak.cpp | 14 +++++----- CheckMemoryLeak.h | 4 ++- CheckOther.cpp | 52 +++++++++++++++++++------------------ CheckOther.h | 8 +++--- CommonCheck.cpp | 14 +--------- CommonCheck.h | 15 ----------- cppcheck.cpp | 30 ++++++++++++++------- cppcheck.h | 11 +++++++- errorlogger.h | 35 +++++++++++++++++++++++++ preprocessor.cpp | 11 +++++--- preprocessor.h | 6 ++++- testbufferoverrun.cpp | 11 +++++--- testcharvar.cpp | 11 ++++---- testconstructors.cpp | 11 ++++---- testdivision.cpp | 4 +-- testincompletestatement.cpp | 4 +-- testmemleak.cpp | 4 +-- testpreprocessor.cpp | 26 +++++++++---------- testrunner.cpp | 3 +-- testsimplifytokens.cpp | 6 +++-- testsuite.cpp | 11 +++++++- testsuite.h | 12 ++++++--- testtokenize.cpp | 11 ++++---- testunusedprivfunc.cpp | 4 +-- testunusedvar.cpp | 5 ++-- tokenize.cpp | 12 +++++---- tokenize.h | 8 +++--- 33 files changed, 239 insertions(+), 157 deletions(-) create mode 100644 errorlogger.h diff --git a/CheckBufferOverrun.cpp b/CheckBufferOverrun.cpp index ef8a7fc07..f17d48712 100644 --- a/CheckBufferOverrun.cpp +++ b/CheckBufferOverrun.cpp @@ -26,7 +26,8 @@ #include #include #include -#include +#include + #include // <- strtoul @@ -35,9 +36,10 @@ // CallStack used when parsing into subfunctions. -CheckBufferOverrunClass::CheckBufferOverrunClass( Tokenizer *tokenizer ) +CheckBufferOverrunClass::CheckBufferOverrunClass( Tokenizer *tokenizer, ErrorLogger *errorLogger ) { _tokenizer = tokenizer; + _errorLogger = errorLogger; } CheckBufferOverrunClass::~CheckBufferOverrunClass() @@ -53,7 +55,7 @@ void CheckBufferOverrunClass::ReportError(const TOKEN *tok, const char errmsg[]) for ( it = CallStack.begin(); it != CallStack.end(); it++ ) ostr << _tokenizer->fileLine(*it ) << " -> "; ostr << _tokenizer->fileLine(tok) << ": " << errmsg; - ReportErr(ostr.str()); + _errorLogger->reportErr(ostr.str()); } //--------------------------------------------------------------------------- @@ -504,14 +506,14 @@ void CheckBufferOverrunClass::WarningDangerousFunctions() { std::ostringstream ostr; ostr << _tokenizer->fileLine(tok) << ": Found 'gets'. You should use 'fgets' instead"; - ReportErr(ostr.str()); + _errorLogger->reportErr(ostr.str()); } else if (Match(tok, "scanf (") && strcmp(Tokenizer::getstr(tok,2),"\"%s\"") == 0) { std::ostringstream ostr; ostr << _tokenizer->fileLine(tok) << ": Found 'scanf'. You should use 'fgets' instead"; - ReportErr(ostr.str()); + _errorLogger->reportErr(ostr.str()); } } } diff --git a/CheckBufferOverrun.h b/CheckBufferOverrun.h index ea086ca58..2b170e2c2 100644 --- a/CheckBufferOverrun.h +++ b/CheckBufferOverrun.h @@ -23,11 +23,12 @@ //--------------------------------------------------------------------------- #include "tokenize.h" +#include "errorlogger.h" class CheckBufferOverrunClass { public: - CheckBufferOverrunClass( Tokenizer *tokenizer ); + CheckBufferOverrunClass( Tokenizer *tokenizer, ErrorLogger *errorLogger ); ~CheckBufferOverrunClass(); // Buffer overrun.. @@ -43,7 +44,8 @@ private: void ReportError(const TOKEN *tok, const char errmsg[]); Tokenizer *_tokenizer; - std::list CallStack; + ErrorLogger *_errorLogger; + std::list CallStack; }; //--------------------------------------------------------------------------- diff --git a/CheckClass.cpp b/CheckClass.cpp index dd998a18d..dce6d9e3c 100644 --- a/CheckClass.cpp +++ b/CheckClass.cpp @@ -34,10 +34,11 @@ #endif //--------------------------------------------------------------------------- -CheckClass::CheckClass( Tokenizer *tokenizer, const Settings &settings ) +CheckClass::CheckClass( Tokenizer *tokenizer, const Settings &settings, ErrorLogger *errorLogger ) { _tokenizer = tokenizer; _settings = settings; + _errorLogger = errorLogger; } CheckClass::~CheckClass() @@ -339,7 +340,7 @@ void CheckClass::CheckConstructors() std::ostringstream ostr; ostr << _tokenizer->fileLine(tok1); ostr << " The class '" << classname << "' has no constructor"; - ReportErr(ostr.str()); + _errorLogger->reportErr(ostr.str()); } // Delete the varlist.. while (varlist) @@ -378,7 +379,7 @@ void CheckClass::CheckConstructors() std::ostringstream ostr; ostr << _tokenizer->fileLine(constructor_token); ostr << " Uninitialized member variable '" << classname << "::" << var->name << "'"; - ReportErr(ostr.str()); + _errorLogger->reportErr(ostr.str()); } } @@ -533,7 +534,7 @@ void CheckClass::CheckUnusedPrivateFunctions() { std::ostringstream ostr; ostr << "Class '" << classname << "', unused private function: '" << FuncList.front() << "'"; - ReportErr(ostr.str()); + _errorLogger->reportErr(ostr.str()); } FuncList.pop_front(); } @@ -576,7 +577,7 @@ void CheckClass::CheckMemset() { std::ostringstream ostr; ostr << _tokenizer->fileLine(tok) << ": Using '" << tok->str << "' on class."; - ReportErr(ostr.str()); + _errorLogger->reportErr(ostr.str()); continue; } @@ -592,7 +593,7 @@ void CheckClass::CheckMemset() { std::ostringstream ostr; ostr << _tokenizer->fileLine(tok) << ": Using '" << tok->str << "' on struct that contains a 'std::" << Tokenizer::getstr(tstruct,2) << "'"; - ReportErr(ostr.str()); + _errorLogger->reportErr(ostr.str()); break; } } @@ -613,7 +614,7 @@ void CheckClass::CheckOperatorEq1() { std::ostringstream ostr; ostr << _tokenizer->fileLine(tok) << ": 'operator=' should return something"; - ReportErr(ostr.str()); + _errorLogger->reportErr(ostr.str()); } } diff --git a/CheckClass.h b/CheckClass.h index b6e4dea5e..5f355cfda 100644 --- a/CheckClass.h +++ b/CheckClass.h @@ -23,6 +23,7 @@ #include "tokenize.h" #include "settings.h" +#include "errorlogger.h" #include struct VAR @@ -35,7 +36,7 @@ struct VAR class CheckClass { public: - CheckClass( Tokenizer *tokenizer, const Settings &settings ); + CheckClass( Tokenizer *tokenizer, const Settings &settings, ErrorLogger *errorLogger ); ~CheckClass(); void CheckConstructors(); @@ -54,6 +55,7 @@ private: Tokenizer *_tokenizer; Settings _settings; + ErrorLogger *_errorLogger; }; //--------------------------------------------------------------------------- #endif diff --git a/CheckHeaders.cpp b/CheckHeaders.cpp index b38a9d36b..4e0eeca0b 100644 --- a/CheckHeaders.cpp +++ b/CheckHeaders.cpp @@ -20,7 +20,8 @@ //--------------------------------------------------------------------------- #include "CheckHeaders.h" #include "tokenize.h" -#include "CommonCheck.h" +#include "CommonCheck.h" + #include #include #include @@ -35,9 +36,10 @@ // HEADERS - No implementation in a header //--------------------------------------------------------------------------- -CheckHeaders::CheckHeaders( Tokenizer *tokenizer ) +CheckHeaders::CheckHeaders( Tokenizer *tokenizer, ErrorLogger *errorLogger ) { _tokenizer = tokenizer; + _errorLogger = errorLogger; } CheckHeaders::~CheckHeaders() @@ -57,7 +59,7 @@ void CheckHeaders::WarningHeaderWithImplementation() { std::ostringstream ostr; ostr << _tokenizer->fileLine(tok) << ": Found implementation in header"; - ReportErr(ostr.str()); + _errorLogger->reportErr(ostr.str()); // Goto next file.. unsigned int fileindex = tok->FileIndex; @@ -245,7 +247,7 @@ void CheckHeaders::WarningIncludeHeader() ostr << _tokenizer->fileLine(includetok) << ": The included header '" << includefile << "' is not needed"; if (NeedDeclaration) ostr << " (but a forward declaration is needed)"; - ReportErr(ostr.str()); + _errorLogger->reportErr(ostr.str()); } } } diff --git a/CheckHeaders.h b/CheckHeaders.h index 2405ed93e..852bdffe7 100644 --- a/CheckHeaders.h +++ b/CheckHeaders.h @@ -23,17 +23,19 @@ //--------------------------------------------------------------------------- #include "tokenize.h" +#include "errorlogger.h" class CheckHeaders { public: - CheckHeaders( Tokenizer *tokenizer ); + CheckHeaders( Tokenizer *tokenizer, ErrorLogger *errorLogger ); ~CheckHeaders(); void WarningHeaderWithImplementation(); void WarningIncludeHeader(); private: - Tokenizer *_tokenizer; + Tokenizer *_tokenizer; + ErrorLogger *_errorLogger; }; //--------------------------------------------------------------------------- diff --git a/CheckMemoryLeak.cpp b/CheckMemoryLeak.cpp index a969aee05..90ddafbc7 100644 --- a/CheckMemoryLeak.cpp +++ b/CheckMemoryLeak.cpp @@ -21,7 +21,8 @@ -#include "CommonCheck.h" +#include "CommonCheck.h" + #include // free @@ -41,10 +42,11 @@ //--------------------------------------------------------------------------- -CheckMemoryLeakClass::CheckMemoryLeakClass( Tokenizer *tokenizer, const Settings &settings ) +CheckMemoryLeakClass::CheckMemoryLeakClass( Tokenizer *tokenizer, const Settings &settings, ErrorLogger *errorLogger ) { _tokenizer = tokenizer; - _settings = settings; + _settings = settings; + _errorLogger = errorLogger; } CheckMemoryLeakClass::~CheckMemoryLeakClass() @@ -239,15 +241,15 @@ void CheckMemoryLeakClass::MismatchError( const TOKEN *Tok1, const std::list::const_iterator tok = callstack.begin(); tok != callstack.end(); ++tok ) errmsg << _tokenizer->fileLine(*tok) << " -> "; errmsg << _tokenizer->fileLine(Tok1) << ": Mismatching allocation and deallocation: " << varname; - ReportErr( errmsg.str() ); + _errorLogger->reportErr( errmsg.str() ); } //--------------------------------------------------------------------------- void CheckMemoryLeakClass::MemoryLeak( const TOKEN *tok, const char varname[] ) -{ +{ std::ostringstream errmsg; errmsg << _tokenizer->fileLine(tok) << ": Memory leak: " << varname; - ReportErr( errmsg.str() ); + _errorLogger->reportErr( errmsg.str() ); } //--------------------------------------------------------------------------- diff --git a/CheckMemoryLeak.h b/CheckMemoryLeak.h index c59134421..ad3df502d 100644 --- a/CheckMemoryLeak.h +++ b/CheckMemoryLeak.h @@ -27,6 +27,7 @@ #include "tokenize.h" #include "settings.h" +#include "errorlogger.h" #include #include @@ -35,7 +36,7 @@ enum AllocType { No, Malloc, gMalloc, New, NewA }; class CheckMemoryLeakClass { public: - CheckMemoryLeakClass( Tokenizer *tokenizer, const Settings &settings ); + CheckMemoryLeakClass( Tokenizer *tokenizer, const Settings &settings, ErrorLogger *errorLogger ); ~CheckMemoryLeakClass(); void CheckMemoryLeak(); @@ -73,6 +74,7 @@ private: bool isclass( const std::string &typestr ); Tokenizer *_tokenizer; + ErrorLogger *_errorLogger; Settings _settings; std::list listallocfunc; }; diff --git a/CheckOther.cpp b/CheckOther.cpp index a34c35be9..13b5b02a1 100644 --- a/CheckOther.cpp +++ b/CheckOther.cpp @@ -20,7 +20,8 @@ //--------------------------------------------------------------------------- #include "CheckOther.h" -#include "CommonCheck.h" +#include "CommonCheck.h" + #include #include #include @@ -35,9 +36,10 @@ // Warning on C-Style casts.. p = (kalle *)foo; //--------------------------------------------------------------------------- -CheckOther::CheckOther( Tokenizer *tokenizer ) +CheckOther::CheckOther( Tokenizer *tokenizer, ErrorLogger *errorLogger ) { - _tokenizer = tokenizer; + _tokenizer = tokenizer; + _errorLogger = errorLogger; } CheckOther::~CheckOther() @@ -61,7 +63,7 @@ void CheckOther::WarningOldStylePointerCast() std::ostringstream ostr; ostr << _tokenizer->fileLine(tok) << ": C-style pointer casting"; - ReportErr(ostr.str()); + _errorLogger->reportErr(ostr.str()); } } @@ -85,7 +87,7 @@ void CheckOther::WarningIsDigit() { std::ostringstream ostr; ostr << _tokenizer->fileLine(tok) << ": The condition can be simplified; use 'isdigit'"; - ReportErr(ostr.str()); + _errorLogger->reportErr(ostr.str()); } } } @@ -114,7 +116,7 @@ void CheckOther::WarningIsAlpha() { std::ostringstream ostr; ostr << _tokenizer->fileLine(tok) << ": The condition can be simplified; use 'isupper'"; - ReportErr(ostr.str()); + _errorLogger->reportErr(ostr.str()); continue; } @@ -127,7 +129,7 @@ void CheckOther::WarningIsAlpha() { std::ostringstream ostr; ostr << _tokenizer->fileLine(tok) << ": The condition can be simplified; use 'islower'"; - ReportErr(ostr.str()); + _errorLogger->reportErr(ostr.str()); continue; } @@ -144,7 +146,7 @@ void CheckOther::WarningIsAlpha() { std::ostringstream ostr; ostr << _tokenizer->fileLine(tok) << ": The condition can be simplified; use 'isalpha'"; - ReportErr(ostr.str()); + _errorLogger->reportErr(ostr.str()); } } } @@ -198,7 +200,7 @@ void CheckOther::WarningRedundantCode() { std::ostringstream ostr; ostr << _tokenizer->fileLine(tok) << ": Redundant condition. It is safe to deallocate a NULL pointer"; - ReportErr(ostr.str()); + _errorLogger->reportErr(ostr.str()); } } @@ -240,7 +242,7 @@ void CheckOther::WarningIf() { std::ostringstream ostr; ostr << _tokenizer->fileLine(tok) << ": Found \"if (condition);\""; - ReportErr(ostr.str()); + _errorLogger->reportErr(ostr.str()); } break; } @@ -296,7 +298,7 @@ void CheckOther::WarningIf() if (strcmp(cond, p[i]) == 0) ostr << (i < 3 ? "True" : "False"); } - ReportErr(ostr.str()); + _errorLogger->reportErr(ostr.str()); } } //--------------------------------------------------------------------------- @@ -336,7 +338,7 @@ void CheckOther::InvalidFunctionUsage() { std::ostringstream ostr; ostr << _tokenizer->fileLine(tok2) << ": Invalid radix in call to strtol or strtoul. Must be 0 or 2-36"; - ReportErr(ostr.str()); + _errorLogger->reportErr(ostr.str()); } } break; @@ -362,7 +364,7 @@ void CheckOther::CheckIfAssignment() { std::ostringstream ostr; ostr << _tokenizer->fileLine(tok) << ": Possible bug. Should it be '==' instead of '='?"; - ReportErr(ostr.str()); + _errorLogger->reportErr(ostr.str()); } } } @@ -401,7 +403,7 @@ void CheckOther::CheckUnsignedDivision() // One of the operands are signed, the other is unsigned.. std::ostringstream ostr; ostr << _tokenizer->fileLine(tok->next) << ": Warning: Division with signed and unsigned operators"; - ReportErr(ostr.str()); + _errorLogger->reportErr(ostr.str()); } } @@ -413,7 +415,7 @@ void CheckOther::CheckUnsignedDivision() { std::ostringstream ostr; ostr << _tokenizer->fileLine(tok->next) << ": Unsigned division. The result will be wrong."; - ReportErr(ostr.str()); + _errorLogger->reportErr(ostr.str()); } } @@ -425,7 +427,7 @@ void CheckOther::CheckUnsignedDivision() { std::ostringstream ostr; ostr << _tokenizer->fileLine(tok->next) << ": Unsigned division. The result will be wrong."; - ReportErr(ostr.str()); + _errorLogger->reportErr(ostr.str()); } } } @@ -585,7 +587,7 @@ void CheckOther::CheckVariableScope_LookupVar( const TOKEN *tok1, const char var // Warning if "used" is true std::ostringstream errmsg; errmsg << _tokenizer->fileLine(tok1) << " The scope of the variable '" << varname << "' can be limited"; - ReportErr( errmsg.str() ); + _errorLogger->reportErr( errmsg.str() ); } //--------------------------------------------------------------------------- @@ -602,7 +604,7 @@ void CheckOther::CheckConstantFunctionParameter() { std::ostringstream errmsg; errmsg << _tokenizer->fileLine(tok) << " " << Tokenizer::getstr(tok,5) << " is passed by value, it could be passed by reference/pointer instead"; - ReportErr( errmsg.str() ); + _errorLogger->reportErr( errmsg.str() ); } else if ( Match(tok,"[,(] const %type% %var% [,)]") ) @@ -614,14 +616,14 @@ void CheckOther::CheckConstantFunctionParameter() { std::ostringstream errmsg; errmsg << _tokenizer->fileLine(tok) << " " << Tokenizer::getstr(tok,3) << " is passed by value, it could be passed by reference/pointer instead"; - ReportErr( errmsg.str() ); + _errorLogger->reportErr( errmsg.str() ); } pattern[0] = "struct"; if ( Tokenizer::findtoken(_tokenizer->tokens(), pattern) ) { std::ostringstream errmsg; errmsg << _tokenizer->fileLine(tok) << " " << Tokenizer::getstr(tok,3) << " is passed by value, it could be passed by reference/pointer instead"; - ReportErr( errmsg.str() ); + _errorLogger->reportErr( errmsg.str() ); } } } @@ -682,7 +684,7 @@ void CheckOther::CheckStructMemberUsage() { std::ostringstream errmsg; errmsg << _tokenizer->fileLine(tok) << ": struct member '" << structname << "::" << varname << "' is never read"; - ReportErr(errmsg.str()); + _errorLogger->reportErr(errmsg.str()); } } } @@ -724,7 +726,7 @@ void CheckOther::CheckCharVariable() { std::ostringstream errmsg; errmsg << _tokenizer->fileLine(tok2->next) << ": Warning - using char variable as array index"; - ReportErr(errmsg.str()); + _errorLogger->reportErr(errmsg.str()); break; } @@ -732,7 +734,7 @@ void CheckOther::CheckCharVariable() { std::ostringstream errmsg; errmsg << _tokenizer->fileLine(tok2) << ": Warning - using char variable in bit operation"; - ReportErr(errmsg.str()); + _errorLogger->reportErr(errmsg.str()); break; } } @@ -768,14 +770,14 @@ void CheckOther::CheckIncompleteStatement() { std::ostringstream errmsg; errmsg << _tokenizer->fileLine(tok->next) << ": Redundant code: Found a statement that begins with string constant"; - ReportErr(errmsg.str()); + _errorLogger->reportErr(errmsg.str()); } if ( !Match(tok,"#") && Match(tok->next,"; %num%") && !Match(Tokenizer::gettok(tok,3), ",") ) { std::ostringstream errmsg; errmsg << _tokenizer->fileLine(tok->next) << ": Redundant code: Found a statement that begins with numeric constant"; - ReportErr(errmsg.str()); + _errorLogger->reportErr(errmsg.str()); } } } diff --git a/CheckOther.h b/CheckOther.h index f2822b394..2ce44afc8 100644 --- a/CheckOther.h +++ b/CheckOther.h @@ -23,12 +23,13 @@ #define CheckOtherH //--------------------------------------------------------------------------- -#include "tokenize.h" +#include "tokenize.h" +#include "errorlogger.h" class CheckOther { public: - CheckOther( Tokenizer *tokenizer ); + CheckOther( Tokenizer *tokenizer, ErrorLogger *errorLogger ); ~CheckOther(); // Casting @@ -75,7 +76,8 @@ public: private: void CheckVariableScope_LookupVar( const TOKEN *tok1, const char varname[] ); - Tokenizer *_tokenizer; + Tokenizer *_tokenizer; + ErrorLogger *_errorLogger; }; //--------------------------------------------------------------------------- diff --git a/CommonCheck.cpp b/CommonCheck.cpp index f2763e6e8..f87e08352 100644 --- a/CommonCheck.cpp +++ b/CommonCheck.cpp @@ -32,8 +32,7 @@ #include #endif //--------------------------------------------------------------------------- -bool OnlyReportUniqueErrors; -std::ostringstream errout; + @@ -56,18 +55,7 @@ bool SameFileName( const char fname1[], const char fname2[] ) } //--------------------------------------------------------------------------- -std::list ErrorList; -void ReportErr(const std::string &errmsg) -{ - if ( OnlyReportUniqueErrors ) - { - if ( std::find( ErrorList.begin(), ErrorList.end(), errmsg ) != ErrorList.end() ) - return; - ErrorList.push_back( errmsg ); - } - errout << errmsg << std::endl; -} //--------------------------------------------------------------------------- bool IsName(const char str[]) diff --git a/CommonCheck.h b/CommonCheck.h index bebbe17ac..da185478e 100644 --- a/CommonCheck.h +++ b/CommonCheck.h @@ -32,25 +32,10 @@ // Are two filenames the same? Case insensitive on windows bool SameFileName( const char fname1[], const char fname2[] ); - -extern bool OnlyReportUniqueErrors; - -void ReportErr(const std::string &errmsg); -extern std::ostringstream errout; - - bool IsName(const char str[]); bool IsNumber(const char str[]); - bool IsStandardType(const char str[]); - - - - - bool Match(const TOKEN *tok, const char pattern[], const char *varname1[]=0, const char *varname2[]=0); - - //--------------------------------------------------------------------------- #endif diff --git a/cppcheck.cpp b/cppcheck.cpp index 27dd3df4a..dc1a43932 100644 --- a/cppcheck.cpp +++ b/cppcheck.cpp @@ -36,7 +36,7 @@ //--------------------------------------------------------------------------- -CppCheck::CppCheck() +CppCheck::CppCheck() : _tokenizer( this ) { _settings._debug = false; _settings._showAll = false; @@ -138,7 +138,7 @@ void CppCheck::check(int argc, char* argv[]) std::ifstream fin( fname.c_str() ); std::map code; - Preprocessor preprocessor; + Preprocessor preprocessor( this ); preprocessor.preprocess(fin, code, fname); for ( std::map::const_iterator it = code.begin(); it != code.end(); ++it ) checkFile(it->second, filenames[c].c_str(), c); @@ -182,9 +182,6 @@ void CppCheck::check(int argc, char* argv[]) void CppCheck::checkFile(const std::string &code, const char FileName[], unsigned int FileId) { - - OnlyReportUniqueErrors = true; - // Tokenize the file { std::istringstream istr(code); @@ -196,13 +193,13 @@ void CppCheck::checkFile(const std::string &code, const char FileName[], unsigne // Check that the memsets are valid. // The 'memset' function can do dangerous things if used wrong. // Important: The checking doesn't work on simplified tokens list. - CheckClass checkClass( &_tokenizer, _settings ); + CheckClass checkClass( &_tokenizer, _settings, this ); checkClass.CheckMemset(); // Check for unsigned divisions where one operand is signed // Very important to run it before 'SimplifyTokenList' - CheckOther checkOther( &_tokenizer ); + CheckOther checkOther( &_tokenizer, this ); checkOther.CheckUnsignedDivision(); // Give warning when using char variable as array index @@ -222,11 +219,11 @@ void CppCheck::checkFile(const std::string &code, const char FileName[], unsigne _tokenizer.SimplifyTokenList(); // Memory leak - CheckMemoryLeakClass checkMemoryLeak( &_tokenizer, _settings ); + CheckMemoryLeakClass checkMemoryLeak( &_tokenizer, _settings, this ); checkMemoryLeak.CheckMemoryLeak(); // Buffer overruns.. - CheckBufferOverrunClass checkBufferOverrun( &_tokenizer ); + CheckBufferOverrunClass checkBufferOverrun( &_tokenizer, this ); checkBufferOverrun.CheckBufferOverrun(); // Check that all class constructors are ok. @@ -298,4 +295,19 @@ void CppCheck::checkFile(const std::string &code, const char FileName[], unsigne } //--------------------------------------------------------------------------- +void CppCheck::reportErr( const std::string &errmsg) +{ + if ( /*OnlyReportUniqueErrors*/ true ) + { + if ( std::find( _errorList.begin(), _errorList.end(), errmsg ) != _errorList.end() ) + return; + _errorList.push_back( errmsg ); + } + errout << errmsg << std::endl; +} +void CppCheck::reportErr( const TOKEN *token, const std::string &errmsg) +{ + std::string message = _tokenizer.fileLine( token ) + errmsg; + reportErr( message ); +} diff --git a/cppcheck.h b/cppcheck.h index 094a6360d..dffa6db92 100644 --- a/cppcheck.h +++ b/cppcheck.h @@ -20,24 +20,33 @@ #define CPPCHECK_H #include +#include +#include #include "settings.h" #include "tokenize.h" // <- Tokenizer +#include "errorlogger.h" + /** * This is the base class which will use other classes to do * static code analysis for C and C++ code to find possible * errors or places that could be improved. */ -class CppCheck +class CppCheck : public ErrorLogger { public: CppCheck(); virtual ~CppCheck(); void check(int argc, char* argv[]); + virtual void reportErr( const TOKEN *token, const std::string &errmsg); + virtual void reportErr( const std::string &errmsg); + private: void checkFile(const std::string &code, const char FileName[], unsigned int FileId); Settings _settings; Tokenizer _tokenizer; + std::list _errorList; + std::ostringstream errout; }; #endif // CPPCHECK_H diff --git a/errorlogger.h b/errorlogger.h new file mode 100644 index 000000000..7eef369b5 --- /dev/null +++ b/errorlogger.h @@ -0,0 +1,35 @@ +/* + * c++check - c/c++ syntax checking + * Copyright (C) 2007-2008 Daniel Marjamäki and Reijo Tomperi + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see reportErr( oss.str() ); result.clear(); return; } diff --git a/preprocessor.h b/preprocessor.h index 1154fb217..3c74ee499 100644 --- a/preprocessor.h +++ b/preprocessor.h @@ -25,10 +25,12 @@ #include #include #include +#include "errorlogger.h" class Preprocessor { -public: +public: + Preprocessor( ErrorLogger *errorLogger ); void preprocess(std::istream &istr, std::map &result, const std::string &filename); private: /** @@ -44,6 +46,8 @@ private: std::string getdef(std::string line, bool def); bool match_cfg_def( std::string cfg, const std::string &def ); + + ErrorLogger *_errorLogger; }; //--------------------------------------------------------------------------- diff --git a/testbufferoverrun.cpp b/testbufferoverrun.cpp index 53a644638..cead642c5 100644 --- a/testbufferoverrun.cpp +++ b/testbufferoverrun.cpp @@ -21,7 +21,7 @@ #include "tokenize.h" #include "CommonCheck.h" #include "CheckBufferOverrun.h" -#include "testsuite.h" +#include "testsuite.h" #include @@ -33,11 +33,14 @@ public: TestBufferOverrun() : TestFixture("TestBufferOverrun") { } -private: +private: + + + void check( const char code[] ) { // Tokenize.. - Tokenizer tokenizer; + Tokenizer tokenizer( this ); tokenizer.getFiles()->push_back( "test.cpp" ); std::istringstream istr(code); tokenizer.TokenizeCode( istr ); @@ -53,7 +56,7 @@ private: errout.str(""); // Check for memory leaks.. - CheckBufferOverrunClass checkBufferOverrun( &tokenizer ); + CheckBufferOverrunClass checkBufferOverrun( &tokenizer, this ); checkBufferOverrun.CheckBufferOverrun(); tokenizer.DeallocateTokens(); diff --git a/testcharvar.cpp b/testcharvar.cpp index 5cd54470a..80939719a 100644 --- a/testcharvar.cpp +++ b/testcharvar.cpp @@ -20,8 +20,7 @@ #include "tokenize.h" #include "CommonCheck.h" #include "CheckOther.h" -#include "testsuite.h" - +#include "testsuite.h" #include extern std::ostringstream errout; @@ -32,7 +31,9 @@ public: TestCharVar() : TestFixture("TestCharVar") { } -private: +private: + + void run() { TEST_CASE( array_index ); @@ -43,7 +44,7 @@ private: void check( const char code[] ) { // Tokenize.. - Tokenizer tokenizer; + Tokenizer tokenizer( this ); tokenizer.getFiles()->push_back( "test.cpp" ); std::istringstream istr(code); tokenizer.TokenizeCode( istr ); @@ -58,7 +59,7 @@ private: errout.str(""); // Check for memory leaks.. - CheckOther checkOther( &tokenizer ); + CheckOther checkOther( &tokenizer, this ); checkOther.CheckCharVariable(); tokenizer.DeallocateTokens(); diff --git a/testconstructors.cpp b/testconstructors.cpp index 140746d0b..67268a59b 100644 --- a/testconstructors.cpp +++ b/testconstructors.cpp @@ -20,8 +20,7 @@ #include "tokenize.h" #include "CheckClass.h" -#include "testsuite.h" - +#include "testsuite.h" #include extern std::ostringstream errout; @@ -32,11 +31,13 @@ public: TestConstructors() : TestFixture("TestConstructors") { } -private: +private: + + void check( const char code[] ) { // Tokenize.. - Tokenizer tokenizer; + Tokenizer tokenizer( this ); tokenizer.getFiles()->push_back( "test.cpp" ); std::istringstream istr(code); tokenizer.TokenizeCode( istr ); @@ -48,7 +49,7 @@ private: // Check for memory leaks.. Settings settings; settings._checkCodingStyle = true; - CheckClass checkClass( &tokenizer, settings ); + CheckClass checkClass( &tokenizer, settings, this ); checkClass.CheckConstructors(); tokenizer.DeallocateTokens(); diff --git a/testdivision.cpp b/testdivision.cpp index 0618633f9..678c79929 100644 --- a/testdivision.cpp +++ b/testdivision.cpp @@ -39,7 +39,7 @@ private: void check( const char code[] ) { // Tokenize.. - Tokenizer tokenizer; + Tokenizer tokenizer( this ); tokenizer.getFiles()->push_back( "test.cpp" ); std::istringstream istr(code); tokenizer.TokenizeCode( istr ); @@ -49,7 +49,7 @@ private: errout.str(""); // Check for memory leaks.. - CheckOther checkOther( &tokenizer ); + CheckOther checkOther( &tokenizer, this ); checkOther.CheckUnsignedDivision(); tokenizer.DeallocateTokens(); diff --git a/testincompletestatement.cpp b/testincompletestatement.cpp index d112bdfe4..b0e246833 100644 --- a/testincompletestatement.cpp +++ b/testincompletestatement.cpp @@ -38,7 +38,7 @@ private: void check( const char code[] ) { // Tokenize.. - Tokenizer tokenizer; + Tokenizer tokenizer( this ); tokenizer.getFiles()->push_back( "test.cpp" ); std::istringstream istr(code); tokenizer.TokenizeCode( istr ); @@ -48,7 +48,7 @@ private: errout.str(""); // Check for unused variables.. - CheckOther checkOther( &tokenizer ); + CheckOther checkOther( &tokenizer, this ); checkOther.CheckIncompleteStatement(); tokenizer.DeallocateTokens(); diff --git a/testmemleak.cpp b/testmemleak.cpp index e6ba5c8b0..f7efd5640 100644 --- a/testmemleak.cpp +++ b/testmemleak.cpp @@ -38,7 +38,7 @@ private: void check( const char code[] ) { // Tokenize.. - Tokenizer tokenizer; + Tokenizer tokenizer( this ); tokenizer.getFiles()->push_back( "test.cpp" ); std::istringstream istr(code); tokenizer.TokenizeCode( istr ); @@ -53,7 +53,7 @@ private: settings._showAll = false; tokenizer.settings( settings ); tokenizer.FillFunctionList(0); - CheckMemoryLeakClass checkMemoryLeak( &tokenizer, settings ); + CheckMemoryLeakClass checkMemoryLeak( &tokenizer, settings, this ); checkMemoryLeak.CheckMemoryLeak(); tokenizer.DeallocateTokens(); diff --git a/testpreprocessor.cpp b/testpreprocessor.cpp index 9edfb61af..27ae4ec4b 100644 --- a/testpreprocessor.cpp +++ b/testpreprocessor.cpp @@ -140,7 +140,7 @@ private: // Preprocess => actual result.. std::istringstream istr(filedata); std::map actual; - Preprocessor preprocessor; + Preprocessor preprocessor( this ); preprocessor.preprocess( istr, actual, "" ); // Compare results.. @@ -164,7 +164,7 @@ private: // Preprocess => actual result.. std::istringstream istr(filedata); std::map actual; - Preprocessor preprocessor; + Preprocessor preprocessor( this ); preprocessor.preprocess( istr, actual, "" ); // Compare results.. @@ -187,7 +187,7 @@ private: // Preprocess => actual result.. std::istringstream istr(filedata); std::map actual; - Preprocessor preprocessor; + Preprocessor preprocessor( this ); preprocessor.preprocess( istr, actual, "" ); // Compare results.. @@ -213,7 +213,7 @@ private: // Preprocess => actual result.. std::istringstream istr(filedata); std::map actual; - Preprocessor preprocessor; + Preprocessor preprocessor( this ); preprocessor.preprocess( istr, actual, "" ); // Compare results.. @@ -237,7 +237,7 @@ private: // Preprocess => actual result.. std::istringstream istr(filedata); std::map actual; - Preprocessor preprocessor; + Preprocessor preprocessor( this ); preprocessor.preprocess( istr, actual, "" ); // Compare results.. @@ -264,7 +264,7 @@ private: // Preprocess => actual result.. std::istringstream istr(filedata); std::map actual; - Preprocessor preprocessor; + Preprocessor preprocessor( this ); preprocessor.preprocess( istr, actual, "" ); // Compare results.. @@ -287,7 +287,7 @@ private: // Preprocess => actual result.. std::istringstream istr(filedata); std::map actual; - Preprocessor preprocessor; + Preprocessor preprocessor( this ); preprocessor.preprocess( istr, actual, "" ); // Compare results.. @@ -310,7 +310,7 @@ private: // Preprocess => actual result.. std::istringstream istr(filedata); std::map actual; - Preprocessor preprocessor; + Preprocessor preprocessor( this ); preprocessor.preprocess( istr, actual, "" ); // Compare results.. @@ -330,7 +330,7 @@ private: // Preprocess => actual result.. std::istringstream istr(filedata); std::map actual; - Preprocessor preprocessor; + Preprocessor preprocessor( this ); preprocessor.preprocess( istr, actual, "" ); // Compare results.. @@ -355,7 +355,7 @@ private: // Preprocess => actual result.. std::istringstream istr(filedata); std::map actual; - Preprocessor preprocessor; + Preprocessor preprocessor( this ); preprocessor.preprocess( istr, actual, "" ); // Compare results.. @@ -375,7 +375,7 @@ private: // Preprocess => actual result.. std::istringstream istr(filedata); std::map actual; - Preprocessor preprocessor; + Preprocessor preprocessor( this ); preprocessor.preprocess( istr, actual, "" ); // Compare results.. @@ -400,7 +400,7 @@ private: // Preprocess => actual result.. std::istringstream istr(filedata); std::map actual; - Preprocessor preprocessor; + Preprocessor preprocessor( this ); preprocessor.preprocess( istr, actual, "" ); // Compare results.. @@ -420,7 +420,7 @@ private: // Preprocess => actual result.. std::istringstream istr(filedata); std::map actual; - Preprocessor preprocessor; + Preprocessor preprocessor( this ); preprocessor.preprocess( istr, actual, "" ); // Compare results.. diff --git a/testrunner.cpp b/testrunner.cpp index 162df639c..2e026ecbc 100644 --- a/testrunner.cpp +++ b/testrunner.cpp @@ -15,8 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see #include diff --git a/testsimplifytokens.cpp b/testsimplifytokens.cpp index 76ca2f144..5dd9ed7a0 100644 --- a/testsimplifytokens.cpp +++ b/testsimplifytokens.cpp @@ -22,6 +22,8 @@ #include "tokenize.h" #include +extern std::ostringstream errout; + class TestSimplifyTokens : public TestFixture { public: @@ -37,10 +39,10 @@ private: TEST_CASE( sizeof1 ); } - static std::string tok(const char code[]) + std::string tok(const char code[]) { std::istringstream istr(code); - Tokenizer tokenizer; + Tokenizer tokenizer( this ); tokenizer.TokenizeCode( istr ); tokenizer.SimplifyTokenList(); diff --git a/testsuite.cpp b/testsuite.cpp index e5bd5204e..5868de6d0 100644 --- a/testsuite.cpp +++ b/testsuite.cpp @@ -25,7 +25,7 @@ #include #include - +std::ostringstream errout; /** * TestRegistry @@ -130,4 +130,13 @@ void TestFixture::runTests(const char cmd[]) } +void TestFixture::reportErr( const std::string &errmsg) +{ + errout << errmsg << std::endl; +} + +void TestFixture::reportErr( const TOKEN *token, const std::string &errmsg) +{ + reportErr( errmsg ); +} diff --git a/testsuite.h b/testsuite.h index 46e341591..0a10c8084 100644 --- a/testsuite.h +++ b/testsuite.h @@ -20,9 +20,11 @@ #include +#include "errorlogger.h" + +class TOKEN; - -class TestFixture +class TestFixture : public ErrorLogger { private: static std::ostringstream errmsg; @@ -37,7 +39,11 @@ protected: bool runTest(const char testname[]); void assertFail(const char *filename, int linenr); -public: +public: + void reportErr( const std::string &errmsg); + + void reportErr( const TOKEN *token, const std::string &errmsg); + TestFixture(const std::string &_name); virtual ~TestFixture() { } diff --git a/testtokenize.cpp b/testtokenize.cpp index 005368125..a3bba0698 100644 --- a/testtokenize.cpp +++ b/testtokenize.cpp @@ -24,7 +24,8 @@ #include "testsuite.h" #define UNIT_TESTING // Get access to "private" data in Tokenizer #include "tokenize.h" - + +extern std::ostringstream errout; class TestTokenizer : public TestFixture { public: @@ -62,7 +63,7 @@ private: " \"def\"\n"; // tokenize.. - Tokenizer tokenizer; + Tokenizer tokenizer( this ); tokenizer.getFiles()->push_back( "test.cpp" ); std::istringstream istr(filedata); tokenizer.TokenizeCode(istr, 0); @@ -88,7 +89,7 @@ private: std::string filedata(10000,'a'); // tokenize.. - Tokenizer tokenizer; + Tokenizer tokenizer( this ); tokenizer.getFiles()->push_back( "test.cpp" ); std::istringstream istr(filedata); tokenizer.TokenizeCode(istr, 0); @@ -112,7 +113,7 @@ private: "}\n"; // tokenize.. - Tokenizer tokenizer; + Tokenizer tokenizer( this ); tokenizer.getFiles()->push_back( "test.cpp" ); std::istringstream istr(filedata); tokenizer.TokenizeCode(istr, 0); @@ -145,7 +146,7 @@ private: "void b()\n" "{ }\n"; // tokenize.. - Tokenizer tokenizer; + Tokenizer tokenizer( this ); tokenizer.getFiles()->push_back( "test.cpp" ); std::istringstream istr(code); tokenizer.TokenizeCode(istr, 0); diff --git a/testunusedprivfunc.cpp b/testunusedprivfunc.cpp index 6c292c627..e62294b35 100644 --- a/testunusedprivfunc.cpp +++ b/testunusedprivfunc.cpp @@ -44,7 +44,7 @@ private: void check( const char code[] ) { // Tokenize.. - Tokenizer tokenizer; + Tokenizer tokenizer( this ); tokenizer.getFiles()->push_back( "test.cpp" ); std::istringstream istr(code); tokenizer.TokenizeCode( istr ); @@ -55,7 +55,7 @@ private: // Check for unused private functions.. Settings settings; settings._checkCodingStyle = true; - CheckClass checkClass( &tokenizer, settings ); + CheckClass checkClass( &tokenizer, settings, this ); checkClass.CheckUnusedPrivateFunctions(); tokenizer.DeallocateTokens(); diff --git a/testunusedvar.cpp b/testunusedvar.cpp index 011d2175a..5a7528055 100644 --- a/testunusedvar.cpp +++ b/testunusedvar.cpp @@ -25,7 +25,6 @@ #include "CheckOther.h" #include - extern std::ostringstream errout; class TestUnusedVar : public TestFixture @@ -38,7 +37,7 @@ private: void check( const char code[] ) { // Tokenize.. - Tokenizer tokenizer; + Tokenizer tokenizer( this ); tokenizer.getFiles()->push_back( "test.cpp" ); std::istringstream istr(code); tokenizer.TokenizeCode( istr ); @@ -48,7 +47,7 @@ private: errout.str(""); // Check for unused variables.. - CheckOther checkOther( &tokenizer ); + CheckOther checkOther( &tokenizer, this ); checkOther.CheckStructMemberUsage(); tokenizer.DeallocateTokens(); diff --git a/tokenize.cpp b/tokenize.cpp index ab1e0924d..ffeb0a710 100644 --- a/tokenize.cpp +++ b/tokenize.cpp @@ -19,7 +19,8 @@ //--------------------------------------------------------------------------- #include "tokenize.h" -#include "CommonCheck.h" // <- IsName +#include "CommonCheck.h" // <- IsName + //--------------------------------------------------------------------------- #include @@ -46,11 +47,12 @@ //--------------------------------------------------------------------------- -Tokenizer::Tokenizer() +Tokenizer::Tokenizer(ErrorLogger *errorLogger) { _tokens = 0; tokens_back = 0; - dsymlist = 0; + dsymlist = 0; + _errorLogger = errorLogger; } Tokenizer::~Tokenizer() @@ -1293,14 +1295,14 @@ void Tokenizer::CheckGlobalFunctionUsage(const std::vector &filenam std::ostringstream errmsg; errmsg << "[" << filenames[func->file_id()] << "]: " << "The function '" << func->name() << "' is never used."; - ReportErr( errmsg.str() ); + _errorLogger->reportErr( errmsg.str() ); } else if ( ! UsedOtherFile ) { std::ostringstream errmsg; errmsg << "[" << filenames[func->file_id()] << "]: " << "The linkage of the function '" << func->name() << "' can be local (static) instead of global"; - ReportErr( errmsg.str() ); + _errorLogger->reportErr( errmsg.str() ); } } diff --git a/tokenize.h b/tokenize.h index 1ecc86ce8..6216183f8 100644 --- a/tokenize.h +++ b/tokenize.h @@ -27,7 +27,8 @@ #include #include #include -#include "settings.h" +#include "settings.h" +#include "errorlogger.h" class TOKEN { @@ -62,7 +63,7 @@ public: class Tokenizer { public: - Tokenizer(); + Tokenizer(ErrorLogger *errorLogger); ~Tokenizer(); void Tokenize(std::istream &code, const char FileName[]); @@ -152,7 +153,8 @@ private: struct DefineSymbol * dsymlist; - TOKEN *_tokens; + TOKEN *_tokens; + ErrorLogger *_errorLogger; };