refactoring error messages

This commit is contained in:
Daniel Marjamäki 2009-03-21 17:58:13 +01:00
parent 60861d6684
commit 468ed653e2
9 changed files with 257 additions and 190 deletions

View File

@ -306,7 +306,7 @@ void CheckClass::constructors()
struct VAR *varlist = ClassChecking_GetVarList(tok1); struct VAR *varlist = ClassChecking_GetVarList(tok1);
if (varlist) if (varlist)
{ {
_errorLogger->noConstructor(_tokenizer, tok1, classNameToken->str()); noConstructorError(tok1, classNameToken->str());
} }
// Delete the varlist.. // Delete the varlist..
while (varlist) while (varlist)
@ -365,7 +365,7 @@ void CheckClass::CheckConstructors(const Token *tok1, struct VAR *varlist, const
continue; continue;
// It's non-static and it's not initialized => error // It's non-static and it's not initialized => error
_errorLogger->uninitVar(_tokenizer, constructor_token, className, var->name); uninitVarError(constructor_token, className, var->name);
} }
for (struct VAR *var = varlist; var; var = var->next) for (struct VAR *var = varlist; var; var = var->next)
@ -511,7 +511,7 @@ void CheckClass::privateFunctions()
const std::string _pattern("return|(|)|,|= " + FuncList.front()->str()); const std::string _pattern("return|(|)|,|= " + FuncList.front()->str());
if (!Token::findmatch(_tokenizer->tokens(), _pattern.c_str())) if (!Token::findmatch(_tokenizer->tokens(), _pattern.c_str()))
{ {
_errorLogger->unusedPrivateFunction(_tokenizer, FuncList.front(), classname, FuncList.front()->str()); unusedPrivateFunctionError(FuncList.front(), classname, FuncList.front()->str());
} }
FuncList.pop_front(); FuncList.pop_front();
} }
@ -551,7 +551,7 @@ void CheckClass::noMemset()
const std::string pattern1(std::string("class ") + type); const std::string pattern1(std::string("class ") + type);
if (Token::findmatch(_tokenizer->tokens(), pattern1.c_str())) if (Token::findmatch(_tokenizer->tokens(), pattern1.c_str()))
{ {
_errorLogger->memsetClass(_tokenizer, tok, tok->str()); memsetClassError(tok, tok->str());
continue; continue;
} }
@ -564,7 +564,7 @@ void CheckClass::noMemset()
if (Token::Match(tstruct, "std :: %type% %var% ;")) if (Token::Match(tstruct, "std :: %type% %var% ;"))
{ {
_errorLogger->memsetStruct(_tokenizer, tok, tok->str(), tstruct->strAt(2)); memsetStructError(tok, tok->str(), tstruct->strAt(2));
break; break;
} }
} }
@ -584,7 +584,7 @@ void CheckClass::operatorEq()
const Token *tok = Token::findmatch(_tokenizer->tokens(), "void operator = ("); const Token *tok = Token::findmatch(_tokenizer->tokens(), "void operator = (");
if (tok) if (tok)
{ {
_errorLogger->operatorEq(_tokenizer, tok); operatorEqError(tok);
} }
} }
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
@ -665,17 +665,55 @@ void CheckClass::virtualDestructor()
base = Token::findmatch(_tokenizer->tokens(), (std::string("class ") + baseName[0] + " :|{").c_str()); base = Token::findmatch(_tokenizer->tokens(), (std::string("class ") + baseName[0] + " :|{").c_str());
if (base) if (base)
{ {
_errorLogger->virtualDestructor(_tokenizer, base, baseName[0], derivedClass->str()); virtualDestructorError(base, baseName[0], derivedClass->str());
} }
} }
// There is a destructor. Check that it's virtual.. // There is a destructor. Check that it's virtual..
else if (base->str() != "virtual") else if (base->str() != "virtual")
{ {
_errorLogger->virtualDestructor(_tokenizer, base, baseName[0], derivedClass->str()); virtualDestructorError(base, baseName[0], derivedClass->str());
} }
} }
} }
} }
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
void CheckClass::noConstructorError(const Token *tok, const std::string &classname)
{
reportError(tok, "style", "noConstructor", "The class '" + classname + "' has no constructor");
}
void CheckClass::uninitVarError(const Token *tok, const std::string &classname, const std::string &varname)
{
reportError(tok, "style", "uninitVar", "Member variable not initialized in the constructor '" + classname + "::" + varname + "'");
}
void CheckClass::unusedPrivateFunctionError(const Token *tok, const std::string &classname, const std::string &funcname)
{
reportError(tok, "style", "unusedPrivateFunction", "Unused private function '" + classname + "::" + funcname + "'");
}
void CheckClass::memsetClassError(const Token *tok, const std::string &memfunc)
{
reportError(tok, "error", "memsetClass", "Using '" + memfunc + "' on class");
}
void CheckClass::memsetStructError(const Token *tok, const std::string &memfunc, const std::string &classname)
{
reportError(tok, "error", "memsetStruct", "Using '" + memfunc + "' on struct that contains a 'std::" + classname + "'");
}
void CheckClass::operatorEqError(const Token *tok)
{
reportError(tok, "style", "operatorEq", "'operator=' should return something");
}
void CheckClass::virtualDestructorError(const Token *tok, const std::string &Base, const std::string &Derived)
{
reportError(tok, "error", "virtualDestructor", "Class " + Base + " which is inherited by class " + Derived + " does not have a virtual destructor");
}

