From 625b77ec332e24bf325c1a1112dda9dda9c2684d Mon Sep 17 00:00:00 2001 From: Nicolas Le Cam Date: Mon, 8 Dec 2008 23:06:19 +0000 Subject: [PATCH] Formatting: uniformize end of lines. --- CheckBufferOverrun.cpp | 8 +- CheckBufferOverrun.h | 2 +- CheckClass.cpp | 120 +++---- CheckClass.h | 24 +- CheckFunctionUsage.cpp | 12 +- CheckMemoryLeak.cpp | 484 ++++++++++++++-------------- CheckMemoryLeak.h | 46 +-- CheckOther.cpp | 316 +++++++++--------- CheckOther.h | 8 +- FileLister.cpp | 4 +- FileLister.h | 18 +- cppcheck.cpp | 714 ++++++++++++++++++++--------------------- cppcheck.h | 222 ++++++------- cppcheckexecutor.cpp | 90 +++--- cppcheckexecutor.h | 126 ++++---- errorlogger.h | 88 ++--- main.cpp | 20 +- preprocessor.cpp | 64 ++-- preprocessor.h | 42 +-- settings.cpp | 60 ++-- settings.h | 74 ++--- testbufferoverrun.cpp | 4 +- testconstructors.cpp | 102 +++--- testfunctionusage.cpp | 64 ++-- testmemleak.cpp | 166 +++++----- testpreprocessor.cpp | 50 +-- testrunner.cpp | 4 +- testsimplifytokens.cpp | 122 +++---- testsuite.cpp | 78 ++--- testsuite.h | 10 +- testtokenize.cpp | 250 +++++++-------- testunusedvar.cpp | 318 +++++++++--------- token.cpp | 198 ++++++------ token.h | 236 +++++++------- tokenize.cpp | 226 ++++++------- tokenize.h | 26 +- 36 files changed, 2198 insertions(+), 2198 deletions(-) diff --git a/CheckBufferOverrun.cpp b/CheckBufferOverrun.cpp index 9bf6e150e..db1e709e6 100644 --- a/CheckBufferOverrun.cpp +++ b/CheckBufferOverrun.cpp @@ -35,7 +35,7 @@ // _callStack used when parsing into subfunctions. -CheckBufferOverrunClass::CheckBufferOverrunClass( const Tokenizer *tokenizer, const Settings &settings, ErrorLogger *errorLogger ) +CheckBufferOverrunClass::CheckBufferOverrunClass( const Tokenizer *tokenizer, const Settings &settings, ErrorLogger *errorLogger ) : _settings(settings) { _tokenizer = tokenizer; @@ -216,10 +216,10 @@ void CheckBufferOverrunClass::CheckBufferOverrun_CheckScope( const TOKEN *tok, c { // Don't make recursive checking.. if (std::find(_callStack.begin(), _callStack.end(), tok) != _callStack.end()) - continue; + continue; - // Only perform this checking if showAll setting is enabled.. - if ( ! _settings._showAll ) + // Only perform this checking if showAll setting is enabled.. + if ( ! _settings._showAll ) continue; unsigned int parlevel = 0, par = 0; diff --git a/CheckBufferOverrun.h b/CheckBufferOverrun.h index 95948fd31..5ffd18c50 100644 --- a/CheckBufferOverrun.h +++ b/CheckBufferOverrun.h @@ -43,7 +43,7 @@ private: void CheckBufferOverrun_CheckScope( const TOKEN *tok, const char *varname[], const int size, const int total_size ); void ReportError(const TOKEN *tok, const char errmsg[]); - const Tokenizer *_tokenizer; + const Tokenizer *_tokenizer; const Settings _settings; ErrorLogger *_errorLogger; std::list _callStack; diff --git a/CheckClass.cpp b/CheckClass.cpp index fd7ef1133..b0a7d4327 100644 --- a/CheckClass.cpp +++ b/CheckClass.cpp @@ -111,27 +111,27 @@ struct CheckClass::VAR *CheckClass::ClassChecking_GetVarList(const TOKEN *tok1) const TOKEN * CheckClass::FindClassFunction( const TOKEN *tok, const char classname[], const char funcname[], int &indentlevel ) { - if ( indentlevel < 0 || tok == NULL ) - return NULL; + if ( indentlevel < 0 || tok == NULL ) + return NULL; - std::ostringstream classPattern; - classPattern << "class " << classname << " :|{"; + std::ostringstream classPattern; + classPattern << "class " << classname << " :|{"; - std::ostringstream internalPattern; - internalPattern << funcname << " ("; + std::ostringstream internalPattern; + internalPattern << funcname << " ("; - std::ostringstream externalPattern; - externalPattern << classname << " :: " << funcname << " ("; + std::ostringstream externalPattern; + externalPattern << classname << " :: " << funcname << " ("; for ( ;tok; tok = tok->next() ) { if ( indentlevel == 0 && TOKEN::Match(tok, classPattern.str().c_str()) ) - { - while ( tok && tok->str() != "{" ) - tok = tok->next(); - if ( tok ) - tok = tok->next(); - if ( ! tok ) + { + while ( tok && tok->str() != "{" ) + tok = tok->next(); + if ( tok ) + tok = tok->next(); + if ( ! tok ) break; indentlevel = 1; } @@ -403,12 +403,12 @@ void CheckClass::CheckConstructors() // Check that all member variables are initialized.. struct VAR *varlist = ClassChecking_GetVarList(tok1); + + // Check constructors + CheckConstructors( tok1, varlist, className[0] ); - // Check constructors - CheckConstructors( tok1, varlist, className[0] ); - - // Check assignment operators - CheckConstructors( tok1, varlist, "operator =" ); + // Check assignment operators + CheckConstructors( tok1, varlist, "operator =" ); // Delete the varlist.. while (varlist) @@ -421,43 +421,43 @@ void CheckClass::CheckConstructors() tok1 = TOKEN::findmatch( tok1->next(), pattern_class ); } } + +void CheckClass::CheckConstructors(const TOKEN *tok1, struct VAR *varlist, const char funcname[]) +{ + const char * const className = tok1->strAt(1); -void CheckClass::CheckConstructors(const TOKEN *tok1, struct VAR *varlist, const char funcname[]) -{ - const char * const className = tok1->strAt(1); + int indentlevel = 0; + const TOKEN *constructor_token = FindClassFunction( tok1, className, funcname, indentlevel ); + std::list callstack; + ClassChecking_VarList_Initialize(tok1, constructor_token, varlist, className, callstack); + while ( constructor_token ) + { + // Check if any variables are uninitialized + for (struct VAR *var = varlist; var; var = var->next) + { + if ( var->init ) + continue; - int indentlevel = 0; - const TOKEN *constructor_token = FindClassFunction( tok1, className, funcname, indentlevel ); - std::list callstack; - ClassChecking_VarList_Initialize(tok1, constructor_token, varlist, className, callstack); - while ( constructor_token ) - { - // Check if any variables are uninitialized - for (struct VAR *var = varlist; var; var = var->next) - { - if ( var->init ) - continue; + // Is it a static member variable? + std::ostringstream pattern; + pattern << className << "::" << var->name << "="; + if (TOKEN::findmatch(_tokenizer->tokens(), pattern.str().c_str())) + continue; - // Is it a static member variable? - std::ostringstream pattern; - pattern << className << "::" << var->name << "="; - if (TOKEN::findmatch(_tokenizer->tokens(), pattern.str().c_str())) - continue; + // It's non-static and it's not initialized => error + std::ostringstream ostr; + ostr << _tokenizer->fileLine(constructor_token); + ostr << " Uninitialized member variable '" << className << "::" << var->name << "'"; + _errorLogger->reportErr(ostr.str()); + } - // It's non-static and it's not initialized => error - std::ostringstream ostr; - ostr << _tokenizer->fileLine(constructor_token); - ostr << " Uninitialized member variable '" << className << "::" << var->name << "'"; - _errorLogger->reportErr(ostr.str()); - } + for ( struct VAR *var = varlist; var; var = var->next ) + var->init = false; - for ( struct VAR *var = varlist; var; var = var->next ) - var->init = false; - - constructor_token = FindClassFunction( constructor_token->next(), className, funcname, indentlevel ); - callstack.clear(); - ClassChecking_VarList_Initialize(tok1, constructor_token, varlist, className, callstack); - } + constructor_token = FindClassFunction( constructor_token->next(), className, funcname, indentlevel ); + callstack.clear(); + ClassChecking_VarList_Initialize(tok1, constructor_token, varlist, className, callstack); + } } @@ -692,8 +692,8 @@ void CheckClass::virtualDestructor() // Iterate through each base class... derived = derived->tokAt(3); while ( TOKEN::Match(derived, "%var%") ) - { - bool isPublic = TOKEN::Match(derived, "public"); + { + bool isPublic = TOKEN::Match(derived, "public"); // What kind of inheritance is it.. public|protected|private if ( TOKEN::Match( derived, "public|protected|private" ) ) @@ -702,15 +702,15 @@ void CheckClass::virtualDestructor() // Name of base class.. const char *baseName[2]; baseName[0] = derived->strAt(0); - baseName[1] = 0; + baseName[1] = 0; - // Update derived so it's ready for the next loop. - derived = derived->next(); - if ( TOKEN::Match(derived, ",") ) - derived = derived->next(); + // Update derived so it's ready for the next loop. + derived = derived->next(); + if ( TOKEN::Match(derived, ",") ) + derived = derived->next(); - // If not public inheritance, skip checking of this base class.. - if ( ! isPublic ) + // If not public inheritance, skip checking of this base class.. + if ( ! isPublic ) continue; // Find the destructor declaration for the base class. diff --git a/CheckClass.h b/CheckClass.h index 730a7aead..53230a837 100644 --- a/CheckClass.h +++ b/CheckClass.h @@ -38,25 +38,25 @@ public: void CheckMemset(); void CheckOperatorEq1(); // Warning upon "void operator=(.." - - // The destructor in a base class should be virtual - void virtualDestructor(); + + // The destructor in a base class should be virtual + void virtualDestructor(); private: - struct VAR - { - const char *name; - bool init; - struct VAR *next; - }; + struct VAR + { + const char *name; + bool init; + struct VAR *next; + }; void ClassChecking_VarList_Initialize(const TOKEN *tok1, const TOKEN *ftok, struct VAR *varlist, const char classname[], std::list &callstack); void InitVar(struct VAR *varlist, const char varname[]); const TOKEN *FindClassFunction( const TOKEN *tok, const char classname[], const char funcname[], int &indentlevel ); struct VAR *ClassChecking_GetVarList(const TOKEN *tok1); - - // Check constructors for a specified class - void CheckConstructors(const TOKEN *tok1, struct VAR *varlist, const char funcname[]); + + // Check constructors for a specified class + void CheckConstructors(const TOKEN *tok1, struct VAR *varlist, const char funcname[]); const Tokenizer *_tokenizer; Settings _settings; diff --git a/CheckFunctionUsage.cpp b/CheckFunctionUsage.cpp index 549bee59b..59bb3fbd4 100644 --- a/CheckFunctionUsage.cpp +++ b/CheckFunctionUsage.cpp @@ -95,9 +95,9 @@ void CheckFunctionUsage::parseTokens( const Tokenizer &tokenizer ) TOKEN::Match(tok, ":: %var% (") || TOKEN::Match(tok, "|= %var% (") || TOKEN::Match(tok, "&= %var% (") || - TOKEN::Match(tok, "&& %var% (") || - TOKEN::Match(tok, "|| %var% (") || - TOKEN::Match(tok, "else %var% (") || + TOKEN::Match(tok, "&& %var% (") || + TOKEN::Match(tok, "|| %var% (") || + TOKEN::Match(tok, "else %var% (") || TOKEN::Match(tok, "return %var% (") ) funcname = tok->next(); @@ -146,9 +146,9 @@ void CheckFunctionUsage::check() continue; if ( ! func.usedSameFile ) { - std::ostringstream errmsg; - if ( func.filename != "+" ) - errmsg << "[" << func.filename << "] "; + std::ostringstream errmsg; + if ( func.filename != "+" ) + errmsg << "[" << func.filename << "] "; errmsg << "The function '" << it->first << "' is never used."; _errorLogger->reportErr( errmsg.str() ); } diff --git a/CheckMemoryLeak.cpp b/CheckMemoryLeak.cpp index 0104ba8d0..a57ef4e1e 100644 --- a/CheckMemoryLeak.cpp +++ b/CheckMemoryLeak.cpp @@ -22,7 +22,7 @@ #include // free #include - + #include #include @@ -38,7 +38,7 @@ //--------------------------------------------------------------------------- -CheckMemoryLeakClass::CheckMemoryLeakClass( const Tokenizer *tokenizer, const Settings &settings, ErrorLogger *errorLogger ) +CheckMemoryLeakClass::CheckMemoryLeakClass( const Tokenizer *tokenizer, const Settings &settings, ErrorLogger *errorLogger ) : _settings(settings) { _tokenizer = tokenizer; @@ -51,7 +51,7 @@ CheckMemoryLeakClass::~CheckMemoryLeakClass() } bool CheckMemoryLeakClass::isclass( const TOKEN *tok ) -{ +{ if ( tok->isStandardType() ) return false; @@ -135,32 +135,32 @@ CheckMemoryLeakClass::AllocType CheckMemoryLeakClass::GetAllocationType( const T return No; } + +CheckMemoryLeakClass::AllocType CheckMemoryLeakClass::GetReallocationType( const TOKEN *tok2 ) +{ + // What we may have... + // * var = (char *)realloc(..; + if ( tok2 && tok2->str() == "(" ) + { + while ( tok2 && tok2->str() != ")" ) + tok2 = tok2->next(); + tok2 = tok2 ? tok2->next() : NULL; + } + if ( ! tok2 ) + return No; -CheckMemoryLeakClass::AllocType CheckMemoryLeakClass::GetReallocationType( const TOKEN *tok2 ) -{ - // What we may have... - // * var = (char *)realloc(..; - if ( tok2 && tok2->str() == "(" ) - { - while ( tok2 && tok2->str() != ")" ) - tok2 = tok2->next(); - tok2 = tok2 ? tok2->next() : NULL; - } - if ( ! tok2 ) - return No; + if ( TOKEN::Match(tok2, "realloc") ) + return Malloc; - if ( TOKEN::Match(tok2, "realloc") ) - return Malloc; - - // GTK memory reallocation.. - if ( TOKEN::Match(tok2, "g_realloc|g_try_realloc|g_renew|g_try_renew") ) - return gMalloc; - - return No; -} + // GTK memory reallocation.. + if ( TOKEN::Match(tok2, "g_realloc|g_try_realloc|g_renew|g_try_renew") ) + return gMalloc; + return No; +} + CheckMemoryLeakClass::AllocType CheckMemoryLeakClass::GetDeallocationType( const TOKEN *tok, const char *varnames[] ) { if ( TOKEN::Match(tok, "delete %var1% ;", varnames) ) @@ -234,29 +234,29 @@ const char * CheckMemoryLeakClass::call_func( const TOKEN *tok, std::liststr() != "{") ) ftok = ftok->next(); TOKEN *func = getcode( ftok->tokAt(1), callstack, parname, alloctype, dealloctype ); - simplifycode( func ); - const TOKEN *func_ = func; - while ( func_ && func_->str() == ";" ) - func_ = func_->next(); - /* - for (const TOKEN *t = func; t; t = t->next()) - { - std::cout << t->str() << "\n"; - }*/ + simplifycode( func ); + const TOKEN *func_ = func; + while ( func_ && func_->str() == ";" ) + func_ = func_->next(); + /* + for (const TOKEN *t = func; t; t = t->next()) + { + std::cout << t->str() << "\n"; + }*/ const char *ret = 0; - if (TOKEN::findmatch(func_, "goto")) - { - // TODO : "goto" isn't handled well - if ( TOKEN::findmatch(func_, "dealloc") ) - ret = "dealloc"; + if (TOKEN::findmatch(func_, "goto")) + { + // TODO : "goto" isn't handled well + if ( TOKEN::findmatch(func_, "dealloc") ) + ret = "dealloc"; else if ( TOKEN::findmatch(func_, "use") ) - ret = "use"; + ret = "use"; } - else if ( TOKEN::findmatch(func_, "dealloc") ) - ret = "dealloc"; - else if ( TOKEN::findmatch(func_, "use") ) - ret = "use"; + else if ( TOKEN::findmatch(func_, "dealloc") ) + ret = "dealloc"; + else if ( TOKEN::findmatch(func_, "use") ) + ret = "use"; Tokenizer::deleteTokens(func); return ret; @@ -325,10 +325,10 @@ TOKEN *CheckMemoryLeakClass::getcode(const TOKEN *tok, std::list rethead = newtok; \ rettail=newtok; \ } + - - // The first token should be ";" - addtoken(";"); + // The first token should be ";" + addtoken(";"); bool isloop = false; @@ -361,24 +361,24 @@ TOKEN *CheckMemoryLeakClass::getcode(const TOKEN *tok, std::list if (TOKEN::Match(tok, "[(;{}] %var1% =", varnames)) { - AllocType alloc = GetAllocationType(tok->tokAt(3)); + AllocType alloc = GetAllocationType(tok->tokAt(3)); - if ( alloc == No ) - { - alloc = GetReallocationType( tok->tokAt(3) ); - if ( alloc != No ) - { - addtoken( "dealloc" ); - addtoken( ";" ); - } + if ( alloc == No ) + { + alloc = GetReallocationType( tok->tokAt(3) ); + if ( alloc != No ) + { + addtoken( "dealloc" ); + addtoken( ";" ); + } } // If "--all" hasn't been given, don't check classes.. if ( alloc == New && ! _settings._showAll ) { if ( TOKEN::Match(tok->tokAt(3), "new %type% [(;]") ) - { - if ( isclass( tok->tokAt(4) ) ) + { + if ( isclass( tok->tokAt(4) ) ) alloc = No; } } @@ -391,12 +391,12 @@ TOKEN *CheckMemoryLeakClass::getcode(const TOKEN *tok, std::list if (dealloctype!=No && dealloctype!=alloc) MismatchError(tok, callstack, varname); alloctype = alloc; - } + } - // assignment.. - else - { - addtoken( "assign" ); + // assignment.. + else + { + addtoken( "assign" ); } } @@ -416,10 +416,10 @@ TOKEN *CheckMemoryLeakClass::getcode(const TOKEN *tok, std::list TOKEN::Match(tok, "if ( %var1% != 0 )", varnames) || TOKEN::Match(tok, "if ( 0 != %var1% )", varnames) ) { - addtoken("if(var)"); + addtoken("if(var)"); - // Make sure the "use" will not be added - while ( tok->str() != ")" ) + // Make sure the "use" will not be added + while ( tok->str() != ")" ) tok = tok->next(); } else if ( TOKEN::Match(tok, "if (") && notvar(tok->tokAt(2), varnames) ) @@ -514,10 +514,10 @@ TOKEN *CheckMemoryLeakClass::getcode(const TOKEN *tok, std::list if ( tok->str() == "throw" ) addtoken("throw"); - // Assignment.. - if ( TOKEN::Match(tok,"[)=] %var1% [;)]", varnames) || - TOKEN::Match(tok, "%var1% +=|-=", varnames) ) - addtoken("use"); + // Assignment.. + if ( TOKEN::Match(tok,"[)=] %var1% [;)]", varnames) || + TOKEN::Match(tok, "%var1% +=|-=", varnames) ) + addtoken("use"); // Investigate function calls.. if ( TOKEN::Match(tok, "%var% (") ) @@ -525,21 +525,21 @@ TOKEN *CheckMemoryLeakClass::getcode(const TOKEN *tok, std::list const char *str = call_func(tok, callstack, varnames, alloctype, dealloctype); if ( str ) addtoken( str ); - } + } - // Callback.. - if ( TOKEN::Match(tok, "( * %var% ) (") ) - { - for ( const TOKEN *tok2 = tok->tokAt(5); tok2; tok2 = tok2->next() ) - { - if ( TOKEN::Match(tok2, ";{") ) - break; - else if ( tok2->str() == varname ) - { - addtoken("use"); - break; - } - } + // Callback.. + if ( TOKEN::Match(tok, "( * %var% ) (") ) + { + for ( const TOKEN *tok2 = tok->tokAt(5); tok2; tok2 = tok2->next() ) + { + if ( TOKEN::Match(tok2, ";{") ) + break; + else if ( tok2->str() == varname ) + { + addtoken("use"); + break; + } + } } // Linux lists.. @@ -605,80 +605,80 @@ void CheckMemoryLeakClass::simplifycode(TOKEN *tok) done = false; } - // Delete empty if that is not followed by an else - if (tok2->tokAt(2) && - (tok2->next()->str().find("if") == 0) && - TOKEN::Match(tok2->tokAt(2), ";") && - !TOKEN::Match(tok2->tokAt(3), "else")) - { + // Delete empty if that is not followed by an else + if (tok2->tokAt(2) && + (tok2->next()->str().find("if") == 0) && + TOKEN::Match(tok2->tokAt(2), ";") && + !TOKEN::Match(tok2->tokAt(3), "else")) + { erase(tok2, tok2->tokAt(2)); done = false; } + + // Delete "if ; else ;" + if ( TOKEN::Match(tok2->next(), "if ; else ;") ) + { + erase( tok2, tok2->tokAt(4) ); + done = false; + } - // Delete "if ; else ;" - if ( TOKEN::Match(tok2->next(), "if ; else ;") ) - { - erase( tok2, tok2->tokAt(4) ); - done = false; - } - - // TODO Make this more generic. Delete "if ; else use ; use" - if ( TOKEN::Match(tok2, "; if ; else use ; use") || - TOKEN::Match(tok2, "; if use ; else ; use") ) - { - erase( tok2, tok2->tokAt(4) ); - done = false; - } + // TODO Make this more generic. Delete "if ; else use ; use" + if ( TOKEN::Match(tok2, "; if ; else use ; use") || + TOKEN::Match(tok2, "; if use ; else ; use") ) + { + erase( tok2, tok2->tokAt(4) ); + done = false; + } // Reduce "if dealloc ;" and "if use ;" that is not followed by an else.. - // If "--all" has been given these are deleted + // If "--all" has been given these are deleted // Otherwise, ony the "if" will be deleted if ((TOKEN::Match(tok2, "[;{}] if dealloc ;") || TOKEN::Match(tok2, "[;{}] if use ;")) && !TOKEN::Match(tok2->tokAt(4), "else")) - { - if ( _settings._showAll ) + { + if ( _settings._showAll ) erase(tok2, tok2->tokAt(3)); - else - erase( tok2, tok2->tokAt(2) ); - done = false; + else + erase( tok2, tok2->tokAt(2) ); + done = false; } // Reduce "if(var) dealloc ;" and "if(var) use ;" that is not followed by an else.. if ((TOKEN::Match(tok2, "[;{}] if(var) dealloc ;") || TOKEN::Match(tok2, "[;{}] if(var) use ;")) && !TOKEN::Match(tok2->tokAt(4), "else")) - { + { erase(tok2, tok2->tokAt(2)); - done = false; + done = false; + } + + // Reduce "if if" => "if" + if ( TOKEN::Match(tok2, "if if") ) + { + erase(tok2, tok2->tokAt(2)); + done = false; } - // Reduce "if if" => "if" - if ( TOKEN::Match(tok2, "if if") ) - { - erase(tok2, tok2->tokAt(2)); - done = false; - } - - // Reduce "else ;" => ";" - if ( TOKEN::Match(tok2->next(), "else ;") ) - { - erase(tok2, tok2->tokAt(2)); - done = false; - } + // Reduce "else ;" => ";" + if ( TOKEN::Match(tok2->next(), "else ;") ) + { + erase(tok2, tok2->tokAt(2)); + done = false; + } // Delete if block: "alloc; if return use ;" if (TOKEN::Match(tok2,"alloc ; if return use ;") && !TOKEN::Match(tok2->tokAt(6),"else")) { erase(tok2, tok2->tokAt(5)); done = false; - } + } + - // Reduce "if return ; alloc ;" => "alloc ;" if (TOKEN::Match(tok2, "[;{}] if return ; alloc ;")) { erase(tok2, tok2->tokAt(4)); done = false; - } + } // "[;{}] if alloc ; else return ;" => "[;{}] alloc ;" if (TOKEN::Match(tok2,"[;{}] if alloc ; else return ;")) @@ -705,55 +705,55 @@ void CheckMemoryLeakClass::simplifycode(TOKEN *tok) { erase(tok2,tok2->tokAt(8)); done = false; - } - - // Reduce "if ; else %var% ;" => "if %var% ;" - if ( TOKEN::Match(tok2, "if ; else %var% ;") ) - { - erase( tok2, tok2->tokAt(3) ); - done = false; } - // Reduce "if ; else return use ;" => "if return use ;" - if ( TOKEN::Match(tok2, "if ; else %var% ;") ) - { - erase( tok2, tok2->tokAt(3) ); - done = false; + // Reduce "if ; else %var% ;" => "if %var% ;" + if ( TOKEN::Match(tok2, "if ; else %var% ;") ) + { + erase( tok2, tok2->tokAt(3) ); + done = false; } - - // Reduce "do { alloc ; } " => "alloc ;" - if ( TOKEN::Match(tok2->next(), "do { alloc ; }") ) - { - erase(tok2, tok2->tokAt(3)); - erase(tok2->next()->next(), tok2->tokAt(4)); - done = false; - } - // Reduce "loop if break ; => ";" - if ( TOKEN::Match( tok2->next(), "loop %var%" ) && - tok2->tokAt(2)->str().find("if") == 0 && - (TOKEN::Match( tok2->tokAt(3), "break ; ") || TOKEN::Match( tok2->tokAt(3), "continue ;")) && - !TOKEN::Match(tok2->tokAt(5),"else") ) - { - erase( tok2, tok2->tokAt(4) ); - done = false; - } + // Reduce "if ; else return use ;" => "if return use ;" + if ( TOKEN::Match(tok2, "if ; else %var% ;") ) + { + erase( tok2, tok2->tokAt(3) ); + done = false; + } + + // Reduce "do { alloc ; } " => "alloc ;" + if ( TOKEN::Match(tok2->next(), "do { alloc ; }") ) + { + erase(tok2, tok2->tokAt(3)); + erase(tok2->next()->next(), tok2->tokAt(4)); + done = false; + } + + // Reduce "loop if break ; => ";" + if ( TOKEN::Match( tok2->next(), "loop %var%" ) && + tok2->tokAt(2)->str().find("if") == 0 && + (TOKEN::Match( tok2->tokAt(3), "break ; ") || TOKEN::Match( tok2->tokAt(3), "continue ;")) && + !TOKEN::Match(tok2->tokAt(5),"else") ) + { + erase( tok2, tok2->tokAt(4) ); + done = false; + } - // Reduce "if(true) X ;" => "X ;" - if (TOKEN::Match(tok2->next(), "if(true) %var% ;") && !TOKEN::Match(tok2->tokAt(4),"else")) - { - erase( tok2, tok2->tokAt(2) ); - done = false; - } + // Reduce "if(true) X ;" => "X ;" + if (TOKEN::Match(tok2->next(), "if(true) %var% ;") && !TOKEN::Match(tok2->tokAt(4),"else")) + { + erase( tok2, tok2->tokAt(2) ); + done = false; + } // Replace "loop { X ; break ; }" with "X ;" if ( TOKEN::Match(tok2->next(), "loop { %var% ; break ; }") ) { - erase(tok2, tok2->tokAt(3)); + erase(tok2, tok2->tokAt(3)); erase(tok2->next()->next(), tok2->tokAt(6)); done = false; } - + // Replace "loop ;" with ";" if ( TOKEN::Match(tok2->next(), "loop ;") ) { @@ -780,7 +780,7 @@ void CheckMemoryLeakClass::simplifycode(TOKEN *tok) { erase(tok2, tok2->tokAt(4)); done = false; - } + } // Delete if block: "alloc; if return use ;" if (TOKEN::Match(tok2,"alloc ; if return use ;") && !TOKEN::Match(tok2->tokAt(6),"else")) @@ -788,56 +788,56 @@ void CheckMemoryLeakClass::simplifycode(TOKEN *tok) erase(tok2, tok2->tokAt(5)); done = false; } - - // Reduce "if return ; if return ;" => "if return ;" - if ( TOKEN::Match(tok2->next(), "if return ; if return ;") ) - { - erase( tok2, tok2->tokAt(4) ); - done = false; - } - - // Reduce "[;{}] return ; %var%" => "[;{}] return ;" - if ( TOKEN::Match(tok2, "[;{}] return ; %var%") ) - { - erase( tok2->next()->next(), tok2->tokAt(4) ); - done = false; - } - - // Reduce "[;{}] return use ; %var%" => "[;{}] return use ;" - if ( TOKEN::Match(tok2, "[;{}] return use ; %var%") ) - { - erase( tok2->next()->next()->next(), tok2->tokAt(5) ); - done = false; - } - - // Reduce "if(var) return use ;" => "return use ;" - if ( TOKEN::Match(tok2->next(), "if(var) return use ;") && !TOKEN::Match(tok2->tokAt(5),"else")) - { - erase( tok2, tok2->tokAt(2) ); - done = false; + + // Reduce "if return ; if return ;" => "if return ;" + if ( TOKEN::Match(tok2->next(), "if return ; if return ;") ) + { + erase( tok2, tok2->tokAt(4) ); + done = false; } - // Reduce "if(var) use ;" => "use ;" - if ( TOKEN::Match(tok2->next(), "if(var) use ;") && !TOKEN::Match(tok2->tokAt(4),"else")) - { - erase( tok2, tok2->tokAt(2) ); - done = false; - } + // Reduce "[;{}] return ; %var%" => "[;{}] return ;" + if ( TOKEN::Match(tok2, "[;{}] return ; %var%") ) + { + erase( tok2->next()->next(), tok2->tokAt(4) ); + done = false; + } - // Reduce "[;{}] alloc ; dealloc ;" => "[;{}]" - if ( TOKEN::Match(tok2, "[;{}] alloc ; dealloc ;") ) - { - erase( tok2, tok2->tokAt(5) ); - done = false; - } + // Reduce "[;{}] return use ; %var%" => "[;{}] return use ;" + if ( TOKEN::Match(tok2, "[;{}] return use ; %var%") ) + { + erase( tok2->next()->next()->next(), tok2->tokAt(5) ); + done = false; + } - // Reduce "if* alloc ; dealloc ;" => ";" - if ( TOKEN::Match(tok2->tokAt(2), "alloc ; dealloc ;") && - tok2->next()->str().find("if") == 0 ) - { - erase( tok2, tok2->tokAt(5) ); - done = false; - } + // Reduce "if(var) return use ;" => "return use ;" + if ( TOKEN::Match(tok2->next(), "if(var) return use ;") && !TOKEN::Match(tok2->tokAt(5),"else")) + { + erase( tok2, tok2->tokAt(2) ); + done = false; + } + + // Reduce "if(var) use ;" => "use ;" + if ( TOKEN::Match(tok2->next(), "if(var) use ;") && !TOKEN::Match(tok2->tokAt(4),"else")) + { + erase( tok2, tok2->tokAt(2) ); + done = false; + } + + // Reduce "[;{}] alloc ; dealloc ;" => "[;{}]" + if ( TOKEN::Match(tok2, "[;{}] alloc ; dealloc ;") ) + { + erase( tok2, tok2->tokAt(5) ); + done = false; + } + + // Reduce "if* alloc ; dealloc ;" => ";" + if ( TOKEN::Match(tok2->tokAt(2), "alloc ; dealloc ;") && + tok2->next()->str().find("if") == 0 ) + { + erase( tok2, tok2->tokAt(5) ); + done = false; + } // Delete second use in "use ; use ;" while (TOKEN::Match(tok2, "[;{}] use ; use ;")) @@ -851,7 +851,7 @@ void CheckMemoryLeakClass::simplifycode(TOKEN *tok) { erase(tok2, tok2->tokAt(3)); done = false; - } + } // Delete first use in "use ; return use ;" if (TOKEN::Match(tok2, "[;{}] use ; return use ;")) @@ -981,8 +981,8 @@ void CheckMemoryLeakClass::CheckMemoryLeak_CheckScope( const TOKEN *Tok1, const else if ( (result = TOKEN::findmatch(tok, "alloc ; if break|continue|return ;")) != NULL ) { - // MemoryLeak(Tokenizer::gettok(TOKEN::findmatch(tok, "alloc ; if continue ;"), 3), varname); - MemoryLeak(result->tokAt(3), varname); + // MemoryLeak(Tokenizer::gettok(TOKEN::findmatch(tok, "alloc ; if continue ;"), 3), varname); + MemoryLeak(result->tokAt(3), varname); } else if ( _settings._showAll && (result = TOKEN::findmatch(tok, "alloc ; ifv break|continue|return ;")) != NULL ) @@ -1004,35 +1004,35 @@ void CheckMemoryLeakClass::CheckMemoryLeak_CheckScope( const TOKEN *Tok1, const last = last->next(); MemoryLeak(last, varname); } + + // detect cases that "simplifycode" don't handle well.. + else if ( _settings._debug ) + { + TOKEN *first = tok; + while ( first && first->str() == ";" ) + first = first->next(); - // detect cases that "simplifycode" don't handle well.. - else if ( _settings._debug ) - { - TOKEN *first = tok; - while ( first && first->str() == ";" ) - first = first->next(); + bool noerr = false; + noerr |= TOKEN::Match( first, "alloc ; }" ); + noerr |= TOKEN::Match( first, "alloc ; dealloc ; }" ); + noerr |= TOKEN::Match( first, "alloc ; return use ; }" ); + noerr |= TOKEN::Match( first, "alloc ; use ; }" ); + noerr |= TOKEN::Match( first, "alloc ; use ; return ; }" ); + noerr |= TOKEN::Match( first, "if alloc ; dealloc ; }" ); + noerr |= TOKEN::Match( first, "if alloc ; return use ; }" ); + noerr |= TOKEN::Match( first, "if alloc ; use ; }" ); + noerr |= TOKEN::Match( first, "alloc ; ifv return ; dealloc ; }" ); + noerr |= TOKEN::Match( first, "alloc ; if return ; dealloc; }" ); - bool noerr = false; - noerr |= TOKEN::Match( first, "alloc ; }" ); - noerr |= TOKEN::Match( first, "alloc ; dealloc ; }" ); - noerr |= TOKEN::Match( first, "alloc ; return use ; }" ); - noerr |= TOKEN::Match( first, "alloc ; use ; }" ); - noerr |= TOKEN::Match( first, "alloc ; use ; return ; }" ); - noerr |= TOKEN::Match( first, "if alloc ; dealloc ; }" ); - noerr |= TOKEN::Match( first, "if alloc ; return use ; }" ); - noerr |= TOKEN::Match( first, "if alloc ; use ; }" ); - noerr |= TOKEN::Match( first, "alloc ; ifv return ; dealloc ; }" ); - noerr |= TOKEN::Match( first, "alloc ; if return ; dealloc; }" ); - - // Unhandled case.. - if ( ! noerr ) - { - std::cout << "Token listing..\n "; - for ( const TOKEN *tok2 = tok; tok2; tok2 = tok2->next() ) - std::cout << " " << tok2->str(); - std::cout << "\n"; - } - } + // Unhandled case.. + if ( ! noerr ) + { + std::cout << "Token listing..\n "; + for ( const TOKEN *tok2 = tok; tok2; tok2 = tok2->next() ) + std::cout << " " << tok2->str(); + std::cout << "\n"; + } + } Tokenizer::deleteTokens(tok); } @@ -1261,7 +1261,7 @@ void CheckMemoryLeakClass::CheckMemoryLeak() // Check for memory leaks inside functions.. CheckMemoryLeak_InFunction(); - // Check that all class members are deallocated.. + // Check that all class members are deallocated.. if ( _settings._showAll ) CheckMemoryLeak_ClassMembers(); } diff --git a/CheckMemoryLeak.h b/CheckMemoryLeak.h index fdcb425c8..93da56dae 100644 --- a/CheckMemoryLeak.h +++ b/CheckMemoryLeak.h @@ -61,31 +61,31 @@ private: void CheckMemoryLeak_ClassMembers(); void CheckMemoryLeak_InFunction(); void CheckMemoryLeak_CheckScope( const TOKEN *Tok1, const char varname[] ); + + /** + * Simplify code e.g. by replacing empty "{ }" with ";" + * @param tok first token. The tokens list can be modified. + */ + void simplifycode(TOKEN *tok); - /** - * Simplify code e.g. by replacing empty "{ }" with ";" - * @param tok first token. The tokens list can be modified. - */ - void simplifycode(TOKEN *tok); - - /** - * Delete tokens between begin and end. E.g. if begin = 1 - * and end = 5, tokens 2,3 and 4 would be erased. - * - * @param begin Tokens after this will be erased. - * @param end Tokens before this will be erased. + /** + * Delete tokens between begin and end. E.g. if begin = 1 + * and end = 5, tokens 2,3 and 4 would be erased. + * + * @param begin Tokens after this will be erased. + * @param end Tokens before this will be erased. */ void erase(TOKEN *begin, const TOKEN *end); - - /** - * Extract a new tokens list that is easier to parse than the "tokens" - * @param tok start parse token - * @param callstack callstack - * @param varname name of variable - * @param alloctype - * @param dealloctype - * @return Newly allocated token array. Caller needs to release reserved - * memory by calling Tokenizer::deleteTokens(returnValue); + + /** + * Extract a new tokens list that is easier to parse than the "tokens" + * @param tok start parse token + * @param callstack callstack + * @param varname name of variable + * @param alloctype + * @param dealloctype + * @return Newly allocated token array. Caller needs to release reserved + * memory by calling Tokenizer::deleteTokens(returnValue); */ TOKEN *getcode(const TOKEN *tok, std::list callstack, const char varname[], AllocType &alloctype, AllocType &dealloctype); bool notvar(const TOKEN *tok, const char *varnames[]); @@ -95,7 +95,7 @@ private: const char * call_func( const TOKEN *tok, std::list callstack, const char *varnames[], AllocType &alloctype, AllocType &dealloctype ); AllocType GetDeallocationType( const TOKEN *tok, const char *varnames[]); AllocType GetAllocationType( const TOKEN *tok2 ); - AllocType GetReallocationType( const TOKEN *tok2 ); + AllocType GetReallocationType( const TOKEN *tok2 ); bool isclass( const TOKEN *typestr ); const Tokenizer *_tokenizer; diff --git a/CheckOther.cpp b/CheckOther.cpp index f80fc4259..9b72d9273 100644 --- a/CheckOther.cpp +++ b/CheckOther.cpp @@ -283,13 +283,13 @@ void CheckOther::WarningIf() // Check that there is a condition.. const char *p[6] = {"==","<=",">=","!=","<",">"}; bool iscond = false; - for (int i = 0; i < 6; i++) + for (int i = 0; i < 6; i++) { - if (strcmp(cond, p[i]) == 0) - { + if (strcmp(cond, p[i]) == 0) + { iscond = true; - break; - } + break; + } } if (!iscond) break; @@ -783,157 +783,157 @@ void CheckOther::CheckIncompleteStatement() _errorLogger->reportErr(errmsg.str()); } } -} -//--------------------------------------------------------------------------- - - - - - - -//--------------------------------------------------------------------------- -// Unreachable code below a 'return' -//--------------------------------------------------------------------------- - -void CheckOther::unreachableCode() -{ - const TOKEN *tok = TOKEN::findmatch( _tokenizer->tokens(), "[;{}] return" ); - while ( tok ) - { - // Goto the 'return' token - tok = tok->next(); - - // Locate the end of the 'return' statement - while ( tok && ! TOKEN::Match(tok, ";") ) - tok = tok->next(); - while ( tok && TOKEN::Match(tok->next(), ";") ) - tok = tok->next(); - - // If there is a statement below the return it is unreachable - if (!TOKEN::Match(tok, "; case|default|}|#") && !TOKEN::Match(tok, "; %var% :")) - { - std::ostringstream errmsg; - errmsg << _tokenizer->fileLine(tok->next()) << ": Unreachable code below a 'return'"; - _errorLogger->reportErr(errmsg.str()); - } - - // Find the next 'return' statement - tok = TOKEN::findmatch( tok, "[;{}] return" ); - } -} -//--------------------------------------------------------------------------- - - - - - - -//--------------------------------------------------------------------------- -// Usage of function variables -//--------------------------------------------------------------------------- - -static bool isOp(const TOKEN *tok) -{ - return bool(tok && - (tok->str() == "&&" || - tok->str() == "||" || - tok->str() == "==" || - tok->str() == "!=" || - tok->str() == "<" || - tok->str() == "<=" || - tok->str() == ">" || - tok->str() == ">=" || - tok->str() == "<<" || - TOKEN::Match(tok, "[+-*/&|,]"))); -} - -void CheckOther::functionVariableUsage() -{ - // Parse all executing scopes.. - const TOKEN *tok1 = TOKEN::findmatch( _tokenizer->tokens(), ") const| {" ); - while ( tok1 ) - { - // Varname, usage {1=declare, 2=read, 4=write} - std::map varUsage; - static const unsigned int USAGE_DECLARE = 1; - static const unsigned int USAGE_READ = 2; - static const unsigned int USAGE_WRITE = 4; - - int indentlevel = 0; - for ( const TOKEN *tok = tok1; tok; tok = tok->next() ) - { - if ( tok->str() == "{" ) - ++indentlevel; - else if ( tok->str() == "}" ) - { - --indentlevel; - if ( indentlevel <= 0 ) - break; - } - - if ( TOKEN::Match(tok, "[;{}] bool|char|short|int|long|float|double %var% ;|=") ) - varUsage[ tok->strAt(2) ] = USAGE_DECLARE; - - if ( TOKEN::Match(tok, "[;{}] bool|char|short|int|long|float|double * %var% ;|=") ) - varUsage[ tok->strAt(3) ] = USAGE_DECLARE; - - if ( TOKEN::Match(tok, "delete|return %var%") ) - varUsage[ tok->strAt(1) ] |= USAGE_READ; - - if ( TOKEN::Match(tok, "%var% =") ) - varUsage[ tok->str() ] |= USAGE_WRITE; - - if ( TOKEN::Match(tok, "else %var% =") ) - varUsage[ tok->strAt(1) ] |= USAGE_WRITE; - - if ( TOKEN::Match(tok, ">>|& %var%") ) - varUsage[ tok->strAt(1) ] |= USAGE_WRITE; - - if ((TOKEN::Match(tok,"[(=&!]") || isOp(tok)) && TOKEN::Match(tok->next(), "%var%")) - varUsage[ tok->strAt(1) ] |= USAGE_READ; - - if (TOKEN::Match(tok, "%var%") && (tok->next()->str()==")" || isOp(tok->next()))) - varUsage[ tok->str() ] |= USAGE_READ; - - if ( TOKEN::Match(tok, "[(,] %var% [,)]") ) - varUsage[ tok->strAt(1) ] |= USAGE_WRITE; - } - - // Check usage of all variables in the current scope.. - for ( std::map::const_iterator it = varUsage.begin(); it != varUsage.end(); ++it ) - { - std::string varname = it->first; - unsigned int usage = it->second; - - if (!isalpha(varname[0])) - continue; - - if ( ! ( usage & USAGE_DECLARE ) ) - continue; - - if ( usage == USAGE_DECLARE ) - { - std::ostringstream errmsg; - errmsg << _tokenizer->fileLine(tok1->next()) << ": Unused variable '" << varname << "'"; - _errorLogger->reportErr(errmsg.str()); - } - - else if ( ! (usage & USAGE_READ) ) - { - std::ostringstream errmsg; - errmsg << _tokenizer->fileLine(tok1->next()) << ": Variable '" << varname << "' is assigned a value that is never used"; - _errorLogger->reportErr(errmsg.str()); - } - - else if ( ! (usage & USAGE_WRITE) ) - { - std::ostringstream errmsg; - errmsg << _tokenizer->fileLine(tok1->next()) << ": Variable '" << varname << "' is not assigned a value"; - _errorLogger->reportErr(errmsg.str()); - } - } - - // Goto next executing scope.. - tok1 = TOKEN::findmatch( tok1->next(), ") const| {" ); - } +} +//--------------------------------------------------------------------------- + + + + + + +//--------------------------------------------------------------------------- +// Unreachable code below a 'return' +//--------------------------------------------------------------------------- + +void CheckOther::unreachableCode() +{ + const TOKEN *tok = TOKEN::findmatch( _tokenizer->tokens(), "[;{}] return" ); + while ( tok ) + { + // Goto the 'return' token + tok = tok->next(); + + // Locate the end of the 'return' statement + while ( tok && ! TOKEN::Match(tok, ";") ) + tok = tok->next(); + while ( tok && TOKEN::Match(tok->next(), ";") ) + tok = tok->next(); + + // If there is a statement below the return it is unreachable + if (!TOKEN::Match(tok, "; case|default|}|#") && !TOKEN::Match(tok, "; %var% :")) + { + std::ostringstream errmsg; + errmsg << _tokenizer->fileLine(tok->next()) << ": Unreachable code below a 'return'"; + _errorLogger->reportErr(errmsg.str()); + } + + // Find the next 'return' statement + tok = TOKEN::findmatch( tok, "[;{}] return" ); + } +} +//--------------------------------------------------------------------------- + + + + + + +//--------------------------------------------------------------------------- +// Usage of function variables +//--------------------------------------------------------------------------- + +static bool isOp(const TOKEN *tok) +{ + return bool(tok && + (tok->str() == "&&" || + tok->str() == "||" || + tok->str() == "==" || + tok->str() == "!=" || + tok->str() == "<" || + tok->str() == "<=" || + tok->str() == ">" || + tok->str() == ">=" || + tok->str() == "<<" || + TOKEN::Match(tok, "[+-*/&|,]"))); +} + +void CheckOther::functionVariableUsage() +{ + // Parse all executing scopes.. + const TOKEN *tok1 = TOKEN::findmatch( _tokenizer->tokens(), ") const| {" ); + while ( tok1 ) + { + // Varname, usage {1=declare, 2=read, 4=write} + std::map varUsage; + static const unsigned int USAGE_DECLARE = 1; + static const unsigned int USAGE_READ = 2; + static const unsigned int USAGE_WRITE = 4; + + int indentlevel = 0; + for ( const TOKEN *tok = tok1; tok; tok = tok->next() ) + { + if ( tok->str() == "{" ) + ++indentlevel; + else if ( tok->str() == "}" ) + { + --indentlevel; + if ( indentlevel <= 0 ) + break; + } + + if ( TOKEN::Match(tok, "[;{}] bool|char|short|int|long|float|double %var% ;|=") ) + varUsage[ tok->strAt(2) ] = USAGE_DECLARE; + + if ( TOKEN::Match(tok, "[;{}] bool|char|short|int|long|float|double * %var% ;|=") ) + varUsage[ tok->strAt(3) ] = USAGE_DECLARE; + + if ( TOKEN::Match(tok, "delete|return %var%") ) + varUsage[ tok->strAt(1) ] |= USAGE_READ; + + if ( TOKEN::Match(tok, "%var% =") ) + varUsage[ tok->str() ] |= USAGE_WRITE; + + if ( TOKEN::Match(tok, "else %var% =") ) + varUsage[ tok->strAt(1) ] |= USAGE_WRITE; + + if ( TOKEN::Match(tok, ">>|& %var%") ) + varUsage[ tok->strAt(1) ] |= USAGE_WRITE; + + if ((TOKEN::Match(tok,"[(=&!]") || isOp(tok)) && TOKEN::Match(tok->next(), "%var%")) + varUsage[ tok->strAt(1) ] |= USAGE_READ; + + if (TOKEN::Match(tok, "%var%") && (tok->next()->str()==")" || isOp(tok->next()))) + varUsage[ tok->str() ] |= USAGE_READ; + + if ( TOKEN::Match(tok, "[(,] %var% [,)]") ) + varUsage[ tok->strAt(1) ] |= USAGE_WRITE; + } + + // Check usage of all variables in the current scope.. + for ( std::map::const_iterator it = varUsage.begin(); it != varUsage.end(); ++it ) + { + std::string varname = it->first; + unsigned int usage = it->second; + + if (!isalpha(varname[0])) + continue; + + if ( ! ( usage & USAGE_DECLARE ) ) + continue; + + if ( usage == USAGE_DECLARE ) + { + std::ostringstream errmsg; + errmsg << _tokenizer->fileLine(tok1->next()) << ": Unused variable '" << varname << "'"; + _errorLogger->reportErr(errmsg.str()); + } + + else if ( ! (usage & USAGE_READ) ) + { + std::ostringstream errmsg; + errmsg << _tokenizer->fileLine(tok1->next()) << ": Variable '" << varname << "' is assigned a value that is never used"; + _errorLogger->reportErr(errmsg.str()); + } + + else if ( ! (usage & USAGE_WRITE) ) + { + std::ostringstream errmsg; + errmsg << _tokenizer->fileLine(tok1->next()) << ": Variable '" << varname << "' is not assigned a value"; + _errorLogger->reportErr(errmsg.str()); + } + } + + // Goto next executing scope.. + tok1 = TOKEN::findmatch( tok1->next(), ") const| {" ); + } } diff --git a/CheckOther.h b/CheckOther.h index 4d45dac71..d80ffd4f9 100644 --- a/CheckOther.h +++ b/CheckOther.h @@ -69,12 +69,12 @@ public: void CheckCharVariable(); // Incomplete statement. A statement that only contains a constant or variable - void CheckIncompleteStatement(); + void CheckIncompleteStatement(); - /** Unreachable code below a 'return' */ - void unreachableCode(); + /** Unreachable code below a 'return' */ + void unreachableCode(); - /** Unused function variables */ + /** Unused function variables */ void functionVariableUsage(); private: void CheckVariableScope_LookupVar( const TOKEN *tok1, const char varname[] ); diff --git a/FileLister.cpp b/FileLister.cpp index 3f9455c9d..77eda42b0 100644 --- a/FileLister.cpp +++ b/FileLister.cpp @@ -38,7 +38,7 @@ bool FileLister::AcceptFile( const std::string &filename ) std::string extension = filename.substr( dotLocation ); - if( extension == ".cpp" || + if( extension == ".cpp" || extension == ".cxx" || extension == ".cc" || extension == ".c" ) @@ -127,7 +127,7 @@ void FileLister::RecursiveAddFiles( std::vector &filenames, const s return; } - AddFiles( filenames, path, "*.cpp" ); + AddFiles( filenames, path, "*.cpp" ); AddFiles( filenames, path, "*.cxx" ); AddFiles( filenames, path, "*.cc" ); AddFiles( filenames, path, "*.c" ); diff --git a/FileLister.h b/FileLister.h index c545df7ec..71bc6e444 100644 --- a/FileLister.h +++ b/FileLister.h @@ -38,18 +38,18 @@ class FileLister { public: - static void RecursiveAddFiles( std::vector &filenames, const std::string &path, bool recursive ); + static void RecursiveAddFiles( std::vector &filenames, const std::string &path, bool recursive ); -private: - static bool AcceptFile( const std::string &filename ); +private: + static bool AcceptFile( const std::string &filename ); -#ifdef __BORLANDC__ - static void AddFiles( std::vector &filenames, const std::string &path, const std::string &pattern ); -#endif +#ifdef __BORLANDC__ + static void AddFiles( std::vector &filenames, const std::string &path, const std::string &pattern ); +#endif -#ifdef _MSC_VER - static void AddFiles( std::vector &filenames, const std::string &path, const std::string &pattern ); -#endif +#ifdef _MSC_VER + static void AddFiles( std::vector &filenames, const std::string &path, const std::string &pattern ); +#endif }; diff --git a/cppcheck.cpp b/cppcheck.cpp index 273b64ecd..4b33d3e4e 100644 --- a/cppcheck.cpp +++ b/cppcheck.cpp @@ -1,360 +1,360 @@ -/* - * 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 -#include -#include -#include -#include - -//--------------------------------------------------------------------------- - -CppCheck::CppCheck( ErrorLogger &errorLogger ) : _checkFunctionUsage( this ) -{ - _errorLogger = &errorLogger; -} - -CppCheck::~CppCheck() -{ - -} - -void CppCheck::settings( const Settings &settings ) -{ - _settings = settings; -} - -void CppCheck::addFile( const std::string &path ) -{ - _filenames.push_back( path ); -} - -void CppCheck::addFile( const std::string &path, const std::string &content ) -{ - _filenames.push_back( path ); - _fileContents[ path ] = content; -} - -std::string CppCheck::parseFromArgs( int argc, const char* const argv[] ) -{ - std::vector pathnames; - bool Recursive = false; - - for (int i = 1; i < argc; i++) - { - // Flag used for various purposes during debugging - if (strcmp(argv[i],"--debug") == 0) - _settings._debug = true; - - // Show all messages - else if (strcmp(argv[i],"--all") == 0) - _settings._showAll = true; - - // Only print something when there are errors - else if (strcmp(argv[i],"--errorsonly")==0) - _settings._errorsOnly = true; - - // Checking coding style - else if (strcmp(argv[i],"--style")==0) - _settings._checkCodingStyle = true; - - // Recursively check source files - else if (strcmp(argv[i],"--recursive")==0) - Recursive = true; - - // Verbose error messages (configuration info) - else if (strcmp(argv[i],"--verbose")==0) - _settings._verbose = true; - - else - pathnames.push_back( argv[i] ); - } - - // --recursive was used - if ( Recursive ) - { - if( pathnames.size() == 0 ) - { - // Handle situation: cppcheck --recursive - FileLister::RecursiveAddFiles( _filenames, "", true ); - } - else - { - // Handle situation: cppcheck --recursive path1 path2 - - // Execute RecursiveAddFiles() to each given file parameter - std::vector::const_iterator iter; - for(iter=pathnames.begin(); iter!=pathnames.end(); iter++) - FileLister::RecursiveAddFiles( _filenames, iter->c_str(), true ); - } - } - else - { - std::vector::const_iterator iter; - for(iter=pathnames.begin(); iter!=pathnames.end(); iter++) - FileLister::RecursiveAddFiles( _filenames, iter->c_str(), false ); - } - - if (_filenames.empty()) - { - std::ostringstream oss; - oss << "c++check 1.26\n" - "\n" - "C/C++ code checking\n" - "\n" - "Syntax:\n" - " cppcheck [--all] [--errorsonly] [--recursive] [--style] [--verbose] [filename1] [filename2]\n" - "\n" - "Options:\n" - " --all Make the checking more sensitive. More bugs are detected,\n" - " but there are also more false positives\n" - " --errorsonly Only print error messages\n" - " --recursive Recursively check all *.cpp, *.cxx, *.cc and *.c files\n" - " --style Check coding style\n" - " --verbose More detailed error reports\n"; - return oss.str(); - } - - // Check function usage if "--style" and "--all" was given. - // There will be false positives for exported library functions - if ( _settings._showAll && _settings._checkCodingStyle ) - _settings._checkFunctionUsage = true; - - return ""; -} - -void CppCheck::check() -{ - std::sort( _filenames.begin(), _filenames.end() ); - for (unsigned int c = 0; c < _filenames.size(); c++) - { - _errout.str(""); - std::string fname = _filenames[c]; - - // If only errors are printed, print filename after the check - if ( _settings._errorsOnly == false ) - _errorLogger->reportOut( std::string( "Checking " ) + fname + std::string( "..." ) ); - - Preprocessor preprocessor( this ); - std::map code; - if( _fileContents.size() > 0 && _fileContents.find( _filenames[c] ) != _fileContents.end() ) - { - // File content was given as a string - std::istringstream iss( _fileContents[ _filenames[c] ] ); - preprocessor.preprocess(iss, code, fname); - } - else - { - // Only file name was given, read the content from file - std::ifstream fin( fname.c_str() ); - preprocessor.preprocess(fin, code, fname); - } - - for ( std::map::const_iterator it = code.begin(); it != code.end(); ++it ) - { - cfg = it->first; - checkFile(it->second, _filenames[c].c_str()); - } - - if ( _settings._errorsOnly == false && _errout.str().empty() ) - _errorLogger->reportOut( "No errors found" ); - } - - // This generates false positives - especially for libraries - _settings._verbose = false; - if ( _settings._checkFunctionUsage ) - { - _errout.str(""); - if( _settings._errorsOnly == false ) - _errorLogger->reportOut( "Checking usage of global functions (this may take several minutes).." ); - - _checkFunctionUsage.check(); - } - -} - - -//--------------------------------------------------------------------------- -// CppCheck - A function that checks a specified file -//--------------------------------------------------------------------------- - -void CppCheck::checkFile(const std::string &code, const char FileName[]) -{ - Tokenizer _tokenizer; - - // Tokenize the file - { - std::istringstream istr(code); - _tokenizer.tokenize(istr, FileName); - } - - _tokenizer.fillFunctionList(); - - // 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, this ); - checkClass.CheckMemset(); - - - // Check for unsigned divisions where one operand is signed - // Very important to run it before 'SimplifyTokenList' - CheckOther checkOther( &_tokenizer, this ); - if ( _settings._checkCodingStyle ) - checkOther.CheckUnsignedDivision(); +/* + * 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 +#include +#include +#include +#include + +//--------------------------------------------------------------------------- + +CppCheck::CppCheck( ErrorLogger &errorLogger ) : _checkFunctionUsage( this ) +{ + _errorLogger = &errorLogger; +} + +CppCheck::~CppCheck() +{ + +} + +void CppCheck::settings( const Settings &settings ) +{ + _settings = settings; +} + +void CppCheck::addFile( const std::string &path ) +{ + _filenames.push_back( path ); +} + +void CppCheck::addFile( const std::string &path, const std::string &content ) +{ + _filenames.push_back( path ); + _fileContents[ path ] = content; +} + +std::string CppCheck::parseFromArgs( int argc, const char* const argv[] ) +{ + std::vector pathnames; + bool Recursive = false; + + for (int i = 1; i < argc; i++) + { + // Flag used for various purposes during debugging + if (strcmp(argv[i],"--debug") == 0) + _settings._debug = true; + + // Show all messages + else if (strcmp(argv[i],"--all") == 0) + _settings._showAll = true; + + // Only print something when there are errors + else if (strcmp(argv[i],"--errorsonly")==0) + _settings._errorsOnly = true; + + // Checking coding style + else if (strcmp(argv[i],"--style")==0) + _settings._checkCodingStyle = true; + + // Recursively check source files + else if (strcmp(argv[i],"--recursive")==0) + Recursive = true; + + // Verbose error messages (configuration info) + else if (strcmp(argv[i],"--verbose")==0) + _settings._verbose = true; + + else + pathnames.push_back( argv[i] ); + } + + // --recursive was used + if ( Recursive ) + { + if( pathnames.size() == 0 ) + { + // Handle situation: cppcheck --recursive + FileLister::RecursiveAddFiles( _filenames, "", true ); + } + else + { + // Handle situation: cppcheck --recursive path1 path2 + + // Execute RecursiveAddFiles() to each given file parameter + std::vector::const_iterator iter; + for(iter=pathnames.begin(); iter!=pathnames.end(); iter++) + FileLister::RecursiveAddFiles( _filenames, iter->c_str(), true ); + } + } + else + { + std::vector::const_iterator iter; + for(iter=pathnames.begin(); iter!=pathnames.end(); iter++) + FileLister::RecursiveAddFiles( _filenames, iter->c_str(), false ); + } + + if (_filenames.empty()) + { + std::ostringstream oss; + oss << "c++check 1.26\n" + "\n" + "C/C++ code checking\n" + "\n" + "Syntax:\n" + " cppcheck [--all] [--errorsonly] [--recursive] [--style] [--verbose] [filename1] [filename2]\n" + "\n" + "Options:\n" + " --all Make the checking more sensitive. More bugs are detected,\n" + " but there are also more false positives\n" + " --errorsonly Only print error messages\n" + " --recursive Recursively check all *.cpp, *.cxx, *.cc and *.c files\n" + " --style Check coding style\n" + " --verbose More detailed error reports\n"; + return oss.str(); + } + + // Check function usage if "--style" and "--all" was given. + // There will be false positives for exported library functions + if ( _settings._showAll && _settings._checkCodingStyle ) + _settings._checkFunctionUsage = true; + + return ""; +} + +void CppCheck::check() +{ + std::sort( _filenames.begin(), _filenames.end() ); + for (unsigned int c = 0; c < _filenames.size(); c++) + { + _errout.str(""); + std::string fname = _filenames[c]; + + // If only errors are printed, print filename after the check + if ( _settings._errorsOnly == false ) + _errorLogger->reportOut( std::string( "Checking " ) + fname + std::string( "..." ) ); + + Preprocessor preprocessor( this ); + std::map code; + if( _fileContents.size() > 0 && _fileContents.find( _filenames[c] ) != _fileContents.end() ) + { + // File content was given as a string + std::istringstream iss( _fileContents[ _filenames[c] ] ); + preprocessor.preprocess(iss, code, fname); + } + else + { + // Only file name was given, read the content from file + std::ifstream fin( fname.c_str() ); + preprocessor.preprocess(fin, code, fname); + } + + for ( std::map::const_iterator it = code.begin(); it != code.end(); ++it ) + { + cfg = it->first; + checkFile(it->second, _filenames[c].c_str()); + } + + if ( _settings._errorsOnly == false && _errout.str().empty() ) + _errorLogger->reportOut( "No errors found" ); + } + + // This generates false positives - especially for libraries + _settings._verbose = false; + if ( _settings._checkFunctionUsage ) + { + _errout.str(""); + if( _settings._errorsOnly == false ) + _errorLogger->reportOut( "Checking usage of global functions (this may take several minutes).." ); + + _checkFunctionUsage.check(); + } + +} + + +//--------------------------------------------------------------------------- +// CppCheck - A function that checks a specified file +//--------------------------------------------------------------------------- + +void CppCheck::checkFile(const std::string &code, const char FileName[]) +{ + Tokenizer _tokenizer; + + // Tokenize the file + { + std::istringstream istr(code); + _tokenizer.tokenize(istr, FileName); + } + + _tokenizer.fillFunctionList(); + + // 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, this ); + checkClass.CheckMemset(); + + + // Check for unsigned divisions where one operand is signed + // Very important to run it before 'SimplifyTokenList' + CheckOther checkOther( &_tokenizer, this ); + if ( _settings._checkCodingStyle ) + checkOther.CheckUnsignedDivision(); + + // Give warning when using char variable as array index + // Doesn't work on simplified token list ('unsigned') + if ( _settings._checkCodingStyle ) + checkOther.CheckCharVariable(); + + + // Including header which is not needed (too many false positives) +// if ( _settings._checkCodingStyle ) +// { +// CheckHeaders checkHeaders( &tokenizer ); +// checkHeaders.WarningIncludeHeader(); +// } + + + _tokenizer.simplifyTokenList(); + + + if ( _settings._checkFunctionUsage ) + _checkFunctionUsage.parseTokens(_tokenizer); + + // Memory leak + CheckMemoryLeakClass checkMemoryLeak( &_tokenizer, _settings, this ); + checkMemoryLeak.CheckMemoryLeak(); + + // Buffer overruns.. + CheckBufferOverrunClass checkBufferOverrun( &_tokenizer, _settings, this ); + checkBufferOverrun.CheckBufferOverrun(); + + // 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)" + checkOther.CheckIfAssignment(); + + // Check for case without break + // Disabled because it generates many false positives + // CheckCaseWithoutBreak(); + + // Dangerous usage of strtok + // Disabled because it generates false positives + //WarningStrTok(); + } + + + + // Dangerous functions, such as 'gets' and 'scanf' + checkBufferOverrun.WarningDangerousFunctions(); + + + // Invalid function usage.. + checkOther.InvalidFunctionUsage(); + + + if (_settings._checkCodingStyle) + { + // Check that all private functions are called. + checkClass.CheckUnusedPrivateFunctions(); + + // Warning upon c-style pointer casts + const char *ext = strrchr(FileName, '.'); + if (ext && strcmp(ext,".cpp")==0) + checkOther.WarningOldStylePointerCast(); + + // Use standard functions instead + checkOther.WarningIsDigit(); + checkOther.WarningIsAlpha(); + + checkClass.CheckOperatorEq1(); + + // if (a) delete a; + checkOther.WarningRedundantCode(); + + // if (condition); + checkOther.WarningIf(); + + // Variable scope (check if the scope could be limited) + //CheckVariableScope(); + + // Check if a constant function parameter is passed by value + checkOther.CheckConstantFunctionParameter(); + + // Unused struct members.. + checkOther.CheckStructMemberUsage(); + + // Check for various types of incomplete statements that could for example + // mean that an ';' has been added by accident + checkOther.CheckIncompleteStatement(); + + // Unreachable code below a 'return' statement + checkOther.unreachableCode(); + + // Usage of local functions + checkOther.functionVariableUsage(); + } +} +//--------------------------------------------------------------------------- + +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 ); + } - // Give warning when using char variable as array index - // Doesn't work on simplified token list ('unsigned') - if ( _settings._checkCodingStyle ) - checkOther.CheckCharVariable(); + std::string errmsg2( errmsg ); + if ( _settings._verbose ) + { + errmsg2 += "\n Defines=\'" + cfg + "\'\n"; + } + + + _errorLogger->reportErr( errmsg2 ); + _errout << errmsg2 << std::endl; +} - // Including header which is not needed (too many false positives) -// if ( _settings._checkCodingStyle ) -// { -// CheckHeaders checkHeaders( &tokenizer ); -// checkHeaders.WarningIncludeHeader(); -// } - - - _tokenizer.simplifyTokenList(); - - - if ( _settings._checkFunctionUsage ) - _checkFunctionUsage.parseTokens(_tokenizer); - - // Memory leak - CheckMemoryLeakClass checkMemoryLeak( &_tokenizer, _settings, this ); - checkMemoryLeak.CheckMemoryLeak(); - - // Buffer overruns.. - CheckBufferOverrunClass checkBufferOverrun( &_tokenizer, _settings, this ); - checkBufferOverrun.CheckBufferOverrun(); - - // 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)" - checkOther.CheckIfAssignment(); - - // Check for case without break - // Disabled because it generates many false positives - // CheckCaseWithoutBreak(); - - // Dangerous usage of strtok - // Disabled because it generates false positives - //WarningStrTok(); - } - - - - // Dangerous functions, such as 'gets' and 'scanf' - checkBufferOverrun.WarningDangerousFunctions(); - - - // Invalid function usage.. - checkOther.InvalidFunctionUsage(); - - - if (_settings._checkCodingStyle) - { - // Check that all private functions are called. - checkClass.CheckUnusedPrivateFunctions(); - - // Warning upon c-style pointer casts - const char *ext = strrchr(FileName, '.'); - if (ext && strcmp(ext,".cpp")==0) - checkOther.WarningOldStylePointerCast(); - - // Use standard functions instead - checkOther.WarningIsDigit(); - checkOther.WarningIsAlpha(); - - checkClass.CheckOperatorEq1(); - - // if (a) delete a; - checkOther.WarningRedundantCode(); - - // if (condition); - checkOther.WarningIf(); - - // Variable scope (check if the scope could be limited) - //CheckVariableScope(); - - // Check if a constant function parameter is passed by value - checkOther.CheckConstantFunctionParameter(); - - // Unused struct members.. - checkOther.CheckStructMemberUsage(); - - // Check for various types of incomplete statements that could for example - // mean that an ';' has been added by accident - checkOther.CheckIncompleteStatement(); - - // Unreachable code below a 'return' statement - checkOther.unreachableCode(); - - // Usage of local functions - checkOther.functionVariableUsage(); - } -} -//--------------------------------------------------------------------------- - -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 ); - } - - std::string errmsg2( errmsg ); - if ( _settings._verbose ) - { - errmsg2 += "\n Defines=\'" + cfg + "\'\n"; - } - - - _errorLogger->reportErr( errmsg2 ); - - _errout << errmsg2 << std::endl; -} - -void CppCheck::reportOut( const std::string &outmsg) -{ - // This is currently never called. It is here just to comply with - // the interface. -} +void CppCheck::reportOut( const std::string &outmsg) +{ + // This is currently never called. It is here just to comply with + // the interface. +} diff --git a/cppcheck.h b/cppcheck.h index bbd3f1bd8..c31910fa0 100644 --- a/cppcheck.h +++ b/cppcheck.h @@ -1,126 +1,126 @@ -/* - * 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 -#include -#include -#include -#include -#include "settings.h" -#include "errorlogger.h" -#include "CheckFunctionUsage.h" +#include +#include +#include +#include +#include +#include "settings.h" +#include "errorlogger.h" +#include "CheckFunctionUsage.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. - * Usage: See check() for more info. - */ -class CppCheck : public ErrorLogger -{ - public: - /** - * Constructor. - */ - CppCheck( ErrorLogger &errorLogger ); +/** + * 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. + * Usage: See check() for more info. + */ +class CppCheck : public ErrorLogger +{ + public: + /** + * Constructor. + */ + CppCheck( ErrorLogger &errorLogger ); - /** - * Destructor. - */ - virtual ~CppCheck(); + /** + * Destructor. + */ + virtual ~CppCheck(); - /** - * This starts the actual checking. Note that you must call - * parseFromArgs() or settings() and addFile() before calling this. - */ - void check(); + /** + * This starts the actual checking. Note that you must call + * parseFromArgs() or settings() and addFile() before calling this. + */ + void check(); - /** - * Adjust the settings before doing the check. E.g. show only - * actual bugs or also coding style issues. - * - * @param settings New settings which will overwrite the old. - */ - void settings( const Settings &settings ); + /** + * Adjust the settings before doing the check. E.g. show only + * actual bugs or also coding style issues. + * + * @param settings New settings which will overwrite the old. + */ + void settings( const Settings &settings ); - /** - * Add new file to be checked. - * - * @param path Relative or absolute path to the file to be checked, - * e.g. "cppcheck.cpp". Note that only source files (.c, .cc or .cpp) - * should be added to the list. Include filese are gathered automatically. - */ - void addFile( const std::string &path ); + /** + * Add new file to be checked. + * + * @param path Relative or absolute path to the file to be checked, + * e.g. "cppcheck.cpp". Note that only source files (.c, .cc or .cpp) + * should be added to the list. Include filese are gathered automatically. + */ + void addFile( const std::string &path ); - /** - * Add new unreal file to be checked. - * - * @param path File name (used for error reporting). - * @param content If the file would be a real file, this should be - * the content of the file. - */ - void addFile( const std::string &path, const std::string &content ); + /** + * Add new unreal file to be checked. + * + * @param path File name (used for error reporting). + * @param content If the file would be a real file, this should be + * the content of the file. + */ + void addFile( const std::string &path, const std::string &content ); - /** - * Parse command line args and get settings and file lists - * from there. - * - * @param argc argc from main() - * @param argv argv from main() - * @return Empty string if parameters were accepted, or - * string containing "help" text if no files were found to be - * checked. - */ - std::string parseFromArgs( int argc, const char* const argv[] ); + /** + * Parse command line args and get settings and file lists + * from there. + * + * @param argc argc from main() + * @param argv argv from main() + * @return Empty string if parameters were accepted, or + * string containing "help" text if no files were found to be + * checked. + */ + std::string parseFromArgs( int argc, const char* const argv[] ); - private: - void checkFile(const std::string &code, const char FileName[]); + private: + void checkFile(const std::string &code, const char FileName[]); - /** - * Errors and warnings are directed here. - * - * @param errmsg Errors messages are normally in format - * "[filepath:line number] Message", e.g. - * "[main.cpp:4] Uninitialized member variable" - */ - virtual void reportErr( const std::string &errmsg); + /** + * Errors and warnings are directed here. + * + * @param errmsg Errors messages are normally in format + * "[filepath:line number] Message", e.g. + * "[main.cpp:4] Uninitialized member variable" + */ + virtual void reportErr( const std::string &errmsg); - /** - * Information about progress is directed here. - * - * @param outmsg, E.g. "Checking main.cpp..." - */ - virtual void reportOut( const std::string &outmsg); + /** + * Information about progress is directed here. + * + * @param outmsg, E.g. "Checking main.cpp..." + */ + virtual void reportOut( const std::string &outmsg); - std::list _errorList; - std::ostringstream _errout; - Settings _settings; - std::vector _filenames; - /** Key is file name, and value is the content of the file */ - std::map _fileContents; - CheckFunctionUsage _checkFunctionUsage; - ErrorLogger *_errorLogger; + std::list _errorList; + std::ostringstream _errout; + Settings _settings; + std::vector _filenames; + /** Key is file name, and value is the content of the file */ + std::map _fileContents; + CheckFunctionUsage _checkFunctionUsage; + ErrorLogger *_errorLogger; - /** Current configuration */ - std::string cfg; -}; + /** Current configuration */ + std::string cfg; +}; -#endif // CPPCHECK_H +#endif // CPPCHECK_H diff --git a/cppcheckexecutor.cpp b/cppcheckexecutor.cpp index ae058ac20..133e7dc95 100644 --- a/cppcheckexecutor.cpp +++ b/cppcheckexecutor.cpp @@ -1,51 +1,51 @@ -/* - * 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 +#include "cppcheckexecutor.h" +#include "cppcheck.h" +#include -CppCheckExecutor::CppCheckExecutor() -{ - //ctor -} +CppCheckExecutor::CppCheckExecutor() +{ + //ctor +} -CppCheckExecutor::~CppCheckExecutor() -{ - //dtor -} +CppCheckExecutor::~CppCheckExecutor() +{ + //dtor +} -void CppCheckExecutor::check( int argc, const char* const argv[] ) -{ - CppCheck cppCheck( *this ); - std::string result = cppCheck.parseFromArgs( argc, argv ); - if( result.length() == 0 ) - cppCheck.check(); - else - std::cout << result; -} +void CppCheckExecutor::check( int argc, const char* const argv[] ) +{ + CppCheck cppCheck( *this ); + std::string result = cppCheck.parseFromArgs( argc, argv ); + if( result.length() == 0 ) + cppCheck.check(); + else + std::cout << result; +} -void CppCheckExecutor::reportErr( const std::string &errmsg) -{ - std::cerr << errmsg << std::endl; -} +void CppCheckExecutor::reportErr( const std::string &errmsg) +{ + std::cerr << errmsg << std::endl; +} -void CppCheckExecutor::reportOut( const std::string &outmsg) -{ - std::cout << outmsg << std::endl; -} +void CppCheckExecutor::reportOut( const std::string &outmsg) +{ + std::cout << outmsg << std::endl; +} diff --git a/cppcheckexecutor.h b/cppcheckexecutor.h index cf6e2be87..aaaf14e1b 100644 --- a/cppcheckexecutor.h +++ b/cppcheckexecutor.h @@ -1,71 +1,71 @@ -/* - * 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 +#include -/** - * This is an interface, which the class responsible of error logging - * should implement. - */ -class ErrorLogger -{ -public: - virtual ~ErrorLogger() {} +/** + * This is an interface, which the class responsible of error logging + * should implement. + */ +class ErrorLogger +{ +public: + virtual ~ErrorLogger() {} - /** - * Errors and warnings are directed here. - * - * @param errmsg Errors messages are normally in format - * "[filepath:line number] Message", e.g. - * "[main.cpp:4] Uninitialized member variable" - */ - virtual void reportErr( const std::string &errmsg) = 0; + /** + * Errors and warnings are directed here. + * + * @param errmsg Errors messages are normally in format + * "[filepath:line number] Message", e.g. + * "[main.cpp:4] Uninitialized member variable" + */ + virtual void reportErr( const std::string &errmsg) = 0; - /** - * Information about progress is directed here. - * - * @param outmsg, E.g. "Checking main.cpp..." - */ - virtual void reportOut( const std::string &outmsg) = 0; -}; + /** + * Information about progress is directed here. + * + * @param outmsg, E.g. "Checking main.cpp..." + */ + virtual void reportOut( const std::string &outmsg) = 0; +}; -#endif // #ifndef ERRORLOGGER_H +#endif // #ifndef ERRORLOGGER_H diff --git a/main.cpp b/main.cpp index 4cf13d56d..c0517ec8d 100644 --- a/main.cpp +++ b/main.cpp @@ -15,19 +15,19 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see reportErr( oss.str() ); return ""; } - - if ( ch == '\n' ) - ++lineno; + + if ( ch == '\n' ) + ++lineno; // Replace assorted special chars with spaces.. if ( (ch != '\n') && (isspace(ch) || iscntrl(ch)) ) @@ -75,7 +75,7 @@ std::string Preprocessor::read(std::istream &istr, const std::string &filename) { while (istr.good() && ch!='\n') ch = (char)istr.get(); - code << "\n"; + code << "\n"; ++lineno; } @@ -86,17 +86,17 @@ std::string Preprocessor::read(std::istream &istr, const std::string &filename) { chPrev = ch; ch = (char)istr.get(); - if (ch == '\n') + if (ch == '\n') { - code << "\n"; - ++lineno; + code << "\n"; + ++lineno; } } } else - { - if ( chNext == '\n' ) + { + if ( chNext == '\n' ) ++lineno; code << std::string(1,ch) << std::string(1,chNext); } @@ -113,10 +113,10 @@ std::string Preprocessor::read(std::istream &istr, const std::string &filename) if ( ch == '\\' ) { ch = (char)istr.get(); - code << std::string(1,ch); + code << std::string(1,ch); - // Avoid exiting loop if string contains "-characters - ch = 0; + // Avoid exiting loop if string contains "-characters + ch = 0; } } while ( istr.good() && ch != '\"' ); } @@ -141,9 +141,9 @@ std::string Preprocessor::read(std::istream &istr, const std::string &filename) { code << std::string(1, ch); } - } + } - return code.str(); + return code.str(); } /** @@ -158,22 +158,22 @@ void Preprocessor::preprocess(std::istream &istr, std::map 0 ) - --loc; + codestr.erase( loc, 1 ); + if ( loc > 0 ) + --loc; } // Using the backslash at the end of a line.. diff --git a/preprocessor.h b/preprocessor.h index a631c58fa..2e19d9491 100644 --- a/preprocessor.h +++ b/preprocessor.h @@ -24,34 +24,34 @@ #include #include #include -#include -#include "errorlogger.h" +#include +#include "errorlogger.h" -class Preprocessor -{ -public: +class Preprocessor +{ +public: Preprocessor( ErrorLogger *errorLogger ); - void preprocess(std::istream &istr, std::map &result, const std::string &filename); - - /** Just read the code into a string. Perform simple cleanup of the code */ - std::string read(std::istream &istr, const std::string &filename); + void preprocess(std::istream &istr, std::map &result, const std::string &filename); + + /** Just read the code into a string. Perform simple cleanup of the code */ + std::string read(std::istream &istr, const std::string &filename); -private: - /** - * Get preprocessed code for a given configuration - */ - std::string getcode(const std::string &filedata, std::string cfg); +private: + /** + * Get preprocessed code for a given configuration + */ + std::string getcode(const std::string &filedata, std::string cfg); - /** - * Get all possible configurations. By looking at the ifdefs and ifndefs in filedata - */ - std::list getcfgs( const std::string &filedata ); + /** + * Get all possible configurations. By looking at the ifdefs and ifndefs in filedata + */ + std::list getcfgs( const std::string &filedata ); - std::string getdef(std::string line, bool def); + std::string getdef(std::string line, bool def); - bool match_cfg_def( std::string cfg, const std::string &def ); + bool match_cfg_def( std::string cfg, const std::string &def ); - ErrorLogger *_errorLogger; + ErrorLogger *_errorLogger; }; //--------------------------------------------------------------------------- diff --git a/settings.cpp b/settings.cpp index 095d84c8d..398a55a81 100644 --- a/settings.cpp +++ b/settings.cpp @@ -1,34 +1,34 @@ -/* - * 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 #include @@ -49,7 +49,7 @@ private: // Check for memory leaks.. Settings settings; - settings._debug = true; + settings._debug = true; settings._showAll = false; tokenizer.fillFunctionList(); CheckMemoryLeakClass checkMemoryLeak( &tokenizer, settings, this ); @@ -112,7 +112,7 @@ private: TEST_CASE( func4 ); TEST_CASE( func5 ); TEST_CASE( func6 ); - // TODO TEST_CASE( func7 ); + // TODO TEST_CASE( func7 ); TEST_CASE( func8 ); // Using callback // TODO TEST_CASE( class1 ); @@ -122,10 +122,10 @@ private: TEST_CASE( linux_list_1 ); - TEST_CASE( sizeof1 ); + TEST_CASE( sizeof1 ); - TEST_CASE( realloc1 ); - TEST_CASE( realloc2 ); + TEST_CASE( realloc1 ); + TEST_CASE( realloc2 ); TEST_CASE( assign ); } @@ -137,7 +137,7 @@ private: check( "void f()\n" "{\n" " int *a = new int[10];\n" - "}\n" ); + "}\n" ); ASSERT_EQUALS( std::string("[test.cpp:4]: Memory leak: a\n"), errout.str() ); } @@ -611,8 +611,8 @@ private: " }\n" " while (!str);\n" " return str;\n" - "}\n" ); - std::string err( errout.str() ); + "}\n" ); + std::string err( errout.str() ); ASSERT_EQUALS( std::string("[test.cpp:5]: Memory leak: str\n"), err ); } @@ -789,38 +789,38 @@ private: ASSERT_EQUALS( std::string("[test.cpp:10]: Memory leak: p\n"), err ); } + + void func7() + { + check( "static void foo(char *str)\n" + "{\n" + " if (abc)\n" + " return;" + " delete [] str;\n" + "}\n" + "\n" + "static void f()\n" + "{\n" + " char *p = new char[100];\n" + " foo(p);\n" + "}\n" ); + std::string err( errout.str() ); + ASSERT_EQUALS( std::string("[test.cpp:11]: Memory leak: p\n"), err ); + } - void func7() - { - check( "static void foo(char *str)\n" - "{\n" - " if (abc)\n" - " return;" - " delete [] str;\n" - "}\n" - "\n" - "static void f()\n" - "{\n" - " char *p = new char[100];\n" - " foo(p);\n" - "}\n" ); - std::string err( errout.str() ); - ASSERT_EQUALS( std::string("[test.cpp:11]: Memory leak: p\n"), err ); - } - - - void func8() - { - check( "static void foo()\n" - "{\n" - " char *str = new char[100];" - " (*release)(str);\n" - "}\n" ); - ASSERT_EQUALS( std::string(""), errout.str() ); - } - + + void func8() + { + check( "static void foo()\n" + "{\n" + " char *str = new char[100];" + " (*release)(str);\n" + "}\n" ); + ASSERT_EQUALS( std::string(""), errout.str() ); + } + /* void func3() { @@ -969,61 +969,61 @@ private: ASSERT_EQUALS( std::string("[test.cpp:12]: Memory leak: s2\n"), err ); } + + void realloc1() + { + check( "void foo()\n" + "{\n" + " char *a = (char *)malloc(10);\n" + " a = realloc(a, 100);\n" + "}\n" ); - void realloc1() - { - check( "void foo()\n" - "{\n" - " char *a = (char *)malloc(10);\n" - " a = realloc(a, 100);\n" - "}\n" ); + ASSERT_EQUALS( std::string("[test.cpp:5]: Memory leak: a\n"), errout.str() ); + } - ASSERT_EQUALS( std::string("[test.cpp:5]: Memory leak: a\n"), errout.str() ); - } + void realloc2() + { + check( "void foo()\n" + "{\n" + " char *a = (char *)malloc(10);\n" + " a = (char *)realloc(a, 100);\n" + " free(a);\n" + "}\n" ); - void realloc2() - { - check( "void foo()\n" - "{\n" - " char *a = (char *)malloc(10);\n" - " a = (char *)realloc(a, 100);\n" - " free(a);\n" - "}\n" ); + ASSERT_EQUALS( std::string(""), errout.str() ); + } - ASSERT_EQUALS( std::string(""), errout.str() ); - } + + void assign() + { + check( "void foo()\n" + "{\n" + " char *a = (char *)malloc(10);\n" + " a = 0;\n" + " free(a);\n" + "}\n" ); + ASSERT_EQUALS( std::string("[test.cpp:3]: Memory leak: a\n"), errout.str() ); - void assign() - { - check( "void foo()\n" - "{\n" - " char *a = (char *)malloc(10);\n" - " a = 0;\n" - " free(a);\n" - "}\n" ); + check( "void foo()\n" + "{\n" + " char *a = (char *)malloc(10);\n" + " char *p = a;\n" + " free(p);\n" + "}\n" ); - ASSERT_EQUALS( std::string("[test.cpp:3]: Memory leak: a\n"), errout.str() ); + ASSERT_EQUALS( std::string(""), errout.str() ); - check( "void foo()\n" - "{\n" - " char *a = (char *)malloc(10);\n" - " char *p = a;\n" - " free(p);\n" - "}\n" ); + check( "void foo()\n" + "{\n" + " char *a = (char *)malloc(10);\n" + " a += 10;\n" + " free(a - 10);\n" + "}\n" ); - ASSERT_EQUALS( std::string(""), errout.str() ); - - check( "void foo()\n" - "{\n" - " char *a = (char *)malloc(10);\n" - " a += 10;\n" - " free(a - 10);\n" - "}\n" ); - - ASSERT_EQUALS( std::string(""), errout.str() ); - } + ASSERT_EQUALS( std::string(""), errout.str() ); + } }; diff --git a/testpreprocessor.cpp b/testpreprocessor.cpp index f12360770..964dc1af6 100644 --- a/testpreprocessor.cpp +++ b/testpreprocessor.cpp @@ -37,8 +37,8 @@ private: void run() { - // Just read the code into a string. Perform simple cleanup of the code - TEST_CASE(readCode); + // Just read the code into a string. Perform simple cleanup of the code + TEST_CASE(readCode); // The bug that started the whole work with the new preprocessor TEST_CASE( Bug2190219 ); @@ -62,17 +62,17 @@ private: TEST_CASE( multiline ); } + - - void readCode() - { - const char code[] = " \t a //\n" - " #aa\t /* remove this */\tb \r\n"; - Preprocessor p(NULL); - std::istringstream istr(code); - std::string codestr( p.read(istr,"") ); - ASSERT_EQUALS( "a \n#aa b \n", codestr ); - } + void readCode() + { + const char code[] = " \t a //\n" + " #aa\t /* remove this */\tb \r\n"; + Preprocessor p(NULL); + std::istringstream istr(code); + std::string codestr( p.read(istr,"") ); + ASSERT_EQUALS( "a \n#aa b \n", codestr ); + } bool cmpmaps(const std::map &m1, const std::map &m2) @@ -154,7 +154,7 @@ private: // Preprocess => actual result.. std::istringstream istr(filedata); std::map actual; - Preprocessor preprocessor( this ); + Preprocessor preprocessor( this ); preprocessor.preprocess( istr, actual, "" ); // Compare results.. @@ -178,7 +178,7 @@ private: // Preprocess => actual result.. std::istringstream istr(filedata); std::map actual; - Preprocessor preprocessor( this ); + Preprocessor preprocessor( this ); preprocessor.preprocess( istr, actual, "" ); // Compare results.. @@ -201,7 +201,7 @@ private: // Preprocess => actual result.. std::istringstream istr(filedata); std::map actual; - Preprocessor preprocessor( this ); + Preprocessor preprocessor( this ); preprocessor.preprocess( istr, actual, "" ); // Compare results.. @@ -227,7 +227,7 @@ private: // Preprocess => actual result.. std::istringstream istr(filedata); std::map actual; - Preprocessor preprocessor( this ); + Preprocessor preprocessor( this ); preprocessor.preprocess( istr, actual, "" ); // Compare results.. @@ -251,7 +251,7 @@ private: // Preprocess => actual result.. std::istringstream istr(filedata); std::map actual; - Preprocessor preprocessor( this ); + Preprocessor preprocessor( this ); preprocessor.preprocess( istr, actual, "" ); // Compare results.. @@ -278,7 +278,7 @@ private: // Preprocess => actual result.. std::istringstream istr(filedata); std::map actual; - Preprocessor preprocessor( this ); + Preprocessor preprocessor( this ); preprocessor.preprocess( istr, actual, "" ); // Compare results.. @@ -301,7 +301,7 @@ private: // Preprocess => actual result.. std::istringstream istr(filedata); std::map actual; - Preprocessor preprocessor( this ); + Preprocessor preprocessor( this ); preprocessor.preprocess( istr, actual, "" ); // Compare results.. @@ -324,7 +324,7 @@ private: // Preprocess => actual result.. std::istringstream istr(filedata); std::map actual; - Preprocessor preprocessor( this ); + Preprocessor preprocessor( this ); preprocessor.preprocess( istr, actual, "" ); // Compare results.. @@ -344,7 +344,7 @@ private: // Preprocess => actual result.. std::istringstream istr(filedata); std::map actual; - Preprocessor preprocessor( this ); + Preprocessor preprocessor( this ); preprocessor.preprocess( istr, actual, "" ); // Compare results.. @@ -369,7 +369,7 @@ private: // Preprocess => actual result.. std::istringstream istr(filedata); std::map actual; - Preprocessor preprocessor( this ); + Preprocessor preprocessor( this ); preprocessor.preprocess( istr, actual, "" ); // Compare results.. @@ -389,7 +389,7 @@ private: // Preprocess => actual result.. std::istringstream istr(filedata); std::map actual; - Preprocessor preprocessor( this ); + Preprocessor preprocessor( this ); preprocessor.preprocess( istr, actual, "" ); // Compare results.. @@ -414,7 +414,7 @@ private: // Preprocess => actual result.. std::istringstream istr(filedata); std::map actual; - Preprocessor preprocessor( this ); + Preprocessor preprocessor( this ); preprocessor.preprocess( istr, actual, "" ); // Compare results.. @@ -434,7 +434,7 @@ private: // Preprocess => actual result.. std::istringstream istr(filedata); std::map actual; - Preprocessor preprocessor( this ); + Preprocessor preprocessor( this ); preprocessor.preprocess( istr, actual, "" ); // Compare results.. diff --git a/testrunner.cpp b/testrunner.cpp index 2e026ecbc..41cf6478b 100644 --- a/testrunner.cpp +++ b/testrunner.cpp @@ -15,13 +15,13 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see #include int main(int argc, const char *argv[]) -{ +{ TestFixture::runTests( (argc==2) ? argv[1] : NULL ); return 0; } diff --git a/testsimplifytokens.cpp b/testsimplifytokens.cpp index 231a807d0..ff6853c17 100644 --- a/testsimplifytokens.cpp +++ b/testsimplifytokens.cpp @@ -1,73 +1,73 @@ -/* - * c++check - c/c++ syntax checking - * Copyright (C) 2007 Daniel Marjamäki - * - * 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 -#include "testsuite.h" -#include "tokenize.h" -#include +extern std::ostringstream errout; -extern std::ostringstream errout; +class TestSimplifyTokens : public TestFixture +{ +public: + TestSimplifyTokens() : TestFixture("TestSimplifyTokens") + { } -class TestSimplifyTokens : public TestFixture -{ -public: - TestSimplifyTokens() : TestFixture("TestSimplifyTokens") - { } + +private: + void run() + { + TEST_CASE( cast0 ); + TEST_CASE( sizeof1 ); + } -private: + std::string tok(const char code[]) + { + std::istringstream istr(code); + Tokenizer tokenizer; + tokenizer.tokenize( istr, "test.cpp" ); + tokenizer.simplifyTokenList(); - void run() - { - TEST_CASE( cast0 ); - TEST_CASE( sizeof1 ); - } + std::string ret; + for ( const TOKEN *tok = tokenizer.tokens(); tok; tok = tok->next() ) + { + ret += std::string(tok->aaaa()) + " "; + } - std::string tok(const char code[]) - { - std::istringstream istr(code); - Tokenizer tokenizer; - tokenizer.tokenize( istr, "test.cpp" ); - tokenizer.simplifyTokenList(); + return ret; + } - std::string ret; - for ( const TOKEN *tok = tokenizer.tokens(); tok; tok = tok->next() ) - { - ret += std::string(tok->aaaa()) + " "; - } + void cast0() + { + const char code1[] = " if ( p == (char *)0 ) "; + const char code2[] = " if ( p == 0 ) "; + ASSERT_EQUALS( tok(code1), tok(code2) ); + } - return ret; - } + void sizeof1() + { + const char code1[] = " struct ABC *abc = malloc(sizeof(*abc)); "; + const char code2[] = " struct ABC *abc = malloc(100); "; + ASSERT_EQUALS( tok(code1), tok(code2) ); + } +}; - void cast0() - { - const char code1[] = " if ( p == (char *)0 ) "; - const char code2[] = " if ( p == 0 ) "; - ASSERT_EQUALS( tok(code1), tok(code2) ); - } - - void sizeof1() - { - const char code1[] = " struct ABC *abc = malloc(sizeof(*abc)); "; - const char code2[] = " struct ABC *abc = malloc(100); "; - ASSERT_EQUALS( tok(code1), tok(code2) ); - } -}; - -REGISTER_TEST( TestSimplifyTokens ) +REGISTER_TEST( TestSimplifyTokens ) diff --git a/testsuite.cpp b/testsuite.cpp index 06e096b59..e7d181a70 100644 --- a/testsuite.cpp +++ b/testsuite.cpp @@ -76,48 +76,48 @@ bool TestFixture::runTest(const char testname[]) std::cout << classname << "::" << testname << "\n"; return true; } - -static std::string writestr( const std::string &str ) -{ - std::ostringstream ostr; - ostr << "\""; - for (unsigned int i = 0; i < str.length(); ++i) - { - char ch = str[i]; - if ( ch == '\n' ) - ostr << "\\n"; - else if ( ch == '\t' ) - ostr << "\\t"; - else if ( ch == '\"' ) - ostr << "\\\""; - else - ostr << std::string(1, ch); - } - ostr << "\""; - return ostr.str(); -} + +static std::string writestr( const std::string &str ) +{ + std::ostringstream ostr; + ostr << "\""; + for (unsigned int i = 0; i < str.length(); ++i) + { + char ch = str[i]; + if ( ch == '\n' ) + ostr << "\\n"; + else if ( ch == '\t' ) + ostr << "\\t"; + else if ( ch == '\"' ) + ostr << "\\\""; + else + ostr << std::string(1, ch); + } + ostr << "\""; + return ostr.str(); +} void TestFixture::assertEquals(const char *filename, int linenr, const std::string &expected, const std::string &actual) -{ - if ( expected != actual ) +{ + if ( expected != actual ) { - errmsg << "Assertion failed in " << filename << " at line " << linenr << std::endl - << "Expected:" << std::endl - << writestr(expected) << std::endl - << "Actual:" << std::endl - << writestr(actual) << std::endl; + errmsg << "Assertion failed in " << filename << " at line " << linenr << std::endl + << "Expected:" << std::endl + << writestr(expected) << std::endl + << "Actual:" << std::endl + << writestr(actual) << std::endl; } } -void TestFixture::assertEquals(const char *filename, int linenr, unsigned int expected, unsigned int actual) -{ - std::ostringstream ostr1; - ostr1 << expected; - std::ostringstream ostr2; - ostr2 << actual; - assertEquals( filename, linenr, ostr1.str(), ostr2.str() ); +void TestFixture::assertEquals(const char *filename, int linenr, unsigned int expected, unsigned int actual) +{ + std::ostringstream ostr1; + ostr1 << expected; + std::ostringstream ostr2; + ostr2 << actual; + assertEquals( filename, linenr, ostr1.str(), ostr2.str() ); } - + void TestFixture::printTests() { const std::list &tests = TestRegistry::theInstance().tests(); @@ -160,7 +160,7 @@ void TestFixture::reportErr( const std::string &errmsg) errout << errmsg << std::endl; } -void TestFixture::reportOut( const std::string &outmsg) -{ - // These can probably be ignored -} +void TestFixture::reportOut( const std::string &outmsg) +{ + // These can probably be ignored +} diff --git a/testsuite.h b/testsuite.h index 5bcade02a..d47a5ea61 100644 --- a/testsuite.h +++ b/testsuite.h @@ -21,8 +21,8 @@ #include #include "errorlogger.h" - -class TOKEN; + +class TOKEN; class TestFixture : public ErrorLogger { @@ -40,10 +40,10 @@ protected: void assertEquals(const char *filename, int linenr, const std::string &expected, const std::string &actual); void assertEquals(const char *filename, int linenr, unsigned int expected, unsigned int actual); -public: - virtual void reportErr( const std::string &errmsg); +public: + virtual void reportErr( const std::string &errmsg); - virtual void reportOut( const std::string &outmsg); + virtual void reportOut( const std::string &outmsg); TestFixture(const std::string &_name); virtual ~TestFixture() { } diff --git a/testtokenize.cpp b/testtokenize.cpp index e3a21ccbf..4802e4510 100644 --- a/testtokenize.cpp +++ b/testtokenize.cpp @@ -21,10 +21,10 @@ // the code for a known configuration, it generates the code for each configuration. -#include +#include #include "testsuite.h" #define UNIT_TESTING // Get access to "private" data in Tokenizer -#include "tokenize.h" +#include "tokenize.h" extern std::ostringstream errout; class TestTokenizer : public TestFixture @@ -42,15 +42,15 @@ private: TEST_CASE( inlineasm ); - TEST_CASE( dupfuncname ); + TEST_CASE( dupfuncname ); - TEST_CASE( const_and_volatile_functions ); + TEST_CASE( const_and_volatile_functions ); - TEST_CASE( numeric_true_condition ); + TEST_CASE( numeric_true_condition ); - TEST_CASE( multi_compare ); + TEST_CASE( multi_compare ); - TEST_CASE( match1 ); + TEST_CASE( match1 ); TEST_CASE( varid1 ); } @@ -156,144 +156,144 @@ private: ASSERT_EQUALS( 1, static_cast(tokenizer._functionList.size()) ); ASSERT_EQUALS( std::string("b"), tokenizer._functionList[0]->aaaa() ); - } + } - void const_and_volatile_functions() - { - const char code[] = "class B\n\ - {\n\ - public:\n\ - void a();\n\ - void b() const;\n\ - void c() volatile;\n\ - };\n\ - \n\ - void B::a()\n\ - {}\n\ - \n\ - void B::b() const\n\ - {}\n\ - \n\ - void B::c() volatile\n\ - {}\n"; + void const_and_volatile_functions() + { + const char code[] = "class B\n\ + {\n\ + public:\n\ + void a();\n\ + void b() const;\n\ + void c() volatile;\n\ + };\n\ + \n\ + void B::a()\n\ + {}\n\ + \n\ + void B::b() const\n\ + {}\n\ + \n\ + void B::c() volatile\n\ + {}\n"; + + // tokenize.. + Tokenizer tokenizer; + std::istringstream istr(code); + tokenizer.tokenize(istr, "test.cpp"); - // tokenize.. - Tokenizer tokenizer; - std::istringstream istr(code); - tokenizer.tokenize(istr, "test.cpp"); + tokenizer.fillFunctionList(); - tokenizer.fillFunctionList(); + ASSERT_EQUALS( 3, static_cast(tokenizer._functionList.size()) ); + if( tokenizer._functionList.size() == 3 ) + { + ASSERT_EQUALS( std::string("a"), tokenizer._functionList[0]->str() ); + ASSERT_EQUALS( std::string("b"), tokenizer._functionList[1]->str() ); + ASSERT_EQUALS( std::string("c"), tokenizer._functionList[2]->str() ); + } + } - ASSERT_EQUALS( 3, static_cast(tokenizer._functionList.size()) ); - if( tokenizer._functionList.size() == 3 ) - { - ASSERT_EQUALS( std::string("a"), tokenizer._functionList[0]->str() ); - ASSERT_EQUALS( std::string("b"), tokenizer._functionList[1]->str() ); - ASSERT_EQUALS( std::string("c"), tokenizer._functionList[2]->str() ); - } - } + + void numeric_true_condition() + { + const char code[] = "void f()\n" + "{\n" + " if (5==5);\n" + "}\n"; + // tokenize.. + Tokenizer tokenizer; + std::istringstream istr(code); + tokenizer.tokenize(istr, "test.cpp"); - void numeric_true_condition() - { - const char code[] = "void f()\n" - "{\n" - " if (5==5);\n" - "}\n"; + tokenizer.simplifyTokenList(); - // tokenize.. - Tokenizer tokenizer; - std::istringstream istr(code); - tokenizer.tokenize(istr, "test.cpp"); + std::ostringstream ostr; + for (const TOKEN *tok = tokenizer.tokens(); tok; tok = tok->next()) + ostr << " " << tok->str(); + ASSERT_EQUALS( std::string(" void f ( ) { if ( true ) ; }"), ostr.str() ); + } - tokenizer.simplifyTokenList(); + void multi_compare() + { + // Test for found + ASSERT_EQUALS( 1, TOKEN::multiCompare( "one|two", "one" ) ); + ASSERT_EQUALS( 1, TOKEN::multiCompare( "one|two", "two" ) ); + ASSERT_EQUALS( 1, TOKEN::multiCompare( "verybig|two|", "two" ) ); - std::ostringstream ostr; - for (const TOKEN *tok = tokenizer.tokens(); tok; tok = tok->next()) - ostr << " " << tok->str(); - ASSERT_EQUALS( std::string(" void f ( ) { if ( true ) ; }"), ostr.str() ); - } + // Test for empty string found + ASSERT_EQUALS( 0, TOKEN::multiCompare( "|one|two", "notfound" ) ); + ASSERT_EQUALS( 0, TOKEN::multiCompare( "one||two", "notfound" ) ); + ASSERT_EQUALS( 0, TOKEN::multiCompare( "one|two|", "notfound" ) ); - void multi_compare() - { - // Test for found - ASSERT_EQUALS( 1, TOKEN::multiCompare( "one|two", "one" ) ); - ASSERT_EQUALS( 1, TOKEN::multiCompare( "one|two", "two" ) ); - ASSERT_EQUALS( 1, TOKEN::multiCompare( "verybig|two|", "two" ) ); + // Test for not found + ASSERT_EQUALS( -1, TOKEN::multiCompare( "one|two", "notfound" ) ); + ASSERT_EQUALS( -1, TOKEN::multiCompare( "verybig|two", "s" ) ); + ASSERT_EQUALS( -1, TOKEN::multiCompare( "one|two", "ne" ) ); + ASSERT_EQUALS( -1, TOKEN::multiCompare( "abc|def", "a" ) ); + } - // Test for empty string found - ASSERT_EQUALS( 0, TOKEN::multiCompare( "|one|two", "notfound" ) ); - ASSERT_EQUALS( 0, TOKEN::multiCompare( "one||two", "notfound" ) ); - ASSERT_EQUALS( 0, TOKEN::multiCompare( "one|two|", "notfound" ) ); + void match1() + { + // Match "%var% | %var%" + { + const std::string code("abc|def"); - // Test for not found - ASSERT_EQUALS( -1, TOKEN::multiCompare( "one|two", "notfound" ) ); - ASSERT_EQUALS( -1, TOKEN::multiCompare( "verybig|two", "s" ) ); - ASSERT_EQUALS( -1, TOKEN::multiCompare( "one|two", "ne" ) ); - ASSERT_EQUALS( -1, TOKEN::multiCompare( "abc|def", "a" ) ); - } + // tokenize.. + Tokenizer tokenizer; + std::istringstream istr(code); + tokenizer.tokenize(istr, "test.cpp"); - void match1() - { - // Match "%var% | %var%" - { - const std::string code("abc|def"); + // Match.. + ASSERT_EQUALS( true, TOKEN::Match(tokenizer.tokens(), "%var% | %var%") ); + } - // tokenize.. - Tokenizer tokenizer; - std::istringstream istr(code); - tokenizer.tokenize(istr, "test.cpp"); + // Match "%var% || %var%" + { + const std::string code("abc||def"); - // Match.. - ASSERT_EQUALS( true, TOKEN::Match(tokenizer.tokens(), "%var% | %var%") ); - } + // tokenize.. + Tokenizer tokenizer; + std::istringstream istr(code); + tokenizer.tokenize(istr, "test.cpp"); - // Match "%var% || %var%" - { - const std::string code("abc||def"); + // Match.. + ASSERT_EQUALS( true, TOKEN::Match(tokenizer.tokens(), "%var% || %var%") ); + } + } - // tokenize.. - Tokenizer tokenizer; - std::istringstream istr(code); - tokenizer.tokenize(istr, "test.cpp"); + + void varid1() + { + const std::string code(";static int i = 1;\n" + "void f()\n" + "{\n" + " int i = 2;\n" + " for (int i = 0; i < 10; ++i)\n" + " i = 3;\n" + " i = 4;\n" + "}\n" ); - // Match.. - ASSERT_EQUALS( true, TOKEN::Match(tokenizer.tokens(), "%var% || %var%") ); - } - } + // tokenize.. + Tokenizer tokenizer; + std::istringstream istr(code); + tokenizer.tokenize(istr, "test.cpp"); + tokenizer.setVarId(); - - void varid1() - { - const std::string code(";static int i = 1;\n" - "void f()\n" - "{\n" - " int i = 2;\n" - " for (int i = 0; i < 10; ++i)\n" - " i = 3;\n" - " i = 4;\n" - "}\n" ); - - // tokenize.. - Tokenizer tokenizer; - std::istringstream istr(code); - tokenizer.tokenize(istr, "test.cpp"); - tokenizer.setVarId(); - - for ( const TOKEN *tok = tokenizer.tokens(); tok; tok = tok->next() ) - { - if ( tok->str() != "i" ) - ASSERT_EQUALS( 0, tok->varId() ); - else if ( TOKEN::Match(tok, "i = 1") ) - ASSERT_EQUALS( 1, tok->varId() ); - else if ( TOKEN::Match(tok, "i = 2") ) - ASSERT_EQUALS( 2, tok->varId() ); - else if ( TOKEN::Match(tok, "i = 3") ) - ASSERT_EQUALS( 3, tok->varId() ); - else if ( TOKEN::Match(tok, "i = 4") ) - ASSERT_EQUALS( 2, tok->varId() ); - } + for ( const TOKEN *tok = tokenizer.tokens(); tok; tok = tok->next() ) + { + if ( tok->str() != "i" ) + ASSERT_EQUALS( 0, tok->varId() ); + else if ( TOKEN::Match(tok, "i = 1") ) + ASSERT_EQUALS( 1, tok->varId() ); + else if ( TOKEN::Match(tok, "i = 2") ) + ASSERT_EQUALS( 2, tok->varId() ); + else if ( TOKEN::Match(tok, "i = 3") ) + ASSERT_EQUALS( 3, tok->varId() ); + else if ( TOKEN::Match(tok, "i = 4") ) + ASSERT_EQUALS( 2, tok->varId() ); + } } }; diff --git a/testunusedvar.cpp b/testunusedvar.cpp index b4960d68b..337df9302 100644 --- a/testunusedvar.cpp +++ b/testunusedvar.cpp @@ -1,184 +1,184 @@ -/* - * c++check - c/c++ syntax checking - * Copyright (C) 2007 Daniel Marjamäki - * - * 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 +extern std::ostringstream errout; -#include -extern std::ostringstream errout; +class TestUnusedVar : public TestFixture +{ +public: + TestUnusedVar() : TestFixture("TestUnusedVar") + { } -class TestUnusedVar : public TestFixture -{ -public: - TestUnusedVar() : TestFixture("TestUnusedVar") - { } +private: + void check( const char code[] ) + { + // Tokenize.. + Tokenizer tokenizer; + std::istringstream istr(code); + tokenizer.tokenize( istr, "test.cpp" ); + tokenizer.simplifyTokenList(); -private: - void check( const char code[] ) - { - // Tokenize.. - Tokenizer tokenizer; - std::istringstream istr(code); - tokenizer.tokenize( istr, "test.cpp" ); - tokenizer.simplifyTokenList(); + // Clear the error buffer.. + errout.str(""); - // Clear the error buffer.. - errout.str(""); + // Check for unused variables.. + CheckOther checkOther( &tokenizer, this ); + checkOther.CheckStructMemberUsage(); + } - // Check for unused variables.. - CheckOther checkOther( &tokenizer, this ); - checkOther.CheckStructMemberUsage(); - } + void run() + { + TEST_CASE( structmember1 ); + TEST_CASE( structmember2 ); + TEST_CASE( structmember3 ); - void run() - { - TEST_CASE( structmember1 ); - TEST_CASE( structmember2 ); - TEST_CASE( structmember3 ); + TEST_CASE( localvar1 ); + TEST_CASE( localvar2 ); + TEST_CASE( localvar3 ); + TEST_CASE( localvar4 ); + } - TEST_CASE( localvar1 ); - TEST_CASE( localvar2 ); - TEST_CASE( localvar3 ); - TEST_CASE( localvar4 ); - } + void structmember1() + { + check( "struct abc\n" + "{\n" + " int a;\n" + " int b;\n" + " int c;\n" + "};\n" ); + ASSERT_EQUALS( std::string("[test.cpp:2]: struct member 'abc::a' is never read\n" + "[test.cpp:3]: struct member 'abc::b' is never read\n" + "[test.cpp:4]: struct member 'abc::c' is never read\n"), errout.str() ); + } - void structmember1() - { - check( "struct abc\n" - "{\n" - " int a;\n" - " int b;\n" - " int c;\n" - "};\n" ); - ASSERT_EQUALS( std::string("[test.cpp:2]: struct member 'abc::a' is never read\n" - "[test.cpp:3]: struct member 'abc::b' is never read\n" - "[test.cpp:4]: struct member 'abc::c' is never read\n"), errout.str() ); - } + void structmember2() + { + check( "struct ABC\n" + "{\n" + " int a;\n" + " int b;\n" + " int c;\n" + "};\n" + "\n" + "void foo()\n" + "{\n" + " struct ABC abc;\n" + " int a = abc.a;\n" + " int b = abc.b;\n" + " int c = abc.c;\n" + "}\n" ); + ASSERT_EQUALS( std::string(""), errout.str() ); + } - void structmember2() - { - check( "struct ABC\n" - "{\n" - " int a;\n" - " int b;\n" - " int c;\n" - "};\n" - "\n" - "void foo()\n" - "{\n" - " struct ABC abc;\n" - " int a = abc.a;\n" - " int b = abc.b;\n" - " int c = abc.c;\n" - "}\n" ); - ASSERT_EQUALS( std::string(""), errout.str() ); - } + void structmember3() + { + check( "struct ABC\n" + "{\n" + " int a;\n" + " int b;\n" + " int c;\n" + "};\n" + "\n" + "static struct ABC abc[] = { {1, 2, 3} };\n" + "\n" + "void foo()\n" + "{\n" + " int a = abc[0].a;\n" + " int b = abc[0].b;\n" + " int c = abc[0].c;\n" + "}\n" ); + ASSERT_EQUALS( std::string(""), errout.str() ); + } - void structmember3() - { - check( "struct ABC\n" - "{\n" - " int a;\n" - " int b;\n" - " int c;\n" - "};\n" - "\n" - "static struct ABC abc[] = { {1, 2, 3} };\n" - "\n" - "void foo()\n" - "{\n" - " int a = abc[0].a;\n" - " int b = abc[0].b;\n" - " int c = abc[0].c;\n" - "}\n" ); - ASSERT_EQUALS( std::string(""), errout.str() ); - } + + + void functionVariableUsage( const char code[] ) + { + // Tokenize.. + Tokenizer tokenizer; + std::istringstream istr(code); + tokenizer.tokenize( istr, "test.cpp" ); + tokenizer.simplifyTokenList(); + // Clear the error buffer.. + errout.str(""); + // Check for unused variables.. + CheckOther checkOther( &tokenizer, this ); + checkOther.functionVariableUsage(); + } - void functionVariableUsage( const char code[] ) - { - // Tokenize.. - Tokenizer tokenizer; - std::istringstream istr(code); - tokenizer.tokenize( istr, "test.cpp" ); - tokenizer.simplifyTokenList(); + void localvar1() + { + functionVariableUsage( "void foo()\n" + "{\n" + " int i = 0;\n" + "}\n" ); + ASSERT_EQUALS( std::string("[test.cpp:2]: Variable 'i' is assigned a value that is never used\n"), errout.str() ); + } - // Clear the error buffer.. - errout.str(""); + void localvar2() + { + functionVariableUsage( "void foo()\n" + "{\n" + " int i;\n" + " return i;\n" + "}\n" ); + ASSERT_EQUALS( std::string("[test.cpp:2]: Variable 'i' is not assigned a value\n"), errout.str() ); + } - // Check for unused variables.. - CheckOther checkOther( &tokenizer, this ); - checkOther.functionVariableUsage(); - } + void localvar3() + { + functionVariableUsage( "void foo()\n" + "{\n" + " int i;\n" + " if ( abc )\n" + " ;\n" + " else i = 0;\n" + "}\n" ); + ASSERT_EQUALS( std::string("[test.cpp:2]: Variable 'i' is assigned a value that is never used\n"), errout.str() ); + } - void localvar1() - { - functionVariableUsage( "void foo()\n" - "{\n" - " int i = 0;\n" - "}\n" ); - ASSERT_EQUALS( std::string("[test.cpp:2]: Variable 'i' is assigned a value that is never used\n"), errout.str() ); - } + void localvar4() + { + functionVariableUsage( "void foo()\n" + "{\n" + " int i = 0;\n" + " f(i);\n" + "}\n" ); + ASSERT_EQUALS( std::string(""), errout.str() ); + } - void localvar2() - { - functionVariableUsage( "void foo()\n" - "{\n" - " int i;\n" - " return i;\n" - "}\n" ); - ASSERT_EQUALS( std::string("[test.cpp:2]: Variable 'i' is not assigned a value\n"), errout.str() ); - } - - void localvar3() - { - functionVariableUsage( "void foo()\n" - "{\n" - " int i;\n" - " if ( abc )\n" - " ;\n" - " else i = 0;\n" - "}\n" ); - ASSERT_EQUALS( std::string("[test.cpp:2]: Variable 'i' is assigned a value that is never used\n"), errout.str() ); - } - - void localvar4() - { - functionVariableUsage( "void foo()\n" - "{\n" - " int i = 0;\n" - " f(i);\n" - "}\n" ); - ASSERT_EQUALS( std::string(""), errout.str() ); - } - - -}; - -REGISTER_TEST( TestUnusedVar ) + +}; +REGISTER_TEST( TestUnusedVar ) + diff --git a/token.cpp b/token.cpp index f45b2714d..f7cf8835a 100644 --- a/token.cpp +++ b/token.cpp @@ -28,10 +28,10 @@ TOKEN::TOKEN() { _fileIndex = 0; - _cstr = 0; + _cstr = 0; _str = ""; _linenr = 0; - _next = 0; + _next = 0; _varId = 0; _isName = false; _isNumber = false; @@ -43,7 +43,7 @@ TOKEN::~TOKEN() } void TOKEN::setstr( const char s[] ) -{ +{ _str = s; std::free(_cstr); #ifndef _MSC_VER @@ -90,55 +90,55 @@ const char *TOKEN::strAt(int index) const const TOKEN *tok = this->tokAt(index); return tok ? tok->_cstr : ""; } + +int TOKEN::multiCompare( const char *needle, const char *haystack ) +{ + bool emptyStringFound = false; + bool findNextOr = false; + const char *haystackPointer = haystack; + for( ; *needle; ++needle ) + { + if( *needle == '|' ) + { + // If needle and haystack are both at the end, we have a match. + if( *haystackPointer == 0 ) + return 1; -int TOKEN::multiCompare( const char *needle, const char *haystack ) -{ - bool emptyStringFound = false; - bool findNextOr = false; - const char *haystackPointer = haystack; - for( ; *needle; ++needle ) - { - if( *needle == '|' ) - { - // If needle and haystack are both at the end, we have a match. - if( *haystackPointer == 0 ) - return 1; + haystackPointer = haystack; + if( findNextOr ) + findNextOr = false; + else + emptyStringFound = true; - haystackPointer = haystack; - if( findNextOr ) - findNextOr = false; - else - emptyStringFound = true; + continue; + } - continue; - } + if( findNextOr ) + continue; - if( findNextOr ) - continue; + // If haystack and needle don't share the same character, reset + // haystackpointer and find next '|' character. + if( *haystackPointer != *needle ) + { + haystackPointer = haystack; + findNextOr = true; + continue; + } - // If haystack and needle don't share the same character, reset - // haystackpointer and find next '|' character. - if( *haystackPointer != *needle ) - { - haystackPointer = haystack; - findNextOr = true; - continue; - } + // All characters in haystack and needle have matched this far + haystackPointer++; + } - // All characters in haystack and needle have matched this far - haystackPointer++; - } + // If both needle and haystack are at the end, then we have a match. + if( *haystackPointer == 0 ) + return 1; - // If both needle and haystack are at the end, then we have a match. - if( *haystackPointer == 0 ) - return 1; + // If empty string was found or if last character in needle was '|' + if( emptyStringFound || findNextOr == false ) + return 0; - // If empty string was found or if last character in needle was '|' - if( emptyStringFound || findNextOr == false ) - return 0; - - return -1; -} + return -1; +} bool TOKEN::Match(const TOKEN *tok, const char pattern[], const char *varname1[], const char *varname2[]) @@ -153,7 +153,7 @@ bool TOKEN::Match(const TOKEN *tok, const char pattern[], const char *varname1[] while ( *p == ' ' ) p++; - // Extract token from pattern.. + // Extract token from pattern.. // TODO: Refactor this so there can't be buffer overflows char str[500]; char *s = str; @@ -175,11 +175,11 @@ bool TOKEN::Match(const TOKEN *tok, const char pattern[], const char *varname1[] { if (!tok->isName()) return false; - } + } - // Accept any token - else if (strcmp(str,"%any%")==0 ) - { + // Accept any token + else if (strcmp(str,"%any%")==0 ) + { } @@ -229,22 +229,22 @@ bool TOKEN::Match(const TOKEN *tok, const char pattern[], const char *varname1[] if ( strchr( str + 1, tok->_str[0] ) == 0 ) return false; } - - // Parse multi options, such as void|int|char (accept token which is one of these 3) - else if ( strchr(str, '|') && strlen( str ) > 2 ) - { - int res = multiCompare( str, tok->_cstr ); - if( res == 0 ) - { - // Empty alternative matches, use the same token on next round - continue; - } - else if( res == -1 ) - { - // No match - return false; - } - } + + // Parse multi options, such as void|int|char (accept token which is one of these 3) + else if ( strchr(str, '|') && strlen( str ) > 2 ) + { + int res = multiCompare( str, tok->_cstr ); + if( res == 0 ) + { + // Empty alternative matches, use the same token on next round + continue; + } + else if( res == -1 ) + { + // No match + return false; + } + } else if (str != tok->_str) return false; @@ -269,7 +269,7 @@ bool TOKEN::isNumber() const } bool TOKEN::isStandardType() const -{ +{ bool ret = false; const char *type[] = {"bool","char","short","int","long","float","double",0}; for (int i = 0; type[i]; i++) @@ -309,43 +309,43 @@ const TOKEN *TOKEN::findtoken(const TOKEN *tok1, const char *tokenstr[]) } return NULL; } + +unsigned int TOKEN::varId() const +{ + return _varId; +} -unsigned int TOKEN::varId() const -{ - return _varId; -} +void TOKEN::varId( unsigned int id ) +{ + _varId = id; +} -void TOKEN::varId( unsigned int id ) -{ - _varId = id; -} +TOKEN *TOKEN::next() const +{ + return _next; +} -TOKEN *TOKEN::next() const -{ - return _next; -} +void TOKEN::next( TOKEN *next ) +{ + _next = next; +} -void TOKEN::next( TOKEN *next ) -{ - _next = next; -} +unsigned int TOKEN::fileIndex() const +{ + return _fileIndex; +} -unsigned int TOKEN::fileIndex() const -{ - return _fileIndex; -} +void TOKEN::fileIndex( unsigned int fileIndex ) +{ + _fileIndex = fileIndex; +} -void TOKEN::fileIndex( unsigned int fileIndex ) -{ - _fileIndex = fileIndex; -} +unsigned int TOKEN::linenr() const +{ + return _linenr; +} -unsigned int TOKEN::linenr() const -{ - return _linenr; -} - -void TOKEN::linenr( unsigned int linenr ) -{ - _linenr = linenr; -} +void TOKEN::linenr( unsigned int linenr ) +{ + _linenr = linenr; +} diff --git a/token.h b/token.h index 8b2ad6e8f..87cdcaf99 100644 --- a/token.h +++ b/token.h @@ -1,138 +1,138 @@ -/* - * 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 +#include -class TOKEN -{ -public: - TOKEN(); - ~TOKEN(); - void setstr( const char s[] ); +class TOKEN +{ +public: + TOKEN(); + ~TOKEN(); + void setstr( const char s[] ); - const std::string &str() const - { return _str; } + const std::string &str() const + { return _str; } - const char *aaaa() const - { return _cstr; } + const char *aaaa() const + { return _cstr; } - char aaaa0() const - { return _cstr[0]; } + char aaaa0() const + { return _cstr[0]; } - char aaaa1() const - { return _cstr[1]; } + char aaaa1() const + { return _cstr[1]; } + + /** + * Combine two tokens that belong to each other. + * Ex: "<" and "=" may become "<=" + */ + void combineWithNext(const char str1[], const char str2[]); - /** - * Combine two tokens that belong to each other. - * Ex: "<" and "=" may become "<=" - */ - void combineWithNext(const char str1[], const char str2[]); + /** + * Unlink and delete next token. + */ + void deleteNext(); - /** - * Unlink and delete next token. - */ - void deleteNext(); + /** + * Returns token in given index, related to this token. + * For example index 1 would return next token, and 2 + * would return next from that one. + */ + const TOKEN *tokAt(int index) const; - /** - * Returns token in given index, related to this token. - * For example index 1 would return next token, and 2 - * would return next from that one. - */ - const TOKEN *tokAt(int index) const; + const char *strAt(int index) const; - const char *strAt(int index) const; + /** + * Match given token (or list of tokens) to a pattern list. + * + * Possible patterns + * "%any%" any token + * "%var%" any token which is a name or type e.g. "hello" or "int" + * "%num%" Any numeric token, e.g. "23" + * "%str%" Any token starting with "-character (C-string). + * "[abc]" Any of the characters 'a' or 'b' or 'c' + * "int|void|char" Any of the strings, int, void or char + * "int|void|char|" Any of the strings, int, void or char or empty string + * "someRandomText" If token contains "someRandomText". + * + * The patterns can be also combined to compare to multiple tokens at once + * by separating tokens with a space, e.g. + * ") const|void {" will return true if first token is ')' next token is either + * "const" or "void" and token after that is '{'. If even one of the tokens does not + * match its pattern, false is returned. + * + * @param tok List of tokens to be compared to the pattern + * @param pattern The pattern where tokens are compared, e.g. "const" + * or ") const|volatile| {". + * @param varname1 Used with pattern "%var1%" and "%var2%" + * @param varname2 Used with pattern "%var1%" and "%var2%" + * @return true if given token matches with given pattern + * false if given token does not match with given pattern + */ + static bool Match(const TOKEN *tok, const char pattern[], const char *varname1[]=0, const char *varname2[]=0); - /** - * Match given token (or list of tokens) to a pattern list. - * - * Possible patterns - * "%any%" any token - * "%var%" any token which is a name or type e.g. "hello" or "int" - * "%num%" Any numeric token, e.g. "23" - * "%str%" Any token starting with "-character (C-string). - * "[abc]" Any of the characters 'a' or 'b' or 'c' - * "int|void|char" Any of the strings, int, void or char - * "int|void|char|" Any of the strings, int, void or char or empty string - * "someRandomText" If token contains "someRandomText". - * - * The patterns can be also combined to compare to multiple tokens at once - * by separating tokens with a space, e.g. - * ") const|void {" will return true if first token is ')' next token is either - * "const" or "void" and token after that is '{'. If even one of the tokens does not - * match its pattern, false is returned. - * - * @param tok List of tokens to be compared to the pattern - * @param pattern The pattern where tokens are compared, e.g. "const" - * or ") const|volatile| {". - * @param varname1 Used with pattern "%var1%" and "%var2%" - * @param varname2 Used with pattern "%var1%" and "%var2%" - * @return true if given token matches with given pattern - * false if given token does not match with given pattern - */ - static bool Match(const TOKEN *tok, const char pattern[], const char *varname1[]=0, const char *varname2[]=0); + bool isName() const; + bool isNumber() const; + bool isStandardType() const; + static const TOKEN *findmatch(const TOKEN *tok, const char pattern[], const char *varname1[]=0, const char *varname2[]=0); + static const TOKEN *findtoken(const TOKEN *tok1, const char *tokenstr[]); - bool isName() const; - bool isNumber() const; - bool isStandardType() const; - static const TOKEN *findmatch(const TOKEN *tok, const char pattern[], const char *varname1[]=0, const char *varname2[]=0); - static const TOKEN *findtoken(const TOKEN *tok1, const char *tokenstr[]); + /** + * Needle is build from multiple alternatives. If one of + * them is equal to haystack, return value is 1. If there + * are no matches, but one alternative to needle is empty + * string, return value is 0. If needle was not found, return + * value is -1. + * + * @param needle e.g. "one|two" or "|one|two" + * @param haystack e.g. "one", "two" or "invalid" + * @return 1 if needle is found from the haystack + * 0 if needle was empty string + * -1 if needle was not found + */ + static int multiCompare( const char *needle, const char *haystack ); - /** - * Needle is build from multiple alternatives. If one of - * them is equal to haystack, return value is 1. If there - * are no matches, but one alternative to needle is empty - * string, return value is 0. If needle was not found, return - * value is -1. - * - * @param needle e.g. "one|two" or "|one|two" - * @param haystack e.g. "one", "two" or "invalid" - * @return 1 if needle is found from the haystack - * 0 if needle was empty string - * -1 if needle was not found - */ - static int multiCompare( const char *needle, const char *haystack ); + + unsigned int linenr() const; + void linenr( unsigned int linenr ); + unsigned int fileIndex() const; + void fileIndex( unsigned int fileIndex ); - unsigned int linenr() const; - void linenr( unsigned int linenr ); + TOKEN *next() const; + void next( TOKEN *next ); - unsigned int fileIndex() const; - void fileIndex( unsigned int fileIndex ); + unsigned int varId() const; + void varId( unsigned int id ); - TOKEN *next() const; - void next( TOKEN *next ); +private: + std::string _str; + char * _cstr; + bool _isName; + bool _isNumber; + unsigned int _varId; + TOKEN *_next; + unsigned int _fileIndex; + unsigned int _linenr; +}; - unsigned int varId() const; - void varId( unsigned int id ); - -private: - std::string _str; - char * _cstr; - bool _isName; - bool _isNumber; - unsigned int _varId; - TOKEN *_next; - unsigned int _fileIndex; - unsigned int _linenr; -}; - -#endif // TOKEN_H +#endif // TOKEN_H diff --git a/tokenize.cpp b/tokenize.cpp index f1d320fee..c74b66296 100644 --- a/tokenize.cpp +++ b/tokenize.cpp @@ -72,7 +72,7 @@ TOKEN *Tokenizer::_gettok(TOKEN *tok, int index) index--; } return tok; -} +} //--------------------------------------------------------------------------- @@ -454,9 +454,9 @@ void Tokenizer::tokenizeCode(std::istream &code, const unsigned int FileIndex) do { // Append token.. - CurrentToken += c; + CurrentToken += c; - if ( c == '\n' ) + if ( c == '\n' ) ++lineno; // Special sequence '\.' @@ -599,76 +599,76 @@ void Tokenizer::tokenizeCode(std::istream &code, const unsigned int FileIndex) break; } } - } + } - // Remove "volatile" - while ( TOKEN::Match(_tokens, "volatile") ) - { - TOKEN *tok = _tokens; - _tokens = _tokens->next(); - delete tok; - } - for ( TOKEN *tok = _tokens; tok; tok = tok->next() ) - { - while ( TOKEN::Match(tok->next(), "volatile") ) - { - tok->deleteNext(); - } + // Remove "volatile" + while ( TOKEN::Match(_tokens, "volatile") ) + { + TOKEN *tok = _tokens; + _tokens = _tokens->next(); + delete tok; + } + for ( TOKEN *tok = _tokens; tok; tok = tok->next() ) + { + while ( TOKEN::Match(tok->next(), "volatile") ) + { + tok->deleteNext(); + } } } //--------------------------------------------------------------------------- + +void Tokenizer::setVarId() +{ + // Clear all variable ids + for ( TOKEN *tok = _tokens; tok; tok = tok->next() ) + tok->varId( 0 ); -void Tokenizer::setVarId() -{ - // Clear all variable ids - for ( TOKEN *tok = _tokens; tok; tok = tok->next() ) - tok->varId( 0 ); + // Set variable ids.. + unsigned int _varId = 0; + for ( TOKEN *tok = _tokens; tok; tok = tok->next() ) + { + if ( ! TOKEN::Match(tok, "[;{}(] %type% %var%") ) + continue; - // Set variable ids.. - unsigned int _varId = 0; - for ( TOKEN *tok = _tokens; tok; tok = tok->next() ) - { - if ( ! TOKEN::Match(tok, "[;{}(] %type% %var%") ) - continue; + // Determine name of declared variable.. + const char *varname = 0; + TOKEN *tok2 = tok->next(); + while ( ! TOKEN::Match( tok2, "[;[=(]" ) ) + { + if ( tok2->isName() ) + varname = tok2->strAt(0); + else if ( tok2->str() != "*" ) + break; + tok2 = tok2->next(); + } - // Determine name of declared variable.. - const char *varname = 0; - TOKEN *tok2 = tok->next(); - while ( ! TOKEN::Match( tok2, "[;[=(]" ) ) - { - if ( tok2->isName() ) - varname = tok2->strAt(0); - else if ( tok2->str() != "*" ) - break; - tok2 = tok2->next(); - } - - // Variable declaration found => Set variable ids - if ( TOKEN::Match(tok2, "[;[=]") && varname ) - { - ++_varId; - int indentlevel = 0; - int parlevel = 0; - for ( tok2 = tok->next(); tok2 && indentlevel >= 0; tok2 = tok2->next() ) - { - if ( tok2->str() == varname ) - tok2->varId( _varId ); - else if ( tok2->str() == "{" ) - ++indentlevel; - else if ( tok2->str() == "}" ) - --indentlevel; - else if ( tok2->str() == "(" ) - ++parlevel; - else if ( tok2->str() == ")" ) - --parlevel; - else if ( parlevel < 0 && tok2->str() == ";" ) - break; - } - } - } -} + // Variable declaration found => Set variable ids + if ( TOKEN::Match(tok2, "[;[=]") && varname ) + { + ++_varId; + int indentlevel = 0; + int parlevel = 0; + for ( tok2 = tok->next(); tok2 && indentlevel >= 0; tok2 = tok2->next() ) + { + if ( tok2->str() == varname ) + tok2->varId( _varId ); + else if ( tok2->str() == "{" ) + ++indentlevel; + else if ( tok2->str() == "}" ) + --indentlevel; + else if ( tok2->str() == "(" ) + ++parlevel; + else if ( tok2->str() == ")" ) + --parlevel; + else if ( parlevel < 0 && tok2->str() == ";" ) + break; + } + } + } +} //--------------------------------------------------------------------------- @@ -682,7 +682,7 @@ void Tokenizer::simplifyTokenList() for ( TOKEN *tok = _tokens; tok; tok = tok->next() ) { if (tok->next() && (tok->next()->str() == "unsigned")) - { + { tok->deleteNext(); } } @@ -834,7 +834,7 @@ void Tokenizer::simplifyTokenList() done = false; } - // (1-2) + // (1-2) if (TOKEN::Match(tok, "[[,(=<>] %num% [+-*/] %num% [],);=<>]")) { int i1 = atoi(tok->strAt(1)); @@ -911,20 +911,20 @@ void Tokenizer::simplifyTokenList() unsigned int typelen = 0; if ( TOKEN::Match(type0, "%type% %var% ,|=") ) - { - if ( type0->next()->str() != "operator" ) + { + if ( type0->next()->str() != "operator" ) { tok2 = _gettok(type0, 2); // The ',' or '=' token - typelen = 1; + typelen = 1; } } else if ( TOKEN::Match(type0, "%type% * %var% ,|=") ) - { - if ( type0->next()->next()->str() != "operator" ) + { + if ( type0->next()->next()->str() != "operator" ) { tok2 = _gettok(type0, 3); // The ',' token - typelen = 1; + typelen = 1; } } @@ -1058,42 +1058,42 @@ bool Tokenizer::simplifyConditions() { tok->next()->setstr((tok->next()->str() != "0") ? "true" : "false"); ret = false; - } + } - // Reduce "(%num% == %num%)" => "(true)"/"(false)" - if ( (TOKEN::Match(tok, "&&") || TOKEN::Match(tok, "||") || TOKEN::Match(tok, "(")) && - TOKEN::Match(tok->tokAt(1), "%num% %any% %num%") && - (TOKEN::Match(tok->tokAt(4), "&&") || TOKEN::Match(tok->tokAt(4), "||") || TOKEN::Match(tok->tokAt(4), ")")) ) - { - double op1 = (strstr(tok->strAt(1), "0x")) ? strtol(tok->strAt(1),0,16) : atof( tok->strAt(1) ); - double op2 = (strstr(tok->strAt(3), "0x")) ? strtol(tok->strAt(3),0,16) : atof( tok->strAt(3) ); - std::string cmp = tok->strAt(2); + // Reduce "(%num% == %num%)" => "(true)"/"(false)" + if ( (TOKEN::Match(tok, "&&") || TOKEN::Match(tok, "||") || TOKEN::Match(tok, "(")) && + TOKEN::Match(tok->tokAt(1), "%num% %any% %num%") && + (TOKEN::Match(tok->tokAt(4), "&&") || TOKEN::Match(tok->tokAt(4), "||") || TOKEN::Match(tok->tokAt(4), ")")) ) + { + double op1 = (strstr(tok->strAt(1), "0x")) ? strtol(tok->strAt(1),0,16) : atof( tok->strAt(1) ); + double op2 = (strstr(tok->strAt(3), "0x")) ? strtol(tok->strAt(3),0,16) : atof( tok->strAt(3) ); + std::string cmp = tok->strAt(2); - bool result = false; - if ( cmp == "==" ) - result = (op1 == op2); - else if ( cmp == "!=" ) - result = (op1 != op2); - else if ( cmp == ">=" ) - result = (op1 >= op2); - else if ( cmp == ">" ) - result = (op1 > op2); - else if ( cmp == "<=" ) - result = (op1 <= op2); - else if ( cmp == "<" ) - result = (op1 < op2); - else - cmp = ""; + bool result = false; + if ( cmp == "==" ) + result = (op1 == op2); + else if ( cmp == "!=" ) + result = (op1 != op2); + else if ( cmp == ">=" ) + result = (op1 >= op2); + else if ( cmp == ">" ) + result = (op1 > op2); + else if ( cmp == "<=" ) + result = (op1 <= op2); + else if ( cmp == "<" ) + result = (op1 < op2); + else + cmp = ""; - if ( ! cmp.empty() ) - { - tok = tok->next(); - tok->deleteNext(); - tok->deleteNext(); + if ( ! cmp.empty() ) + { + tok = tok->next(); + tok->deleteNext(); + tok->deleteNext(); - tok->setstr( result ? "true" : "false" ); - ret = false; - } + tok->setstr( result ? "true" : "false" ); + ret = false; + } } } @@ -1169,12 +1169,12 @@ void Tokenizer::fillFunctionList() } else if ( tok2->str() == ")" ) - { - if ( TOKEN::Match(tok2, ") const| {") ) - { - _functionList.push_back( tok ); - tok = tok2; - } + { + if ( TOKEN::Match(tok2, ") const| {") ) + { + _functionList.push_back( tok ); + tok = tok2; + } else { tok = tok2; @@ -1190,7 +1190,7 @@ void Tokenizer::fillFunctionList() // If the _functionList functions with duplicate names, remove them // TODO this will need some better handling for ( unsigned int func1 = 0; func1 < _functionList.size(); ) - { + { bool hasDuplicates = false; for ( unsigned int func2 = func1 + 1; func2 < _functionList.size(); ) { @@ -1213,7 +1213,7 @@ void Tokenizer::fillFunctionList() { _functionList.erase( _functionList.begin() + func1 ); } - } + } } //--------------------------------------------------------------------------- @@ -1245,7 +1245,7 @@ void Tokenizer::deleteTokens(TOKEN *tok) delete tok; tok = next; } -} +} //--------------------------------------------------------------------------- diff --git a/tokenize.h b/tokenize.h index 44b3a1d5d..5374b731c 100644 --- a/tokenize.h +++ b/tokenize.h @@ -26,7 +26,7 @@ #include #include #include "settings.h" -#include "errorlogger.h" +#include "errorlogger.h" #include "token.h" class Tokenizer @@ -35,23 +35,23 @@ private: // Deallocate lists.. void DeallocateTokens(); - /** - * Helper function for "tokenize". This recursively parses into included header files. - */ - void tokenizeCode(std::istream &code, const unsigned int FileIndex=0); + /** + * Helper function for "tokenize". This recursively parses into included header files. + */ + void tokenizeCode(std::istream &code, const unsigned int FileIndex=0); public: Tokenizer(); ~Tokenizer(); - - /** - * Tokenize code - * @param code input stream for code - * @param FileName The filename + + /** + * Tokenize code + * @param code input stream for code + * @param FileName The filename */ - void tokenize(std::istream &code, const char FileName[]); + void tokenize(std::istream &code, const char FileName[]); - /** Set variable id */ + /** Set variable id */ void setVarId(); /** Simplify tokenlist */ @@ -110,4 +110,4 @@ private: }; //--------------------------------------------------------------------------- -#endif +#endif