- Solved FIXME: Made detection of code that is no pointer-dereference more robust, uncommented code (checknullpointer.cpp)
- Removed more indendation level counters - Make use of symbol database more often - Other refactorizations
This commit is contained in:
parent
87e19d2552
commit
36479499e7
|
@ -119,16 +119,18 @@ void CheckInternal::checkTokenSimpleMatchPatterns()
|
||||||
|
|
||||||
void CheckInternal::checkMissingPercentCharacter()
|
void CheckInternal::checkMissingPercentCharacter()
|
||||||
{
|
{
|
||||||
std::set<std::string> magics;
|
static std::set<std::string> magics;
|
||||||
magics.insert("%any%");
|
if (magics.empty()) {
|
||||||
magics.insert("%var%");
|
magics.insert("%any%");
|
||||||
magics.insert("%type%");
|
magics.insert("%var%");
|
||||||
magics.insert("%num%");
|
magics.insert("%type%");
|
||||||
magics.insert("%bool%");
|
magics.insert("%num%");
|
||||||
magics.insert("%str%");
|
magics.insert("%bool%");
|
||||||
magics.insert("%varid%");
|
magics.insert("%str%");
|
||||||
magics.insert("%or%");
|
magics.insert("%varid%");
|
||||||
magics.insert("%oror%");
|
magics.insert("%or%");
|
||||||
|
magics.insert("%oror%");
|
||||||
|
}
|
||||||
|
|
||||||
for (const Token *tok = _tokenizer->tokens(); tok; tok = tok->next()) {
|
for (const Token *tok = _tokenizer->tokens(); tok; tok = tok->next()) {
|
||||||
if (!Token::simpleMatch(tok, "Token :: Match (") && !Token::simpleMatch(tok, "Token :: findmatch ("))
|
if (!Token::simpleMatch(tok, "Token :: Match (") && !Token::simpleMatch(tok, "Token :: findmatch ("))
|
||||||
|
|
|
@ -37,7 +37,7 @@ namespace {
|
||||||
bool CheckNullPointer::isUpper(const std::string &str)
|
bool CheckNullPointer::isUpper(const std::string &str)
|
||||||
{
|
{
|
||||||
for (unsigned int i = 0; i < str.length(); ++i) {
|
for (unsigned int i = 0; i < str.length(); ++i) {
|
||||||
if (str[i] >= 'a' && str[i] <= 'z')
|
if (std::islower(str[i]))
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
@ -234,10 +234,7 @@ bool CheckNullPointer::isPointerDeRef(const Token *tok, bool &unknown)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Token::Match(tok->previous(), "[;{}=+-/(,] %var% ["))
|
if (Token::Match(tok->previous(), "!!& %var% ["))
|
||||||
return true;
|
|
||||||
|
|
||||||
if (Token::Match(tok->previous(), "return %var% ["))
|
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
if (Token::Match(tok, "%var% ("))
|
if (Token::Match(tok, "%var% ("))
|
||||||
|
@ -252,7 +249,7 @@ bool CheckNullPointer::isPointerDeRef(const Token *tok, bool &unknown)
|
||||||
// This is most useful in inconclusive checking
|
// This is most useful in inconclusive checking
|
||||||
if (inconclusive) {
|
if (inconclusive) {
|
||||||
// Not a dereference..
|
// Not a dereference..
|
||||||
if (Token::Match(tok->previous(), "[;{}(] %var% ="))
|
if (Token::Match(tok, "%var% ="))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// OK to delete a null
|
// OK to delete a null
|
||||||
|
@ -261,7 +258,7 @@ bool CheckNullPointer::isPointerDeRef(const Token *tok, bool &unknown)
|
||||||
|
|
||||||
// OK to check if pointer is null
|
// OK to check if pointer is null
|
||||||
// OK to take address of pointer
|
// OK to take address of pointer
|
||||||
if (Token::Match(tok->previous(), "!|& %var% )|,|&&|%oror%"))
|
if (Token::Match(tok->previous(), "!|& %var%"))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// OK to pass pointer to function
|
// OK to pass pointer to function
|
||||||
|
@ -269,7 +266,9 @@ bool CheckNullPointer::isPointerDeRef(const Token *tok, bool &unknown)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// Compare pointer
|
// Compare pointer
|
||||||
if (Token::Match(tok->previous(), "(|&&|%oror%|==|!= %var% &&|%oror%|)"))
|
if (Token::Match(tok->previous(), "(|&&|%oror%|==|!= %var%"))
|
||||||
|
return false;
|
||||||
|
if (Token::Match(tok, "%var% &&|%oror%|==|!=|)"))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// Taking address
|
// Taking address
|
||||||
|
@ -277,11 +276,7 @@ bool CheckNullPointer::isPointerDeRef(const Token *tok, bool &unknown)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// unknown if it's a dereference
|
// unknown if it's a dereference
|
||||||
// FIXME: Uncomment this. We just need to fix false positives
|
unknown = true;
|
||||||
// when cppcheck source code is checked before it can
|
|
||||||
// be uncommented. We need to have better checks to
|
|
||||||
// determine when there is NOT a pointer dereference.
|
|
||||||
//unknown = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// assume that it's not a dereference (no false positives)
|
// assume that it's not a dereference (no false positives)
|
||||||
|
@ -292,7 +287,7 @@ bool CheckNullPointer::isPointerDeRef(const Token *tok, bool &unknown)
|
||||||
// check if function can assign pointer
|
// check if function can assign pointer
|
||||||
bool CheckNullPointer::CanFunctionAssignPointer(const Token *functiontoken, unsigned int varid) const
|
bool CheckNullPointer::CanFunctionAssignPointer(const Token *functiontoken, unsigned int varid) const
|
||||||
{
|
{
|
||||||
if (Token::Match(functiontoken, "if|while|sizeof"))
|
if (Token::Match(functiontoken, "if|while|for|switch|sizeof|catch"))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
int argumentNumber = 0;
|
int argumentNumber = 0;
|
||||||
|
@ -434,7 +429,7 @@ void CheckNullPointer::nullPointerLinkedList()
|
||||||
const std::string varname(tok2->str());
|
const std::string varname(tok2->str());
|
||||||
|
|
||||||
// Check usage of dereferenced variable in the loop..
|
// Check usage of dereferenced variable in the loop..
|
||||||
for (const Token *tok3 = i->classStart; tok3 && tok3 != i->classEnd; tok3 = tok3->next()) {
|
for (const Token *tok3 = i->classStart->next(); tok3 && tok3 != i->classEnd; tok3 = tok3->next()) {
|
||||||
// TODO: are there false negatives for "while ( %varid% ||"
|
// TODO: are there false negatives for "while ( %varid% ||"
|
||||||
if (Token::Match(tok3, "while ( %varid% &&|)", varid)) {
|
if (Token::Match(tok3, "while ( %varid% &&|)", varid)) {
|
||||||
// Make sure there is a "break" or "return" inside the loop.
|
// Make sure there is a "break" or "return" inside the loop.
|
||||||
|
@ -801,174 +796,167 @@ void CheckNullPointer::nullPointerByDeRefAndChec()
|
||||||
|
|
||||||
void CheckNullPointer::nullPointerByCheckAndDeRef()
|
void CheckNullPointer::nullPointerByCheckAndDeRef()
|
||||||
{
|
{
|
||||||
|
const SymbolDatabase *symbolDatabase = _tokenizer->getSymbolDatabase();
|
||||||
|
|
||||||
// Check if pointer is NULL and then dereference it..
|
// Check if pointer is NULL and then dereference it..
|
||||||
|
for (std::list<Scope>::const_iterator i = symbolDatabase->scopeList.begin(); i != symbolDatabase->scopeList.end(); ++i) {
|
||||||
|
if (i->type != Scope::eIf && i->type != Scope::eElseIf && i->type != Scope::eWhile)
|
||||||
|
continue;
|
||||||
|
if (!i->classDef || i->classDef->isExpandedMacro())
|
||||||
|
continue;
|
||||||
|
|
||||||
for (const Token *tok = _tokenizer->tokens(); tok; tok = tok->next()) {
|
const Token* const tok = i->type != Scope::eElseIf ? i->classDef : i->classDef->next();
|
||||||
if (Token::simpleMatch(tok, "if (") && !tok->isExpandedMacro()) {
|
// TODO: investigate false negatives:
|
||||||
// TODO: investigate false negatives:
|
// - handle "while"?
|
||||||
// - handle "while"?
|
// - if there are logical operators
|
||||||
// - if there are logical operators
|
// - if (x) { } else { ... }
|
||||||
// - if (x) { } else { ... }
|
|
||||||
|
|
||||||
// If the if-body ends with a unknown macro then bailout
|
// If the if-body ends with a unknown macro then bailout
|
||||||
{
|
if (Token::Match(i->classEnd->tokAt(-3), "[;{}] %var% ;") && isUpper(i->classEnd->strAt(-2)))
|
||||||
// goto the end parenthesis
|
continue;
|
||||||
const Token *endpar = tok->next()->link();
|
|
||||||
const Token *endbody = Token::simpleMatch(endpar, ") {") ? endpar->next()->link() : 0;
|
|
||||||
if (endbody &&
|
|
||||||
Token::Match(endbody->tokAt(-3), "[;{}] %var% ;") &&
|
|
||||||
isUpper(endbody->strAt(-2)))
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// vartok : token for the variable
|
// vartok : token for the variable
|
||||||
const Token *vartok = 0;
|
const Token *vartok = 0;
|
||||||
if (Token::Match(tok, "if ( ! %var% )|&&"))
|
if (Token::Match(tok, "if ( ! %var% )|&&"))
|
||||||
vartok = tok->tokAt(3);
|
vartok = tok->tokAt(3);
|
||||||
else if (Token::Match(tok, "if|while ( %var% )|&&"))
|
else if (Token::Match(tok, "if|while ( %var% )|&&"))
|
||||||
vartok = tok->tokAt(2);
|
vartok = tok->tokAt(2);
|
||||||
else if (Token::Match(tok, "if ( ! ( %var% ="))
|
else if (Token::Match(tok, "if ( ! ( %var% ="))
|
||||||
vartok = tok->tokAt(4);
|
vartok = tok->tokAt(4);
|
||||||
else
|
else
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// variable id for pointer
|
||||||
|
const unsigned int varid(vartok->varId());
|
||||||
|
if (varid == 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
const unsigned int linenr = vartok->linenr();
|
||||||
|
|
||||||
|
const Variable* var = _tokenizer->getSymbolDatabase()->getVariableFromVarId(varid);
|
||||||
|
// Check if variable is a pointer
|
||||||
|
if (!var || !var->isPointer())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (Token::Match(vartok->next(), "&& ( %varid% =", varid))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// if this is true then it is known that the pointer is null
|
||||||
|
bool null = true;
|
||||||
|
|
||||||
|
// start token = inside the if-body
|
||||||
|
const Token *tok1 = i->classStart;
|
||||||
|
|
||||||
|
if (Token::Match(tok, "if|while ( %var% )|&&")) {
|
||||||
|
// pointer might be null
|
||||||
|
null = false;
|
||||||
|
|
||||||
|
// start token = first token after the if/while body
|
||||||
|
tok1 = i->classEnd->next();
|
||||||
|
if (!tok1)
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
// variable id for pointer
|
unsigned int indentlevel = 0;
|
||||||
const unsigned int varid(vartok->varId());
|
|
||||||
if (varid == 0)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
const unsigned int linenr = vartok->linenr();
|
// Name of the pointer
|
||||||
|
const std::string &pointerName = vartok->str();
|
||||||
|
|
||||||
const Variable* var = _tokenizer->getSymbolDatabase()->getVariableFromVarId(varid);
|
// Set to true if we would normally bail out the check.
|
||||||
// Check if variable is a pointer
|
bool inconclusive = false;
|
||||||
if (!var || !var->isPointer())
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (Token::Match(vartok->next(), "&& ( %varid% =", varid))
|
// Count { and } for tok2
|
||||||
continue;
|
for (const Token *tok2 = tok1; tok2; tok2 = tok2->next()) {
|
||||||
|
if (tok2->str() == "{")
|
||||||
// if this is true then it is known that the pointer is null
|
++indentlevel;
|
||||||
bool null = true;
|
else if (tok2->str() == "}") {
|
||||||
|
if (indentlevel == 0)
|
||||||
// start token = inside the if-body
|
|
||||||
const Token *tok1 = tok->next()->link()->tokAt(2);
|
|
||||||
|
|
||||||
// indentlevel inside the if-body is 1
|
|
||||||
unsigned int indentlevel = 1;
|
|
||||||
|
|
||||||
if (Token::Match(tok, "if|while ( %var% )|&&")) {
|
|
||||||
// pointer might be null
|
|
||||||
null = false;
|
|
||||||
|
|
||||||
// start token = first token after the if/while body
|
|
||||||
tok1 = tok1->previous()->link();
|
|
||||||
tok1 = tok1 ? tok1->next() : NULL;
|
|
||||||
if (!tok1)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
// indentlevel at the base level is 0
|
|
||||||
indentlevel = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Name of the pointer
|
|
||||||
const std::string &pointerName = vartok->str();
|
|
||||||
|
|
||||||
// Set to true if we would normally bail out the check.
|
|
||||||
bool inconclusive = false;
|
|
||||||
|
|
||||||
// Count { and } for tok2
|
|
||||||
for (const Token *tok2 = tok1; tok2; tok2 = tok2->next()) {
|
|
||||||
if (tok2->str() == "{")
|
|
||||||
++indentlevel;
|
|
||||||
else if (tok2->str() == "}") {
|
|
||||||
if (indentlevel == 0)
|
|
||||||
break;
|
|
||||||
--indentlevel;
|
|
||||||
|
|
||||||
// calling exit function?
|
|
||||||
bool unknown = false;
|
|
||||||
if (_tokenizer->IsScopeNoReturn(tok2, &unknown)) {
|
|
||||||
if (_settings->inconclusive && unknown)
|
|
||||||
inconclusive = true;
|
|
||||||
else
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (null && indentlevel == 0) {
|
|
||||||
// skip all "else" blocks because they are not executed in this execution path
|
|
||||||
while (Token::simpleMatch(tok2, "} else {"))
|
|
||||||
tok2 = tok2->linkAt(2);
|
|
||||||
null = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Token::Match(tok2, "goto|return|continue|break|throw|if|switch|for")) {
|
|
||||||
bool dummy = false;
|
|
||||||
if (Token::Match(tok2, "return * %varid%", varid))
|
|
||||||
nullPointerError(tok2, pointerName, linenr, inconclusive);
|
|
||||||
else if (Token::Match(tok2, "return %varid%", varid) &&
|
|
||||||
CheckNullPointer::isPointerDeRef(tok2->next(), dummy))
|
|
||||||
nullPointerError(tok2, pointerName, linenr, inconclusive);
|
|
||||||
break;
|
break;
|
||||||
}
|
--indentlevel;
|
||||||
|
|
||||||
// parameters to sizeof are not dereferenced
|
// calling exit function?
|
||||||
if (Token::Match(tok2, "decltype|sizeof")) {
|
bool unknown = false;
|
||||||
if (tok2->strAt(1) != "(")
|
if (_tokenizer->IsScopeNoReturn(tok2, &unknown)) {
|
||||||
break;
|
if (_settings->inconclusive && unknown)
|
||||||
|
|
||||||
tok2 = tok2->next()->link();
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// function call, check if pointer is dereferenced
|
|
||||||
if (Token::Match(tok2, "%var% (")) {
|
|
||||||
std::list<const Token *> vars;
|
|
||||||
parseFunctionCall(*tok2, vars, 0);
|
|
||||||
for (std::list<const Token *>::const_iterator it = vars.begin(); it != vars.end(); ++it) {
|
|
||||||
if (Token::Match(*it, "%varid% [,)]", varid)) {
|
|
||||||
nullPointerError(*it, pointerName, linenr, inconclusive);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// calling unknown function (abort/init)..
|
|
||||||
if (Token::simpleMatch(tok2, ") ;") &&
|
|
||||||
(Token::Match(tok2->link()->tokAt(-2), "[;{}.] %var% (") ||
|
|
||||||
Token::Match(tok2->link()->tokAt(-5), "[;{}] ( * %var% ) ("))) {
|
|
||||||
// noreturn function?
|
|
||||||
bool unknown = false;
|
|
||||||
if (_tokenizer->IsScopeNoReturn(tok2->tokAt(2), &unknown)) {
|
|
||||||
if (!unknown || !_settings->inconclusive) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
inconclusive = true;
|
inconclusive = true;
|
||||||
}
|
|
||||||
|
|
||||||
// init function (global variables)
|
|
||||||
if (!var || !(var->isLocal() || var->isArgument()))
|
|
||||||
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 = _settings->inconclusive;
|
|
||||||
|
|
||||||
if (Token::Match(tok2->previous(), "[;{}=] %var% = 0 ;"))
|
|
||||||
;
|
|
||||||
|
|
||||||
else if (CheckNullPointer::isPointerDeRef(tok2, unknown))
|
|
||||||
nullPointerError(tok2, pointerName, linenr, inconclusive);
|
|
||||||
|
|
||||||
else if (unknown && _settings->inconclusive)
|
|
||||||
nullPointerError(tok2, pointerName, linenr, true);
|
|
||||||
|
|
||||||
else
|
else
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (null && indentlevel == 0) {
|
||||||
|
// skip all "else" blocks because they are not executed in this execution path
|
||||||
|
while (Token::simpleMatch(tok2, "} else {"))
|
||||||
|
tok2 = tok2->linkAt(2);
|
||||||
|
null = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Token::Match(tok2, "goto|return|continue|break|throw|if|switch|for")) {
|
||||||
|
bool dummy = false;
|
||||||
|
if (Token::Match(tok2, "return * %varid%", varid))
|
||||||
|
nullPointerError(tok2, pointerName, linenr, inconclusive);
|
||||||
|
else if (Token::Match(tok2, "return %varid%", varid) &&
|
||||||
|
CheckNullPointer::isPointerDeRef(tok2->next(), dummy))
|
||||||
|
nullPointerError(tok2, pointerName, linenr, inconclusive);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// parameters to sizeof are not dereferenced
|
||||||
|
if (Token::Match(tok2, "decltype|sizeof")) {
|
||||||
|
if (tok2->strAt(1) != "(")
|
||||||
|
break;
|
||||||
|
|
||||||
|
tok2 = tok2->next()->link();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// function call, check if pointer is dereferenced
|
||||||
|
if (Token::Match(tok2, "%var% (")) {
|
||||||
|
std::list<const Token *> vars;
|
||||||
|
parseFunctionCall(*tok2, vars, 0);
|
||||||
|
for (std::list<const Token *>::const_iterator it = vars.begin(); it != vars.end(); ++it) {
|
||||||
|
if (Token::Match(*it, "%varid% [,)]", varid)) {
|
||||||
|
nullPointerError(*it, pointerName, linenr, inconclusive);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// calling unknown function (abort/init)..
|
||||||
|
if (Token::simpleMatch(tok2, ") ;") &&
|
||||||
|
(Token::Match(tok2->link()->tokAt(-2), "[;{}.] %var% (") ||
|
||||||
|
Token::Match(tok2->link()->tokAt(-5), "[;{}] ( * %var% ) ("))) {
|
||||||
|
// noreturn function?
|
||||||
|
bool unknown = false;
|
||||||
|
if (_tokenizer->IsScopeNoReturn(tok2->tokAt(2), &unknown)) {
|
||||||
|
if (!unknown || !_settings->inconclusive) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
inconclusive = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// init function (global variables)
|
||||||
|
if (!var || !(var->isLocal() || var->isArgument()))
|
||||||
|
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 = _settings->inconclusive;
|
||||||
|
|
||||||
|
if (Token::Match(tok2->previous(), "[;{}=] %var% = 0 ;"))
|
||||||
|
;
|
||||||
|
|
||||||
|
else if (CheckNullPointer::isPointerDeRef(tok2, unknown))
|
||||||
|
nullPointerError(tok2, pointerName, linenr, inconclusive);
|
||||||
|
|
||||||
|
else if (unknown && _settings->inconclusive)
|
||||||
|
nullPointerError(tok2, pointerName, linenr, true);
|
||||||
|
|
||||||
|
else
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -987,25 +975,13 @@ void CheckNullPointer::nullPointer()
|
||||||
/** Dereferencing null constant (simplified token list) */
|
/** Dereferencing null constant (simplified token list) */
|
||||||
void CheckNullPointer::nullConstantDereference()
|
void CheckNullPointer::nullConstantDereference()
|
||||||
{
|
{
|
||||||
// this is kept at 0 for all scopes that are not executing
|
const SymbolDatabase *symbolDatabase = _tokenizer->getSymbolDatabase();
|
||||||
unsigned int indentlevel = 0;
|
|
||||||
|
|
||||||
for (const Token *tok = _tokenizer->tokens(); tok; tok = tok->next()) {
|
for (std::list<Scope>::const_iterator i = symbolDatabase->scopeList.begin(); i != symbolDatabase->scopeList.end(); ++i) {
|
||||||
// start of executable scope..
|
if (i->type != Scope::eFunction || !i->classStart)
|
||||||
if (indentlevel == 0 && Token::Match(tok, ") const| {"))
|
continue;
|
||||||
indentlevel = 1;
|
|
||||||
|
|
||||||
else if (indentlevel >= 1) {
|
|
||||||
if (tok->str() == "{")
|
|
||||||
++indentlevel;
|
|
||||||
|
|
||||||
else if (tok->str() == "}") {
|
|
||||||
if (indentlevel <= 2)
|
|
||||||
indentlevel = 0;
|
|
||||||
else
|
|
||||||
--indentlevel;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
for (const Token *tok = i->classStart; tok != i->classEnd; tok = tok->next()) {
|
||||||
if (tok->str() == "(" && Token::Match(tok->previous(), "sizeof|decltype|typeid"))
|
if (tok->str() == "(" && Token::Match(tok->previous(), "sizeof|decltype|typeid"))
|
||||||
tok = tok->link();
|
tok = tok->link();
|
||||||
|
|
||||||
|
@ -1015,7 +991,7 @@ void CheckNullPointer::nullConstantDereference()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (indentlevel > 0 && Token::Match(tok->previous(), "[={};] %var% (")) {
|
else if (Token::Match(tok->previous(), "[={};] %var% (")) {
|
||||||
std::list<const Token *> var;
|
std::list<const Token *> var;
|
||||||
parseFunctionCall(*tok, var, 0);
|
parseFunctionCall(*tok, var, 0);
|
||||||
|
|
||||||
|
|
|
@ -599,8 +599,7 @@ void CheckOther::checkSwitchCaseFallThrough()
|
||||||
const char breakPattern[] = "break|continue|return|exit|goto|throw";
|
const char breakPattern[] = "break|continue|return|exit|goto|throw";
|
||||||
|
|
||||||
for (std::list<Scope>::const_iterator i = symbolDatabase->scopeList.begin(); i != symbolDatabase->scopeList.end(); ++i) {
|
for (std::list<Scope>::const_iterator i = symbolDatabase->scopeList.begin(); i != symbolDatabase->scopeList.end(); ++i) {
|
||||||
const Token* const tok = i->classDef;
|
if (i->type != Scope::eSwitch || !i->classStart) // Find the beginning of a switch
|
||||||
if (i->type != Scope::eSwitch || !tok) // Find the beginning of a switch
|
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// Check the contents of the switch statement
|
// Check the contents of the switch statement
|
||||||
|
@ -609,7 +608,7 @@ void CheckOther::checkSwitchCaseFallThrough()
|
||||||
std::stack<Token *> scopenest;
|
std::stack<Token *> scopenest;
|
||||||
bool justbreak = true;
|
bool justbreak = true;
|
||||||
bool firstcase = true;
|
bool firstcase = true;
|
||||||
for (const Token *tok2 = tok->next()->link()->tokAt(2); tok2; tok2 = tok2->next()) {
|
for (const Token *tok2 = i->classStart; tok2 != i->classEnd; tok2 = tok2->next()) {
|
||||||
if (Token::simpleMatch(tok2, "if (")) {
|
if (Token::simpleMatch(tok2, "if (")) {
|
||||||
tok2 = tok2->next()->link()->next();
|
tok2 = tok2->next()->link()->next();
|
||||||
if (tok2->link() == NULL) {
|
if (tok2->link() == NULL) {
|
||||||
|
@ -827,11 +826,11 @@ void CheckOther::checkAssignmentInAssert()
|
||||||
const Token *endTok = tok ? tok->next()->link() : NULL;
|
const Token *endTok = tok ? tok->next()->link() : NULL;
|
||||||
|
|
||||||
while (tok && endTok) {
|
while (tok && endTok) {
|
||||||
const Token* varTok = Token::findmatch(tok->tokAt(2), "%var% --|++|+=|-=|*=|/=|&=|^=|=", endTok);
|
for (tok = tok->tokAt(2); tok != endTok; tok = tok->next()) {
|
||||||
if (varTok) {
|
if (tok->isName() && (tok->next()->isAssignmentOp() || tok->next()->str() == "++" || tok->next()->str() == "--"))
|
||||||
assignmentInAssertError(tok, varTok->str());
|
assignmentInAssertError(tok, tok->str());
|
||||||
} else if (NULL != (varTok = Token::findmatch(tok->tokAt(2), "--|++ %var%", endTok))) {
|
else if (Token::Match(tok, "--|++ %var%"))
|
||||||
assignmentInAssertError(tok, varTok->strAt(1));
|
assignmentInAssertError(tok, tok->strAt(1));
|
||||||
}
|
}
|
||||||
|
|
||||||
tok = Token::findmatch(endTok->next(), assertPattern);
|
tok = Token::findmatch(endTok->next(), assertPattern);
|
||||||
|
@ -1638,7 +1637,7 @@ void CheckOther::checkUnreachableCode()
|
||||||
// that the goto jump was intended to skip some code on the first loop iteration.
|
// that the goto jump was intended to skip some code on the first loop iteration.
|
||||||
bool labelInFollowingLoop = false;
|
bool labelInFollowingLoop = false;
|
||||||
if (labelName && Token::Match(secondBreak, "while|do|for")) {
|
if (labelName && Token::Match(secondBreak, "while|do|for")) {
|
||||||
const Token *scope = Token::findmatch(secondBreak, "{");
|
const Token *scope = Token::findsimplematch(secondBreak, "{");
|
||||||
if (scope) {
|
if (scope) {
|
||||||
for (const Token *tokIter = scope; tokIter != scope->link() && tokIter; tokIter = tokIter->next()) {
|
for (const Token *tokIter = scope; tokIter != scope->link() && tokIter; tokIter = tokIter->next()) {
|
||||||
if (Token::Match(tokIter, "[;{}] %any% :") && labelName->str() == tokIter->strAt(1)) {
|
if (Token::Match(tokIter, "[;{}] %any% :") && labelName->str() == tokIter->strAt(1)) {
|
||||||
|
@ -2270,24 +2269,12 @@ void CheckOther::checkMisusedScopedObject()
|
||||||
|
|
||||||
const SymbolDatabase * const symbolDatabase = _tokenizer->getSymbolDatabase();
|
const SymbolDatabase * const symbolDatabase = _tokenizer->getSymbolDatabase();
|
||||||
|
|
||||||
std::list<Scope>::const_iterator scope;
|
for (std::list<Scope>::const_iterator scope = symbolDatabase->scopeList.begin(); scope != symbolDatabase->scopeList.end(); ++scope) {
|
||||||
|
|
||||||
for (scope = symbolDatabase->scopeList.begin(); scope != symbolDatabase->scopeList.end(); ++scope) {
|
|
||||||
// only check functions
|
// only check functions
|
||||||
if (scope->type != Scope::eFunction)
|
if (scope->type != Scope::eFunction)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
unsigned int depth = 0;
|
for (const Token *tok = scope->classStart; tok && tok != scope->classEnd; tok = tok->next()) {
|
||||||
|
|
||||||
for (const Token *tok = scope->classStart; tok; tok = tok->next()) {
|
|
||||||
if (tok->str() == "{") {
|
|
||||||
++depth;
|
|
||||||
} else if (tok->str() == "}") {
|
|
||||||
if (depth <= 1)
|
|
||||||
break;
|
|
||||||
--depth;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Token::Match(tok, "[;{}] %var% (")
|
if (Token::Match(tok, "[;{}] %var% (")
|
||||||
&& Token::simpleMatch(tok->linkAt(2), ") ;")
|
&& Token::simpleMatch(tok->linkAt(2), ") ;")
|
||||||
&& symbolDatabase->isClassOrStruct(tok->next()->str())
|
&& symbolDatabase->isClassOrStruct(tok->next()->str())
|
||||||
|
@ -2484,15 +2471,15 @@ void CheckOther::checkDuplicateBranch()
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
void CheckOther::checkDoubleFree()
|
void CheckOther::checkDoubleFree()
|
||||||
{
|
{
|
||||||
std::set<int> freedVariables;
|
std::set<unsigned int> freedVariables;
|
||||||
std::set<int> closeDirVariables;
|
std::set<unsigned int> closeDirVariables;
|
||||||
|
|
||||||
for (const Token* tok = _tokenizer->tokens(); tok; tok = tok->next()) {
|
for (const Token* tok = _tokenizer->tokens(); tok; tok = tok->next()) {
|
||||||
|
|
||||||
// Keep track of any variables passed to "free()", "g_free()" or "closedir()",
|
// Keep track of any variables passed to "free()", "g_free()" or "closedir()",
|
||||||
// and report an error if the same variable is passed twice.
|
// and report an error if the same variable is passed twice.
|
||||||
if (Token::Match(tok, "free|g_free|closedir ( %var% )")) {
|
if (Token::Match(tok, "free|g_free|closedir ( %var% )")) {
|
||||||
int var = tok->tokAt(2)->varId();
|
unsigned int var = tok->tokAt(2)->varId();
|
||||||
if (var) {
|
if (var) {
|
||||||
if (Token::Match(tok, "free|g_free")) {
|
if (Token::Match(tok, "free|g_free")) {
|
||||||
if (freedVariables.find(var) != freedVariables.end())
|
if (freedVariables.find(var) != freedVariables.end())
|
||||||
|
@ -2512,7 +2499,7 @@ void CheckOther::checkDoubleFree()
|
||||||
// and report an error if the same variable is delete'd twice.
|
// and report an error if the same variable is delete'd twice.
|
||||||
else if (Token::Match(tok, "delete %var% ;") || Token::Match(tok, "delete [ ] %var% ;")) {
|
else if (Token::Match(tok, "delete %var% ;") || Token::Match(tok, "delete [ ] %var% ;")) {
|
||||||
int varIdx = (tok->strAt(1) == "[") ? 3 : 1;
|
int varIdx = (tok->strAt(1) == "[") ? 3 : 1;
|
||||||
int var = tok->tokAt(varIdx)->varId();
|
unsigned int var = tok->tokAt(varIdx)->varId();
|
||||||
if (var) {
|
if (var) {
|
||||||
if (freedVariables.find(var) != freedVariables.end())
|
if (freedVariables.find(var) != freedVariables.end())
|
||||||
doubleFreeError(tok, tok->tokAt(varIdx)->str());
|
doubleFreeError(tok, tok->tokAt(varIdx)->str());
|
||||||
|
@ -2531,7 +2518,7 @@ void CheckOther::checkDoubleFree()
|
||||||
else if (Token::Match(tok, "%var% (") && !Token::Match(tok, "printf|sprintf|snprintf|fprintf")) {
|
else if (Token::Match(tok, "%var% (") && !Token::Match(tok, "printf|sprintf|snprintf|fprintf")) {
|
||||||
for (const Token* tok2 = tok->tokAt(2); tok2 != tok->linkAt(1); tok2 = tok2->next()) {
|
for (const Token* tok2 = tok->tokAt(2); tok2 != tok->linkAt(1); tok2 = tok2->next()) {
|
||||||
if (Token::Match(tok2, "%var%")) {
|
if (Token::Match(tok2, "%var%")) {
|
||||||
int var = tok2->varId();
|
unsigned int var = tok2->varId();
|
||||||
if (var) {
|
if (var) {
|
||||||
freedVariables.erase(var);
|
freedVariables.erase(var);
|
||||||
closeDirVariables.erase(var);
|
closeDirVariables.erase(var);
|
||||||
|
@ -2542,7 +2529,7 @@ void CheckOther::checkDoubleFree()
|
||||||
|
|
||||||
// If a pointer is assigned a new value, remove it from the set of previously freed variables
|
// If a pointer is assigned a new value, remove it from the set of previously freed variables
|
||||||
else if (Token::Match(tok, "%var% =")) {
|
else if (Token::Match(tok, "%var% =")) {
|
||||||
int var = tok->varId();
|
unsigned int var = tok->varId();
|
||||||
if (var) {
|
if (var) {
|
||||||
freedVariables.erase(var);
|
freedVariables.erase(var);
|
||||||
closeDirVariables.erase(var);
|
closeDirVariables.erase(var);
|
||||||
|
|
|
@ -79,16 +79,18 @@ std::string Settings::addEnabled(const std::string &str)
|
||||||
|
|
||||||
bool handled = false;
|
bool handled = false;
|
||||||
|
|
||||||
std::set<std::string> id;
|
static std::set<std::string> id;
|
||||||
id.insert("style");
|
if (id.empty()) {
|
||||||
id.insert("performance");
|
id.insert("style");
|
||||||
id.insert("portability");
|
id.insert("performance");
|
||||||
id.insert("information");
|
id.insert("portability");
|
||||||
id.insert("missingInclude");
|
id.insert("information");
|
||||||
id.insert("unusedFunction");
|
id.insert("missingInclude");
|
||||||
|
id.insert("unusedFunction");
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
id.insert("internal");
|
id.insert("internal");
|
||||||
#endif
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
if (str == "all") {
|
if (str == "all") {
|
||||||
std::set<std::string>::const_iterator it;
|
std::set<std::string>::const_iterator it;
|
||||||
|
|
|
@ -83,15 +83,15 @@ const Token* TemplateSimplifier::hasComplicatedSyntaxErrorsInTemplates(Token *to
|
||||||
}
|
}
|
||||||
|
|
||||||
// skip executing scopes (ticket #1984)..
|
// skip executing scopes (ticket #1984)..
|
||||||
if (Token::simpleMatch(tok, "; {"))
|
else if (Token::simpleMatch(tok, "; {"))
|
||||||
tok = tok->next()->link();
|
tok = tok->next()->link();
|
||||||
|
|
||||||
// skip executing scopes (ticket #3183)..
|
// skip executing scopes (ticket #3183)..
|
||||||
if (Token::simpleMatch(tok, "( {"))
|
else if (Token::simpleMatch(tok, "( {"))
|
||||||
tok = tok->next()->link();
|
tok = tok->next()->link();
|
||||||
|
|
||||||
// skip executing scopes (ticket #1985)..
|
// skip executing scopes (ticket #1985)..
|
||||||
if (Token::simpleMatch(tok, "try {")) {
|
else if (Token::simpleMatch(tok, "try {")) {
|
||||||
tok = tok->next()->link();
|
tok = tok->next()->link();
|
||||||
while (Token::simpleMatch(tok, "} catch (")) {
|
while (Token::simpleMatch(tok, "} catch (")) {
|
||||||
tok = tok->linkAt(2);
|
tok = tok->linkAt(2);
|
||||||
|
|
|
@ -2392,7 +2392,7 @@ bool Tokenizer::hasEnumsWithTypedef()
|
||||||
for (const Token *tok = _tokens; tok; tok = tok->next()) {
|
for (const Token *tok = _tokens; tok; tok = tok->next()) {
|
||||||
if (Token::Match(tok, "enum %var% {")) {
|
if (Token::Match(tok, "enum %var% {")) {
|
||||||
tok = tok->tokAt(2);
|
tok = tok->tokAt(2);
|
||||||
const Token *tok2 = Token::findmatch(tok, "typedef", tok->link());
|
const Token *tok2 = Token::findsimplematch(tok, "typedef", tok->link());
|
||||||
if (tok2) {
|
if (tok2) {
|
||||||
syntaxError(tok2);
|
syntaxError(tok2);
|
||||||
return true;
|
return true;
|
||||||
|
|
Loading…
Reference in New Issue