View File

@ -97,6 +97,16 @@ private:
// Check constructors for a specified class // Check constructors for a specified class
void CheckConstructors(const Token *tok1, struct VAR *varlist, const char funcname[]); void CheckConstructors(const Token *tok1, struct VAR *varlist, const char funcname[]);
// Reporting errors..
void noConstructorError(const Token *tok, const std::string &classname);
void uninitVarError(const Token *tok, const std::string &classname, const std::string &varname);
void unusedPrivateFunctionError(const Token *tok, const std::string &classname, const std::string &funcname);
void memsetClassError(const Token *tok, const std::string &memfunc);
void memsetStructError(const Token *tok, const std::string &memfunc, const std::string &classname);
void operatorEqError(const Token *tok);
void virtualDestructorError(const Token *tok, const std::string &Base, const std::string &Derived);
}; };
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
#endif #endif

View File

@ -304,11 +304,11 @@ void CheckMemoryLeakClass::MemoryLeak(const Token *tok, const char varname[], Al
{ {
if (alloctype == CheckMemoryLeakClass::FOPEN || if (alloctype == CheckMemoryLeakClass::FOPEN ||
alloctype == CheckMemoryLeakClass::POPEN) alloctype == CheckMemoryLeakClass::POPEN)
_errorLogger->resourceLeak(_tokenizer, tok, varname); resourceLeakError(tok, varname);
else if (all) else if (all)
_errorLogger->memleakall(_tokenizer, tok, varname); memleakallError(tok, varname);
else else
_errorLogger->memleak(_tokenizer, tok, varname); memleakError(tok, varname);
} }
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
@ -402,7 +402,7 @@ Token *CheckMemoryLeakClass::getcode(const Token *tok, std::list<const Token *>
Token::Match(tok->tokAt(2), "malloc ( %num% )") && Token::Match(tok->tokAt(2), "malloc ( %num% )") &&
(std::atoi(tok->strAt(4)) % sz) != 0) (std::atoi(tok->strAt(4)) % sz) != 0)
{ {
_errorLogger->mismatchSize(_tokenizer, tok->tokAt(4), tok->strAt(4)); mismatchSizeError(tok->tokAt(4), tok->strAt(4));
} }
if (alloc == No) if (alloc == No)
@ -1213,7 +1213,7 @@ void CheckMemoryLeakClass::CheckMemoryLeak_CheckScope(const Token *Tok1, const c
} }
if ((result = Token::findmatch(tok, "dealloc [;{}] use|use_ ;")) != NULL) if ((result = Token::findmatch(tok, "dealloc [;{}] use|use_ ;")) != NULL)
{ {
_errorLogger->deallocuse(_tokenizer, result->tokAt(2), varname); deallocuseError(result->tokAt(2), varname);
} }
// Replace "&use" with "use". Replace "use_" with ";" // Replace "&use" with "use". Replace "use_" with ";"
@ -1277,7 +1277,7 @@ void CheckMemoryLeakClass::CheckMemoryLeak_CheckScope(const Token *Tok1, const c
else if ((result = Token::findmatch(tok, "dealloc ; dealloc ;")) != NULL) else if ((result = Token::findmatch(tok, "dealloc ; dealloc ;")) != NULL)
{ {
_errorLogger->deallocDealloc(_tokenizer, result->tokAt(2), varname); deallocDeallocError(result->tokAt(2), varname);
} }
else if (! Token::findmatch(tok, "dealloc") && else if (! Token::findmatch(tok, "dealloc") &&
@ -1617,3 +1617,34 @@ Token * CheckMemoryLeakClass::functionParameterCode(const Token *ftok, int param
return NULL; return NULL;
} }
void CheckMemoryLeakClass::memleakError(const Token *tok, const std::string &varname)
{
reportError(tok, "error", "memleak", "Memory leak: " + varname);
}
void CheckMemoryLeakClass::memleakallError(const Token *tok, const std::string &varname)
{
reportError(tok, "all", "memleakall", "Memory leak: " + varname);
}
void CheckMemoryLeakClass::resourceLeakError(const Token *tok, const std::string &varname)
{
reportError(tok, "error", "resourceLeak", "Resource leak: " + varname);
}
void CheckMemoryLeakClass::deallocDeallocError(const Token *tok, const std::string &varname)
{
reportError(tok, "error", "deallocDealloc", "Deallocating a deallocated pointer: " + varname);
}
void CheckMemoryLeakClass::deallocuseError(const Token *tok, const std::string &varname)
{
reportError(tok, "error", "deallocuse", "Using '" + varname + "' after it is deallocated / released");
}
void CheckMemoryLeakClass::mismatchSizeError(const Token *tok, const std::string &sz)
{
reportError(tok, "error", "mismatchSize", "The given size " + sz + " is mismatching");
}

View File

@ -125,6 +125,14 @@ private:
std::list<AllocFunc> _listAllocFunc; std::list<AllocFunc> _listAllocFunc;
void memleakError(const Token *tok, const std::string &varname);
void memleakallError(const Token *tok, const std::string &varname);
void resourceLeakError(const Token *tok, const std::string &varname);
void deallocDeallocError(const Token *tok, const std::string &varname);
void deallocuseError(const Token *tok, const std::string &varname);
void mismatchSizeError(const Token *tok, const std::string &sz);
// Experimental functionality.. // Experimental functionality..
protected: protected:
Token *functionParameterCode(const Token *ftok, int parameter); Token *functionParameterCode(const Token *ftok, int parameter);

View File

@ -54,7 +54,7 @@ void CheckOther::WarningOldStylePointerCast()
if (!Token::findmatch(_tokenizer->tokens(), pattern.c_str())) if (!Token::findmatch(_tokenizer->tokens(), pattern.c_str()))
continue; continue;
_errorLogger->cstyleCast(_tokenizer, tok); cstyleCastError(tok);
} }
} }
@ -135,7 +135,7 @@ void CheckOther::WarningRedundantCode()
if (err) if (err)
{ {
_errorLogger->redundantIfDelete0(_tokenizer, tok); redundantIfDelete0Error(tok);
} }
} }
@ -171,7 +171,7 @@ void CheckOther::redundantCondition2()
var2->str() == var3->str() && var2->str() == var3->str() &&
any1->str() == any2->str()) any1->str() == any2->str())
{ {
_errorLogger->redundantIfRemove(_tokenizer, tok); redundantIfRemoveError(tok);
} }
tok = Token::findmatch(tok->next(), pattern); tok = Token::findmatch(tok->next(), pattern);
@ -209,7 +209,7 @@ void CheckOther::WarningIf()
{ {
if (Token::Match(tok2, ") ; !!else")) if (Token::Match(tok2, ") ; !!else"))
{ {
_errorLogger->ifNoAction(_tokenizer, tok); ifNoActionError(tok);
} }
break; break;
} }
@ -272,7 +272,7 @@ void CheckOther::WarningIf()
if (strcmp(cond, p[i]) == 0) if (strcmp(cond, p[i]) == 0)
b = (i < 3); b = (i < 3);
} }
_errorLogger->conditionAlwaysTrueFalse(_tokenizer, tok->tokAt(4), b ? "True" : "False"); conditionAlwaysTrueFalse(tok->tokAt(4), b ? "True" : "False");
} }
} }
} }
@ -312,7 +312,7 @@ void CheckOther::InvalidFunctionUsage()
int radix = std::atoi(tok2->strAt(1)); int radix = std::atoi(tok2->strAt(1));
if (!(radix == 0 || (radix >= 2 && radix <= 36))) if (!(radix == 0 || (radix >= 2 && radix <= 36)))
{ {
_errorLogger->dangerousUsageStrtol(_tokenizer, tok2); dangerousUsageStrtolError(tok2);
} }
} }
break; break;
@ -355,7 +355,7 @@ void CheckOther::InvalidFunctionUsage()
} }
else if (parlevel == 0 && Token::Match(tok2, ", %varid% [,)]", varid)) else if (parlevel == 0 && Token::Match(tok2, ", %varid% [,)]", varid))
{ {
_errorLogger->sprintfOverlappingData(_tokenizer, tok2->next(), tok2->next()->str()); sprintfOverlappingDataError(tok2->next(), tok2->next()->str());
break; break;
} }
} }
@ -396,7 +396,7 @@ void CheckOther::CheckUnsignedDivision()
if (sign1 && sign2 && sign1 != sign2) if (sign1 && sign2 && sign1 != sign2)
{ {
// One of the operands are signed, the other is unsigned.. // One of the operands are signed, the other is unsigned..
_errorLogger->udivWarning(_tokenizer, tok->next()); udivWarning(tok->next());
} }
} }
} }
@ -409,7 +409,7 @@ void CheckOther::CheckUnsignedDivision()
char sign1 = varsign[varname1]; char sign1 = varsign[varname1];
if (sign1 == 'u') if (sign1 == 'u')
{ {
_errorLogger->udivError(_tokenizer, tok->next()); udivError(tok->next());
} }
} }
} }
@ -422,7 +422,7 @@ void CheckOther::CheckUnsignedDivision()
char sign2 = varsign[varname2]; char sign2 = varsign[varname2];
if (sign2 == 'u') if (sign2 == 'u')
{ {
_errorLogger->udivError(_tokenizer, tok->next()); udivError(tok->next());
} }
} }
} }
@ -580,7 +580,7 @@ void CheckOther::CheckVariableScope_LookupVar(const Token *tok1, const char varn
} }
// Warning if "used" is true // Warning if "used" is true
_errorLogger->variableScope(_tokenizer, tok1, varname); variableScopeError(tok1, varname);
} }
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
@ -595,7 +595,7 @@ void CheckOther::CheckConstantFunctionParameter()
{ {
if (Token::Match(tok, "[,(] const std :: %type% %var% [,)]")) if (Token::Match(tok, "[,(] const std :: %type% %var% [,)]"))
{ {
_errorLogger->passedByValue(_tokenizer, tok, tok->strAt(5)); passedByValueError(tok, tok->strAt(5));
} }
else if (Token::Match(tok, "[,(] const %type% %var% [,)]")) else if (Token::Match(tok, "[,(] const %type% %var% [,)]"))
@ -604,7 +604,7 @@ void CheckOther::CheckConstantFunctionParameter()
const std::string pattern(std::string("class|struct ") + tok->strAt(2)); 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()))
{ {
_errorLogger->passedByValue(_tokenizer, tok, tok->strAt(3)); passedByValueError(tok, tok->strAt(3));
} }
} }
} }
@ -672,7 +672,7 @@ void CheckOther::CheckStructMemberUsage()
if (! used) if (! used)
{ {
_errorLogger->unusedStructMember(_tokenizer, tok->next(), structname, varname); unusedStructMemberError(tok->next(), structname, varname);
} }
} }
} }
@ -715,7 +715,7 @@ void CheckOther::CheckCharVariable()
std::string temp = "%var% [ " + tok->str() + " ]"; std::string temp = "%var% [ " + tok->str() + " ]";
if ((tok2->str() != ".") && Token::Match(tok2->next(), temp.c_str())) if ((tok2->str() != ".") && Token::Match(tok2->next(), temp.c_str()))
{ {
_errorLogger->charArrayIndex(_tokenizer, tok2->next()); charArrayIndexError(tok2->next());
break; break;
} }
@ -723,7 +723,7 @@ void CheckOther::CheckCharVariable()
std::string tempSecond = 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()))
{ {
_errorLogger->charBitOp(_tokenizer, tok2); charBitOpError(tok2);
break; break;
} }
} }
@ -783,12 +783,12 @@ void CheckOther::CheckIncompleteStatement()
if (Token::Match(tok, "[;{}] %str%") && !Token::Match(tok->tokAt(2), "[,}]")) if (Token::Match(tok, "[;{}] %str%") && !Token::Match(tok->tokAt(2), "[,}]"))
{ {
_errorLogger->constStatement(_tokenizer, tok->next(), "string"); constStatementError(tok->next(), "string");
} }
if (Token::Match(tok, "[;{}] %num%") && !Token::Match(tok->tokAt(2), "[,}]")) if (Token::Match(tok, "[;{}] %num%") && !Token::Match(tok->tokAt(2), "[,}]"))
{ {
_errorLogger->constStatement(_tokenizer, tok->next(), "numeric"); constStatementError(tok->next(), "numeric");
} }
} }
} }
@ -823,12 +823,12 @@ void CheckOther::strPlusChar()
// char constant.. // char constant..
const char *s = tok->strAt(3); const char *s = tok->strAt(3);
if (*s == '\'') if (*s == '\'')
_errorLogger->strPlusChar(_tokenizer, tok->next()); strPlusChar(tok->next());
// char variable.. // char variable..
unsigned int varid = tok->tokAt(3)->varId(); unsigned int varid = tok->tokAt(3)->varId();
if (varid > 0 && varid < 10000 && charVars[varid]) if (varid > 0 && varid < 10000 && charVars[varid])
_errorLogger->strPlusChar(_tokenizer, tok->next()); strPlusChar(tok->next());
} }
} }
} }
@ -874,7 +874,7 @@ void CheckOther::returnPointerToStackData()
{ {
unsigned int varid = tok->next()->varId(); unsigned int varid = tok->next()->varId();
if (varid > 0 && std::find(arrayVar.begin(), arrayVar.end(), varid) != arrayVar.end()) if (varid > 0 && std::find(arrayVar.begin(), arrayVar.end(), varid) != arrayVar.end())
_errorLogger->returnLocalVariable(_tokenizer, tok); returnLocalVariable(tok);
} }
} }
@ -884,3 +884,88 @@ void CheckOther::returnPointerToStackData()
} }
} }
void CheckOther::cstyleCastError(const Token *tok)
{
reportError(tok, "style", "cstyleCast", "C-style pointer casting");
}
void CheckOther::redundantIfDelete0Error(const Token *tok)
{
reportError(tok, "style", "redundantIfDelete0", "Redundant condition. It is safe to deallocate a NULL pointer");
}
void CheckOther::redundantIfRemoveError(const Token *tok)
{
reportError(tok, "style", "redundantIfRemove", "Redundant condition. The remove function in the STL will not do anything if element doesn't exist");
}
void CheckOther::dangerousUsageStrtolError(const Token *tok)
{
reportError(tok, "error", "dangerousUsageStrtol", "Invalid radix in call to strtol or strtoul. Must be 0 or 2-36");
}
void CheckOther::ifNoActionError(const Token *tok)
{
reportError(tok, "style", "ifNoAction", "Found redundant if condition - 'if (condition);'");
}
void CheckOther::sprintfOverlappingDataError(const Token *tok, const std::string &varname)
{
reportError(tok, "error", "sprintfOverlappingData", "Overlapping data buffer " + varname);
}
void CheckOther::udivError(const Token *tok)
{
reportError(tok, "error", "udivError", "Unsigned division. The result will be wrong.");
}
void CheckOther::udivWarning(const Token *tok)
{
reportError(tok, "all style", "udivWarning", "Warning: Division with signed and unsigned operators");
}
void CheckOther::unusedStructMemberError(const Token *tok, const std::string &structname, const std::string &varname)
{
reportError(tok, "style", "unusedStructMember", "struct or union member '" + structname + "::" + varname + "' is never used");
}
void CheckOther::passedByValueError(const Token *tok, const std::string &parname)
{
reportError(tok, "style", "passedByValue", "Function parameter '" + parname + "' is passed by value. It could be passed by reference instead.");
}
void CheckOther::constStatementError(const Token *tok, const std::string &type)
{
reportError(tok, "style", "constStatement", "Redundant code: Found a statement that begins with " + type + " constant");
}
void CheckOther::charArrayIndexError(const Token *tok)
{
reportError(tok, "style", "charArrayIndex", "Warning - using char variable as array index");
}
void CheckOther::charBitOpError(const Token *tok)
{
reportError(tok, "style", "charBitOp", "Warning - using char variable in bit operation");
}
void CheckOther::variableScopeError(const Token *tok, const std::string &varname)
{
reportError(tok, "style", "variableScope", "The scope of the variable " + varname + " can be limited");
}
void CheckOther::conditionAlwaysTrueFalse(const Token *tok, const std::string &truefalse)
{
reportError(tok, "style", "conditionAlwaysTrueFalse", "Condition is always " + truefalse);
}
void CheckOther::strPlusChar(const Token *tok)
{
reportError(tok, "error", "strPlusChar", "Unusual pointer arithmetic");
}
void CheckOther::returnLocalVariable(const Token *tok)
{
reportError(tok, "error", "returnLocalVariable", "Returning pointer to local array variable");
}

