Merge branch 'master' of https://github.com/danmar/cppcheck
This commit is contained in:
commit
1a7f8ffff8
|
@ -512,6 +512,7 @@ void CmdLineParser::PrintHelp()
|
|||
" --enable=id Enable additional checks. The available ids are:\n"
|
||||
" * all - enable all checks\n"
|
||||
" * style - Check coding style\n"
|
||||
" * information - Enable information messages\n"
|
||||
" * unusedFunction - check for unused functions\n"
|
||||
" * missingInclude - check for missing includes\n"
|
||||
" Several ids can be given if you separate them with commas\n"
|
||||
|
|
|
@ -391,6 +391,7 @@ Settings MainWindow::GetCppcheckSettings()
|
|||
}
|
||||
|
||||
result.addEnabled("style");
|
||||
result.addEnabled("information");
|
||||
result.debug = false;
|
||||
result.debugwarnings = mSettings->value(SETTINGS_SHOW_DEBUG_WARNINGS, false).toBool();
|
||||
result._errorsOnly = false;
|
||||
|
|
|
@ -198,8 +198,10 @@ private:
|
|||
*/
|
||||
static bool bailoutIfSwitch(const Token *tok, const unsigned int varid)
|
||||
{
|
||||
// Used later to check if the body belongs to a "if"
|
||||
const std::string str1(tok->str());
|
||||
|
||||
// Count { and }
|
||||
unsigned int indentlevel = 0;
|
||||
for (; tok; tok = tok->next())
|
||||
{
|
||||
|
@ -441,6 +443,7 @@ void CheckBufferOverrun::parse_for_body(const Token *tok2, const ArrayInfo &arra
|
|||
{
|
||||
const std::string pattern((arrayInfo.varid ? std::string("%varid%") : arrayInfo.varname) + " [ " + strindex + " ]");
|
||||
|
||||
// count { and } for tok2
|
||||
int indentlevel2 = 0;
|
||||
for (; tok2; tok2 = tok2->next())
|
||||
{
|
||||
|
@ -567,7 +570,12 @@ void CheckBufferOverrun::checkFunctionCall(const Token &tok, unsigned int par, c
|
|||
if (arrayInfo.element_size == 0)
|
||||
return;
|
||||
|
||||
// arg : the index of the "wanted" argument in the function call.
|
||||
unsigned int arg = it->second;
|
||||
|
||||
// Parse function call. When a ',' is seen, arg is decremented.
|
||||
// if arg becomes 1 then the current function parameter is the wanted parameter.
|
||||
// if arg becomes 1000 then multiply current and next argument.
|
||||
for (const Token *tok2 = tok.tokAt(2); tok2; tok2 = tok2->next())
|
||||
{
|
||||
if (tok2->str() == "(")
|
||||
|
@ -750,6 +758,7 @@ void CheckBufferOverrun::checkScope(const Token *tok, const std::vector<std::str
|
|||
// out of bounds then this flag will be set.
|
||||
bool pointerIsOutOfBounds = false;
|
||||
|
||||
// Count { and } for tok
|
||||
int indentlevel = 0;
|
||||
for (; tok; tok = tok->next())
|
||||
{
|
||||
|
@ -949,6 +958,7 @@ void CheckBufferOverrun::checkScope(const Token *tok, const ArrayInfo &arrayInfo
|
|||
{
|
||||
const MathLib::bigint total_size = arrayInfo.num[0] * arrayInfo.element_size;
|
||||
|
||||
// Count { and } for tok
|
||||
unsigned int indentlevel = 0;
|
||||
for (; tok; tok = tok->next())
|
||||
{
|
||||
|
@ -1208,6 +1218,7 @@ void CheckBufferOverrun::checkScope(const Token *tok, const ArrayInfo &arrayInfo
|
|||
|
||||
void CheckBufferOverrun::checkGlobalAndLocalVariable()
|
||||
{
|
||||
// Count { and } when parsing all tokens
|
||||
int indentlevel = 0;
|
||||
for (const Token *tok = _tokenizer->tokens(); tok; tok = tok->next())
|
||||
{
|
||||
|
@ -1217,9 +1228,16 @@ void CheckBufferOverrun::checkGlobalAndLocalVariable()
|
|||
else if (tok->str() == "}")
|
||||
--indentlevel;
|
||||
|
||||
// size : Max array index
|
||||
MathLib::bigint size = 0;
|
||||
|
||||
// type : The type of a array element
|
||||
std::string type;
|
||||
|
||||
// varid : The variable id for the array
|
||||
unsigned int varid = 0;
|
||||
|
||||
// nextTok : number of tokens used in variable declaration - used to skip to next statement.
|
||||
int nextTok = 0;
|
||||
|
||||
// if the previous token exists, it must be either a variable name or "[;{}]"
|
||||
|
@ -1243,6 +1261,7 @@ void CheckBufferOverrun::checkGlobalAndLocalVariable()
|
|||
|
||||
if (Token::Match(tok, "%type% *| %var% [ %var% ] [;=]"))
|
||||
{
|
||||
// varpos : position for variable token
|
||||
unsigned char varpos = 1;
|
||||
if (tok->next()->str() == "*")
|
||||
++varpos;
|
||||
|
@ -1661,6 +1680,8 @@ void CheckBufferOverrun::checkSprintfCall(const Token *tok, const MathLib::bigin
|
|||
// Parameter is more complex, than just a value or variable. Ignore it for now
|
||||
// and skip to next token.
|
||||
parameters.push_back(0);
|
||||
|
||||
// count parantheses for tok3
|
||||
int ind = 0;
|
||||
for (const Token *tok3 = tok2->next(); tok3; tok3 = tok3->next())
|
||||
{
|
||||
|
@ -1734,6 +1755,7 @@ void CheckBufferOverrun::checkBufferAllocatedWithStrlen()
|
|||
else
|
||||
continue;
|
||||
|
||||
// count { and } for tok
|
||||
int indentlevel = 0;
|
||||
for (; tok && tok->next(); tok = tok->next())
|
||||
{
|
||||
|
@ -1958,6 +1980,7 @@ bool CheckBufferOverrun::ArrayInfo::declare(const Token *tok, const Tokenizer &t
|
|||
tok->str() == "extern"))
|
||||
tok = tok->next();
|
||||
|
||||
// ivar : number of type tokens
|
||||
int ivar = 0;
|
||||
if (Token::Match(tok, "%type% *| %var% ["))
|
||||
ivar = 1;
|
||||
|
|
|
@ -891,7 +891,7 @@ void CheckClass::thisSubtractionError(const Token *tok)
|
|||
|
||||
void CheckClass::checkConst()
|
||||
{
|
||||
if (!_settings->_checkCodingStyle || _settings->ifcfg)
|
||||
if (!_settings->isEnabled("information") || _settings->ifcfg)
|
||||
return;
|
||||
|
||||
// Don't check C# and JAVA classes
|
||||
|
|
|
@ -86,7 +86,7 @@ void CheckNullPointer::parseFunctionCall(const Token &tok, std::list<const Token
|
|||
var.push_back(tok.tokAt(2));
|
||||
else if (value == 0 && Token::Match(&tok, "memchr|memcmp|memcpy|memmove|memset|strcpy|printf|sprintf|snprintf"))
|
||||
var.push_back(tok.tokAt(2));
|
||||
else if (Token::simpleMatch(&tok, "fflush"))
|
||||
else if (value != 0 && Token::simpleMatch(&tok, "fflush"))
|
||||
var.push_back(tok.tokAt(2));
|
||||
}
|
||||
|
||||
|
@ -430,20 +430,28 @@ void CheckNullPointer::nullPointerStructByDeRefAndChec()
|
|||
void CheckNullPointer::nullPointerByDeRefAndChec()
|
||||
{
|
||||
// Dereferencing a pointer and then checking if it's NULL..
|
||||
// This check will first scan for the check. And then scan backwards
|
||||
// from the check, searching for dereferencing.
|
||||
for (const Token *tok = _tokenizer->tokens(); tok; tok = tok->next())
|
||||
{
|
||||
// TODO: false negatives.
|
||||
// - logical operators
|
||||
// - while
|
||||
if (tok->str() == "if" && Token::Match(tok->previous(), "; if ( ! %var% )"))
|
||||
{
|
||||
// Variable id for pointer
|
||||
const unsigned int varid(tok->tokAt(3)->varId());
|
||||
if (varid == 0)
|
||||
continue;
|
||||
|
||||
// Name of pointer
|
||||
const std::string varname(tok->strAt(3));
|
||||
|
||||
// Check that variable is a pointer..
|
||||
if (!isPointer(varid))
|
||||
continue;
|
||||
|
||||
// Token where pointer is declared
|
||||
const Token * const decltok = Token::findmatch(_tokenizer->tokens(), "%varid%", varid);
|
||||
|
||||
for (const Token *tok1 = tok->previous(); tok1 && tok1 != decltok; tok1 = tok1->previous())
|
||||
|
@ -455,7 +463,10 @@ void CheckNullPointer::nullPointerByDeRefAndChec()
|
|||
|
||||
if (tok1->varId() == varid)
|
||||
{
|
||||
// unknown : this is set by isPointerDeRef if it is
|
||||
// uncertain
|
||||
bool unknown = false;
|
||||
|
||||
if (Token::Match(tok1->tokAt(-2), "%varid% = %varid% .", varid))
|
||||
{
|
||||
break;
|
||||
|
@ -490,7 +501,11 @@ void CheckNullPointer::nullPointerByDeRefAndChec()
|
|||
void CheckNullPointer::nullPointerByCheckAndDeRef()
|
||||
{
|
||||
// Check if pointer is NULL and then dereference it..
|
||||
|
||||
// used to check if a variable is a pointer.
|
||||
// TODO: Use isPointer?
|
||||
std::set<unsigned int> pointerVariables;
|
||||
|
||||
for (const Token *tok = _tokenizer->tokens(); tok; tok = tok->next())
|
||||
{
|
||||
if (Token::Match(tok, "* %var% [;,)=]"))
|
||||
|
@ -498,6 +513,12 @@ void CheckNullPointer::nullPointerByCheckAndDeRef()
|
|||
|
||||
else if (Token::Match(tok, "if ("))
|
||||
{
|
||||
// TODO: investigate false negatives:
|
||||
// - handle "while"?
|
||||
// - if there are logical operators
|
||||
// - if (x) { } else { ... }
|
||||
|
||||
// vartok : token for the variable
|
||||
const Token *vartok = 0;
|
||||
if (Token::Match(tok, "if ( ! %var% ) {"))
|
||||
vartok = tok->tokAt(3);
|
||||
|
@ -508,16 +529,22 @@ void CheckNullPointer::nullPointerByCheckAndDeRef()
|
|||
else
|
||||
continue;
|
||||
|
||||
bool null = true;
|
||||
// variable id for pointer
|
||||
const unsigned int varid(vartok->varId());
|
||||
if (varid == 0)
|
||||
continue;
|
||||
|
||||
// Check if variable is a pointer. TODO: Use isPointer?
|
||||
if (pointerVariables.find(varid) == pointerVariables.end())
|
||||
continue;
|
||||
|
||||
// if this is true then it is known that the pointer is null
|
||||
bool null = true;
|
||||
|
||||
// Name of the pointer
|
||||
const std::string &pointerName = vartok->str();
|
||||
|
||||
// Count { and } for tok2
|
||||
unsigned int indentlevel = 1;
|
||||
for (const Token *tok2 = tok->next()->link()->tokAt(2); tok2; tok2 = tok2->next())
|
||||
{
|
||||
|
@ -553,13 +580,17 @@ void CheckNullPointer::nullPointerByCheckAndDeRef()
|
|||
|
||||
// calling unknown function (abort/init)..
|
||||
if (Token::simpleMatch(tok2, ") ;") &&
|
||||
Token::Match(tok2->link()->tokAt(-2), "[;{}] %var% ("))
|
||||
(Token::Match(tok2->link()->tokAt(-2), "[;{}] %var% (") ||
|
||||
Token::Match(tok2->link()->tokAt(-5), "[;{}] ( * %var% ) (")))
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if (tok2->varId() == varid)
|
||||
{
|
||||
// unknown: this is set to true by isPointerDeRef if
|
||||
// the function fails to determine if there
|
||||
// is a dereference or not
|
||||
bool unknown = false;
|
||||
|
||||
if (Token::Match(tok2->previous(), "[;{}=] %var% = 0 ;"))
|
||||
|
@ -816,7 +847,11 @@ private:
|
|||
|
||||
if (tok.varId() != 0)
|
||||
{
|
||||
// unknown : not really used. it is passed to isPointerDeRef.
|
||||
// if isPointerDeRef fails to determine if there
|
||||
// is a dereference the this will be set to true.
|
||||
bool unknown = false;
|
||||
|
||||
if (Token::Match(tok.previous(), "[;{}=] %var% = 0 ;"))
|
||||
setnull(checks, tok.varId());
|
||||
else if (CheckNullPointer::isPointerDeRef(&tok, unknown))
|
||||
|
|
|
@ -520,6 +520,19 @@ void CheckOther::checkUnsignedDivision()
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// memset(p, y, 0 /* bytes to fill */) <- 2nd and 3rd arguments inverted
|
||||
//---------------------------------------------------------------------------
|
||||
void CheckOther::checkMemsetZeroBytes()
|
||||
{
|
||||
const Token *tok = _tokenizer->tokens();
|
||||
while (tok && ((tok = Token::findmatch(tok, "memset ( %var% , %num% , 0 )")) != NULL))
|
||||
{
|
||||
memsetZeroBytesError(tok, tok->strAt(2));
|
||||
tok = tok->tokAt(8);
|
||||
}
|
||||
}
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
|
||||
|
@ -1887,7 +1900,7 @@ void CheckOther::unassignedVariableError(const Token *tok, const std::string &va
|
|||
|
||||
void CheckOther::checkVariableScope()
|
||||
{
|
||||
if (!_settings->_checkCodingStyle)
|
||||
if (!_settings->isEnabled("information"))
|
||||
return;
|
||||
|
||||
SymbolDatabase *symbolDatabase = _tokenizer->getSymbolDatabase();
|
||||
|
@ -2803,3 +2816,10 @@ void CheckOther::catchExceptionByValueError(const Token *tok)
|
|||
"The exception is caught as a value. It could be caught "
|
||||
"as a (const) reference which is usually recommended in C++.");
|
||||
}
|
||||
|
||||
void CheckOther::memsetZeroBytesError(const Token *tok, const std::string &varname)
|
||||
{
|
||||
reportError(tok, Severity::warning,
|
||||
"memsetZeroBytes", "memset() called to fill 0 bytes of \"" + varname + "\""
|
||||
". Second and third arguments might be inverted.");
|
||||
}
|
||||
|
|
|
@ -83,6 +83,7 @@ public:
|
|||
checkOther.checkIncorrectLogicOperator();
|
||||
checkOther.checkMisusedScopedObject();
|
||||
checkOther.checkCatchExceptionByValue();
|
||||
checkOther.checkMemsetZeroBytes();
|
||||
}
|
||||
|
||||
/** @brief Are there C-style pointer casts in a c++ file? */
|
||||
|
@ -166,6 +167,9 @@ public:
|
|||
/** @brief %Check for exceptions that are caught by value instead of by reference */
|
||||
void checkCatchExceptionByValue();
|
||||
|
||||
/** @brief %Check for filling zero bytes with memset() */
|
||||
void checkMemsetZeroBytes();
|
||||
|
||||
// Error messages..
|
||||
void cstyleCastError(const Token *tok);
|
||||
void dangerousUsageStrtolError(const Token *tok);
|
||||
|
@ -188,6 +192,7 @@ public:
|
|||
void incorrectLogicOperatorError(const Token *tok);
|
||||
void misusedScopeObjectError(const Token *tok, const std::string &varname);
|
||||
void catchExceptionByValueError(const Token *tok);
|
||||
void memsetZeroBytesError(const Token *tok, const std::string &varname);
|
||||
|
||||
void getErrorMessages(ErrorLogger *errorLogger, const Settings *settings)
|
||||
{
|
||||
|
@ -224,6 +229,7 @@ public:
|
|||
c.unreadVariableError(0, "varname");
|
||||
c.unassignedVariableError(0, "varname");
|
||||
c.catchExceptionByValueError(0);
|
||||
c.memsetZeroBytesError(0, "varname");
|
||||
}
|
||||
|
||||
std::string name() const
|
||||
|
|
|
@ -229,18 +229,24 @@ void CheckStl::stlOutOfBounds()
|
|||
|
||||
if (Token::Match(tok2, "; %var% <= %var% . size ( ) ;"))
|
||||
{
|
||||
unsigned int indent2 = 0;
|
||||
// Count { and } for tok3
|
||||
unsigned int indent3 = 0;
|
||||
|
||||
// variable id for loop variable.
|
||||
unsigned int numId = tok2->tokAt(1)->varId();
|
||||
|
||||
// variable id for the container variable
|
||||
unsigned int varId = tok2->tokAt(3)->varId();
|
||||
|
||||
for (const Token *tok3 = tok2->tokAt(8); tok3; tok3 = tok3->next())
|
||||
{
|
||||
if (tok3->str() == "{")
|
||||
++indent2;
|
||||
++indent3;
|
||||
else if (tok3->str() == "}")
|
||||
{
|
||||
if (indent2 <= 1)
|
||||
if (indent3 <= 1)
|
||||
break;
|
||||
--indent2;
|
||||
--indent3;
|
||||
}
|
||||
else if (tok3->varId() == varId)
|
||||
{
|
||||
|
@ -470,11 +476,16 @@ void CheckStl::pushback()
|
|||
{
|
||||
if (Token::Match(tok, "%var% = & %var% ["))
|
||||
{
|
||||
// Variable id for pointer
|
||||
const unsigned int pointerId(tok->varId());
|
||||
|
||||
// Variable id for the container variable
|
||||
const unsigned int containerId(tok->tokAt(3)->varId());
|
||||
|
||||
if (pointerId == 0 || containerId == 0)
|
||||
continue;
|
||||
|
||||
// Count { , } and parantheses for tok2
|
||||
int indent = 0;
|
||||
bool invalidPointer = false;
|
||||
for (const Token *tok2 = tok; indent >= 0 && tok2; tok2 = tok2->next())
|
||||
|
@ -537,8 +548,12 @@ void CheckStl::pushback()
|
|||
tok = tok->tokAt(3);
|
||||
}
|
||||
|
||||
// the variable id for the vector
|
||||
unsigned int vectorid = 0;
|
||||
|
||||
// count { , } and parantheses for tok2
|
||||
int indent = 0;
|
||||
|
||||
std::string invalidIterator;
|
||||
for (const Token *tok2 = tok; indent >= 0 && tok2; tok2 = tok2->next())
|
||||
{
|
||||
|
@ -560,11 +575,14 @@ void CheckStl::pushback()
|
|||
|
||||
if (Token::Match(tok2, "%varid% = %var% . begin ( ) ; %varid% != %var% . end ( ) ; ++| %varid% ++| ) {", iteratorid))
|
||||
{
|
||||
// variable id for the loop iterator
|
||||
const unsigned int varId(tok2->tokAt(2)->varId());
|
||||
if (varId == 0)
|
||||
continue;
|
||||
|
||||
const Token *pushbackTok = 0;
|
||||
|
||||
// Count { and } for tok3
|
||||
unsigned int indent3 = 0;
|
||||
for (const Token *tok3 = tok2->tokAt(20); tok3; tok3 = tok3->next())
|
||||
{
|
||||
|
@ -929,7 +947,10 @@ void CheckStl::missingComparison()
|
|||
continue;
|
||||
|
||||
const Token *incrementToken = 0;
|
||||
|
||||
// Count { and } for tok3
|
||||
unsigned int indentlevel = 0;
|
||||
|
||||
// Parse loop..
|
||||
for (const Token *tok3 = tok2->tokAt(20); tok3; tok3 = tok3->next())
|
||||
{
|
||||
|
|
|
@ -600,7 +600,7 @@ private:
|
|||
{
|
||||
// sizeof/typeof doesn't dereference. A function name that is all uppercase
|
||||
// might be an unexpanded macro that uses sizeof/typeof
|
||||
if (Token::Match(&tok, "sizeof|typeof (") || isUpper(tok.str()))
|
||||
if (Token::Match(&tok, "sizeof|typeof ("))
|
||||
return tok.next()->link();
|
||||
|
||||
// deallocate pointer
|
||||
|
@ -690,8 +690,22 @@ private:
|
|||
{
|
||||
if (Token::Match(tok2->tokAt(-2), "[(,] *") || Token::Match(tok2->next(), ". %var%"))
|
||||
{
|
||||
if (use_dead_pointer(checks, tok2))
|
||||
ExecutionPath::bailOutVar(checks, tok2->varId());
|
||||
// find function call..
|
||||
const Token *functionCall = tok2;
|
||||
while (0 != (functionCall = functionCall ? functionCall->previous() : 0))
|
||||
{
|
||||
if (functionCall->str() == "(")
|
||||
break;
|
||||
if (functionCall->str() == ")")
|
||||
functionCall = functionCall->link();
|
||||
}
|
||||
|
||||
functionCall = functionCall ? functionCall->previous() : 0;
|
||||
if (functionCall)
|
||||
{
|
||||
if (functionCall->isName() && !isUpper(functionCall->str()) && use_dead_pointer(checks, tok2))
|
||||
ExecutionPath::bailOutVar(checks, tok2->varId());
|
||||
}
|
||||
}
|
||||
|
||||
// it is possible that the variable is initialized here
|
||||
|
|
|
@ -122,7 +122,7 @@ static void parseIfSwitchBody(const Token * const tok,
|
|||
std::list<ExecutionPath *>::const_iterator it;
|
||||
for (it = checks.begin(); it != checks.end(); ++it)
|
||||
{
|
||||
if (*(*it) == *c.back())
|
||||
if (*(*it) == *c.back() && (*it)->numberOfIf == c.back()->numberOfIf)
|
||||
{
|
||||
duplicate = true;
|
||||
countif2.erase((*it)->varId);
|
||||
|
|
|
@ -195,6 +195,7 @@ std::string Settings::addEnabled(const std::string &str)
|
|||
std::set<std::string> id;
|
||||
id.insert("missingInclude");
|
||||
id.insert("unusedFunction");
|
||||
id.insert("information");
|
||||
|
||||
if (str == "all")
|
||||
{
|
||||
|
|
|
@ -1574,6 +1574,41 @@ void SymbolDatabase::SpaceInfo::initializeVarList(const Func &func, std::list<st
|
|||
}
|
||||
|
||||
// Calling member function?
|
||||
else if (Token::simpleMatch(ftok, "operator = ("))
|
||||
{
|
||||
// check if member function exists
|
||||
std::list<Func>::const_iterator it;
|
||||
for (it = functionList.begin(); it != functionList.end(); ++it)
|
||||
{
|
||||
if (ftok->next()->str() == it->tokenDef->str() && it->type != Func::Constructor)
|
||||
break;
|
||||
}
|
||||
|
||||
// member function found
|
||||
if (it != functionList.end())
|
||||
{
|
||||
// member function has implementation
|
||||
if (it->hasBody)
|
||||
{
|
||||
// initialize variable use list using member function
|
||||
callstack.push_back(ftok->str());
|
||||
initializeVarList(*it, callstack);
|
||||
callstack.pop_back();
|
||||
}
|
||||
|
||||
// there is a called member function, but it has no implementation, so we assume it initializes everything
|
||||
else
|
||||
{
|
||||
assignAllVar();
|
||||
}
|
||||
}
|
||||
|
||||
// using default operator =, assume everything initialized
|
||||
else
|
||||
{
|
||||
assignAllVar();
|
||||
}
|
||||
}
|
||||
else if (Token::Match(ftok, "%var% (") && ftok->str() != "if")
|
||||
{
|
||||
// Passing "this" => assume that everything is initialized
|
||||
|
|
|
@ -4374,6 +4374,7 @@ void Tokenizer::removeRedundantAssignment()
|
|||
|
||||
bool Tokenizer::removeReduntantConditions()
|
||||
{
|
||||
// Return value for function. Set to true if there are any simplifications
|
||||
bool ret = false;
|
||||
|
||||
for (Token *tok = _tokens; tok; tok = tok->next())
|
||||
|
@ -6132,6 +6133,7 @@ Token * Tokenizer::initVar(Token * tok)
|
|||
|
||||
bool Tokenizer::simplifyKnownVariables()
|
||||
{
|
||||
// return value for function. Set to true if any simplifications are made
|
||||
bool ret = false;
|
||||
|
||||
// constants..
|
||||
|
@ -7709,6 +7711,8 @@ void Tokenizer::simplifyEnum()
|
|||
if (enumType)
|
||||
{
|
||||
const std::string pattern(className.empty() ? "" : (className + " :: " + enumType->str()).c_str());
|
||||
|
||||
// count { and } for tok2
|
||||
int level = 0;
|
||||
bool inScope = true;
|
||||
|
||||
|
@ -8311,6 +8315,8 @@ bool Tokenizer::validate() const
|
|||
std::string Tokenizer::simplifyString(const std::string &source)
|
||||
{
|
||||
std::string str = source;
|
||||
|
||||
// true when previous char is a \ .
|
||||
bool escaped = false;
|
||||
for (std::string::size_type i = 0; i + 2 < str.size(); i++)
|
||||
{
|
||||
|
@ -8599,6 +8605,7 @@ void Tokenizer::simplifyFuncInWhile()
|
|||
|
||||
void Tokenizer::simplifyStructDecl()
|
||||
{
|
||||
// A counter that is used when giving unique names for anonymous structs.
|
||||
unsigned int count = 0;
|
||||
|
||||
// Skip simplification of unions in class definition
|
||||
|
@ -8901,10 +8908,10 @@ void Tokenizer::simplifyBitfields()
|
|||
for (Token *tok = _tokens; tok; tok = tok->next())
|
||||
{
|
||||
Token *last = 0;
|
||||
int offset = 0;
|
||||
|
||||
if (Token::Match(tok, ";|{|}|public:|protected:|private: const| %type% %var% : %num% ;|,"))
|
||||
{
|
||||
int offset = 0;
|
||||
if (tok->next()->str() == "const")
|
||||
offset = 1;
|
||||
|
||||
|
@ -8913,6 +8920,7 @@ void Tokenizer::simplifyBitfields()
|
|||
}
|
||||
else if (Token::Match(tok, ";|{|}|public:|protected:|private: const| %type% : %num% ;"))
|
||||
{
|
||||
int offset = 0;
|
||||
if (tok->next()->str() == "const")
|
||||
offset = 1;
|
||||
|
||||
|
@ -8943,6 +8951,7 @@ void Tokenizer::simplifyBuiltinExpect()
|
|||
{
|
||||
if (Token::simpleMatch(tok->next(), "__builtin_expect ("))
|
||||
{
|
||||
// Count parantheses for tok2
|
||||
unsigned int parlevel = 0;
|
||||
for (Token *tok2 = tok->next(); tok2; tok2 = tok2->next())
|
||||
{
|
||||
|
@ -9024,6 +9033,7 @@ void Tokenizer::simplifyBorland()
|
|||
|
||||
if (Token::Match(tok, "class %var% :|{"))
|
||||
{
|
||||
// count { and } for tok2
|
||||
unsigned int indentlevel = 0;
|
||||
for (Token *tok2 = tok; tok2; tok2 = tok2->next())
|
||||
{
|
||||
|
@ -9066,6 +9076,7 @@ void Tokenizer::simplifyQtSignalsSlots()
|
|||
Token *tok = _tokens;
|
||||
while ((tok = const_cast<Token *>(Token::findmatch(tok, "class %var% :"))))
|
||||
{
|
||||
// count { and } for tok2
|
||||
unsigned int indentlevel = 0;
|
||||
for (Token *tok2 = tok; tok2; tok2 = tok2->next())
|
||||
{
|
||||
|
|
|
@ -21,7 +21,7 @@ sub checkfile
|
|||
# missing comment before variable declaration?
|
||||
if (($comment == 0) &&
|
||||
($line =~ /^\s+([a-z]+)? [a-z]+(\s)+[a-z][a-z0-9]*\s*[;=]/) &&
|
||||
(!($line =~ /return|delete/)))
|
||||
(!($line =~ /return|delete|operator/)))
|
||||
{
|
||||
print "[$filename:$linenr] No comment before variable declaration\n";
|
||||
}
|
||||
|
|
|
@ -19,7 +19,7 @@ sub checkfile
|
|||
$linenr = $linenr + 1;
|
||||
|
||||
# is there a magic number?
|
||||
if (($line =~ /[^a-zA-Z_][0-9]{3,}/) &&
|
||||
if (($line =~ /[^a-zA-Z0-9_][0-9]{3,}/) &&
|
||||
(!($line =~ /define|const|(\/\/)/)))
|
||||
{
|
||||
print "[$filename:$linenr] Magic number\n";
|
||||
|
|
|
@ -89,6 +89,7 @@ private:
|
|||
TEST_CASE(uninitSameClassName); // No FP when two classes have the same name
|
||||
TEST_CASE(uninitFunctionOverload); // No FP when there are overloaded functions
|
||||
TEST_CASE(uninitJava); // Java: no FP when variable is initialized in declaration
|
||||
TEST_CASE(uninitVarOperatorEqual); // ticket #2415
|
||||
|
||||
TEST_CASE(noConstructor1);
|
||||
TEST_CASE(noConstructor2);
|
||||
|
@ -2706,6 +2707,37 @@ private:
|
|||
ASSERT_EQUALS("", errout.str());
|
||||
}
|
||||
|
||||
void uninitVarOperatorEqual() // ticket #2415
|
||||
{
|
||||
checkUninitVar("struct A {\n"
|
||||
" int a;\n"
|
||||
" A() { a=0; }\n"
|
||||
" A(A const &a) { operator=(a); }\n"
|
||||
"};");
|
||||
ASSERT_EQUALS("", errout.str());
|
||||
|
||||
checkUninitVar("struct A {\n"
|
||||
" int a;\n"
|
||||
" A() { a=0; }\n"
|
||||
" A(A const &a) { operator=(a); }\n"
|
||||
" A & operator = (const A & rhs) {\n"
|
||||
" a = rhs.a;\n"
|
||||
" return *this;\n"
|
||||
" }\n"
|
||||
"};");
|
||||
ASSERT_EQUALS("", errout.str());
|
||||
|
||||
checkUninitVar("struct A {\n"
|
||||
" int a;\n"
|
||||
" A() { a=0; }\n"
|
||||
" A(A const &a) { operator=(a); }\n"
|
||||
" A & operator = (const A & rhs) {\n"
|
||||
" return *this;\n"
|
||||
" }\n"
|
||||
"};");
|
||||
ASSERT_EQUALS("[test.cpp:4]: (warning) Member variable 'A::a' is not initialised in the constructor.\n"
|
||||
"[test.cpp:5]: (warning) Member variable 'A::a' is not assigned a value in 'A::operator='\n", errout.str());
|
||||
}
|
||||
|
||||
void checkNoConstructor(const char code[])
|
||||
{
|
||||
|
@ -2929,7 +2961,7 @@ private:
|
|||
if (s)
|
||||
settings = *s;
|
||||
else
|
||||
settings._checkCodingStyle = true;
|
||||
settings.addEnabled("information");
|
||||
|
||||
// Tokenize..
|
||||
Tokenizer tokenizer(&settings, this);
|
||||
|
@ -5218,7 +5250,7 @@ private:
|
|||
"};";
|
||||
|
||||
Settings settings;
|
||||
settings._checkCodingStyle = true;
|
||||
settings.addEnabled("information");
|
||||
|
||||
settings.ifcfg = false;
|
||||
checkConst(code, &settings);
|
||||
|
|
|
@ -754,6 +754,14 @@ private:
|
|||
"}\n");
|
||||
ASSERT_EQUALS("", errout.str());
|
||||
|
||||
check("void foo(char *p) {\n"
|
||||
" if (!p) {\n"
|
||||
" (*bail)();\n"
|
||||
" }\n"
|
||||
" *p = 0;\n"
|
||||
"}\n");
|
||||
ASSERT_EQUALS("", errout.str());
|
||||
|
||||
check("void foo(char *p) {\n"
|
||||
" if (!p) {\n"
|
||||
" throw x;\n"
|
||||
|
@ -813,6 +821,13 @@ private:
|
|||
" strcpy(p, \"abcd\");\n"
|
||||
"}\n");
|
||||
ASSERT_EQUALS("[test.cpp:3]: (error) Null pointer dereference\n", errout.str());
|
||||
|
||||
// Ticket #2413 - it's ok to pass NULL to fflush
|
||||
check("void foo() {\n"
|
||||
" fflush(NULL);\n"
|
||||
"}\n");
|
||||
ASSERT_EQUALS("", errout.str());
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
|
|
|
@ -94,6 +94,8 @@ private:
|
|||
TEST_CASE(assignmentInAssert);
|
||||
TEST_CASE(incorrectLogicOperator);
|
||||
TEST_CASE(catchExceptionByValue);
|
||||
|
||||
TEST_CASE(memsetZeroBytes);
|
||||
}
|
||||
|
||||
void check(const char code[], const char *filename = NULL)
|
||||
|
@ -127,6 +129,7 @@ private:
|
|||
checkOther.checkMisusedScopedObject();
|
||||
checkOther.checkIncorrectLogicOperator();
|
||||
checkOther.checkCatchExceptionByValue();
|
||||
checkOther.checkMemsetZeroBytes();
|
||||
}
|
||||
|
||||
|
||||
|
@ -378,7 +381,7 @@ private:
|
|||
errout.str("");
|
||||
|
||||
Settings settings;
|
||||
settings._checkCodingStyle = true;
|
||||
settings.addEnabled("information");
|
||||
|
||||
// Tokenize..
|
||||
Tokenizer tokenizer(&settings, this);
|
||||
|
@ -1614,6 +1617,23 @@ private:
|
|||
);
|
||||
ASSERT_EQUALS("", errout.str());
|
||||
}
|
||||
|
||||
void memsetZeroBytes()
|
||||
{
|
||||
check("void f() {\n"
|
||||
" memset(p, 10, 0)\n"
|
||||
"}\n"
|
||||
);
|
||||
ASSERT_EQUALS("[test.cpp:2]: (warning) memset() called to fill 0"
|
||||
" bytes of \"p\". Second and third arguments might be inverted.\n", errout.str());
|
||||
|
||||
check("void f() {\n"
|
||||
" memset(p, sizeof(p), 0)\n"
|
||||
"}\n"
|
||||
);
|
||||
TODO_ASSERT_EQUALS("[test.cpp:2]: (warning) memset() called to fill 0"
|
||||
" bytes of \"p\". Second and third arguments might be inverted.\n", errout.str());
|
||||
}
|
||||
};
|
||||
|
||||
REGISTER_TEST(TestOther)
|
||||
|
|
|
@ -231,6 +231,7 @@ private:
|
|||
TEST_CASE(simplifyTypedef71); // ticket #2348
|
||||
TEST_CASE(simplifyTypedef72); // ticket #2375
|
||||
TEST_CASE(simplifyTypedef73); // ticket #2412
|
||||
TEST_CASE(simplifyTypedef74); // ticket #2414
|
||||
|
||||
TEST_CASE(simplifyTypedefFunction1);
|
||||
TEST_CASE(simplifyTypedefFunction2); // ticket #1685
|
||||
|
@ -4772,6 +4773,19 @@ private:
|
|||
ASSERT_EQUALS("", errout.str());
|
||||
}
|
||||
|
||||
void simplifyTypedef74() // ticket #2414
|
||||
{
|
||||
const char code[] = "typedef long (*state_func_t)(void);\n"
|
||||
"typedef state_func_t (*state_t)(void);\n"
|
||||
"state_t current_state = death;\n"
|
||||
"static char get_runlevel(const state_t);\n";
|
||||
const std::string expected = "; "
|
||||
"long ( * ( * current_state ) ( void ) ) ( void ) = death ; "
|
||||
"static char get_runlevel ( const long ( * ( * ) ( void ) ) ( void ) ) ;";
|
||||
ASSERT_EQUALS(expected, sizeof_(code));
|
||||
ASSERT_EQUALS("", errout.str());
|
||||
}
|
||||
|
||||
void simplifyTypedefFunction1()
|
||||
{
|
||||
{
|
||||
|
|
|
@ -597,7 +597,8 @@ private:
|
|||
" }\n"
|
||||
" }\n"
|
||||
"}\n");
|
||||
ASSERT_EQUALS("[test.cpp:9]: (error) Dangerous iterator usage after erase()-method.\n", errout.str());
|
||||
TODO_ASSERT_EQUALS("[test.cpp:9]: (error) Dangerous iterator usage after erase()-method.\n", errout.str());
|
||||
ASSERT_EQUALS("", errout.str());
|
||||
}
|
||||
|
||||
void eraseGoto()
|
||||
|
|
|
@ -637,6 +637,18 @@ private:
|
|||
"}\n");
|
||||
ASSERT_EQUALS("", errout.str());
|
||||
|
||||
checkUninitVar("int test(int cond1, int cond2) {\n"
|
||||
" int foo;\n"
|
||||
" if (cond1 || cond2) {\n"
|
||||
" if (cond2)\n"
|
||||
" foo = 0;\n"
|
||||
" }\n"
|
||||
" if (cond2) {\n"
|
||||
" int t = foo*foo;\n"
|
||||
" }\n"
|
||||
"}\n");
|
||||
ASSERT_EQUALS("", errout.str());
|
||||
|
||||
// ? :
|
||||
checkUninitVar("static void foo(int v)\n"
|
||||
"{\n"
|
||||
|
@ -1354,6 +1366,14 @@ private:
|
|||
TODO_ASSERT_EQUALS("[test.cpp:4]: (error) Uninitialized variable: x\n", errout.str());
|
||||
ASSERT_EQUALS("", errout.str());
|
||||
|
||||
// #2401 - unknown function/macro might init the variable
|
||||
checkUninitVar("int f() {\n"
|
||||
" int x;\n"
|
||||
" INIT(x);\n"
|
||||
" return x;\n"
|
||||
"}\n");
|
||||
ASSERT_EQUALS("", errout.str());
|
||||
|
||||
// using uninitialized function pointer..
|
||||
checkUninitVar("void foo()\n"
|
||||
"{\n"
|
||||
|
|
Loading…
Reference in New Issue