Style: Updated the coding style with "astyle"
This commit is contained in:
parent
7495190312
commit
ea1f3f4e85
|
@ -36,7 +36,7 @@
|
|||
|
||||
|
||||
CheckBufferOverrunClass::CheckBufferOverrunClass(const Tokenizer *tokenizer, const Settings &settings, ErrorLogger *errorLogger)
|
||||
: _settings(settings)
|
||||
: _settings(settings)
|
||||
{
|
||||
_tokenizer = tokenizer;
|
||||
_errorLogger = errorLogger;
|
||||
|
@ -52,8 +52,8 @@ void CheckBufferOverrunClass::ReportError(const Token *tok, const char errmsg[])
|
|||
{
|
||||
std::ostringstream ostr;
|
||||
std::list<const Token *>::const_iterator it;
|
||||
for ( it = _callStack.begin(); it != _callStack.end(); it++ )
|
||||
ostr << _tokenizer->fileLine(*it ) << " -> ";
|
||||
for (it = _callStack.begin(); it != _callStack.end(); it++)
|
||||
ostr << _tokenizer->fileLine(*it) << " -> ";
|
||||
ostr << _tokenizer->fileLine(tok) << ": " << errmsg;
|
||||
_errorLogger->reportErr(ostr.str());
|
||||
}
|
||||
|
@ -69,9 +69,9 @@ void CheckBufferOverrunClass::CheckBufferOverrun_CheckScope(const Token *tok, co
|
|||
unsigned int varc = 0;
|
||||
|
||||
std::string varnames;
|
||||
while ( varname[varc] )
|
||||
while (varname[varc])
|
||||
{
|
||||
if( varc > 0 )
|
||||
if (varc > 0)
|
||||
varnames += " . ";
|
||||
|
||||
varnames += varname[varc];
|
||||
|
@ -79,15 +79,15 @@ void CheckBufferOverrunClass::CheckBufferOverrun_CheckScope(const Token *tok, co
|
|||
++varc;
|
||||
}
|
||||
|
||||
if( varc == 0 )
|
||||
if (varc == 0)
|
||||
varc = 1;
|
||||
|
||||
varc = 2 * (varc - 1);
|
||||
|
||||
// Array index..
|
||||
if ( varid > 0 )
|
||||
if (varid > 0)
|
||||
{
|
||||
if ( Token::Match(tok, "%varid% [ %num% ]", varid) )
|
||||
if (Token::Match(tok, "%varid% [ %num% ]", varid))
|
||||
{
|
||||
const char *num = tok->strAt(2);
|
||||
if (strtol(num, NULL, 10) >= size)
|
||||
|
@ -96,7 +96,7 @@ void CheckBufferOverrunClass::CheckBufferOverrun_CheckScope(const Token *tok, co
|
|||
}
|
||||
}
|
||||
}
|
||||
else if ( Token::Match(tok, std::string( varnames + " [ %num% ]" ).c_str() ) )
|
||||
else if (Token::Match(tok, std::string(varnames + " [ %num% ]").c_str()))
|
||||
{
|
||||
const char *num = tok->strAt(2 + varc);
|
||||
if (strtol(num, NULL, 10) >= size)
|
||||
|
@ -107,7 +107,7 @@ void CheckBufferOverrunClass::CheckBufferOverrun_CheckScope(const Token *tok, co
|
|||
|
||||
|
||||
int indentlevel = 0;
|
||||
for ( ; tok; tok = tok->next() )
|
||||
for (; tok; tok = tok->next())
|
||||
{
|
||||
if (tok->str() == "{")
|
||||
{
|
||||
|
@ -117,14 +117,14 @@ void CheckBufferOverrunClass::CheckBufferOverrun_CheckScope(const Token *tok, co
|
|||
else if (tok->str() == "}")
|
||||
{
|
||||
--indentlevel;
|
||||
if ( indentlevel < 0 )
|
||||
if (indentlevel < 0)
|
||||
return;
|
||||
}
|
||||
|
||||
// Array index..
|
||||
if ( varid > 0 )
|
||||
if (varid > 0)
|
||||
{
|
||||
if ( !tok->isName() && !Token::Match(tok, "[.&]") && Token::Match(tok->next(), "%varid% [ %num% ]", varid) )
|
||||
if (!tok->isName() && !Token::Match(tok, "[.&]") && Token::Match(tok->next(), "%varid% [ %num% ]", varid))
|
||||
{
|
||||
const char *num = tok->strAt(3);
|
||||
if (strtol(num, NULL, 10) >= size)
|
||||
|
@ -133,7 +133,7 @@ void CheckBufferOverrunClass::CheckBufferOverrun_CheckScope(const Token *tok, co
|
|||
}
|
||||
}
|
||||
}
|
||||
else if ( !tok->isName() && !Token::Match(tok, "[.&]") && Token::Match(tok->next(), std::string( varnames + " [ %num% ]" ).c_str() ) )
|
||||
else if (!tok->isName() && !Token::Match(tok, "[.&]") && Token::Match(tok->next(), std::string(varnames + " [ %num% ]").c_str()))
|
||||
{
|
||||
const char *num = tok->next()->strAt(2 + varc);
|
||||
if (strtol(num, NULL, 10) >= size)
|
||||
|
@ -146,15 +146,15 @@ void CheckBufferOverrunClass::CheckBufferOverrun_CheckScope(const Token *tok, co
|
|||
|
||||
|
||||
// memset, memcmp, memcpy, strncpy, fgets..
|
||||
if ( varid > 0 )
|
||||
if (varid > 0)
|
||||
{
|
||||
if ( Token::Match(tok, "memset|memcpy|memmove|memcmp|strncpy|fgets") )
|
||||
if (Token::Match(tok, "memset|memcpy|memmove|memcmp|strncpy|fgets"))
|
||||
{
|
||||
if ( Token::Match(tok->next(), "( %varid% , %num% , %num% )", varid) ||
|
||||
Token::Match(tok->next(), "( %var% , %varid% , %num% )", varid) )
|
||||
if (Token::Match(tok->next(), "( %varid% , %num% , %num% )", varid) ||
|
||||
Token::Match(tok->next(), "( %var% , %varid% , %num% )", varid))
|
||||
{
|
||||
const char *num = tok->strAt(6);
|
||||
if ( atoi(num) > total_size )
|
||||
if (atoi(num) > total_size)
|
||||
{
|
||||
ReportError(tok, "Buffer overrun");
|
||||
}
|
||||
|
@ -162,13 +162,13 @@ void CheckBufferOverrunClass::CheckBufferOverrun_CheckScope(const Token *tok, co
|
|||
continue;
|
||||
}
|
||||
}
|
||||
else if (Token::Match(tok,"memset|memcpy|memmove|memcmp|strncpy|fgets") )
|
||||
else if (Token::Match(tok, "memset|memcpy|memmove|memcmp|strncpy|fgets"))
|
||||
{
|
||||
if ( Token::Match(tok->next(), std::string( "( "+varnames+" , %num% , %num% )" ).c_str()) ||
|
||||
Token::Match(tok->next(), std::string( "( %var% , "+varnames+" , %num% )" ).c_str()) )
|
||||
if (Token::Match(tok->next(), std::string("( " + varnames + " , %num% , %num% )").c_str()) ||
|
||||
Token::Match(tok->next(), std::string("( %var% , " + varnames + " , %num% )").c_str()))
|
||||
{
|
||||
const char *num = tok->strAt(varc + 6);
|
||||
if ( atoi(num) > total_size )
|
||||
if (atoi(num) > total_size)
|
||||
{
|
||||
ReportError(tok, "Buffer overrun");
|
||||
}
|
||||
|
@ -178,56 +178,56 @@ void CheckBufferOverrunClass::CheckBufferOverrun_CheckScope(const Token *tok, co
|
|||
|
||||
|
||||
// Loop..
|
||||
if ( Token::simpleMatch(tok, "for (") )
|
||||
if (Token::simpleMatch(tok, "for ("))
|
||||
{
|
||||
const Token *tok2 = tok->tokAt(2);
|
||||
|
||||
// for - setup..
|
||||
if ( Token::Match(tok2, "%var% = 0 ;") )
|
||||
if (Token::Match(tok2, "%var% = 0 ;"))
|
||||
tok2 = tok2->tokAt(4);
|
||||
else if ( Token::Match(tok2, "%type% %var% = 0 ;") )
|
||||
else if (Token::Match(tok2, "%type% %var% = 0 ;"))
|
||||
tok2 = tok2->tokAt(5);
|
||||
else if ( Token::Match(tok2, "%type% %type% %var% = 0 ;") )
|
||||
else if (Token::Match(tok2, "%type% %type% %var% = 0 ;"))
|
||||
tok2 = tok2->tokAt(6);
|
||||
else
|
||||
continue;
|
||||
|
||||
// for - condition..
|
||||
if ( !Token::Match(tok2, "%var% < %num% ;") && !Token::Match(tok2, "%var% <= %num% ;"))
|
||||
if (!Token::Match(tok2, "%var% < %num% ;") && !Token::Match(tok2, "%var% <= %num% ;"))
|
||||
continue;
|
||||
|
||||
// Get index variable and stopsize.
|
||||
const char *strindex = tok2->aaaa();
|
||||
int value = ((tok2->next()->aaaa1() == '=') ? 1 : 0) + atoi(tok2->strAt(2));
|
||||
if ( value <= size )
|
||||
if (value <= size)
|
||||
continue;
|
||||
|
||||
// Goto the end of the for loop..
|
||||
while ( tok2 && tok2->str() != ")" )
|
||||
while (tok2 && tok2->str() != ")")
|
||||
tok2 = tok2->next();
|
||||
if ( !tok2 || !tok2->tokAt(5) )
|
||||
if (!tok2 || !tok2->tokAt(5))
|
||||
break;
|
||||
|
||||
std::ostringstream pattern;
|
||||
pattern << varnames << " [ " << strindex << " ]";
|
||||
|
||||
int indentlevel2 = 0;
|
||||
while ( (tok2 = tok2->next()) )
|
||||
while ((tok2 = tok2->next()))
|
||||
{
|
||||
if ( tok2->str() == ";" && indentlevel2 == 0 )
|
||||
if (tok2->str() == ";" && indentlevel2 == 0)
|
||||
break;
|
||||
|
||||
if ( tok2->str() == "{" )
|
||||
if (tok2->str() == "{")
|
||||
++indentlevel2;
|
||||
|
||||
if ( tok2->str() == "}" )
|
||||
if (tok2->str() == "}")
|
||||
{
|
||||
--indentlevel2;
|
||||
if ( indentlevel2 <= 0 )
|
||||
if (indentlevel2 <= 0)
|
||||
break;
|
||||
}
|
||||
|
||||
if ( Token::Match(tok2, pattern.str().c_str()) )
|
||||
if (Token::Match(tok2, pattern.str().c_str()))
|
||||
{
|
||||
ReportError(tok2, "Buffer overrun");
|
||||
break;
|
||||
|
@ -239,20 +239,20 @@ void CheckBufferOverrunClass::CheckBufferOverrun_CheckScope(const Token *tok, co
|
|||
|
||||
|
||||
// Writing data into array..
|
||||
if ( Token::Match(tok, std::string( "strcpy ( "+varnames+" , %str% )" ).c_str()) )
|
||||
if (Token::Match(tok, std::string("strcpy ( " + varnames + " , %str% )").c_str()))
|
||||
{
|
||||
int len = 0;
|
||||
const char *str = tok->strAt(varc + 4 );
|
||||
while ( *str )
|
||||
const char *str = tok->strAt(varc + 4);
|
||||
while (*str)
|
||||
{
|
||||
if (*str=='\\')
|
||||
if (*str == '\\')
|
||||
++str;
|
||||
++str;
|
||||
++len;
|
||||
}
|
||||
if (len > 2 && len >= (int)size + 2)
|
||||
{
|
||||
ReportError(tok, "Buffer overrun");
|
||||
ReportError(tok, "Buffer overrun");
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
@ -261,69 +261,69 @@ void CheckBufferOverrunClass::CheckBufferOverrun_CheckScope(const Token *tok, co
|
|||
// Function call..
|
||||
// It's not interesting to check what happens when the whole struct is
|
||||
// sent as the parameter, that is checked separately anyway.
|
||||
if ( Token::Match(tok, "%var% (") )
|
||||
if (Token::Match(tok, "%var% ("))
|
||||
{
|
||||
// Don't make recursive checking..
|
||||
if (std::find(_callStack.begin(), _callStack.end(), tok) != _callStack.end())
|
||||
continue;
|
||||
|
||||
// Only perform this checking if showAll setting is enabled..
|
||||
if ( !_settings._showAll )
|
||||
if (!_settings._showAll)
|
||||
continue;
|
||||
|
||||
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 ( tok2->str() == "(" )
|
||||
if (tok2->str() == "(")
|
||||
{
|
||||
++parlevel;
|
||||
}
|
||||
|
||||
else if ( tok2->str() == ")" )
|
||||
else if (tok2->str() == ")")
|
||||
{
|
||||
--parlevel;
|
||||
if ( parlevel < 1 )
|
||||
if (parlevel < 1)
|
||||
{
|
||||
par = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
else if ( parlevel == 1 && (tok2->str() == ",") )
|
||||
else if (parlevel == 1 && (tok2->str() == ","))
|
||||
{
|
||||
++par;
|
||||
}
|
||||
|
||||
if ( parlevel == 1 && Token::Match(tok2, std::string( "[(,] "+varnames+" [,)]" ).c_str()) )
|
||||
if (parlevel == 1 && Token::Match(tok2, std::string("[(,] " + varnames + " [,)]").c_str()))
|
||||
{
|
||||
++par;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ( par == 0 )
|
||||
if (par == 0)
|
||||
continue;
|
||||
|
||||
// Find function..
|
||||
const Token *ftok = _tokenizer->GetFunctionTokenByName(tok->aaaa());
|
||||
if ( !ftok )
|
||||
if (!ftok)
|
||||
continue;
|
||||
|
||||
// Parse head of function..
|
||||
ftok = ftok->tokAt(2);
|
||||
parlevel = 1;
|
||||
while ( ftok && parlevel == 1 && par >= 1 )
|
||||
while (ftok && parlevel == 1 && par >= 1)
|
||||
{
|
||||
if ( ftok->str() == "(" )
|
||||
if (ftok->str() == "(")
|
||||
++parlevel;
|
||||
|
||||
else if ( ftok->str() == ")" )
|
||||
else if (ftok->str() == ")")
|
||||
--parlevel;
|
||||
|
||||
else if ( ftok->str() == "," )
|
||||
else if (ftok->str() == ",")
|
||||
--par;
|
||||
|
||||
else if ( par==1 && parlevel==1 && Token::Match(ftok, "%var% [,)]") )
|
||||
else if (par == 1 && parlevel == 1 && Token::Match(ftok, "%var% [,)]"))
|
||||
{
|
||||
// Parameter name..
|
||||
const char *parname[2];
|
||||
|
@ -331,7 +331,7 @@ void CheckBufferOverrunClass::CheckBufferOverrun_CheckScope(const Token *tok, co
|
|||
parname[1] = 0;
|
||||
|
||||
// Goto function body..
|
||||
while ( ftok && (ftok->str() != "{") )
|
||||
while (ftok && (ftok->str() != "{"))
|
||||
ftok = ftok->next();
|
||||
ftok = ftok ? ftok->next() : 0;
|
||||
|
||||
|
@ -415,50 +415,50 @@ void CheckBufferOverrunClass::CheckBufferOverrun_LocalVariable()
|
|||
void CheckBufferOverrunClass::CheckBufferOverrun_StructVariable()
|
||||
{
|
||||
const char declstruct[] = "struct|class %var% {";
|
||||
for ( const Token *tok = Token::findmatch(_tokenizer->tokens(), declstruct);
|
||||
tok; tok = Token::findmatch(tok->next(), declstruct) )
|
||||
for (const Token *tok = Token::findmatch(_tokenizer->tokens(), declstruct);
|
||||
tok; tok = Token::findmatch(tok->next(), declstruct))
|
||||
{
|
||||
const std::string &structname = tok->next()->str();
|
||||
|
||||
// Found a struct declaration. Search for arrays..
|
||||
for ( const Token *tok2 = tok->tokAt(2); tok2; tok2 = tok2->next() )
|
||||
for (const Token *tok2 = tok->tokAt(2); tok2; tok2 = tok2->next())
|
||||
{
|
||||
if ( tok2->str() == "}" )
|
||||
if (tok2->str() == "}")
|
||||
break;
|
||||
|
||||
int ivar = 0;
|
||||
if ( Token::Match(tok2->next(), "%type% %var% [ %num% ] ;") )
|
||||
if (Token::Match(tok2->next(), "%type% %var% [ %num% ] ;"))
|
||||
ivar = 2;
|
||||
else if ( Token::Match(tok2->next(), "%type% %type% %var% [ %num% ] ;") )
|
||||
else if (Token::Match(tok2->next(), "%type% %type% %var% [ %num% ] ;"))
|
||||
ivar = 3;
|
||||
else if ( Token::Match(tok2->next(), "%type% * %var% [ %num% ] ;") )
|
||||
else if (Token::Match(tok2->next(), "%type% * %var% [ %num% ] ;"))
|
||||
ivar = 3;
|
||||
else if ( Token::Match(tok2->next(), "%type% %type% * %var% [ %num% ] ;") )
|
||||
else if (Token::Match(tok2->next(), "%type% %type% * %var% [ %num% ] ;"))
|
||||
ivar = 4;
|
||||
else
|
||||
continue;
|
||||
|
||||
const char *varname[3] = {0,0,0};
|
||||
const char *varname[3] = {0, 0, 0};
|
||||
varname[1] = tok2->strAt(ivar);
|
||||
int arrsize = atoi(tok2->strAt(ivar+2));
|
||||
int arrsize = atoi(tok2->strAt(ivar + 2));
|
||||
int total_size = arrsize * _tokenizer->SizeOfType(tok2->next()->aaaa());
|
||||
if (total_size == 0)
|
||||
continue;
|
||||
|
||||
|
||||
// Class member variable => Check functions
|
||||
if ( tok->str() == "class" )
|
||||
if (tok->str() == "class")
|
||||
{
|
||||
std::string func_pattern(structname + " :: %var% (");
|
||||
const Token *tok3 = Token::findmatch(_tokenizer->tokens(), func_pattern.c_str());
|
||||
while ( tok3 )
|
||||
while (tok3)
|
||||
{
|
||||
for ( const Token *tok4 = tok3; tok4; tok4 = tok4->next() )
|
||||
for (const Token *tok4 = tok3; tok4; tok4 = tok4->next())
|
||||
{
|
||||
if ( Token::Match(tok4, "[;{}]") )
|
||||
if (Token::Match(tok4, "[;{}]"))
|
||||
break;
|
||||
|
||||
if ( Token::simpleMatch(tok4, ") {") )
|
||||
if (Token::simpleMatch(tok4, ") {"))
|
||||
{
|
||||
const char *names[2] = {varname[1], 0};
|
||||
CheckBufferOverrun_CheckScope(tok4->tokAt(2), names, arrsize, total_size, 0);
|
||||
|
@ -469,17 +469,17 @@ void CheckBufferOverrunClass::CheckBufferOverrun_StructVariable()
|
|||
}
|
||||
}
|
||||
|
||||
for ( const Token *tok3 = _tokenizer->tokens(); tok3; tok3 = tok3->next() )
|
||||
for (const Token *tok3 = _tokenizer->tokens(); tok3; tok3 = tok3->next())
|
||||
{
|
||||
if ( tok3->str() != structname )
|
||||
if (tok3->str() != structname)
|
||||
continue;
|
||||
|
||||
// Declare variable: Fred fred1;
|
||||
if ( Token::Match( tok3->next(), "%var% ;" ) )
|
||||
if (Token::Match(tok3->next(), "%var% ;"))
|
||||
varname[0] = tok3->strAt(1);
|
||||
|
||||
// Declare pointer: Fred *fred1
|
||||
else if ( Token::Match(tok3->next(), "* %var% [,);=]") )
|
||||
else if (Token::Match(tok3->next(), "* %var% [,);=]"))
|
||||
varname[0] = tok3->strAt(2);
|
||||
|
||||
else
|
||||
|
@ -488,21 +488,21 @@ void CheckBufferOverrunClass::CheckBufferOverrun_StructVariable()
|
|||
|
||||
// Goto end of statement.
|
||||
const Token *CheckTok = NULL;
|
||||
while ( tok3 )
|
||||
while (tok3)
|
||||
{
|
||||
// End of statement.
|
||||
if ( tok3->str() == ";" )
|
||||
if (tok3->str() == ";")
|
||||
{
|
||||
CheckTok = tok3;
|
||||
break;
|
||||
}
|
||||
|
||||
// End of function declaration..
|
||||
if ( Token::simpleMatch(tok3, ") ;") )
|
||||
if (Token::simpleMatch(tok3, ") ;"))
|
||||
break;
|
||||
|
||||
// Function implementation..
|
||||
if ( Token::simpleMatch(tok3, ") {") )
|
||||
if (Token::simpleMatch(tok3, ") {"))
|
||||
{
|
||||
CheckTok = tok3->tokAt(2);
|
||||
break;
|
||||
|
@ -511,10 +511,10 @@ void CheckBufferOverrunClass::CheckBufferOverrun_StructVariable()
|
|||
tok3 = tok3->next();
|
||||
}
|
||||
|
||||
if ( !tok3 )
|
||||
if (!tok3)
|
||||
break;
|
||||
|
||||
if ( !CheckTok )
|
||||
if (!CheckTok)
|
||||
continue;
|
||||
|
||||
// Check variable usage..
|
||||
|
|
|
@ -28,7 +28,7 @@
|
|||
class CheckBufferOverrunClass
|
||||
{
|
||||
public:
|
||||
CheckBufferOverrunClass( const Tokenizer *tokenizer, const Settings &settings, ErrorLogger *errorLogger );
|
||||
CheckBufferOverrunClass(const Tokenizer *tokenizer, const Settings &settings, ErrorLogger *errorLogger);
|
||||
~CheckBufferOverrunClass();
|
||||
|
||||
// Buffer overrun..
|
||||
|
@ -40,7 +40,7 @@ public:
|
|||
private:
|
||||
void CheckBufferOverrun_StructVariable();
|
||||
void CheckBufferOverrun_LocalVariable();
|
||||
void CheckBufferOverrun_CheckScope( const Token *tok, const char *varname[], const int size, const int total_size, unsigned int varid );
|
||||
void CheckBufferOverrun_CheckScope(const Token *tok, const char *varname[], const int size, const int total_size, unsigned int varid);
|
||||
void ReportError(const Token *tok, const char errmsg[]);
|
||||
|
||||
const Tokenizer *_tokenizer;
|
||||
|
|
178
checkclass.cpp
178
checkclass.cpp
|
@ -33,7 +33,7 @@
|
|||
#endif
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
CheckClass::CheckClass( const Tokenizer *tokenizer, const Settings &settings, ErrorLogger *errorLogger )
|
||||
CheckClass::CheckClass(const Tokenizer *tokenizer, const Settings &settings, ErrorLogger *errorLogger)
|
||||
{
|
||||
_tokenizer = tokenizer;
|
||||
_settings = settings;
|
||||
|
@ -66,14 +66,14 @@ struct CheckClass::VAR *CheckClass::ClassChecking_GetVarList(const Token *tok1)
|
|||
--indentlevel;
|
||||
}
|
||||
|
||||
if ( indentlevel != 1 )
|
||||
if (indentlevel != 1)
|
||||
continue;
|
||||
|
||||
// "private:" "public:" "protected:" etc
|
||||
bool b = bool((*tok->strAt(0) != ':') && strchr(tok->strAt(0), ':') != 0);
|
||||
|
||||
// Search for start of statement..
|
||||
if ( ! Token::Match(tok, "[;{}]") && ! b )
|
||||
if (! Token::Match(tok, "[;{}]") && ! b)
|
||||
continue;
|
||||
|
||||
// This is the start of a statement
|
||||
|
@ -81,14 +81,14 @@ struct CheckClass::VAR *CheckClass::ClassChecking_GetVarList(const Token *tok1)
|
|||
const char *varname = 0;
|
||||
|
||||
// Is it a variable declaration?
|
||||
if ( Token::Match(next,"%type% %var% ;") )
|
||||
if (Token::Match(next, "%type% %var% ;"))
|
||||
{
|
||||
if ( next->isStandardType() )
|
||||
if (next->isStandardType())
|
||||
varname = next->strAt(1);
|
||||
}
|
||||
|
||||
// Pointer?
|
||||
else if ( Token::Match(next, "%type% * %var% ;") )
|
||||
else if (Token::Match(next, "%type% * %var% ;"))
|
||||
{
|
||||
varname = next->strAt(2);
|
||||
}
|
||||
|
@ -109,9 +109,9 @@ struct CheckClass::VAR *CheckClass::ClassChecking_GetVarList(const Token *tok1)
|
|||
}
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
const Token * CheckClass::FindClassFunction( const Token *tok, const char classname[], const char funcname[], int &indentlevel )
|
||||
const Token * CheckClass::FindClassFunction(const Token *tok, const char classname[], const char funcname[], int &indentlevel)
|
||||
{
|
||||
if ( indentlevel < 0 || tok == NULL )
|
||||
if (indentlevel < 0 || tok == NULL)
|
||||
return NULL;
|
||||
|
||||
std::ostringstream classPattern;
|
||||
|
@ -123,66 +123,66 @@ const Token * CheckClass::FindClassFunction( const Token *tok, const char classn
|
|||
std::ostringstream externalPattern;
|
||||
externalPattern << classname << " :: " << funcname << " (";
|
||||
|
||||
for ( ;tok; tok = tok->next() )
|
||||
for (;tok; tok = tok->next())
|
||||
{
|
||||
if ( indentlevel == 0 && Token::Match(tok, classPattern.str().c_str()) )
|
||||
if (indentlevel == 0 && Token::Match(tok, classPattern.str().c_str()))
|
||||
{
|
||||
while ( tok && tok->str() != "{" )
|
||||
while (tok && tok->str() != "{")
|
||||
tok = tok->next();
|
||||
if ( tok )
|
||||
if (tok)
|
||||
tok = tok->next();
|
||||
if ( ! tok )
|
||||
if (! tok)
|
||||
break;
|
||||
indentlevel = 1;
|
||||
}
|
||||
|
||||
if ( tok->str() == "{" )
|
||||
if (tok->str() == "{")
|
||||
{
|
||||
// If indentlevel==0 don't go to indentlevel 1. Skip the block.
|
||||
if ( indentlevel > 0 )
|
||||
if (indentlevel > 0)
|
||||
++indentlevel;
|
||||
|
||||
else
|
||||
{
|
||||
for ( ; tok; tok = tok->next() )
|
||||
for (; tok; tok = tok->next())
|
||||
{
|
||||
if ( tok->str() == "{" )
|
||||
if (tok->str() == "{")
|
||||
++indentlevel;
|
||||
else if ( tok->str() == "}" )
|
||||
else if (tok->str() == "}")
|
||||
{
|
||||
--indentlevel;
|
||||
if ( indentlevel <= 0 )
|
||||
if (indentlevel <= 0)
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ( tok == NULL )
|
||||
if (tok == NULL)
|
||||
return NULL;
|
||||
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if ( tok->str() == "}" )
|
||||
if (tok->str() == "}")
|
||||
{
|
||||
--indentlevel;
|
||||
if ( indentlevel < 0 )
|
||||
if (indentlevel < 0)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if ( indentlevel == 1 )
|
||||
if (indentlevel == 1)
|
||||
{
|
||||
// Member function implemented in the class declaration?
|
||||
if (tok->str()!="~" && Token::Match(tok->next(), internalPattern.str().c_str()))
|
||||
if (tok->str() != "~" && Token::Match(tok->next(), internalPattern.str().c_str()))
|
||||
{
|
||||
const Token *tok2 = tok;
|
||||
while ( tok2 && tok2->str() != "{" && tok2->str() != ";" )
|
||||
while (tok2 && tok2->str() != "{" && tok2->str() != ";")
|
||||
tok2 = tok2->next();
|
||||
if ( tok2 && tok2->str() == "{" )
|
||||
if (tok2 && tok2->str() == "{")
|
||||
return tok->next();
|
||||
}
|
||||
}
|
||||
|
||||
else if ( indentlevel == 0 && Token::Match(tok, externalPattern.str().c_str()) )
|
||||
else if (indentlevel == 0 && Token::Match(tok, externalPattern.str().c_str()))
|
||||
{
|
||||
return tok;
|
||||
}
|
||||
|
@ -197,7 +197,7 @@ void CheckClass::InitVar(struct VAR *varlist, const char varname[])
|
|||
{
|
||||
for (struct VAR *var = varlist; var; var = var->next)
|
||||
{
|
||||
if ( strcmp(var->name, varname) == 0 )
|
||||
if (strcmp(var->name, varname) == 0)
|
||||
{
|
||||
var->init = true;
|
||||
break;
|
||||
|
@ -218,11 +218,11 @@ void CheckClass::ClassChecking_VarList_Initialize(const Token *tok1, const Token
|
|||
|
||||
// Class constructor.. initializing variables like this
|
||||
// clKalle::clKalle() : var(value) { }
|
||||
if (indentlevel==0)
|
||||
if (indentlevel == 0)
|
||||
{
|
||||
if (Assign && Token::Match(ftok, "%var% ("))
|
||||
{
|
||||
InitVar( varlist, ftok->aaaa() );
|
||||
InitVar(varlist, ftok->aaaa());
|
||||
}
|
||||
|
||||
Assign |= (ftok->str() == ":");
|
||||
|
@ -242,15 +242,15 @@ void CheckClass::ClassChecking_VarList_Initialize(const Token *tok1, const Token
|
|||
--indentlevel;
|
||||
}
|
||||
|
||||
if ( indentlevel < 1 )
|
||||
if (indentlevel < 1)
|
||||
continue;
|
||||
|
||||
// Before a new statement there is "[{};)=]" or "else"
|
||||
if ( ! Token::Match(ftok, "[{};)=]") && ftok->str() != "else" )
|
||||
if (! Token::Match(ftok, "[{};)=]") && ftok->str() != "else")
|
||||
continue;
|
||||
|
||||
// Using the operator= function to initialize all variables..
|
||||
if ( Token::simpleMatch(ftok->next(), "* this = ") )
|
||||
if (Token::simpleMatch(ftok->next(), "* this = "))
|
||||
{
|
||||
for (struct VAR *var = varlist; var; var = var->next)
|
||||
var->init = true;
|
||||
|
@ -264,11 +264,11 @@ void CheckClass::ClassChecking_VarList_Initialize(const Token *tok1, const Token
|
|||
ftok = ftok->next();
|
||||
|
||||
// Skip "this->"
|
||||
if ( Token::simpleMatch(ftok, "this .") )
|
||||
if (Token::simpleMatch(ftok, "this ."))
|
||||
ftok = ftok->tokAt(2);
|
||||
|
||||
// Clearing all variables..
|
||||
if (Token::simpleMatch(ftok,"memset ( this ,"))
|
||||
if (Token::simpleMatch(ftok, "memset ( this ,"))
|
||||
{
|
||||
for (struct VAR *var = varlist; var; var = var->next)
|
||||
var->init = true;
|
||||
|
@ -279,11 +279,11 @@ void CheckClass::ClassChecking_VarList_Initialize(const Token *tok1, const Token
|
|||
else if (Token::Match(ftok, "%var% ("))
|
||||
{
|
||||
// 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())
|
||||
{
|
||||
callstack.push_back( ftok->str() );
|
||||
callstack.push_back(ftok->str());
|
||||
int i = 0;
|
||||
const Token *ftok2 = FindClassFunction( tok1, classname, ftok->aaaa(), i );
|
||||
const Token *ftok2 = FindClassFunction(tok1, classname, ftok->aaaa(), i);
|
||||
ClassChecking_VarList_Initialize(tok1, ftok2, varlist, classname, callstack);
|
||||
}
|
||||
}
|
||||
|
@ -291,13 +291,13 @@ void CheckClass::ClassChecking_VarList_Initialize(const Token *tok1, const Token
|
|||
// Assignment of member variable?
|
||||
else if (Token::Match(ftok, "%var% ="))
|
||||
{
|
||||
InitVar( varlist, ftok->aaaa() );
|
||||
InitVar(varlist, ftok->aaaa());
|
||||
}
|
||||
|
||||
// The functions 'clear' and 'Clear' are supposed to initialize variable.
|
||||
if (Token::Match(ftok,"%var% . clear|Clear ("))
|
||||
if (Token::Match(ftok, "%var% . clear|Clear ("))
|
||||
{
|
||||
InitVar( varlist, ftok->aaaa() );
|
||||
InitVar(varlist, ftok->aaaa());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -316,26 +316,26 @@ void CheckClass::constructors()
|
|||
const char pattern_class[] = "class %var% {";
|
||||
|
||||
// Locate class
|
||||
const Token *tok1 = Token::findmatch( _tokenizer->tokens(), pattern_class );
|
||||
const Token *tok1 = Token::findmatch(_tokenizer->tokens(), pattern_class);
|
||||
while (tok1)
|
||||
{
|
||||
const char *className[2];
|
||||
className[0] = tok1->strAt( 1 );
|
||||
className[0] = tok1->strAt(1);
|
||||
className[1] = 0;
|
||||
const Token *classNameToken = tok1->tokAt( 1 );
|
||||
const Token *classNameToken = tok1->tokAt(1);
|
||||
|
||||
// TODO: handling of private constructors should be improved.
|
||||
bool hasPrivateConstructor = false;
|
||||
{
|
||||
int indentlevel = 0;
|
||||
bool isPrivate = true;
|
||||
for ( const Token *tok = tok1; tok; tok = tok->next() )
|
||||
for (const Token *tok = tok1; tok; tok = tok->next())
|
||||
{
|
||||
// Indentation
|
||||
if ( tok->str() == "{" )
|
||||
if (tok->str() == "{")
|
||||
++indentlevel;
|
||||
|
||||
else if ( tok->str() == "}" )
|
||||
else if (tok->str() == "}")
|
||||
{
|
||||
--indentlevel;
|
||||
if (indentlevel <= 0)
|
||||
|
@ -343,16 +343,16 @@ void CheckClass::constructors()
|
|||
}
|
||||
|
||||
// Parse class contents (indentlevel == 1)..
|
||||
if ( indentlevel == 1 )
|
||||
if (indentlevel == 1)
|
||||
{
|
||||
// What section are we in.. private/non-private
|
||||
if ( tok->str() == "private:" )
|
||||
if (tok->str() == "private:")
|
||||
isPrivate = true;
|
||||
else if ( tok->str() == "protected:" || tok->str() == "public:" )
|
||||
else if (tok->str() == "protected:" || tok->str() == "public:")
|
||||
isPrivate = false;
|
||||
|
||||
// Is there a private constructor?
|
||||
else if ( isPrivate && Token::simpleMatch(tok, classNameToken->str() + " (") )
|
||||
else if (isPrivate && Token::simpleMatch(tok, (classNameToken->str() + " (").c_str()))
|
||||
{
|
||||
hasPrivateConstructor = true;
|
||||
break;
|
||||
|
@ -361,29 +361,29 @@ void CheckClass::constructors()
|
|||
}
|
||||
}
|
||||
|
||||
if ( hasPrivateConstructor )
|
||||
if (hasPrivateConstructor)
|
||||
{
|
||||
// TODO: Handle private constructors.
|
||||
// Right now to avoid false positives I just bail out
|
||||
tok1 = Token::findmatch( tok1->next(), pattern_class );
|
||||
tok1 = Token::findmatch(tok1->next(), pattern_class);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Are there a class constructor?
|
||||
std::string tempPattern = "%any% " + classNameToken->str() + " (";
|
||||
const Token *constructor_token = Token::findmatch( tok1, tempPattern.c_str() );
|
||||
while ( Token::Match( constructor_token, "~" ) )
|
||||
constructor_token = Token::findmatch( constructor_token->next(), tempPattern.c_str() );
|
||||
const Token *constructor_token = Token::findmatch(tok1, tempPattern.c_str());
|
||||
while (Token::Match(constructor_token, "~"))
|
||||
constructor_token = Token::findmatch(constructor_token->next(), tempPattern.c_str());
|
||||
|
||||
// There are no constructor.
|
||||
if ( ! constructor_token )
|
||||
if (! constructor_token)
|
||||
{
|
||||
// If "--style" has been given, give a warning
|
||||
if ( _settings._checkCodingStyle )
|
||||
if (_settings._checkCodingStyle)
|
||||
{
|
||||
// If the class has member variables there should be an constructor
|
||||
struct VAR *varlist = ClassChecking_GetVarList(tok1);
|
||||
if ( varlist )
|
||||
if (varlist)
|
||||
{
|
||||
std::ostringstream ostr;
|
||||
ostr << _tokenizer->fileLine(tok1);
|
||||
|
@ -399,7 +399,7 @@ void CheckClass::constructors()
|
|||
}
|
||||
}
|
||||
|
||||
tok1 = Token::findmatch( tok1->next(), pattern_class );
|
||||
tok1 = Token::findmatch(tok1->next(), pattern_class);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -407,10 +407,10 @@ void CheckClass::constructors()
|
|||
struct VAR *varlist = ClassChecking_GetVarList(tok1);
|
||||
|
||||
// Check constructors
|
||||
CheckConstructors( tok1, varlist, className[0] );
|
||||
CheckConstructors(tok1, varlist, className[0]);
|
||||
|
||||
// Check assignment operators
|
||||
CheckConstructors( tok1, varlist, "operator =" );
|
||||
CheckConstructors(tok1, varlist, "operator =");
|
||||
|
||||
// Delete the varlist..
|
||||
while (varlist)
|
||||
|
@ -420,7 +420,7 @@ void CheckClass::constructors()
|
|||
varlist = nextvar;
|
||||
}
|
||||
|
||||
tok1 = Token::findmatch( tok1->next(), pattern_class );
|
||||
tok1 = Token::findmatch(tok1->next(), pattern_class);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -429,15 +429,15 @@ void CheckClass::CheckConstructors(const Token *tok1, struct VAR *varlist, const
|
|||
const char * const className = tok1->strAt(1);
|
||||
|
||||
int indentlevel = 0;
|
||||
const Token *constructor_token = FindClassFunction( tok1, className, funcname, indentlevel );
|
||||
const Token *constructor_token = FindClassFunction(tok1, className, funcname, indentlevel);
|
||||
std::list<std::string> callstack;
|
||||
ClassChecking_VarList_Initialize(tok1, constructor_token, varlist, className, callstack);
|
||||
while ( constructor_token )
|
||||
while (constructor_token)
|
||||
{
|
||||
// Check if any variables are uninitialized
|
||||
for (struct VAR *var = varlist; var; var = var->next)
|
||||
{
|
||||
if ( var->init )
|
||||
if (var->init)
|
||||
continue;
|
||||
|
||||
// Is it a static member variable?
|
||||
|
@ -453,10 +453,10 @@ void CheckClass::CheckConstructors(const Token *tok1, struct VAR *varlist, const
|
|||
_errorLogger->reportErr(ostr.str());
|
||||
}
|
||||
|
||||
for ( struct VAR *var = varlist; var; var = var->next )
|
||||
for (struct VAR *var = varlist; var; var = var->next)
|
||||
var->init = false;
|
||||
|
||||
constructor_token = FindClassFunction( constructor_token->next(), className, funcname, indentlevel );
|
||||
constructor_token = FindClassFunction(constructor_token->next(), className, funcname, indentlevel);
|
||||
callstack.clear();
|
||||
ClassChecking_VarList_Initialize(tok1, constructor_token, varlist, className, callstack);
|
||||
}
|
||||
|
@ -486,7 +486,7 @@ void CheckClass::privateFunctions()
|
|||
unsigned int indent_level = 0;
|
||||
for (const Token *tok = tok1; tok; tok = tok->next())
|
||||
{
|
||||
if (Token::Match(tok,"friend %var%"))
|
||||
if (Token::Match(tok, "friend %var%"))
|
||||
{
|
||||
// Todo: Handle friend classes
|
||||
FuncList.clear();
|
||||
|
@ -509,11 +509,11 @@ void CheckClass::privateFunctions()
|
|||
priv = false;
|
||||
else if (priv && indent_level == 1)
|
||||
{
|
||||
if ( Token::Match(tok, "typedef %type% (") )
|
||||
if (Token::Match(tok, "typedef %type% ("))
|
||||
tok = tok->tokAt(2);
|
||||
|
||||
if (Token::Match(tok, "%var% (") &&
|
||||
!Token::Match(tok,classname.c_str()))
|
||||
!Token::Match(tok, classname.c_str()))
|
||||
{
|
||||
FuncList.push_back(tok->str());
|
||||
}
|
||||
|
@ -526,7 +526,7 @@ void CheckClass::privateFunctions()
|
|||
const Token *ftok = _tokenizer->tokens();
|
||||
while (ftok)
|
||||
{
|
||||
ftok = Token::findmatch(ftok,pattern_function.c_str());
|
||||
ftok = Token::findmatch(ftok, pattern_function.c_str());
|
||||
int numpar = 0;
|
||||
while (ftok && !Token::Match(ftok, "[;{]"))
|
||||
{
|
||||
|
@ -551,11 +551,11 @@ void CheckClass::privateFunctions()
|
|||
++indent_level;
|
||||
if (ftok->str() == "}")
|
||||
{
|
||||
if (indent_level<=1)
|
||||
if (indent_level <= 1)
|
||||
break;
|
||||
--indent_level;
|
||||
}
|
||||
if (Token::Match( ftok->next(), "(") )
|
||||
if (Token::Match(ftok->next(), "("))
|
||||
FuncList.remove(ftok->str());
|
||||
ftok = ftok->next();
|
||||
}
|
||||
|
@ -589,7 +589,7 @@ void CheckClass::noMemset()
|
|||
// Locate all 'memset' tokens..
|
||||
for (const Token *tok = _tokenizer->tokens(); tok; tok = tok->next())
|
||||
{
|
||||
if (!Token::Match(tok,"memset|memcpy|memmove"))
|
||||
if (!Token::Match(tok, "memset|memcpy|memmove"))
|
||||
continue;
|
||||
|
||||
// Todo: Handle memcpy and memmove
|
||||
|
@ -611,7 +611,7 @@ void CheckClass::noMemset()
|
|||
|
||||
// Warn if type is a class..
|
||||
const std::string pattern1(std::string("class ") + type);
|
||||
if (Token::findmatch(_tokenizer->tokens(),pattern1.c_str()))
|
||||
if (Token::findmatch(_tokenizer->tokens(), pattern1.c_str()))
|
||||
{
|
||||
std::ostringstream ostr;
|
||||
ostr << _tokenizer->fileLine(tok) << ": Using '" << tok->str() << "' on class.";
|
||||
|
@ -674,17 +674,17 @@ void CheckClass::virtualDestructor()
|
|||
{
|
||||
std::ostringstream destructorPattern;
|
||||
destructorPattern << "~ " << derived->strAt(1) << " ( ) {";
|
||||
const Token *derived_destructor = Token::findmatch( _tokenizer->tokens(), destructorPattern.str().c_str() );
|
||||
const Token *derived_destructor = Token::findmatch(_tokenizer->tokens(), destructorPattern.str().c_str());
|
||||
|
||||
// No destructor..
|
||||
if ( ! derived_destructor )
|
||||
if (! derived_destructor)
|
||||
{
|
||||
derived = derived->next();
|
||||
continue;
|
||||
}
|
||||
|
||||
// Empty destructor..
|
||||
if ( Token::Match(derived_destructor, "~ %var% ( ) { }") )
|
||||
if (Token::Match(derived_destructor, "~ %var% ( ) { }"))
|
||||
{
|
||||
derived = derived->next();
|
||||
continue;
|
||||
|
@ -695,12 +695,12 @@ void CheckClass::virtualDestructor()
|
|||
|
||||
// Iterate through each base class...
|
||||
derived = derived->tokAt(3);
|
||||
while ( Token::Match(derived, "%var%") )
|
||||
while (Token::Match(derived, "%var%"))
|
||||
{
|
||||
bool isPublic = Token::Match(derived, "public");
|
||||
|
||||
// What kind of inheritance is it.. public|protected|private
|
||||
if ( Token::Match( derived, "public|protected|private" ) )
|
||||
if (Token::Match(derived, "public|protected|private"))
|
||||
derived = derived->next();
|
||||
|
||||
// Name of base class..
|
||||
|
@ -710,27 +710,27 @@ void CheckClass::virtualDestructor()
|
|||
|
||||
// Update derived so it's ready for the next loop.
|
||||
derived = derived->next();
|
||||
if ( Token::Match(derived, ",") )
|
||||
if (Token::Match(derived, ","))
|
||||
derived = derived->next();
|
||||
|
||||
// If not public inheritance, skip checking of this base class..
|
||||
if ( ! isPublic )
|
||||
if (! isPublic)
|
||||
continue;
|
||||
|
||||
// Find the destructor declaration for the base class.
|
||||
const Token *base = Token::findmatch(_tokenizer->tokens(), (std::string( "%any% ~ " )+baseName[0]+" (" ).c_str());
|
||||
const Token *base = Token::findmatch(_tokenizer->tokens(), (std::string("%any% ~ ") + baseName[0] + " (").c_str());
|
||||
while (Token::Match(base, "::"))
|
||||
base = Token::findmatch(base->next(), (std::string( "%any% ~ " ) + baseName[0] + +" (").c_str());
|
||||
base = Token::findmatch(base->next(), (std::string("%any% ~ ") + baseName[0] + + " (").c_str());
|
||||
|
||||
while (Token::Match(base, "%var%") && !Token::Match(base, "virtual"))
|
||||
base = base->previous();
|
||||
|
||||
// Check that there is a destructor..
|
||||
if ( ! base )
|
||||
if (! base)
|
||||
{
|
||||
// Is the class declaration available?
|
||||
base = Token::findmatch(_tokenizer->tokens(), (std::string( "class ")+baseName[0]+" :|{").c_str());
|
||||
if ( base )
|
||||
base = Token::findmatch(_tokenizer->tokens(), (std::string("class ") + baseName[0] + " :|{").c_str());
|
||||
if (base)
|
||||
{
|
||||
std::ostringstream errmsg;
|
||||
errmsg << _tokenizer->fileLine(base) << ": Class " << baseName[0] << " which is inherited by class " << derivedClass->str() << " does not have a virtual destructor";
|
||||
|
@ -739,7 +739,7 @@ void CheckClass::virtualDestructor()
|
|||
}
|
||||
|
||||
// There is a destructor. Check that it's virtual..
|
||||
else if ( base->str() != "virtual" )
|
||||
else if (base->str() != "virtual")
|
||||
{
|
||||
std::ostringstream errmsg;
|
||||
errmsg << _tokenizer->fileLine(base) << ": Class " << baseName[0] << " which is inherited by class " << derivedClass->str() << " does not have a virtual destructor";
|
||||
|
|
|
@ -28,7 +28,7 @@
|
|||
class CheckClass
|
||||
{
|
||||
public:
|
||||
CheckClass( const Tokenizer *tokenizer, const Settings &settings, ErrorLogger *errorLogger );
|
||||
CheckClass(const Tokenizer *tokenizer, const Settings &settings, ErrorLogger *errorLogger);
|
||||
~CheckClass();
|
||||
|
||||
void constructors();
|
||||
|
@ -52,7 +52,7 @@ private:
|
|||
|
||||
void ClassChecking_VarList_Initialize(const Token *tok1, const Token *ftok, struct VAR *varlist, const char classname[], std::list<std::string> &callstack);
|
||||
void InitVar(struct VAR *varlist, const char varname[]);
|
||||
const Token *FindClassFunction( const Token *tok, const char classname[], const char funcname[], int &indentlevel );
|
||||
const Token *FindClassFunction(const Token *tok, const char classname[], const char funcname[], int &indentlevel);
|
||||
struct VAR *ClassChecking_GetVarList(const Token *tok1);
|
||||
|
||||
// Check constructors for a specified class
|
||||
|
|
|
@ -30,7 +30,7 @@
|
|||
// FUNCTION USAGE - Check for unused functions etc
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
CheckFunctionUsage::CheckFunctionUsage( ErrorLogger *errorLogger )
|
||||
CheckFunctionUsage::CheckFunctionUsage(ErrorLogger *errorLogger)
|
||||
{
|
||||
_errorLogger = errorLogger;
|
||||
}
|
||||
|
@ -40,42 +40,42 @@ CheckFunctionUsage::~CheckFunctionUsage()
|
|||
|
||||
}
|
||||
|
||||
void CheckFunctionUsage::setErrorLogger( ErrorLogger *errorLogger )
|
||||
void CheckFunctionUsage::setErrorLogger(ErrorLogger *errorLogger)
|
||||
{
|
||||
_errorLogger = errorLogger;
|
||||
}
|
||||
|
||||
void CheckFunctionUsage::parseTokens( const Tokenizer &tokenizer )
|
||||
void CheckFunctionUsage::parseTokens(const Tokenizer &tokenizer)
|
||||
{
|
||||
// Function declarations..
|
||||
for ( const Token *tok = tokenizer.tokens(); tok; tok = tok->next() )
|
||||
for (const Token *tok = tokenizer.tokens(); tok; tok = tok->next())
|
||||
{
|
||||
if ( tok->fileIndex() != 0 )
|
||||
if (tok->fileIndex() != 0)
|
||||
continue;
|
||||
|
||||
const Token *funcname = 0;
|
||||
|
||||
if ( Token::Match( tok, "%type% %var% (" ) )
|
||||
if (Token::Match(tok, "%type% %var% ("))
|
||||
funcname = tok->tokAt(1);
|
||||
else if ( Token::Match(tok, "%type% * %var% (") )
|
||||
else if (Token::Match(tok, "%type% * %var% ("))
|
||||
funcname = tok->tokAt(2);
|
||||
else if ( Token::Match(tok, "%type% :: %var% (") && !Token::Match(tok, tok->strAt(2)) )
|
||||
else if (Token::Match(tok, "%type% :: %var% (") && !Token::Match(tok, tok->strAt(2)))
|
||||
funcname = tok->tokAt(2);
|
||||
|
||||
// Check that ") {" is found..
|
||||
for (const Token *tok2 = funcname; tok2; tok2 = tok2->next())
|
||||
{
|
||||
if ( Token::Match(tok2, ")") )
|
||||
if (Token::Match(tok2, ")"))
|
||||
{
|
||||
if ( ! Token::Match(tok2, ") {") && ! Token::Match(tok2, ") const {") )
|
||||
if (! Token::Match(tok2, ") {") && ! Token::Match(tok2, ") const {"))
|
||||
funcname = NULL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ( funcname )
|
||||
if (funcname)
|
||||
{
|
||||
FunctionUsage &func = _functions[ funcname->str() ];
|
||||
FunctionUsage &func = _functions[ funcname->str()];
|
||||
|
||||
// No filename set yet..
|
||||
if (func.filename.empty())
|
||||
|
@ -91,25 +91,25 @@ void CheckFunctionUsage::parseTokens( const Tokenizer &tokenizer )
|
|||
}
|
||||
|
||||
// Function usage..
|
||||
for ( const Token *tok = tokenizer.tokens(); tok; tok = tok->next() )
|
||||
for (const Token *tok = tokenizer.tokens(); tok; tok = tok->next())
|
||||
{
|
||||
const Token *funcname = 0;
|
||||
|
||||
if ( Token::Match( tok, "[;{}.,()[=+-/&|!?:] %var% [(),;:}]" ) ||
|
||||
Token::Match(tok, ":: %var% (") ||
|
||||
Token::Match(tok, "|= %var% (") ||
|
||||
Token::Match(tok, "&= %var% (") ||
|
||||
Token::Match(tok, "&& %var% (") ||
|
||||
Token::Match(tok, "|| %var% (") ||
|
||||
Token::Match(tok, "else %var% (") ||
|
||||
Token::Match(tok, "return %var% (") )
|
||||
if (Token::Match(tok, "[;{}.,()[=+-/&|!?:] %var% [(),;:}]") ||
|
||||
Token::Match(tok, ":: %var% (") ||
|
||||
Token::Match(tok, "|= %var% (") ||
|
||||
Token::Match(tok, "&= %var% (") ||
|
||||
Token::Match(tok, "&& %var% (") ||
|
||||
Token::Match(tok, "|| %var% (") ||
|
||||
Token::Match(tok, "else %var% (") ||
|
||||
Token::Match(tok, "return %var% ("))
|
||||
funcname = tok->next();
|
||||
|
||||
// funcname ( => Assert that the end paranthesis isn't followed by {
|
||||
if ( Token::Match(funcname, "%var% (") )
|
||||
if (Token::Match(funcname, "%var% ("))
|
||||
{
|
||||
int parlevel = 0;
|
||||
for ( const Token *tok2 = funcname; tok2; tok2 = tok2->next() )
|
||||
for (const Token *tok2 = funcname; tok2; tok2 = tok2->next())
|
||||
{
|
||||
if (tok2->str() == "(")
|
||||
++parlevel;
|
||||
|
@ -119,17 +119,17 @@ void CheckFunctionUsage::parseTokens( const Tokenizer &tokenizer )
|
|||
--parlevel;
|
||||
if (parlevel == 0 && (Token::Match(tok2, ") {") || Token::Match(tok2, ") const")))
|
||||
funcname = NULL;
|
||||
if ( parlevel <= 0 )
|
||||
if (parlevel <= 0)
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( funcname )
|
||||
if (funcname)
|
||||
{
|
||||
FunctionUsage &func = _functions[ funcname->str() ];
|
||||
FunctionUsage &func = _functions[ funcname->str()];
|
||||
|
||||
if ( func.filename.empty() || func.filename == "+" )
|
||||
if (func.filename.empty() || func.filename == "+")
|
||||
func.usedOtherFile = true;
|
||||
|
||||
else
|
||||
|
@ -143,20 +143,20 @@ void CheckFunctionUsage::parseTokens( const Tokenizer &tokenizer )
|
|||
|
||||
void CheckFunctionUsage::check()
|
||||
{
|
||||
for ( std::map<std::string, FunctionUsage>::const_iterator it = _functions.begin(); it != _functions.end(); ++it )
|
||||
for (std::map<std::string, FunctionUsage>::const_iterator it = _functions.begin(); it != _functions.end(); ++it)
|
||||
{
|
||||
const FunctionUsage &func = it->second;
|
||||
if ( func.usedOtherFile || func.filename.empty() )
|
||||
if (func.usedOtherFile || func.filename.empty())
|
||||
continue;
|
||||
if ( ! func.usedSameFile )
|
||||
if (! func.usedSameFile)
|
||||
{
|
||||
std::ostringstream errmsg;
|
||||
if ( func.filename != "+" )
|
||||
if (func.filename != "+")
|
||||
errmsg << "[" << func.filename << "] ";
|
||||
errmsg << "The function '" << it->first << "' is never used.";
|
||||
_errorLogger->reportErr( errmsg.str() );
|
||||
_errorLogger->reportErr(errmsg.str());
|
||||
}
|
||||
else if ( ! func.usedOtherFile )
|
||||
else if (! func.usedOtherFile)
|
||||
{
|
||||
/* TODO - add error message "function is only used in <file> it can be static"
|
||||
std::ostringstream errmsg;
|
||||
|
|
|
@ -28,7 +28,7 @@
|
|||
class CheckFunctionUsage
|
||||
{
|
||||
public:
|
||||
CheckFunctionUsage( ErrorLogger *errorLogger = 0 );
|
||||
CheckFunctionUsage(ErrorLogger *errorLogger = 0);
|
||||
~CheckFunctionUsage();
|
||||
|
||||
/**
|
||||
|
@ -36,12 +36,12 @@ public:
|
|||
* errorlogger.
|
||||
* @param errorLogger The errorlogger to be used.
|
||||
*/
|
||||
void setErrorLogger( ErrorLogger *errorLogger );
|
||||
void setErrorLogger(ErrorLogger *errorLogger);
|
||||
|
||||
// Parse current tokens and determine..
|
||||
// * Check what functions are used
|
||||
// * What functions are declared
|
||||
void parseTokens( const Tokenizer &tokenizer );
|
||||
void parseTokens(const Tokenizer &tokenizer);
|
||||
|
||||
|
||||
void check();
|
||||
|
|
|
@ -35,7 +35,7 @@
|
|||
// HEADERS - No implementation in a header
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
CheckHeaders::CheckHeaders( const Tokenizer *tokenizer, ErrorLogger *errorLogger )
|
||||
CheckHeaders::CheckHeaders(const Tokenizer *tokenizer, ErrorLogger *errorLogger)
|
||||
{
|
||||
_tokenizer = tokenizer;
|
||||
_errorLogger = errorLogger;
|
||||
|
@ -48,7 +48,7 @@ CheckHeaders::~CheckHeaders()
|
|||
|
||||
void CheckHeaders::WarningHeaderWithImplementation()
|
||||
{
|
||||
for ( const Token *tok = _tokenizer->tokens(); tok; tok = tok->next())
|
||||
for (const Token *tok = _tokenizer->tokens(); tok; tok = tok->next())
|
||||
{
|
||||
// Only interested in included file
|
||||
if (tok->fileIndex() == 0)
|
||||
|
@ -62,7 +62,7 @@ void CheckHeaders::WarningHeaderWithImplementation()
|
|||
|
||||
// Goto next file..
|
||||
unsigned int fileindex = tok->fileIndex();
|
||||
while ( tok->next() && tok->fileIndex() == fileindex )
|
||||
while (tok->next() && tok->fileIndex() == fileindex)
|
||||
tok = tok->next();
|
||||
}
|
||||
}
|
||||
|
@ -83,7 +83,7 @@ void CheckHeaders::WarningHeaderWithImplementation()
|
|||
void CheckHeaders::WarningIncludeHeader()
|
||||
{
|
||||
// Including..
|
||||
for ( const Token *includetok = _tokenizer->tokens(); includetok; includetok = includetok->next())
|
||||
for (const Token *includetok = _tokenizer->tokens(); includetok; includetok = includetok->next())
|
||||
{
|
||||
if (includetok->str() != "#include")
|
||||
continue;
|
||||
|
@ -93,7 +93,7 @@ void CheckHeaders::WarningIncludeHeader()
|
|||
const char *includefile = includetok->next()->aaaa();
|
||||
while (hfile < _tokenizer->getFiles()->size())
|
||||
{
|
||||
if ( Tokenizer::SameFileName( _tokenizer->getFiles()->at(hfile).c_str(), includefile ) )
|
||||
if (Tokenizer::SameFileName(_tokenizer->getFiles()->at(hfile).c_str(), includefile))
|
||||
break;
|
||||
++hfile;
|
||||
}
|
||||
|
@ -112,9 +112,9 @@ void CheckHeaders::WarningIncludeHeader()
|
|||
|
||||
// Extract classes and names in the header..
|
||||
int indentlevel = 0;
|
||||
for ( const Token *tok1 = _tokenizer->tokens(); tok1; tok1 = tok1->next() )
|
||||
for (const Token *tok1 = _tokenizer->tokens(); tok1; tok1 = tok1->next())
|
||||
{
|
||||
if ( tok1->fileIndex() != hfile )
|
||||
if (tok1->fileIndex() != hfile)
|
||||
continue;
|
||||
|
||||
// I'm only interested in stuff that is declared at indentlevel 0
|
||||
|
@ -129,7 +129,7 @@ void CheckHeaders::WarningIncludeHeader()
|
|||
|
||||
// Class or namespace declaration..
|
||||
// --------------------------------------
|
||||
if (Token::Match(tok1,"class %var% {") || Token::Match(tok1,"class %var% :") || Token::Match(tok1,"namespace %var% {"))
|
||||
if (Token::Match(tok1, "class %var% {") || Token::Match(tok1, "class %var% :") || Token::Match(tok1, "namespace %var% {"))
|
||||
classlist.push_back(tok1->strAt(1));
|
||||
|
||||
// Variable declaration..
|
||||
|
@ -151,9 +151,9 @@ void CheckHeaders::WarningIncludeHeader()
|
|||
else if (tok1->str() == "enum")
|
||||
{
|
||||
tok1 = tok1->next();
|
||||
while ( ! Token::Match( tok1, "; %any%" ) )
|
||||
while (! Token::Match(tok1, "; %any%"))
|
||||
{
|
||||
if ( tok1->isName() )
|
||||
if (tok1->isName())
|
||||
namelist.push_back(tok1->str());
|
||||
tok1 = tok1->next();
|
||||
}
|
||||
|
@ -161,39 +161,39 @@ void CheckHeaders::WarningIncludeHeader()
|
|||
|
||||
// function..
|
||||
// --------------------------------------
|
||||
else if (Token::Match(tok1,"%type% %var% ("))
|
||||
else if (Token::Match(tok1, "%type% %var% ("))
|
||||
namelist.push_back(tok1->strAt(1));
|
||||
|
||||
else if (Token::Match(tok1,"%type% * %var% ("))
|
||||
else if (Token::Match(tok1, "%type% * %var% ("))
|
||||
namelist.push_back(tok1->strAt(2));
|
||||
|
||||
else if (Token::Match(tok1,"const %type% %var% ("))
|
||||
else if (Token::Match(tok1, "const %type% %var% ("))
|
||||
namelist.push_back(tok1->strAt(2));
|
||||
|
||||
else if (Token::Match(tok1,"const %type% * %var% ("))
|
||||
else if (Token::Match(tok1, "const %type% * %var% ("))
|
||||
namelist.push_back(tok1->strAt(3));
|
||||
|
||||
// typedef..
|
||||
// --------------------------------------
|
||||
else if (tok1->str() == "typedef")
|
||||
{
|
||||
if (strcmp(tok1->strAt(1),"enum")==0)
|
||||
if (strcmp(tok1->strAt(1), "enum") == 0)
|
||||
continue;
|
||||
int parlevel = 0;
|
||||
while (tok1->next())
|
||||
{
|
||||
if ( Token::Match(tok1, "[({]") )
|
||||
if (Token::Match(tok1, "[({]"))
|
||||
++parlevel;
|
||||
|
||||
else if ( Token::Match(tok1, "[)}]") )
|
||||
else if (Token::Match(tok1, "[)}]"))
|
||||
--parlevel;
|
||||
|
||||
else if (parlevel == 0)
|
||||
{
|
||||
if ( tok1->str() == ";" )
|
||||
if (tok1->str() == ";")
|
||||
break;
|
||||
|
||||
if ( Token::Match(tok1, "%var% ;") )
|
||||
if (Token::Match(tok1, "%var% ;"))
|
||||
namelist.push_back(tok1->str());
|
||||
}
|
||||
|
||||
|
@ -206,32 +206,32 @@ void CheckHeaders::WarningIncludeHeader()
|
|||
// Check if the extracted names are used...
|
||||
bool Needed = false;
|
||||
bool NeedDeclaration = false;
|
||||
for ( const Token *tok1 = _tokenizer->tokens(); tok1; tok1 = tok1->next())
|
||||
for (const Token *tok1 = _tokenizer->tokens(); tok1; tok1 = tok1->next())
|
||||
{
|
||||
if (tok1->fileIndex() != includetok->fileIndex())
|
||||
continue;
|
||||
|
||||
if ( Token::Match(tok1, ": %var% {") || Token::Match(tok1, ": %type% %var% {") )
|
||||
if (Token::Match(tok1, ": %var% {") || Token::Match(tok1, ": %type% %var% {"))
|
||||
{
|
||||
std::string classname = tok1->strAt((strcmp(tok1->strAt(2),"{")) ? 2 : 1);
|
||||
if (std::find(classlist.begin(),classlist.end(),classname)!=classlist.end())
|
||||
std::string classname = tok1->strAt((strcmp(tok1->strAt(2), "{")) ? 2 : 1);
|
||||
if (std::find(classlist.begin(), classlist.end(), classname) != classlist.end())
|
||||
{
|
||||
Needed = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ( ! tok1->isName() )
|
||||
if (! tok1->isName())
|
||||
continue;
|
||||
|
||||
if (std::find(namelist.begin(),namelist.end(),tok1->aaaa() ) != namelist.end())
|
||||
if (std::find(namelist.begin(), namelist.end(), tok1->aaaa()) != namelist.end())
|
||||
{
|
||||
Needed = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if ( ! NeedDeclaration )
|
||||
NeedDeclaration = (std::find(classlist.begin(),classlist.end(),tok1->aaaa() ) != classlist.end());
|
||||
if (! NeedDeclaration)
|
||||
NeedDeclaration = (std::find(classlist.begin(), classlist.end(), tok1->aaaa()) != classlist.end());
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -28,7 +28,7 @@
|
|||
class CheckHeaders
|
||||
{
|
||||
public:
|
||||
CheckHeaders( const Tokenizer *tokenizer, ErrorLogger *errorLogger );
|
||||
CheckHeaders(const Tokenizer *tokenizer, ErrorLogger *errorLogger);
|
||||
~CheckHeaders();
|
||||
void WarningHeaderWithImplementation();
|
||||
void WarningIncludeHeader();
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -34,7 +34,7 @@
|
|||
class CheckMemoryLeakClass
|
||||
{
|
||||
public:
|
||||
CheckMemoryLeakClass( const Tokenizer *tokenizer, const Settings &settings, ErrorLogger *errorLogger );
|
||||
CheckMemoryLeakClass(const Tokenizer *tokenizer, const Settings &settings, ErrorLogger *errorLogger);
|
||||
~CheckMemoryLeakClass();
|
||||
void CheckMemoryLeak();
|
||||
|
||||
|
@ -45,22 +45,22 @@ private:
|
|||
// Extra allocation..
|
||||
class AllocFunc
|
||||
{
|
||||
public:
|
||||
const char *funcname;
|
||||
AllocType alloctype;
|
||||
public:
|
||||
const char *funcname;
|
||||
AllocType alloctype;
|
||||
|
||||
AllocFunc(const char f[], AllocType a)
|
||||
{
|
||||
funcname = f;
|
||||
alloctype = a;
|
||||
}
|
||||
AllocFunc(const char f[], AllocType a)
|
||||
{
|
||||
funcname = f;
|
||||
alloctype = a;
|
||||
}
|
||||
};
|
||||
|
||||
void CheckMemoryLeak_ClassMembers_Variable( const std::vector<const char *> &classname, const char varname[] );
|
||||
void CheckMemoryLeak_ClassMembers_ParseClass( const Token *tok1, std::vector<const char *> &classname );
|
||||
void CheckMemoryLeak_ClassMembers_Variable(const std::vector<const char *> &classname, const char varname[]);
|
||||
void CheckMemoryLeak_ClassMembers_ParseClass(const Token *tok1, std::vector<const char *> &classname);
|
||||
void CheckMemoryLeak_ClassMembers();
|
||||
void CheckMemoryLeak_InFunction();
|
||||
void CheckMemoryLeak_CheckScope( const Token *Tok1, const char varname[] );
|
||||
void CheckMemoryLeak_CheckScope(const Token *Tok1, const char varname[]);
|
||||
|
||||
/**
|
||||
* Simplify code e.g. by replacing empty "{ }" with ";"
|
||||
|
@ -90,13 +90,13 @@ private:
|
|||
Token *getcode(const Token *tok, std::list<const Token *> callstack, const char varname[], AllocType &alloctype, AllocType &dealloctype);
|
||||
bool notvar(const Token *tok, const char *varnames[]);
|
||||
void instoken(Token *tok, const char str[]);
|
||||
void MemoryLeak( const Token *tok, const char varname[], AllocType alloctype );
|
||||
void MismatchError( const Token *Tok1, const std::list<const Token *> &callstack, const char varname[] );
|
||||
const char * call_func( const Token *tok, std::list<const Token *> callstack, const char *varnames[], AllocType &alloctype, AllocType &dealloctype );
|
||||
AllocType GetDeallocationType( const Token *tok, const char *varnames[]);
|
||||
AllocType GetAllocationType( const Token *tok2 );
|
||||
AllocType GetReallocationType( const Token *tok2 );
|
||||
bool isclass( const Token *typestr );
|
||||
void MemoryLeak(const Token *tok, const char varname[], AllocType alloctype);
|
||||
void MismatchError(const Token *Tok1, const std::list<const Token *> &callstack, const char varname[]);
|
||||
const char * call_func(const Token *tok, std::list<const Token *> callstack, const char *varnames[], AllocType &alloctype, AllocType &dealloctype);
|
||||
AllocType GetDeallocationType(const Token *tok, const char *varnames[]);
|
||||
AllocType GetAllocationType(const Token *tok2);
|
||||
AllocType GetReallocationType(const Token *tok2);
|
||||
bool isclass(const Token *typestr);
|
||||
|
||||
const Tokenizer *_tokenizer;
|
||||
ErrorLogger *_errorLogger;
|
||||
|
|
322
checkother.cpp
322
checkother.cpp
|
@ -35,7 +35,7 @@
|
|||
// Warning on C-Style casts.. p = (kalle *)foo;
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
CheckOther::CheckOther( const Tokenizer *tokenizer, ErrorLogger *errorLogger )
|
||||
CheckOther::CheckOther(const Tokenizer *tokenizer, ErrorLogger *errorLogger)
|
||||
{
|
||||
_tokenizer = tokenizer;
|
||||
_errorLogger = errorLogger;
|
||||
|
@ -78,65 +78,65 @@ void CheckOther::WarningRedundantCode()
|
|||
// if (p) delete p
|
||||
for (const Token *tok = _tokenizer->tokens(); tok; tok = tok->next())
|
||||
{
|
||||
if ( tok->str() != "if" )
|
||||
if (tok->str() != "if")
|
||||
continue;
|
||||
|
||||
const char *varname1 = NULL;
|
||||
const Token *tok2 = NULL;
|
||||
|
||||
if (Token::Match(tok,"if ( %var% )"))
|
||||
if (Token::Match(tok, "if ( %var% )"))
|
||||
{
|
||||
varname1 = tok->strAt( 2);
|
||||
varname1 = tok->strAt(2);
|
||||
tok2 = tok->tokAt(4);
|
||||
}
|
||||
else if (Token::Match(tok,"if ( %var% != NULL )"))
|
||||
else if (Token::Match(tok, "if ( %var% != NULL )"))
|
||||
{
|
||||
varname1 = tok->strAt( 2);
|
||||
varname1 = tok->strAt(2);
|
||||
tok2 = tok->tokAt(6);
|
||||
}
|
||||
|
||||
if (varname1==NULL || tok2==NULL)
|
||||
if (varname1 == NULL || tok2 == NULL)
|
||||
continue;
|
||||
|
||||
bool err = false;
|
||||
if ( tok2->str() == "{" )
|
||||
if (tok2->str() == "{")
|
||||
{
|
||||
tok2 = tok2->next();
|
||||
|
||||
if (Token::Match(tok2,"delete %var% ; }"))
|
||||
if (Token::Match(tok2, "delete %var% ; }"))
|
||||
{
|
||||
err = (strcmp(tok2->strAt(1),varname1)==0);
|
||||
err = (strcmp(tok2->strAt(1), varname1) == 0);
|
||||
}
|
||||
else if (Token::Match(tok2,"delete [ ] %var% ; }"))
|
||||
else if (Token::Match(tok2, "delete [ ] %var% ; }"))
|
||||
{
|
||||
err = (strcmp(tok2->strAt(1),varname1)==0);
|
||||
err = (strcmp(tok2->strAt(1), varname1) == 0);
|
||||
}
|
||||
else if (Token::Match(tok2,"free ( %var% ) ; }"))
|
||||
else if (Token::Match(tok2, "free ( %var% ) ; }"))
|
||||
{
|
||||
err = (strcmp(tok2->strAt(2),varname1)==0);
|
||||
err = (strcmp(tok2->strAt(2), varname1) == 0);
|
||||
}
|
||||
else if (Token::Match(tok2,"kfree ( %var% ) ; }"))
|
||||
else if (Token::Match(tok2, "kfree ( %var% ) ; }"))
|
||||
{
|
||||
err = (strcmp(tok2->strAt(2),varname1)==0);
|
||||
err = (strcmp(tok2->strAt(2), varname1) == 0);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (Token::Match(tok2,"delete %var% ;"))
|
||||
if (Token::Match(tok2, "delete %var% ;"))
|
||||
{
|
||||
err = (strcmp(tok2->strAt(1),varname1)==0);
|
||||
err = (strcmp(tok2->strAt(1), varname1) == 0);
|
||||
}
|
||||
else if (Token::Match(tok2,"delete [ ] %var% ;"))
|
||||
else if (Token::Match(tok2, "delete [ ] %var% ;"))
|
||||
{
|
||||
err = (strcmp(tok2->strAt(1),varname1)==0);
|
||||
err = (strcmp(tok2->strAt(1), varname1) == 0);
|
||||
}
|
||||
else if (Token::Match(tok2,"free ( %var% ) ;"))
|
||||
else if (Token::Match(tok2, "free ( %var% ) ;"))
|
||||
{
|
||||
err = (strcmp(tok2->strAt(2),varname1)==0);
|
||||
err = (strcmp(tok2->strAt(2), varname1) == 0);
|
||||
}
|
||||
else if (Token::Match(tok2,"kfree ( %var% ) ;"))
|
||||
else if (Token::Match(tok2, "kfree ( %var% ) ;"))
|
||||
{
|
||||
err = (strcmp(tok2->strAt(2),varname1)==0);
|
||||
err = (strcmp(tok2->strAt(2), varname1) == 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -163,10 +163,10 @@ void CheckOther::redundantCondition2()
|
|||
"{|{|"
|
||||
" %var% . remove ( %any% ) ; "
|
||||
"}|}|";
|
||||
const Token *tok = Token::findmatch( _tokenizer->tokens(), pattern );
|
||||
while ( tok )
|
||||
const Token *tok = Token::findmatch(_tokenizer->tokens(), pattern);
|
||||
while (tok)
|
||||
{
|
||||
bool b = Token::Match( tok->tokAt(15), "{" );
|
||||
bool b = Token::Match(tok->tokAt(15), "{");
|
||||
|
||||
// Get tokens for the fields %var% and %any%
|
||||
const Token *var1 = tok->tokAt(2);
|
||||
|
@ -178,15 +178,15 @@ void CheckOther::redundantCondition2()
|
|||
// Check if all the "%var%" fields are the same and if all the "%any%" are the same..
|
||||
if (var1->str() == var2->str() &&
|
||||
var2->str() == var3->str() &&
|
||||
any1->str() == any2->str() )
|
||||
any1->str() == any2->str())
|
||||
{
|
||||
std::ostringstream errmsg;
|
||||
errmsg << _tokenizer->fileLine(tok)
|
||||
<< ": Redundant condition found. The remove function in the STL will not do anything if element doesn't exist";
|
||||
<< ": Redundant condition found. The remove function in the STL will not do anything if element doesn't exist";
|
||||
_errorLogger->reportErr(errmsg.str());
|
||||
}
|
||||
|
||||
tok = Token::findmatch( tok->next(), pattern );
|
||||
tok = Token::findmatch(tok->next(), pattern);
|
||||
}
|
||||
}
|
||||
//---------------------------------------------------------------------------
|
||||
|
@ -215,9 +215,9 @@ void CheckOther::WarningIf()
|
|||
else if (tok2->str() == ")")
|
||||
{
|
||||
--parlevel;
|
||||
if ( parlevel <= 0 )
|
||||
if (parlevel <= 0)
|
||||
{
|
||||
if ( Token::Match(tok2, ") ; !!else") )
|
||||
if (Token::Match(tok2, ") ; !!else"))
|
||||
{
|
||||
std::ostringstream ostr;
|
||||
ostr << _tokenizer->fileLine(tok) << ": Found \"if (condition);\"";
|
||||
|
@ -233,35 +233,35 @@ void CheckOther::WarningIf()
|
|||
for (const Token *tok = _tokenizer->tokens(); tok; tok = tok->next())
|
||||
{
|
||||
// Begin statement?
|
||||
if ( ! Token::Match(tok, "[;{}]") )
|
||||
if (! Token::Match(tok, "[;{}]"))
|
||||
continue;
|
||||
tok = tok->next();
|
||||
if ( ! tok )
|
||||
if (! tok)
|
||||
break;
|
||||
|
||||
if (!Token::Match(tok,"%var% = %var% ; if ( %var%"))
|
||||
if (!Token::Match(tok, "%var% = %var% ; if ( %var%"))
|
||||
continue;
|
||||
|
||||
if ( strcmp(tok->strAt( 9), ")") != 0 )
|
||||
if (strcmp(tok->strAt(9), ")") != 0)
|
||||
continue;
|
||||
|
||||
// var1 = var2 ; if ( var3 cond var4 )
|
||||
const char *var1 = tok->strAt( 0);
|
||||
const char *var2 = tok->strAt( 2);
|
||||
const char *var3 = tok->strAt( 6);
|
||||
const char *cond = tok->strAt( 7);
|
||||
const char *var4 = tok->strAt( 8);
|
||||
const char *var1 = tok->strAt(0);
|
||||
const char *var2 = tok->strAt(2);
|
||||
const char *var3 = tok->strAt(6);
|
||||
const char *cond = tok->strAt(7);
|
||||
const char *var4 = tok->strAt(8);
|
||||
|
||||
// Check that var3 is equal with either var1 or var2
|
||||
if (strcmp(var1,var3) && strcmp(var2,var3))
|
||||
if (strcmp(var1, var3) && strcmp(var2, var3))
|
||||
continue;
|
||||
|
||||
// Check that var4 is equal with either var1 or var2
|
||||
if (strcmp(var1,var4) && strcmp(var2,var4))
|
||||
if (strcmp(var1, var4) && strcmp(var2, var4))
|
||||
continue;
|
||||
|
||||
// Check that there is a condition..
|
||||
const char *p[6] = {"==","<=",">=","!=","<",">"};
|
||||
const char *p[6] = {"==", "<=", ">=", "!=", "<", ">"};
|
||||
bool iscond = false;
|
||||
for (int i = 0; i < 6; i++)
|
||||
{
|
||||
|
@ -296,7 +296,7 @@ void CheckOther::WarningIf()
|
|||
|
||||
void CheckOther::InvalidFunctionUsage()
|
||||
{
|
||||
for ( const Token *tok = _tokenizer->tokens(); tok; tok = tok->next() )
|
||||
for (const Token *tok = _tokenizer->tokens(); tok; tok = tok->next())
|
||||
{
|
||||
if ((tok->str() != "strtol") && (tok->str() != "strtoul"))
|
||||
continue;
|
||||
|
@ -304,21 +304,21 @@ void CheckOther::InvalidFunctionUsage()
|
|||
// Locate the third parameter of the function call..
|
||||
int parlevel = 0;
|
||||
int param = 1;
|
||||
for ( const Token *tok2 = tok->next(); tok2; tok2 = tok2->next() )
|
||||
for (const Token *tok2 = tok->next(); tok2; tok2 = tok2->next())
|
||||
{
|
||||
if ( Token::Match(tok2, "(") )
|
||||
if (Token::Match(tok2, "("))
|
||||
++parlevel;
|
||||
else if (Token::Match(tok2, ")"))
|
||||
--parlevel;
|
||||
else if (parlevel == 1 && Token::Match(tok2, ","))
|
||||
{
|
||||
++param;
|
||||
if (param==3)
|
||||
if (param == 3)
|
||||
{
|
||||
if ( Token::Match(tok2, ", %num% )") )
|
||||
if (Token::Match(tok2, ", %num% )"))
|
||||
{
|
||||
int radix = atoi(tok2->strAt( 1));
|
||||
if (!(radix==0 || (radix>=2 && radix<=36)))
|
||||
int radix = atoi(tok2->strAt(1));
|
||||
if (!(radix == 0 || (radix >= 2 && radix <= 36)))
|
||||
{
|
||||
std::ostringstream ostr;
|
||||
ostr << _tokenizer->fileLine(tok2) << ": Invalid radix in call to strtol or strtoul. Must be 0 or 2-36";
|
||||
|
@ -344,7 +344,7 @@ void CheckOther::CheckIfAssignment()
|
|||
{
|
||||
if (Token::Match(tok, "if ( %var% = %num% )") ||
|
||||
Token::Match(tok, "if ( %var% = %str% )") ||
|
||||
Token::Match(tok, "if ( %var% = %var% )") )
|
||||
Token::Match(tok, "if ( %var% = %var% )"))
|
||||
{
|
||||
std::ostringstream ostr;
|
||||
ostr << _tokenizer->fileLine(tok) << ": Possible bug. Should it be '==' instead of '='?";
|
||||
|
@ -363,26 +363,26 @@ void CheckOther::CheckUnsignedDivision()
|
|||
{
|
||||
// Check for "ivar / uvar" and "uvar / ivar"
|
||||
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 ( Token::Match(tok, "[{};(,] %type% %var% [;=,)]") )
|
||||
if (Token::Match(tok, "[{};(,] %type% %var% [;=,)]"))
|
||||
{
|
||||
const char *type = tok->strAt( 1);
|
||||
if (strcmp(type,"char")==0 || strcmp(type,"short")==0 || strcmp(type,"int")==0)
|
||||
const char *type = tok->strAt(1);
|
||||
if (strcmp(type, "char") == 0 || strcmp(type, "short") == 0 || strcmp(type, "int") == 0)
|
||||
varsign[tok->strAt(2)] = 's';
|
||||
}
|
||||
|
||||
else if ( Token::Match(tok, "[{};(,] unsigned %type% %var% [;=,)]") )
|
||||
else if (Token::Match(tok, "[{};(,] unsigned %type% %var% [;=,)]"))
|
||||
varsign[tok->strAt(3)] = 'u';
|
||||
|
||||
else if (!Token::Match(tok,"[).]") && Token::Match(tok->next(), "%var% / %var%"))
|
||||
else if (!Token::Match(tok, "[).]") && Token::Match(tok->next(), "%var% / %var%"))
|
||||
{
|
||||
const char *varname1 = tok->strAt(1);
|
||||
const char *varname2 = tok->strAt(3);
|
||||
char sign1 = varsign[varname1];
|
||||
char sign2 = varsign[varname2];
|
||||
|
||||
if ( sign1 && sign2 && sign1 != sign2 )
|
||||
if (sign1 && sign2 && sign1 != sign2)
|
||||
{
|
||||
// One of the operands are signed, the other is unsigned..
|
||||
std::ostringstream ostr;
|
||||
|
@ -391,11 +391,11 @@ void CheckOther::CheckUnsignedDivision()
|
|||
}
|
||||
}
|
||||
|
||||
else if (!Token::Match(tok,"[).]") && Token::Match(tok->next(), "%var% / - %num%"))
|
||||
else if (!Token::Match(tok, "[).]") && Token::Match(tok->next(), "%var% / - %num%"))
|
||||
{
|
||||
const char *varname1 = tok->strAt(1);
|
||||
char sign1 = varsign[varname1];
|
||||
if ( sign1 == 'u' )
|
||||
if (sign1 == 'u')
|
||||
{
|
||||
std::ostringstream ostr;
|
||||
ostr << _tokenizer->fileLine(tok->next()) << ": Unsigned division. The result will be wrong.";
|
||||
|
@ -407,7 +407,7 @@ void CheckOther::CheckUnsignedDivision()
|
|||
{
|
||||
const char *varname2 = tok->strAt(4);
|
||||
char sign2 = varsign[varname2];
|
||||
if ( sign2 == 'u' )
|
||||
if (sign2 == 'u')
|
||||
{
|
||||
std::ostringstream ostr;
|
||||
ostr << _tokenizer->fileLine(tok->next()) << ": Unsigned division. The result will be wrong.";
|
||||
|
@ -430,26 +430,26 @@ void CheckOther::CheckVariableScope()
|
|||
// Walk through all tokens..
|
||||
bool func = false;
|
||||
int indentlevel = 0;
|
||||
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..
|
||||
if ( (tok->str() == "class") || (tok->str() == "struct") )
|
||||
if ((tok->str() == "class") || (tok->str() == "struct"))
|
||||
{
|
||||
for (const Token *tok2 = tok; tok2; tok2 = tok2->next())
|
||||
{
|
||||
if ( tok2->str() == "{" )
|
||||
if (tok2->str() == "{")
|
||||
{
|
||||
int indentlevel2 = 0;
|
||||
for (tok = tok2; tok; tok = tok->next())
|
||||
{
|
||||
if ( tok->str() == "{" )
|
||||
if (tok->str() == "{")
|
||||
{
|
||||
++indentlevel2;
|
||||
}
|
||||
if ( tok->str() == "}" )
|
||||
if (tok->str() == "}")
|
||||
{
|
||||
--indentlevel2;
|
||||
if ( indentlevel2 <= 0 )
|
||||
if (indentlevel2 <= 0)
|
||||
{
|
||||
tok = tok->next();
|
||||
break;
|
||||
|
@ -463,29 +463,29 @@ void CheckOther::CheckVariableScope()
|
|||
break;
|
||||
}
|
||||
}
|
||||
if ( ! tok )
|
||||
if (! tok)
|
||||
break;
|
||||
}
|
||||
|
||||
if ( tok->str() == "{" )
|
||||
if (tok->str() == "{")
|
||||
{
|
||||
++indentlevel;
|
||||
}
|
||||
if ( tok->str() == "}" )
|
||||
if (tok->str() == "}")
|
||||
{
|
||||
--indentlevel;
|
||||
if ( indentlevel == 0 )
|
||||
if (indentlevel == 0)
|
||||
func = false;
|
||||
}
|
||||
if ( indentlevel == 0 && Token::Match(tok, ") {") )
|
||||
if (indentlevel == 0 && Token::Match(tok, ") {"))
|
||||
{
|
||||
func = true;
|
||||
}
|
||||
if ( indentlevel > 0 && func && Token::Match(tok, "[{};]") )
|
||||
if (indentlevel > 0 && func && Token::Match(tok, "[{};]"))
|
||||
{
|
||||
// First token of statement..
|
||||
const Token *tok1 = tok->next();
|
||||
if ( ! tok1 )
|
||||
if (! tok1)
|
||||
continue;
|
||||
|
||||
if ((tok1->str() == "return") ||
|
||||
|
@ -496,9 +496,9 @@ void CheckOther::CheckVariableScope()
|
|||
|
||||
// Variable declaration?
|
||||
if (Token::Match(tok1, "%var% %var% ;") ||
|
||||
Token::Match(tok1, "%var% %var% =") )
|
||||
Token::Match(tok1, "%var% %var% ="))
|
||||
{
|
||||
CheckVariableScope_LookupVar( tok1, tok1->strAt( 1) );
|
||||
CheckVariableScope_LookupVar(tok1, tok1->strAt(1));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -506,12 +506,12 @@ void CheckOther::CheckVariableScope()
|
|||
}
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
void CheckOther::CheckVariableScope_LookupVar( const Token *tok1, const char varname[] )
|
||||
void CheckOther::CheckVariableScope_LookupVar(const Token *tok1, const char varname[])
|
||||
{
|
||||
const Token *tok = tok1;
|
||||
|
||||
// Skip the variable declaration..
|
||||
while (tok && !Token::Match(tok,";"))
|
||||
while (tok && !Token::Match(tok, ";"))
|
||||
tok = tok->next();
|
||||
|
||||
// Check if the variable is used in this indentlevel..
|
||||
|
@ -519,48 +519,48 @@ void CheckOther::CheckVariableScope_LookupVar( const Token *tok1, const char var
|
|||
int indentlevel = 0;
|
||||
int parlevel = 0;
|
||||
bool for_or_while = false;
|
||||
while ( indentlevel >= 0 && tok )
|
||||
while (indentlevel >= 0 && tok)
|
||||
{
|
||||
if ( tok->str() == "{" )
|
||||
if (tok->str() == "{")
|
||||
{
|
||||
++indentlevel;
|
||||
}
|
||||
|
||||
else if ( tok->str() == "}" )
|
||||
else if (tok->str() == "}")
|
||||
{
|
||||
--indentlevel;
|
||||
if ( indentlevel == 0 )
|
||||
if (indentlevel == 0)
|
||||
{
|
||||
if ( for_or_while && used )
|
||||
if (for_or_while && used)
|
||||
return;
|
||||
used1 = used;
|
||||
used = false;
|
||||
}
|
||||
}
|
||||
|
||||
else if ( tok->str() == "(" )
|
||||
else if (tok->str() == "(")
|
||||
{
|
||||
++parlevel;
|
||||
}
|
||||
|
||||
else if ( tok->str() == ")" )
|
||||
else if (tok->str() == ")")
|
||||
{
|
||||
--parlevel;
|
||||
}
|
||||
|
||||
|
||||
else if ( tok->str() == varname )
|
||||
else if (tok->str() == varname)
|
||||
{
|
||||
if ( indentlevel == 0 || used1 )
|
||||
if (indentlevel == 0 || used1)
|
||||
return;
|
||||
used = true;
|
||||
}
|
||||
|
||||
else if ( indentlevel==0 )
|
||||
else if (indentlevel == 0)
|
||||
{
|
||||
if ( (tok->str() == "for") || (tok->str() == "while") )
|
||||
if ((tok->str() == "for") || (tok->str() == "while"))
|
||||
for_or_while = true;
|
||||
if ( parlevel == 0 && (tok->str() == ";") )
|
||||
if (parlevel == 0 && (tok->str() == ";"))
|
||||
for_or_while = false;
|
||||
}
|
||||
|
||||
|
@ -570,7 +570,7 @@ void CheckOther::CheckVariableScope_LookupVar( const Token *tok1, const char var
|
|||
// Warning if "used" is true
|
||||
std::ostringstream errmsg;
|
||||
errmsg << _tokenizer->fileLine(tok1) << " The scope of the variable '" << varname << "' can be limited";
|
||||
_errorLogger->reportErr( errmsg.str() );
|
||||
_errorLogger->reportErr(errmsg.str());
|
||||
}
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
|
@ -583,22 +583,22 @@ void CheckOther::CheckConstantFunctionParameter()
|
|||
{
|
||||
for (const Token *tok = _tokenizer->tokens(); tok; tok = tok->next())
|
||||
{
|
||||
if ( Token::Match(tok,"[,(] const std :: %type% %var% [,)]") )
|
||||
if (Token::Match(tok, "[,(] const std :: %type% %var% [,)]"))
|
||||
{
|
||||
std::ostringstream errmsg;
|
||||
errmsg << _tokenizer->fileLine(tok) << " " << tok->strAt(5) << " is passed by value, it could be passed by reference/pointer instead";
|
||||
_errorLogger->reportErr( errmsg.str() );
|
||||
_errorLogger->reportErr(errmsg.str());
|
||||
}
|
||||
|
||||
else if ( Token::Match(tok,"[,(] const %type% %var% [,)]") )
|
||||
else if (Token::Match(tok, "[,(] const %type% %var% [,)]"))
|
||||
{
|
||||
// Check if type is a struct or class.
|
||||
const std::string pattern(std::string("class|struct ") + tok->strAt(2));
|
||||
if ( Token::findmatch(_tokenizer->tokens(), pattern.c_str()) )
|
||||
if (Token::findmatch(_tokenizer->tokens(), pattern.c_str()))
|
||||
{
|
||||
std::ostringstream errmsg;
|
||||
errmsg << _tokenizer->fileLine(tok) << " " << tok->strAt(3) << " is passed by value, it could be passed by reference/pointer instead";
|
||||
_errorLogger->reportErr( errmsg.str() );
|
||||
_errorLogger->reportErr(errmsg.str());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -614,41 +614,41 @@ void CheckOther::CheckStructMemberUsage()
|
|||
{
|
||||
const char *structname = 0;
|
||||
|
||||
for ( const Token *tok = _tokenizer->tokens(); tok; tok = tok->next() )
|
||||
for (const Token *tok = _tokenizer->tokens(); tok; tok = tok->next())
|
||||
{
|
||||
if ( tok->fileIndex() != 0 )
|
||||
if (tok->fileIndex() != 0)
|
||||
continue;
|
||||
if ( tok->str() == "}" )
|
||||
if (tok->str() == "}")
|
||||
structname = 0;
|
||||
if ( Token::Match(tok, "struct|union %type% {") )
|
||||
structname = tok->strAt( 1);
|
||||
if (Token::Match(tok, "struct|union %type% {"))
|
||||
structname = tok->strAt(1);
|
||||
|
||||
if (structname && Token::Match(tok, "[{;]"))
|
||||
{
|
||||
const char *varname = 0;
|
||||
if (Token::Match(tok->next(), "%type% %var% [;[]"))
|
||||
varname = tok->strAt( 2 );
|
||||
varname = tok->strAt(2);
|
||||
else if (Token::Match(tok->next(), "%type% %type% %var% [;[]"))
|
||||
varname = tok->strAt( 2 );
|
||||
varname = tok->strAt(2);
|
||||
else if (Token::Match(tok->next(), "%type% * %var% [;[]"))
|
||||
varname = tok->strAt( 3 );
|
||||
varname = tok->strAt(3);
|
||||
else if (Token::Match(tok->next(), "%type% %type% * %var% [;[]"))
|
||||
varname = tok->strAt( 4 );
|
||||
varname = tok->strAt(4);
|
||||
else
|
||||
continue;
|
||||
|
||||
const std::string usagePattern( ". " + std::string(varname) );
|
||||
const std::string usagePattern(". " + std::string(varname));
|
||||
bool used = false;
|
||||
for ( const Token *tok2 = _tokenizer->tokens(); tok2; tok2 = tok2->next() )
|
||||
for (const Token *tok2 = _tokenizer->tokens(); tok2; tok2 = tok2->next())
|
||||
{
|
||||
if (Token::simpleMatch(tok2, usagePattern.c_str() ))
|
||||
if (Token::simpleMatch(tok2, usagePattern.c_str()))
|
||||
{
|
||||
used = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ( ! used )
|
||||
if (! used)
|
||||
{
|
||||
std::ostringstream errmsg;
|
||||
errmsg << _tokenizer->fileLine(tok->next()) << ": struct or union member '" << structname << "::" << varname << "' is never used";
|
||||
|
@ -671,22 +671,22 @@ void CheckOther::CheckCharVariable()
|
|||
for (const Token *tok = _tokenizer->tokens(); tok; tok = tok->next())
|
||||
{
|
||||
// Declaring the variable..
|
||||
if ( Token::Match(tok, "[{};(,] char %var% [;=,)]") )
|
||||
if (Token::Match(tok, "[{};(,] char %var% [;=,)]"))
|
||||
{
|
||||
// Set tok to point to the variable name
|
||||
tok = tok->tokAt( 2 );
|
||||
tok = tok->tokAt(2);
|
||||
|
||||
// Check usage of char variable..
|
||||
int indentlevel = 0;
|
||||
for ( const Token *tok2 = tok->next(); tok2; tok2 = tok2->next() )
|
||||
for (const Token *tok2 = tok->next(); tok2; tok2 = tok2->next())
|
||||
{
|
||||
if ( tok2->str() == "{" )
|
||||
if (tok2->str() == "{")
|
||||
++indentlevel;
|
||||
|
||||
else if ( tok2->str() == "}" )
|
||||
else if (tok2->str() == "}")
|
||||
{
|
||||
--indentlevel;
|
||||
if ( indentlevel <= 0 )
|
||||
if (indentlevel <= 0)
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -701,7 +701,7 @@ void CheckOther::CheckCharVariable()
|
|||
|
||||
std::string tempFirst = "%var% [&|] " + tok->str();
|
||||
std::string tempSecond = tok->str() + " [&|]";
|
||||
if ( Token::Match(tok2, tempFirst.c_str()) || Token::Match(tok2, tempSecond.c_str()) )
|
||||
if (Token::Match(tok2, tempFirst.c_str()) || Token::Match(tok2, tempSecond.c_str()))
|
||||
{
|
||||
std::ostringstream errmsg;
|
||||
errmsg << _tokenizer->fileLine(tok2) << ": Warning - using char variable in bit operation";
|
||||
|
@ -727,24 +727,24 @@ void CheckOther::CheckIncompleteStatement()
|
|||
{
|
||||
int parlevel = 0;
|
||||
|
||||
for ( const Token *tok = _tokenizer->tokens(); tok; tok = tok->next() )
|
||||
for (const Token *tok = _tokenizer->tokens(); tok; tok = tok->next())
|
||||
{
|
||||
if ( tok->str() == "(" )
|
||||
if (tok->str() == "(")
|
||||
++parlevel;
|
||||
else if ( tok->str() == ")" )
|
||||
else if (tok->str() == ")")
|
||||
--parlevel;
|
||||
|
||||
if ( parlevel != 0 )
|
||||
if (parlevel != 0)
|
||||
continue;
|
||||
|
||||
if ( (tok->str() != "#") && Token::Match(tok->next(),"; %str%") && !Token::Match(tok->tokAt(3), ",") )
|
||||
if ((tok->str() != "#") && Token::Match(tok->next(), "; %str%") && !Token::Match(tok->tokAt(3), ","))
|
||||
{
|
||||
std::ostringstream errmsg;
|
||||
errmsg << _tokenizer->fileLine(tok->next()) << ": Redundant code: Found a statement that begins with string constant";
|
||||
_errorLogger->reportErr(errmsg.str());
|
||||
}
|
||||
|
||||
if ( !Token::Match(tok,"#") && Token::Match(tok->next(),"; %num%") && !Token::Match(tok->tokAt(3), ",") )
|
||||
if (!Token::Match(tok, "#") && Token::Match(tok->next(), "; %num%") && !Token::Match(tok->tokAt(3), ","))
|
||||
{
|
||||
std::ostringstream errmsg;
|
||||
errmsg << _tokenizer->fileLine(tok->next()) << ": Redundant code: Found a statement that begins with numeric constant";
|
||||
|
@ -765,16 +765,16 @@ void CheckOther::CheckIncompleteStatement()
|
|||
|
||||
void CheckOther::unreachableCode()
|
||||
{
|
||||
const Token *tok = Token::findmatch( _tokenizer->tokens(), "[;{}] return" );
|
||||
while ( tok )
|
||||
const Token *tok = Token::findmatch(_tokenizer->tokens(), "[;{}] return");
|
||||
while (tok)
|
||||
{
|
||||
// Goto the 'return' token
|
||||
tok = tok->next();
|
||||
|
||||
// Locate the end of the 'return' statement
|
||||
while ( tok && ! Token::Match(tok, ";") )
|
||||
while (tok && ! Token::Match(tok, ";"))
|
||||
tok = tok->next();
|
||||
while ( tok && Token::Match(tok->next(), ";") )
|
||||
while (tok && Token::Match(tok->next(), ";"))
|
||||
tok = tok->next();
|
||||
|
||||
// If there is a statement below the return it is unreachable
|
||||
|
@ -786,7 +786,7 @@ void CheckOther::unreachableCode()
|
|||
}
|
||||
|
||||
// Find the next 'return' statement
|
||||
tok = Token::findmatch( tok, "[;{}] return" );
|
||||
tok = Token::findmatch(tok, "[;{}] return");
|
||||
}
|
||||
}
|
||||
//---------------------------------------------------------------------------
|
||||
|
@ -822,7 +822,7 @@ void CheckOther::functionVariableUsage()
|
|||
if (!tok1)
|
||||
return;
|
||||
|
||||
while ((tok1 = Token::findmatch( tok1->next(), ") const| {" )) != NULL)
|
||||
while ((tok1 = Token::findmatch(tok1->next(), ") const| {")) != NULL)
|
||||
{
|
||||
// Varname, usage {1=declare, 2=read, 4=write}
|
||||
std::map<std::string, unsigned int> varUsage;
|
||||
|
@ -831,59 +831,59 @@ void CheckOther::functionVariableUsage()
|
|||
static const unsigned int USAGE_WRITE = 4;
|
||||
|
||||
int indentlevel = 0;
|
||||
for ( const Token *tok = tok1; tok; tok = tok->next() )
|
||||
for (const Token *tok = tok1; tok; tok = tok->next())
|
||||
{
|
||||
if ( tok->str() == "{" )
|
||||
if (tok->str() == "{")
|
||||
++indentlevel;
|
||||
else if ( tok->str() == "}" )
|
||||
else if (tok->str() == "}")
|
||||
{
|
||||
--indentlevel;
|
||||
if ( indentlevel <= 0 )
|
||||
if (indentlevel <= 0)
|
||||
break;
|
||||
}
|
||||
else if ( Token::Match(tok, "struct|union|class {") ||
|
||||
Token::Match(tok, "struct|union|class %type% {") )
|
||||
else if (Token::Match(tok, "struct|union|class {") ||
|
||||
Token::Match(tok, "struct|union|class %type% {"))
|
||||
{
|
||||
while ( tok && tok->str() != "}" )
|
||||
while (tok && tok->str() != "}")
|
||||
tok = tok->next();
|
||||
if ( tok )
|
||||
if (tok)
|
||||
continue;
|
||||
break;
|
||||
}
|
||||
|
||||
if ( Token::Match(tok, "[;{}] bool|char|short|int|long|float|double %var% ;|=") )
|
||||
varUsage[ tok->strAt(2) ] = USAGE_DECLARE;
|
||||
if (Token::Match(tok, "[;{}] bool|char|short|int|long|float|double %var% ;|="))
|
||||
varUsage[ tok->strAt(2)] = USAGE_DECLARE;
|
||||
|
||||
if ( Token::Match(tok, "[;{}] bool|char|short|int|long|float|double * %var% ;|=") )
|
||||
varUsage[ tok->strAt(3) ] = USAGE_DECLARE;
|
||||
if (Token::Match(tok, "[;{}] bool|char|short|int|long|float|double * %var% ;|="))
|
||||
varUsage[ tok->strAt(3)] = USAGE_DECLARE;
|
||||
|
||||
if ( Token::Match(tok, "delete|return %var%") )
|
||||
varUsage[ tok->strAt(1) ] |= USAGE_READ;
|
||||
if (Token::Match(tok, "delete|return %var%"))
|
||||
varUsage[ tok->strAt(1)] |= USAGE_READ;
|
||||
|
||||
if ( Token::Match(tok, "%var% =") )
|
||||
varUsage[ tok->str() ] |= USAGE_WRITE;
|
||||
if (Token::Match(tok, "%var% ="))
|
||||
varUsage[ tok->str()] |= USAGE_WRITE;
|
||||
|
||||
if ( Token::Match(tok, "else %var% =") )
|
||||
varUsage[ tok->strAt(1) ] |= USAGE_WRITE;
|
||||
if (Token::Match(tok, "else %var% ="))
|
||||
varUsage[ tok->strAt(1)] |= USAGE_WRITE;
|
||||
|
||||
if ( Token::Match(tok, ">>|& %var%") )
|
||||
varUsage[ tok->strAt(1) ] |= USAGE_WRITE;
|
||||
if (Token::Match(tok, ">>|& %var%"))
|
||||
varUsage[ tok->strAt(1)] |= USAGE_WRITE;
|
||||
|
||||
if ((Token::Match(tok,"[(=&!]") || isOp(tok)) && Token::Match(tok->next(), "%var%"))
|
||||
varUsage[ tok->strAt(1) ] |= USAGE_READ;
|
||||
if ((Token::Match(tok, "[(=&!]") || isOp(tok)) && Token::Match(tok->next(), "%var%"))
|
||||
varUsage[ tok->strAt(1)] |= USAGE_READ;
|
||||
|
||||
if (Token::Match(tok, "-=|+=|*=|/=|&=|^= %var%") || Token::Match(tok, "|= %var%"))
|
||||
varUsage[ tok->strAt(1) ] |= USAGE_READ;
|
||||
varUsage[ tok->strAt(1)] |= USAGE_READ;
|
||||
|
||||
if (Token::Match(tok, "%var%") && (tok->next()->str()==")" || isOp(tok->next())))
|
||||
varUsage[ tok->str() ] |= USAGE_READ;
|
||||
if (Token::Match(tok, "%var%") && (tok->next()->str() == ")" || isOp(tok->next())))
|
||||
varUsage[ tok->str()] |= USAGE_READ;
|
||||
|
||||
if ( Token::Match(tok, "[(,] %var% [,)]") )
|
||||
varUsage[ tok->strAt(1) ] |= USAGE_WRITE;
|
||||
if (Token::Match(tok, "[(,] %var% [,)]"))
|
||||
varUsage[ tok->strAt(1)] |= USAGE_WRITE;
|
||||
}
|
||||
|
||||
// Check usage of all variables in the current scope..
|
||||
for ( std::map<std::string, unsigned int>::const_iterator it = varUsage.begin(); it != varUsage.end(); ++it )
|
||||
for (std::map<std::string, unsigned int>::const_iterator it = varUsage.begin(); it != varUsage.end(); ++it)
|
||||
{
|
||||
std::string varname = it->first;
|
||||
unsigned int usage = it->second;
|
||||
|
@ -891,24 +891,24 @@ void CheckOther::functionVariableUsage()
|
|||
if (!std::isalpha(varname[0]))
|
||||
continue;
|
||||
|
||||
if ( ! ( usage & USAGE_DECLARE ) )
|
||||
if (!(usage & USAGE_DECLARE))
|
||||
continue;
|
||||
|
||||
if ( usage == USAGE_DECLARE )
|
||||
if (usage == USAGE_DECLARE)
|
||||
{
|
||||
std::ostringstream errmsg;
|
||||
errmsg << _tokenizer->fileLine(tok1->next()) << ": Unused variable '" << varname << "'";
|
||||
_errorLogger->reportErr(errmsg.str());
|
||||
}
|
||||
|
||||
else if ( ! (usage & USAGE_READ) )
|
||||
else if (!(usage & USAGE_READ))
|
||||
{
|
||||
std::ostringstream errmsg;
|
||||
errmsg << _tokenizer->fileLine(tok1->next()) << ": Variable '" << varname << "' is assigned a value that is never used";
|
||||
_errorLogger->reportErr(errmsg.str());
|
||||
}
|
||||
|
||||
else if ( ! (usage & USAGE_WRITE) )
|
||||
else if (!(usage & USAGE_WRITE))
|
||||
{
|
||||
std::ostringstream errmsg;
|
||||
errmsg << _tokenizer->fileLine(tok1->next()) << ": Variable '" << varname << "' is not assigned a value";
|
||||
|
|
|
@ -29,7 +29,7 @@
|
|||
class CheckOther
|
||||
{
|
||||
public:
|
||||
CheckOther( const Tokenizer *tokenizer, ErrorLogger *errorLogger );
|
||||
CheckOther(const Tokenizer *tokenizer, ErrorLogger *errorLogger);
|
||||
~CheckOther();
|
||||
|
||||
// Casting
|
||||
|
@ -74,7 +74,7 @@ public:
|
|||
#ifndef UNIT_TESTING
|
||||
private:
|
||||
#endif
|
||||
void CheckVariableScope_LookupVar( const Token *tok1, const char varname[] );
|
||||
void CheckVariableScope_LookupVar(const Token *tok1, const char varname[]);
|
||||
|
||||
// Redundant condition
|
||||
// if (haystack.find(needle) != haystack.end())
|
||||
|
|
156
cppcheck.cpp
156
cppcheck.cpp
|
@ -36,7 +36,7 @@
|
|||
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
CppCheck::CppCheck( ErrorLogger &errorLogger )
|
||||
CppCheck::CppCheck(ErrorLogger &errorLogger)
|
||||
{
|
||||
_errorLogger = &errorLogger;
|
||||
}
|
||||
|
@ -46,97 +46,97 @@ CppCheck::~CppCheck()
|
|||
|
||||
}
|
||||
|
||||
void CppCheck::settings( const Settings &settings )
|
||||
void CppCheck::settings(const Settings &settings)
|
||||
{
|
||||
_settings = settings;
|
||||
}
|
||||
|
||||
void CppCheck::addFile( const std::string &path )
|
||||
void CppCheck::addFile(const std::string &path)
|
||||
{
|
||||
_filenames.push_back( path );
|
||||
_filenames.push_back(path);
|
||||
}
|
||||
|
||||
void CppCheck::addFile( const std::string &path, const std::string &content )
|
||||
void CppCheck::addFile(const std::string &path, const std::string &content)
|
||||
{
|
||||
_filenames.push_back( path );
|
||||
_filenames.push_back(path);
|
||||
_fileContents[ path ] = content;
|
||||
}
|
||||
|
||||
std::string CppCheck::parseFromArgs( int argc, const char* const argv[] )
|
||||
std::string CppCheck::parseFromArgs(int argc, const char* const argv[])
|
||||
{
|
||||
std::vector<std::string> pathnames;
|
||||
|
||||
for (int i = 1; i < argc; i++)
|
||||
{
|
||||
// Flag used for various purposes during debugging
|
||||
if (strcmp(argv[i],"--debug") == 0)
|
||||
if (strcmp(argv[i], "--debug") == 0)
|
||||
_settings._debug = true;
|
||||
|
||||
// Show all messages
|
||||
else if (strcmp(argv[i],"-a") == 0 || strcmp(argv[i],"--all") == 0)
|
||||
else if (strcmp(argv[i], "-a") == 0 || strcmp(argv[i], "--all") == 0)
|
||||
_settings._showAll = true;
|
||||
|
||||
// Only print something when there are errors
|
||||
else if (strcmp(argv[i],"-q")==0 || strcmp(argv[i],"--quiet")==0)
|
||||
else if (strcmp(argv[i], "-q") == 0 || strcmp(argv[i], "--quiet") == 0)
|
||||
_settings._errorsOnly = true;
|
||||
|
||||
// Checking coding style
|
||||
else if (strcmp(argv[i],"-s")==0 || strcmp(argv[i],"--style")==0)
|
||||
else if (strcmp(argv[i], "-s") == 0 || strcmp(argv[i], "--style") == 0)
|
||||
_settings._checkCodingStyle = true;
|
||||
|
||||
// Verbose error messages (configuration info)
|
||||
else if (strcmp(argv[i],"-v")==0 || strcmp(argv[i],"--verbose")==0)
|
||||
else if (strcmp(argv[i], "-v") == 0 || strcmp(argv[i], "--verbose") == 0)
|
||||
_settings._verbose = true;
|
||||
|
||||
// Force checking of files that have "too many" configurations
|
||||
else if (strcmp(argv[i],"-f")==0 || strcmp(argv[i],"--force")==0)
|
||||
else if (strcmp(argv[i], "-f") == 0 || strcmp(argv[i], "--force") == 0)
|
||||
_settings._force = true;
|
||||
|
||||
else
|
||||
pathnames.push_back( argv[i] );
|
||||
pathnames.push_back(argv[i]);
|
||||
}
|
||||
|
||||
if( pathnames.size() > 0 )
|
||||
if (pathnames.size() > 0)
|
||||
{
|
||||
// Execute RecursiveAddFiles() to each given file parameter
|
||||
std::vector<std::string>::const_iterator iter;
|
||||
for(iter=pathnames.begin(); iter!=pathnames.end(); iter++)
|
||||
FileLister::RecursiveAddFiles( _filenames, iter->c_str(), true );
|
||||
for (iter = pathnames.begin(); iter != pathnames.end(); iter++)
|
||||
FileLister::RecursiveAddFiles(_filenames, iter->c_str(), true);
|
||||
}
|
||||
|
||||
if (_filenames.empty())
|
||||
{
|
||||
std::ostringstream oss;
|
||||
oss << "cppcheck 1.27\n"
|
||||
"\n"
|
||||
"C/C++ code checking\n"
|
||||
"\n"
|
||||
"Syntax:\n"
|
||||
" cppcheck [--all] [--force] [--quiet] [--style] [--verbose] [file or path1] [file or path]\n"
|
||||
"\n"
|
||||
"If path is given instead of filename, *.cpp, *.cxx, *.cc and *.c files are \n"
|
||||
"checked recursively from given directory.\n\n"
|
||||
"Options:\n"
|
||||
" -a, --all Make the checking more sensitive. More bugs are detected,\n"
|
||||
" but there are also more false positives\n"
|
||||
" -f, --force Force checking on files that have \"too many\" configurations\n"
|
||||
" -q, --quiet Only print error messages\n"
|
||||
" -s, --style Check coding style\n"
|
||||
" -v, --verbose More detailed error reports\n"
|
||||
"\n"
|
||||
"Example usage:\n"
|
||||
" # Recursively check the current folder. Print the progress on the screen and write errors in a file:\n"
|
||||
" cppcheck . 2> err.txt\n"
|
||||
" # Recursively check ../myproject/ and print only most fatal errors:\n"
|
||||
" cppcheck --quiet ../myproject/\n"
|
||||
" # Check only files one.cpp and two.cpp and give all information there is:\n"
|
||||
" cppcheck -v -a -s one.cpp two.cpp\n";
|
||||
"\n"
|
||||
"C/C++ code checking\n"
|
||||
"\n"
|
||||
"Syntax:\n"
|
||||
" cppcheck [--all] [--force] [--quiet] [--style] [--verbose] [file or path1] [file or path]\n"
|
||||
"\n"
|
||||
"If path is given instead of filename, *.cpp, *.cxx, *.cc and *.c files are \n"
|
||||
"checked recursively from given directory.\n\n"
|
||||
"Options:\n"
|
||||
" -a, --all Make the checking more sensitive. More bugs are detected,\n"
|
||||
" but there are also more false positives\n"
|
||||
" -f, --force Force checking on files that have \"too many\" configurations\n"
|
||||
" -q, --quiet Only print error messages\n"
|
||||
" -s, --style Check coding style\n"
|
||||
" -v, --verbose More detailed error reports\n"
|
||||
"\n"
|
||||
"Example usage:\n"
|
||||
" # Recursively check the current folder. Print the progress on the screen and write errors in a file:\n"
|
||||
" cppcheck . 2> err.txt\n"
|
||||
" # Recursively check ../myproject/ and print only most fatal errors:\n"
|
||||
" cppcheck --quiet ../myproject/\n"
|
||||
" # Check only files one.cpp and two.cpp and give all information there is:\n"
|
||||
" cppcheck -v -a -s one.cpp two.cpp\n";
|
||||
return oss.str();
|
||||
}
|
||||
|
||||
// Check function usage if "--style" and "--all" was given.
|
||||
// There will be false positives for exported library functions
|
||||
if ( _settings._showAll && _settings._checkCodingStyle )
|
||||
if (_settings._showAll && _settings._checkCodingStyle)
|
||||
_settings._checkFunctionUsage = true;
|
||||
|
||||
return "";
|
||||
|
@ -144,8 +144,8 @@ std::string CppCheck::parseFromArgs( int argc, const char* const argv[] )
|
|||
|
||||
void CppCheck::check()
|
||||
{
|
||||
_checkFunctionUsage.setErrorLogger( this );
|
||||
std::sort( _filenames.begin(), _filenames.end() );
|
||||
_checkFunctionUsage.setErrorLogger(this);
|
||||
std::sort(_filenames.begin(), _filenames.end());
|
||||
for (unsigned int c = 0; c < _filenames.size(); c++)
|
||||
{
|
||||
_errout.str("");
|
||||
|
@ -155,54 +155,54 @@ void CppCheck::check()
|
|||
Preprocessor preprocessor;
|
||||
std::list<std::string> configurations;
|
||||
std::string filedata = "";
|
||||
if( _fileContents.size() > 0 && _fileContents.find( _filenames[c] ) != _fileContents.end() )
|
||||
if (_fileContents.size() > 0 && _fileContents.find(_filenames[c]) != _fileContents.end())
|
||||
{
|
||||
// File content was given as a string
|
||||
std::istringstream iss( _fileContents[ _filenames[c] ] );
|
||||
preprocessor.preprocess(iss, filedata, configurations );
|
||||
std::istringstream iss(_fileContents[ _filenames[c] ]);
|
||||
preprocessor.preprocess(iss, filedata, configurations);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Only file name was given, read the content from file
|
||||
std::ifstream fin( fname.c_str() );
|
||||
preprocessor.preprocess(fin, filedata, configurations );
|
||||
std::ifstream fin(fname.c_str());
|
||||
preprocessor.preprocess(fin, filedata, configurations);
|
||||
}
|
||||
|
||||
int checkCount = 0;
|
||||
for ( std::list<std::string>::const_iterator it = configurations.begin(); it != configurations.end(); ++it )
|
||||
for (std::list<std::string>::const_iterator it = configurations.begin(); it != configurations.end(); ++it)
|
||||
{
|
||||
// Check only 12 first configurations, after that bail out, unless --force
|
||||
// was used.
|
||||
if( !_settings._force && checkCount > 11 )
|
||||
if (!_settings._force && checkCount > 11)
|
||||
{
|
||||
if( _settings._errorsOnly == false )
|
||||
_errorLogger->reportOut( std::string( "Bailing out from checking " ) + fname + ": Too many configurations. Recheck this file with --force if you want to check them all." );
|
||||
if (_settings._errorsOnly == false)
|
||||
_errorLogger->reportOut(std::string("Bailing out from checking ") + fname + ": Too many configurations. Recheck this file with --force if you want to check them all.");
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
cfg = *it;
|
||||
std::string codeWithoutCfg = Preprocessor::getcode( filedata, *it );
|
||||
std::string codeWithoutCfg = Preprocessor::getcode(filedata, *it);
|
||||
|
||||
// If only errors are printed, print filename after the check
|
||||
if ( _settings._errorsOnly == false )
|
||||
_errorLogger->reportOut( std::string( "Checking " ) + fname + ": "+cfg+std::string( "..." ) );
|
||||
if (_settings._errorsOnly == false)
|
||||
_errorLogger->reportOut(std::string("Checking ") + fname + ": " + cfg + std::string("..."));
|
||||
|
||||
checkFile( codeWithoutCfg, _filenames[c].c_str());
|
||||
checkFile(codeWithoutCfg, _filenames[c].c_str());
|
||||
++checkCount;
|
||||
}
|
||||
|
||||
if ( _settings._errorsOnly == false && _errout.str().empty() )
|
||||
_errorLogger->reportOut( "No errors found" );
|
||||
if (_settings._errorsOnly == false && _errout.str().empty())
|
||||
_errorLogger->reportOut("No errors found");
|
||||
}
|
||||
|
||||
// This generates false positives - especially for libraries
|
||||
_settings._verbose = false;
|
||||
if ( _settings._checkFunctionUsage )
|
||||
if (_settings._checkFunctionUsage)
|
||||
{
|
||||
_errout.str("");
|
||||
if( _settings._errorsOnly == false )
|
||||
_errorLogger->reportOut( "Checking usage of global functions (this may take several minutes).." );
|
||||
if (_settings._errorsOnly == false)
|
||||
_errorLogger->reportOut("Checking usage of global functions (this may take several minutes)..");
|
||||
|
||||
_checkFunctionUsage.check();
|
||||
}
|
||||
|
@ -221,8 +221,8 @@ void CppCheck::checkFile(const std::string &code, const char FileName[])
|
|||
|
||||
// Tokenize the file
|
||||
{
|
||||
std::istringstream istr(code);
|
||||
_tokenizer.tokenize(istr, FileName);
|
||||
std::istringstream istr(code);
|
||||
_tokenizer.tokenize(istr, FileName);
|
||||
}
|
||||
|
||||
// Set variable id
|
||||
|
@ -233,13 +233,13 @@ void CppCheck::checkFile(const std::string &code, const char FileName[])
|
|||
// Check that the memsets are valid.
|
||||
// The 'memset' function can do dangerous things if used wrong.
|
||||
// Important: The checking doesn't work on simplified tokens list.
|
||||
CheckClass checkClass( &_tokenizer, _settings, this );
|
||||
CheckClass checkClass(&_tokenizer, _settings, this);
|
||||
checkClass.noMemset();
|
||||
|
||||
|
||||
// Coding style checks that must be run before the simplifyTokenList
|
||||
CheckOther checkOther( &_tokenizer, this );
|
||||
if ( _settings._checkCodingStyle )
|
||||
CheckOther checkOther(&_tokenizer, this);
|
||||
if (_settings._checkCodingStyle)
|
||||
{
|
||||
// Check for unsigned divisions where one operand is signed
|
||||
checkOther.CheckUnsignedDivision();
|
||||
|
@ -263,14 +263,14 @@ void CppCheck::checkFile(const std::string &code, const char FileName[])
|
|||
_tokenizer.simplifyTokenList();
|
||||
|
||||
|
||||
if ( _settings._checkFunctionUsage )
|
||||
if (_settings._checkFunctionUsage)
|
||||
_checkFunctionUsage.parseTokens(_tokenizer);
|
||||
|
||||
// Class for detecting buffer overruns and related problems
|
||||
CheckBufferOverrunClass checkBufferOverrun( &_tokenizer, _settings, this );
|
||||
CheckBufferOverrunClass checkBufferOverrun(&_tokenizer, _settings, this);
|
||||
|
||||
// Memory leak
|
||||
CheckMemoryLeakClass checkMemoryLeak( &_tokenizer, _settings, this );
|
||||
CheckMemoryLeakClass checkMemoryLeak(&_tokenizer, _settings, this);
|
||||
checkMemoryLeak.CheckMemoryLeak();
|
||||
|
||||
// Check that all class constructors are ok.
|
||||
|
@ -313,7 +313,7 @@ void CppCheck::checkFile(const std::string &code, const char FileName[])
|
|||
|
||||
// Warning upon c-style pointer casts
|
||||
const char *ext = strrchr(FileName, '.');
|
||||
if (ext && strcmp(ext,".cpp")==0)
|
||||
if (ext && strcmp(ext, ".cpp") == 0)
|
||||
checkOther.WarningOldStylePointerCast();
|
||||
|
||||
checkClass.operatorEq();
|
||||
|
@ -343,28 +343,28 @@ void CppCheck::checkFile(const std::string &code, const char FileName[])
|
|||
}
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
void CppCheck::reportErr( const std::string &errmsg)
|
||||
void CppCheck::reportErr(const std::string &errmsg)
|
||||
{
|
||||
if ( /*OnlyReportUniqueErrors*/ true )
|
||||
if (/*OnlyReportUniqueErrors*/ true)
|
||||
{
|
||||
if ( std::find( _errorList.begin(), _errorList.end(), errmsg ) != _errorList.end() )
|
||||
if (std::find(_errorList.begin(), _errorList.end(), errmsg) != _errorList.end())
|
||||
return;
|
||||
_errorList.push_back( errmsg );
|
||||
_errorList.push_back(errmsg);
|
||||
}
|
||||
|
||||
std::string errmsg2( errmsg );
|
||||
if ( _settings._verbose )
|
||||
std::string errmsg2(errmsg);
|
||||
if (_settings._verbose)
|
||||
{
|
||||
errmsg2 += "\n Defines=\'" + cfg + "\'\n";
|
||||
}
|
||||
|
||||
|
||||
_errorLogger->reportErr( errmsg2 );
|
||||
_errorLogger->reportErr(errmsg2);
|
||||
|
||||
_errout << errmsg2 << std::endl;
|
||||
}
|
||||
|
||||
void CppCheck::reportOut( const std::string &outmsg)
|
||||
void CppCheck::reportOut(const std::string &outmsg)
|
||||
{
|
||||
// This is currently never called. It is here just to comply with
|
||||
// the interface.
|
||||
|
|
148
cppcheck.h
148
cppcheck.h
|
@ -36,91 +36,91 @@
|
|||
*/
|
||||
class CppCheck : public ErrorLogger
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
CppCheck( ErrorLogger &errorLogger );
|
||||
public:
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
CppCheck(ErrorLogger &errorLogger);
|
||||
|
||||
/**
|
||||
* Destructor.
|
||||
*/
|
||||
virtual ~CppCheck();
|
||||
/**
|
||||
* Destructor.
|
||||
*/
|
||||
virtual ~CppCheck();
|
||||
|
||||
/**
|
||||
* This starts the actual checking. Note that you must call
|
||||
* parseFromArgs() or settings() and addFile() before calling this.
|
||||
*/
|
||||
void check();
|
||||
/**
|
||||
* This starts the actual checking. Note that you must call
|
||||
* parseFromArgs() or settings() and addFile() before calling this.
|
||||
*/
|
||||
void check();
|
||||
|
||||
/**
|
||||
* Adjust the settings before doing the check. E.g. show only
|
||||
* actual bugs or also coding style issues.
|
||||
*
|
||||
* @param settings New settings which will overwrite the old.
|
||||
*/
|
||||
void settings( const Settings &settings );
|
||||
/**
|
||||
* Adjust the settings before doing the check. E.g. show only
|
||||
* actual bugs or also coding style issues.
|
||||
*
|
||||
* @param settings New settings which will overwrite the old.
|
||||
*/
|
||||
void settings(const Settings &settings);
|
||||
|
||||
/**
|
||||
* Add new file to be checked.
|
||||
*
|
||||
* @param path Relative or absolute path to the file to be checked,
|
||||
* e.g. "cppcheck.cpp". Note that only source files (.c, .cc or .cpp)
|
||||
* should be added to the list. Include filese are gathered automatically.
|
||||
*/
|
||||
void addFile( const std::string &path );
|
||||
/**
|
||||
* Add new file to be checked.
|
||||
*
|
||||
* @param path Relative or absolute path to the file to be checked,
|
||||
* e.g. "cppcheck.cpp". Note that only source files (.c, .cc or .cpp)
|
||||
* should be added to the list. Include filese are gathered automatically.
|
||||
*/
|
||||
void addFile(const std::string &path);
|
||||
|
||||
/**
|
||||
* Add new unreal file to be checked.
|
||||
*
|
||||
* @param path File name (used for error reporting).
|
||||
* @param content If the file would be a real file, this should be
|
||||
* the content of the file.
|
||||
*/
|
||||
void addFile( const std::string &path, const std::string &content );
|
||||
/**
|
||||
* Add new unreal file to be checked.
|
||||
*
|
||||
* @param path File name (used for error reporting).
|
||||
* @param content If the file would be a real file, this should be
|
||||
* the content of the file.
|
||||
*/
|
||||
void addFile(const std::string &path, const std::string &content);
|
||||
|
||||
/**
|
||||
* Parse command line args and get settings and file lists
|
||||
* from there.
|
||||
*
|
||||
* @param argc argc from main()
|
||||
* @param argv argv from main()
|
||||
* @return Empty string if parameters were accepted, or
|
||||
* string containing "help" text if no files were found to be
|
||||
* checked.
|
||||
*/
|
||||
std::string parseFromArgs( int argc, const char* const argv[] );
|
||||
/**
|
||||
* Parse command line args and get settings and file lists
|
||||
* from there.
|
||||
*
|
||||
* @param argc argc from main()
|
||||
* @param argv argv from main()
|
||||
* @return Empty string if parameters were accepted, or
|
||||
* string containing "help" text if no files were found to be
|
||||
* checked.
|
||||
*/
|
||||
std::string parseFromArgs(int argc, const char* const argv[]);
|
||||
|
||||
private:
|
||||
void checkFile(const std::string &code, const char FileName[]);
|
||||
private:
|
||||
void checkFile(const std::string &code, const char FileName[]);
|
||||
|
||||
/**
|
||||
* Errors and warnings are directed here.
|
||||
*
|
||||
* @param errmsg Errors messages are normally in format
|
||||
* "[filepath:line number] Message", e.g.
|
||||
* "[main.cpp:4] Uninitialized member variable"
|
||||
*/
|
||||
virtual void reportErr( const std::string &errmsg);
|
||||
/**
|
||||
* Errors and warnings are directed here.
|
||||
*
|
||||
* @param errmsg Errors messages are normally in format
|
||||
* "[filepath:line number] Message", e.g.
|
||||
* "[main.cpp:4] Uninitialized member variable"
|
||||
*/
|
||||
virtual void reportErr(const std::string &errmsg);
|
||||
|
||||
/**
|
||||
* Information about progress is directed here.
|
||||
*
|
||||
* @param outmsg, E.g. "Checking main.cpp..."
|
||||
*/
|
||||
virtual void reportOut( const std::string &outmsg);
|
||||
/**
|
||||
* Information about progress is directed here.
|
||||
*
|
||||
* @param outmsg, E.g. "Checking main.cpp..."
|
||||
*/
|
||||
virtual void reportOut(const std::string &outmsg);
|
||||
|
||||
std::list<std::string> _errorList;
|
||||
std::ostringstream _errout;
|
||||
Settings _settings;
|
||||
std::vector<std::string> _filenames;
|
||||
/** Key is file name, and value is the content of the file */
|
||||
std::map<std::string,std::string> _fileContents;
|
||||
CheckFunctionUsage _checkFunctionUsage;
|
||||
ErrorLogger *_errorLogger;
|
||||
std::list<std::string> _errorList;
|
||||
std::ostringstream _errout;
|
||||
Settings _settings;
|
||||
std::vector<std::string> _filenames;
|
||||
/** Key is file name, and value is the content of the file */
|
||||
std::map<std::string, std::string> _fileContents;
|
||||
CheckFunctionUsage _checkFunctionUsage;
|
||||
ErrorLogger *_errorLogger;
|
||||
|
||||
/** Current configuration */
|
||||
std::string cfg;
|
||||
/** Current configuration */
|
||||
std::string cfg;
|
||||
};
|
||||
|
||||
#endif // CPPCHECK_H
|
||||
|
|
|
@ -30,22 +30,22 @@ CppCheckExecutor::~CppCheckExecutor()
|
|||
//dtor
|
||||
}
|
||||
|
||||
void CppCheckExecutor::check( int argc, const char* const argv[] )
|
||||
void CppCheckExecutor::check(int argc, const char* const argv[])
|
||||
{
|
||||
CppCheck cppCheck( *this );
|
||||
std::string result = cppCheck.parseFromArgs( argc, argv );
|
||||
if( result.length() == 0 )
|
||||
CppCheck cppCheck(*this);
|
||||
std::string result = cppCheck.parseFromArgs(argc, argv);
|
||||
if (result.length() == 0)
|
||||
cppCheck.check();
|
||||
else
|
||||
std::cout << result;
|
||||
}
|
||||
|
||||
void CppCheckExecutor::reportErr( const std::string &errmsg)
|
||||
void CppCheckExecutor::reportErr(const std::string &errmsg)
|
||||
{
|
||||
std::cerr << errmsg << std::endl;
|
||||
}
|
||||
|
||||
void CppCheckExecutor::reportOut( const std::string &outmsg)
|
||||
void CppCheckExecutor::reportOut(const std::string &outmsg)
|
||||
{
|
||||
std::cout << outmsg << std::endl;
|
||||
}
|
||||
|
|
|
@ -47,7 +47,7 @@ public:
|
|||
* @param argc from main()
|
||||
* @param argv from main()
|
||||
*/
|
||||
void check( int argc, const char* const argv[] );
|
||||
void check(int argc, const char* const argv[]);
|
||||
|
||||
/**
|
||||
* Errors and warnings are directed here. This should be
|
||||
|
@ -57,7 +57,7 @@ public:
|
|||
* "[filepath:line number] Message", e.g.
|
||||
* "[main.cpp:4] Uninitialized member variable"
|
||||
*/
|
||||
virtual void reportErr( const std::string &errmsg);
|
||||
virtual void reportErr(const std::string &errmsg);
|
||||
|
||||
/**
|
||||
* Information about progress is directed here. This should be
|
||||
|
@ -65,7 +65,7 @@ public:
|
|||
*
|
||||
* @param outmsg, E.g. "Checking main.cpp..."
|
||||
*/
|
||||
virtual void reportOut( const std::string &outmsg);
|
||||
virtual void reportOut(const std::string &outmsg);
|
||||
};
|
||||
|
||||
#endif // CPPCHECKEXECUTOR_H
|
||||
|
|
|
@ -37,14 +37,14 @@ public:
|
|||
* "[filepath:line number] Message", e.g.
|
||||
* "[main.cpp:4] Uninitialized member variable"
|
||||
*/
|
||||
virtual void reportErr( const std::string &errmsg) = 0;
|
||||
virtual void reportErr(const std::string &errmsg) = 0;
|
||||
|
||||
/**
|
||||
* Information about progress is directed here.
|
||||
*
|
||||
* @param outmsg, E.g. "Checking main.cpp..."
|
||||
*/
|
||||
virtual void reportOut( const std::string &outmsg) = 0;
|
||||
virtual void reportOut(const std::string &outmsg) = 0;
|
||||
};
|
||||
|
||||
#endif // #ifndef ERRORLOGGER_H
|
||||
|
|
|
@ -9,11 +9,11 @@
|
|||
*/
|
||||
class ErrorMessage
|
||||
{
|
||||
public:
|
||||
ErrorMessage();
|
||||
virtual ~ErrorMessage();
|
||||
protected:
|
||||
private:
|
||||
public:
|
||||
ErrorMessage();
|
||||
virtual ~ErrorMessage();
|
||||
protected:
|
||||
private:
|
||||
};
|
||||
|
||||
#endif // ErrorMessageH
|
||||
|
|
|
@ -31,52 +31,52 @@
|
|||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
std::string FileLister::simplifyPath( const char *originalPath )
|
||||
std::string FileLister::simplifyPath(const char *originalPath)
|
||||
{
|
||||
std::string subPath = "";
|
||||
std::vector<std::string> pathParts;
|
||||
for( ; *originalPath; ++originalPath )
|
||||
for (; *originalPath; ++originalPath)
|
||||
{
|
||||
if( *originalPath == '/' )
|
||||
if (*originalPath == '/')
|
||||
{
|
||||
if( subPath.length() > 0 )
|
||||
if (subPath.length() > 0)
|
||||
{
|
||||
pathParts.push_back( subPath );
|
||||
pathParts.push_back(subPath);
|
||||
subPath = "";
|
||||
}
|
||||
|
||||
pathParts.push_back( "/" );
|
||||
pathParts.push_back("/");
|
||||
}
|
||||
else
|
||||
subPath.append( 1, *originalPath );
|
||||
subPath.append(1, *originalPath);
|
||||
}
|
||||
|
||||
if( subPath.length() > 0 )
|
||||
pathParts.push_back( subPath );
|
||||
if (subPath.length() > 0)
|
||||
pathParts.push_back(subPath);
|
||||
|
||||
for( std::vector<std::string>::size_type i = 0; i < pathParts.size(); ++i )
|
||||
for (std::vector<std::string>::size_type i = 0; i < pathParts.size(); ++i)
|
||||
{
|
||||
if( pathParts[i] == ".." && i > 1 )
|
||||
if (pathParts[i] == ".." && i > 1)
|
||||
{
|
||||
pathParts.erase( pathParts.begin() + i );
|
||||
pathParts.erase( pathParts.begin()+i-1 );
|
||||
pathParts.erase( pathParts.begin()+i-2 );
|
||||
pathParts.erase(pathParts.begin() + i);
|
||||
pathParts.erase(pathParts.begin() + i - 1);
|
||||
pathParts.erase(pathParts.begin() + i - 2);
|
||||
i = 0;
|
||||
}
|
||||
else if( i > 0 && pathParts[i] == "." )
|
||||
else if (i > 0 && pathParts[i] == ".")
|
||||
{
|
||||
pathParts.erase( pathParts.begin()+i );
|
||||
pathParts.erase(pathParts.begin() + i);
|
||||
i = 0;
|
||||
}
|
||||
else if( pathParts[i] == "/" && i > 0 && pathParts[i-1] == "/" )
|
||||
else if (pathParts[i] == "/" && i > 0 && pathParts[i-1] == "/")
|
||||
{
|
||||
pathParts.erase( pathParts.begin()+i-1 );
|
||||
pathParts.erase(pathParts.begin() + i - 1);
|
||||
i = 0;
|
||||
}
|
||||
}
|
||||
|
||||
std::ostringstream oss;
|
||||
for( std::vector<std::string>::size_type i = 0; i < pathParts.size(); ++i )
|
||||
for (std::vector<std::string>::size_type i = 0; i < pathParts.size(); ++i)
|
||||
{
|
||||
oss << pathParts[i];
|
||||
}
|
||||
|
@ -86,19 +86,19 @@ std::string FileLister::simplifyPath( const char *originalPath )
|
|||
|
||||
|
||||
|
||||
bool FileLister::AcceptFile( const std::string &filename )
|
||||
bool FileLister::AcceptFile(const std::string &filename)
|
||||
{
|
||||
std::string::size_type dotLocation = filename.find_last_of ( '.' );
|
||||
if ( dotLocation == std::string::npos )
|
||||
std::string::size_type dotLocation = filename.find_last_of('.');
|
||||
if (dotLocation == std::string::npos)
|
||||
return false;
|
||||
|
||||
std::string extension = filename.substr( dotLocation );
|
||||
std::transform( extension.begin(), extension.end(), extension.begin(), static_cast<int(*)(int)> (std::tolower) );
|
||||
std::string extension = filename.substr(dotLocation);
|
||||
std::transform(extension.begin(), extension.end(), extension.begin(), static_cast < int(*)(int) > (std::tolower));
|
||||
|
||||
if( extension == ".cpp" ||
|
||||
if (extension == ".cpp" ||
|
||||
extension == ".cxx" ||
|
||||
extension == ".cc" ||
|
||||
extension == ".c" )
|
||||
extension == ".c")
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
@ -112,33 +112,33 @@ bool FileLister::AcceptFile( const std::string &filename )
|
|||
|
||||
#if defined(__GNUC__) && !defined(__MINGW32__)
|
||||
// gcc / cygwin..
|
||||
void FileLister::RecursiveAddFiles( std::vector<std::string> &filenames, const std::string &path, bool recursive )
|
||||
void FileLister::RecursiveAddFiles(std::vector<std::string> &filenames, const std::string &path, bool recursive)
|
||||
{
|
||||
std::ostringstream oss;
|
||||
oss << path;
|
||||
if ( path.length() > 0 && path[path.length()-1] == '/' )
|
||||
if (path.length() > 0 && path[path.length()-1] == '/')
|
||||
oss << "*";
|
||||
|
||||
glob_t glob_results;
|
||||
glob( oss.str().c_str(), GLOB_MARK, 0, &glob_results);
|
||||
for ( unsigned int i = 0; i < glob_results.gl_pathc; i++ )
|
||||
glob(oss.str().c_str(), GLOB_MARK, 0, &glob_results);
|
||||
for (unsigned int i = 0; i < glob_results.gl_pathc; i++)
|
||||
{
|
||||
std::string filename = glob_results.gl_pathv[i];
|
||||
if ( filename == "." || filename == ".." || filename.length() == 0 )
|
||||
if (filename == "." || filename == ".." || filename.length() == 0)
|
||||
continue;
|
||||
|
||||
if ( filename[filename.length()-1] != '/' )
|
||||
if (filename[filename.length()-1] != '/')
|
||||
{
|
||||
// File
|
||||
|
||||
// If recursive is not used, accept all files given by user
|
||||
if( !recursive || FileLister::AcceptFile( filename ) )
|
||||
filenames.push_back( filename );
|
||||
if (!recursive || FileLister::AcceptFile(filename))
|
||||
filenames.push_back(filename);
|
||||
}
|
||||
else if( recursive )
|
||||
else if (recursive)
|
||||
{
|
||||
// Directory
|
||||
FileLister::RecursiveAddFiles( filenames, filename, recursive );
|
||||
FileLister::RecursiveAddFiles(filenames, filename, recursive);
|
||||
}
|
||||
}
|
||||
globfree(&glob_results);
|
||||
|
@ -152,11 +152,11 @@ void FileLister::RecursiveAddFiles( std::vector<std::string> &filenames, const s
|
|||
|
||||
#if defined(__BORLANDC__) || defined(_MSC_VER) || defined(__MINGW32__)
|
||||
|
||||
void FileLister::RecursiveAddFiles( std::vector<std::string> &filenames, const std::string &path, bool recursive )
|
||||
void FileLister::RecursiveAddFiles(std::vector<std::string> &filenames, const std::string &path, bool recursive)
|
||||
{
|
||||
std::ostringstream bdir, oss;
|
||||
oss << path;
|
||||
if ( path.length() > 0 && path[path.length()-1] == '/' )
|
||||
if (path.length() > 0 && path[path.length()-1] == '/')
|
||||
{
|
||||
bdir << path;
|
||||
oss << "*";
|
||||
|
@ -164,7 +164,7 @@ void FileLister::RecursiveAddFiles( std::vector<std::string> &filenames, const s
|
|||
|
||||
WIN32_FIND_DATA ffd;
|
||||
HANDLE hFind = FindFirstFile(oss.str().c_str(), &ffd);
|
||||
if ( INVALID_HANDLE_VALUE == hFind )
|
||||
if (INVALID_HANDLE_VALUE == hFind)
|
||||
return;
|
||||
|
||||
do
|
||||
|
@ -172,22 +172,22 @@ void FileLister::RecursiveAddFiles( std::vector<std::string> &filenames, const s
|
|||
std::ostringstream fname;
|
||||
fname << bdir.str().c_str() << ffd.cFileName;
|
||||
|
||||
if ( ffd.cFileName[0] == '.' || ffd.cFileName[0] == '\0' )
|
||||
if (ffd.cFileName[0] == '.' || ffd.cFileName[0] == '\0')
|
||||
continue;
|
||||
|
||||
if ( ( ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ) == 0 )
|
||||
if ((ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0)
|
||||
{
|
||||
// File
|
||||
|
||||
// If recursive is not used, accept all files given by user
|
||||
if ( !recursive || FileLister::AcceptFile( ffd.cFileName ) )
|
||||
filenames.push_back( fname.str() );
|
||||
if (!recursive || FileLister::AcceptFile(ffd.cFileName))
|
||||
filenames.push_back(fname.str());
|
||||
}
|
||||
else if ( recursive )
|
||||
else if (recursive)
|
||||
{
|
||||
// Directory
|
||||
fname << "/";
|
||||
FileLister::RecursiveAddFiles( filenames, fname.str().c_str(), recursive );
|
||||
FileLister::RecursiveAddFiles(filenames, fname.str().c_str(), recursive);
|
||||
}
|
||||
}
|
||||
while (FindNextFile(hFind, &ffd) != FALSE);
|
||||
|
|
|
@ -38,10 +38,10 @@
|
|||
class FileLister
|
||||
{
|
||||
public:
|
||||
static void RecursiveAddFiles( std::vector<std::string> &filenames, const std::string &path, bool recursive );
|
||||
static std::string simplifyPath( const char *originalPath );
|
||||
static void RecursiveAddFiles(std::vector<std::string> &filenames, const std::string &path, bool recursive);
|
||||
static std::string simplifyPath(const char *originalPath);
|
||||
private:
|
||||
static bool AcceptFile( const std::string &filename );
|
||||
static bool AcceptFile(const std::string &filename);
|
||||
};
|
||||
|
||||
#endif // #ifndef FILELISTER_H
|
||||
|
|
2
main.cpp
2
main.cpp
|
@ -28,6 +28,6 @@
|
|||
int main(int argc, char* argv[])
|
||||
{
|
||||
CppCheckExecutor exec;
|
||||
exec.check( argc, argv );
|
||||
exec.check(argc, argv);
|
||||
return 0;
|
||||
}
|
||||
|
|
199
preprocessor.cpp
199
preprocessor.cpp
|
@ -45,38 +45,38 @@ std::string Preprocessor::read(std::istream &istr)
|
|||
std::ostringstream code;
|
||||
for (char ch = (char)istr.get(); istr.good(); ch = (char)istr.get())
|
||||
{
|
||||
if ( ch < 0 )
|
||||
if (ch < 0)
|
||||
continue;
|
||||
|
||||
if ( ch == '\n' )
|
||||
if (ch == '\n')
|
||||
++lineno;
|
||||
|
||||
// Replace assorted special chars with spaces..
|
||||
if ( (ch != '\n') && (isspace(ch) || iscntrl(ch)) )
|
||||
if ((ch != '\n') && (isspace(ch) || iscntrl(ch)))
|
||||
ch = ' ';
|
||||
|
||||
// Skip spaces after ' ' and after '#'
|
||||
if ( ch == ' ' && ignoreSpace )
|
||||
if (ch == ' ' && ignoreSpace)
|
||||
continue;
|
||||
ignoreSpace = bool(ch == ' ' || ch == '#' || ch == '/');
|
||||
|
||||
// Remove comments..
|
||||
if ( ch == '/' )
|
||||
if (ch == '/')
|
||||
{
|
||||
char chNext = (char)istr.get();
|
||||
|
||||
if ( chNext == '/' )
|
||||
if (chNext == '/')
|
||||
{
|
||||
while (istr.good() && ch!='\n')
|
||||
while (istr.good() && ch != '\n')
|
||||
ch = (char)istr.get();
|
||||
code << "\n";
|
||||
++lineno;
|
||||
}
|
||||
|
||||
else if ( chNext == '*' )
|
||||
else if (chNext == '*')
|
||||
{
|
||||
char chPrev = 0;
|
||||
while (istr.good() && (chPrev!='*' || ch!='/'))
|
||||
while (istr.good() && (chPrev != '*' || ch != '/'))
|
||||
{
|
||||
chPrev = ch;
|
||||
ch = (char)istr.get();
|
||||
|
@ -90,41 +90,42 @@ std::string Preprocessor::read(std::istream &istr)
|
|||
|
||||
else
|
||||
{
|
||||
if ( chNext == '\n' )
|
||||
if (chNext == '\n')
|
||||
++lineno;
|
||||
code << std::string(1,ch) << std::string(1,chNext);
|
||||
code << std::string(1, ch) << std::string(1, chNext);
|
||||
}
|
||||
}
|
||||
|
||||
// String constants..
|
||||
else if ( ch == '\"' )
|
||||
else if (ch == '\"')
|
||||
{
|
||||
code << "\"";
|
||||
do
|
||||
{
|
||||
ch = (char)istr.get();
|
||||
code << std::string(1,ch);
|
||||
if ( ch == '\\' )
|
||||
code << std::string(1, ch);
|
||||
if (ch == '\\')
|
||||
{
|
||||
ch = (char)istr.get();
|
||||
code << std::string(1,ch);
|
||||
code << std::string(1, ch);
|
||||
|
||||
// Avoid exiting loop if string contains "-characters
|
||||
ch = 0;
|
||||
}
|
||||
} while ( istr.good() && ch != '\"' );
|
||||
}
|
||||
while (istr.good() && ch != '\"');
|
||||
}
|
||||
|
||||
// char constants..
|
||||
else if ( ch == '\'' )
|
||||
else if (ch == '\'')
|
||||
{
|
||||
code << "\'";
|
||||
ch = (char)istr.get();
|
||||
code << std::string(1,ch);
|
||||
if ( ch == '\\' )
|
||||
code << std::string(1, ch);
|
||||
if (ch == '\\')
|
||||
{
|
||||
ch = (char)istr.get();
|
||||
code << std::string(1,ch);
|
||||
code << std::string(1, ch);
|
||||
}
|
||||
ch = (char)istr.get();
|
||||
code << "\'";
|
||||
|
@ -142,30 +143,30 @@ std::string Preprocessor::read(std::istream &istr)
|
|||
|
||||
void Preprocessor::preprocess(std::istream &istr, std::map<std::string, std::string> &result)
|
||||
{
|
||||
std::list<std::string> configs;
|
||||
std::string data;
|
||||
preprocess( istr, data, configs );
|
||||
for ( std::list<std::string>::const_iterator it = configs.begin(); it != configs.end(); ++it )
|
||||
result[ *it ] = Preprocessor::getcode( data, *it );
|
||||
std::list<std::string> configs;
|
||||
std::string data;
|
||||
preprocess(istr, data, configs);
|
||||
for (std::list<std::string>::const_iterator it = configs.begin(); it != configs.end(); ++it)
|
||||
result[ *it ] = Preprocessor::getcode(data, *it);
|
||||
}
|
||||
|
||||
std::string Preprocessor::removeSpaceNearNL( const std::string &str )
|
||||
std::string Preprocessor::removeSpaceNearNL(const std::string &str)
|
||||
{
|
||||
std::string tmp;
|
||||
int prev = -1;
|
||||
for( unsigned int i = 0; i < str.size(); i++ )
|
||||
for (unsigned int i = 0; i < str.size(); i++)
|
||||
{
|
||||
if( str[i] == ' ' &&
|
||||
( ( i > 0 && tmp[prev] == '\n' ) ||
|
||||
( i+1 < str.size() && str[i+1] == '\n' )
|
||||
if (str[i] == ' ' &&
|
||||
((i > 0 && tmp[prev] == '\n') ||
|
||||
(i + 1 < str.size() && str[i+1] == '\n')
|
||||
)
|
||||
)
|
||||
)
|
||||
{
|
||||
// Ignore space that has new line in either side of it
|
||||
}
|
||||
else
|
||||
{
|
||||
tmp.append( 1,str[i] );
|
||||
tmp.append(1, str[i]);
|
||||
++prev;
|
||||
}
|
||||
}
|
||||
|
@ -173,20 +174,20 @@ std::string Preprocessor::removeSpaceNearNL( const std::string &str )
|
|||
return tmp;
|
||||
}
|
||||
|
||||
std::string Preprocessor::replaceIfDefined( const std::string &str )
|
||||
std::string Preprocessor::replaceIfDefined(const std::string &str)
|
||||
{
|
||||
std::string ret(str);
|
||||
std::string::size_type pos = 0;
|
||||
while ((pos = ret.find("#if defined(", pos)) != std::string::npos)
|
||||
{
|
||||
std::string::size_type pos2 = ret.find(")", pos+9);
|
||||
std::string::size_type pos2 = ret.find(")", pos + 9);
|
||||
if (pos2 > ret.length() - 1)
|
||||
break;
|
||||
if (ret[pos2+1] == '\n')
|
||||
{
|
||||
ret.erase( pos2, 1 );
|
||||
ret.erase( pos + 3, 9 );
|
||||
ret.insert( pos + 3, "def " );
|
||||
ret.erase(pos2, 1);
|
||||
ret.erase(pos + 3, 9);
|
||||
ret.insert(pos + 3, "def ");
|
||||
}
|
||||
++pos;
|
||||
}
|
||||
|
@ -199,30 +200,30 @@ void Preprocessor::preprocess(std::istream &istr, std::string &processedFile, st
|
|||
processedFile = read(istr);
|
||||
|
||||
// Replace all tabs with spaces..
|
||||
std::replace( processedFile.begin(), processedFile.end(), '\t', ' ' );
|
||||
std::replace(processedFile.begin(), processedFile.end(), '\t', ' ');
|
||||
|
||||
// Remove all indentation..
|
||||
if ( !processedFile.empty() && processedFile[0] == ' ' )
|
||||
processedFile.erase( 0, processedFile.find_first_not_of(" ") );
|
||||
if (!processedFile.empty() && processedFile[0] == ' ')
|
||||
processedFile.erase(0, processedFile.find_first_not_of(" "));
|
||||
|
||||
// Remove space characters that are after or before new line character
|
||||
processedFile = removeSpaceNearNL( processedFile );
|
||||
processedFile = removeSpaceNearNL(processedFile);
|
||||
|
||||
// Using the backslash at the end of a line..
|
||||
std::string::size_type loc = 0;
|
||||
while ( (loc = processedFile.rfind("\\\n")) != std::string::npos )
|
||||
while ((loc = processedFile.rfind("\\\n")) != std::string::npos)
|
||||
{
|
||||
processedFile.erase(loc, 2);
|
||||
if (loc > 0 && processedFile[loc-1] != ' ')
|
||||
processedFile.insert(loc, " ");
|
||||
if ( (loc = processedFile.find("\n", loc)) != std::string::npos)
|
||||
processedFile.insert( loc, "\n" );
|
||||
if ((loc = processedFile.find("\n", loc)) != std::string::npos)
|
||||
processedFile.insert(loc, "\n");
|
||||
}
|
||||
|
||||
processedFile = replaceIfDefined(processedFile);
|
||||
|
||||
// Get all possible configurations..
|
||||
resultConfigurations = getcfgs( processedFile );
|
||||
resultConfigurations = getcfgs(processedFile);
|
||||
}
|
||||
|
||||
|
||||
|
@ -231,23 +232,23 @@ void Preprocessor::preprocess(std::istream &istr, std::string &processedFile, st
|
|||
std::string Preprocessor::getdef(std::string line, bool def)
|
||||
{
|
||||
// If def is true, the line must start with "#ifdef"
|
||||
if ( def && line.find("#ifdef ") != 0 && line.find("#if ") != 0 && line.find("#elif ") != 0 )
|
||||
if (def && line.find("#ifdef ") != 0 && line.find("#if ") != 0 && line.find("#elif ") != 0)
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
// If def is false, the line must start with "#ifndef"
|
||||
if ( !def && line.find("#ifndef ") != 0 )
|
||||
if (!def && line.find("#ifndef ") != 0)
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
// Remove the "#ifdef" or "#ifndef"
|
||||
line.erase( 0, line.find(" ") );
|
||||
line.erase(0, line.find(" "));
|
||||
|
||||
// Remove all spaces.
|
||||
while ( line.find(" ") != std::string::npos )
|
||||
line.erase( line.find(" "), 1 );
|
||||
while (line.find(" ") != std::string::npos)
|
||||
line.erase(line.find(" "), 1);
|
||||
|
||||
// The remaining string is our result.
|
||||
return line;
|
||||
|
@ -255,7 +256,7 @@ std::string Preprocessor::getdef(std::string line, bool def)
|
|||
|
||||
|
||||
|
||||
std::list<std::string> Preprocessor::getcfgs( const std::string &filedata )
|
||||
std::list<std::string> Preprocessor::getcfgs(const std::string &filedata)
|
||||
{
|
||||
std::list<std::string> ret;
|
||||
ret.push_back("");
|
||||
|
@ -264,38 +265,38 @@ std::list<std::string> Preprocessor::getcfgs( const std::string &filedata )
|
|||
|
||||
std::istringstream istr(filedata);
|
||||
std::string line;
|
||||
while ( getline(istr, line) )
|
||||
while (getline(istr, line))
|
||||
{
|
||||
std::string def = getdef(line, true) + getdef(line, false);
|
||||
if (!def.empty())
|
||||
{
|
||||
if ( ! deflist.empty() && line.find("#elif ") == 0 )
|
||||
if (! deflist.empty() && line.find("#elif ") == 0)
|
||||
deflist.pop_back();
|
||||
deflist.push_back(def);
|
||||
def = "";
|
||||
for ( std::list<std::string>::const_iterator it = deflist.begin(); it != deflist.end(); ++it)
|
||||
for (std::list<std::string>::const_iterator it = deflist.begin(); it != deflist.end(); ++it)
|
||||
{
|
||||
if ( *it == "0" )
|
||||
if (*it == "0")
|
||||
break;
|
||||
if ( *it == "1" )
|
||||
if (*it == "1")
|
||||
continue;
|
||||
if ( ! def.empty() )
|
||||
if (! def.empty())
|
||||
def += ";";
|
||||
def += *it;
|
||||
}
|
||||
|
||||
if (std::find(ret.begin(), ret.end(), def) == ret.end())
|
||||
ret.push_back( def );
|
||||
ret.push_back(def);
|
||||
}
|
||||
|
||||
if ( line.find("#else") == 0 && ! deflist.empty() )
|
||||
if (line.find("#else") == 0 && ! deflist.empty())
|
||||
{
|
||||
std::string def( ( deflist.back() == "1" ) ? "0" : "1" );
|
||||
std::string def((deflist.back() == "1") ? "0" : "1");
|
||||
deflist.pop_back();
|
||||
deflist.push_back( def );
|
||||
deflist.push_back(def);
|
||||
}
|
||||
|
||||
if ( line.find("#endif") == 0 && ! deflist.empty() )
|
||||
if (line.find("#endif") == 0 && ! deflist.empty())
|
||||
deflist.pop_back();
|
||||
}
|
||||
|
||||
|
@ -304,25 +305,25 @@ std::list<std::string> Preprocessor::getcfgs( const std::string &filedata )
|
|||
|
||||
|
||||
|
||||
bool Preprocessor::match_cfg_def( std::string cfg, const std::string &def )
|
||||
bool Preprocessor::match_cfg_def(std::string cfg, const std::string &def)
|
||||
{
|
||||
if ( def == "0" )
|
||||
if (def == "0")
|
||||
return false;
|
||||
|
||||
if ( def == "1" )
|
||||
if (def == "1")
|
||||
return true;
|
||||
|
||||
if ( cfg.empty() )
|
||||
if (cfg.empty())
|
||||
return false;
|
||||
|
||||
while ( ! cfg.empty() )
|
||||
while (! cfg.empty())
|
||||
{
|
||||
if ( cfg.find(";") == std::string::npos )
|
||||
if (cfg.find(";") == std::string::npos)
|
||||
return bool(cfg == def);
|
||||
std::string _cfg = cfg.substr( 0, cfg.find(";") );
|
||||
if ( _cfg == def )
|
||||
std::string _cfg = cfg.substr(0, cfg.find(";"));
|
||||
if (_cfg == def)
|
||||
return true;
|
||||
cfg.erase( 0, cfg.find(";") + 1 );
|
||||
cfg.erase(0, cfg.find(";") + 1);
|
||||
}
|
||||
|
||||
return false;
|
||||
|
@ -339,20 +340,20 @@ std::string Preprocessor::getcode(const std::string &filedata, std::string cfg)
|
|||
|
||||
std::istringstream istr(filedata);
|
||||
std::string line;
|
||||
while ( getline(istr, line) )
|
||||
while (getline(istr, line))
|
||||
{
|
||||
std::string def = getdef( line, true );
|
||||
std::string ndef = getdef( line, false );
|
||||
std::string def = getdef(line, true);
|
||||
std::string ndef = getdef(line, false);
|
||||
|
||||
if ( line.find("#elif ") == 0 )
|
||||
if (line.find("#elif ") == 0)
|
||||
{
|
||||
if ( matched_ifdef.back() )
|
||||
if (matched_ifdef.back())
|
||||
{
|
||||
matching_ifdef.back() = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( match_cfg_def(cfg, def) )
|
||||
if (match_cfg_def(cfg, def))
|
||||
{
|
||||
matching_ifdef.back() = true;
|
||||
matched_ifdef.back() = true;
|
||||
|
@ -360,45 +361,45 @@ std::string Preprocessor::getcode(const std::string &filedata, std::string cfg)
|
|||
}
|
||||
}
|
||||
|
||||
else if ( ! def.empty() )
|
||||
else if (! def.empty())
|
||||
{
|
||||
matching_ifdef.push_back( match_cfg_def(cfg, def) );
|
||||
matched_ifdef.push_back( matching_ifdef.back() );
|
||||
matching_ifdef.push_back(match_cfg_def(cfg, def));
|
||||
matched_ifdef.push_back(matching_ifdef.back());
|
||||
}
|
||||
|
||||
else if ( ! ndef.empty() )
|
||||
else if (! ndef.empty())
|
||||
{
|
||||
matching_ifdef.push_back( ! match_cfg_def(cfg, ndef) );
|
||||
matched_ifdef.push_back( matching_ifdef.back() );
|
||||
matching_ifdef.push_back(! match_cfg_def(cfg, ndef));
|
||||
matched_ifdef.push_back(matching_ifdef.back());
|
||||
}
|
||||
|
||||
else if ( line == "#else" )
|
||||
else if (line == "#else")
|
||||
{
|
||||
if ( ! matched_ifdef.empty() )
|
||||
if (! matched_ifdef.empty())
|
||||
matching_ifdef.back() = ! matched_ifdef.back();
|
||||
}
|
||||
|
||||
else if ( line == "#endif" )
|
||||
else if (line == "#endif")
|
||||
{
|
||||
if ( ! matched_ifdef.empty() )
|
||||
if (! matched_ifdef.empty())
|
||||
matched_ifdef.pop_back();
|
||||
if ( ! matching_ifdef.empty() )
|
||||
if (! matching_ifdef.empty())
|
||||
matching_ifdef.pop_back();
|
||||
}
|
||||
|
||||
if ( !line.empty() && line[0] == '#' )
|
||||
if (!line.empty() && line[0] == '#')
|
||||
{
|
||||
match = true;
|
||||
for ( std::list<bool>::const_iterator it = matching_ifdef.begin(); it != matching_ifdef.end(); ++it )
|
||||
for (std::list<bool>::const_iterator it = matching_ifdef.begin(); it != matching_ifdef.end(); ++it)
|
||||
match &= bool(*it);
|
||||
}
|
||||
if ( ! match )
|
||||
if (! match)
|
||||
line = "";
|
||||
|
||||
if ( line.find("#if") == 0 ||
|
||||
line.find("#else") == 0 ||
|
||||
line.find("#elif") == 0 ||
|
||||
line.find("#endif") == 0 )
|
||||
if (line.find("#if") == 0 ||
|
||||
line.find("#else") == 0 ||
|
||||
line.find("#elif") == 0 ||
|
||||
line.find("#endif") == 0)
|
||||
line = "";
|
||||
|
||||
ret << line << "\n";
|
||||
|
@ -409,7 +410,7 @@ std::string Preprocessor::getcode(const std::string &filedata, std::string cfg)
|
|||
|
||||
|
||||
|
||||
static std::string Preprocessor::expandMacros( std::string code )
|
||||
std::string Preprocessor::expandMacros(std::string code)
|
||||
{
|
||||
std::list<std::string> macros;
|
||||
|
||||
|
@ -423,12 +424,12 @@ static std::string Preprocessor::expandMacros( std::string code )
|
|||
endpos = code.find("\n", endpos + 1);
|
||||
if (endpos == std::string::npos)
|
||||
{
|
||||
code.erase( defpos );
|
||||
code.erase(defpos);
|
||||
break;
|
||||
}
|
||||
|
||||
macros.push_back( code.substr( defpos, endpos - defpos ) );
|
||||
code.erase( defpos, endpos + 1 - defpos );
|
||||
macros.push_back(code.substr(defpos, endpos - defpos));
|
||||
code.erase(defpos, endpos + 1 - defpos);
|
||||
}
|
||||
|
||||
// Expand macros..
|
||||
|
|
|
@ -50,7 +50,7 @@ public:
|
|||
* @param resultConfigurations List of configurations. Pass these one by one
|
||||
* to getcode() with processedFile.
|
||||
*/
|
||||
void preprocess(std::istream &istr, std::string &processedFile, std::list<std::string> &resultConfigurations );
|
||||
void preprocess(std::istream &istr, std::string &processedFile, std::list<std::string> &resultConfigurations);
|
||||
|
||||
/** Just read the code into a string. Perform simple cleanup of the code */
|
||||
std::string read(std::istream &istr);
|
||||
|
@ -70,7 +70,7 @@ private:
|
|||
* @param str The string to be converted
|
||||
* @return The string where space characters have been removed.
|
||||
*/
|
||||
static std::string removeSpaceNearNL( const std::string &str );
|
||||
static std::string removeSpaceNearNL(const std::string &str);
|
||||
|
||||
/**
|
||||
* Replace "#if defined" with "#ifdef" where possible
|
||||
|
@ -78,18 +78,18 @@ private:
|
|||
* @param str The string to be converted
|
||||
* @return The replaced string
|
||||
*/
|
||||
static std::string replaceIfDefined( const std::string &str );
|
||||
static std::string replaceIfDefined(const std::string &str);
|
||||
|
||||
/**
|
||||
* Get all possible configurations. By looking at the ifdefs and ifndefs in filedata
|
||||
*/
|
||||
std::list<std::string> getcfgs( const std::string &filedata );
|
||||
std::list<std::string> getcfgs(const std::string &filedata);
|
||||
|
||||
static std::string getdef(std::string line, bool def);
|
||||
|
||||
static bool match_cfg_def( std::string cfg, const std::string &def );
|
||||
static bool match_cfg_def(std::string cfg, const std::string &def);
|
||||
|
||||
static std::string expandMacros( const std::string &code );
|
||||
static std::string expandMacros(std::string code);
|
||||
};
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
|
|
|
@ -36,12 +36,12 @@ private:
|
|||
|
||||
|
||||
|
||||
void check( const char code[] )
|
||||
void check(const char code[])
|
||||
{
|
||||
// Tokenize..
|
||||
Tokenizer tokenizer;
|
||||
std::istringstream istr(code);
|
||||
tokenizer.tokenize( istr, "test.cpp" );
|
||||
tokenizer.tokenize(istr, "test.cpp");
|
||||
tokenizer.simplifyTokenList();
|
||||
|
||||
// Assign variable ids
|
||||
|
@ -56,342 +56,342 @@ private:
|
|||
// Check for buffer overruns..
|
||||
Settings settings;
|
||||
settings._showAll = true;
|
||||
CheckBufferOverrunClass checkBufferOverrun( &tokenizer, settings, this );
|
||||
CheckBufferOverrunClass checkBufferOverrun(&tokenizer, settings, this);
|
||||
checkBufferOverrun.bufferOverrun();
|
||||
}
|
||||
|
||||
void run()
|
||||
{
|
||||
TEST_CASE( noerr1 );
|
||||
TEST_CASE( noerr2 );
|
||||
TEST_CASE( noerr3 );
|
||||
TEST_CASE( noerr4 );
|
||||
TEST_CASE(noerr1);
|
||||
TEST_CASE(noerr2);
|
||||
TEST_CASE(noerr3);
|
||||
TEST_CASE(noerr4);
|
||||
|
||||
TEST_CASE( array_index_1 );
|
||||
TEST_CASE( array_index_2 );
|
||||
TEST_CASE( array_index_3 );
|
||||
TEST_CASE( array_index_4 );
|
||||
TEST_CASE( array_index_5 );
|
||||
TEST_CASE( array_index_6 );
|
||||
TEST_CASE( array_index_7 );
|
||||
TEST_CASE( array_index_8 );
|
||||
TEST_CASE( array_index_9 );
|
||||
TEST_CASE( array_index_10 );
|
||||
TEST_CASE( array_index_11 );
|
||||
TEST_CASE( array_index_12 );
|
||||
TEST_CASE(array_index_1);
|
||||
TEST_CASE(array_index_2);
|
||||
TEST_CASE(array_index_3);
|
||||
TEST_CASE(array_index_4);
|
||||
TEST_CASE(array_index_5);
|
||||
TEST_CASE(array_index_6);
|
||||
TEST_CASE(array_index_7);
|
||||
TEST_CASE(array_index_8);
|
||||
TEST_CASE(array_index_9);
|
||||
TEST_CASE(array_index_10);
|
||||
TEST_CASE(array_index_11);
|
||||
TEST_CASE(array_index_12);
|
||||
|
||||
TEST_CASE( buffer_overrun_1 );
|
||||
TEST_CASE( buffer_overrun_2 );
|
||||
TEST_CASE(buffer_overrun_1);
|
||||
TEST_CASE(buffer_overrun_2);
|
||||
|
||||
TEST_CASE( varid1 );
|
||||
TEST_CASE( varid2 );
|
||||
TEST_CASE(varid1);
|
||||
TEST_CASE(varid2);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void noerr1()
|
||||
{
|
||||
check( "void f()\n"
|
||||
"{\n"
|
||||
" if (ab)\n"
|
||||
" {\n"
|
||||
" char str[50];\n"
|
||||
" }\n"
|
||||
" if (ab)\n"
|
||||
" {\n"
|
||||
" char str[50];\n"
|
||||
" }\n"
|
||||
"}\n" );
|
||||
ASSERT_EQUALS( std::string(""), errout.str() );
|
||||
check("void f()\n"
|
||||
"{\n"
|
||||
" if (ab)\n"
|
||||
" {\n"
|
||||
" char str[50];\n"
|
||||
" }\n"
|
||||
" if (ab)\n"
|
||||
" {\n"
|
||||
" char str[50];\n"
|
||||
" }\n"
|
||||
"}\n");
|
||||
ASSERT_EQUALS(std::string(""), errout.str());
|
||||
}
|
||||
|
||||
|
||||
void noerr2()
|
||||
{
|
||||
check( "void f1(char *str)\n"
|
||||
"{\n"
|
||||
" strcpy(buf,str);\n"
|
||||
"}\n"
|
||||
"void f2(char *str)\n"
|
||||
"{\n"
|
||||
" strcat(buf,str);\n"
|
||||
"}\n"
|
||||
"void f3(char *str)\n"
|
||||
"{\n"
|
||||
" sprintf(buf,\"%s\",str);\n"
|
||||
"}\n"
|
||||
"void f4(const char str[])\n"
|
||||
"{\n"
|
||||
" strcpy(buf, str);\n"
|
||||
"}\n" );
|
||||
ASSERT_EQUALS( std::string(""), errout.str() );
|
||||
check("void f1(char *str)\n"
|
||||
"{\n"
|
||||
" strcpy(buf,str);\n"
|
||||
"}\n"
|
||||
"void f2(char *str)\n"
|
||||
"{\n"
|
||||
" strcat(buf,str);\n"
|
||||
"}\n"
|
||||
"void f3(char *str)\n"
|
||||
"{\n"
|
||||
" sprintf(buf,\"%s\",str);\n"
|
||||
"}\n"
|
||||
"void f4(const char str[])\n"
|
||||
"{\n"
|
||||
" strcpy(buf, str);\n"
|
||||
"}\n");
|
||||
ASSERT_EQUALS(std::string(""), errout.str());
|
||||
}
|
||||
|
||||
|
||||
void noerr3()
|
||||
{
|
||||
check( "static void f()\n"
|
||||
"{\n"
|
||||
" char data[1];\n"
|
||||
" return abc.data[1];\n"
|
||||
"}\n" );
|
||||
ASSERT_EQUALS( std::string(""), errout.str() );
|
||||
check("static void f()\n"
|
||||
"{\n"
|
||||
" char data[1];\n"
|
||||
" return abc.data[1];\n"
|
||||
"}\n");
|
||||
ASSERT_EQUALS(std::string(""), errout.str());
|
||||
}
|
||||
|
||||
|
||||
void noerr4()
|
||||
{
|
||||
// The memory isn't read or written and therefore there is no error.
|
||||
check( "static void f()\n"
|
||||
"{\n"
|
||||
" char data[100];\n"
|
||||
" const char *p = &data[100];\n"
|
||||
"}\n" );
|
||||
ASSERT_EQUALS( std::string(""), errout.str() );
|
||||
check("static void f()\n"
|
||||
"{\n"
|
||||
" char data[100];\n"
|
||||
" const char *p = &data[100];\n"
|
||||
"}\n");
|
||||
ASSERT_EQUALS(std::string(""), errout.str());
|
||||
}
|
||||
|
||||
|
||||
void array_index_1()
|
||||
{
|
||||
check("void f()\n"
|
||||
"{\n"
|
||||
" char str[0x10];\n"
|
||||
" str[15] = 0;\n"
|
||||
" str[16] = 0;\n"
|
||||
"}\n" );
|
||||
ASSERT_EQUALS( std::string("[test.cpp:5]: Array index out of bounds\n"), errout.str() );
|
||||
"{\n"
|
||||
" char str[0x10];\n"
|
||||
" str[15] = 0;\n"
|
||||
" str[16] = 0;\n"
|
||||
"}\n");
|
||||
ASSERT_EQUALS(std::string("[test.cpp:5]: Array index out of bounds\n"), errout.str());
|
||||
}
|
||||
|
||||
|
||||
void array_index_2()
|
||||
{
|
||||
check("void f()\n"
|
||||
"{\n"
|
||||
" char *str = new char[0x10];\n"
|
||||
" str[15] = 0;\n"
|
||||
" str[16] = 0;\n"
|
||||
"}\n" );
|
||||
ASSERT_EQUALS( std::string("[test.cpp:5]: Array index out of bounds\n"), errout.str() );
|
||||
"{\n"
|
||||
" char *str = new char[0x10];\n"
|
||||
" str[15] = 0;\n"
|
||||
" str[16] = 0;\n"
|
||||
"}\n");
|
||||
ASSERT_EQUALS(std::string("[test.cpp:5]: Array index out of bounds\n"), errout.str());
|
||||
}
|
||||
|
||||
|
||||
void array_index_3()
|
||||
{
|
||||
check( "void f()\n"
|
||||
"{\n"
|
||||
" int val[50];\n"
|
||||
" for (i = 0; i < 100; i++)\n"
|
||||
" sum += val[i];\n"
|
||||
"}\n" );
|
||||
ASSERT_EQUALS( std::string("[test.cpp:5]: Buffer overrun\n"), errout.str() );
|
||||
check("void f()\n"
|
||||
"{\n"
|
||||
" int val[50];\n"
|
||||
" for (i = 0; i < 100; i++)\n"
|
||||
" sum += val[i];\n"
|
||||
"}\n");
|
||||
ASSERT_EQUALS(std::string("[test.cpp:5]: Buffer overrun\n"), errout.str());
|
||||
}
|
||||
|
||||
|
||||
void array_index_4()
|
||||
{
|
||||
check( "const int SIZE = 10;\n"
|
||||
"void f()\n"
|
||||
"{\n"
|
||||
" int i[SIZE];\n"
|
||||
" i[SIZE] = 0;\n"
|
||||
"}\n" );
|
||||
ASSERT_EQUALS( std::string("[test.cpp:5]: Array index out of bounds\n"), errout.str() );
|
||||
check("const int SIZE = 10;\n"
|
||||
"void f()\n"
|
||||
"{\n"
|
||||
" int i[SIZE];\n"
|
||||
" i[SIZE] = 0;\n"
|
||||
"}\n");
|
||||
ASSERT_EQUALS(std::string("[test.cpp:5]: Array index out of bounds\n"), errout.str());
|
||||
}
|
||||
|
||||
|
||||
void array_index_5()
|
||||
{
|
||||
check( "void f()\n"
|
||||
"{\n"
|
||||
" int i[10];\n"
|
||||
" i[ sizeof(i) - 1 ] = 0;\n"
|
||||
"}\n" );
|
||||
ASSERT_EQUALS( std::string("[test.cpp:4]: Array index out of bounds\n"), errout.str() );
|
||||
check("void f()\n"
|
||||
"{\n"
|
||||
" int i[10];\n"
|
||||
" i[ sizeof(i) - 1 ] = 0;\n"
|
||||
"}\n");
|
||||
ASSERT_EQUALS(std::string("[test.cpp:4]: Array index out of bounds\n"), errout.str());
|
||||
}
|
||||
|
||||
|
||||
void array_index_6()
|
||||
{
|
||||
check( "struct ABC\n"
|
||||
"{\n"
|
||||
" char str[10];\n"
|
||||
"};\n"
|
||||
"\n"
|
||||
"static void f()\n"
|
||||
"{\n"
|
||||
" struct ABC abc;\n"
|
||||
" abc.str[10] = 0;\n"
|
||||
"}\n" );
|
||||
ASSERT_EQUALS( std::string("[test.cpp:9]: Array index out of bounds\n"), errout.str() );
|
||||
check("struct ABC\n"
|
||||
"{\n"
|
||||
" char str[10];\n"
|
||||
"};\n"
|
||||
"\n"
|
||||
"static void f()\n"
|
||||
"{\n"
|
||||
" struct ABC abc;\n"
|
||||
" abc.str[10] = 0;\n"
|
||||
"}\n");
|
||||
ASSERT_EQUALS(std::string("[test.cpp:9]: Array index out of bounds\n"), errout.str());
|
||||
}
|
||||
|
||||
|
||||
void array_index_7()
|
||||
{
|
||||
check( "struct ABC\n"
|
||||
"{\n"
|
||||
" char str[10];\n"
|
||||
"};\n"
|
||||
"\n"
|
||||
"static void f(ABC *abc)\n"
|
||||
"{\n"
|
||||
" abc->str[10] = 0;\n"
|
||||
"}\n" );
|
||||
ASSERT_EQUALS( std::string("[test.cpp:8]: Array index out of bounds\n"), errout.str() );
|
||||
check("struct ABC\n"
|
||||
"{\n"
|
||||
" char str[10];\n"
|
||||
"};\n"
|
||||
"\n"
|
||||
"static void f(ABC *abc)\n"
|
||||
"{\n"
|
||||
" abc->str[10] = 0;\n"
|
||||
"}\n");
|
||||
ASSERT_EQUALS(std::string("[test.cpp:8]: Array index out of bounds\n"), errout.str());
|
||||
}
|
||||
|
||||
|
||||
void array_index_8()
|
||||
{
|
||||
check( "const int SIZE = 10;\n"
|
||||
"\n"
|
||||
"struct ABC\n"
|
||||
"{\n"
|
||||
" char str[SIZE];\n"
|
||||
"};\n"
|
||||
"\n"
|
||||
"static void f()\n"
|
||||
"{\n"
|
||||
" struct ABC abc;\n"
|
||||
" abc.str[SIZE] = 0;\n"
|
||||
"}\n" );
|
||||
ASSERT_EQUALS( std::string("[test.cpp:11]: Array index out of bounds\n"), errout.str() );
|
||||
check("const int SIZE = 10;\n"
|
||||
"\n"
|
||||
"struct ABC\n"
|
||||
"{\n"
|
||||
" char str[SIZE];\n"
|
||||
"};\n"
|
||||
"\n"
|
||||
"static void f()\n"
|
||||
"{\n"
|
||||
" struct ABC abc;\n"
|
||||
" abc.str[SIZE] = 0;\n"
|
||||
"}\n");
|
||||
ASSERT_EQUALS(std::string("[test.cpp:11]: Array index out of bounds\n"), errout.str());
|
||||
}
|
||||
|
||||
void array_index_9()
|
||||
{
|
||||
check( "static void memclr( char *data )\n"
|
||||
"{\n"
|
||||
" data[10] = 0;\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"static void f()\n"
|
||||
"{\n"
|
||||
" char str[5];\n"
|
||||
" memclr( str ); // ERROR\n"
|
||||
"}\n" );
|
||||
ASSERT_EQUALS( std::string("[test.cpp:9] -> [test.cpp:3]: Array index out of bounds\n"), errout.str() );
|
||||
check("static void memclr( char *data )\n"
|
||||
"{\n"
|
||||
" data[10] = 0;\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"static void f()\n"
|
||||
"{\n"
|
||||
" char str[5];\n"
|
||||
" memclr( str ); // ERROR\n"
|
||||
"}\n");
|
||||
ASSERT_EQUALS(std::string("[test.cpp:9] -> [test.cpp:3]: Array index out of bounds\n"), errout.str());
|
||||
}
|
||||
|
||||
|
||||
void array_index_10()
|
||||
{
|
||||
check( "struct ABC\n"
|
||||
"{\n"
|
||||
" char str[10];\n"
|
||||
"};\n"
|
||||
"\n"
|
||||
"static void memclr( char *data )\n"
|
||||
"{\n"
|
||||
" data[10] = 0;\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"static void f(ABC *abc)\n"
|
||||
"{\n"
|
||||
" memclr(abc->str);\n"
|
||||
"}\n" );
|
||||
ASSERT_EQUALS( std::string("[test.cpp:13] -> [test.cpp:8]: Array index out of bounds\n"), errout.str() );
|
||||
check("struct ABC\n"
|
||||
"{\n"
|
||||
" char str[10];\n"
|
||||
"};\n"
|
||||
"\n"
|
||||
"static void memclr( char *data )\n"
|
||||
"{\n"
|
||||
" data[10] = 0;\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"static void f(ABC *abc)\n"
|
||||
"{\n"
|
||||
" memclr(abc->str);\n"
|
||||
"}\n");
|
||||
ASSERT_EQUALS(std::string("[test.cpp:13] -> [test.cpp:8]: Array index out of bounds\n"), errout.str());
|
||||
}
|
||||
|
||||
|
||||
void array_index_11()
|
||||
{
|
||||
check( "class ABC\n"
|
||||
"{\n"
|
||||
"public:\n"
|
||||
" ABC();\n"
|
||||
" char *str[10];\n"
|
||||
" struct ABC *next;"
|
||||
"};\n"
|
||||
"\n"
|
||||
"static void f()\n"
|
||||
"{\n"
|
||||
" for ( ABC *abc = abc1; abc; abc = abc->next() )\n"
|
||||
" {\n"
|
||||
" abc->str[10] = 0;\n"
|
||||
" }\n"
|
||||
"}\n" );
|
||||
ASSERT_EQUALS( std::string("[test.cpp:12]: Array index out of bounds\n"), errout.str() );
|
||||
check("class ABC\n"
|
||||
"{\n"
|
||||
"public:\n"
|
||||
" ABC();\n"
|
||||
" char *str[10];\n"
|
||||
" struct ABC *next;"
|
||||
"};\n"
|
||||
"\n"
|
||||
"static void f()\n"
|
||||
"{\n"
|
||||
" for ( ABC *abc = abc1; abc; abc = abc->next() )\n"
|
||||
" {\n"
|
||||
" abc->str[10] = 0;\n"
|
||||
" }\n"
|
||||
"}\n");
|
||||
ASSERT_EQUALS(std::string("[test.cpp:12]: Array index out of bounds\n"), errout.str());
|
||||
}
|
||||
|
||||
|
||||
void array_index_12()
|
||||
{
|
||||
check( "class Fred\n"
|
||||
"{\n"
|
||||
"private:\n"
|
||||
" char str[10];\n"
|
||||
"public:\n"
|
||||
" Fred();\n"
|
||||
"};\n"
|
||||
"Fred::Fred()\n"
|
||||
"{\n"
|
||||
" str[10] = 0;\n"
|
||||
"}\n" );
|
||||
std::string err( errout.str() );
|
||||
ASSERT_EQUALS( std::string("[test.cpp:10]: Array index out of bounds\n"), err );
|
||||
check("class Fred\n"
|
||||
"{\n"
|
||||
"private:\n"
|
||||
" char str[10];\n"
|
||||
"public:\n"
|
||||
" Fred();\n"
|
||||
"};\n"
|
||||
"Fred::Fred()\n"
|
||||
"{\n"
|
||||
" str[10] = 0;\n"
|
||||
"}\n");
|
||||
std::string err(errout.str());
|
||||
ASSERT_EQUALS(std::string("[test.cpp:10]: Array index out of bounds\n"), err);
|
||||
}
|
||||
|
||||
|
||||
void buffer_overrun_1()
|
||||
{
|
||||
check( "void f()\n"
|
||||
"{\n"
|
||||
" char str[3];\n"
|
||||
" strcpy(str, \"abc\");\n"
|
||||
"}\n" );
|
||||
ASSERT_EQUALS( std::string("[test.cpp:4]: Buffer overrun\n"), errout.str() );
|
||||
check("void f()\n"
|
||||
"{\n"
|
||||
" char str[3];\n"
|
||||
" strcpy(str, \"abc\");\n"
|
||||
"}\n");
|
||||
ASSERT_EQUALS(std::string("[test.cpp:4]: Buffer overrun\n"), errout.str());
|
||||
}
|
||||
|
||||
|
||||
void buffer_overrun_2()
|
||||
{
|
||||
check( "struct ABC\n"
|
||||
"{\n"
|
||||
" char str[5];\n"
|
||||
"};\n"
|
||||
"\n"
|
||||
"static void f(ABC *abc)\n"
|
||||
"{\n"
|
||||
" strcpy( abc->str, \"abcdef\" );\n"
|
||||
"}\n" );
|
||||
ASSERT_EQUALS( std::string("[test.cpp:8]: Buffer overrun\n"), errout.str() );
|
||||
check("struct ABC\n"
|
||||
"{\n"
|
||||
" char str[5];\n"
|
||||
"};\n"
|
||||
"\n"
|
||||
"static void f(ABC *abc)\n"
|
||||
"{\n"
|
||||
" strcpy( abc->str, \"abcdef\" );\n"
|
||||
"}\n");
|
||||
ASSERT_EQUALS(std::string("[test.cpp:8]: Buffer overrun\n"), errout.str());
|
||||
}
|
||||
|
||||
|
||||
|
||||
void varid1()
|
||||
{
|
||||
check( "void foo()\n"
|
||||
"{\n"
|
||||
" char str[10];\n"
|
||||
" if (str[0])\n"
|
||||
" {\n"
|
||||
" char str[50];\n"
|
||||
" str[30] = 0;\n"
|
||||
" }\n"
|
||||
"}\n" );
|
||||
ASSERT_EQUALS( std::string(""), errout.str() );
|
||||
check("void foo()\n"
|
||||
"{\n"
|
||||
" char str[10];\n"
|
||||
" if (str[0])\n"
|
||||
" {\n"
|
||||
" char str[50];\n"
|
||||
" str[30] = 0;\n"
|
||||
" }\n"
|
||||
"}\n");
|
||||
ASSERT_EQUALS(std::string(""), errout.str());
|
||||
}
|
||||
|
||||
|
||||
void varid2()
|
||||
{
|
||||
check( "void foo()\n"
|
||||
"{\n"
|
||||
" char str[10];\n"
|
||||
" if (str[0])\n"
|
||||
" {\n"
|
||||
" char str[50];\n"
|
||||
" memset(str,0,50);\n"
|
||||
" }\n"
|
||||
"}\n" );
|
||||
ASSERT_EQUALS( std::string(""), errout.str() );
|
||||
check("void foo()\n"
|
||||
"{\n"
|
||||
" char str[10];\n"
|
||||
" if (str[0])\n"
|
||||
" {\n"
|
||||
" char str[50];\n"
|
||||
" memset(str,0,50);\n"
|
||||
" }\n"
|
||||
"}\n");
|
||||
ASSERT_EQUALS(std::string(""), errout.str());
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
|
||||
REGISTER_TEST( TestBufferOverrun )
|
||||
REGISTER_TEST(TestBufferOverrun)
|
||||
|
||||
|
||||
|
|
|
@ -36,71 +36,71 @@ private:
|
|||
|
||||
void run()
|
||||
{
|
||||
TEST_CASE( array_index );
|
||||
TEST_CASE( bitop1 );
|
||||
TEST_CASE( bitop2 );
|
||||
TEST_CASE(array_index);
|
||||
TEST_CASE(bitop1);
|
||||
TEST_CASE(bitop2);
|
||||
}
|
||||
|
||||
void check( const char code[] )
|
||||
void check(const char code[])
|
||||
{
|
||||
// Tokenize..
|
||||
Tokenizer tokenizer;
|
||||
std::istringstream istr(code);
|
||||
tokenizer.tokenize( istr, "test.cpp" );
|
||||
tokenizer.tokenize(istr, "test.cpp");
|
||||
tokenizer.setVarId();
|
||||
|
||||
// Clear the error buffer..
|
||||
errout.str("");
|
||||
|
||||
// Check char variable usage..
|
||||
CheckOther checkOther( &tokenizer, this );
|
||||
CheckOther checkOther(&tokenizer, this);
|
||||
checkOther.CheckCharVariable();
|
||||
}
|
||||
|
||||
void array_index()
|
||||
{
|
||||
check( "void foo()\n"
|
||||
"{\n"
|
||||
" unsigned char ch = 0x80;\n"
|
||||
" buf[ch] = 0;\n"
|
||||
"}\n" );
|
||||
ASSERT_EQUALS( std::string(""), errout.str() );
|
||||
check("void foo()\n"
|
||||
"{\n"
|
||||
" unsigned char ch = 0x80;\n"
|
||||
" buf[ch] = 0;\n"
|
||||
"}\n");
|
||||
ASSERT_EQUALS(std::string(""), errout.str());
|
||||
|
||||
check( "void foo()\n"
|
||||
"{\n"
|
||||
" char ch = 0x80;\n"
|
||||
" buf[ch] = 0;\n"
|
||||
"}\n" );
|
||||
ASSERT_EQUALS( std::string("[test.cpp:4]: Warning - using char variable as array index\n"), errout.str() );
|
||||
check("void foo()\n"
|
||||
"{\n"
|
||||
" char ch = 0x80;\n"
|
||||
" buf[ch] = 0;\n"
|
||||
"}\n");
|
||||
ASSERT_EQUALS(std::string("[test.cpp:4]: Warning - using char variable as array index\n"), errout.str());
|
||||
|
||||
check( "void foo(char ch)\n"
|
||||
"{\n"
|
||||
" buf[ch] = 0;\n"
|
||||
"}\n" );
|
||||
ASSERT_EQUALS( std::string("[test.cpp:3]: Warning - using char variable as array index\n"), errout.str() );
|
||||
check("void foo(char ch)\n"
|
||||
"{\n"
|
||||
" buf[ch] = 0;\n"
|
||||
"}\n");
|
||||
ASSERT_EQUALS(std::string("[test.cpp:3]: Warning - using char variable as array index\n"), errout.str());
|
||||
}
|
||||
|
||||
|
||||
void bitop1()
|
||||
{
|
||||
check( "void foo()\n"
|
||||
"{\n"
|
||||
" char ch;\n"
|
||||
" result = a | ch;\n"
|
||||
"}\n" );
|
||||
ASSERT_EQUALS( std::string("[test.cpp:4]: Warning - using char variable in bit operation\n"), errout.str() );
|
||||
check("void foo()\n"
|
||||
"{\n"
|
||||
" char ch;\n"
|
||||
" result = a | ch;\n"
|
||||
"}\n");
|
||||
ASSERT_EQUALS(std::string("[test.cpp:4]: Warning - using char variable in bit operation\n"), errout.str());
|
||||
}
|
||||
|
||||
void bitop2()
|
||||
{
|
||||
check( "void foo()\n"
|
||||
"{\n"
|
||||
" char ch;\n"
|
||||
" func(&ch);\n"
|
||||
"}\n" );
|
||||
ASSERT_EQUALS( std::string(""), errout.str() );
|
||||
check("void foo()\n"
|
||||
"{\n"
|
||||
" char ch;\n"
|
||||
" func(&ch);\n"
|
||||
"}\n");
|
||||
ASSERT_EQUALS(std::string(""), errout.str());
|
||||
}
|
||||
};
|
||||
|
||||
REGISTER_TEST( TestCharVar )
|
||||
REGISTER_TEST(TestCharVar)
|
||||
|
||||
|
|
|
@ -36,11 +36,11 @@ private:
|
|||
|
||||
void run()
|
||||
{
|
||||
TEST_CASE( virtualDestructor1 ); // Base class not found => no error
|
||||
TEST_CASE( virtualDestructor2 ); // Base class doesn't have a destructor
|
||||
TEST_CASE( virtualDestructor3 ); // Base class has a destructor, but it's not virtual
|
||||
TEST_CASE( virtualDestructor4 ); // Derived class doesn't have a destructor => no error
|
||||
TEST_CASE( virtualDestructor5 ); // Derived class has empty destructor => no error
|
||||
TEST_CASE(virtualDestructor1); // Base class not found => no error
|
||||
TEST_CASE(virtualDestructor2); // Base class doesn't have a destructor
|
||||
TEST_CASE(virtualDestructor3); // Base class has a destructor, but it's not virtual
|
||||
TEST_CASE(virtualDestructor4); // Derived class doesn't have a destructor => no error
|
||||
TEST_CASE(virtualDestructor5); // Derived class has empty destructor => no error
|
||||
}
|
||||
|
||||
// Check that base classes have virtual destructors
|
||||
|
@ -49,7 +49,7 @@ private:
|
|||
// Tokenize..
|
||||
Tokenizer tokenizer;
|
||||
std::istringstream istr(code);
|
||||
tokenizer.tokenize( istr, "test.cpp" );
|
||||
tokenizer.tokenize(istr, "test.cpp");
|
||||
tokenizer.simplifyTokenList();
|
||||
|
||||
// Clear the error log
|
||||
|
@ -57,73 +57,73 @@ private:
|
|||
|
||||
// Check..
|
||||
Settings settings;
|
||||
CheckClass checkClass( &tokenizer, settings, this );
|
||||
CheckClass checkClass(&tokenizer, settings, this);
|
||||
checkClass.virtualDestructor();
|
||||
}
|
||||
|
||||
|
||||
void virtualDestructor1()
|
||||
{
|
||||
// Base class not found
|
||||
// Base class not found
|
||||
|
||||
checkVirtualDestructor("class Derived : public Base { };");
|
||||
ASSERT_EQUALS( std::string(""), errout.str() );
|
||||
ASSERT_EQUALS(std::string(""), errout.str());
|
||||
|
||||
checkVirtualDestructor("class Derived : Base { };");
|
||||
ASSERT_EQUALS( std::string(""), errout.str() );
|
||||
ASSERT_EQUALS(std::string(""), errout.str());
|
||||
}
|
||||
|
||||
void virtualDestructor2()
|
||||
{
|
||||
// Base class doesn't have a destructor
|
||||
// Base class doesn't have a destructor
|
||||
|
||||
checkVirtualDestructor("class Base { };\n"
|
||||
"class Derived : public Base { public: ~Derived() { (void)11; } };");
|
||||
ASSERT_EQUALS( std::string("[test.cpp:1]: Class Base which is inherited by class Derived does not have a virtual destructor\n"), errout.str() );
|
||||
ASSERT_EQUALS(std::string("[test.cpp:1]: Class Base which is inherited by class Derived does not have a virtual destructor\n"), errout.str());
|
||||
|
||||
checkVirtualDestructor("class Base { };\n"
|
||||
"class Derived : Base { public: ~Derived() { (void)11; } };");
|
||||
ASSERT_EQUALS( std::string(""), errout.str() );
|
||||
ASSERT_EQUALS(std::string(""), errout.str());
|
||||
}
|
||||
|
||||
void virtualDestructor3()
|
||||
{
|
||||
// Base class has a destructor, but it's not virtual
|
||||
// Base class has a destructor, but it's not virtual
|
||||
|
||||
checkVirtualDestructor("class Base { public: ~Base(); };\n"
|
||||
"class Derived : public Base { public: ~Derived() { (void)11; } };");
|
||||
ASSERT_EQUALS( std::string("[test.cpp:1]: Class Base which is inherited by class Derived does not have a virtual destructor\n"), errout.str() );
|
||||
ASSERT_EQUALS(std::string("[test.cpp:1]: Class Base which is inherited by class Derived does not have a virtual destructor\n"), errout.str());
|
||||
|
||||
checkVirtualDestructor("class Base { public: ~Base(); };\n"
|
||||
"class Derived : private Fred, public Base { public: ~Derived() { (void)11; } };");
|
||||
ASSERT_EQUALS( std::string("[test.cpp:1]: Class Base which is inherited by class Derived does not have a virtual destructor\n"), errout.str() );
|
||||
ASSERT_EQUALS(std::string("[test.cpp:1]: Class Base which is inherited by class Derived does not have a virtual destructor\n"), errout.str());
|
||||
}
|
||||
|
||||
void virtualDestructor4()
|
||||
{
|
||||
// Derived class doesn't have a destructor => no error
|
||||
// Derived class doesn't have a destructor => no error
|
||||
|
||||
checkVirtualDestructor("class Base { public: ~Base(); };\n"
|
||||
"class Derived : public Base { };");
|
||||
ASSERT_EQUALS( std::string(""), errout.str() );
|
||||
ASSERT_EQUALS(std::string(""), errout.str());
|
||||
|
||||
checkVirtualDestructor("class Base { public: ~Base(); };\n"
|
||||
"class Derived : private Fred, public Base { };");
|
||||
ASSERT_EQUALS( std::string(""), errout.str() );
|
||||
ASSERT_EQUALS(std::string(""), errout.str());
|
||||
}
|
||||
|
||||
void virtualDestructor5()
|
||||
{
|
||||
// Derived class has empty destructor => no error
|
||||
// Derived class has empty destructor => no error
|
||||
|
||||
checkVirtualDestructor("class Base { public: ~Base(); };\n"
|
||||
"class Derived : public Base { public: ~Derived() {} };");
|
||||
ASSERT_EQUALS( std::string(""), errout.str() );
|
||||
ASSERT_EQUALS(std::string(""), errout.str());
|
||||
|
||||
checkVirtualDestructor("class Base { public: ~Base(); };\n"
|
||||
"class Derived : public Base { public: ~Derived(); }; Derived::~Derived() {}");
|
||||
ASSERT_EQUALS( std::string(""), errout.str() );
|
||||
ASSERT_EQUALS(std::string(""), errout.str());
|
||||
}
|
||||
};
|
||||
|
||||
REGISTER_TEST( TestClass )
|
||||
REGISTER_TEST(TestClass)
|
||||
|
|
|
@ -35,12 +35,12 @@ public:
|
|||
private:
|
||||
|
||||
|
||||
void check( const char code[] )
|
||||
void check(const char code[])
|
||||
{
|
||||
// Tokenize..
|
||||
Tokenizer tokenizer;
|
||||
std::istringstream istr(code);
|
||||
tokenizer.tokenize( istr, "test.cpp" );
|
||||
tokenizer.tokenize(istr, "test.cpp");
|
||||
tokenizer.simplifyTokenList();
|
||||
|
||||
// Clear the error buffer..
|
||||
|
@ -49,278 +49,278 @@ private:
|
|||
// Check class constructors..
|
||||
Settings settings;
|
||||
settings._checkCodingStyle = true;
|
||||
CheckClass checkClass( &tokenizer, settings, this );
|
||||
CheckClass checkClass(&tokenizer, settings, this);
|
||||
checkClass.constructors();
|
||||
}
|
||||
|
||||
void run()
|
||||
{
|
||||
TEST_CASE( simple1 );
|
||||
TEST_CASE( simple2 );
|
||||
TEST_CASE( simple3 );
|
||||
TEST_CASE( simple4 );
|
||||
TEST_CASE(simple1);
|
||||
TEST_CASE(simple2);
|
||||
TEST_CASE(simple3);
|
||||
TEST_CASE(simple4);
|
||||
|
||||
TEST_CASE( initvar_with_this ); // BUG 2190300
|
||||
TEST_CASE( initvar_if ); // BUG 2190290
|
||||
TEST_CASE( initvar_operator_eq1 ); // BUG 2190376
|
||||
TEST_CASE( initvar_operator_eq2 ); // BUG 2190376
|
||||
TEST_CASE( initvar_operator_eq3 );
|
||||
TEST_CASE( initvar_same_classname ); // BUG 2208157
|
||||
TEST_CASE( initvar_chained_assign ); // BUG 2270433
|
||||
TEST_CASE( initvar_2constructors ); // BUG 2270353
|
||||
TEST_CASE(initvar_with_this); // BUG 2190300
|
||||
TEST_CASE(initvar_if); // BUG 2190290
|
||||
TEST_CASE(initvar_operator_eq1); // BUG 2190376
|
||||
TEST_CASE(initvar_operator_eq2); // BUG 2190376
|
||||
TEST_CASE(initvar_operator_eq3);
|
||||
TEST_CASE(initvar_same_classname); // BUG 2208157
|
||||
TEST_CASE(initvar_chained_assign); // BUG 2270433
|
||||
TEST_CASE(initvar_2constructors); // BUG 2270353
|
||||
|
||||
TEST_CASE( initvar_private_constructor ); // BUG 2354171 - private constructor
|
||||
TEST_CASE(initvar_private_constructor); // BUG 2354171 - private constructor
|
||||
|
||||
TEST_CASE( initvar_destructor ); // No variables need to be initialized in a destructor
|
||||
TEST_CASE(initvar_destructor); // No variables need to be initialized in a destructor
|
||||
}
|
||||
|
||||
|
||||
void simple1()
|
||||
{
|
||||
check( "class Fred\n"
|
||||
"{\n"
|
||||
"public:\n"
|
||||
" int i;\n"
|
||||
"};\n" );
|
||||
std::string actual( errout.str() );
|
||||
std::string expected( "[test.cpp:1] The class 'Fred' has no constructor\n" );
|
||||
ASSERT_EQUALS( expected, actual );
|
||||
check("class Fred\n"
|
||||
"{\n"
|
||||
"public:\n"
|
||||
" int i;\n"
|
||||
"};\n");
|
||||
std::string actual(errout.str());
|
||||
std::string expected("[test.cpp:1] The class 'Fred' has no constructor\n");
|
||||
ASSERT_EQUALS(expected, actual);
|
||||
}
|
||||
|
||||
|
||||
void simple2()
|
||||
{
|
||||
check( "class Fred\n"
|
||||
"{\n"
|
||||
"public:\n"
|
||||
" Fred() { }\n"
|
||||
" int i;\n"
|
||||
"};\n" );
|
||||
ASSERT_EQUALS( std::string("[test.cpp:4] Uninitialized member variable 'Fred::i'\n"), errout.str() );
|
||||
check("class Fred\n"
|
||||
"{\n"
|
||||
"public:\n"
|
||||
" Fred() { }\n"
|
||||
" int i;\n"
|
||||
"};\n");
|
||||
ASSERT_EQUALS(std::string("[test.cpp:4] Uninitialized member variable 'Fred::i'\n"), errout.str());
|
||||
}
|
||||
|
||||
|
||||
void simple3()
|
||||
{
|
||||
check( "class Fred\n"
|
||||
"{\n"
|
||||
"public:\n"
|
||||
" Fred();\n"
|
||||
" int i;\n"
|
||||
"};\n"
|
||||
"Fred::Fred()\n"
|
||||
"{ }\n" );
|
||||
ASSERT_EQUALS( std::string("[test.cpp:7] Uninitialized member variable 'Fred::i'\n"), errout.str() );
|
||||
check("class Fred\n"
|
||||
"{\n"
|
||||
"public:\n"
|
||||
" Fred();\n"
|
||||
" int i;\n"
|
||||
"};\n"
|
||||
"Fred::Fred()\n"
|
||||
"{ }\n");
|
||||
ASSERT_EQUALS(std::string("[test.cpp:7] Uninitialized member variable 'Fred::i'\n"), errout.str());
|
||||
}
|
||||
|
||||
|
||||
void simple4()
|
||||
{
|
||||
check( "class Fred\n"
|
||||
"{\n"
|
||||
"public:\n"
|
||||
" Fred();\n"
|
||||
" Fred(int _i);\n"
|
||||
" int i;\n"
|
||||
"};\n"
|
||||
"Fred::Fred()\n"
|
||||
"{ }\n"
|
||||
"Fred::Fred(int _i)\n"
|
||||
"{\n"
|
||||
" i = _i;\n"
|
||||
"}\n" );
|
||||
ASSERT_EQUALS( std::string("[test.cpp:8] Uninitialized member variable 'Fred::i'\n"), errout.str() );
|
||||
check("class Fred\n"
|
||||
"{\n"
|
||||
"public:\n"
|
||||
" Fred();\n"
|
||||
" Fred(int _i);\n"
|
||||
" int i;\n"
|
||||
"};\n"
|
||||
"Fred::Fred()\n"
|
||||
"{ }\n"
|
||||
"Fred::Fred(int _i)\n"
|
||||
"{\n"
|
||||
" i = _i;\n"
|
||||
"}\n");
|
||||
ASSERT_EQUALS(std::string("[test.cpp:8] Uninitialized member variable 'Fred::i'\n"), errout.str());
|
||||
}
|
||||
|
||||
|
||||
void initvar_with_this()
|
||||
{
|
||||
check( "class Fred\n"
|
||||
"{\n"
|
||||
"public:\n"
|
||||
" Fred()\n"
|
||||
" { this->i = 0; }\n"
|
||||
" int i;\n"
|
||||
"};\n" );
|
||||
ASSERT_EQUALS( std::string(""), errout.str() );
|
||||
check("class Fred\n"
|
||||
"{\n"
|
||||
"public:\n"
|
||||
" Fred()\n"
|
||||
" { this->i = 0; }\n"
|
||||
" int i;\n"
|
||||
"};\n");
|
||||
ASSERT_EQUALS(std::string(""), errout.str());
|
||||
}
|
||||
|
||||
void initvar_if()
|
||||
{
|
||||
check( "class Fred\n"
|
||||
"{\n"
|
||||
"public:\n"
|
||||
" Fred()\n"
|
||||
" {\n"
|
||||
" if (true)\n"
|
||||
" i = 0;\n"
|
||||
" else\n"
|
||||
" i = 1;\n"
|
||||
" }\n"
|
||||
" int i;\n"
|
||||
"};\n" );
|
||||
ASSERT_EQUALS( std::string(""), errout.str() );
|
||||
check("class Fred\n"
|
||||
"{\n"
|
||||
"public:\n"
|
||||
" Fred()\n"
|
||||
" {\n"
|
||||
" if (true)\n"
|
||||
" i = 0;\n"
|
||||
" else\n"
|
||||
" i = 1;\n"
|
||||
" }\n"
|
||||
" int i;\n"
|
||||
"};\n");
|
||||
ASSERT_EQUALS(std::string(""), errout.str());
|
||||
}
|
||||
|
||||
void initvar_operator_eq1()
|
||||
{
|
||||
// Bug 2190376 - False positive, Uninitialized member variable with operator=
|
||||
|
||||
check( "class Fred\n"
|
||||
"{\n"
|
||||
"private:\n"
|
||||
" int i;\n"
|
||||
"\n"
|
||||
"public:\n"
|
||||
" Fred()\n"
|
||||
" { i = 0; }\n"
|
||||
"\n"
|
||||
" Fred(const Fred &fred)\n"
|
||||
" { *this = fred; }\n"
|
||||
"\n"
|
||||
" const Fred & operator=(const Fred &fred)\n"
|
||||
" { i = fred.i; return *this; }\n"
|
||||
"};\n" );
|
||||
check("class Fred\n"
|
||||
"{\n"
|
||||
"private:\n"
|
||||
" int i;\n"
|
||||
"\n"
|
||||
"public:\n"
|
||||
" Fred()\n"
|
||||
" { i = 0; }\n"
|
||||
"\n"
|
||||
" Fred(const Fred &fred)\n"
|
||||
" { *this = fred; }\n"
|
||||
"\n"
|
||||
" const Fred & operator=(const Fred &fred)\n"
|
||||
" { i = fred.i; return *this; }\n"
|
||||
"};\n");
|
||||
|
||||
std::string err( errout.str() );
|
||||
ASSERT_EQUALS( std::string(""), err );
|
||||
std::string err(errout.str());
|
||||
ASSERT_EQUALS(std::string(""), err);
|
||||
}
|
||||
|
||||
|
||||
void initvar_operator_eq2()
|
||||
{
|
||||
check( "class Fred\n"
|
||||
"{\n"
|
||||
"public:\n"
|
||||
" Fred() { i = 0; }\n"
|
||||
" void operator=() { }\n"
|
||||
" int i;\n"
|
||||
"};\n" );
|
||||
ASSERT_EQUALS( std::string("[test.cpp:5] Uninitialized member variable 'Fred::i'\n"), errout.str() );
|
||||
check("class Fred\n"
|
||||
"{\n"
|
||||
"public:\n"
|
||||
" Fred() { i = 0; }\n"
|
||||
" void operator=() { }\n"
|
||||
" int i;\n"
|
||||
"};\n");
|
||||
ASSERT_EQUALS(std::string("[test.cpp:5] Uninitialized member variable 'Fred::i'\n"), errout.str());
|
||||
}
|
||||
|
||||
void initvar_operator_eq3()
|
||||
{
|
||||
check( "class Fred\n"
|
||||
"{\n"
|
||||
"public:\n"
|
||||
" Fred() { Init(); }\n"
|
||||
" void operator=() { Init(); }\n"
|
||||
"private:\n"
|
||||
" Init() { i = 0; }\n"
|
||||
" int i;\n"
|
||||
"};\n" );
|
||||
ASSERT_EQUALS( std::string(""), errout.str() );
|
||||
check("class Fred\n"
|
||||
"{\n"
|
||||
"public:\n"
|
||||
" Fred() { Init(); }\n"
|
||||
" void operator=() { Init(); }\n"
|
||||
"private:\n"
|
||||
" Init() { i = 0; }\n"
|
||||
" int i;\n"
|
||||
"};\n");
|
||||
ASSERT_EQUALS(std::string(""), errout.str());
|
||||
}
|
||||
|
||||
void initvar_same_classname()
|
||||
{
|
||||
// Bug 2208157 - False positive: Uninitialized variable, same class name
|
||||
|
||||
check( "void func1()\n"
|
||||
"{\n"
|
||||
" class Fred\n"
|
||||
" {\n"
|
||||
" int a;\n"
|
||||
" Fred() { a = 0; }\n"
|
||||
" };\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"void func2()\n"
|
||||
"{\n"
|
||||
" class Fred\n"
|
||||
" {\n"
|
||||
" int b;\n"
|
||||
" Fred() { b = 0; }\n"
|
||||
" };\n"
|
||||
"}\n" );
|
||||
check("void func1()\n"
|
||||
"{\n"
|
||||
" class Fred\n"
|
||||
" {\n"
|
||||
" int a;\n"
|
||||
" Fred() { a = 0; }\n"
|
||||
" };\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"void func2()\n"
|
||||
"{\n"
|
||||
" class Fred\n"
|
||||
" {\n"
|
||||
" int b;\n"
|
||||
" Fred() { b = 0; }\n"
|
||||
" };\n"
|
||||
"}\n");
|
||||
|
||||
std::string err( errout.str() );
|
||||
ASSERT_EQUALS( std::string(""), err );
|
||||
std::string err(errout.str());
|
||||
ASSERT_EQUALS(std::string(""), err);
|
||||
}
|
||||
|
||||
void initvar_chained_assign()
|
||||
{
|
||||
// Bug 2270433 - Uninitialized variable false positive on chained assigns
|
||||
|
||||
check( "class c\n"
|
||||
"{\n"
|
||||
" c();\n"
|
||||
"\n"
|
||||
" int m_iMyInt1;\n"
|
||||
" int m_iMyInt2;\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"c::c()\n"
|
||||
"{\n"
|
||||
" m_iMyInt1 = m_iMyInt2 = 0;\n"
|
||||
"}\n" );
|
||||
check("class c\n"
|
||||
"{\n"
|
||||
" c();\n"
|
||||
"\n"
|
||||
" int m_iMyInt1;\n"
|
||||
" int m_iMyInt2;\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"c::c()\n"
|
||||
"{\n"
|
||||
" m_iMyInt1 = m_iMyInt2 = 0;\n"
|
||||
"}\n");
|
||||
|
||||
std::string err( errout.str() );
|
||||
ASSERT_EQUALS( std::string(""), err );
|
||||
std::string err(errout.str());
|
||||
ASSERT_EQUALS(std::string(""), err);
|
||||
}
|
||||
|
||||
|
||||
void initvar_2constructors()
|
||||
{
|
||||
check( "class c\n"
|
||||
"{\n"
|
||||
" c();\n"
|
||||
" c(bool b);"
|
||||
"\n"
|
||||
" void InitInt();\n"
|
||||
"\n"
|
||||
" int m_iMyInt;\n"
|
||||
" int m_bMyBool;\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"c::c()\n"
|
||||
"{\n"
|
||||
" m_bMyBool = false;\n"
|
||||
" InitInt();"
|
||||
"}\n"
|
||||
"\n"
|
||||
"c::c(bool b)\n"
|
||||
"{\n"
|
||||
" m_bMyBool = b;\n"
|
||||
" InitInt();\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"void c::InitInt()\n"
|
||||
"{\n"
|
||||
" m_iMyInt = 0;\n"
|
||||
"}\n" );
|
||||
check("class c\n"
|
||||
"{\n"
|
||||
" c();\n"
|
||||
" c(bool b);"
|
||||
"\n"
|
||||
" void InitInt();\n"
|
||||
"\n"
|
||||
" int m_iMyInt;\n"
|
||||
" int m_bMyBool;\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"c::c()\n"
|
||||
"{\n"
|
||||
" m_bMyBool = false;\n"
|
||||
" InitInt();"
|
||||
"}\n"
|
||||
"\n"
|
||||
"c::c(bool b)\n"
|
||||
"{\n"
|
||||
" m_bMyBool = b;\n"
|
||||
" InitInt();\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"void c::InitInt()\n"
|
||||
"{\n"
|
||||
" m_iMyInt = 0;\n"
|
||||
"}\n");
|
||||
|
||||
std::string err( errout.str() );
|
||||
ASSERT_EQUALS( std::string(""), err );
|
||||
std::string err(errout.str());
|
||||
ASSERT_EQUALS(std::string(""), err);
|
||||
}
|
||||
|
||||
|
||||
void initvar_private_constructor()
|
||||
{
|
||||
check( "class Fred\n"
|
||||
"{\n"
|
||||
"private:\n"
|
||||
" int var;\n"
|
||||
" Fred();\n"
|
||||
"};\n"
|
||||
"Fred::Fred()\n"
|
||||
"{ }" );
|
||||
ASSERT_EQUALS( std::string(""), errout.str() );
|
||||
check("class Fred\n"
|
||||
"{\n"
|
||||
"private:\n"
|
||||
" int var;\n"
|
||||
" Fred();\n"
|
||||
"};\n"
|
||||
"Fred::Fred()\n"
|
||||
"{ }");
|
||||
ASSERT_EQUALS(std::string(""), errout.str());
|
||||
}
|
||||
|
||||
void initvar_destructor()
|
||||
{
|
||||
check( "class Fred\n"
|
||||
"{\n"
|
||||
"private:\n"
|
||||
" int var;\n"
|
||||
"public:\n"
|
||||
" Fred() : var(0) {}\n"
|
||||
" ~Fred() {}\n"
|
||||
"};\n" );
|
||||
ASSERT_EQUALS( std::string(""), errout.str() );
|
||||
}
|
||||
void initvar_destructor()
|
||||
{
|
||||
check("class Fred\n"
|
||||
"{\n"
|
||||
"private:\n"
|
||||
" int var;\n"
|
||||
"public:\n"
|
||||
" Fred() : var(0) {}\n"
|
||||
" ~Fred() {}\n"
|
||||
"};\n");
|
||||
ASSERT_EQUALS(std::string(""), errout.str());
|
||||
}
|
||||
};
|
||||
|
||||
REGISTER_TEST( TestConstructors )
|
||||
REGISTER_TEST(TestConstructors)
|
||||
|
|
128
testdivision.cpp
128
testdivision.cpp
|
@ -37,114 +37,114 @@ public:
|
|||
{ }
|
||||
|
||||
private:
|
||||
void check( const char code[] )
|
||||
void check(const char code[])
|
||||
{
|
||||
// Tokenize..
|
||||
Tokenizer tokenizer;
|
||||
std::istringstream istr(code);
|
||||
tokenizer.tokenize( istr, "test.cpp" );
|
||||
tokenizer.tokenize(istr, "test.cpp");
|
||||
|
||||
// Clear the error buffer..
|
||||
errout.str("");
|
||||
|
||||
// Check for unsigned divisions..
|
||||
CheckOther checkOther( &tokenizer, this );
|
||||
CheckOther checkOther(&tokenizer, this);
|
||||
checkOther.CheckUnsignedDivision();
|
||||
}
|
||||
|
||||
void run()
|
||||
{
|
||||
TEST_CASE( division1 );
|
||||
TEST_CASE( division2 );
|
||||
TEST_CASE( division3 );
|
||||
TEST_CASE( division4 );
|
||||
TEST_CASE( division5 );
|
||||
TEST_CASE( division6 );
|
||||
TEST_CASE( division7 );
|
||||
TEST_CASE(division1);
|
||||
TEST_CASE(division2);
|
||||
TEST_CASE(division3);
|
||||
TEST_CASE(division4);
|
||||
TEST_CASE(division5);
|
||||
TEST_CASE(division6);
|
||||
TEST_CASE(division7);
|
||||
}
|
||||
|
||||
void division1()
|
||||
{
|
||||
check( "void f()\n"
|
||||
"{\n"
|
||||
" int ivar = -2;\n"
|
||||
" unsigned int uvar = 2;\n"
|
||||
" return ivar / uvar;\n"
|
||||
"}\n" );
|
||||
ASSERT_EQUALS( std::string("[test.cpp:5]: Warning: Division with signed and unsigned operators\n"), errout.str() );
|
||||
check("void f()\n"
|
||||
"{\n"
|
||||
" int ivar = -2;\n"
|
||||
" unsigned int uvar = 2;\n"
|
||||
" return ivar / uvar;\n"
|
||||
"}\n");
|
||||
ASSERT_EQUALS(std::string("[test.cpp:5]: Warning: Division with signed and unsigned operators\n"), errout.str());
|
||||
}
|
||||
|
||||
void division2()
|
||||
{
|
||||
check( "void f()\n"
|
||||
"{\n"
|
||||
" int ivar = -2;\n"
|
||||
" unsigned int uvar = 2;\n"
|
||||
" return uvar / ivar;\n"
|
||||
"}\n" );
|
||||
ASSERT_EQUALS( std::string("[test.cpp:5]: Warning: Division with signed and unsigned operators\n"), errout.str() );
|
||||
check("void f()\n"
|
||||
"{\n"
|
||||
" int ivar = -2;\n"
|
||||
" unsigned int uvar = 2;\n"
|
||||
" return uvar / ivar;\n"
|
||||
"}\n");
|
||||
ASSERT_EQUALS(std::string("[test.cpp:5]: Warning: Division with signed and unsigned operators\n"), errout.str());
|
||||
}
|
||||
|
||||
void division3()
|
||||
{
|
||||
check( "typedef int s32;\n"
|
||||
"typedef unsigned int u32;\n"
|
||||
"void f()\n"
|
||||
"{\n"
|
||||
" s32 ivar = -2;\n"
|
||||
" u32 uvar = 2;\n"
|
||||
" return uvar / ivar;\n"
|
||||
"}\n" );
|
||||
ASSERT_EQUALS( std::string("[test.cpp:7]: Warning: Division with signed and unsigned operators\n"), errout.str() );
|
||||
check("typedef int s32;\n"
|
||||
"typedef unsigned int u32;\n"
|
||||
"void f()\n"
|
||||
"{\n"
|
||||
" s32 ivar = -2;\n"
|
||||
" u32 uvar = 2;\n"
|
||||
" return uvar / ivar;\n"
|
||||
"}\n");
|
||||
ASSERT_EQUALS(std::string("[test.cpp:7]: Warning: Division with signed and unsigned operators\n"), errout.str());
|
||||
}
|
||||
|
||||
void division4()
|
||||
{
|
||||
check( "void f1()\n"
|
||||
"{\n"
|
||||
" int i1;\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"void f2(unsigned int i1)\n"
|
||||
"{\n"
|
||||
" unsigned int i2;\n"
|
||||
" result = i2 / i1;\n"
|
||||
);
|
||||
ASSERT_EQUALS( std::string(""), errout.str() );
|
||||
check("void f1()\n"
|
||||
"{\n"
|
||||
" int i1;\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"void f2(unsigned int i1)\n"
|
||||
"{\n"
|
||||
" unsigned int i2;\n"
|
||||
" result = i2 / i1;\n"
|
||||
);
|
||||
ASSERT_EQUALS(std::string(""), errout.str());
|
||||
}
|
||||
|
||||
void division5()
|
||||
{
|
||||
check( "#define USER_HASH (16)\n"
|
||||
"void foo()\n"
|
||||
"{\n"
|
||||
" unsigned int val = 32;\n"
|
||||
" val = val / USER_HASH;\n"
|
||||
);
|
||||
ASSERT_EQUALS( std::string(""), errout.str() );
|
||||
check("#define USER_HASH (16)\n"
|
||||
"void foo()\n"
|
||||
"{\n"
|
||||
" unsigned int val = 32;\n"
|
||||
" val = val / USER_HASH;\n"
|
||||
);
|
||||
ASSERT_EQUALS(std::string(""), errout.str());
|
||||
}
|
||||
|
||||
void division6()
|
||||
{
|
||||
check( "void foo()\n"
|
||||
"{\n"
|
||||
" unsigned int val = 32;\n"
|
||||
" int i = val / -2;\n"
|
||||
);
|
||||
ASSERT_EQUALS( std::string("[test.cpp:4]: Unsigned division. The result will be wrong.\n"), errout.str() );
|
||||
check("void foo()\n"
|
||||
"{\n"
|
||||
" unsigned int val = 32;\n"
|
||||
" int i = val / -2;\n"
|
||||
);
|
||||
ASSERT_EQUALS(std::string("[test.cpp:4]: Unsigned division. The result will be wrong.\n"), errout.str());
|
||||
}
|
||||
|
||||
void division7()
|
||||
{
|
||||
check( "void foo()\n"
|
||||
"{\n"
|
||||
" unsigned int val = 32;\n"
|
||||
" int i = -96 / val;\n"
|
||||
);
|
||||
ASSERT_EQUALS( std::string("[test.cpp:4]: Unsigned division. The result will be wrong.\n"), errout.str() );
|
||||
check("void foo()\n"
|
||||
"{\n"
|
||||
" unsigned int val = 32;\n"
|
||||
" int i = -96 / val;\n"
|
||||
);
|
||||
ASSERT_EQUALS(std::string("[test.cpp:4]: Unsigned division. The result will be wrong.\n"), errout.str());
|
||||
}
|
||||
};
|
||||
|
||||
REGISTER_TEST( TestDivision )
|
||||
REGISTER_TEST(TestDivision)
|
||||
|
||||
|
||||
|
|
|
@ -30,24 +30,24 @@ private:
|
|||
|
||||
void run()
|
||||
{
|
||||
TEST_CASE( simplify_path );
|
||||
TEST_CASE(simplify_path);
|
||||
}
|
||||
|
||||
void simplify_path()
|
||||
{
|
||||
ASSERT_EQUALS( std::string( "index.h" ), FileLister::simplifyPath( "index.h" ) );
|
||||
ASSERT_EQUALS( std::string( "/index.h" ), FileLister::simplifyPath( "/index.h" ) );
|
||||
ASSERT_EQUALS( std::string( "/path/" ), FileLister::simplifyPath( "/path/" ) );
|
||||
ASSERT_EQUALS( std::string( "/" ), FileLister::simplifyPath( "/" ) );
|
||||
ASSERT_EQUALS( std::string( "./index.h" ), FileLister::simplifyPath( "./index.h" ) );
|
||||
ASSERT_EQUALS( std::string( "../index.h" ), FileLister::simplifyPath( "../index.h" ) );
|
||||
ASSERT_EQUALS( std::string( "/index.h" ), FileLister::simplifyPath( "/path/../index.h" ) );
|
||||
ASSERT_EQUALS( std::string( "/index.h" ), FileLister::simplifyPath( "/path/../other/../index.h" ) );
|
||||
ASSERT_EQUALS( std::string( "/index.h" ), FileLister::simplifyPath( "/path/../other///././../index.h" ) );
|
||||
ASSERT_EQUALS( std::string( "../path/index.h" ), FileLister::simplifyPath( "../path/other/../index.h" ) );
|
||||
ASSERT_EQUALS(std::string("index.h"), FileLister::simplifyPath("index.h"));
|
||||
ASSERT_EQUALS(std::string("/index.h"), FileLister::simplifyPath("/index.h"));
|
||||
ASSERT_EQUALS(std::string("/path/"), FileLister::simplifyPath("/path/"));
|
||||
ASSERT_EQUALS(std::string("/"), FileLister::simplifyPath("/"));
|
||||
ASSERT_EQUALS(std::string("./index.h"), FileLister::simplifyPath("./index.h"));
|
||||
ASSERT_EQUALS(std::string("../index.h"), FileLister::simplifyPath("../index.h"));
|
||||
ASSERT_EQUALS(std::string("/index.h"), FileLister::simplifyPath("/path/../index.h"));
|
||||
ASSERT_EQUALS(std::string("/index.h"), FileLister::simplifyPath("/path/../other/../index.h"));
|
||||
ASSERT_EQUALS(std::string("/index.h"), FileLister::simplifyPath("/path/../other///././../index.h"));
|
||||
ASSERT_EQUALS(std::string("../path/index.h"), FileLister::simplifyPath("../path/other/../index.h"));
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
|
||||
REGISTER_TEST( TestFileLister )
|
||||
REGISTER_TEST(TestFileLister)
|
||||
|
|
|
@ -36,70 +36,70 @@ private:
|
|||
|
||||
void run()
|
||||
{
|
||||
TEST_CASE( incondition );
|
||||
TEST_CASE( return1 );
|
||||
TEST_CASE( callback1 );
|
||||
TEST_CASE( else1 );
|
||||
TEST_CASE(incondition);
|
||||
TEST_CASE(return1);
|
||||
TEST_CASE(callback1);
|
||||
TEST_CASE(else1);
|
||||
}
|
||||
|
||||
void check( const char code[] )
|
||||
void check(const char code[])
|
||||
{
|
||||
// Tokenize..
|
||||
Tokenizer tokenizer;
|
||||
std::istringstream istr(code);
|
||||
tokenizer.tokenize( istr, "test.cpp" );
|
||||
tokenizer.tokenize(istr, "test.cpp");
|
||||
|
||||
// Clear the error buffer..
|
||||
errout.str("");
|
||||
|
||||
// Check for unused functions..
|
||||
CheckFunctionUsage checkFunctionUsage(this);
|
||||
checkFunctionUsage.parseTokens( tokenizer );
|
||||
checkFunctionUsage.parseTokens(tokenizer);
|
||||
checkFunctionUsage.check();
|
||||
}
|
||||
|
||||
void incondition()
|
||||
{
|
||||
check( "int f1()\n"
|
||||
"{\n"
|
||||
" if (f1())\n"
|
||||
" { }\n"
|
||||
"}\n" );
|
||||
std::string err( errout.str() );
|
||||
ASSERT_EQUALS( std::string(""), errout.str() );
|
||||
check("int f1()\n"
|
||||
"{\n"
|
||||
" if (f1())\n"
|
||||
" { }\n"
|
||||
"}\n");
|
||||
std::string err(errout.str());
|
||||
ASSERT_EQUALS(std::string(""), errout.str());
|
||||
}
|
||||
|
||||
void return1()
|
||||
{
|
||||
check( "int f1()\n"
|
||||
"{\n"
|
||||
" return f1();\n"
|
||||
"}\n" );
|
||||
std::string err( errout.str() );
|
||||
ASSERT_EQUALS( std::string(""), errout.str() );
|
||||
check("int f1()\n"
|
||||
"{\n"
|
||||
" return f1();\n"
|
||||
"}\n");
|
||||
std::string err(errout.str());
|
||||
ASSERT_EQUALS(std::string(""), errout.str());
|
||||
}
|
||||
|
||||
void callback1()
|
||||
{
|
||||
check( "void f1()\n"
|
||||
"{\n"
|
||||
" void (*f)() = cond ? f1 : NULL;\n"
|
||||
"}\n" );
|
||||
std::string err( errout.str() );
|
||||
ASSERT_EQUALS( std::string(""), errout.str() );
|
||||
check("void f1()\n"
|
||||
"{\n"
|
||||
" void (*f)() = cond ? f1 : NULL;\n"
|
||||
"}\n");
|
||||
std::string err(errout.str());
|
||||
ASSERT_EQUALS(std::string(""), errout.str());
|
||||
}
|
||||
|
||||
void else1()
|
||||
{
|
||||
check( "void f1()\n"
|
||||
"{\n"
|
||||
" if (cond) ;\n"
|
||||
" else f1();\n"
|
||||
"}\n" );
|
||||
std::string err( errout.str() );
|
||||
ASSERT_EQUALS( std::string(""), errout.str() );
|
||||
check("void f1()\n"
|
||||
"{\n"
|
||||
" if (cond) ;\n"
|
||||
" else f1();\n"
|
||||
"}\n");
|
||||
std::string err(errout.str());
|
||||
ASSERT_EQUALS(std::string(""), errout.str());
|
||||
}
|
||||
};
|
||||
|
||||
REGISTER_TEST( TestFunctionUsage )
|
||||
REGISTER_TEST(TestFunctionUsage)
|
||||
|
||||
|
|
|
@ -36,56 +36,56 @@ public:
|
|||
{ }
|
||||
|
||||
private:
|
||||
void check( const char code[] )
|
||||
void check(const char code[])
|
||||
{
|
||||
// Tokenize..
|
||||
Tokenizer tokenizer;
|
||||
std::istringstream istr(code);
|
||||
tokenizer.tokenize( istr, "test.cpp" );
|
||||
tokenizer.tokenize(istr, "test.cpp");
|
||||
tokenizer.simplifyTokenList();
|
||||
|
||||
// Clear the error buffer..
|
||||
errout.str("");
|
||||
|
||||
// Check for unused variables..
|
||||
CheckOther checkOther( &tokenizer, this );
|
||||
CheckOther checkOther(&tokenizer, this);
|
||||
checkOther.CheckIncompleteStatement();
|
||||
}
|
||||
|
||||
void run()
|
||||
{
|
||||
TEST_CASE( test1 );
|
||||
TEST_CASE( test2 );
|
||||
TEST_CASE(test1);
|
||||
TEST_CASE(test2);
|
||||
}
|
||||
|
||||
void test1()
|
||||
{
|
||||
check( "void foo()\n"
|
||||
"{\n"
|
||||
" const char def[] =\n"
|
||||
"#ifdef ABC\n"
|
||||
" \"abc\";\n"
|
||||
"#else\n"
|
||||
" \"not abc\";\n"
|
||||
"#endif\n"
|
||||
"}\n" );
|
||||
check("void foo()\n"
|
||||
"{\n"
|
||||
" const char def[] =\n"
|
||||
"#ifdef ABC\n"
|
||||
" \"abc\";\n"
|
||||
"#else\n"
|
||||
" \"not abc\";\n"
|
||||
"#endif\n"
|
||||
"}\n");
|
||||
|
||||
ASSERT_EQUALS( std::string(""), errout.str() );
|
||||
ASSERT_EQUALS(std::string(""), errout.str());
|
||||
}
|
||||
|
||||
void test2()
|
||||
{
|
||||
// Todo: remove the ';' before the string
|
||||
|
||||
check( "void foo()\n"
|
||||
"{\n"
|
||||
" ;\"abc\";\n"
|
||||
"}\n" );
|
||||
check("void foo()\n"
|
||||
"{\n"
|
||||
" ;\"abc\";\n"
|
||||
"}\n");
|
||||
|
||||
ASSERT_EQUALS( std::string("[test.cpp:3]: Redundant code: Found a statement that begins with string constant\n"), errout.str() );
|
||||
ASSERT_EQUALS(std::string("[test.cpp:3]: Redundant code: Found a statement that begins with string constant\n"), errout.str());
|
||||
}
|
||||
};
|
||||
|
||||
REGISTER_TEST( TestIncompleteStatement )
|
||||
REGISTER_TEST(TestIncompleteStatement)
|
||||
|
||||
|
||||
|
|
1734
testmemleak.cpp
1734
testmemleak.cpp
File diff suppressed because it is too large
Load Diff
|
@ -36,7 +36,7 @@ private:
|
|||
|
||||
void run()
|
||||
{
|
||||
TEST_CASE( param1 );
|
||||
TEST_CASE(param1);
|
||||
}
|
||||
|
||||
void param1()
|
||||
|
@ -49,7 +49,7 @@ private:
|
|||
// Tokenize..
|
||||
Tokenizer tokenizer;
|
||||
std::istringstream istr(code);
|
||||
tokenizer.tokenize( istr, "test.cpp" );
|
||||
tokenizer.tokenize(istr, "test.cpp");
|
||||
tokenizer.simplifyTokenList();
|
||||
|
||||
// Clear the error log
|
||||
|
@ -57,16 +57,16 @@ private:
|
|||
|
||||
// Check..
|
||||
Settings settings;
|
||||
CheckMemoryLeakClass checkMemoryLeak( &tokenizer, settings, this );
|
||||
CheckMemoryLeakClass checkMemoryLeak(&tokenizer, settings, this);
|
||||
Token *tok = checkMemoryLeak.functionParameterCode(tokenizer.tokens(), 1);
|
||||
|
||||
// Compare tokens..
|
||||
std::string s;
|
||||
for ( const Token *tok2 = tok; tok2; tok2 = tok2->next() )
|
||||
for (const Token *tok2 = tok; tok2; tok2 = tok2->next())
|
||||
s += tok2->str() + " ";
|
||||
ASSERT_EQUALS( "; } ", s );
|
||||
ASSERT_EQUALS("; } ", s);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
REGISTER_TEST( TestMemleakMultiPass )
|
||||
REGISTER_TEST(TestMemleakMultiPass)
|
||||
|
|
|
@ -34,58 +34,58 @@ private:
|
|||
|
||||
void run()
|
||||
{
|
||||
TEST_CASE( delete1 );
|
||||
TEST_CASE(delete1);
|
||||
|
||||
TEST_CASE( delete2 );
|
||||
TEST_CASE(delete2);
|
||||
}
|
||||
|
||||
void check( const char code[] )
|
||||
void check(const char code[])
|
||||
{
|
||||
// Tokenize..
|
||||
Tokenizer tokenizer;
|
||||
std::istringstream istr(code);
|
||||
tokenizer.tokenize( istr, "test.cpp" );
|
||||
tokenizer.tokenize(istr, "test.cpp");
|
||||
|
||||
// Clear the error buffer..
|
||||
errout.str("");
|
||||
|
||||
// Check for redundant code..
|
||||
CheckOther checkOther( &tokenizer, this );
|
||||
CheckOther checkOther(&tokenizer, this);
|
||||
checkOther.WarningRedundantCode();
|
||||
}
|
||||
|
||||
void delete1()
|
||||
{
|
||||
check( "void foo()\n"
|
||||
"{\n"
|
||||
" if (p)\n"
|
||||
" {\n"
|
||||
" delete p;\n"
|
||||
" p = 0;\n"
|
||||
" }\n"
|
||||
"}\n" );
|
||||
ASSERT_EQUALS( std::string(""), errout.str() );
|
||||
check("void foo()\n"
|
||||
"{\n"
|
||||
" if (p)\n"
|
||||
" {\n"
|
||||
" delete p;\n"
|
||||
" p = 0;\n"
|
||||
" }\n"
|
||||
"}\n");
|
||||
ASSERT_EQUALS(std::string(""), errout.str());
|
||||
}
|
||||
|
||||
void delete2()
|
||||
{
|
||||
check( "void foo()\n"
|
||||
"{\n"
|
||||
" if (p)\n"
|
||||
" {\n"
|
||||
" delete p;\n"
|
||||
" }\n"
|
||||
"}\n" );
|
||||
ASSERT_EQUALS( std::string("[test.cpp:3]: Redundant condition. It is safe to deallocate a NULL pointer\n"), errout.str() );
|
||||
check("void foo()\n"
|
||||
"{\n"
|
||||
" if (p)\n"
|
||||
" {\n"
|
||||
" delete p;\n"
|
||||
" }\n"
|
||||
"}\n");
|
||||
ASSERT_EQUALS(std::string("[test.cpp:3]: Redundant condition. It is safe to deallocate a NULL pointer\n"), errout.str());
|
||||
|
||||
check( "void foo()\n"
|
||||
"{\n"
|
||||
" if (p)\n"
|
||||
" delete p;\n"
|
||||
"}\n" );
|
||||
ASSERT_EQUALS( std::string("[test.cpp:3]: Redundant condition. It is safe to deallocate a NULL pointer\n"), errout.str() );
|
||||
check("void foo()\n"
|
||||
"{\n"
|
||||
" if (p)\n"
|
||||
" delete p;\n"
|
||||
"}\n");
|
||||
ASSERT_EQUALS(std::string("[test.cpp:3]: Redundant condition. It is safe to deallocate a NULL pointer\n"), errout.str());
|
||||
}
|
||||
};
|
||||
|
||||
REGISTER_TEST( TestOther )
|
||||
REGISTER_TEST(TestOther)
|
||||
|
||||
|
|
|
@ -42,31 +42,31 @@ private:
|
|||
TEST_CASE(readCode);
|
||||
|
||||
// The bug that started the whole work with the new preprocessor
|
||||
TEST_CASE( Bug2190219 );
|
||||
TEST_CASE(Bug2190219);
|
||||
|
||||
TEST_CASE( test1 );
|
||||
TEST_CASE( test2 );
|
||||
TEST_CASE( test3 );
|
||||
TEST_CASE( test4 );
|
||||
TEST_CASE( test5 );
|
||||
TEST_CASE(test1);
|
||||
TEST_CASE(test2);
|
||||
TEST_CASE(test3);
|
||||
TEST_CASE(test4);
|
||||
TEST_CASE(test5);
|
||||
|
||||
TEST_CASE( comments1 );
|
||||
TEST_CASE(comments1);
|
||||
|
||||
TEST_CASE( if0 );
|
||||
TEST_CASE( if1 );
|
||||
TEST_CASE(if0);
|
||||
TEST_CASE(if1);
|
||||
|
||||
TEST_CASE( elif );
|
||||
TEST_CASE(elif);
|
||||
|
||||
TEST_CASE( include1 );
|
||||
TEST_CASE(include1);
|
||||
|
||||
TEST_CASE( if_cond1 );
|
||||
TEST_CASE(if_cond1);
|
||||
|
||||
TEST_CASE( multiline );
|
||||
TEST_CASE(multiline);
|
||||
|
||||
TEST_CASE( if_defined ); // "#if defined(AAA)" => "#ifdef AAA"
|
||||
TEST_CASE(if_defined); // "#if defined(AAA)" => "#ifdef AAA"
|
||||
|
||||
// Macros..
|
||||
TEST_CASE( macro1 );
|
||||
TEST_CASE(macro1);
|
||||
}
|
||||
|
||||
|
||||
|
@ -76,29 +76,29 @@ private:
|
|||
" #aa\t /* remove this */\tb \r\n";
|
||||
Preprocessor p;
|
||||
std::istringstream istr(code);
|
||||
std::string codestr( p.read(istr) );
|
||||
ASSERT_EQUALS( "a \n#aa b \n", codestr );
|
||||
std::string codestr(p.read(istr));
|
||||
ASSERT_EQUALS("a \n#aa b \n", codestr);
|
||||
}
|
||||
|
||||
|
||||
bool cmpmaps(const std::map<std::string, std::string> &m1, const std::map<std::string, std::string> &m2)
|
||||
{
|
||||
// Begin by checking the sizes
|
||||
if ( m1.size() != m2.size() )
|
||||
if (m1.size() != m2.size())
|
||||
return false;
|
||||
|
||||
// Check each item in the maps..
|
||||
for ( std::map<std::string,std::string>::const_iterator it1 = m1.begin(); it1 != m1.end(); ++it1 )
|
||||
for (std::map<std::string, std::string>::const_iterator it1 = m1.begin(); it1 != m1.end(); ++it1)
|
||||
{
|
||||
std::string s1 = it1->first;
|
||||
std::map<std::string,std::string>::const_iterator it2 = m2.find(s1);
|
||||
if ( it2 == m2.end() )
|
||||
std::map<std::string, std::string>::const_iterator it2 = m2.find(s1);
|
||||
if (it2 == m2.end())
|
||||
return false;
|
||||
else
|
||||
{
|
||||
std::string s1 = it1->second;
|
||||
std::string s2 = it2->second;
|
||||
if ( s1 != s2 )
|
||||
if (s1 != s2)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -143,28 +143,28 @@ private:
|
|||
"}\n";
|
||||
|
||||
expected["__cplusplus"] = "int main()\n"
|
||||
"{\n"
|
||||
"\n"
|
||||
"int* flags = new int[10];\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"delete [] flags;\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"}\n";
|
||||
"{\n"
|
||||
"\n"
|
||||
"int* flags = new int[10];\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"delete [] flags;\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"}\n";
|
||||
|
||||
// Preprocess => actual result..
|
||||
std::istringstream istr(filedata);
|
||||
std::map<std::string, std::string> actual;
|
||||
Preprocessor preprocessor;
|
||||
preprocessor.preprocess( istr, actual );
|
||||
preprocessor.preprocess(istr, actual);
|
||||
|
||||
// Compare results..
|
||||
ASSERT_EQUALS( true, cmpmaps(actual, expected));
|
||||
ASSERT_EQUALS(true, cmpmaps(actual, expected));
|
||||
}
|
||||
|
||||
|
||||
|
@ -185,10 +185,10 @@ private:
|
|||
std::istringstream istr(filedata);
|
||||
std::map<std::string, std::string> actual;
|
||||
Preprocessor preprocessor;
|
||||
preprocessor.preprocess( istr, actual );
|
||||
preprocessor.preprocess(istr, actual);
|
||||
|
||||
// Compare results..
|
||||
ASSERT_EQUALS( true, cmpmaps(actual, expected));
|
||||
ASSERT_EQUALS(true, cmpmaps(actual, expected));
|
||||
}
|
||||
|
||||
void test2()
|
||||
|
@ -208,10 +208,10 @@ private:
|
|||
std::istringstream istr(filedata);
|
||||
std::map<std::string, std::string> actual;
|
||||
Preprocessor preprocessor;
|
||||
preprocessor.preprocess( istr, actual );
|
||||
preprocessor.preprocess(istr, actual);
|
||||
|
||||
// Compare results..
|
||||
ASSERT_EQUALS( true, cmpmaps(actual, expected));
|
||||
ASSERT_EQUALS(true, cmpmaps(actual, expected));
|
||||
}
|
||||
|
||||
void test3()
|
||||
|
@ -234,10 +234,10 @@ private:
|
|||
std::istringstream istr(filedata);
|
||||
std::map<std::string, std::string> actual;
|
||||
Preprocessor preprocessor;
|
||||
preprocessor.preprocess( istr, actual );
|
||||
preprocessor.preprocess(istr, actual);
|
||||
|
||||
// Compare results..
|
||||
ASSERT_EQUALS( true, cmpmaps(actual, expected));
|
||||
ASSERT_EQUALS(true, cmpmaps(actual, expected));
|
||||
}
|
||||
|
||||
void test4()
|
||||
|
@ -258,10 +258,10 @@ private:
|
|||
std::istringstream istr(filedata);
|
||||
std::map<std::string, std::string> actual;
|
||||
Preprocessor preprocessor;
|
||||
preprocessor.preprocess( istr, actual );
|
||||
preprocessor.preprocess(istr, actual);
|
||||
|
||||
// Compare results..
|
||||
ASSERT_EQUALS( true, cmpmaps(actual, expected));
|
||||
ASSERT_EQUALS(true, cmpmaps(actual, expected));
|
||||
}
|
||||
|
||||
void test5()
|
||||
|
@ -285,10 +285,10 @@ private:
|
|||
std::istringstream istr(filedata);
|
||||
std::map<std::string, std::string> actual;
|
||||
Preprocessor preprocessor;
|
||||
preprocessor.preprocess( istr, actual );
|
||||
preprocessor.preprocess(istr, actual);
|
||||
|
||||
// Compare results..
|
||||
ASSERT_EQUALS( true, cmpmaps(actual, expected));
|
||||
ASSERT_EQUALS(true, cmpmaps(actual, expected));
|
||||
}
|
||||
|
||||
|
||||
|
@ -308,10 +308,10 @@ private:
|
|||
std::istringstream istr(filedata);
|
||||
std::map<std::string, std::string> actual;
|
||||
Preprocessor preprocessor;
|
||||
preprocessor.preprocess( istr, actual );
|
||||
preprocessor.preprocess(istr, actual);
|
||||
|
||||
// Compare results..
|
||||
ASSERT_EQUALS( true, cmpmaps(actual, expected));
|
||||
ASSERT_EQUALS(true, cmpmaps(actual, expected));
|
||||
}
|
||||
|
||||
|
||||
|
@ -331,10 +331,10 @@ private:
|
|||
std::istringstream istr(filedata);
|
||||
std::map<std::string, std::string> actual;
|
||||
Preprocessor preprocessor;
|
||||
preprocessor.preprocess( istr, actual );
|
||||
preprocessor.preprocess(istr, actual);
|
||||
|
||||
// Compare results..
|
||||
ASSERT_EQUALS( true, cmpmaps(actual, expected));
|
||||
ASSERT_EQUALS(true, cmpmaps(actual, expected));
|
||||
}
|
||||
|
||||
void if1()
|
||||
|
@ -351,10 +351,10 @@ private:
|
|||
std::istringstream istr(filedata);
|
||||
std::map<std::string, std::string> actual;
|
||||
Preprocessor preprocessor;
|
||||
preprocessor.preprocess( istr, actual );
|
||||
preprocessor.preprocess(istr, actual);
|
||||
|
||||
// Compare results..
|
||||
ASSERT_EQUALS( true, cmpmaps(actual, expected));
|
||||
ASSERT_EQUALS(true, cmpmaps(actual, expected));
|
||||
}
|
||||
|
||||
|
||||
|
@ -376,10 +376,10 @@ private:
|
|||
std::istringstream istr(filedata);
|
||||
std::map<std::string, std::string> actual;
|
||||
Preprocessor preprocessor;
|
||||
preprocessor.preprocess( istr, actual );
|
||||
preprocessor.preprocess(istr, actual);
|
||||
|
||||
// Compare results..
|
||||
ASSERT_EQUALS( true, cmpmaps(actual, expected));
|
||||
ASSERT_EQUALS(true, cmpmaps(actual, expected));
|
||||
}
|
||||
|
||||
|
||||
|
@ -396,10 +396,10 @@ private:
|
|||
std::istringstream istr(filedata);
|
||||
std::map<std::string, std::string> actual;
|
||||
Preprocessor preprocessor;
|
||||
preprocessor.preprocess( istr, actual );
|
||||
preprocessor.preprocess(istr, actual);
|
||||
|
||||
// Compare results..
|
||||
ASSERT_EQUALS( true, cmpmaps(actual, expected));
|
||||
ASSERT_EQUALS(true, cmpmaps(actual, expected));
|
||||
}
|
||||
|
||||
|
||||
|
@ -421,10 +421,10 @@ private:
|
|||
std::istringstream istr(filedata);
|
||||
std::map<std::string, std::string> actual;
|
||||
Preprocessor preprocessor;
|
||||
preprocessor.preprocess( istr, actual );
|
||||
preprocessor.preprocess(istr, actual);
|
||||
|
||||
// Compare results..
|
||||
ASSERT_EQUALS( true, cmpmaps(actual, expected));
|
||||
ASSERT_EQUALS(true, cmpmaps(actual, expected));
|
||||
}
|
||||
|
||||
|
||||
|
@ -441,10 +441,10 @@ private:
|
|||
std::istringstream istr(filedata);
|
||||
std::map<std::string, std::string> actual;
|
||||
Preprocessor preprocessor;
|
||||
preprocessor.preprocess( istr, actual );
|
||||
preprocessor.preprocess(istr, actual);
|
||||
|
||||
// Compare results..
|
||||
ASSERT_EQUALS( true, cmpmaps(actual, expected));
|
||||
ASSERT_EQUALS(true, cmpmaps(actual, expected));
|
||||
}
|
||||
|
||||
|
||||
|
@ -454,10 +454,10 @@ private:
|
|||
"#endif\n";
|
||||
|
||||
// Expected result..
|
||||
std::string expected( "#ifdef AAA\n#endif\n" );
|
||||
std::string expected("#ifdef AAA\n#endif\n");
|
||||
|
||||
// Compare result..
|
||||
ASSERT_EQUALS( expected, Preprocessor::replaceIfDefined(filedata) );
|
||||
ASSERT_EQUALS(expected, Preprocessor::replaceIfDefined(filedata));
|
||||
}
|
||||
|
||||
|
||||
|
@ -467,7 +467,7 @@ private:
|
|||
"AAA(5);\n";
|
||||
|
||||
// Expected result..
|
||||
std::string expected( "\nf(5);\n" );
|
||||
std::string expected("\nf(5);\n");
|
||||
|
||||
// Compare result..
|
||||
//ASSERT_EQUALS( expected, Preprocessor::expandMacros(filedata) );
|
||||
|
@ -476,4 +476,4 @@ private:
|
|||
|
||||
};
|
||||
|
||||
REGISTER_TEST( TestPreprocessor )
|
||||
REGISTER_TEST(TestPreprocessor)
|
||||
|
|
|
@ -37,51 +37,51 @@ public:
|
|||
{ }
|
||||
|
||||
private:
|
||||
void check( const char code[] )
|
||||
void check(const char code[])
|
||||
{
|
||||
// Tokenize..
|
||||
Tokenizer tokenizer;
|
||||
std::istringstream istr(code);
|
||||
tokenizer.tokenize( istr, "test.cpp" );
|
||||
tokenizer.tokenize(istr, "test.cpp");
|
||||
|
||||
// Clear the error buffer..
|
||||
errout.str("");
|
||||
|
||||
// Check for redundant condition..
|
||||
CheckOther checkOther( &tokenizer, this );
|
||||
CheckOther checkOther(&tokenizer, this);
|
||||
checkOther.redundantCondition2();
|
||||
}
|
||||
|
||||
void run()
|
||||
{
|
||||
TEST_CASE( remove1 );
|
||||
TEST_CASE( remove2 );
|
||||
TEST_CASE(remove1);
|
||||
TEST_CASE(remove2);
|
||||
}
|
||||
|
||||
void remove1()
|
||||
{
|
||||
check( "void f()\n"
|
||||
"{\n"
|
||||
" if (haystack.find(needle) != haystack.end())\n"
|
||||
" haystack.remove(needle);"
|
||||
"}\n" );
|
||||
ASSERT_EQUALS( std::string("[test.cpp:3]: Redundant condition found. The remove function in the STL will not do anything if element doesn't exist\n"), errout.str() );
|
||||
check("void f()\n"
|
||||
"{\n"
|
||||
" if (haystack.find(needle) != haystack.end())\n"
|
||||
" haystack.remove(needle);"
|
||||
"}\n");
|
||||
ASSERT_EQUALS(std::string("[test.cpp:3]: Redundant condition found. The remove function in the STL will not do anything if element doesn't exist\n"), errout.str());
|
||||
}
|
||||
|
||||
void remove2()
|
||||
{
|
||||
check( "void f()\n"
|
||||
"{\n"
|
||||
" if (haystack.find(needle) != haystack.end())\n"
|
||||
" {\n"
|
||||
" haystack.remove(needle);\n"
|
||||
" }\n"
|
||||
"}\n" );
|
||||
ASSERT_EQUALS( std::string("[test.cpp:3]: Redundant condition found. The remove function in the STL will not do anything if element doesn't exist\n"), errout.str() );
|
||||
check("void f()\n"
|
||||
"{\n"
|
||||
" if (haystack.find(needle) != haystack.end())\n"
|
||||
" {\n"
|
||||
" haystack.remove(needle);\n"
|
||||
" }\n"
|
||||
"}\n");
|
||||
ASSERT_EQUALS(std::string("[test.cpp:3]: Redundant condition found. The remove function in the STL will not do anything if element doesn't exist\n"), errout.str());
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
REGISTER_TEST( TestRedundantIf )
|
||||
REGISTER_TEST(TestRedundantIf)
|
||||
|
||||
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
|
||||
int main(int argc, const char *argv[])
|
||||
{
|
||||
TestFixture::runTests( (argc==2) ? argv[1] : NULL );
|
||||
TestFixture::runTests((argc == 2) ? argv[1] : NULL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -35,20 +35,20 @@ private:
|
|||
|
||||
void run()
|
||||
{
|
||||
TEST_CASE( cast0 );
|
||||
TEST_CASE( sizeof1 );
|
||||
TEST_CASE( iftruefalse );
|
||||
TEST_CASE(cast0);
|
||||
TEST_CASE(sizeof1);
|
||||
TEST_CASE(iftruefalse);
|
||||
}
|
||||
|
||||
std::string tok(const char code[])
|
||||
{
|
||||
std::istringstream istr(code);
|
||||
Tokenizer tokenizer;
|
||||
tokenizer.tokenize( istr, "test.cpp" );
|
||||
tokenizer.tokenize(istr, "test.cpp");
|
||||
tokenizer.setVarId();
|
||||
tokenizer.simplifyTokenList();
|
||||
std::string ret;
|
||||
for ( const Token *tok = tokenizer.tokens(); tok; tok = tok->next() )
|
||||
for (const Token *tok = tokenizer.tokens(); tok; tok = tok->next())
|
||||
{
|
||||
ret += tok->str() + " ";
|
||||
}
|
||||
|
@ -60,14 +60,14 @@ private:
|
|||
{
|
||||
const char code1[] = " if ( p == (char *)0 ) ";
|
||||
const char code2[] = " if ( p == 0 ) ";
|
||||
ASSERT_EQUALS( tok(code1), tok(code2) );
|
||||
ASSERT_EQUALS(tok(code1), tok(code2));
|
||||
}
|
||||
|
||||
void sizeof1()
|
||||
{
|
||||
const char code1[] = " struct ABC *abc = malloc(sizeof(*abc)); ";
|
||||
const char code2[] = " struct ABC *abc = malloc(100); ";
|
||||
ASSERT_EQUALS( tok(code1), tok(code2) );
|
||||
ASSERT_EQUALS(tok(code1), tok(code2));
|
||||
}
|
||||
|
||||
void iftruefalse()
|
||||
|
@ -75,69 +75,69 @@ private:
|
|||
{
|
||||
const char code1[] = " void f() { int a; bool use = false; if( use ) { a=0; } else {a=1;} } ";
|
||||
const char code2[] = " void f() { int a; bool use = false; {a=1;} } ";
|
||||
ASSERT_EQUALS( tok(code2), tok(code1) );
|
||||
ASSERT_EQUALS(tok(code2), tok(code1));
|
||||
}
|
||||
|
||||
{
|
||||
const char code1[] = " void f() { int a; bool use = true; if( use ) { a=0; } else {a=1;} } ";
|
||||
const char code2[] = " void f() { int a; bool use = true; { a=0; } } ";
|
||||
ASSERT_EQUALS( tok(code2), tok(code1) );
|
||||
ASSERT_EQUALS(tok(code2), tok(code1));
|
||||
}
|
||||
|
||||
{
|
||||
const char code1[] = " void f() { int a; int use = 5; if( use ) { a=0; } else {a=1;} } ";
|
||||
const char code2[] = " void f() { int a; int use = 5; { a=0; } } ";
|
||||
ASSERT_EQUALS( tok(code2), tok(code1) );
|
||||
ASSERT_EQUALS(tok(code2), tok(code1));
|
||||
}
|
||||
|
||||
{
|
||||
const char code1[] = " void f() { int a; int use = 0; if( use ) { a=0; } else {a=1;} } ";
|
||||
const char code2[] = " void f() { int a; int use = 0; {a=1;} } ";
|
||||
ASSERT_EQUALS( tok(code2), tok(code1) );
|
||||
ASSERT_EQUALS(tok(code2), tok(code1));
|
||||
}
|
||||
|
||||
{
|
||||
const char code1[] = " void f() { int a; bool use = false; if( use ) a=0; else a=1; int c=1; } ";
|
||||
const char code2[] = " void f() { int a; bool use = false; { a=1; } int c=1; } ";
|
||||
ASSERT_EQUALS( tok(code2), tok(code1) );
|
||||
ASSERT_EQUALS(tok(code2), tok(code1));
|
||||
}
|
||||
|
||||
{
|
||||
const char code1[] = " void f() { int a; bool use = true; if( use ) a=0; else a=1; int c=1; } ";
|
||||
const char code2[] = " void f() { int a; bool use = true; { a=0; } int c=1; } ";
|
||||
ASSERT_EQUALS( tok(code2), tok(code1) );
|
||||
ASSERT_EQUALS(tok(code2), tok(code1));
|
||||
}
|
||||
|
||||
{
|
||||
const char code1[] = " void f() { int a; bool use = false; if( use ) a=0; else if( bb ) a=1; int c=1; } ";
|
||||
const char code2[] = " void f() { int a; bool use = false; if( bb ) a=1; int c=1; } ";
|
||||
ASSERT_EQUALS( tok(code2), tok(code1) );
|
||||
ASSERT_EQUALS(tok(code2), tok(code1));
|
||||
}
|
||||
|
||||
{
|
||||
const char code1[] = " void f() { int a; bool use = true; if( use ) a=0; else if( bb ) a=1; int c=1; } ";
|
||||
const char code2[] = " void f() { int a; bool use = true; { a=0;} int c=1; } ";
|
||||
ASSERT_EQUALS( tok(code2), tok(code1) );
|
||||
ASSERT_EQUALS(tok(code2), tok(code1));
|
||||
}
|
||||
|
||||
{
|
||||
const char code1[] = " void f() { int a; bool use = true; if( use ) a=0; else if( bb ) a=1; else if( cc ) a=33; else { gg = 0; } int c=1; } ";
|
||||
const char code2[] = " void f() { int a; bool use = true; { a=0; }int c=1; } ";
|
||||
ASSERT_EQUALS( tok(code2), tok(code1) );
|
||||
ASSERT_EQUALS(tok(code2), tok(code1));
|
||||
}
|
||||
|
||||
{
|
||||
const char code1[] = " void f() { if( aa ) { a=0; } else if( true ) a=1; else { a=2; } } ";
|
||||
const char code2[] = " void f() { if( aa ) { a=0; } else { a=1; } } ";
|
||||
ASSERT_EQUALS( tok(code2), tok(code1) );
|
||||
ASSERT_EQUALS(tok(code2), tok(code1));
|
||||
}
|
||||
|
||||
{
|
||||
const char code1[] = " void f() { if( aa ) { a=0; } else if( false ) a=1; else { a=2; } } ";
|
||||
const char code2[] = " void f() { if( aa ) { a=0; } else { a=2; } } ";
|
||||
ASSERT_EQUALS( tok(code2), tok(code1) );
|
||||
ASSERT_EQUALS(tok(code2), tok(code1));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
REGISTER_TEST( TestSimplifyTokens )
|
||||
REGISTER_TEST(TestSimplifyTokens)
|
||||
|
|
|
@ -43,9 +43,9 @@ public:
|
|||
return testreg;
|
||||
}
|
||||
|
||||
void addTest( TestFixture *t )
|
||||
void addTest(TestFixture *t)
|
||||
{
|
||||
_tests.push_back( t );
|
||||
_tests.push_back(t);
|
||||
}
|
||||
|
||||
const std::list<TestFixture *> &tests() const
|
||||
|
@ -72,7 +72,7 @@ TestFixture::TestFixture(const std::string &_name) : classname(_name)
|
|||
|
||||
bool TestFixture::runTest(const char testname[])
|
||||
{
|
||||
if ( testToRun.empty() || testToRun == testname )
|
||||
if (testToRun.empty() || testToRun == testname)
|
||||
{
|
||||
++countTests;
|
||||
std::cout << classname << "::" << testname << "\n";
|
||||
|
@ -81,18 +81,18 @@ bool TestFixture::runTest(const char testname[])
|
|||
return false;
|
||||
}
|
||||
|
||||
static std::string writestr( const std::string &str )
|
||||
static std::string writestr(const std::string &str)
|
||||
{
|
||||
std::ostringstream ostr;
|
||||
ostr << "\"";
|
||||
for (unsigned int i = 0; i < str.length(); ++i)
|
||||
{
|
||||
char ch = str[i];
|
||||
if ( ch == '\n' )
|
||||
if (ch == '\n')
|
||||
ostr << "\\n";
|
||||
else if ( ch == '\t' )
|
||||
else if (ch == '\t')
|
||||
ostr << "\\t";
|
||||
else if ( ch == '\"' )
|
||||
else if (ch == '\"')
|
||||
ostr << "\\\"";
|
||||
else
|
||||
ostr << std::string(1, ch);
|
||||
|
@ -103,13 +103,13 @@ static std::string writestr( const std::string &str )
|
|||
|
||||
void TestFixture::assertEquals(const char *filename, int linenr, const std::string &expected, const std::string &actual)
|
||||
{
|
||||
if ( expected != actual )
|
||||
if (expected != actual)
|
||||
{
|
||||
errmsg << "Assertion failed in " << filename << " at line " << linenr << std::endl
|
||||
<< "Expected:" << std::endl
|
||||
<< writestr(expected) << std::endl
|
||||
<< "Actual:" << std::endl
|
||||
<< writestr(actual) << std::endl;
|
||||
<< "Expected:" << std::endl
|
||||
<< writestr(expected) << std::endl
|
||||
<< "Actual:" << std::endl
|
||||
<< writestr(actual) << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -119,14 +119,14 @@ void TestFixture::assertEquals(const char *filename, int linenr, unsigned int ex
|
|||
ostr1 << expected;
|
||||
std::ostringstream ostr2;
|
||||
ostr2 << actual;
|
||||
assertEquals( filename, linenr, ostr1.str(), ostr2.str() );
|
||||
assertEquals(filename, linenr, ostr1.str(), ostr2.str());
|
||||
}
|
||||
|
||||
void TestFixture::printTests()
|
||||
{
|
||||
const std::list<TestFixture *> &tests = TestRegistry::theInstance().tests();
|
||||
|
||||
for ( std::list<TestFixture *>::const_iterator it = tests.begin(); it != tests.end(); ++it )
|
||||
for (std::list<TestFixture *>::const_iterator it = tests.begin(); it != tests.end(); ++it)
|
||||
{
|
||||
std::cout << (*it)->classname << std::endl;
|
||||
}
|
||||
|
@ -142,10 +142,10 @@ void TestFixture::runTests(const char cmd[])
|
|||
{
|
||||
std::string classname(cmd ? cmd : "");
|
||||
std::string testname("");
|
||||
if ( classname.find("::") != std::string::npos )
|
||||
if (classname.find("::") != std::string::npos)
|
||||
{
|
||||
testname = classname.substr( classname.find("::") + 2 );
|
||||
classname.erase( classname.find("::") );
|
||||
testname = classname.substr(classname.find("::") + 2);
|
||||
classname.erase(classname.find("::"));
|
||||
}
|
||||
|
||||
countTests = 0;
|
||||
|
@ -153,9 +153,9 @@ void TestFixture::runTests(const char cmd[])
|
|||
|
||||
const std::list<TestFixture *> &tests = TestRegistry::theInstance().tests();
|
||||
|
||||
for ( std::list<TestFixture *>::const_iterator it = tests.begin(); it != tests.end(); ++it )
|
||||
for (std::list<TestFixture *>::const_iterator it = tests.begin(); it != tests.end(); ++it)
|
||||
{
|
||||
if ( classname.empty() || (*it)->classname == classname )
|
||||
if (classname.empty() || (*it)->classname == classname)
|
||||
{
|
||||
(*it)->run(testname);
|
||||
}
|
||||
|
@ -167,12 +167,12 @@ void TestFixture::runTests(const char cmd[])
|
|||
}
|
||||
|
||||
|
||||
void TestFixture::reportErr( const std::string &errmsg)
|
||||
void TestFixture::reportErr(const std::string &errmsg)
|
||||
{
|
||||
errout << errmsg << std::endl;
|
||||
}
|
||||
|
||||
void TestFixture::reportOut( const std::string &outmsg)
|
||||
void TestFixture::reportOut(const std::string &outmsg)
|
||||
{
|
||||
// These can probably be ignored
|
||||
}
|
||||
|
|
|
@ -41,9 +41,9 @@ protected:
|
|||
void assertEquals(const char *filename, int linenr, unsigned int expected, unsigned int actual);
|
||||
|
||||
public:
|
||||
virtual void reportErr( const std::string &errmsg);
|
||||
virtual void reportErr(const std::string &errmsg);
|
||||
|
||||
virtual void reportOut( const std::string &outmsg);
|
||||
virtual void reportOut(const std::string &outmsg);
|
||||
|
||||
void run(const std::string &str);
|
||||
|
||||
|
|
|
@ -31,31 +31,31 @@ private:
|
|||
|
||||
void run()
|
||||
{
|
||||
TEST_CASE( nextprevious );
|
||||
TEST_CASE(nextprevious);
|
||||
|
||||
}
|
||||
|
||||
void nextprevious()
|
||||
{
|
||||
Token *token = new Token;
|
||||
token->str( "1" );
|
||||
token->insertToken( "2" );
|
||||
token->next()->insertToken( "3" );
|
||||
token->str("1");
|
||||
token->insertToken("2");
|
||||
token->next()->insertToken("3");
|
||||
Token *last = token->next()->next();
|
||||
ASSERT_EQUALS( token->str(), "1" );
|
||||
ASSERT_EQUALS( token->next()->str(), "2" );
|
||||
ASSERT_EQUALS( token->next()->next()->str(), "3" );
|
||||
if( last->next() )
|
||||
ASSERT_EQUALS( "Null was expected", "" );
|
||||
ASSERT_EQUALS(token->str(), "1");
|
||||
ASSERT_EQUALS(token->next()->str(), "2");
|
||||
ASSERT_EQUALS(token->next()->next()->str(), "3");
|
||||
if (last->next())
|
||||
ASSERT_EQUALS("Null was expected", "");
|
||||
|
||||
ASSERT_EQUALS( last->str(), "3" );
|
||||
ASSERT_EQUALS( last->previous()->str(), "2" );
|
||||
ASSERT_EQUALS( last->previous()->previous()->str(), "1" );
|
||||
if( token->previous() )
|
||||
ASSERT_EQUALS( "Null was expected", "" );
|
||||
ASSERT_EQUALS(last->str(), "3");
|
||||
ASSERT_EQUALS(last->previous()->str(), "2");
|
||||
ASSERT_EQUALS(last->previous()->previous()->str(), "1");
|
||||
if (token->previous())
|
||||
ASSERT_EQUALS("Null was expected", "");
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
|
||||
REGISTER_TEST( TestTOKEN )
|
||||
REGISTER_TEST(TestTOKEN)
|
||||
|
|
166
testtokenize.cpp
166
testtokenize.cpp
|
@ -37,36 +37,36 @@ private:
|
|||
|
||||
void run()
|
||||
{
|
||||
TEST_CASE( multiline );
|
||||
TEST_CASE( longtok );
|
||||
TEST_CASE(multiline);
|
||||
TEST_CASE(longtok);
|
||||
|
||||
TEST_CASE( inlineasm );
|
||||
TEST_CASE(inlineasm);
|
||||
|
||||
TEST_CASE( dupfuncname );
|
||||
TEST_CASE(dupfuncname);
|
||||
|
||||
TEST_CASE( const_and_volatile_functions );
|
||||
TEST_CASE(const_and_volatile_functions);
|
||||
|
||||
TEST_CASE( ifAddBraces1 );
|
||||
TEST_CASE( ifAddBraces2 );
|
||||
TEST_CASE( ifAddBraces3 );
|
||||
TEST_CASE( ifAddBraces4 );
|
||||
TEST_CASE(ifAddBraces1);
|
||||
TEST_CASE(ifAddBraces2);
|
||||
TEST_CASE(ifAddBraces3);
|
||||
TEST_CASE(ifAddBraces4);
|
||||
|
||||
TEST_CASE( numeric_true_condition );
|
||||
TEST_CASE(numeric_true_condition);
|
||||
|
||||
TEST_CASE( simplifyKnownVariables1 );
|
||||
TEST_CASE( simplifyKnownVariables2 );
|
||||
TEST_CASE( simplifyKnownVariables3 );
|
||||
TEST_CASE( simplifyKnownVariables4 );
|
||||
TEST_CASE( simplifyKnownVariables5 );
|
||||
TEST_CASE(simplifyKnownVariables1);
|
||||
TEST_CASE(simplifyKnownVariables2);
|
||||
TEST_CASE(simplifyKnownVariables3);
|
||||
TEST_CASE(simplifyKnownVariables4);
|
||||
TEST_CASE(simplifyKnownVariables5);
|
||||
|
||||
TEST_CASE( multiCompare );
|
||||
TEST_CASE(multiCompare);
|
||||
|
||||
TEST_CASE( match1 );
|
||||
TEST_CASE(match1);
|
||||
|
||||
TEST_CASE( match2 );
|
||||
TEST_CASE(match2);
|
||||
|
||||
TEST_CASE( varid1 );
|
||||
TEST_CASE( varid2 );
|
||||
TEST_CASE(varid1);
|
||||
TEST_CASE(varid2);
|
||||
}
|
||||
|
||||
|
||||
|
@ -75,7 +75,7 @@ private:
|
|||
unsigned int i = 0;
|
||||
for (; expected[i] && actual; ++i, actual = actual->next())
|
||||
{
|
||||
if ( strcmp( expected[i], actual->aaaa() ) != 0)
|
||||
if (strcmp(expected[i], actual->aaaa()) != 0)
|
||||
return false;
|
||||
}
|
||||
return (expected[i] == NULL && actual == NULL);
|
||||
|
@ -102,13 +102,13 @@ private:
|
|||
};
|
||||
|
||||
// Compare..
|
||||
ASSERT_EQUALS( true, cmptok(expected, tokenizer.tokens()) );
|
||||
ASSERT_EQUALS(true, cmptok(expected, tokenizer.tokens()));
|
||||
}
|
||||
|
||||
|
||||
void longtok()
|
||||
{
|
||||
std::string filedata(10000,'a');
|
||||
std::string filedata(10000, 'a');
|
||||
|
||||
// tokenize..
|
||||
Tokenizer tokenizer;
|
||||
|
@ -116,7 +116,7 @@ private:
|
|||
tokenizer.tokenize(istr, "test.cpp");
|
||||
|
||||
// Expected result..
|
||||
ASSERT_EQUALS( std::string(10000,'a'), std::string(tokenizer.tokens()->aaaa()) );
|
||||
ASSERT_EQUALS(std::string(10000, 'a'), std::string(tokenizer.tokens()->aaaa()));
|
||||
}
|
||||
|
||||
|
||||
|
@ -149,7 +149,7 @@ private:
|
|||
};
|
||||
|
||||
// Compare..
|
||||
ASSERT_EQUALS( true, cmptok(expected, tokenizer.tokens()) );
|
||||
ASSERT_EQUALS(true, cmptok(expected, tokenizer.tokens()));
|
||||
}
|
||||
|
||||
|
||||
|
@ -168,8 +168,8 @@ private:
|
|||
|
||||
tokenizer.fillFunctionList();
|
||||
|
||||
ASSERT_EQUALS( 1, static_cast<unsigned int>(tokenizer._functionList.size()) );
|
||||
ASSERT_EQUALS( std::string("b"), tokenizer._functionList[0]->aaaa() );
|
||||
ASSERT_EQUALS(1, static_cast<unsigned int>(tokenizer._functionList.size()));
|
||||
ASSERT_EQUALS(std::string("b"), tokenizer._functionList[0]->aaaa());
|
||||
}
|
||||
|
||||
void const_and_volatile_functions()
|
||||
|
@ -199,12 +199,12 @@ private:
|
|||
|
||||
tokenizer.fillFunctionList();
|
||||
|
||||
ASSERT_EQUALS( 3, static_cast<unsigned int>(tokenizer._functionList.size()) );
|
||||
if( tokenizer._functionList.size() == 3 )
|
||||
ASSERT_EQUALS(3, static_cast<unsigned int>(tokenizer._functionList.size()));
|
||||
if (tokenizer._functionList.size() == 3)
|
||||
{
|
||||
ASSERT_EQUALS( std::string("a"), tokenizer._functionList[0]->str() );
|
||||
ASSERT_EQUALS( std::string("b"), tokenizer._functionList[1]->str() );
|
||||
ASSERT_EQUALS( std::string("c"), tokenizer._functionList[2]->str() );
|
||||
ASSERT_EQUALS(std::string("a"), tokenizer._functionList[0]->str());
|
||||
ASSERT_EQUALS(std::string("b"), tokenizer._functionList[1]->str());
|
||||
ASSERT_EQUALS(std::string("c"), tokenizer._functionList[2]->str());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -226,7 +226,7 @@ private:
|
|||
std::ostringstream ostr;
|
||||
for (const Token *tok = tokenizer.tokens(); tok; tok = tok->next())
|
||||
ostr << " " << tok->str();
|
||||
ASSERT_EQUALS( std::string(" void f ( ) { { ; } }"), ostr.str() );
|
||||
ASSERT_EQUALS(std::string(" void f ( ) { { ; } }"), ostr.str());
|
||||
}
|
||||
|
||||
void ifAddBraces1()
|
||||
|
@ -242,12 +242,12 @@ private:
|
|||
std::istringstream istr(code);
|
||||
tokenizer.tokenize(istr, "test.cpp");
|
||||
|
||||
ASSERT_EQUALS( true, tokenizer.simplifyIfAddBraces() );
|
||||
ASSERT_EQUALS(true, tokenizer.simplifyIfAddBraces());
|
||||
|
||||
std::ostringstream ostr;
|
||||
for (const Token *tok = tokenizer.tokens(); tok; tok = tok->next())
|
||||
ostr << " " << tok->str();
|
||||
ASSERT_EQUALS( std::string(" void f ( ) { if ( a ) { ; } else { ; } }"), ostr.str() );
|
||||
ASSERT_EQUALS(std::string(" void f ( ) { if ( a ) { ; } else { ; } }"), ostr.str());
|
||||
}
|
||||
|
||||
void ifAddBraces2()
|
||||
|
@ -262,12 +262,12 @@ private:
|
|||
std::istringstream istr(code);
|
||||
tokenizer.tokenize(istr, "test.cpp");
|
||||
|
||||
ASSERT_EQUALS( true, tokenizer.simplifyIfAddBraces() );
|
||||
ASSERT_EQUALS(true, tokenizer.simplifyIfAddBraces());
|
||||
|
||||
std::ostringstream ostr;
|
||||
for (const Token *tok = tokenizer.tokens(); tok; tok = tok->next())
|
||||
ostr << " " << tok->str();
|
||||
ASSERT_EQUALS( std::string(" void f ( ) { if ( a ) { if ( b ) { } } }"), ostr.str() );
|
||||
ASSERT_EQUALS(std::string(" void f ( ) { if ( a ) { if ( b ) { } } }"), ostr.str());
|
||||
}
|
||||
|
||||
void ifAddBraces3()
|
||||
|
@ -282,12 +282,12 @@ private:
|
|||
std::istringstream istr(code);
|
||||
tokenizer.tokenize(istr, "test.cpp");
|
||||
|
||||
ASSERT_EQUALS( true, tokenizer.simplifyIfAddBraces() );
|
||||
ASSERT_EQUALS(true, tokenizer.simplifyIfAddBraces());
|
||||
|
||||
std::ostringstream ostr;
|
||||
for (const Token *tok = tokenizer.tokens(); tok; tok = tok->next())
|
||||
ostr << " " << tok->str();
|
||||
ASSERT_EQUALS( std::string(" void f ( ) { if ( a ) { for ( ; ; ) { } } }"), ostr.str() );
|
||||
ASSERT_EQUALS(std::string(" void f ( ) { if ( a ) { for ( ; ; ) { } } }"), ostr.str());
|
||||
}
|
||||
|
||||
void ifAddBraces4()
|
||||
|
@ -307,12 +307,12 @@ private:
|
|||
std::istringstream istr(code);
|
||||
tokenizer.tokenize(istr, "test.cpp");
|
||||
|
||||
ASSERT_EQUALS( true, tokenizer.simplifyIfAddBraces() );
|
||||
ASSERT_EQUALS(true, tokenizer.simplifyIfAddBraces());
|
||||
|
||||
std::ostringstream ostr;
|
||||
for (const Token *tok = tokenizer.tokens(); tok; tok = tok->next())
|
||||
ostr << " " << tok->str();
|
||||
ASSERT_EQUALS( std::string(" char * foo ( ) { char * str = malloc ( 10 ) ; if ( somecondition ) { for ( ; ; ) { } } return str ; }"), ostr.str() );
|
||||
ASSERT_EQUALS(std::string(" char * foo ( ) { char * str = malloc ( 10 ) ; if ( somecondition ) { for ( ; ; ) { } } return str ; }"), ostr.str());
|
||||
}
|
||||
|
||||
void simplifyKnownVariables1()
|
||||
|
@ -334,7 +334,7 @@ private:
|
|||
std::ostringstream ostr;
|
||||
for (const Token *tok = tokenizer.tokens(); tok; tok = tok->next())
|
||||
ostr << " " << tok->str();
|
||||
ASSERT_EQUALS( std::string(" void f ( ) { int a = 10 ; if ( 10 ) ; }"), ostr.str() );
|
||||
ASSERT_EQUALS(std::string(" void f ( ) { int a = 10 ; if ( 10 ) ; }"), ostr.str());
|
||||
}
|
||||
|
||||
void simplifyKnownVariables2()
|
||||
|
@ -357,7 +357,7 @@ private:
|
|||
std::ostringstream ostr;
|
||||
for (const Token *tok = tokenizer.tokens(); tok; tok = tok->next())
|
||||
ostr << " " << tok->str();
|
||||
ASSERT_EQUALS( std::string(" void f ( ) { int a = 10 ; a = g ( ) ; if ( a ) ; }"), ostr.str() );
|
||||
ASSERT_EQUALS(std::string(" void f ( ) { int a = 10 ; a = g ( ) ; if ( a ) ; }"), ostr.str());
|
||||
}
|
||||
|
||||
void simplifyKnownVariables3()
|
||||
|
@ -383,7 +383,7 @@ private:
|
|||
std::ostringstream ostr;
|
||||
for (const Token *tok = tokenizer.tokens(); tok; tok = tok->next())
|
||||
ostr << " " << tok->str();
|
||||
ASSERT_EQUALS( std::string(" void f ( ) { int a = 4 ; while ( true ) { break ; a = 10 ; } if ( a ) ; }"), ostr.str() );
|
||||
ASSERT_EQUALS(std::string(" void f ( ) { int a = 4 ; while ( true ) { break ; a = 10 ; } if ( a ) ; }"), ostr.str());
|
||||
}
|
||||
|
||||
void simplifyKnownVariables4()
|
||||
|
@ -405,7 +405,7 @@ private:
|
|||
std::ostringstream ostr;
|
||||
for (const Token *tok = tokenizer.tokens(); tok; tok = tok->next())
|
||||
ostr << " " << tok->str();
|
||||
ASSERT_EQUALS( std::string(" void f ( ) { int a = 4 ; if ( g ( a ) ) ; }"), ostr.str() );
|
||||
ASSERT_EQUALS(std::string(" void f ( ) { int a = 4 ; if ( g ( a ) ) ; }"), ostr.str());
|
||||
}
|
||||
|
||||
void simplifyKnownVariables5()
|
||||
|
@ -427,26 +427,26 @@ private:
|
|||
std::ostringstream ostr;
|
||||
for (const Token *tok = tokenizer.tokens(); tok; tok = tok->next())
|
||||
ostr << " " << tok->str();
|
||||
ASSERT_EQUALS( std::string(" void f ( ) { int a = 4 ; if ( a = 5 ) ; }"), ostr.str() );
|
||||
ASSERT_EQUALS(std::string(" void f ( ) { int a = 4 ; if ( a = 5 ) ; }"), ostr.str());
|
||||
}
|
||||
|
||||
void multiCompare()
|
||||
{
|
||||
// Test for found
|
||||
ASSERT_EQUALS( 1, Token::multiCompare( "one|two", "one" ) );
|
||||
ASSERT_EQUALS( 1, Token::multiCompare( "one|two", "two" ) );
|
||||
ASSERT_EQUALS( 1, Token::multiCompare( "verybig|two|", "two" ) );
|
||||
ASSERT_EQUALS(1, Token::multiCompare("one|two", "one"));
|
||||
ASSERT_EQUALS(1, Token::multiCompare("one|two", "two"));
|
||||
ASSERT_EQUALS(1, Token::multiCompare("verybig|two|", "two"));
|
||||
|
||||
// Test for empty string found
|
||||
ASSERT_EQUALS( 0, Token::multiCompare( "|one|two", "notfound" ) );
|
||||
ASSERT_EQUALS( 0, Token::multiCompare( "one||two", "notfound" ) );
|
||||
ASSERT_EQUALS( 0, Token::multiCompare( "one|two|", "notfound" ) );
|
||||
ASSERT_EQUALS(0, Token::multiCompare("|one|two", "notfound"));
|
||||
ASSERT_EQUALS(0, Token::multiCompare("one||two", "notfound"));
|
||||
ASSERT_EQUALS(0, Token::multiCompare("one|two|", "notfound"));
|
||||
|
||||
// Test for not found
|
||||
ASSERT_EQUALS( -1, Token::multiCompare( "one|two", "notfound" ) );
|
||||
ASSERT_EQUALS( -1, Token::multiCompare( "verybig|two", "s" ) );
|
||||
ASSERT_EQUALS( -1, Token::multiCompare( "one|two", "ne" ) );
|
||||
ASSERT_EQUALS( -1, Token::multiCompare( "abc|def", "a" ) );
|
||||
ASSERT_EQUALS(-1, Token::multiCompare("one|two", "notfound"));
|
||||
ASSERT_EQUALS(-1, Token::multiCompare("verybig|two", "s"));
|
||||
ASSERT_EQUALS(-1, Token::multiCompare("one|two", "ne"));
|
||||
ASSERT_EQUALS(-1, Token::multiCompare("abc|def", "a"));
|
||||
}
|
||||
|
||||
void match1()
|
||||
|
@ -461,7 +461,7 @@ private:
|
|||
tokenizer.tokenize(istr, "test.cpp");
|
||||
|
||||
// Match..
|
||||
ASSERT_EQUALS( true, Token::Match(tokenizer.tokens(), "%var% | %var%") );
|
||||
ASSERT_EQUALS(true, Token::Match(tokenizer.tokens(), "%var% | %var%"));
|
||||
}
|
||||
|
||||
// Match "%var% || %var%"
|
||||
|
@ -474,7 +474,7 @@ private:
|
|||
tokenizer.tokenize(istr, "test.cpp");
|
||||
|
||||
// Match..
|
||||
ASSERT_EQUALS( true, Token::Match(tokenizer.tokens(), "%var% || %var%") );
|
||||
ASSERT_EQUALS(true, Token::Match(tokenizer.tokens(), "%var% || %var%"));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -489,7 +489,7 @@ private:
|
|||
tokenizer.tokenize(istr, "test.cpp");
|
||||
|
||||
// Match..
|
||||
ASSERT_EQUALS( true, Token::Match(tokenizer.tokens(), "!!else") );
|
||||
ASSERT_EQUALS(true, Token::Match(tokenizer.tokens(), "!!else"));
|
||||
}
|
||||
|
||||
{
|
||||
|
@ -501,7 +501,7 @@ private:
|
|||
tokenizer.tokenize(istr, "test.cpp");
|
||||
|
||||
// Match..
|
||||
ASSERT_EQUALS( true, Token::Match(tokenizer.tokens(), "if ; !!else") );
|
||||
ASSERT_EQUALS(true, Token::Match(tokenizer.tokens(), "if ; !!else"));
|
||||
}
|
||||
|
||||
{
|
||||
|
@ -513,7 +513,7 @@ private:
|
|||
tokenizer.tokenize(istr, "test.cpp");
|
||||
|
||||
// Match..
|
||||
ASSERT_EQUALS( true, Token::Match(tokenizer.tokens(), "if ; !!else") );
|
||||
ASSERT_EQUALS(true, Token::Match(tokenizer.tokens(), "if ; !!else"));
|
||||
}
|
||||
|
||||
{
|
||||
|
@ -525,7 +525,7 @@ private:
|
|||
tokenizer.tokenize(istr, "test.cpp");
|
||||
|
||||
// Match..
|
||||
ASSERT_EQUALS( false, Token::Match(tokenizer.tokens(), "!!else") );
|
||||
ASSERT_EQUALS(false, Token::Match(tokenizer.tokens(), "!!else"));
|
||||
}
|
||||
|
||||
{
|
||||
|
@ -537,7 +537,7 @@ private:
|
|||
tokenizer.tokenize(istr, "test.cpp");
|
||||
|
||||
// Match..
|
||||
ASSERT_EQUALS( false, Token::Match(tokenizer.tokens(), "if ; !!else") );
|
||||
ASSERT_EQUALS(false, Token::Match(tokenizer.tokens(), "if ; !!else"));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -550,7 +550,7 @@ private:
|
|||
" for (int i = 0; i < 10; ++i)\n"
|
||||
" i = 3;\n"
|
||||
" i = 4;\n"
|
||||
"}\n" );
|
||||
"}\n");
|
||||
|
||||
// tokenize..
|
||||
Tokenizer tokenizer;
|
||||
|
@ -558,18 +558,18 @@ private:
|
|||
tokenizer.tokenize(istr, "test.cpp");
|
||||
tokenizer.setVarId();
|
||||
|
||||
for ( const Token *tok = tokenizer.tokens(); tok; tok = tok->next() )
|
||||
for (const Token *tok = tokenizer.tokens(); tok; tok = tok->next())
|
||||
{
|
||||
if ( tok->str() != "i" )
|
||||
ASSERT_EQUALS( 0, tok->varId() );
|
||||
else if ( Token::Match(tok, "i = 1") )
|
||||
ASSERT_EQUALS( 1, tok->varId() );
|
||||
else if ( Token::Match(tok, "i = 2") )
|
||||
ASSERT_EQUALS( 2, tok->varId() );
|
||||
else if ( Token::Match(tok, "i = 3") )
|
||||
ASSERT_EQUALS( 3, tok->varId() );
|
||||
else if ( Token::Match(tok, "i = 4") )
|
||||
ASSERT_EQUALS( 2, tok->varId() );
|
||||
if (tok->str() != "i")
|
||||
ASSERT_EQUALS(0, tok->varId());
|
||||
else if (Token::Match(tok, "i = 1"))
|
||||
ASSERT_EQUALS(1, tok->varId());
|
||||
else if (Token::Match(tok, "i = 2"))
|
||||
ASSERT_EQUALS(2, tok->varId());
|
||||
else if (Token::Match(tok, "i = 3"))
|
||||
ASSERT_EQUALS(3, tok->varId());
|
||||
else if (Token::Match(tok, "i = 4"))
|
||||
ASSERT_EQUALS(2, tok->varId());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -580,7 +580,7 @@ private:
|
|||
" struct ABC abc;\n"
|
||||
" abc.a = 3;\n"
|
||||
" i = abc.a;\n"
|
||||
"}\n" );
|
||||
"}\n");
|
||||
|
||||
// tokenize..
|
||||
Tokenizer tokenizer;
|
||||
|
@ -588,16 +588,16 @@ private:
|
|||
tokenizer.tokenize(istr, "test.cpp");
|
||||
tokenizer.setVarId();
|
||||
|
||||
for ( const Token *tok = tokenizer.tokens(); tok; tok = tok->next() )
|
||||
for (const Token *tok = tokenizer.tokens(); tok; tok = tok->next())
|
||||
{
|
||||
if ( tok->str() == "abc" )
|
||||
ASSERT_EQUALS( 1, tok->varId() );
|
||||
else if ( tok->str() == "a" )
|
||||
ASSERT_EQUALS( 2, tok->varId() );
|
||||
if (tok->str() == "abc")
|
||||
ASSERT_EQUALS(1, tok->varId());
|
||||
else if (tok->str() == "a")
|
||||
ASSERT_EQUALS(2, tok->varId());
|
||||
else
|
||||
ASSERT_EQUALS( 0, tok->varId() );
|
||||
ASSERT_EQUALS(0, tok->varId());
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
REGISTER_TEST( TestTokenizer )
|
||||
REGISTER_TEST(TestTokenizer)
|
||||
|
|
|
@ -35,19 +35,19 @@ public:
|
|||
private:
|
||||
void run()
|
||||
{
|
||||
TEST_CASE( test1 );
|
||||
TEST_CASE(test1);
|
||||
|
||||
// [ 2236547 ] False positive --style unused function, called via pointer
|
||||
TEST_CASE( func_pointer );
|
||||
TEST_CASE(func_pointer);
|
||||
}
|
||||
|
||||
|
||||
void check( const char code[] )
|
||||
void check(const char code[])
|
||||
{
|
||||
// Tokenize..
|
||||
Tokenizer tokenizer;
|
||||
std::istringstream istr(code);
|
||||
tokenizer.tokenize( istr, "test.cpp" );
|
||||
tokenizer.tokenize(istr, "test.cpp");
|
||||
|
||||
// Clear the error buffer..
|
||||
errout.str("");
|
||||
|
@ -55,7 +55,7 @@ private:
|
|||
// Check for unused private functions..
|
||||
Settings settings;
|
||||
settings._checkCodingStyle = true;
|
||||
CheckClass checkClass( &tokenizer, settings, this );
|
||||
CheckClass checkClass(&tokenizer, settings, this);
|
||||
checkClass.privateFunctions();
|
||||
}
|
||||
|
||||
|
@ -63,21 +63,21 @@ private:
|
|||
|
||||
void test1()
|
||||
{
|
||||
check( "class Fred\n"
|
||||
"{\n"
|
||||
"private:\n"
|
||||
" unsigned int f();\n"
|
||||
"public:\n"
|
||||
" Fred();\n"
|
||||
"};\n"
|
||||
"\n"
|
||||
"Fred::Fred()\n"
|
||||
"{ }\n"
|
||||
"\n"
|
||||
"unsigned int Fred::f()\n"
|
||||
"{ }\n" );
|
||||
check("class Fred\n"
|
||||
"{\n"
|
||||
"private:\n"
|
||||
" unsigned int f();\n"
|
||||
"public:\n"
|
||||
" Fred();\n"
|
||||
"};\n"
|
||||
"\n"
|
||||
"Fred::Fred()\n"
|
||||
"{ }\n"
|
||||
"\n"
|
||||
"unsigned int Fred::f()\n"
|
||||
"{ }\n");
|
||||
|
||||
ASSERT_EQUALS( std::string("Class 'Fred', unused private function: 'f'\n"), errout.str() );
|
||||
ASSERT_EQUALS(std::string("Class 'Fred', unused private function: 'f'\n"), errout.str());
|
||||
}
|
||||
|
||||
|
||||
|
@ -87,34 +87,34 @@ private:
|
|||
|
||||
void func_pointer()
|
||||
{
|
||||
check( "class Fred\n"
|
||||
"{\n"
|
||||
"private:\n"
|
||||
" typedef void (*testfp)();\n"
|
||||
"\n"
|
||||
" testfp get()\n"
|
||||
" {\n"
|
||||
" return test;\n"
|
||||
" }\n"
|
||||
"\n"
|
||||
" static void test()\n"
|
||||
" { }\n"
|
||||
"\n"
|
||||
"public:\n"
|
||||
" Fred();\n"
|
||||
"};\n"
|
||||
"\n"
|
||||
"Fred::Fred()\n"
|
||||
"{}\n" );
|
||||
check("class Fred\n"
|
||||
"{\n"
|
||||
"private:\n"
|
||||
" typedef void (*testfp)();\n"
|
||||
"\n"
|
||||
" testfp get()\n"
|
||||
" {\n"
|
||||
" return test;\n"
|
||||
" }\n"
|
||||
"\n"
|
||||
" static void test()\n"
|
||||
" { }\n"
|
||||
"\n"
|
||||
"public:\n"
|
||||
" Fred();\n"
|
||||
"};\n"
|
||||
"\n"
|
||||
"Fred::Fred()\n"
|
||||
"{}\n");
|
||||
|
||||
std::string str( errout.str() );
|
||||
std::string str(errout.str());
|
||||
|
||||
ASSERT_EQUALS( std::string("Class 'Fred', unused private function: 'get'\n"), str );
|
||||
ASSERT_EQUALS(std::string("Class 'Fred', unused private function: 'get'\n"), str);
|
||||
}
|
||||
|
||||
|
||||
|
||||
};
|
||||
|
||||
REGISTER_TEST( TestUnusedPrivateFunction )
|
||||
REGISTER_TEST(TestUnusedPrivateFunction)
|
||||
|
||||
|
|
|
@ -35,188 +35,188 @@ public:
|
|||
{ }
|
||||
|
||||
private:
|
||||
void check( const char code[] )
|
||||
void check(const char code[])
|
||||
{
|
||||
// Tokenize..
|
||||
Tokenizer tokenizer;
|
||||
std::istringstream istr(code);
|
||||
tokenizer.tokenize( istr, "test.cpp" );
|
||||
tokenizer.tokenize(istr, "test.cpp");
|
||||
tokenizer.simplifyTokenList();
|
||||
|
||||
// Clear the error buffer..
|
||||
errout.str("");
|
||||
|
||||
// Check for unused variables..
|
||||
CheckOther checkOther( &tokenizer, this );
|
||||
CheckOther checkOther(&tokenizer, this);
|
||||
checkOther.CheckStructMemberUsage();
|
||||
}
|
||||
|
||||
void run()
|
||||
{
|
||||
TEST_CASE( structmember1 );
|
||||
TEST_CASE( structmember2 );
|
||||
TEST_CASE( structmember3 );
|
||||
TEST_CASE(structmember1);
|
||||
TEST_CASE(structmember2);
|
||||
TEST_CASE(structmember3);
|
||||
|
||||
TEST_CASE( localvar1 );
|
||||
TEST_CASE( localvar2 );
|
||||
TEST_CASE( localvar3 );
|
||||
TEST_CASE( localvar4 );
|
||||
TEST_CASE( localvar5 );
|
||||
TEST_CASE(localvar1);
|
||||
TEST_CASE(localvar2);
|
||||
TEST_CASE(localvar3);
|
||||
TEST_CASE(localvar4);
|
||||
TEST_CASE(localvar5);
|
||||
|
||||
// Don't give false positives for variables in structs/unions
|
||||
TEST_CASE( localvarStruct1 );
|
||||
TEST_CASE( localvarStruct2 );
|
||||
TEST_CASE(localvarStruct1);
|
||||
TEST_CASE(localvarStruct2);
|
||||
|
||||
TEST_CASE( localvarOp ); // Usage with arithmetic operators
|
||||
TEST_CASE( localvarInvert ); // Usage with inverted variable
|
||||
TEST_CASE( localvarIf ); // Usage in if
|
||||
TEST_CASE( localvarIfElse ); // return tmp1 ? tmp2 : tmp3;
|
||||
TEST_CASE( localvarOpAssign ); // a |= b;
|
||||
TEST_CASE(localvarOp); // Usage with arithmetic operators
|
||||
TEST_CASE(localvarInvert); // Usage with inverted variable
|
||||
TEST_CASE(localvarIf); // Usage in if
|
||||
TEST_CASE(localvarIfElse); // return tmp1 ? tmp2 : tmp3;
|
||||
TEST_CASE(localvarOpAssign); // a |= b;
|
||||
}
|
||||
|
||||
void structmember1()
|
||||
{
|
||||
check( "struct abc\n"
|
||||
"{\n"
|
||||
" int a;\n"
|
||||
" int b;\n"
|
||||
" int c;\n"
|
||||
"};\n" );
|
||||
ASSERT_EQUALS( std::string("[test.cpp:3]: struct or union member 'abc::a' is never used\n"
|
||||
"[test.cpp:4]: struct or union member 'abc::b' is never used\n"
|
||||
"[test.cpp:5]: struct or union member 'abc::c' is never used\n"), errout.str() );
|
||||
check("struct abc\n"
|
||||
"{\n"
|
||||
" int a;\n"
|
||||
" int b;\n"
|
||||
" int c;\n"
|
||||
"};\n");
|
||||
ASSERT_EQUALS(std::string("[test.cpp:3]: struct or union member 'abc::a' is never used\n"
|
||||
"[test.cpp:4]: struct or union member 'abc::b' is never used\n"
|
||||
"[test.cpp:5]: struct or union member 'abc::c' is never used\n"), errout.str());
|
||||
}
|
||||
|
||||
void structmember2()
|
||||
{
|
||||
check( "struct ABC\n"
|
||||
"{\n"
|
||||
" int a;\n"
|
||||
" int b;\n"
|
||||
" int c;\n"
|
||||
"};\n"
|
||||
"\n"
|
||||
"void foo()\n"
|
||||
"{\n"
|
||||
" struct ABC abc;\n"
|
||||
" int a = abc.a;\n"
|
||||
" int b = abc.b;\n"
|
||||
" int c = abc.c;\n"
|
||||
"}\n" );
|
||||
ASSERT_EQUALS( std::string(""), errout.str() );
|
||||
check("struct ABC\n"
|
||||
"{\n"
|
||||
" int a;\n"
|
||||
" int b;\n"
|
||||
" int c;\n"
|
||||
"};\n"
|
||||
"\n"
|
||||
"void foo()\n"
|
||||
"{\n"
|
||||
" struct ABC abc;\n"
|
||||
" int a = abc.a;\n"
|
||||
" int b = abc.b;\n"
|
||||
" int c = abc.c;\n"
|
||||
"}\n");
|
||||
ASSERT_EQUALS(std::string(""), errout.str());
|
||||
}
|
||||
|
||||
void structmember3()
|
||||
{
|
||||
check( "struct ABC\n"
|
||||
"{\n"
|
||||
" int a;\n"
|
||||
" int b;\n"
|
||||
" int c;\n"
|
||||
"};\n"
|
||||
"\n"
|
||||
"static struct ABC abc[] = { {1, 2, 3} };\n"
|
||||
"\n"
|
||||
"void foo()\n"
|
||||
"{\n"
|
||||
" int a = abc[0].a;\n"
|
||||
" int b = abc[0].b;\n"
|
||||
" int c = abc[0].c;\n"
|
||||
"}\n" );
|
||||
ASSERT_EQUALS( std::string(""), errout.str() );
|
||||
check("struct ABC\n"
|
||||
"{\n"
|
||||
" int a;\n"
|
||||
" int b;\n"
|
||||
" int c;\n"
|
||||
"};\n"
|
||||
"\n"
|
||||
"static struct ABC abc[] = { {1, 2, 3} };\n"
|
||||
"\n"
|
||||
"void foo()\n"
|
||||
"{\n"
|
||||
" int a = abc[0].a;\n"
|
||||
" int b = abc[0].b;\n"
|
||||
" int c = abc[0].c;\n"
|
||||
"}\n");
|
||||
ASSERT_EQUALS(std::string(""), errout.str());
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void functionVariableUsage( const char code[] )
|
||||
void functionVariableUsage(const char code[])
|
||||
{
|
||||
// Tokenize..
|
||||
Tokenizer tokenizer;
|
||||
std::istringstream istr(code);
|
||||
tokenizer.tokenize( istr, "test.cpp" );
|
||||
tokenizer.tokenize(istr, "test.cpp");
|
||||
tokenizer.simplifyTokenList();
|
||||
|
||||
// Clear the error buffer..
|
||||
errout.str("");
|
||||
|
||||
// Check for unused variables..
|
||||
CheckOther checkOther( &tokenizer, this );
|
||||
CheckOther checkOther(&tokenizer, this);
|
||||
checkOther.functionVariableUsage();
|
||||
}
|
||||
|
||||
void localvar1()
|
||||
{
|
||||
functionVariableUsage( "void foo()\n"
|
||||
"{\n"
|
||||
" int i = 0;\n"
|
||||
"}\n" );
|
||||
ASSERT_EQUALS( std::string("[test.cpp:2]: Variable 'i' is assigned a value that is never used\n"), errout.str() );
|
||||
functionVariableUsage("void foo()\n"
|
||||
"{\n"
|
||||
" int i = 0;\n"
|
||||
"}\n");
|
||||
ASSERT_EQUALS(std::string("[test.cpp:2]: Variable 'i' is assigned a value that is never used\n"), errout.str());
|
||||
}
|
||||
|
||||
void localvar2()
|
||||
{
|
||||
functionVariableUsage( "void foo()\n"
|
||||
"{\n"
|
||||
" int i;\n"
|
||||
" return i;\n"
|
||||
"}\n" );
|
||||
ASSERT_EQUALS( std::string("[test.cpp:2]: Variable 'i' is not assigned a value\n"), errout.str() );
|
||||
functionVariableUsage("void foo()\n"
|
||||
"{\n"
|
||||
" int i;\n"
|
||||
" return i;\n"
|
||||
"}\n");
|
||||
ASSERT_EQUALS(std::string("[test.cpp:2]: Variable 'i' is not assigned a value\n"), errout.str());
|
||||
}
|
||||
|
||||
void localvar3()
|
||||
{
|
||||
functionVariableUsage( "void foo()\n"
|
||||
"{\n"
|
||||
" int i;\n"
|
||||
" if ( abc )\n"
|
||||
" ;\n"
|
||||
" else i = 0;\n"
|
||||
"}\n" );
|
||||
ASSERT_EQUALS( std::string("[test.cpp:2]: Variable 'i' is assigned a value that is never used\n"), errout.str() );
|
||||
functionVariableUsage("void foo()\n"
|
||||
"{\n"
|
||||
" int i;\n"
|
||||
" if ( abc )\n"
|
||||
" ;\n"
|
||||
" else i = 0;\n"
|
||||
"}\n");
|
||||
ASSERT_EQUALS(std::string("[test.cpp:2]: Variable 'i' is assigned a value that is never used\n"), errout.str());
|
||||
}
|
||||
|
||||
void localvar4()
|
||||
{
|
||||
functionVariableUsage( "void foo()\n"
|
||||
"{\n"
|
||||
" int i = 0;\n"
|
||||
" f(i);\n"
|
||||
"}\n" );
|
||||
ASSERT_EQUALS( std::string(""), errout.str() );
|
||||
functionVariableUsage("void foo()\n"
|
||||
"{\n"
|
||||
" int i = 0;\n"
|
||||
" f(i);\n"
|
||||
"}\n");
|
||||
ASSERT_EQUALS(std::string(""), errout.str());
|
||||
}
|
||||
|
||||
void localvar5()
|
||||
{
|
||||
functionVariableUsage( "void foo()\n"
|
||||
"{\n"
|
||||
" int a = 0;\n"
|
||||
" b = (char)a;\n"
|
||||
"}\n" );
|
||||
ASSERT_EQUALS( std::string(""), errout.str() );
|
||||
functionVariableUsage("void foo()\n"
|
||||
"{\n"
|
||||
" int a = 0;\n"
|
||||
" b = (char)a;\n"
|
||||
"}\n");
|
||||
ASSERT_EQUALS(std::string(""), errout.str());
|
||||
}
|
||||
|
||||
|
||||
|
||||
void localvarStruct1()
|
||||
{
|
||||
functionVariableUsage( "void foo()\n"
|
||||
"{\n"
|
||||
" static const struct{ int x, y, w, h; } bounds = {1,2,3,4};\n"
|
||||
" return bounds.x + bounds.y + bounds.w + bounds.h;\n"
|
||||
"}\n" );
|
||||
ASSERT_EQUALS( std::string(""), errout.str() );
|
||||
functionVariableUsage("void foo()\n"
|
||||
"{\n"
|
||||
" static const struct{ int x, y, w, h; } bounds = {1,2,3,4};\n"
|
||||
" return bounds.x + bounds.y + bounds.w + bounds.h;\n"
|
||||
"}\n");
|
||||
ASSERT_EQUALS(std::string(""), errout.str());
|
||||
}
|
||||
|
||||
void localvarStruct2()
|
||||
{
|
||||
functionVariableUsage( "void foo()\n"
|
||||
"{\n"
|
||||
" struct ABC { int a, b, c; };\n"
|
||||
" struct ABC abc = { 1, 2, 3 };\n"
|
||||
"}\n" );
|
||||
ASSERT_EQUALS( std::string(""), errout.str() );
|
||||
functionVariableUsage("void foo()\n"
|
||||
"{\n"
|
||||
" struct ABC { int a, b, c; };\n"
|
||||
" struct ABC abc = { 1, 2, 3 };\n"
|
||||
"}\n");
|
||||
ASSERT_EQUALS(std::string(""), errout.str());
|
||||
}
|
||||
|
||||
|
||||
|
@ -226,64 +226,64 @@ private:
|
|||
const char op[] = "+-*/%&|^";
|
||||
for (const char *p = op; *p; ++p)
|
||||
{
|
||||
std::string code( "int main()\n"
|
||||
"{\n"
|
||||
" int tmp = 10;\n"
|
||||
" return 123 " + std::string(1, *p) + " tmp;\n"
|
||||
"}\n" );
|
||||
functionVariableUsage( code.c_str() );
|
||||
ASSERT_EQUALS( std::string(""), errout.str() );
|
||||
std::string code("int main()\n"
|
||||
"{\n"
|
||||
" int tmp = 10;\n"
|
||||
" return 123 " + std::string(1, *p) + " tmp;\n"
|
||||
"}\n");
|
||||
functionVariableUsage(code.c_str());
|
||||
ASSERT_EQUALS(std::string(""), errout.str());
|
||||
}
|
||||
}
|
||||
|
||||
void localvarInvert()
|
||||
{
|
||||
functionVariableUsage( "int main()\n"
|
||||
"{\n"
|
||||
" int tmp = 10;\n"
|
||||
" return ~tmp;\n"
|
||||
"}\n" );
|
||||
ASSERT_EQUALS( std::string(""), errout.str() );
|
||||
functionVariableUsage("int main()\n"
|
||||
"{\n"
|
||||
" int tmp = 10;\n"
|
||||
" return ~tmp;\n"
|
||||
"}\n");
|
||||
ASSERT_EQUALS(std::string(""), errout.str());
|
||||
}
|
||||
|
||||
void localvarIf()
|
||||
{
|
||||
functionVariableUsage( "int main()\n"
|
||||
"{\n"
|
||||
" int tmp = 10;\n"
|
||||
" if ( tmp )\n"
|
||||
" return 1;\n"
|
||||
" return 0;\n"
|
||||
"}\n" );
|
||||
ASSERT_EQUALS( std::string(""), errout.str() );
|
||||
functionVariableUsage("int main()\n"
|
||||
"{\n"
|
||||
" int tmp = 10;\n"
|
||||
" if ( tmp )\n"
|
||||
" return 1;\n"
|
||||
" return 0;\n"
|
||||
"}\n");
|
||||
ASSERT_EQUALS(std::string(""), errout.str());
|
||||
}
|
||||
|
||||
void localvarIfElse()
|
||||
{
|
||||
functionVariableUsage( "int foo()\n"
|
||||
"{\n"
|
||||
" int tmp1 = 1;\n"
|
||||
" int tmp2 = 2;\n"
|
||||
" int tmp3 = 3;\n"
|
||||
" return tmp1 ? tmp2 : tmp3;\n"
|
||||
"}\n" );
|
||||
ASSERT_EQUALS( std::string(""), errout.str() );
|
||||
functionVariableUsage("int foo()\n"
|
||||
"{\n"
|
||||
" int tmp1 = 1;\n"
|
||||
" int tmp2 = 2;\n"
|
||||
" int tmp3 = 3;\n"
|
||||
" return tmp1 ? tmp2 : tmp3;\n"
|
||||
"}\n");
|
||||
ASSERT_EQUALS(std::string(""), errout.str());
|
||||
}
|
||||
|
||||
void localvarOpAssign()
|
||||
{
|
||||
functionVariableUsage( "void foo()\n"
|
||||
"{\n"
|
||||
" int a = 1;\n"
|
||||
" int b = 2;\n"
|
||||
" a |= b;\n"
|
||||
"}\n" );
|
||||
ASSERT_EQUALS( std::string("[test.cpp:2]: Variable 'a' is assigned a value that is never used\n"), errout.str() );
|
||||
functionVariableUsage("void foo()\n"
|
||||
"{\n"
|
||||
" int a = 1;\n"
|
||||
" int b = 2;\n"
|
||||
" a |= b;\n"
|
||||
"}\n");
|
||||
ASSERT_EQUALS(std::string("[test.cpp:2]: Variable 'a' is assigned a value that is never used\n"), errout.str());
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
|
||||
REGISTER_TEST( TestUnusedVar )
|
||||
REGISTER_TEST(TestUnusedVar)
|
||||
|
||||
|
||||
|
|
176
token.cpp
176
token.cpp
|
@ -27,16 +27,16 @@
|
|||
#endif
|
||||
|
||||
Token::Token() :
|
||||
_str(""),
|
||||
_cstr(0),
|
||||
_isName(false),
|
||||
_isNumber(false),
|
||||
_isBoolean(false),
|
||||
_varId(0),
|
||||
_next(0),
|
||||
_previous(0),
|
||||
_fileIndex(0),
|
||||
_linenr(0)
|
||||
_str(""),
|
||||
_cstr(0),
|
||||
_isName(false),
|
||||
_isNumber(false),
|
||||
_isBoolean(false),
|
||||
_varId(0),
|
||||
_next(0),
|
||||
_previous(0),
|
||||
_fileIndex(0),
|
||||
_linenr(0)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -45,14 +45,14 @@ Token::~Token()
|
|||
std::free(_cstr);
|
||||
}
|
||||
|
||||
void Token::str( const char s[] )
|
||||
void Token::str(const char s[])
|
||||
{
|
||||
_str = s;
|
||||
std::free(_cstr);
|
||||
_cstr = strdup(s);
|
||||
_isName = bool(_str[0]=='_' || isalpha(_str[0]));
|
||||
_isName = bool(_str[0] == '_' || isalpha(_str[0]));
|
||||
_isNumber = bool(isdigit(_str[0]) != 0);
|
||||
if( _str == "true" || _str == "false" )
|
||||
if (_str == "true" || _str == "false")
|
||||
_isBoolean = true;
|
||||
else
|
||||
_isBoolean = false;
|
||||
|
@ -72,7 +72,7 @@ void Token::deleteNext()
|
|||
const Token *Token::tokAt(int index) const
|
||||
{
|
||||
const Token *tok = this;
|
||||
while (index>0 && tok)
|
||||
while (index > 0 && tok)
|
||||
{
|
||||
tok = tok->next();
|
||||
--index;
|
||||
|
@ -86,21 +86,21 @@ const char *Token::strAt(int index) const
|
|||
return tok ? tok->_cstr : "";
|
||||
}
|
||||
|
||||
int Token::multiCompare( const char *needle, const char *haystack )
|
||||
int Token::multiCompare(const char *needle, const char *haystack)
|
||||
{
|
||||
bool emptyStringFound = false;
|
||||
bool findNextOr = false;
|
||||
const char *haystackPointer = haystack;
|
||||
for( ; *needle; ++needle )
|
||||
for (; *needle; ++needle)
|
||||
{
|
||||
if( *needle == '|' )
|
||||
if (*needle == '|')
|
||||
{
|
||||
// If needle and haystack are both at the end, we have a match.
|
||||
if( *haystackPointer == 0 )
|
||||
if (*haystackPointer == 0)
|
||||
return 1;
|
||||
|
||||
haystackPointer = haystack;
|
||||
if( findNextOr )
|
||||
if (findNextOr)
|
||||
findNextOr = false;
|
||||
else
|
||||
emptyStringFound = true;
|
||||
|
@ -108,12 +108,12 @@ int Token::multiCompare( const char *needle, const char *haystack )
|
|||
continue;
|
||||
}
|
||||
|
||||
if( findNextOr )
|
||||
if (findNextOr)
|
||||
continue;
|
||||
|
||||
// If haystack and needle don't share the same character, reset
|
||||
// haystackpointer and find next '|' character.
|
||||
if( *haystackPointer != *needle )
|
||||
if (*haystackPointer != *needle)
|
||||
{
|
||||
haystackPointer = haystack;
|
||||
findNextOr = true;
|
||||
|
@ -125,11 +125,11 @@ int Token::multiCompare( const char *needle, const char *haystack )
|
|||
}
|
||||
|
||||
// If both needle and haystack are at the end, then we have a match.
|
||||
if( *haystackPointer == 0 )
|
||||
if (*haystackPointer == 0)
|
||||
return 1;
|
||||
|
||||
// If empty string was found or if last character in needle was '|'
|
||||
if( emptyStringFound || findNextOr == false )
|
||||
if (emptyStringFound || findNextOr == false)
|
||||
return 0;
|
||||
|
||||
return -1;
|
||||
|
@ -141,21 +141,21 @@ bool Token::simpleMatch(const Token *tok, const char pattern[])
|
|||
|
||||
current = pattern;
|
||||
next = strchr(pattern, ' ');
|
||||
if ( !next )
|
||||
if (!next)
|
||||
next = pattern + strlen(pattern);
|
||||
|
||||
while ( *current )
|
||||
while (*current)
|
||||
{
|
||||
size_t length = static_cast<size_t>(next-current);
|
||||
size_t length = static_cast<size_t>(next - current);
|
||||
|
||||
if ( !tok || length != tok->_str.length() || strncmp(current, tok->_cstr, length) )
|
||||
if (!tok || length != tok->_str.length() || strncmp(current, tok->_cstr, length))
|
||||
return false;
|
||||
|
||||
current = next;
|
||||
if ( *next )
|
||||
if (*next)
|
||||
{
|
||||
next = strchr(++current, ' ');
|
||||
if ( !next )
|
||||
if (!next)
|
||||
next = current + strlen(current);
|
||||
}
|
||||
tok = tok->next();
|
||||
|
@ -164,19 +164,19 @@ bool Token::simpleMatch(const Token *tok, const char pattern[])
|
|||
return true;
|
||||
}
|
||||
|
||||
bool Token::Match(const Token *tok, const char pattern[], unsigned int varid, const char *varname1[] )
|
||||
bool Token::Match(const Token *tok, const char pattern[], unsigned int varid, const char *varname1[])
|
||||
{
|
||||
const char *p = pattern;
|
||||
while ( *p )
|
||||
while (*p)
|
||||
{
|
||||
// Skip spaces in pattern..
|
||||
while ( *p == ' ' )
|
||||
while (*p == ' ')
|
||||
++p;
|
||||
|
||||
if (!tok)
|
||||
{
|
||||
// If we have no tokens, pattern "!!else" should return true
|
||||
if( p[1] == '!' && p[0] == '!' && strlen(p) > 2 )
|
||||
if (p[1] == '!' && p[0] == '!' && strlen(p) > 2)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
|
@ -186,7 +186,7 @@ bool Token::Match(const Token *tok, const char pattern[], unsigned int varid, co
|
|||
// TODO: Refactor this so there can't be buffer overflows
|
||||
char str[500];
|
||||
char *s = str;
|
||||
while (*p && *p!=' ')
|
||||
while (*p && *p != ' ')
|
||||
{
|
||||
*s = *p;
|
||||
++s;
|
||||
|
@ -198,13 +198,13 @@ bool Token::Match(const Token *tok, const char pattern[], unsigned int varid, co
|
|||
if (str[0] == 0)
|
||||
return true;
|
||||
|
||||
// Compare the first character of the string for optimization reasons
|
||||
// before doing more detailed checks.
|
||||
// Compare the first character of the string for optimization reasons
|
||||
// before doing more detailed checks.
|
||||
bool patternIdentified = false;
|
||||
if( str[0] == '%' )
|
||||
if (str[0] == '%')
|
||||
{
|
||||
// Any symbolname..
|
||||
if (strcmp(str,"%var%")==0 || strcmp(str,"%type%")==0)
|
||||
if (strcmp(str, "%var%") == 0 || strcmp(str, "%type%") == 0)
|
||||
{
|
||||
if (!tok->isName())
|
||||
return false;
|
||||
|
@ -213,7 +213,7 @@ bool Token::Match(const Token *tok, const char pattern[], unsigned int varid, co
|
|||
}
|
||||
|
||||
// Accept any token
|
||||
else if (strcmp(str,"%any%")==0 )
|
||||
else if (strcmp(str, "%any%") == 0)
|
||||
{
|
||||
patternIdentified = true;
|
||||
}
|
||||
|
@ -221,21 +221,21 @@ bool Token::Match(const Token *tok, const char pattern[], unsigned int varid, co
|
|||
// Variable name..
|
||||
else if (strcmp(str, "%var1%") == 0)
|
||||
{
|
||||
if ( ! varname1 )
|
||||
if (! varname1)
|
||||
return false;
|
||||
|
||||
if (tok->_str != varname1[0])
|
||||
return false;
|
||||
|
||||
for ( int i = 1; varname1[i]; i++ )
|
||||
for (int i = 1; varname1[i]; i++)
|
||||
{
|
||||
if ( !(tok->tokAt(2)) )
|
||||
if (!(tok->tokAt(2)))
|
||||
return false;
|
||||
|
||||
if ( strcmp(tok->strAt(1), ".") )
|
||||
if (strcmp(tok->strAt(1), "."))
|
||||
return false;
|
||||
|
||||
if ( strcmp(tok->strAt(2), varname1[i]) )
|
||||
if (strcmp(tok->strAt(2), varname1[i]))
|
||||
return false;
|
||||
|
||||
tok = tok->tokAt(2);
|
||||
|
@ -244,67 +244,67 @@ bool Token::Match(const Token *tok, const char pattern[], unsigned int varid, co
|
|||
patternIdentified = true;
|
||||
}
|
||||
|
||||
else if (strcmp(str,"%varid%")==0)
|
||||
else if (strcmp(str, "%varid%") == 0)
|
||||
{
|
||||
if( varid == 0 )
|
||||
if (varid == 0)
|
||||
{
|
||||
std::cout << "\n###### If you see this, there is a bug ###### Token::Match() - varid was 0" << std::endl;
|
||||
}
|
||||
|
||||
if ( tok->varId() != varid )
|
||||
if (tok->varId() != varid)
|
||||
return false;
|
||||
|
||||
patternIdentified = true;
|
||||
}
|
||||
|
||||
else if (strcmp(str,"%num%")==0)
|
||||
else if (strcmp(str, "%num%") == 0)
|
||||
{
|
||||
if ( !tok->isNumber() )
|
||||
if (!tok->isNumber())
|
||||
return false;
|
||||
|
||||
patternIdentified = true;
|
||||
}
|
||||
|
||||
else if (strcmp(str,"%bool%")==0)
|
||||
else if (strcmp(str, "%bool%") == 0)
|
||||
{
|
||||
if ( !tok->isBoolean() )
|
||||
if (!tok->isBoolean())
|
||||
return false;
|
||||
|
||||
patternIdentified = true;
|
||||
}
|
||||
|
||||
else if (strcmp(str,"%str%")==0)
|
||||
else if (strcmp(str, "%str%") == 0)
|
||||
{
|
||||
if ( tok->_str[0] != '\"' )
|
||||
if (tok->_str[0] != '\"')
|
||||
return false;
|
||||
|
||||
patternIdentified = true;
|
||||
}
|
||||
}
|
||||
|
||||
if( patternIdentified )
|
||||
if (patternIdentified)
|
||||
{
|
||||
// Pattern was identified already above.
|
||||
}
|
||||
|
||||
// [.. => search for a one-character token..
|
||||
else if (str[0]=='[' && strchr(str, ']') && tok->_str[1] == 0)
|
||||
else if (str[0] == '[' && strchr(str, ']') && tok->_str[1] == 0)
|
||||
{
|
||||
*strrchr(str, ']') = 0;
|
||||
if ( strchr( str + 1, tok->_str[0] ) == 0 )
|
||||
if (strchr(str + 1, tok->_str[0]) == 0)
|
||||
return false;
|
||||
}
|
||||
|
||||
// Parse multi options, such as void|int|char (accept token which is one of these 3)
|
||||
else if ( strchr(str, '|') && strlen( str ) > 2 )
|
||||
else if (strchr(str, '|') && strlen(str) > 2)
|
||||
{
|
||||
int res = multiCompare( str, tok->_cstr );
|
||||
if( res == 0 )
|
||||
int res = multiCompare(str, tok->_cstr);
|
||||
if (res == 0)
|
||||
{
|
||||
// Empty alternative matches, use the same token on next round
|
||||
continue;
|
||||
}
|
||||
else if( res == -1 )
|
||||
else if (res == -1)
|
||||
{
|
||||
// No match
|
||||
return false;
|
||||
|
@ -312,9 +312,9 @@ bool Token::Match(const Token *tok, const char pattern[], unsigned int varid, co
|
|||
}
|
||||
|
||||
// Parse "not" options. Token can be anything except the given one
|
||||
else if( str[1] == '!' && str[0] == '!' && strlen(str) > 2 )
|
||||
else if (str[1] == '!' && str[0] == '!' && strlen(str) > 2)
|
||||
{
|
||||
if( strcmp( tok->aaaa(), &(str[2]) ) == 0 )
|
||||
if (strcmp(tok->aaaa(), &(str[2])) == 0)
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -346,7 +346,7 @@ bool Token::isBoolean() const
|
|||
bool Token::isStandardType() const
|
||||
{
|
||||
bool ret = false;
|
||||
const char *type[] = {"bool","char","short","int","long","float","double",0};
|
||||
const char *type[] = {"bool", "char", "short", "int", "long", "float", "double", 0};
|
||||
for (int i = 0; type[i]; i++)
|
||||
ret |= (_str == type[i]);
|
||||
return ret;
|
||||
|
@ -356,19 +356,19 @@ bool Token::isStandardType() const
|
|||
|
||||
const Token *Token::findmatch(const Token *tok, const char pattern[], const char *varname1[])
|
||||
{
|
||||
for ( ; tok; tok = tok->next())
|
||||
for (; tok; tok = tok->next())
|
||||
{
|
||||
if ( Token::Match(tok, pattern, 0, varname1) )
|
||||
if (Token::Match(tok, pattern, 0, varname1))
|
||||
return tok;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
const Token *Token::findmatch(const Token *tok, const char pattern[], unsigned int varId )
|
||||
const Token *Token::findmatch(const Token *tok, const char pattern[], unsigned int varId)
|
||||
{
|
||||
for ( ; tok; tok = tok->next())
|
||||
for (; tok; tok = tok->next())
|
||||
{
|
||||
if ( Token::Match(tok, pattern, varId) )
|
||||
if (Token::Match(tok, pattern, varId))
|
||||
return tok;
|
||||
}
|
||||
return 0;
|
||||
|
@ -379,7 +379,7 @@ unsigned int Token::varId() const
|
|||
return _varId;
|
||||
}
|
||||
|
||||
void Token::varId( unsigned int id )
|
||||
void Token::varId(unsigned int id)
|
||||
{
|
||||
_varId = id;
|
||||
}
|
||||
|
@ -389,7 +389,7 @@ Token *Token::next() const
|
|||
return _next;
|
||||
}
|
||||
|
||||
void Token::next( Token *next )
|
||||
void Token::next(Token *next)
|
||||
{
|
||||
_next = next;
|
||||
}
|
||||
|
@ -399,33 +399,33 @@ Token *Token::previous() const
|
|||
return _previous;
|
||||
}
|
||||
|
||||
void Token::previous( Token *previous )
|
||||
void Token::previous(Token *previous)
|
||||
{
|
||||
_previous = previous;
|
||||
}
|
||||
|
||||
void Token::insertToken( const char str[] )
|
||||
void Token::insertToken(const char str[])
|
||||
{
|
||||
Token *newToken = new Token;
|
||||
newToken->str( str );
|
||||
newToken->str(str);
|
||||
newToken->_linenr = _linenr;
|
||||
newToken->_fileIndex = _fileIndex;
|
||||
if( this->next() )
|
||||
if (this->next())
|
||||
{
|
||||
newToken->next( this->next() );
|
||||
newToken->next()->previous( newToken );
|
||||
newToken->next(this->next());
|
||||
newToken->next()->previous(newToken);
|
||||
}
|
||||
|
||||
this->next( newToken );
|
||||
newToken->previous( this );
|
||||
this->next(newToken);
|
||||
newToken->previous(this);
|
||||
}
|
||||
|
||||
void Token::eraseTokens( Token *begin, const Token *end )
|
||||
void Token::eraseTokens(Token *begin, const Token *end)
|
||||
{
|
||||
if ( ! begin )
|
||||
if (! begin)
|
||||
return;
|
||||
|
||||
while ( begin->next() && begin->next() != end )
|
||||
while (begin->next() && begin->next() != end)
|
||||
{
|
||||
begin->deleteNext();
|
||||
}
|
||||
|
@ -436,7 +436,7 @@ unsigned int Token::fileIndex() const
|
|||
return _fileIndex;
|
||||
}
|
||||
|
||||
void Token::fileIndex( unsigned int fileIndex )
|
||||
void Token::fileIndex(unsigned int fileIndex)
|
||||
{
|
||||
_fileIndex = fileIndex;
|
||||
}
|
||||
|
@ -446,25 +446,25 @@ unsigned int Token::linenr() const
|
|||
return _linenr;
|
||||
}
|
||||
|
||||
void Token::linenr( unsigned int linenr )
|
||||
void Token::linenr(unsigned int linenr)
|
||||
{
|
||||
_linenr = linenr;
|
||||
}
|
||||
|
||||
void Token::printOut( const char *title ) const
|
||||
void Token::printOut(const char *title) const
|
||||
{
|
||||
std::cout << std::endl << "###";
|
||||
if ( title )
|
||||
if (title)
|
||||
std::cout << " " << title << " ";
|
||||
else
|
||||
std::cout << "########";
|
||||
|
||||
std::cout << "###" << std::endl;
|
||||
for( const Token *t = this; t; t = t->next() )
|
||||
for (const Token *t = this; t; t = t->next())
|
||||
{
|
||||
std::cout << t->linenr() << ": " << t->str();
|
||||
if ( t->varId() )
|
||||
std::cout << " ("<< t->varId() <<")";
|
||||
if (t->varId())
|
||||
std::cout << " (" << t->varId() << ")";
|
||||
|
||||
std::cout << std::endl;
|
||||
}
|
||||
|
|
42
token.h
42
token.h
|
@ -26,19 +26,27 @@ class Token
|
|||
public:
|
||||
Token();
|
||||
~Token();
|
||||
void str( const char s[] );
|
||||
void str(const char s[]);
|
||||
|
||||
const std::string &str() const
|
||||
{ return _str; }
|
||||
{
|
||||
return _str;
|
||||
}
|
||||
|
||||
const char *aaaa() const
|
||||
{ return _cstr; }
|
||||
{
|
||||
return _cstr;
|
||||
}
|
||||
|
||||
char aaaa0() const
|
||||
{ return _cstr[0]; }
|
||||
{
|
||||
return _cstr[0];
|
||||
}
|
||||
|
||||
char aaaa1() const
|
||||
{ return _cstr[1]; }
|
||||
{
|
||||
return _cstr[1];
|
||||
}
|
||||
|
||||
/**
|
||||
* Unlink and delete next token.
|
||||
|
@ -105,14 +113,14 @@ public:
|
|||
* @return true if given token matches with given pattern
|
||||
* false if given token does not match with given pattern
|
||||
*/
|
||||
static bool Match(const Token *tok, const char pattern[], unsigned int varid=0, const char *varname1[]=0 );
|
||||
static bool Match(const Token *tok, const char pattern[], unsigned int varid = 0, const char *varname1[] = 0);
|
||||
|
||||
bool isName() const;
|
||||
bool isNumber() const;
|
||||
bool isBoolean() const;
|
||||
bool isStandardType() const;
|
||||
static const Token *findmatch(const Token *tok, const char pattern[], const char *varname1[]=0);
|
||||
static const Token *findmatch(const Token *tok, const char pattern[], unsigned int varId );
|
||||
static const Token *findmatch(const Token *tok, const char pattern[], const char *varname1[] = 0);
|
||||
static const Token *findmatch(const Token *tok, const char pattern[], unsigned int varId);
|
||||
|
||||
/**
|
||||
* Needle is build from multiple alternatives. If one of
|
||||
|
@ -127,14 +135,14 @@ public:
|
|||
* 0 if needle was empty string
|
||||
* -1 if needle was not found
|
||||
*/
|
||||
static int multiCompare( const char *needle, const char *haystack );
|
||||
static int multiCompare(const char *needle, const char *haystack);
|
||||
|
||||
|
||||
unsigned int linenr() const;
|
||||
void linenr( unsigned int linenr );
|
||||
void linenr(unsigned int linenr);
|
||||
|
||||
unsigned int fileIndex() const;
|
||||
void fileIndex( unsigned int fileIndex );
|
||||
void fileIndex(unsigned int fileIndex);
|
||||
|
||||
Token *next() const;
|
||||
|
||||
|
@ -146,20 +154,20 @@ public:
|
|||
* @param begin Tokens after this will be erased.
|
||||
* @param end Tokens before this will be erased.
|
||||
*/
|
||||
static void eraseTokens( Token *begin, const Token *end );
|
||||
static void eraseTokens(Token *begin, const Token *end);
|
||||
|
||||
/**
|
||||
* Insert new token after this token. This function will handle
|
||||
* relations between next and previous token also.
|
||||
* @param str String for the new token.
|
||||
*/
|
||||
void insertToken( const char str[] );
|
||||
void insertToken(const char str[]);
|
||||
|
||||
Token *previous() const;
|
||||
|
||||
|
||||
unsigned int varId() const;
|
||||
void varId( unsigned int id );
|
||||
void varId(unsigned int id);
|
||||
|
||||
/**
|
||||
* For debugging purposes, prints token and all tokens
|
||||
|
@ -167,11 +175,11 @@ public:
|
|||
* @param title Title for the printout or use default parameter or 0
|
||||
* for no title.
|
||||
*/
|
||||
void printOut( const char *title = 0 ) const;
|
||||
void printOut(const char *title = 0) const;
|
||||
|
||||
private:
|
||||
void next( Token *next );
|
||||
void previous( Token *previous );
|
||||
void next(Token *next);
|
||||
void previous(Token *previous);
|
||||
|
||||
std::string _str;
|
||||
char * _cstr;
|
||||
|
|
562
tokenize.cpp
562
tokenize.cpp
File diff suppressed because it is too large
Load Diff
12
tokenize.h
12
tokenize.h
|
@ -38,7 +38,7 @@ private:
|
|||
/**
|
||||
* Helper function for "tokenize". This recursively parses into included header files.
|
||||
*/
|
||||
void tokenizeCode(std::istream &code, const unsigned int FileIndex=0);
|
||||
void tokenizeCode(std::istream &code, const unsigned int FileIndex = 0);
|
||||
|
||||
public:
|
||||
Tokenizer();
|
||||
|
@ -61,12 +61,12 @@ public:
|
|||
// Helper functions for handling the tokens list..
|
||||
|
||||
static void deleteTokens(Token *tok);
|
||||
static const char *getParameterName( const Token *ftok, int par );
|
||||
static const char *getParameterName(const Token *ftok, int par);
|
||||
|
||||
static bool SameFileName( const char fname1[], const char fname2[] );
|
||||
static bool SameFileName(const char fname1[], const char fname2[]);
|
||||
|
||||
|
||||
std::string fileLine( const Token *tok ) const;
|
||||
std::string fileLine(const Token *tok) const;
|
||||
|
||||
// Return size.
|
||||
int SizeOfType(const char type[]) const;
|
||||
|
@ -76,7 +76,7 @@ public:
|
|||
const std::vector<std::string> *getFiles() const;
|
||||
|
||||
void fillFunctionList();
|
||||
const Token *GetFunctionTokenByName( const char funcname[] ) const;
|
||||
const Token *GetFunctionTokenByName(const char funcname[]) const;
|
||||
const Token *tokens() const;
|
||||
|
||||
|
||||
|
@ -98,7 +98,7 @@ private:
|
|||
* @param end e.g. "}"
|
||||
* @return The end tag that matches given parameter or 0 if not found.
|
||||
*/
|
||||
static const Token *findClosing( const Token *tok, const char *start, const char *end );
|
||||
static const Token *findClosing(const Token *tok, const char *start, const char *end);
|
||||
|
||||
void Define(const char Name[], const char Value[]);
|
||||
|
||||
|
|
Loading…
Reference in New Issue