View File

@ -111,6 +111,27 @@ protected:
// if (haystack.find(needle) != haystack.end()) // if (haystack.find(needle) != haystack.end())
// haystack.remove(needle); // haystack.remove(needle);
void redundantCondition2(); void redundantCondition2();
private:
// Error messages..
void cstyleCastError(const Token *tok);
void redundantIfDelete0Error(const Token *tok);
void redundantIfRemoveError(const Token *tok);
void dangerousUsageStrtolError(const Token *tok);
void ifNoActionError(const Token *tok);
void sprintfOverlappingDataError(const Token *tok, const std::string &varname);
void udivError(const Token *tok);
void udivWarning(const Token *tok);
void unusedStructMemberError(const Token *tok, const std::string &structname, const std::string &varname);
void passedByValueError(const Token *tok, const std::string &parname);
void constStatementError(const Token *tok, const std::string &type);
void charArrayIndexError(const Token *tok);
void charBitOpError(const Token *tok);
void variableScopeError(const Token *tok, const std::string &varname);
void conditionAlwaysTrueFalse(const Token *tok, const std::string &truefalse);
void strPlusChar(const Token *tok);
void returnLocalVariable(const Token *tok);
}; };
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------

View File

@ -166,7 +166,6 @@ void CheckStl::erase()
} }
} }
void CheckStl::eraseCheckLoop(const Token *it) void CheckStl::eraseCheckLoop(const Token *it)
{ {
const Token *tok = it; const Token *tok = it;
@ -209,10 +208,15 @@ void CheckStl::eraseCheckLoop(const Token *it)
// Write error message.. // Write error message..
if (tok2) if (tok2)
_errorLogger->erase(_tokenizer, tok2); eraseError(tok2);
} }
// Error message for bad iterator usage..
void CheckStl::eraseError(const Token *tok)
{
reportError(tok, "error", "erase", "Dangerous usage of erase");
}
@ -259,9 +263,9 @@ void CheckStl::pushback()
if (invalidIterator) if (invalidIterator)
{ {
if (Token::Match(tok2, ("++|--|*|+|-|(|, " + iteratorname).c_str())) if (Token::Match(tok2, ("++|--|*|+|-|(|, " + iteratorname).c_str()))
_errorLogger->pushback(_tokenizer, tok2, iteratorname); pushbackError(tok2, iteratorname);
if (Token::Match(tok2, (iteratorname + " ++|--|+|-").c_str())) if (Token::Match(tok2, (iteratorname + " ++|--|+|-").c_str()))
_errorLogger->pushback(_tokenizer, tok2, iteratorname); pushbackError(tok2, iteratorname);
} }
} }
} }
@ -270,4 +274,10 @@ void CheckStl::pushback()
} }
// Error message for bad iterator usage..
void CheckStl::pushbackError(const Token *tok, const std::string &iterator_name)
{
reportError(tok, "error", "pushback", "After push_back or push_front, the iterator '" + iterator_name + "' may be invalid");
}

