Refactoring: CommonCheck.* files are removed. Rest of the global functions from there were moved to Tokenizer class

This commit is contained in:
Reijo Tomperi 2008-11-21 21:14:24 +00:00
parent 66412ed4ae
commit 125692bc65
15 changed files with 484 additions and 580 deletions

View File

@ -21,7 +21,6 @@
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
#include "CheckBufferOverrun.h" #include "CheckBufferOverrun.h"
#include "CommonCheck.h"
#include <algorithm> #include <algorithm>
#include <sstream> #include <sstream>
@ -73,7 +72,7 @@ void CheckBufferOverrunClass::CheckBufferOverrun_CheckScope( const TOKEN *tok, c
// Array index.. // Array index..
if ( Match(tok, "%var1% [ %num% ]", varname) ) if ( Tokenizer::Match(tok, "%var1% [ %num% ]", varname) )
{ {
const char *num = Tokenizer::getstr(tok, 2 + varc); const char *num = Tokenizer::getstr(tok, 2 + varc);
if (strtol(num, NULL, 10) >= size) if (strtol(num, NULL, 10) >= size)
@ -86,12 +85,12 @@ void CheckBufferOverrunClass::CheckBufferOverrun_CheckScope( const TOKEN *tok, c
int indentlevel = 0; int indentlevel = 0;
for ( ; tok; tok = tok->next ) for ( ; tok; tok = tok->next )
{ {
if (Match(tok, "{")) if (Tokenizer::Match(tok, "{"))
{ {
indentlevel++; indentlevel++;
} }
else if (Match(tok, "}")) else if (Tokenizer::Match(tok, "}"))
{ {
indentlevel--; indentlevel--;
if ( indentlevel < 0 ) if ( indentlevel < 0 )
@ -99,7 +98,7 @@ void CheckBufferOverrunClass::CheckBufferOverrun_CheckScope( const TOKEN *tok, c
} }
// Array index.. // Array index..
if ( !Match(tok, "%var%") && !Match(tok,"[.&]") && Match(tok->next, "%var1% [ %num% ]", varname) ) if ( !Tokenizer::Match(tok, "%var%") && !Tokenizer::Match(tok,"[.&]") && Tokenizer::Match(tok->next, "%var1% [ %num% ]", varname) )
{ {
const char *num = Tokenizer::getstr(tok->next, 2 + varc); const char *num = Tokenizer::getstr(tok->next, 2 + varc);
if (strtol(num, NULL, 10) >= size) if (strtol(num, NULL, 10) >= size)
@ -112,15 +111,15 @@ void CheckBufferOverrunClass::CheckBufferOverrun_CheckScope( const TOKEN *tok, c
// memset, memcmp, memcpy, strncpy, fgets.. // memset, memcmp, memcpy, strncpy, fgets..
if (Match(tok,"memset") || if (Tokenizer::Match(tok,"memset") ||
Match(tok,"memcpy") || Tokenizer::Match(tok,"memcpy") ||
Match(tok,"memmove") || Tokenizer::Match(tok,"memmove") ||
Match(tok,"memcmp") || Tokenizer::Match(tok,"memcmp") ||
Match(tok,"strncpy") || Tokenizer::Match(tok,"strncpy") ||
Match(tok,"fgets") ) Tokenizer::Match(tok,"fgets") )
{ {
if ( Match( tok->next, "( %var1% , %num% , %num% )", varname ) || if ( Tokenizer::Match( tok->next, "( %var1% , %num% , %num% )", varname ) ||
Match( tok->next, "( %var% , %var1% , %num% )", varname ) ) Tokenizer::Match( tok->next, "( %var% , %var1% , %num% )", varname ) )
{ {
const char *num = Tokenizer::getstr(tok, varc + 6); const char *num = Tokenizer::getstr(tok, varc + 6);
if ( atoi(num) > total_size ) if ( atoi(num) > total_size )
@ -133,22 +132,22 @@ void CheckBufferOverrunClass::CheckBufferOverrun_CheckScope( const TOKEN *tok, c
// Loop.. // Loop..
if ( Match(tok, "for (") ) if ( Tokenizer::Match(tok, "for (") )
{ {
const TOKEN *tok2 = Tokenizer::gettok( tok, 2 ); const TOKEN *tok2 = Tokenizer::gettok( tok, 2 );
// for - setup.. // for - setup..
if ( Match(tok2, "%var% = 0 ;") ) if ( Tokenizer::Match(tok2, "%var% = 0 ;") )
tok2 = Tokenizer::gettok(tok2, 4); tok2 = Tokenizer::gettok(tok2, 4);
else if ( Match(tok2, "%type% %var% = 0 ;") ) else if ( Tokenizer::Match(tok2, "%type% %var% = 0 ;") )
tok2 = Tokenizer::gettok(tok2, 5); tok2 = Tokenizer::gettok(tok2, 5);
else if ( Match(tok2, "%type% %type% %var% = 0 ;") ) else if ( Tokenizer::Match(tok2, "%type% %type% %var% = 0 ;") )
tok2 = Tokenizer::gettok(tok2, 6); tok2 = Tokenizer::gettok(tok2, 6);
else else
continue; continue;
// for - condition.. // for - condition..
if ( ! Match(tok2, "%var% < %num% ;") && ! Match(tok2, "%var% <= %num% ;")) if ( ! Tokenizer::Match(tok2, "%var% < %num% ;") && ! Tokenizer::Match(tok2, "%var% <= %num% ;"))
continue; continue;
// Get index variable and stopsize. // Get index variable and stopsize.
@ -158,7 +157,7 @@ void CheckBufferOverrunClass::CheckBufferOverrun_CheckScope( const TOKEN *tok, c
continue; continue;
// Goto the end of the for loop.. // Goto the end of the for loop..
while (tok2 && !Match(tok2,")")) while (tok2 && !Tokenizer::Match(tok2,")"))
tok2 = tok2->next; tok2 = tok2->next;
if (!Tokenizer::gettok(tok2,5)) if (!Tokenizer::gettok(tok2,5))
break; break;
@ -169,20 +168,20 @@ void CheckBufferOverrunClass::CheckBufferOverrun_CheckScope( const TOKEN *tok, c
int indentlevel2 = 0; int indentlevel2 = 0;
while (tok2) while (tok2)
{ {
if ( Match(tok2, ";") && indentlevel2 == 0 ) if ( Tokenizer::Match(tok2, ";") && indentlevel2 == 0 )
break; break;
if ( Match(tok2, "{") ) if ( Tokenizer::Match(tok2, "{") )
indentlevel2++; indentlevel2++;
if ( Match(tok2, "}") ) if ( Tokenizer::Match(tok2, "}") )
{ {
indentlevel2--; indentlevel2--;
if ( indentlevel2 <= 0 ) if ( indentlevel2 <= 0 )
break; break;
} }
if ( Match( tok2, pattern.str().c_str(), varname ) ) if ( Tokenizer::Match( tok2, pattern.str().c_str(), varname ) )
{ {
ReportError(tok2, "Buffer overrun"); ReportError(tok2, "Buffer overrun");
break; break;
@ -195,7 +194,7 @@ void CheckBufferOverrunClass::CheckBufferOverrun_CheckScope( const TOKEN *tok, c
// Writing data into array.. // Writing data into array..
if ( Match(tok, "strcpy ( %var1% , %str% )", varname) ) if ( Tokenizer::Match(tok, "strcpy ( %var1% , %str% )", varname) )
{ {
int len = 0; int len = 0;
const char *str = Tokenizer::getstr(tok, varc + 4 ); const char *str = Tokenizer::getstr(tok, varc + 4 );
@ -217,7 +216,7 @@ void CheckBufferOverrunClass::CheckBufferOverrun_CheckScope( const TOKEN *tok, c
// Function call.. // Function call..
// It's not interesting to check what happens when the whole struct is // It's not interesting to check what happens when the whole struct is
// sent as the parameter, that is checked separately anyway. // sent as the parameter, that is checked separately anyway.
if ( Match( tok, "%var% (" ) ) if ( Tokenizer::Match( tok, "%var% (" ) )
{ {
// Don't make recursive checking.. // Don't make recursive checking..
if (std::find(CallStack.begin(), CallStack.end(), tok) != CallStack.end()) if (std::find(CallStack.begin(), CallStack.end(), tok) != CallStack.end())
@ -226,12 +225,12 @@ void CheckBufferOverrunClass::CheckBufferOverrun_CheckScope( const TOKEN *tok, c
unsigned int parlevel = 0, par = 0; unsigned int parlevel = 0, par = 0;
for ( const TOKEN *tok2 = tok; tok2; tok2 = tok2->next ) for ( const TOKEN *tok2 = tok; tok2; tok2 = tok2->next )
{ {
if ( Match(tok2, "(") ) if ( Tokenizer::Match(tok2, "(") )
{ {
parlevel++; parlevel++;
} }
else if ( Match(tok2, ")") ) else if ( Tokenizer::Match(tok2, ")") )
{ {
parlevel--; parlevel--;
if ( parlevel < 1 ) if ( parlevel < 1 )
@ -241,12 +240,12 @@ void CheckBufferOverrunClass::CheckBufferOverrun_CheckScope( const TOKEN *tok, c
} }
} }
else if ( parlevel == 1 && Match(tok2, ",") ) else if ( parlevel == 1 && Tokenizer::Match(tok2, ",") )
{ {
par++; par++;
} }
if ( parlevel == 1 && Match(tok2, "[(,] %var1% [,)]", varname) ) if ( parlevel == 1 && Tokenizer::Match(tok2, "[(,] %var1% [,)]", varname) )
{ {
par++; par++;
break; break;
@ -266,16 +265,16 @@ void CheckBufferOverrunClass::CheckBufferOverrun_CheckScope( const TOKEN *tok, c
parlevel = 1; parlevel = 1;
while ( ftok && parlevel == 1 && par >= 1 ) while ( ftok && parlevel == 1 && par >= 1 )
{ {
if ( Match(ftok, "(") ) if ( Tokenizer::Match(ftok, "(") )
parlevel++; parlevel++;
else if ( Match(ftok, ")") ) else if ( Tokenizer::Match(ftok, ")") )
parlevel--; parlevel--;
else if ( Match(ftok, ",") ) else if ( Tokenizer::Match(ftok, ",") )
par--; par--;
else if (par==1 && parlevel==1 && (Match(ftok, "%var% ,") || Match(ftok, "%var% )"))) else if (par==1 && parlevel==1 && (Tokenizer::Match(ftok, "%var% ,") || Tokenizer::Match(ftok, "%var% )")))
{ {
// Parameter name.. // Parameter name..
const char *parname[2]; const char *parname[2];
@ -283,7 +282,7 @@ void CheckBufferOverrunClass::CheckBufferOverrun_CheckScope( const TOKEN *tok, c
parname[1] = 0; parname[1] = 0;
// Goto function body.. // Goto function body..
while ( ftok && !Match(ftok,"{") ) while ( ftok && !Tokenizer::Match(ftok,"{") )
ftok = ftok->next; ftok = ftok->next;
ftok = ftok ? ftok->next : 0; ftok = ftok ? ftok->next : 0;
@ -312,10 +311,10 @@ void CheckBufferOverrunClass::CheckBufferOverrun_LocalVariable()
int indentlevel = 0; int indentlevel = 0;
for (const TOKEN *tok = _tokenizer->tokens(); tok; tok = tok->next) for (const TOKEN *tok = _tokenizer->tokens(); tok; tok = tok->next)
{ {
if (Match(tok, "{")) if (Tokenizer::Match(tok, "{"))
indentlevel++; indentlevel++;
else if (Match(tok, "}")) else if (Tokenizer::Match(tok, "}"))
indentlevel--; indentlevel--;
else if (indentlevel > 0) else if (indentlevel > 0)
@ -324,13 +323,13 @@ void CheckBufferOverrunClass::CheckBufferOverrun_LocalVariable()
unsigned int size = 0; unsigned int size = 0;
const char *type = 0; const char *type = 0;
if (Match(tok, "%type% %var% [ %num% ] ;")) if (Tokenizer::Match(tok, "%type% %var% [ %num% ] ;"))
{ {
varname[0] = Tokenizer::getstr(tok,1); varname[0] = Tokenizer::getstr(tok,1);
size = strtoul(Tokenizer::getstr(tok,3), NULL, 10); size = strtoul(Tokenizer::getstr(tok,3), NULL, 10);
type = tok->str; type = tok->str;
} }
else if (indentlevel > 0 && Match(tok, "[*;{}] %var% = new %type% [ %num% ]")) else if (indentlevel > 0 && Tokenizer::Match(tok, "[*;{}] %var% = new %type% [ %num% ]"))
{ {
varname[0] = Tokenizer::getstr(tok,1); varname[0] = Tokenizer::getstr(tok,1);
size = strtoul(Tokenizer::getstr(tok,6), NULL, 10); size = strtoul(Tokenizer::getstr(tok,6), NULL, 10);
@ -365,28 +364,28 @@ void CheckBufferOverrunClass::CheckBufferOverrun_StructVariable()
tok; tok;
tok = Tokenizer::findtoken( tok->next, declstruct_pattern ) ) tok = Tokenizer::findtoken( tok->next, declstruct_pattern ) )
{ {
if (!Match(tok,"struct") && !Match(tok,"class")) if (!Tokenizer::Match(tok,"struct") && !Tokenizer::Match(tok,"class"))
continue; continue;
const char *structname = tok->next->str; const char *structname = tok->next->str;
if ( ! IsName( structname ) ) if ( ! Tokenizer::IsName( structname ) )
continue; continue;
// Found a struct declaration. Search for arrays.. // Found a struct declaration. Search for arrays..
for ( TOKEN * tok2 = tok->next->next; tok2; tok2 = tok2->next ) for ( TOKEN * tok2 = tok->next->next; tok2; tok2 = tok2->next )
{ {
if ( Match(tok2, "}") ) if ( Tokenizer::Match(tok2, "}") )
break; break;
int ivar = 0; int ivar = 0;
if ( Match(tok2->next, "%type% %var% [ %num% ] ;") ) if ( Tokenizer::Match(tok2->next, "%type% %var% [ %num% ] ;") )
ivar = 2; ivar = 2;
else if ( Match(tok2->next, "%type% %type% %var% [ %num% ] ;") ) else if ( Tokenizer::Match(tok2->next, "%type% %type% %var% [ %num% ] ;") )
ivar = 3; ivar = 3;
else if ( Match(tok2->next, "%type% * %var% [ %num% ] ;") ) else if ( Tokenizer::Match(tok2->next, "%type% * %var% [ %num% ] ;") )
ivar = 3; ivar = 3;
else if ( Match(tok2->next, "%type% %type% * %var% [ %num% ] ;") ) else if ( Tokenizer::Match(tok2->next, "%type% %type% * %var% [ %num% ] ;") )
ivar = 4; ivar = 4;
else else
continue; continue;
@ -400,7 +399,7 @@ void CheckBufferOverrunClass::CheckBufferOverrun_StructVariable()
// Class member variable => Check functions // Class member variable => Check functions
if ( Match(tok, "class") ) if ( Tokenizer::Match(tok, "class") )
{ {
std::string func_pattern(structname + std::string(" :: %var% (")); std::string func_pattern(structname + std::string(" :: %var% ("));
const TOKEN *tok3 = Tokenizer::findmatch(_tokenizer->tokens(), func_pattern.c_str()); const TOKEN *tok3 = Tokenizer::findmatch(_tokenizer->tokens(), func_pattern.c_str());
@ -408,10 +407,10 @@ void CheckBufferOverrunClass::CheckBufferOverrun_StructVariable()
{ {
for ( const TOKEN *tok4 = tok3; tok4; tok4 = tok4->next ) for ( const TOKEN *tok4 = tok3; tok4; tok4 = tok4->next )
{ {
if ( Match(tok4,"[;{}]") ) if ( Tokenizer::Match(tok4,"[;{}]") )
break; break;
if ( Match(tok4, ") {") ) if ( Tokenizer::Match(tok4, ") {") )
{ {
const char *names[2] = {varname[1], 0}; const char *names[2] = {varname[1], 0};
CheckBufferOverrun_CheckScope( Tokenizer::gettok(tok4, 2), names, arrsize, total_size ); CheckBufferOverrun_CheckScope( Tokenizer::gettok(tok4, 2), names, arrsize, total_size );
@ -428,11 +427,11 @@ void CheckBufferOverrunClass::CheckBufferOverrun_StructVariable()
continue; continue;
// Declare variable: Fred fred1; // Declare variable: Fred fred1;
if ( Match( tok3->next, "%var% ;" ) ) if ( Tokenizer::Match( tok3->next, "%var% ;" ) )
varname[0] = Tokenizer::getstr(tok3, 1); varname[0] = Tokenizer::getstr(tok3, 1);
// Declare pointer: Fred *fred1 // Declare pointer: Fred *fred1
else if ( Match(tok3->next, "* %var% [,);=]") ) else if ( Tokenizer::Match(tok3->next, "* %var% [,);=]") )
varname[0] = Tokenizer::getstr(tok3, 2); varname[0] = Tokenizer::getstr(tok3, 2);
else else
@ -444,18 +443,18 @@ void CheckBufferOverrunClass::CheckBufferOverrun_StructVariable()
while ( tok3 ) while ( tok3 )
{ {
// End of statement. // End of statement.
if ( Match(tok3, ";") ) if ( Tokenizer::Match(tok3, ";") )
{ {
CheckTok = tok3; CheckTok = tok3;
break; break;
} }
// End of function declaration.. // End of function declaration..
if ( Match(tok3, ") ;") ) if ( Tokenizer::Match(tok3, ") ;") )
break; break;
// Function implementation.. // Function implementation..
if ( Match(tok3, ") {") ) if ( Tokenizer::Match(tok3, ") {") )
{ {
CheckTok = Tokenizer::gettok(tok3, 2); CheckTok = Tokenizer::gettok(tok3, 2);
break; break;
@ -502,14 +501,14 @@ void CheckBufferOverrunClass::WarningDangerousFunctions()
{ {
for (const TOKEN *tok = _tokenizer->tokens(); tok; tok = tok->next) for (const TOKEN *tok = _tokenizer->tokens(); tok; tok = tok->next)
{ {
if (Match(tok, "gets (")) if (Tokenizer::Match(tok, "gets ("))
{ {
std::ostringstream ostr; std::ostringstream ostr;
ostr << _tokenizer->fileLine(tok) << ": Found 'gets'. You should use 'fgets' instead"; ostr << _tokenizer->fileLine(tok) << ": Found 'gets'. You should use 'fgets' instead";
_errorLogger->reportErr(ostr.str()); _errorLogger->reportErr(ostr.str());
} }
else if (Match(tok, "scanf (") && strcmp(Tokenizer::getstr(tok,2),"\"%s\"") == 0) else if (Tokenizer::Match(tok, "scanf (") && strcmp(Tokenizer::getstr(tok,2),"\"%s\"") == 0)
{ {
std::ostringstream ostr; std::ostringstream ostr;
ostr << _tokenizer->fileLine(tok) << ": Found 'scanf'. You should use 'fgets' instead"; ostr << _tokenizer->fileLine(tok) << ": Found 'scanf'. You should use 'fgets' instead";

View File

@ -19,7 +19,6 @@
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
#include "CheckClass.h" #include "CheckClass.h"
#include "CommonCheck.h"
#include <locale> #include <locale>
#include <string> #include <string>
@ -75,7 +74,7 @@ struct VAR *CheckClass::ClassChecking_GetVarList(const TOKEN *tok1)
const char *varname = 0; const char *varname = 0;
// Is it a variable declaration? // Is it a variable declaration?
if ( Match(next,"%type% %var% ;") ) if ( Tokenizer::Match(next,"%type% %var% ;") )
{ {
const char *types[] = {"bool", "char", "int", "short", "long", "float", "double", 0}; const char *types[] = {"bool", "char", "int", "short", "long", "float", "double", 0};
for ( int type = 0; types[type]; type++ ) for ( int type = 0; types[type]; type++ )
@ -89,7 +88,7 @@ struct VAR *CheckClass::ClassChecking_GetVarList(const TOKEN *tok1)
} }
// Pointer? // Pointer?
else if ( Match(next, "%type% * %var% ;") ) else if ( Tokenizer::Match(next, "%type% * %var% ;") )
{ {
varname = Tokenizer::getstr(next, 2); varname = Tokenizer::getstr(next, 2);
} }
@ -123,10 +122,10 @@ const TOKEN * CheckClass::FindClassFunction( const TOKEN *tok, const char classn
for ( ;tok; tok = tok->next ) for ( ;tok; tok = tok->next )
{ {
if ( indentlevel == 0 && if ( indentlevel == 0 &&
( Match(tok, "class %var1% {", _classname) || ( Tokenizer::Match(tok, "class %var1% {", _classname) ||
Match(tok, "class %var1% : %type% {", _classname) ) ) Tokenizer::Match(tok, "class %var1% : %type% {", _classname) ) )
{ {
if ( Match(tok, "class %var% {") ) if ( Tokenizer::Match(tok, "class %var% {") )
tok = Tokenizer::gettok(tok, 3); tok = Tokenizer::gettok(tok, 3);
else else
tok = Tokenizer::gettok(tok, 5); tok = Tokenizer::gettok(tok, 5);
@ -169,7 +168,7 @@ const TOKEN * CheckClass::FindClassFunction( const TOKEN *tok, const char classn
if ( indentlevel == 1 ) if ( indentlevel == 1 )
{ {
// Member function implemented in the class declaration? // Member function implemented in the class declaration?
if ( Match( tok, "%var1% (", _funcname ) ) if ( Tokenizer::Match( tok, "%var1% (", _funcname ) )
{ {
const TOKEN *tok2 = tok; const TOKEN *tok2 = tok;
while ( tok2 && tok2->str[0] != '{' && tok2->str[0] != ';' ) while ( tok2 && tok2->str[0] != '{' && tok2->str[0] != ';' )
@ -179,7 +178,7 @@ const TOKEN * CheckClass::FindClassFunction( const TOKEN *tok, const char classn
} }
} }
else if ( indentlevel == 0 && Match(tok, "%var1% :: %var2% (", _classname, _funcname) ) else if ( indentlevel == 0 && Tokenizer::Match(tok, "%var1% :: %var2% (", _classname, _funcname) )
{ {
return tok; return tok;
} }
@ -217,7 +216,7 @@ void CheckClass::ClassChecking_VarList_Initialize(const TOKEN *tok1, const TOKEN
// clKalle::clKalle() : var(value) { } // clKalle::clKalle() : var(value) { }
if (indentlevel==0) if (indentlevel==0)
{ {
if (Assign && Match(ftok, "%var% (")) if (Assign && Tokenizer::Match(ftok, "%var% ("))
{ {
InitVar( varlist, ftok->str ); InitVar( varlist, ftok->str );
} }
@ -243,29 +242,29 @@ void CheckClass::ClassChecking_VarList_Initialize(const TOKEN *tok1, const TOKEN
continue; continue;
// Before a new statement there is "[{};)=]" or "else" // Before a new statement there is "[{};)=]" or "else"
if ( ! Match(ftok, "[{};)=]") && ! Match(ftok, "else") ) if ( ! Tokenizer::Match(ftok, "[{};)=]") && ! Tokenizer::Match(ftok, "else") )
continue; continue;
// Using the operator= function to initialize all variables.. // Using the operator= function to initialize all variables..
if ( Match(ftok->next, "* this = ") ) if ( Tokenizer::Match(ftok->next, "* this = ") )
{ {
for (struct VAR *var = varlist; var; var = var->next) for (struct VAR *var = varlist; var; var = var->next)
var->init = true; var->init = true;
break; break;
} }
if (!Match(ftok->next, "%var%") && !Match(ftok->next, "this . %var%")) if (!Tokenizer::Match(ftok->next, "%var%") && !Tokenizer::Match(ftok->next, "this . %var%"))
continue; continue;
// Goto the first token in this statement.. // Goto the first token in this statement..
ftok = ftok->next; ftok = ftok->next;
// Skip "this->" // Skip "this->"
if ( Match(ftok, "this .") ) if ( Tokenizer::Match(ftok, "this .") )
ftok = Tokenizer::gettok(ftok, 2); ftok = Tokenizer::gettok(ftok, 2);
// Clearing all variables.. // Clearing all variables..
if (Match(ftok,"memset ( this ,")) if (Tokenizer::Match(ftok,"memset ( this ,"))
{ {
for (struct VAR *var = varlist; var; var = var->next) for (struct VAR *var = varlist; var; var = var->next)
var->init = true; var->init = true;
@ -273,7 +272,7 @@ void CheckClass::ClassChecking_VarList_Initialize(const TOKEN *tok1, const TOKEN
} }
// Calling member function? // Calling member function?
else if (Match(ftok, "%var% (")) else if (Tokenizer::Match(ftok, "%var% ("))
{ {
// No recursive calls! // No recursive calls!
if ( std::find(callstack.begin(),callstack.end(),ftok->str) == callstack.end() ) if ( std::find(callstack.begin(),callstack.end(),ftok->str) == callstack.end() )
@ -286,13 +285,13 @@ void CheckClass::ClassChecking_VarList_Initialize(const TOKEN *tok1, const TOKEN
} }
// Assignment of member variable? // Assignment of member variable?
else if (Match(ftok, "%var% =")) else if (Tokenizer::Match(ftok, "%var% ="))
{ {
InitVar( varlist, ftok->str ); InitVar( varlist, ftok->str );
} }
// The functions 'clear' and 'Clear' are supposed to initialize variable. // The functions 'clear' and 'Clear' are supposed to initialize variable.
if (Match(ftok,"%var% . clear (") || Match(ftok,"%var% . Clear (")) if (Tokenizer::Match(ftok,"%var% . clear (") || Tokenizer::Match(ftok,"%var% . Clear ("))
{ {
InitVar( varlist, ftok->str ); InitVar( varlist, ftok->str );
} }
@ -316,7 +315,7 @@ void CheckClass::CheckConstructors()
while (tok1) while (tok1)
{ {
const char *classname = tok1->next->str; const char *classname = tok1->next->str;
if ( ! IsName(classname) ) if ( ! Tokenizer::IsName(classname) )
{ {
tok1 = Tokenizer::findtoken( tok1->next, pattern_classname ); tok1 = Tokenizer::findtoken( tok1->next, pattern_classname );
continue; continue;
@ -431,7 +430,7 @@ void CheckClass::CheckUnusedPrivateFunctions()
unsigned int indent_level = 0; unsigned int indent_level = 0;
for (const TOKEN *tok = tok1; tok; tok = tok->next) for (const TOKEN *tok = tok1; tok; tok = tok->next)
{ {
if (Match(tok,"friend %var%")) if (Tokenizer::Match(tok,"friend %var%"))
{ {
// Todo: Handle friend classes // Todo: Handle friend classes
FuncList.clear(); FuncList.clear();
@ -456,11 +455,11 @@ void CheckClass::CheckUnusedPrivateFunctions()
priv = false; priv = false;
else if (priv && indent_level == 1) else if (priv && indent_level == 1)
{ {
if ( Match(tok, "typedef %type% (") ) if ( Tokenizer::Match(tok, "typedef %type% (") )
tok = Tokenizer::gettok(tok, 2); tok = Tokenizer::gettok(tok, 2);
if (Match(tok, "%var% (") && if (Tokenizer::Match(tok, "%var% (") &&
!Match(tok,classname)) !Tokenizer::Match(tok,classname))
{ {
FuncList.push_back(tok->str); FuncList.push_back(tok->str);
} }
@ -550,20 +549,20 @@ void CheckClass::CheckMemset()
// Locate all 'memset' tokens.. // Locate all 'memset' tokens..
for (const TOKEN *tok = _tokenizer->tokens(); tok; tok = tok->next) for (const TOKEN *tok = _tokenizer->tokens(); tok; tok = tok->next)
{ {
if (!Match(tok,"memset") && !Match(tok,"memcpy") && !Match(tok,"memmove")) if (!Tokenizer::Match(tok,"memset") && !Tokenizer::Match(tok,"memcpy") && !Tokenizer::Match(tok,"memmove"))
continue; continue;
// Todo: Handle memcpy and memmove // Todo: Handle memcpy and memmove
const char *type = NULL; const char *type = NULL;
if (Match(tok, "memset ( %var% , %num% , sizeof ( %type% ) )")) if (Tokenizer::Match(tok, "memset ( %var% , %num% , sizeof ( %type% ) )"))
type = Tokenizer::getstr(tok, 8); type = Tokenizer::getstr(tok, 8);
else if (Match(tok, "memset ( & %var% , %num% , sizeof ( %type% ) )")) else if (Tokenizer::Match(tok, "memset ( & %var% , %num% , sizeof ( %type% ) )"))
type = Tokenizer::getstr(tok, 9); type = Tokenizer::getstr(tok, 9);
else if (Match(tok, "memset ( %var% , %num% , sizeof ( struct %type% ) )")) else if (Tokenizer::Match(tok, "memset ( %var% , %num% , sizeof ( struct %type% ) )"))
type = Tokenizer::getstr(tok, 9); type = Tokenizer::getstr(tok, 9);
else if (Match(tok, "memset ( & %var% , %num% , sizeof ( struct %type% ) )")) else if (Tokenizer::Match(tok, "memset ( & %var% , %num% , sizeof ( struct %type% ) )"))
type = Tokenizer::getstr(tok, 10); type = Tokenizer::getstr(tok, 10);
else if (Match(tok, "%type% ( %var% , %var% , sizeof ( %type% ) )")) else if (Tokenizer::Match(tok, "%type% ( %var% , %var% , sizeof ( %type% ) )"))
type = Tokenizer::getstr(tok, 8); type = Tokenizer::getstr(tok, 8);
// No type defined => The tokens didn't match // No type defined => The tokens didn't match
@ -589,7 +588,7 @@ void CheckClass::CheckMemset()
if (tstruct->str[0] == '}') if (tstruct->str[0] == '}')
break; break;
if (Match(tstruct, "std :: %type% %var% ;")) if (Tokenizer::Match(tstruct, "std :: %type% %var% ;"))
{ {
std::ostringstream ostr; std::ostringstream ostr;
ostr << _tokenizer->fileLine(tok) << ": Using '" << tok->str << "' on struct that contains a 'std::" << Tokenizer::getstr(tstruct,2) << "'"; ostr << _tokenizer->fileLine(tok) << ": Using '" << tok->str << "' on struct that contains a 'std::" << Tokenizer::getstr(tstruct,2) << "'";

View File

@ -20,7 +20,6 @@
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
#include "CheckHeaders.h" #include "CheckHeaders.h"
#include "tokenize.h" #include "tokenize.h"
#include "CommonCheck.h"
#include <algorithm> #include <algorithm>
#include <list> #include <list>
@ -55,7 +54,7 @@ void CheckHeaders::WarningHeaderWithImplementation()
if (tok->FileIndex == 0) if (tok->FileIndex == 0)
continue; continue;
if (Match(tok, ") {")) if (Tokenizer::Match(tok, ") {"))
{ {
std::ostringstream ostr; std::ostringstream ostr;
ostr << _tokenizer->fileLine(tok) << ": Found implementation in header"; ostr << _tokenizer->fileLine(tok) << ": Found implementation in header";
@ -94,7 +93,7 @@ void CheckHeaders::WarningIncludeHeader()
const char *includefile = includetok->next->str; const char *includefile = includetok->next->str;
while (hfile < _tokenizer->getFiles()->size()) while (hfile < _tokenizer->getFiles()->size())
{ {
if ( SameFileName( _tokenizer->getFiles()->at(hfile).c_str(), includefile ) ) if ( Tokenizer::SameFileName( _tokenizer->getFiles()->at(hfile).c_str(), includefile ) )
break; break;
hfile++; hfile++;
} }
@ -130,21 +129,21 @@ void CheckHeaders::WarningIncludeHeader()
// Class or namespace declaration.. // Class or namespace declaration..
// -------------------------------------- // --------------------------------------
if (Match(tok1,"class %var% {") || Match(tok1,"class %var% :") || Match(tok1,"namespace %var% {")) if (Tokenizer::Match(tok1,"class %var% {") || Tokenizer::Match(tok1,"class %var% :") || Tokenizer::Match(tok1,"namespace %var% {"))
classlist.push_back(Tokenizer::getstr(tok1, 1)); classlist.push_back(Tokenizer::getstr(tok1, 1));
// Variable declaration.. // Variable declaration..
// -------------------------------------- // --------------------------------------
else if (Match(tok1, "%type% %var% ;") || Match(tok1, "%type% %var% [")) else if (Tokenizer::Match(tok1, "%type% %var% ;") || Tokenizer::Match(tok1, "%type% %var% ["))
namelist.push_back(Tokenizer::getstr(tok1, 1)); namelist.push_back(Tokenizer::getstr(tok1, 1));
else if (Match(tok1, "%type% * %var% ;") || Match(tok1, "%type% * %var% [")) else if (Tokenizer::Match(tok1, "%type% * %var% ;") || Tokenizer::Match(tok1, "%type% * %var% ["))
namelist.push_back(Tokenizer::getstr(tok1, 2)); namelist.push_back(Tokenizer::getstr(tok1, 2));
else if (Match(tok1, "const %type% %var% =") || Match(tok1, "const %type% %var% [")) else if (Tokenizer::Match(tok1, "const %type% %var% =") || Tokenizer::Match(tok1, "const %type% %var% ["))
namelist.push_back(Tokenizer::getstr(tok1, 2)); namelist.push_back(Tokenizer::getstr(tok1, 2));
else if (Match(tok1, "const %type% * %var% =") || Match(tok1, "const %type% * %var% [")) else if (Tokenizer::Match(tok1, "const %type% * %var% =") || Tokenizer::Match(tok1, "const %type% * %var% ["))
namelist.push_back(Tokenizer::getstr(tok1, 3)); namelist.push_back(Tokenizer::getstr(tok1, 3));
// enum.. // enum..
@ -154,7 +153,7 @@ void CheckHeaders::WarningIncludeHeader()
tok1 = tok1->next; tok1 = tok1->next;
while (tok1->next && tok1->str[0]!=';') while (tok1->next && tok1->str[0]!=';')
{ {
if ( IsName(tok1->str) ) if ( Tokenizer::IsName(tok1->str) )
namelist.push_back(tok1->str); namelist.push_back(tok1->str);
tok1 = tok1->next; tok1 = tok1->next;
} }
@ -162,16 +161,16 @@ void CheckHeaders::WarningIncludeHeader()
// function.. // function..
// -------------------------------------- // --------------------------------------
else if (Match(tok1,"%type% %var% (")) else if (Tokenizer::Match(tok1,"%type% %var% ("))
namelist.push_back(Tokenizer::getstr(tok1, 1)); namelist.push_back(Tokenizer::getstr(tok1, 1));
else if (Match(tok1,"%type% * %var% (")) else if (Tokenizer::Match(tok1,"%type% * %var% ("))
namelist.push_back(Tokenizer::getstr(tok1, 2)); namelist.push_back(Tokenizer::getstr(tok1, 2));
else if (Match(tok1,"const %type% %var% (")) else if (Tokenizer::Match(tok1,"const %type% %var% ("))
namelist.push_back(Tokenizer::getstr(tok1, 2)); namelist.push_back(Tokenizer::getstr(tok1, 2));
else if (Match(tok1,"const %type% * %var% (")) else if (Tokenizer::Match(tok1,"const %type% * %var% ("))
namelist.push_back(Tokenizer::getstr(tok1, 3)); namelist.push_back(Tokenizer::getstr(tok1, 3));
// typedef.. // typedef..
@ -194,7 +193,7 @@ void CheckHeaders::WarningIncludeHeader()
if ( tok1->str[0] == ';' ) if ( tok1->str[0] == ';' )
break; break;
if ( Match(tok1, "%var% ;") ) if ( Tokenizer::Match(tok1, "%var% ;") )
namelist.push_back(tok1->str); namelist.push_back(tok1->str);
} }
@ -212,7 +211,7 @@ void CheckHeaders::WarningIncludeHeader()
if (tok1->FileIndex != includetok->FileIndex) if (tok1->FileIndex != includetok->FileIndex)
continue; continue;
if ( Match(tok1, ": %var% {") || Match(tok1, ": %type% %var% {") ) if ( Tokenizer::Match(tok1, ": %var% {") || Tokenizer::Match(tok1, ": %type% %var% {") )
{ {
std::string classname = Tokenizer::getstr(tok1, (strcmp(Tokenizer::getstr(tok1,2),"{")) ? 2 : 1); std::string classname = Tokenizer::getstr(tok1, (strcmp(Tokenizer::getstr(tok1,2),"{")) ? 2 : 1);
if (std::find(classlist.begin(),classlist.end(),classname)!=classlist.end()) if (std::find(classlist.begin(),classlist.end(),classname)!=classlist.end())
@ -222,7 +221,7 @@ void CheckHeaders::WarningIncludeHeader()
} }
} }
if ( ! IsName(tok1->str) ) if ( ! Tokenizer::IsName(tok1->str) )
continue; continue;
if (std::find(namelist.begin(),namelist.end(),tok1->str ) != namelist.end()) if (std::find(namelist.begin(),namelist.end(),tok1->str ) != namelist.end())

View File

@ -19,11 +19,6 @@
#include "CheckMemoryLeak.h" #include "CheckMemoryLeak.h"
#include "CommonCheck.h"
#include <stdlib.h> // free #include <stdlib.h> // free
#include <algorithm> #include <algorithm>
@ -124,16 +119,16 @@ CheckMemoryLeakClass::AllocType CheckMemoryLeakClass::GetAllocationType( const T
return gMalloc; return gMalloc;
} }
if ( Match( tok2, "new %type% [;(]" ) ) if ( Tokenizer::Match( tok2, "new %type% [;(]" ) )
return New; return New;
if ( Match( tok2, "new %type% [" ) ) if ( Tokenizer::Match( tok2, "new %type% [" ) )
return NewA; return NewA;
if ( Match( tok2, "fopen (" ) ) if ( Tokenizer::Match( tok2, "fopen (" ) )
return FOPEN; return FOPEN;
if ( Match( tok2, "popen (" ) ) if ( Tokenizer::Match( tok2, "popen (" ) )
return POPEN; return POPEN;
// Userdefined allocation function.. // Userdefined allocation function..
@ -151,32 +146,32 @@ CheckMemoryLeakClass::AllocType CheckMemoryLeakClass::GetAllocationType( const T
CheckMemoryLeakClass::AllocType CheckMemoryLeakClass::GetDeallocationType( const TOKEN *tok, const char *varnames[] ) CheckMemoryLeakClass::AllocType CheckMemoryLeakClass::GetDeallocationType( const TOKEN *tok, const char *varnames[] )
{ {
// Redundant condition.. // Redundant condition..
if ( Match(tok, "if ( %var1% )", varnames) ) if ( Tokenizer::Match(tok, "if ( %var1% )", varnames) )
{ {
tok = Tokenizer::gettok( tok, 4 ); tok = Tokenizer::gettok( tok, 4 );
if ( Match(tok,"{") ) if ( Tokenizer::Match(tok,"{") )
tok = tok->next; tok = tok->next;
} }
if ( Match(tok, "delete %var1% ;", varnames) ) if ( Tokenizer::Match(tok, "delete %var1% ;", varnames) )
return New; return New;
if ( Match(tok, "delete [ ] %var1% ;", varnames) ) if ( Tokenizer::Match(tok, "delete [ ] %var1% ;", varnames) )
return NewA; return NewA;
if ( Match(tok, "free ( %var1% ) ;", varnames) || if ( Tokenizer::Match(tok, "free ( %var1% ) ;", varnames) ||
Match(tok, "kfree ( %var1% ) ;", varnames) ) Tokenizer::Match(tok, "kfree ( %var1% ) ;", varnames) )
{ {
return Malloc; return Malloc;
} }
if ( Match(tok, "g_free ( %var1% ) ;", varnames) ) if ( Tokenizer::Match(tok, "g_free ( %var1% ) ;", varnames) )
return gMalloc; return gMalloc;
if ( Match(tok, "fclose ( %var1% )", varnames) ) if ( Tokenizer::Match(tok, "fclose ( %var1% )", varnames) )
return FOPEN; return FOPEN;
if ( Match(tok, "pclose ( %var1% )", varnames) ) if ( Tokenizer::Match(tok, "pclose ( %var1% )", varnames) )
return POPEN; return POPEN;
return No; return No;
@ -185,7 +180,7 @@ CheckMemoryLeakClass::AllocType CheckMemoryLeakClass::GetDeallocationType( const
const char * CheckMemoryLeakClass::call_func( const TOKEN *tok, std::list<const TOKEN *> callstack, const char *varnames[], AllocType &alloctype, AllocType &dealloctype ) const char * CheckMemoryLeakClass::call_func( const TOKEN *tok, std::list<const TOKEN *> callstack, const char *varnames[], AllocType &alloctype, AllocType &dealloctype )
{ {
if (Match(tok,"if") || Match(tok,"for") || Match(tok,"while")) if (Tokenizer::Match(tok,"if") || Tokenizer::Match(tok,"for") || Tokenizer::Match(tok,"while"))
return 0; return 0;
if (GetAllocationType(tok)!=No || GetDeallocationType(tok,varnames)!=No) if (GetAllocationType(tok)!=No || GetDeallocationType(tok,varnames)!=No)
@ -206,9 +201,9 @@ const char * CheckMemoryLeakClass::call_func( const TOKEN *tok, std::list<const
int parlevel = 0; int parlevel = 0;
for ( ; tok; tok = tok->next ) for ( ; tok; tok = tok->next )
{ {
if ( Match(tok, "(") ) if ( Tokenizer::Match(tok, "(") )
++parlevel; ++parlevel;
else if ( Match(tok, ")") ) else if ( Tokenizer::Match(tok, ")") )
{ {
--parlevel; --parlevel;
if ( parlevel < 1 ) if ( parlevel < 1 )
@ -217,16 +212,16 @@ const char * CheckMemoryLeakClass::call_func( const TOKEN *tok, std::list<const
if ( parlevel == 1 ) if ( parlevel == 1 )
{ {
if ( Match(tok, ",") ) if ( Tokenizer::Match(tok, ",") )
++par; ++par;
if ( Match(tok, "[,()] %var1% [,()]", varnames) ) if ( Tokenizer::Match(tok, "[,()] %var1% [,()]", varnames) )
{ {
const TOKEN *ftok = _tokenizer->GetFunctionTokenByName(funcname); const TOKEN *ftok = _tokenizer->GetFunctionTokenByName(funcname);
const char *parname = Tokenizer::getParameterName( ftok, par ); const char *parname = Tokenizer::getParameterName( ftok, par );
if ( ! parname ) if ( ! parname )
return "use"; return "use";
// Check if the function deallocates the variable.. // Check if the function deallocates the variable..
while ( ftok && ! Match(ftok,"{") ) while ( ftok && ! Tokenizer::Match(ftok,"{") )
ftok = ftok->next; ftok = ftok->next;
TOKEN *func = getcode( Tokenizer::gettok(ftok,1), callstack, parname, alloctype, dealloctype ); TOKEN *func = getcode( Tokenizer::gettok(ftok,1), callstack, parname, alloctype, dealloctype );
simplifycode( func ); simplifycode( func );
@ -276,12 +271,12 @@ void CheckMemoryLeakClass::instoken(TOKEN *tok, const char str[])
bool CheckMemoryLeakClass::notvar(const TOKEN *tok, const char *varnames[]) bool CheckMemoryLeakClass::notvar(const TOKEN *tok, const char *varnames[])
{ {
return bool( Match(tok, "! %var1% [;)&|]", varnames) || return bool( Tokenizer::Match(tok, "! %var1% [;)&|]", varnames) ||
Match(tok, "! ( %var1% )", varnames) || Tokenizer::Match(tok, "! ( %var1% )", varnames) ||
Match(tok, "unlikely ( ! %var1% )", varnames) || Tokenizer::Match(tok, "unlikely ( ! %var1% )", varnames) ||
Match(tok, "unlikely ( %var1% == 0 )", varnames) || Tokenizer::Match(tok, "unlikely ( %var1% == 0 )", varnames) ||
Match(tok, "0 == %var1% [;)&|]", varnames) || Tokenizer::Match(tok, "0 == %var1% [;)&|]", varnames) ||
Match(tok, "%var1% == 0", varnames) ); Tokenizer::Match(tok, "%var1% == 0", varnames) );
} }
/** /**
@ -339,14 +334,14 @@ TOKEN *CheckMemoryLeakClass::getcode(const TOKEN *tok, std::list<const TOKEN *>
if ( parlevel == 0 && tok->str[0]==';') if ( parlevel == 0 && tok->str[0]==';')
addtoken(";"); addtoken(";");
if (Match(tok, "[(;{}] %var1% =", varnames)) if (Tokenizer::Match(tok, "[(;{}] %var1% =", varnames))
{ {
AllocType alloc = GetAllocationType(Tokenizer::gettok(tok,3)); AllocType alloc = GetAllocationType(Tokenizer::gettok(tok,3));
// If "--all" hasn't been given, don't check classes.. // If "--all" hasn't been given, don't check classes..
if ( alloc == New && ! _settings._showAll ) if ( alloc == New && ! _settings._showAll )
{ {
if ( Match(Tokenizer::gettok(tok,3), "new %type% [(;]") ) if ( Tokenizer::Match(Tokenizer::gettok(tok,3), "new %type% [(;]") )
{ {
if ( isclass( Tokenizer::getstr(tok, 4) ) ) if ( isclass( Tokenizer::getstr(tok, 4) ) )
alloc = No; alloc = No;
@ -376,35 +371,35 @@ TOKEN *CheckMemoryLeakClass::getcode(const TOKEN *tok, std::list<const TOKEN *>
} }
// if else switch // if else switch
if ( Match(tok, "if ( %var1% )", varnames) || if ( Tokenizer::Match(tok, "if ( %var1% )", varnames) ||
Match(tok, "if ( %var1% != 0 )", varnames) || Tokenizer::Match(tok, "if ( %var1% != 0 )", varnames) ||
Match(tok, "if ( 0 != %var1% )", varnames) ) Tokenizer::Match(tok, "if ( 0 != %var1% )", varnames) )
{ {
addtoken("if(var)"); addtoken("if(var)");
tok = Tokenizer::gettok(tok, 3); // Make sure the "use" will not be added tok = Tokenizer::gettok(tok, 3); // Make sure the "use" will not be added
} }
else if ( Match(tok, "if (") && notvar(Tokenizer::gettok(tok,2), varnames) ) else if ( Tokenizer::Match(tok, "if (") && notvar(Tokenizer::gettok(tok,2), varnames) )
{ {
addtoken("if(!var)"); addtoken("if(!var)");
} }
else if ( Match(tok, "if") ) else if ( Tokenizer::Match(tok, "if") )
{ {
// Check if the condition depends on var somehow.. // Check if the condition depends on var somehow..
bool dep = false; bool dep = false;
int parlevel = 0; int parlevel = 0;
for ( const TOKEN *tok2 = tok; tok2; tok2 = tok2->next ) for ( const TOKEN *tok2 = tok; tok2; tok2 = tok2->next )
{ {
if ( Match(tok2,"(") ) if ( Tokenizer::Match(tok2,"(") )
++parlevel; ++parlevel;
if ( Match(tok2,")") ) if ( Tokenizer::Match(tok2,")") )
{ {
--parlevel; --parlevel;
if ( parlevel <= 0 ) if ( parlevel <= 0 )
break; break;
} }
if ( !Match(tok2,".") && if ( !Tokenizer::Match(tok2,".") &&
Match(tok2->next, "%var1%", varnames) && Tokenizer::Match(tok2->next, "%var1%", varnames) &&
!Match(tok2->next, "%var1% .", varnames) ) !Tokenizer::Match(tok2->next, "%var1% .", varnames) )
{ {
dep = true; dep = true;
break; break;
@ -412,30 +407,30 @@ TOKEN *CheckMemoryLeakClass::getcode(const TOKEN *tok, std::list<const TOKEN *>
} }
addtoken( (dep ? "ifv" : "if") ); addtoken( (dep ? "ifv" : "if") );
} }
else if ( Match(tok, "else") || Match(tok, "switch") ) else if ( Tokenizer::Match(tok, "else") || Tokenizer::Match(tok, "switch") )
{ {
addtoken(tok->str); addtoken(tok->str);
} }
if ( Match(tok, "case") ) if ( Tokenizer::Match(tok, "case") )
{ {
addtoken("case"); addtoken("case");
addtoken(";"); addtoken(";");
} }
if ( Match(tok, "default") ) if ( Tokenizer::Match(tok, "default") )
{ {
addtoken("case"); addtoken("case");
addtoken(";"); addtoken(";");
} }
// Loops.. // Loops..
if (Match(tok, "for") || Match(tok, "while") ) if (Tokenizer::Match(tok, "for") || Tokenizer::Match(tok, "while") )
{ {
addtoken("loop"); addtoken("loop");
isloop = true; isloop = true;
} }
if ( Match(tok, "do") ) if ( Tokenizer::Match(tok, "do") )
{ {
addtoken("do"); addtoken("do");
} }
@ -443,36 +438,36 @@ TOKEN *CheckMemoryLeakClass::getcode(const TOKEN *tok, std::list<const TOKEN *>
addtoken("!var"); addtoken("!var");
// continue / break.. // continue / break..
if ( Match(tok, "continue") ) if ( Tokenizer::Match(tok, "continue") )
addtoken("continue"); addtoken("continue");
if ( Match(tok, "break") ) if ( Tokenizer::Match(tok, "break") )
addtoken("break"); addtoken("break");
// goto.. // goto..
if ( Match(tok, "goto") ) if ( Tokenizer::Match(tok, "goto") )
{ {
addtoken("goto"); addtoken("goto");
} }
// Return.. // Return..
if ( Match(tok, "return") ) if ( Tokenizer::Match(tok, "return") )
{ {
addtoken("return"); addtoken("return");
if ( Match(tok, "return %var1%", varnames) || if ( Tokenizer::Match(tok, "return %var1%", varnames) ||
Match(tok, "return & %var1%", varnames) ) Tokenizer::Match(tok, "return & %var1%", varnames) )
addtoken("use"); addtoken("use");
} }
// throw.. // throw..
if ( Match(tok, "throw") ) if ( Tokenizer::Match(tok, "throw") )
addtoken("throw"); addtoken("throw");
// Assignment.. // Assignment..
if ( Match(tok,"[)=] %var1% [;)]", varnames) ) if ( Tokenizer::Match(tok,"[)=] %var1% [;)]", varnames) )
addtoken("use"); addtoken("use");
// Investigate function calls.. // Investigate function calls..
if ( Match(tok, "%var% (") ) if ( Tokenizer::Match(tok, "%var% (") )
{ {
const char *str = call_func(tok, callstack, varnames, alloctype, dealloctype); const char *str = call_func(tok, callstack, varnames, alloctype, dealloctype);
if ( str ) if ( str )
@ -480,7 +475,7 @@ TOKEN *CheckMemoryLeakClass::getcode(const TOKEN *tok, std::list<const TOKEN *>
} }
// Linux lists.. // Linux lists..
if ( Match( tok, "[=(,] & %var1% [.[]", varnames ) ) if ( Tokenizer::Match( tok, "[=(,] & %var1% [.[]", varnames ) )
{ {
// todo: better checking // todo: better checking
addtoken("use"); addtoken("use");
@ -517,7 +512,7 @@ void CheckMemoryLeakClass::simplifycode(TOKEN *tok)
// { x } while(y) { x }" // { x } while(y) { x }"
for ( TOKEN *tok2 = tok; tok2; tok2 = tok2->next ) for ( TOKEN *tok2 = tok; tok2; tok2 = tok2->next )
{ {
if ( ! Match(tok2->next, "do") ) if ( ! Tokenizer::Match(tok2->next, "do") )
continue; continue;
// Remove the next token "do" // Remove the next token "do"
@ -529,13 +524,13 @@ void CheckMemoryLeakClass::simplifycode(TOKEN *tok)
int indentlevel = 0; int indentlevel = 0;
for ( tok2_ = tok2; tok2_ && indentlevel>=0; tok2_ = tok2_->next ) for ( tok2_ = tok2; tok2_ && indentlevel>=0; tok2_ = tok2_->next )
{ {
if ( Match(tok2_, "{") ) if ( Tokenizer::Match(tok2_, "{") )
++indentlevel; ++indentlevel;
else if ( Match(tok2_, "}") ) else if ( Tokenizer::Match(tok2_, "}") )
--indentlevel; --indentlevel;
else if ( indentlevel == 0 && Match(tok2_->next, ";") ) else if ( indentlevel == 0 && Tokenizer::Match(tok2_->next, ";") )
break; break;
} }
@ -547,9 +542,9 @@ void CheckMemoryLeakClass::simplifycode(TOKEN *tok)
indentlevel = 0; indentlevel = 0;
do do
{ {
if ( Match( tok2, "{" ) ) if ( Tokenizer::Match( tok2, "{" ) )
++indentlevel; ++indentlevel;
else if ( Match(tok2, "}") ) else if ( Tokenizer::Match(tok2, "}") )
--indentlevel; --indentlevel;
// Copy token.. // Copy token..
@ -572,14 +567,14 @@ void CheckMemoryLeakClass::simplifycode(TOKEN *tok)
for (TOKEN *tok2 = tok; tok2; tok2 = tok2 ? tok2->next : NULL ) for (TOKEN *tok2 = tok; tok2; tok2 = tok2 ? tok2->next : NULL )
{ {
// Delete extra ";" // Delete extra ";"
while (Match(tok2,"[;{}] ;")) while (Tokenizer::Match(tok2,"[;{}] ;"))
{ {
erase(tok2, Tokenizer::gettok(tok2,2)); erase(tok2, Tokenizer::gettok(tok2,2));
done = false; done = false;
} }
// Replace "{ }" with ";" // Replace "{ }" with ";"
if ( Match(tok2->next, "{ }") ) if ( Tokenizer::Match(tok2->next, "{ }") )
{ {
tok2->next->setstr(";"); tok2->next->setstr(";");
erase(tok2->next, Tokenizer::gettok(tok2,3)); erase(tok2->next, Tokenizer::gettok(tok2,3));
@ -587,13 +582,13 @@ void CheckMemoryLeakClass::simplifycode(TOKEN *tok)
} }
// Delete braces around a single instruction.. // Delete braces around a single instruction..
if ( Match(tok2->next, "{ %var% ; }") ) if ( Tokenizer::Match(tok2->next, "{ %var% ; }") )
{ {
erase( tok2, Tokenizer::gettok(tok2,2) ); erase( tok2, Tokenizer::gettok(tok2,2) );
erase( tok2->next->next, Tokenizer::gettok(tok2,4) ); erase( tok2->next->next, Tokenizer::gettok(tok2,4) );
done = false; done = false;
} }
if ( Match(tok2->next, "{ return use ; }") ) if ( Tokenizer::Match(tok2->next, "{ return use ; }") )
{ {
erase( tok2, Tokenizer::gettok(tok2,2) ); erase( tok2, Tokenizer::gettok(tok2,2) );
erase( tok2->next->next->next, Tokenizer::gettok(tok2,5) ); erase( tok2->next->next->next, Tokenizer::gettok(tok2,5) );
@ -601,12 +596,12 @@ void CheckMemoryLeakClass::simplifycode(TOKEN *tok)
} }
// Delete empty if that is not followed by an else // Delete empty if that is not followed by an else
if ( Match(tok2,"[;{}] if ;") || if ( Tokenizer::Match(tok2,"[;{}] if ;") ||
Match(tok2,"[;{}] if(var) ;") || Tokenizer::Match(tok2,"[;{}] if(var) ;") ||
Match(tok2,"[;{}] if(!var) ;") || Tokenizer::Match(tok2,"[;{}] if(!var) ;") ||
Match(tok2,"[;{}] ifv ;") ) Tokenizer::Match(tok2,"[;{}] ifv ;") )
{ {
if ( ! Match(Tokenizer::gettok(tok2,3), "else") ) if ( ! Tokenizer::Match(Tokenizer::gettok(tok2,3), "else") )
{ {
erase(tok2, Tokenizer::gettok(tok2, 3)); erase(tok2, Tokenizer::gettok(tok2, 3));
done = false; done = false;
@ -617,22 +612,22 @@ void CheckMemoryLeakClass::simplifycode(TOKEN *tok)
// Delete "if dealloc ;" and "if use ;" that is not followed by an else.. // Delete "if dealloc ;" and "if use ;" that is not followed by an else..
// This may cause false positives // This may cause false positives
if (_settings._showAll && if (_settings._showAll &&
(Match(tok2, "[;{}] if dealloc ;") || Match(tok2, "[;{}] if use ;")) && (Tokenizer::Match(tok2, "[;{}] if dealloc ;") || Tokenizer::Match(tok2, "[;{}] if use ;")) &&
!Match(Tokenizer::gettok(tok2,4), "else")) !Tokenizer::Match(Tokenizer::gettok(tok2,4), "else"))
{ {
erase(tok2->next, Tokenizer::gettok(tok2,3)); erase(tok2->next, Tokenizer::gettok(tok2,3));
done = false; done = false;
} }
// Delete if block: "alloc; if return use ;" // Delete if block: "alloc; if return use ;"
if (Match(tok2,"alloc ; if return use ;") && !Match(Tokenizer::gettok(tok2,6),"else")) if (Tokenizer::Match(tok2,"alloc ; if return use ;") && !Tokenizer::Match(Tokenizer::gettok(tok2,6),"else"))
{ {
erase(tok2, Tokenizer::gettok(tok2,5)); erase(tok2, Tokenizer::gettok(tok2,5));
done = false; done = false;
} }
// "[;{}] if alloc ; else return ;" => "[;{}] alloc ;" // "[;{}] if alloc ; else return ;" => "[;{}] alloc ;"
if (Match(tok2,"[;{}] if alloc ; else return ;")) if (Tokenizer::Match(tok2,"[;{}] if alloc ; else return ;"))
{ {
erase(tok2, Tokenizer::gettok(tok2,2)); // Remove "if" erase(tok2, Tokenizer::gettok(tok2,2)); // Remove "if"
erase(tok2->next, Tokenizer::gettok(tok2,5)); // Remove "; else return" erase(tok2->next, Tokenizer::gettok(tok2,5)); // Remove "; else return"
@ -640,68 +635,68 @@ void CheckMemoryLeakClass::simplifycode(TOKEN *tok)
} }
// Replace "dealloc use ;" with "dealloc ;" // Replace "dealloc use ;" with "dealloc ;"
if ( Match(tok2, "dealloc use ;") ) if ( Tokenizer::Match(tok2, "dealloc use ;") )
{ {
erase(tok2, Tokenizer::gettok(tok2,2)); erase(tok2, Tokenizer::gettok(tok2,2));
done = false; done = false;
} }
// Reducing if.. // Reducing if..
if (Match(tok2,"if dealloc ; else") || Match(tok2,"if use ; else")) if (Tokenizer::Match(tok2,"if dealloc ; else") || Tokenizer::Match(tok2,"if use ; else"))
{ {
erase(tok2, Tokenizer::gettok(tok2, 2)); erase(tok2, Tokenizer::gettok(tok2, 2));
done = false; done = false;
} }
if (Match(tok2,"[;{}] if { dealloc ; return ; }") && !Match(Tokenizer::gettok(tok2,8),"else")) if (Tokenizer::Match(tok2,"[;{}] if { dealloc ; return ; }") && !Tokenizer::Match(Tokenizer::gettok(tok2,8),"else"))
{ {
erase(tok2,Tokenizer::gettok(tok2,8)); erase(tok2,Tokenizer::gettok(tok2,8));
done = false; done = false;
} }
// Replace "loop ;" with ";" // Replace "loop ;" with ";"
if ( Match(tok2->next, "loop ;") ) if ( Tokenizer::Match(tok2->next, "loop ;") )
{ {
erase(tok2, Tokenizer::gettok(tok2,2)); erase(tok2, Tokenizer::gettok(tok2,2));
done = false; done = false;
} }
// Replace "loop !var ;" with ";" // Replace "loop !var ;" with ";"
if ( Match(tok2->next, "loop !var ;") ) if ( Tokenizer::Match(tok2->next, "loop !var ;") )
{ {
erase(tok2, Tokenizer::gettok(tok2,4)); erase(tok2, Tokenizer::gettok(tok2,4));
done = false; done = false;
} }
// Replace "loop !var alloc ;" with " alloc ;" // Replace "loop !var alloc ;" with " alloc ;"
if ( Match(tok2->next, "loop !var alloc ;") ) if ( Tokenizer::Match(tok2->next, "loop !var alloc ;") )
{ {
erase(tok2, Tokenizer::gettok(tok2,3)); erase(tok2, Tokenizer::gettok(tok2,3));
done = false; done = false;
} }
// Delete if block in "alloc ; if(!var) return ;" // Delete if block in "alloc ; if(!var) return ;"
if ( Match(tok2, "alloc ; if(!var) return ;") ) if ( Tokenizer::Match(tok2, "alloc ; if(!var) return ;") )
{ {
erase(tok2, Tokenizer::gettok(tok2,4)); erase(tok2, Tokenizer::gettok(tok2,4));
done = false; done = false;
} }
// Delete second use in "use ; use ;" // Delete second use in "use ; use ;"
while (Match(tok2, "[;{}] use ; use ;")) while (Tokenizer::Match(tok2, "[;{}] use ; use ;"))
{ {
erase(tok2, Tokenizer::gettok(tok2,3)); erase(tok2, Tokenizer::gettok(tok2,3));
done = false; done = false;
} }
// Delete second case in "case ; case ;" // Delete second case in "case ; case ;"
while (Match(tok2, "case ; case ;")) while (Tokenizer::Match(tok2, "case ; case ;"))
{ {
erase(tok2, Tokenizer::gettok(tok2,3)); erase(tok2, Tokenizer::gettok(tok2,3));
done = false; done = false;
} }
// Replace switch with if (if not complicated) // Replace switch with if (if not complicated)
if (Match(tok2, "switch {")) if (Tokenizer::Match(tok2, "switch {"))
{ {
// Right now, I just handle if there are a few case and perhaps a default. // Right now, I just handle if there are a few case and perhaps a default.
bool valid = false; bool valid = false;
@ -726,11 +721,11 @@ void CheckMemoryLeakClass::simplifycode(TOKEN *tok)
else if (strcmp(_tok->str,"loop")==0) else if (strcmp(_tok->str,"loop")==0)
break; break;
else if (incase && Match(_tok,"case")) else if (incase && Tokenizer::Match(_tok,"case"))
break; break;
incase |= Match(_tok,"case"); incase |= Tokenizer::Match(_tok,"case");
incase &= !Match(_tok,"break"); incase &= !Tokenizer::Match(_tok,"break");
} }
if ( !incase && valid ) if ( !incase && valid )
@ -740,9 +735,9 @@ void CheckMemoryLeakClass::simplifycode(TOKEN *tok)
erase( tok2, Tokenizer::gettok(tok2, 2) ); erase( tok2, Tokenizer::gettok(tok2, 2) );
tok2 = tok2->next; tok2 = tok2->next;
bool first = true; bool first = true;
while (Match(tok2,"case") || Match(tok2,"default")) while (Tokenizer::Match(tok2,"case") || Tokenizer::Match(tok2,"default"))
{ {
bool def = Match(tok2, "default"); bool def = Tokenizer::Match(tok2, "default");
tok2->setstr(first ? "if" : "}"); tok2->setstr(first ? "if" : "}");
if ( first ) if ( first )
{ {
@ -757,9 +752,9 @@ void CheckMemoryLeakClass::simplifycode(TOKEN *tok)
instoken( tok2, "if" ); instoken( tok2, "if" );
instoken( tok2, "else" ); instoken( tok2, "else" );
} }
while ( tok2 && tok2->str[0] != '}' && ! Match(tok2,"break ;") ) while ( tok2 && tok2->str[0] != '}' && ! Tokenizer::Match(tok2,"break ;") )
tok2 = tok2->next; tok2 = tok2->next;
if (Match(tok2,"break ;")) if (Tokenizer::Match(tok2,"break ;"))
{ {
tok2->setstr(";"); tok2->setstr(";");
tok2 = tok2->next->next; tok2 = tok2->next->next;
@ -768,7 +763,7 @@ void CheckMemoryLeakClass::simplifycode(TOKEN *tok)
} }
} }
if ( Match(tok2, "throw") ) if ( Tokenizer::Match(tok2, "throw") )
{ {
tok2->setstr( "return" ); tok2->setstr( "return" );
done = false; done = false;
@ -889,20 +884,20 @@ void CheckMemoryLeakClass::CheckMemoryLeak_InFunction()
// In function.. // In function..
if ( indentlevel == 0 ) if ( indentlevel == 0 )
{ {
if ( Match(tok, ") {") ) if ( Tokenizer::Match(tok, ") {") )
infunc = true; infunc = true;
if ( Match(tok, "[;}]") ) if ( Tokenizer::Match(tok, "[;}]") )
infunc = false; infunc = false;
} }
// Declare a local variable => Check // Declare a local variable => Check
if (indentlevel>0 && infunc) if (indentlevel>0 && infunc)
{ {
if ( Match(tok, "[{};] %type% * %var% [;=]") ) if ( Tokenizer::Match(tok, "[{};] %type% * %var% [;=]") )
CheckMemoryLeak_CheckScope( tok->next, Tokenizer::getstr(tok, 3) ); CheckMemoryLeak_CheckScope( tok->next, Tokenizer::getstr(tok, 3) );
else if ( Match(tok, "[{};] %type% %type% * %var% [;=]") ) else if ( Tokenizer::Match(tok, "[{};] %type% %type% * %var% [;=]") )
CheckMemoryLeak_CheckScope( tok->next, Tokenizer::getstr(tok, 4) ); CheckMemoryLeak_CheckScope( tok->next, Tokenizer::getstr(tok, 4) );
} }
} }
@ -928,7 +923,7 @@ void CheckMemoryLeakClass::CheckMemoryLeak_ClassMembers()
else if ( tok->str[0] == '}' ) else if ( tok->str[0] == '}' )
indentlevel--; indentlevel--;
else if ( indentlevel == 0 && Match(tok, "class %var% [{:]") ) else if ( indentlevel == 0 && Tokenizer::Match(tok, "class %var% [{:]") )
{ {
std::vector<const char *> classname; std::vector<const char *> classname;
classname.push_back( Tokenizer::getstr(tok, 1) ); classname.push_back( Tokenizer::getstr(tok, 1) );
@ -964,7 +959,7 @@ void CheckMemoryLeakClass::CheckMemoryLeak_ClassMembers_ParseClass( const TOKEN
continue; continue;
// Declaring subclass.. recursive checking // Declaring subclass.. recursive checking
if ( Match(tok, "class %var% [{:]") ) if ( Tokenizer::Match(tok, "class %var% [{:]") )
{ {
classname.push_back( Tokenizer::getstr(tok, 1) ); classname.push_back( Tokenizer::getstr(tok, 1) );
CheckMemoryLeak_ClassMembers_ParseClass( tok, classname ); CheckMemoryLeak_ClassMembers_ParseClass( tok, classname );
@ -972,9 +967,9 @@ void CheckMemoryLeakClass::CheckMemoryLeak_ClassMembers_ParseClass( const TOKEN
} }
// Declaring member variable.. check allocations and deallocations // Declaring member variable.. check allocations and deallocations
if ( Match(tok->next, "%type% * %var% ;") ) if ( Tokenizer::Match(tok->next, "%type% * %var% ;") )
{ {
if ( IsName(tok->str) || strchr(";}", tok->str[0]) ) if ( Tokenizer::IsName(tok->str) || strchr(";}", tok->str[0]) )
{ {
if (_settings._showAll || !isclass(Tokenizer::getstr(tok,1))) if (_settings._showAll || !isclass(Tokenizer::getstr(tok,1)))
CheckMemoryLeak_ClassMembers_Variable( classname, Tokenizer::getstr(tok, 3) ); CheckMemoryLeak_ClassMembers_Variable( classname, Tokenizer::getstr(tok, 3) );
@ -1031,7 +1026,7 @@ void CheckMemoryLeakClass::CheckMemoryLeak_ClassMembers_Variable( const std::vec
{ {
if ( strchr(";}", tok->str[0]) ) if ( strchr(";}", tok->str[0]) )
memberfunction = false; memberfunction = false;
else if ( Match( tok, fpattern.str().c_str() ) || Match( tok, destructor.str().c_str() ) ) else if ( Tokenizer::Match( tok, fpattern.str().c_str() ) || Tokenizer::Match( tok, destructor.str().c_str() ) )
memberfunction = true; memberfunction = true;
} }
@ -1039,7 +1034,7 @@ void CheckMemoryLeakClass::CheckMemoryLeak_ClassMembers_Variable( const std::vec
if ( indentlevel > 0 && memberfunction ) if ( indentlevel > 0 && memberfunction )
{ {
// Allocate.. // Allocate..
if ( Match( tok, varname_eq.str().c_str() ) ) if ( Tokenizer::Match( tok, varname_eq.str().c_str() ) )
{ {
AllocType alloc = GetAllocationType( Tokenizer::gettok( tok, 2 ) ); AllocType alloc = GetAllocationType( Tokenizer::gettok( tok, 2 ) );
if ( alloc != No ) if ( alloc != No )

View File

@ -20,8 +20,6 @@
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
#include "CheckOther.h" #include "CheckOther.h"
#include "CommonCheck.h"
#include <list> #include <list>
#include <map> #include <map>
#include <sstream> #include <sstream>
@ -52,7 +50,7 @@ void CheckOther::WarningOldStylePointerCast()
for (const TOKEN *tok = _tokenizer->tokens(); tok; tok = tok->next) for (const TOKEN *tok = _tokenizer->tokens(); tok; tok = tok->next)
{ {
// Old style pointer casting.. // Old style pointer casting..
if (!Match(tok, "( %type% * ) %var%")) if (!Tokenizer::Match(tok, "( %type% * ) %var%"))
continue; continue;
// Is "type" a class? // Is "type" a class?
@ -79,10 +77,10 @@ void CheckOther::WarningIsDigit()
for (const TOKEN *tok = _tokenizer->tokens(); tok; tok = tok->next) for (const TOKEN *tok = _tokenizer->tokens(); tok; tok = tok->next)
{ {
bool err = false; bool err = false;
err |= Match(tok, "%var% >= '0' && %var% <= '9'"); err |= Tokenizer::Match(tok, "%var% >= '0' && %var% <= '9'");
err |= Match(tok, "* %var% >= '0' && * %var% <= '9'"); err |= Tokenizer::Match(tok, "* %var% >= '0' && * %var% <= '9'");
err |= Match(tok, "( %var% >= '0' ) && ( %var% <= '9' )"); err |= Tokenizer::Match(tok, "( %var% >= '0' ) && ( %var% <= '9' )");
err |= Match(tok, "( * %var% >= '0' ) && ( * %var% <= '9' )"); err |= Tokenizer::Match(tok, "( * %var% >= '0' ) && ( * %var% <= '9' )");
if (err) if (err)
{ {
std::ostringstream ostr; std::ostringstream ostr;
@ -103,15 +101,15 @@ void CheckOther::WarningIsAlpha()
{ {
for (const TOKEN *tok = _tokenizer->tokens(); tok; tok = tok->next) for (const TOKEN *tok = _tokenizer->tokens(); tok; tok = tok->next)
{ {
if ( ! Match(tok, "(") ) if ( ! Tokenizer::Match(tok, "(") )
continue; continue;
bool err = false; bool err = false;
err |= Match(tok, "( %var% >= 'A' && %var% <= 'Z' )"); err |= Tokenizer::Match(tok, "( %var% >= 'A' && %var% <= 'Z' )");
err |= Match(tok, "( * %var% >= 'A' && * %var% <= 'Z' )"); err |= Tokenizer::Match(tok, "( * %var% >= 'A' && * %var% <= 'Z' )");
err |= Match(tok, "( ( %var% >= 'A' ) && ( %var% <= 'Z' ) )"); err |= Tokenizer::Match(tok, "( ( %var% >= 'A' ) && ( %var% <= 'Z' ) )");
err |= Match(tok, "( ( * %var% >= 'A' ) && ( * %var% <= 'Z' ) )"); err |= Tokenizer::Match(tok, "( ( * %var% >= 'A' ) && ( * %var% <= 'Z' ) )");
if (err) if (err)
{ {
std::ostringstream ostr; std::ostringstream ostr;
@ -121,10 +119,10 @@ void CheckOther::WarningIsAlpha()
} }
err = false; err = false;
err |= Match(tok, "( %var% >= 'a' && %var% <= 'z' )"); err |= Tokenizer::Match(tok, "( %var% >= 'a' && %var% <= 'z' )");
err |= Match(tok, "( * %var% >= 'a' && * %var% <= 'z' )"); err |= Tokenizer::Match(tok, "( * %var% >= 'a' && * %var% <= 'z' )");
err |= Match(tok, "( ( %var% >= 'a' ) && ( %var% <= 'z' ) )"); err |= Tokenizer::Match(tok, "( ( %var% >= 'a' ) && ( %var% <= 'z' ) )");
err |= Match(tok, "( ( * %var% >= 'a' ) && ( * %var% <= 'z' ) )"); err |= Tokenizer::Match(tok, "( ( * %var% >= 'a' ) && ( * %var% <= 'z' ) )");
if (err) if (err)
{ {
std::ostringstream ostr; std::ostringstream ostr;
@ -134,14 +132,14 @@ void CheckOther::WarningIsAlpha()
} }
err = false; err = false;
err |= Match(tok, "( %var% >= 'A' && %var% <= 'Z' ) || ( %var% >= 'a' && %var% <= 'z' )"); err |= Tokenizer::Match(tok, "( %var% >= 'A' && %var% <= 'Z' ) || ( %var% >= 'a' && %var% <= 'z' )");
err |= Match(tok, "( %var% >= 'a' && %var% <= 'z' ) || ( %var% >= 'A' && %var% <= 'Z' )"); err |= Tokenizer::Match(tok, "( %var% >= 'a' && %var% <= 'z' ) || ( %var% >= 'A' && %var% <= 'Z' )");
err |= Match(tok, "( * %var% >= 'A' && * %var% <= 'Z' ) || ( * %var% >= 'a' && * %var% <= 'z' )"); err |= Tokenizer::Match(tok, "( * %var% >= 'A' && * %var% <= 'Z' ) || ( * %var% >= 'a' && * %var% <= 'z' )");
err |= Match(tok, "( * %var% >= 'a' && * %var% <= 'z' ) || ( * %var% >= 'A' && * %var% <= 'Z' )"); err |= Tokenizer::Match(tok, "( * %var% >= 'a' && * %var% <= 'z' ) || ( * %var% >= 'A' && * %var% <= 'Z' )");
err |= Match(tok, "( ( %var% >= 'A' ) && ( %var% <= 'Z' ) ) || ( ( %var% >= 'a' ) && ( %var% <= 'z' ) )"); err |= Tokenizer::Match(tok, "( ( %var% >= 'A' ) && ( %var% <= 'Z' ) ) || ( ( %var% >= 'a' ) && ( %var% <= 'z' ) )");
err |= Match(tok, "( ( %var% >= 'a' ) && ( %var% <= 'z' ) ) || ( ( %var% >= 'A' ) && ( %var% <= 'Z' ) )"); err |= Tokenizer::Match(tok, "( ( %var% >= 'a' ) && ( %var% <= 'z' ) ) || ( ( %var% >= 'A' ) && ( %var% <= 'Z' ) )");
err |= Match(tok, "( ( * %var% >= 'A' ) && ( * %var% <= 'Z' ) ) || ( ( * var >= 'a' ) && ( * %var% <= 'z' ) )"); err |= Tokenizer::Match(tok, "( ( * %var% >= 'A' ) && ( * %var% <= 'Z' ) ) || ( ( * var >= 'a' ) && ( * %var% <= 'z' ) )");
err |= Match(tok, "( ( * %var% >= 'a' ) && ( * %var% <= 'z' ) ) || ( ( * var >= 'A' ) && ( * %var% <= 'Z' ) )"); err |= Tokenizer::Match(tok, "( ( * %var% >= 'a' ) && ( * %var% <= 'z' ) ) || ( ( * var >= 'A' ) && ( * %var% <= 'Z' ) )");
if (err) if (err)
{ {
std::ostringstream ostr; std::ostringstream ostr;
@ -163,18 +161,18 @@ void CheckOther::WarningRedundantCode()
// if (p) delete p // if (p) delete p
for (const TOKEN *tok = _tokenizer->tokens(); tok; tok = tok->next) for (const TOKEN *tok = _tokenizer->tokens(); tok; tok = tok->next)
{ {
if (!Match(tok,"if")) if (!Tokenizer::Match(tok,"if"))
continue; continue;
const char *varname1 = NULL; const char *varname1 = NULL;
const TOKEN *tok2 = NULL; const TOKEN *tok2 = NULL;
if (Match(tok,"if ( %var% )")) if (Tokenizer::Match(tok,"if ( %var% )"))
{ {
varname1 = Tokenizer::getstr(tok, 2); varname1 = Tokenizer::getstr(tok, 2);
tok2 = Tokenizer::gettok(tok, 4); tok2 = Tokenizer::gettok(tok, 4);
} }
else if (Match(tok,"if ( %var% != NULL )")) else if (Tokenizer::Match(tok,"if ( %var% != NULL )"))
{ {
varname1 = Tokenizer::getstr(tok, 2); varname1 = Tokenizer::getstr(tok, 2);
tok2 = Tokenizer::gettok(tok, 6); tok2 = Tokenizer::gettok(tok, 6);
@ -183,17 +181,17 @@ void CheckOther::WarningRedundantCode()
if (varname1==NULL || tok2==NULL) if (varname1==NULL || tok2==NULL)
continue; continue;
if ( Match(tok2, "{") ) if ( Tokenizer::Match(tok2, "{") )
tok2 = tok2->next; tok2 = tok2->next;
bool err = false; bool err = false;
if (Match(tok2,"delete %var% ;")) if (Tokenizer::Match(tok2,"delete %var% ;"))
err = (strcmp(Tokenizer::getstr(tok2,1),varname1)==0); err = (strcmp(Tokenizer::getstr(tok2,1),varname1)==0);
else if (Match(tok2,"delete [ ] %var% ;")) else if (Tokenizer::Match(tok2,"delete [ ] %var% ;"))
err = (strcmp(Tokenizer::getstr(tok2,1),varname1)==0); err = (strcmp(Tokenizer::getstr(tok2,1),varname1)==0);
else if (Match(tok2,"free ( %var% )")) else if (Tokenizer::Match(tok2,"free ( %var% )"))
err = (strcmp(Tokenizer::getstr(tok2,2),varname1)==0); err = (strcmp(Tokenizer::getstr(tok2,2),varname1)==0);
else if (Match(tok2,"kfree ( %var% )")) else if (Tokenizer::Match(tok2,"kfree ( %var% )"))
err = (strcmp(Tokenizer::getstr(tok2,2),varname1)==0); err = (strcmp(Tokenizer::getstr(tok2,2),varname1)==0);
if (err) if (err)
@ -225,14 +223,14 @@ void CheckOther::WarningIf()
// Search for 'if (condition);' // Search for 'if (condition);'
for (const TOKEN *tok = _tokenizer->tokens(); tok; tok = tok->next) for (const TOKEN *tok = _tokenizer->tokens(); tok; tok = tok->next)
{ {
if (Match(tok,"if")) if (Tokenizer::Match(tok,"if"))
{ {
int parlevel = 0; int parlevel = 0;
for (const TOKEN *tok2 = tok->next; tok2; tok2 = tok2->next) for (const TOKEN *tok2 = tok->next; tok2; tok2 = tok2->next)
{ {
if (Match(tok2,"(")) if (Tokenizer::Match(tok2,"("))
parlevel++; parlevel++;
else if (Match(tok2,")")) else if (Tokenizer::Match(tok2,")"))
{ {
parlevel--; parlevel--;
if (parlevel<=0) if (parlevel<=0)
@ -255,13 +253,13 @@ void CheckOther::WarningIf()
for (const TOKEN *tok = _tokenizer->tokens(); tok; tok = tok->next) for (const TOKEN *tok = _tokenizer->tokens(); tok; tok = tok->next)
{ {
// Begin statement? // Begin statement?
if ( ! Match(tok, "[;{}]") ) if ( ! Tokenizer::Match(tok, "[;{}]") )
continue; continue;
tok = tok->next; tok = tok->next;
if ( ! tok ) if ( ! tok )
break; break;
if (!Match(tok,"%var% = %var% ; if ( %var%")) if (!Tokenizer::Match(tok,"%var% = %var% ; if ( %var%"))
continue; continue;
if ( strcmp(Tokenizer::getstr(tok, 9), ")") != 0 ) if ( strcmp(Tokenizer::getstr(tok, 9), ")") != 0 )
@ -314,7 +312,7 @@ void CheckOther::InvalidFunctionUsage()
{ {
for ( const TOKEN *tok = _tokenizer->tokens(); tok; tok = tok->next ) for ( const TOKEN *tok = _tokenizer->tokens(); tok; tok = tok->next )
{ {
if (!Match(tok, "strtol") && !Match(tok, "strtoul")) if (!Tokenizer::Match(tok, "strtol") && !Tokenizer::Match(tok, "strtoul"))
continue; continue;
// Locate the third parameter of the function call.. // Locate the third parameter of the function call..
@ -322,16 +320,16 @@ void CheckOther::InvalidFunctionUsage()
int param = 1; int param = 1;
for ( const TOKEN *tok2 = tok->next; tok2; tok2 = tok2->next ) for ( const TOKEN *tok2 = tok->next; tok2; tok2 = tok2->next )
{ {
if ( Match(tok2, "(") ) if ( Tokenizer::Match(tok2, "(") )
parlevel++; parlevel++;
else if (Match(tok2, ")")) else if (Tokenizer::Match(tok2, ")"))
parlevel--; parlevel--;
else if (parlevel == 1 && Match(tok2, ",")) else if (parlevel == 1 && Tokenizer::Match(tok2, ","))
{ {
param++; param++;
if (param==3) if (param==3)
{ {
if ( Match(tok2, ", %num% )") ) if ( Tokenizer::Match(tok2, ", %num% )") )
{ {
int radix = atoi(Tokenizer::getstr(tok2, 1)); int radix = atoi(Tokenizer::getstr(tok2, 1));
if (!(radix==0 || (radix>=2 && radix<=36))) if (!(radix==0 || (radix>=2 && radix<=36)))
@ -358,9 +356,9 @@ void CheckOther::CheckIfAssignment()
{ {
for (const TOKEN *tok = _tokenizer->tokens(); tok; tok = tok->next) for (const TOKEN *tok = _tokenizer->tokens(); tok; tok = tok->next)
{ {
if (Match(tok, "if ( %var% = %num% )") || if (Tokenizer::Match(tok, "if ( %var% = %num% )") ||
Match(tok, "if ( %var% = %str% )") || Tokenizer::Match(tok, "if ( %var% = %str% )") ||
Match(tok, "if ( %var% = %var% )") ) Tokenizer::Match(tok, "if ( %var% = %var% )") )
{ {
std::ostringstream ostr; std::ostringstream ostr;
ostr << _tokenizer->fileLine(tok) << ": Possible bug. Should it be '==' instead of '='?"; ostr << _tokenizer->fileLine(tok) << ": Possible bug. Should it be '==' instead of '='?";
@ -381,17 +379,17 @@ void CheckOther::CheckUnsignedDivision()
std::map<std::string, char> varsign; std::map<std::string, char> varsign;
for ( const TOKEN *tok = _tokenizer->tokens(); tok; tok = tok->next ) for ( const TOKEN *tok = _tokenizer->tokens(); tok; tok = tok->next )
{ {
if ( Match(tok, "[{};(,] %type% %var% [;=,)]") ) if ( Tokenizer::Match(tok, "[{};(,] %type% %var% [;=,)]") )
{ {
const char *type = Tokenizer::getstr(tok, 1); const char *type = Tokenizer::getstr(tok, 1);
if (strcmp(type,"char")==0 || strcmp(type,"short")==0 || strcmp(type,"int")==0) if (strcmp(type,"char")==0 || strcmp(type,"short")==0 || strcmp(type,"int")==0)
varsign[Tokenizer::getstr(tok,2)] = 's'; varsign[Tokenizer::getstr(tok,2)] = 's';
} }
else if ( Match(tok, "[{};(,] unsigned %type% %var% [;=,)]") ) else if ( Tokenizer::Match(tok, "[{};(,] unsigned %type% %var% [;=,)]") )
varsign[Tokenizer::getstr(tok,3)] = 'u'; varsign[Tokenizer::getstr(tok,3)] = 'u';
else if (!Match(tok,"[).]") && Match(tok->next, "%var% / %var%")) else if (!Tokenizer::Match(tok,"[).]") && Tokenizer::Match(tok->next, "%var% / %var%"))
{ {
const char *varname1 = Tokenizer::getstr(tok,1); const char *varname1 = Tokenizer::getstr(tok,1);
const char *varname2 = Tokenizer::getstr(tok,3); const char *varname2 = Tokenizer::getstr(tok,3);
@ -407,7 +405,7 @@ void CheckOther::CheckUnsignedDivision()
} }
} }
else if (!Match(tok,"[).]") && Match(tok->next, "%var% / - %num%")) else if (!Tokenizer::Match(tok,"[).]") && Tokenizer::Match(tok->next, "%var% / - %num%"))
{ {
const char *varname1 = Tokenizer::getstr(tok,1); const char *varname1 = Tokenizer::getstr(tok,1);
char sign1 = varsign[varname1]; char sign1 = varsign[varname1];
@ -419,7 +417,7 @@ void CheckOther::CheckUnsignedDivision()
} }
} }
else if (Match(tok, "[([=*/+-] - %num% / %var%")) else if (Tokenizer::Match(tok, "[([=*/+-] - %num% / %var%"))
{ {
const char *varname2 = Tokenizer::getstr(tok,4); const char *varname2 = Tokenizer::getstr(tok,4);
char sign2 = varsign[varname2]; char sign2 = varsign[varname2];
@ -449,21 +447,21 @@ void CheckOther::CheckVariableScope()
for ( const TOKEN *tok = _tokenizer->tokens(); tok; tok = tok->next ) for ( const TOKEN *tok = _tokenizer->tokens(); tok; tok = tok->next )
{ {
// Skip class and struct declarations.. // Skip class and struct declarations..
if ( Match(tok, "class") || Match(tok, "struct") ) if ( Tokenizer::Match(tok, "class") || Tokenizer::Match(tok, "struct") )
{ {
for (const TOKEN *tok2 = tok; tok2; tok2 = tok2->next) for (const TOKEN *tok2 = tok; tok2; tok2 = tok2->next)
{ {
if ( Match(tok2, "{") ) if ( Tokenizer::Match(tok2, "{") )
{ {
int _indentlevel = 0; int _indentlevel = 0;
tok = tok2; tok = tok2;
for (tok = tok2; tok; tok = tok->next) for (tok = tok2; tok; tok = tok->next)
{ {
if ( Match(tok, "{") ) if ( Tokenizer::Match(tok, "{") )
{ {
_indentlevel++; _indentlevel++;
} }
if ( Match(tok, "}") ) if ( Tokenizer::Match(tok, "}") )
{ {
_indentlevel--; _indentlevel--;
if ( _indentlevel <= 0 ) if ( _indentlevel <= 0 )
@ -475,7 +473,7 @@ void CheckOther::CheckVariableScope()
} }
break; break;
} }
if (Match(tok2, "[,);]")) if (Tokenizer::Match(tok2, "[,);]"))
{ {
break; break;
} }
@ -484,36 +482,36 @@ void CheckOther::CheckVariableScope()
break; break;
} }
if ( Match(tok, "{") ) if ( Tokenizer::Match(tok, "{") )
{ {
indentlevel++; indentlevel++;
} }
if ( Match(tok, "}") ) if ( Tokenizer::Match(tok, "}") )
{ {
indentlevel--; indentlevel--;
if ( indentlevel == 0 ) if ( indentlevel == 0 )
func = false; func = false;
} }
if ( indentlevel == 0 && Match(tok, ") {") ) if ( indentlevel == 0 && Tokenizer::Match(tok, ") {") )
{ {
func = true; func = true;
} }
if ( indentlevel > 0 && func && Match(tok, "[{};]") ) if ( indentlevel > 0 && func && Tokenizer::Match(tok, "[{};]") )
{ {
// First token of statement.. // First token of statement..
const TOKEN *tok1 = tok->next; const TOKEN *tok1 = tok->next;
if ( ! tok1 ) if ( ! tok1 )
continue; continue;
if (Match(tok1,"return") || if (Tokenizer::Match(tok1,"return") ||
Match(tok1,"delete") || Tokenizer::Match(tok1,"delete") ||
Match(tok1,"goto") || Tokenizer::Match(tok1,"goto") ||
Match(tok1,"else")) Tokenizer::Match(tok1,"else"))
continue; continue;
// Variable declaration? // Variable declaration?
if (Match(tok1, "%var% %var% ;") || if (Tokenizer::Match(tok1, "%var% %var% ;") ||
Match(tok1, "%var% %var% =") ) Tokenizer::Match(tok1, "%var% %var% =") )
{ {
CheckVariableScope_LookupVar( tok1, Tokenizer::getstr(tok1, 1) ); CheckVariableScope_LookupVar( tok1, Tokenizer::getstr(tok1, 1) );
} }
@ -528,7 +526,7 @@ void CheckOther::CheckVariableScope_LookupVar( const TOKEN *tok1, const char var
const TOKEN *tok = tok1; const TOKEN *tok = tok1;
// Skip the variable declaration.. // Skip the variable declaration..
while (tok && !Match(tok,";")) while (tok && !Tokenizer::Match(tok,";"))
tok = tok->next; tok = tok->next;
// Check if the variable is used in this indentlevel.. // Check if the variable is used in this indentlevel..
@ -538,12 +536,12 @@ void CheckOther::CheckVariableScope_LookupVar( const TOKEN *tok1, const char var
bool for_or_while = false; bool for_or_while = false;
while ( indentlevel >= 0 && tok ) while ( indentlevel >= 0 && tok )
{ {
if ( Match(tok, "{") ) if ( Tokenizer::Match(tok, "{") )
{ {
indentlevel++; indentlevel++;
} }
else if ( Match(tok, "}") ) else if ( Tokenizer::Match(tok, "}") )
{ {
indentlevel--; indentlevel--;
if ( indentlevel == 0 ) if ( indentlevel == 0 )
@ -555,12 +553,12 @@ void CheckOther::CheckVariableScope_LookupVar( const TOKEN *tok1, const char var
} }
} }
else if ( Match(tok, "(") ) else if ( Tokenizer::Match(tok, "(") )
{ {
parlevel++; parlevel++;
} }
else if ( Match(tok, ")") ) else if ( Tokenizer::Match(tok, ")") )
{ {
parlevel--; parlevel--;
} }
@ -575,9 +573,9 @@ void CheckOther::CheckVariableScope_LookupVar( const TOKEN *tok1, const char var
else if ( indentlevel==0 ) else if ( indentlevel==0 )
{ {
if ( Match(tok,"for") || Match(tok,"while") ) if ( Tokenizer::Match(tok,"for") || Tokenizer::Match(tok,"while") )
for_or_while = true; for_or_while = true;
if ( parlevel == 0 && Match(tok, ";") ) if ( parlevel == 0 && Tokenizer::Match(tok, ";") )
for_or_while = false; for_or_while = false;
} }
@ -600,14 +598,14 @@ void CheckOther::CheckConstantFunctionParameter()
{ {
for (const TOKEN *tok = _tokenizer->tokens(); tok; tok = tok->next) for (const TOKEN *tok = _tokenizer->tokens(); tok; tok = tok->next)
{ {
if ( Match(tok,"[,(] const std :: %type% %var% [,)]") ) if ( Tokenizer::Match(tok,"[,(] const std :: %type% %var% [,)]") )
{ {
std::ostringstream errmsg; std::ostringstream errmsg;
errmsg << _tokenizer->fileLine(tok) << " " << Tokenizer::getstr(tok,5) << " is passed by value, it could be passed by reference/pointer instead"; errmsg << _tokenizer->fileLine(tok) << " " << Tokenizer::getstr(tok,5) << " is passed by value, it could be passed by reference/pointer instead";
_errorLogger->reportErr( errmsg.str() ); _errorLogger->reportErr( errmsg.str() );
} }
else if ( Match(tok,"[,(] const %type% %var% [,)]") ) else if ( Tokenizer::Match(tok,"[,(] const %type% %var% [,)]") )
{ {
// Check if type is a struct or class. // Check if type is a struct or class.
const char *pattern[3] = {"class","type",0}; const char *pattern[3] = {"class","type",0};
@ -643,21 +641,21 @@ void CheckOther::CheckStructMemberUsage()
{ {
if ( tok->FileIndex != 0 ) if ( tok->FileIndex != 0 )
continue; continue;
if ( Match(tok,"}") ) if ( Tokenizer::Match(tok,"}") )
structname = 0; structname = 0;
if ( Match(tok, "struct %type% {") ) if ( Tokenizer::Match(tok, "struct %type% {") )
structname = Tokenizer::getstr(tok, 1); structname = Tokenizer::getstr(tok, 1);
if (structname && Match(tok, "[{;]")) if (structname && Tokenizer::Match(tok, "[{;]"))
{ {
const char *varname = 0; const char *varname = 0;
if (Match(tok->next, "%type% %var% [;[]")) if (Tokenizer::Match(tok->next, "%type% %var% [;[]"))
varname = Tokenizer::getstr( tok, 2 ); varname = Tokenizer::getstr( tok, 2 );
else if (Match(tok->next, "%type% %type% %var% [;[]")) else if (Tokenizer::Match(tok->next, "%type% %type% %var% [;[]"))
varname = Tokenizer::getstr( tok, 2 ); varname = Tokenizer::getstr( tok, 2 );
else if (Match(tok->next, "%type% * %var% [;[]")) else if (Tokenizer::Match(tok->next, "%type% * %var% [;[]"))
varname = Tokenizer::getstr( tok, 3 ); varname = Tokenizer::getstr( tok, 3 );
else if (Match(tok->next, "%type% %type% * %var% [;[]")) else if (Tokenizer::Match(tok->next, "%type% %type% * %var% [;[]"))
varname = Tokenizer::getstr( tok, 4 ); varname = Tokenizer::getstr( tok, 4 );
else else
continue; continue;
@ -671,7 +669,7 @@ void CheckOther::CheckStructMemberUsage()
if ( tok->FileIndex != 0 ) if ( tok->FileIndex != 0 )
continue; continue;
if (Match(tok2, ". %var%", varnames)) if (Tokenizer::Match(tok2, ". %var%", varnames))
{ {
if ( strcmp("=", Tokenizer::getstr(tok2,2)) == 0 ) if ( strcmp("=", Tokenizer::getstr(tok2,2)) == 0 )
continue; continue;
@ -703,7 +701,7 @@ void CheckOther::CheckCharVariable()
for (const TOKEN *tok = _tokenizer->tokens(); tok; tok = tok->next) for (const TOKEN *tok = _tokenizer->tokens(); tok; tok = tok->next)
{ {
// Declaring the variable.. // Declaring the variable..
if ( Match(tok, "[{};(,] char %var% [;=,)]") ) if ( Tokenizer::Match(tok, "[{};(,] char %var% [;=,)]") )
{ {
const char *varname[2] = {0}; const char *varname[2] = {0};
varname[0] = Tokenizer::getstr(tok, 2); varname[0] = Tokenizer::getstr(tok, 2);
@ -712,17 +710,17 @@ void CheckOther::CheckCharVariable()
int indentlevel = 0; int indentlevel = 0;
for ( const TOKEN *tok2 = tok->next; tok2; tok2 = tok2->next ) for ( const TOKEN *tok2 = tok->next; tok2; tok2 = tok2->next )
{ {
if ( Match(tok2, "{") ) if ( Tokenizer::Match(tok2, "{") )
++indentlevel; ++indentlevel;
else if ( Match(tok2, "}") ) else if ( Tokenizer::Match(tok2, "}") )
{ {
--indentlevel; --indentlevel;
if ( indentlevel <= 0 ) if ( indentlevel <= 0 )
break; break;
} }
if (!Match(tok2,".") && Match(tok2->next, "%var% [ %var1% ]", varname)) if (!Tokenizer::Match(tok2,".") && Tokenizer::Match(tok2->next, "%var% [ %var1% ]", varname))
{ {
std::ostringstream errmsg; std::ostringstream errmsg;
errmsg << _tokenizer->fileLine(tok2->next) << ": Warning - using char variable as array index"; errmsg << _tokenizer->fileLine(tok2->next) << ": Warning - using char variable as array index";
@ -730,7 +728,7 @@ void CheckOther::CheckCharVariable()
break; break;
} }
if ( Match(tok2, "%var% [&|] %var1%", varname) || Match(tok2, "%var1% [&|]", varname) ) if ( Tokenizer::Match(tok2, "%var% [&|] %var1%", varname) || Tokenizer::Match(tok2, "%var1% [&|]", varname) )
{ {
std::ostringstream errmsg; std::ostringstream errmsg;
errmsg << _tokenizer->fileLine(tok2) << ": Warning - using char variable in bit operation"; errmsg << _tokenizer->fileLine(tok2) << ": Warning - using char variable in bit operation";
@ -758,22 +756,22 @@ void CheckOther::CheckIncompleteStatement()
for ( const TOKEN *tok = _tokenizer->tokens(); tok; tok = tok->next ) for ( const TOKEN *tok = _tokenizer->tokens(); tok; tok = tok->next )
{ {
if ( Match(tok, "(") ) if ( Tokenizer::Match(tok, "(") )
++parlevel; ++parlevel;
else if ( Match(tok, ")") ) else if ( Tokenizer::Match(tok, ")") )
--parlevel; --parlevel;
if ( parlevel != 0 ) if ( parlevel != 0 )
continue; continue;
if ( !Match(tok,"#") && Match(tok->next,"; %str%") && !Match(Tokenizer::gettok(tok,3), ",") ) if ( !Tokenizer::Match(tok,"#") && Tokenizer::Match(tok->next,"; %str%") && !Tokenizer::Match(Tokenizer::gettok(tok,3), ",") )
{ {
std::ostringstream errmsg; std::ostringstream errmsg;
errmsg << _tokenizer->fileLine(tok->next) << ": Redundant code: Found a statement that begins with string constant"; errmsg << _tokenizer->fileLine(tok->next) << ": Redundant code: Found a statement that begins with string constant";
_errorLogger->reportErr(errmsg.str()); _errorLogger->reportErr(errmsg.str());
} }
if ( !Match(tok,"#") && Match(tok->next,"; %num%") && !Match(Tokenizer::gettok(tok,3), ",") ) if ( !Tokenizer::Match(tok,"#") && Tokenizer::Match(tok->next,"; %num%") && !Tokenizer::Match(Tokenizer::gettok(tok,3), ",") )
{ {
std::ostringstream errmsg; std::ostringstream errmsg;
errmsg << _tokenizer->fileLine(tok->next) << ": Redundant code: Found a statement that begins with numeric constant"; errmsg << _tokenizer->fileLine(tok->next) << ": Redundant code: Found a statement that begins with numeric constant";

View File

@ -1,182 +0,0 @@
/*
* 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 <http://www.gnu.org/licenses/
*/
//---------------------------------------------------------------------------
#include "CommonCheck.h"
#include "tokenize.h"
#include <stdlib.h> // free
#include <iostream>
#include <sstream>
#include <list>
#include <algorithm>
#include <cstring>
#ifdef __BORLANDC__
#include <ctype.h>
#endif
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
bool SameFileName( const char fname1[], const char fname2[] )
{
#ifdef __linux__
return bool( strcmp(fname1, fname2) == 0 );
#endif
#ifdef __GNUC__
return bool( strcasecmp(fname1, fname2) == 0 );
#endif
#ifdef __BORLANDC__
return bool( stricmp(fname1, fname2) == 0 );
#endif
#ifdef _MSC_VER
return bool( _stricmp(fname1, fname2) == 0 );
#endif
}
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
bool IsName(const char str[])
{
return bool(str[0]=='_' || isalpha(str[0]));
}
//---------------------------------------------------------------------------
bool IsNumber(const char str[])
{
return bool(isdigit(str[0]) != 0);
}
//---------------------------------------------------------------------------
bool IsStandardType(const char str[])
{
if (!str)
return false;
bool Ret = false;
const char *type[] = {"bool","char","short","int","long","float","double",0};
for (int i = 0; type[i]; i++)
Ret |= (strcmp(str,type[i])==0);
return Ret;
}
//--------------------------------------------------------------------------
bool Match(const TOKEN *tok, const char pattern[], const char *varname1[], const char *varname2[])
{
if (!tok)
return false;
const char *p = pattern;
while (*p)
{
// Skip spaces in pattern..
while ( *p == ' ' )
p++;
// Extract token from pattern..
char str[50];
char *s = str;
while (*p && *p!=' ')
{
*s = *p;
s++;
p++;
}
*s = 0;
// No token => Success!
if (str[0] == 0)
return true;
// Any symbolname..
if (strcmp(str,"%var%")==0 || strcmp(str,"%type%")==0)
{
if (!IsName(tok->str))
return false;
}
// Variable name..
else if (strcmp(str,"%var1%")==0 || strcmp(str,"%var2%")==0)
{
const char **varname = (strcmp(str,"%var1%")==0) ? varname1 : varname2;
if ( ! varname )
return false;
if (strcmp(tok->str, varname[0]) != 0)
return false;
for ( int i = 1; varname[i]; i++ )
{
if ( ! Tokenizer::gettok(tok, 2) )
return false;
if ( strcmp(Tokenizer::getstr(tok, 1), ".") )
return false;
if ( strcmp(Tokenizer::getstr(tok, 2), varname[i]) )
return false;
tok = Tokenizer::gettok(tok, 2);
}
}
else if (strcmp(str,"%num%")==0)
{
if ( ! IsNumber(tok->str) )
return false;
}
else if (strcmp(str,"%str%")==0)
{
if ( tok->str[0] != '\"' )
return false;
}
// [.. => search for a one-character token..
else if (str[0]=='[' && strchr(str, ']') && tok->str[1] == 0)
{
*strrchr(str, ']') = 0;
if ( strchr( str + 1, tok->str[0] ) == 0 )
return false;
}
else if (strcmp(str, tok->str) != 0)
return false;
tok = tok->next;
if (!tok)
return false;
}
// The end of the pattern has been reached and nothing wrong has been found
return true;
}
//---------------------------------------------------------------------------

View File

@ -1,41 +0,0 @@
/*
* 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 <http://www.gnu.org/licenses/
*/
//---------------------------------------------------------------------------
#ifndef CommonCheckH
#define CommonCheckH
//---------------------------------------------------------------------------
#include <string>
#include <sstream>
#include <vector>
#include "tokenize.h"
// Are two filenames the same? Case insensitive on windows
bool SameFileName( const char fname1[], const char fname2[] );
bool IsName(const char str[]);
bool IsNumber(const char str[]);
bool IsStandardType(const char str[]);
bool Match(const TOKEN *tok, const char pattern[], const char *varname1[]=0, const char *varname2[]=0);
//---------------------------------------------------------------------------
#endif

View File

@ -1,4 +1,4 @@
SRCS=CheckBufferOverrun.cpp CheckClass.cpp CheckHeaders.cpp CheckMemoryLeak.cpp CheckOther.cpp CommonCheck.cpp FileLister.cpp preprocessor.cpp tokenize.cpp cppcheck.cpp settings.cpp SRCS=CheckBufferOverrun.cpp CheckClass.cpp CheckHeaders.cpp CheckMemoryLeak.cpp CheckOther.cpp FileLister.cpp preprocessor.cpp tokenize.cpp cppcheck.cpp settings.cpp
OBJS=$(SRCS:%.cpp=%.o) OBJS=$(SRCS:%.cpp=%.o)
TESTS=testbufferoverrun.o testcharvar.o testconstructors.o testdivision.o testincompletestatement.o testmemleak.o testpreprocessor.o testsimplifytokens.o testtokenize.o testunusedprivfunc.o testunusedvar.o settings.o cppcheck.o TESTS=testbufferoverrun.o testcharvar.o testconstructors.o testdivision.o testincompletestatement.o testmemleak.o testpreprocessor.o testsimplifytokens.o testtokenize.o testunusedprivfunc.o testunusedvar.o settings.o cppcheck.o
BIN = ${DESTDIR}/usr/bin BIN = ${DESTDIR}/usr/bin
@ -7,31 +7,29 @@ all: ${OBJS} main.o
g++ -Wall -g -o cppcheck $^ g++ -Wall -g -o cppcheck $^
test: ${OBJS} testrunner.o testsuite.o ${TESTS} test: ${OBJS} testrunner.o testsuite.o ${TESTS}
g++ -Wall -g -o testrunner $^ g++ -Wall -g -o testrunner $^
cppcheck.o: cppcheck.cpp cppcheck.h preprocessor.h tokenize.h CommonCheck.h CheckMemoryLeak.h CheckBufferOverrun.h CheckClass.h CheckHeaders.h CheckOther.h FileLister.h settings.h cppcheck.o: cppcheck.cpp cppcheck.h preprocessor.h tokenize.h CheckMemoryLeak.h CheckBufferOverrun.h CheckClass.h CheckHeaders.h CheckOther.h FileLister.h settings.h
g++ -Wall -pedantic -g -I. -o $@ -c $*.cpp g++ -Wall -pedantic -g -I. -o $@ -c $*.cpp
main.o: main.cpp cppcheck.h main.o: main.cpp cppcheck.h
g++ -Wall -pedantic -g -I. -o $@ -c $*.cpp g++ -Wall -pedantic -g -I. -o $@ -c $*.cpp
settings.o: settings.cpp settings.o: settings.cpp
g++ -Wall -pedantic -g -I. -o $@ -c $*.cpp g++ -Wall -pedantic -g -I. -o $@ -c $*.cpp
CheckBufferOverrun.o: CheckBufferOverrun.cpp CheckBufferOverrun.h tokenize.h CommonCheck.h CheckBufferOverrun.o: CheckBufferOverrun.cpp CheckBufferOverrun.h tokenize.h
g++ -Wall -pedantic -g -I. -o $@ -c $*.cpp g++ -Wall -pedantic -g -I. -o $@ -c $*.cpp
CheckClass.o: CheckClass.cpp CheckClass.h tokenize.h CommonCheck.h CheckClass.o: CheckClass.cpp CheckClass.h tokenize.h
g++ -Wall -pedantic -g -I. -o $@ -c $*.cpp g++ -Wall -pedantic -g -I. -o $@ -c $*.cpp
CheckHeaders.o: CheckHeaders.cpp CheckHeaders.h tokenize.h CommonCheck.h CheckHeaders.o: CheckHeaders.cpp CheckHeaders.h tokenize.h
g++ -Wall -pedantic -g -I. -o $@ -c $*.cpp g++ -Wall -pedantic -g -I. -o $@ -c $*.cpp
CheckMemoryLeak.o: CheckMemoryLeak.cpp CheckMemoryLeak.h tokenize.h CommonCheck.h CheckMemoryLeak.o: CheckMemoryLeak.cpp CheckMemoryLeak.h tokenize.h
g++ -Wall -pedantic -g -I. -o $@ -c $*.cpp g++ -Wall -pedantic -g -I. -o $@ -c $*.cpp
CheckOther.o: CheckOther.cpp CheckOther.h tokenize.h CommonCheck.h CheckOther.o: CheckOther.cpp CheckOther.h tokenize.h
g++ -Wall -pedantic -g -I. -o $@ -c $*.cpp
CommonCheck.o: CommonCheck.cpp CommonCheck.h tokenize.h
g++ -Wall -pedantic -g -I. -o $@ -c $*.cpp g++ -Wall -pedantic -g -I. -o $@ -c $*.cpp
FileLister.o: FileLister.cpp FileLister.h FileLister.o: FileLister.cpp FileLister.h
g++ -Wall -pedantic -g -I. -o $@ -c $*.cpp g++ -Wall -pedantic -g -I. -o $@ -c $*.cpp
preprocessor.o: preprocessor.cpp preprocessor.h CommonCheck.h preprocessor.o: preprocessor.cpp preprocessor.h
g++ -Wall -pedantic -g -I. -o $@ -c $*.cpp g++ -Wall -pedantic -g -I. -o $@ -c $*.cpp
testbufferoverrun.o: testbufferoverrun.cpp tokenize.h CommonCheck.h CheckBufferOverrun.h testsuite.h testbufferoverrun.o: testbufferoverrun.cpp tokenize.h CheckBufferOverrun.h testsuite.h
g++ -Wall -pedantic -g -I. -o $@ -c $*.cpp g++ -Wall -pedantic -g -I. -o $@ -c $*.cpp
testcharvar.o: testcharvar.cpp tokenize.h CommonCheck.h CheckOther.h testsuite.h testcharvar.o: testcharvar.cpp tokenize.h CheckOther.h testsuite.h
g++ -Wall -pedantic -g -I. -o $@ -c $*.cpp g++ -Wall -pedantic -g -I. -o $@ -c $*.cpp
testconstructors.o: testconstructors.cpp tokenize.h CheckClass.h testsuite.h testconstructors.o: testconstructors.cpp tokenize.h CheckClass.h testsuite.h
g++ -Wall -pedantic -g -I. -o $@ -c $*.cpp g++ -Wall -pedantic -g -I. -o $@ -c $*.cpp
@ -39,7 +37,7 @@ testdivision.o: testdivision.cpp tokenize.h CheckOther.h testsuite.h
g++ -Wall -pedantic -g -I. -o $@ -c $*.cpp g++ -Wall -pedantic -g -I. -o $@ -c $*.cpp
testincompletestatement.o: testincompletestatement.cpp testsuite.h tokenize.h CheckOther.h testincompletestatement.o: testincompletestatement.cpp testsuite.h tokenize.h CheckOther.h
g++ -Wall -pedantic -g -I. -o $@ -c $*.cpp g++ -Wall -pedantic -g -I. -o $@ -c $*.cpp
testmemleak.o: testmemleak.cpp CommonCheck.h tokenize.h CheckMemoryLeak.h testsuite.h testmemleak.o: testmemleak.cpp tokenize.h CheckMemoryLeak.h testsuite.h
g++ -Wall -pedantic -g -I. -o $@ -c $*.cpp g++ -Wall -pedantic -g -I. -o $@ -c $*.cpp
testpreprocessor.o: testpreprocessor.cpp testsuite.h preprocessor.h testpreprocessor.o: testpreprocessor.cpp testsuite.h preprocessor.h
g++ -Wall -pedantic -g -I. -o $@ -c $*.cpp g++ -Wall -pedantic -g -I. -o $@ -c $*.cpp
@ -55,7 +53,7 @@ testunusedprivfunc.o: testunusedprivfunc.cpp tokenize.h CheckClass.h testsuite.h
g++ -Wall -pedantic -g -I. -o $@ -c $*.cpp g++ -Wall -pedantic -g -I. -o $@ -c $*.cpp
testunusedvar.o: testunusedvar.cpp testsuite.h tokenize.h CheckOther.h testunusedvar.o: testunusedvar.cpp testsuite.h tokenize.h CheckOther.h
g++ -Wall -pedantic -g -I. -o $@ -c $*.cpp g++ -Wall -pedantic -g -I. -o $@ -c $*.cpp
tokenize.o: tokenize.cpp tokenize.h CommonCheck.h tokenize.o: tokenize.cpp tokenize.h
g++ -Wall -pedantic -g -I. -o $@ -c $*.cpp g++ -Wall -pedantic -g -I. -o $@ -c $*.cpp
clean: clean:
rm -f *.o testrunner cppcheck rm -f *.o testrunner cppcheck

View File

@ -19,7 +19,6 @@
#include "preprocessor.h" // preprocessor. #include "preprocessor.h" // preprocessor.
#include "CommonCheck.h"
#include "CheckMemoryLeak.h" #include "CheckMemoryLeak.h"
#include "CheckBufferOverrun.h" #include "CheckBufferOverrun.h"
#include "CheckClass.h" #include "CheckClass.h"

View File

@ -18,7 +18,6 @@
#include "preprocessor.h" #include "preprocessor.h"
#include "CommonCheck.h"
#include <algorithm> #include <algorithm>

View File

@ -19,7 +19,6 @@
#include "tokenize.h" #include "tokenize.h"
#include "CommonCheck.h"
#include "CheckBufferOverrun.h" #include "CheckBufferOverrun.h"
#include "testsuite.h" #include "testsuite.h"

View File

@ -18,7 +18,6 @@
#include "tokenize.h" #include "tokenize.h"
#include "CommonCheck.h"
#include "CheckOther.h" #include "CheckOther.h"
#include "testsuite.h" #include "testsuite.h"
#include <sstream> #include <sstream>

View File

@ -19,7 +19,6 @@
#include "CommonCheck.h"
#include "tokenize.h" #include "tokenize.h"
#include "CheckMemoryLeak.h" #include "CheckMemoryLeak.h"
#include "testsuite.h" #include "testsuite.h"

View File

@ -19,7 +19,6 @@
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
#include "tokenize.h" #include "tokenize.h"
#include "CommonCheck.h" // <- IsName
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
@ -29,7 +28,9 @@
#include <string> #include <string>
#include <cstring> #include <cstring>
#include <iostream> #include <iostream>
#include <sstream>
#include <list>
#include <algorithm> #include <algorithm>
#include <stdlib.h> // <- strtoul #include <stdlib.h> // <- strtoul
#include <stdio.h> #include <stdio.h>
@ -594,7 +595,7 @@ void Tokenizer::TokenizeCode(std::istream &code, const unsigned int FileIndex)
// typedef.. // typedef..
for ( TOKEN *tok = _tokens; tok; tok = tok->next ) for ( TOKEN *tok = _tokens; tok; tok = tok->next )
{ {
if (Match(tok, "typedef %type% %type% ;")) if (Tokenizer::Match(tok, "typedef %type% %type% ;"))
{ {
const char *type1 = getstr(tok, 1); const char *type1 = getstr(tok, 1);
const char *type2 = getstr(tok, 2); const char *type2 = getstr(tok, 2);
@ -607,14 +608,14 @@ void Tokenizer::TokenizeCode(std::istream &code, const unsigned int FileIndex)
} }
} }
else if (Match(tok, "typedef %type% %type% %type% ;")) else if (Tokenizer::Match(tok, "typedef %type% %type% %type% ;"))
{ {
const char *type1 = getstr(tok, 1); const char *type1 = getstr(tok, 1);
const char *type2 = getstr(tok, 2); const char *type2 = getstr(tok, 2);
const char *type3 = getstr(tok, 3); const char *type3 = getstr(tok, 3);
TOKEN *tok2 = tok; TOKEN *tok2 = tok;
while ( ! Match(tok2, ";") ) while ( ! Tokenizer::Match(tok2, ";") )
tok2 = tok2->next; tok2 = tok2->next;
for ( ; tok2; tok2 = tok2->next ) for ( ; tok2; tok2 = tok2->next )
@ -639,11 +640,11 @@ void Tokenizer::TokenizeCode(std::istream &code, const unsigned int FileIndex)
// Remove __asm.. // Remove __asm..
for ( TOKEN *tok = _tokens; tok; tok = tok->next ) for ( TOKEN *tok = _tokens; tok; tok = tok->next )
{ {
if ( Match(tok->next, "__asm {") ) if ( Tokenizer::Match(tok->next, "__asm {") )
{ {
while ( tok->next ) while ( tok->next )
{ {
bool last = Match( tok->next, "}" ); bool last = Tokenizer::Match( tok->next, "}" );
// Unlink and delete tok->next // Unlink and delete tok->next
TOKEN *next = tok->next; TOKEN *next = tok->next;
@ -686,7 +687,7 @@ void Tokenizer::SimplifyTokenList()
// Replace constants.. // Replace constants..
for (TOKEN *tok = _tokens; tok; tok = tok->next) for (TOKEN *tok = _tokens; tok; tok = tok->next)
{ {
if (Match(tok,"const %type% %var% = %num% ;")) if (Tokenizer::Match(tok,"const %type% %var% = %num% ;"))
{ {
const char *sym = getstr(tok,2); const char *sym = getstr(tok,2);
const char *num = getstr(tok,4); const char *num = getstr(tok,4);
@ -712,12 +713,12 @@ void Tokenizer::SimplifyTokenList()
TypeSize["double"] = sizeof(double); TypeSize["double"] = sizeof(double);
for (TOKEN *tok = _tokens; tok; tok = tok->next) for (TOKEN *tok = _tokens; tok; tok = tok->next)
{ {
if (Match(tok,"class %var%")) if (Tokenizer::Match(tok,"class %var%"))
{ {
TypeSize[getstr(tok,1)] = 11; TypeSize[getstr(tok,1)] = 11;
} }
else if (Match(tok, "struct %var%")) else if (Tokenizer::Match(tok, "struct %var%"))
{ {
TypeSize[getstr(tok,1)] = 13; TypeSize[getstr(tok,1)] = 13;
} }
@ -730,7 +731,7 @@ void Tokenizer::SimplifyTokenList()
if (strcmp(tok->str,"sizeof") != 0) if (strcmp(tok->str,"sizeof") != 0)
continue; continue;
if (Match(tok, "sizeof ( %type% * )")) if (Tokenizer::Match(tok, "sizeof ( %type% * )"))
{ {
std::ostringstream str; std::ostringstream str;
// 'sizeof(type *)' has the same size as 'sizeof(char *)' // 'sizeof(type *)' has the same size as 'sizeof(char *)'
@ -743,7 +744,7 @@ void Tokenizer::SimplifyTokenList()
} }
} }
else if (Match(tok, "sizeof ( %type% )")) else if (Tokenizer::Match(tok, "sizeof ( %type% )"))
{ {
const char *type = getstr(tok, 2); const char *type = getstr(tok, 2);
int size = SizeOfType(type); int size = SizeOfType(type);
@ -759,7 +760,7 @@ void Tokenizer::SimplifyTokenList()
} }
} }
else if (Match(tok, "sizeof ( * %var% )")) else if (Tokenizer::Match(tok, "sizeof ( * %var% )"))
{ {
tok->setstr("100"); tok->setstr("100");
for ( int i = 0; i < 4; ++i ) for ( int i = 0; i < 4; ++i )
@ -771,7 +772,7 @@ void Tokenizer::SimplifyTokenList()
for (TOKEN *tok = _tokens; tok; tok = tok->next) for (TOKEN *tok = _tokens; tok; tok = tok->next)
{ {
// type array [ num ] ; // type array [ num ] ;
if ( ! Match(tok, "%type% %var% [ %num% ] ;") ) if ( ! Tokenizer::Match(tok, "%type% %var% [ %num% ] ;") )
continue; continue;
int size = SizeOfType(tok->str); int size = SizeOfType(tok->str);
@ -797,8 +798,8 @@ void Tokenizer::SimplifyTokenList()
break; break;
} }
// Todo: Match varname directly // Todo: Tokenizer::Match varname directly
else if (Match(tok2, "sizeof ( %var% )")) else if (Tokenizer::Match(tok2, "sizeof ( %var% )"))
{ {
if (strcmp(getstr(tok2,2), varname) == 0) if (strcmp(getstr(tok2,2), varname) == 0)
{ {
@ -827,7 +828,7 @@ void Tokenizer::SimplifyTokenList()
for (TOKEN *tok = _tokens; tok; tok = tok->next) for (TOKEN *tok = _tokens; tok; tok = tok->next)
{ {
if (Match(tok->next, "* 1") || Match(tok->next, "1 *")) if (Tokenizer::Match(tok->next, "* 1") || Tokenizer::Match(tok->next, "1 *"))
{ {
for (int i = 0; i < 2; i++) for (int i = 0; i < 2; i++)
DeleteNextToken(tok); DeleteNextToken(tok);
@ -836,9 +837,9 @@ void Tokenizer::SimplifyTokenList()
// (1-2) // (1-2)
if (strchr("[,(=<>",tok->str[0]) && if (strchr("[,(=<>",tok->str[0]) &&
IsNumber(getstr(tok,1)) && Tokenizer::IsNumber(getstr(tok,1)) &&
strchr("+-*/",*(getstr(tok,2))) && strchr("+-*/",*(getstr(tok,2))) &&
IsNumber(getstr(tok,3)) && Tokenizer::IsNumber(getstr(tok,3)) &&
strchr("],);=<>",*(getstr(tok,4))) ) strchr("],);=<>",*(getstr(tok,4))) )
{ {
int i1 = atoi(getstr(tok,1)); int i1 = atoi(getstr(tok,1));
@ -880,7 +881,7 @@ void Tokenizer::SimplifyTokenList()
if ( ! next ) if ( ! next )
break; break;
if (Match(next, "* ( %var% + %num% )")) if (Tokenizer::Match(next, "* ( %var% + %num% )"))
{ {
const char *str[4] = {"var","[","num","]"}; const char *str[4] = {"var","[","num","]"};
str[0] = getstr(tok,3); str[0] = getstr(tok,3);
@ -906,64 +907,64 @@ void Tokenizer::SimplifyTokenList()
continue; continue;
TOKEN *type0 = tok->next; TOKEN *type0 = tok->next;
if (!Match(type0, "%type%")) if (!Tokenizer::Match(type0, "%type%"))
continue; continue;
if (Match(type0, "else") || Match(type0, "return")) if (Tokenizer::Match(type0, "else") || Tokenizer::Match(type0, "return"))
continue; continue;
TOKEN *tok2 = NULL; TOKEN *tok2 = NULL;
unsigned int typelen = 0; unsigned int typelen = 0;
if ( Match(type0, "%type% %var% ,") ) if ( Tokenizer::Match(type0, "%type% %var% ,") )
{ {
tok2 = _gettok(type0, 2); // The ',' token tok2 = _gettok(type0, 2); // The ',' token
typelen = 1; typelen = 1;
} }
else if ( Match(type0, "%type% * %var% ,") ) else if ( Tokenizer::Match(type0, "%type% * %var% ,") )
{ {
tok2 = _gettok(type0, 3); // The ',' token tok2 = _gettok(type0, 3); // The ',' token
typelen = 1; typelen = 1;
} }
else if ( Match(type0, "%type% %var% [ %num% ] ,") ) else if ( Tokenizer::Match(type0, "%type% %var% [ %num% ] ,") )
{ {
tok2 = _gettok(type0, 5); // The ',' token tok2 = _gettok(type0, 5); // The ',' token
typelen = 1; typelen = 1;
} }
else if ( Match(type0, "%type% * %var% [ %num% ] ,") ) else if ( Tokenizer::Match(type0, "%type% * %var% [ %num% ] ,") )
{ {
tok2 = _gettok(type0, 6); // The ',' token tok2 = _gettok(type0, 6); // The ',' token
typelen = 1; typelen = 1;
} }
else if ( Match(type0, "struct %type% %var% ,") ) else if ( Tokenizer::Match(type0, "struct %type% %var% ,") )
{ {
tok2 = _gettok(type0, 3); tok2 = _gettok(type0, 3);
typelen = 2; typelen = 2;
} }
else if ( Match(type0, "struct %type% * %var% ,") ) else if ( Tokenizer::Match(type0, "struct %type% * %var% ,") )
{ {
tok2 = _gettok(type0, 4); tok2 = _gettok(type0, 4);
typelen = 2; typelen = 2;
} }
else if ( Match(type0, "%type% %var% =") ) else if ( Tokenizer::Match(type0, "%type% %var% =") )
{ {
tok2 = _gettok(type0, 2); tok2 = _gettok(type0, 2);
typelen = 1; typelen = 1;
} }
else if ( Match(type0, "%type% * %var% =") ) else if ( Tokenizer::Match(type0, "%type% * %var% =") )
{ {
tok2 = _gettok(type0, 3); tok2 = _gettok(type0, 3);
typelen = 1; typelen = 1;
} }
else if ( Match(type0, "struct %type% * %var% =") ) else if ( Tokenizer::Match(type0, "struct %type% * %var% =") )
{ {
tok2 = _gettok(type0, 4); tok2 = _gettok(type0, 4);
typelen = 2; typelen = 2;
@ -1023,16 +1024,16 @@ void Tokenizer::SimplifyTokenList()
// Replace NULL with 0.. // Replace NULL with 0..
for ( TOKEN *tok = _tokens; tok; tok = tok->next ) for ( TOKEN *tok = _tokens; tok; tok = tok->next )
{ {
if ( Match(tok, "NULL") ) if ( Tokenizer::Match(tok, "NULL") )
tok->setstr("0"); tok->setstr("0");
} }
// Replace pointer casts of 0.. "(char *)0" => "0" // Replace pointer casts of 0.. "(char *)0" => "0"
for ( TOKEN *tok = _tokens; tok; tok = tok->next ) for ( TOKEN *tok = _tokens; tok; tok = tok->next )
{ {
if ( Match(tok->next, "( %type% * ) 0") || Match(tok->next,"( %type% %type% * ) 0") ) if ( Tokenizer::Match(tok->next, "( %type% * ) 0") || Tokenizer::Match(tok->next,"( %type% %type% * ) 0") )
{ {
while (!Match(tok->next,"0")) while (!Tokenizer::Match(tok->next,"0"))
DeleteNextToken(tok); DeleteNextToken(tok);
} }
} }
@ -1141,10 +1142,10 @@ void Tokenizer::FillFunctionList(const unsigned int file_id)
{ {
const char *funcname = 0; const char *funcname = 0;
if ( Match(tok,"%var% (") ) if ( Tokenizer::Match(tok,"%var% (") )
funcname = tok->str; funcname = tok->str;
else if ( Match(tok, "= %var% ;") || else if ( Tokenizer::Match(tok, "= %var% ;") ||
Match(tok, "= %var% ,") ) Tokenizer::Match(tok, "= %var% ,") )
funcname = tok->next->str; funcname = tok->next->str;
if ( std::find(_usedfunc.begin(), _usedfunc.end(), funcname) == _usedfunc.end() ) if ( std::find(_usedfunc.begin(), _usedfunc.end(), funcname) == _usedfunc.end() )
@ -1163,7 +1164,7 @@ void Tokenizer::FillFunctionList(const unsigned int file_id)
else if ( strcmp( tok->str, "::" ) == 0 ) else if ( strcmp( tok->str, "::" ) == 0 )
classfunc = true; classfunc = true;
else if (Match(tok, "%var% (")) else if (Tokenizer::Match(tok, "%var% ("))
{ {
// Check if this is the first token of a function implementation.. // Check if this is the first token of a function implementation..
for ( const TOKEN *tok2 = tok; tok2; tok2 = tok2->next ) for ( const TOKEN *tok2 = tok; tok2; tok2 = tok2->next )
@ -1181,7 +1182,7 @@ void Tokenizer::FillFunctionList(const unsigned int file_id)
else if ( tok2->str[0] == ')' ) else if ( tok2->str[0] == ')' )
{ {
if ( Match(tok2, ") {") ) if ( Tokenizer::Match(tok2, ") {") )
{ {
if (_settings._checkCodingStyle && !staticfunc && !classfunc && tok->FileIndex==0) if (_settings._checkCodingStyle && !staticfunc && !classfunc && tok->FileIndex==0)
GlobalFunctions.push_back( GlobalFunction(file_id, tok->str) ); GlobalFunctions.push_back( GlobalFunction(file_id, tok->str) );
@ -1352,9 +1353,9 @@ const char *Tokenizer::getParameterName( const TOKEN *ftok, int par )
int _par = 1; int _par = 1;
for ( ; ftok; ftok = ftok->next) for ( ; ftok; ftok = ftok->next)
{ {
if ( Match(ftok, ",") ) if ( Tokenizer::Match(ftok, ",") )
++_par; ++_par;
if ( par==_par && Match(ftok, "%var% [,)]") ) if ( par==_par && Tokenizer::Match(ftok, "%var% [,)]") )
return ftok->str; return ftok->str;
} }
return NULL; return NULL;
@ -1366,7 +1367,7 @@ const TOKEN *Tokenizer::findmatch(const TOKEN *tok, const char pattern[], const
{ {
for ( ; tok; tok = tok->next) for ( ; tok; tok = tok->next)
{ {
if ( Match(tok, pattern, varname1, varname2) ) if ( Tokenizer::Match(tok, pattern, varname1, varname2) )
return tok; return tok;
} }
return 0; return 0;
@ -1380,3 +1381,139 @@ std::string Tokenizer::fileLine( const TOKEN *tok )
ostr << "[" << Files.at(tok->FileIndex) << ":" << tok->linenr << "]"; ostr << "[" << Files.at(tok->FileIndex) << ":" << tok->linenr << "]";
return ostr.str(); return ostr.str();
} }
bool Tokenizer::Match(const TOKEN *tok, const char pattern[], const char *varname1[], const char *varname2[])
{
if (!tok)
return false;
const char *p = pattern;
while (*p)
{
// Skip spaces in pattern..
while ( *p == ' ' )
p++;
// Extract token from pattern..
char str[50];
char *s = str;
while (*p && *p!=' ')
{
*s = *p;
s++;
p++;
}
*s = 0;
// No token => Success!
if (str[0] == 0)
return true;
// Any symbolname..
if (strcmp(str,"%var%")==0 || strcmp(str,"%type%")==0)
{
if (!Tokenizer::IsName(tok->str))
return false;
}
// Variable name..
else if (strcmp(str,"%var1%")==0 || strcmp(str,"%var2%")==0)
{
const char **varname = (strcmp(str,"%var1%")==0) ? varname1 : varname2;
if ( ! varname )
return false;
if (strcmp(tok->str, varname[0]) != 0)
return false;
for ( int i = 1; varname[i]; i++ )
{
if ( ! Tokenizer::gettok(tok, 2) )
return false;
if ( strcmp(Tokenizer::getstr(tok, 1), ".") )
return false;
if ( strcmp(Tokenizer::getstr(tok, 2), varname[i]) )
return false;
tok = Tokenizer::gettok(tok, 2);
}
}
else if (strcmp(str,"%num%")==0)
{
if ( ! Tokenizer::IsNumber(tok->str) )
return false;
}
else if (strcmp(str,"%str%")==0)
{
if ( tok->str[0] != '\"' )
return false;
}
// [.. => search for a one-character token..
else if (str[0]=='[' && strchr(str, ']') && tok->str[1] == 0)
{
*strrchr(str, ']') = 0;
if ( strchr( str + 1, tok->str[0] ) == 0 )
return false;
}
else if (strcmp(str, tok->str) != 0)
return false;
tok = tok->next;
if (!tok)
return false;
}
// The end of the pattern has been reached and nothing wrong has been found
return true;
}
//---------------------------------------------------------------------------
bool Tokenizer::SameFileName( const char fname1[], const char fname2[] )
{
#ifdef __linux__
return bool( strcmp(fname1, fname2) == 0 );
#endif
#ifdef __GNUC__
return bool( strcasecmp(fname1, fname2) == 0 );
#endif
#ifdef __BORLANDC__
return bool( stricmp(fname1, fname2) == 0 );
#endif
#ifdef _MSC_VER
return bool( _stricmp(fname1, fname2) == 0 );
#endif
}
bool Tokenizer::IsName(const char str[])
{
return bool(str[0]=='_' || isalpha(str[0]));
}
//---------------------------------------------------------------------------
bool Tokenizer::IsNumber(const char str[])
{
return bool(isdigit(str[0]) != 0);
}
//---------------------------------------------------------------------------
bool Tokenizer::IsStandardType(const char str[])
{
if (!str)
return false;
bool Ret = false;
const char *type[] = {"bool","char","short","int","long","float","double",0};
for (int i = 0; type[i]; i++)
Ret |= (strcmp(str,type[i])==0);
return Ret;
}

View File

@ -84,6 +84,12 @@ public:
static void deleteTokens(TOKEN *tok); static void deleteTokens(TOKEN *tok);
static const char *getParameterName( const TOKEN *ftok, int par ); static const char *getParameterName( const TOKEN *ftok, int par );
static const TOKEN *findmatch(const TOKEN *tok, const char pattern[], const char *varname1[]=0, const char *varname2[]=0); static const TOKEN *findmatch(const TOKEN *tok, const char pattern[], const char *varname1[]=0, const char *varname2[]=0);
static bool Match(const TOKEN *tok, const char pattern[], const char *varname1[]=0, const char *varname2[]=0);
static bool SameFileName( const char fname1[], const char fname2[] );
static bool IsName(const char str[]);
static bool IsNumber(const char str[]);
static bool IsStandardType(const char str[]);
std::string fileLine( const TOKEN *tok ); std::string fileLine( const TOKEN *tok );
@ -100,7 +106,8 @@ public:
const TOKEN *GetFunctionTokenByName( const char funcname[] ) const; const TOKEN *GetFunctionTokenByName( const char funcname[] ) const;
void CheckGlobalFunctionUsage(const std::vector<std::string> &filenames); void CheckGlobalFunctionUsage(const std::vector<std::string> &filenames);
void settings( const Settings &settings ); void settings( const Settings &settings );
const TOKEN *tokens() const; const TOKEN *tokens() const;
#ifndef UNIT_TESTING #ifndef UNIT_TESTING