View File

@ -83,11 +83,15 @@ private:
void stlOutOfBoundsError(const Token *tok, const std::string &num, const std::string &var); void stlOutOfBoundsError(const Token *tok, const std::string &num, const std::string &var);
void iteratorsError(const Token *tok, const std::string &container1, const std::string &container2); void iteratorsError(const Token *tok, const std::string &container1, const std::string &container2);
void eraseError(const Token *tok);
void pushbackError(const Token *tok, const std::string &iterator_name);
void getErrorMessages() void getErrorMessages()
{ {
iteratorsError(0, "container1", "container2"); iteratorsError(0, "container1", "container2");
stlOutOfBoundsError(0, "i", "foo"); stlOutOfBoundsError(0, "i", "foo");
eraseError(0);
pushbackError(0, "iterator");
} }
}; };

View File

@ -140,73 +140,41 @@ public:
return true; return true;
} }
void stlOutOfBounds(const Tokenizer *tokenizer, const Token *Location, const std::string &what)
{
_writemsg(tokenizer, Location, "error", "" + what + " is out of bounds", "stlOutOfBounds");
}
static bool stlOutOfBounds() static bool stlOutOfBounds()
{ {
return true; return true;
} }
void noConstructor(const Tokenizer *tokenizer, const Token *Location, const std::string &classname)
{
_writemsg(tokenizer, Location, "style", "The class '" + classname + "' has no constructor", "noConstructor");
}
static bool noConstructor(const Settings &s) static bool noConstructor(const Settings &s)
{ {
return s._checkCodingStyle; return s._checkCodingStyle;
} }
void uninitVar(const Tokenizer *tokenizer, const Token *Location, const std::string &classname, const std::string &varname)
{
_writemsg(tokenizer, Location, "style", "Member variable not initialized in the constructor '" + classname + "::" + varname + "'", "uninitVar");
}
static bool uninitVar(const Settings &s) static bool uninitVar(const Settings &s)
{ {
return s._checkCodingStyle; return s._checkCodingStyle;
} }
void unusedPrivateFunction(const Tokenizer *tokenizer, const Token *Location, const std::string &classname, const std::string &funcname)
{
_writemsg(tokenizer, Location, "style", "Unused private function '" + classname + "::" + funcname + "'", "unusedPrivateFunction");
}
static bool unusedPrivateFunction(const Settings &s) static bool unusedPrivateFunction(const Settings &s)
{ {
return s._checkCodingStyle; return s._checkCodingStyle;
} }
void memsetClass(const Tokenizer *tokenizer, const Token *Location, const std::string &memfunc)
{
_writemsg(tokenizer, Location, "error", "Using '" + memfunc + "' on class", "memsetClass");
}
static bool memsetClass() static bool memsetClass()
{ {
return true; return true;
} }
void memsetStruct(const Tokenizer *tokenizer, const Token *Location, const std::string &memfunc, const std::string &classname)
{
_writemsg(tokenizer, Location, "error", "Using '" + memfunc + "' on struct that contains a 'std::" + classname + "'", "memsetStruct");
}
static bool memsetStruct() static bool memsetStruct()
{ {
return true; return true;
} }
void operatorEq(const Tokenizer *tokenizer, const Token *Location)
{
_writemsg(tokenizer, Location, "style", "'operator=' should return something", "operatorEq");
}
static bool operatorEq(const Settings &s) static bool operatorEq(const Settings &s)
{ {
return s._checkCodingStyle; return s._checkCodingStyle;
} }
void virtualDestructor(const Tokenizer *tokenizer, const Token *Location, const std::string &Base, const std::string &Derived)
{
_writemsg(tokenizer, Location, "error", "Class " + Base + " which is inherited by class " + Derived + " does not have a virtual destructor", "virtualDestructor");
}
static bool virtualDestructor() static bool virtualDestructor()
{ {
return true; return true;
@ -230,208 +198,127 @@ public:
return true; return true;
} }
void memleak(const Tokenizer *tokenizer, const Token *Location, const std::string &varname)
{
_writemsg(tokenizer, Location, "error", "Memory leak: " + varname + "", "memleak");
}
static bool memleak() static bool memleak()
{ {
return true; return true;
} }
void memleakall(const Tokenizer *tokenizer, const Token *Location, const std::string &varname)
{
_writemsg(tokenizer, Location, "all", "Memory leak: " + varname + "", "memleakall");
}
static bool memleakall(const Settings &s) static bool memleakall(const Settings &s)
{ {
return s._showAll; return s._showAll;
} }
void resourceLeak(const Tokenizer *tokenizer, const Token *Location, const std::string &varname)
{
_writemsg(tokenizer, Location, "error", "Resource leak: " + varname + "", "resourceLeak");
}
static bool resourceLeak() static bool resourceLeak()
{ {
return true; return true;
} }
void deallocDealloc(const Tokenizer *tokenizer, const Token *Location, const std::string &varname)
{
_writemsg(tokenizer, Location, "error", "Deallocating a deallocated pointer: " + varname + "", "deallocDealloc");
}
static bool deallocDealloc() static bool deallocDealloc()
{ {
return true; return true;
} }
void deallocuse(const Tokenizer *tokenizer, const Token *Location, const std::string &varname)
{
_writemsg(tokenizer, Location, "error", "Using '" + varname + "' after it is deallocated / released", "deallocuse");
}
static bool deallocuse() static bool deallocuse()
{ {
return true; return true;
} }
void mismatchSize(const Tokenizer *tokenizer, const Token *Location, const std::string &sz)
{
_writemsg(tokenizer, Location, "error", "The given size " + sz + " is mismatching", "mismatchSize");
}
static bool mismatchSize() static bool mismatchSize()
{ {
return true; return true;
} }
void cstyleCast(const Tokenizer *tokenizer, const Token *Location)
{
_writemsg(tokenizer, Location, "style", "C-style pointer casting", "cstyleCast");
}
static bool cstyleCast(const Settings &s) static bool cstyleCast(const Settings &s)
{ {
return s._checkCodingStyle; return s._checkCodingStyle;
} }
void redundantIfDelete0(const Tokenizer *tokenizer, const Token *Location)
{
_writemsg(tokenizer, Location, "style", "Redundant condition. It is safe to deallocate a NULL pointer", "redundantIfDelete0");
}
static bool redundantIfDelete0(const Settings &s) static bool redundantIfDelete0(const Settings &s)
{ {
return s._checkCodingStyle; return s._checkCodingStyle;
} }
void redundantIfRemove(const Tokenizer *tokenizer, const Token *Location)
{
_writemsg(tokenizer, Location, "style", "Redundant condition. The remove function in the STL will not do anything if element doesn't exist", "redundantIfRemove");
}
static bool redundantIfRemove(const Settings &s) static bool redundantIfRemove(const Settings &s)
{ {
return s._checkCodingStyle; return s._checkCodingStyle;
} }
void dangerousUsageStrtol(const Tokenizer *tokenizer, const Token *Location)
{
_writemsg(tokenizer, Location, "error", "Invalid radix in call to strtol or strtoul. Must be 0 or 2-36", "dangerousUsageStrtol");
}
static bool dangerousUsageStrtol() static bool dangerousUsageStrtol()
{ {
return true; return true;
} }
void ifNoAction(const Tokenizer *tokenizer, const Token *Location)
{
_writemsg(tokenizer, Location, "style", "Found redundant if condition - 'if (condition);'", "ifNoAction");
}
static bool ifNoAction(const Settings &s) static bool ifNoAction(const Settings &s)
{ {
return s._checkCodingStyle; return s._checkCodingStyle;
} }
void sprintfOverlappingData(const Tokenizer *tokenizer, const Token *Location, const std::string &varname)
{
_writemsg(tokenizer, Location, "error", "Overlapping data buffer " + varname + "", "sprintfOverlappingData");
}
static bool sprintfOverlappingData() static bool sprintfOverlappingData()
{ {
return true; return true;
} }
void udivError(const Tokenizer *tokenizer, const Token *Location)
{
_writemsg(tokenizer, Location, "error", "Unsigned division. The result will be wrong.", "udivError");
}
static bool udivError() static bool udivError()
{ {
return true; return true;
} }
void udivWarning(const Tokenizer *tokenizer, const Token *Location)
{
_writemsg(tokenizer, Location, "all style", "Warning: Division with signed and unsigned operators", "udivWarning");
}
static bool udivWarning(const Settings &s) static bool udivWarning(const Settings &s)
{ {
return s._checkCodingStyle || s._showAll; return s._checkCodingStyle || s._showAll;
} }
void unusedStructMember(const Tokenizer *tokenizer, const Token *Location, const std::string &structname, const std::string &varname)
{
_writemsg(tokenizer, Location, "style", "struct or union member '" + structname + "::" + varname + "' is never used", "unusedStructMember");
}
static bool unusedStructMember(const Settings &s) static bool unusedStructMember(const Settings &s)
{ {
return s._checkCodingStyle; return s._checkCodingStyle;
} }
void passedByValue(const Tokenizer *tokenizer, const Token *Location, const std::string &parname)
{
_writemsg(tokenizer, Location, "style", "Function parameter '" + parname + "' is passed by value. It could be passed by reference instead.", "passedByValue");
}
static bool passedByValue(const Settings &s) static bool passedByValue(const Settings &s)
{ {
return s._checkCodingStyle; return s._checkCodingStyle;
} }
void constStatement(const Tokenizer *tokenizer, const Token *Location, const std::string &type)
{
_writemsg(tokenizer, Location, "style", "Redundant code: Found a statement that begins with " + type + " constant", "constStatement");
}
static bool constStatement(const Settings &s) static bool constStatement(const Settings &s)
{ {
return s._checkCodingStyle; return s._checkCodingStyle;
} }
void charArrayIndex(const Tokenizer *tokenizer, const Token *Location)
{
_writemsg(tokenizer, Location, "style", "Warning - using char variable as array index", "charArrayIndex");
}
static bool charArrayIndex(const Settings &s) static bool charArrayIndex(const Settings &s)
{ {
return s._checkCodingStyle; return s._checkCodingStyle;
} }
void charBitOp(const Tokenizer *tokenizer, const Token *Location)
{
_writemsg(tokenizer, Location, "style", "Warning - using char variable in bit operation", "charBitOp");
}
static bool charBitOp(const Settings &s) static bool charBitOp(const Settings &s)
{ {
return s._checkCodingStyle; return s._checkCodingStyle;
} }
void variableScope(const Tokenizer *tokenizer, const Token *Location, const std::string &varname)
{
_writemsg(tokenizer, Location, "never", "The scope of the variable " + varname + " can be limited", "variableScope");
}
static bool variableScope() static bool variableScope()
{ {
return false; return false;
} }
void conditionAlwaysTrueFalse(const Tokenizer *tokenizer, const Token *Location, const std::string &truefalse)
{
_writemsg(tokenizer, Location, "style", "Condition is always " + truefalse + "", "conditionAlwaysTrueFalse");
}
static bool conditionAlwaysTrueFalse(const Settings &s) static bool conditionAlwaysTrueFalse(const Settings &s)
{ {
return s._checkCodingStyle; return s._checkCodingStyle;
} }
void strPlusChar(const Tokenizer *tokenizer, const Token *Location)
{
_writemsg(tokenizer, Location, "error", "Unusual pointer arithmetic", "strPlusChar");
}
static bool strPlusChar() static bool strPlusChar()
{ {
return true; return true;
} }
void returnLocalVariable(const Tokenizer *tokenizer, const Token *Location)
{
_writemsg(tokenizer, Location, "error", "Returning pointer to local array variable", "returnLocalVariable");
}
static bool returnLocalVariable() static bool returnLocalVariable()
{ {
return true; return true;
@ -464,33 +351,6 @@ public:
return s._checkCodingStyle; return s._checkCodingStyle;
} }
void iteratorUsage(const Tokenizer *tokenizer, const Token *Location, const std::string &container1, const std::string &container2)
{
_writemsg(tokenizer, Location, "error", "Same iterator is used with both " + container1 + " and " + container2 + "", "iteratorUsage");
}
static bool iteratorUsage()
{
return true;
}
void erase(const Tokenizer *tokenizer, const Token *Location)
{
_writemsg(tokenizer, Location, "error", "Dangerous usage of erase", "erase");
}
static bool erase()
{
return true;
}
void pushback(const Tokenizer *tokenizer, const Token *Location, const std::string &iterator_name)
{
_writemsg(tokenizer, Location, "error", "After push_back or push_front, the iterator '" + iterator_name + "' may be invalid", "pushback");
}
static bool pushback()
{
return true;
}
void unvalidatedInput(const Tokenizer *tokenizer, const Token *Location) void unvalidatedInput(const Tokenizer *tokenizer, const Token *Location)
{ {
_writemsg(tokenizer, Location, "security", "Unvalidated input", "unvalidatedInput"); _writemsg(tokenizer, Location, "security", "Unvalidated input", "unvalidatedInput");