Refactoring: some refactoring of ExecutionPath. The foundError was removed. No automatic bailout of all checks are made when errors are found.
This commit is contained in:
parent
78852b08ab
commit
abceff497b
|
@ -2747,7 +2747,7 @@ private:
|
||||||
}
|
}
|
||||||
|
|
||||||
/** return */
|
/** return */
|
||||||
static void ret(const std::list<ExecutionPath *> &checks, const Token *tok, bool &foundError)
|
static void ret(const std::list<ExecutionPath *> &checks, const Token *tok)
|
||||||
{
|
{
|
||||||
std::list<ExecutionPath *>::const_iterator it;
|
std::list<ExecutionPath *>::const_iterator it;
|
||||||
for (it = checks.begin(); it != checks.end(); ++it)
|
for (it = checks.begin(); it != checks.end(); ++it)
|
||||||
|
@ -2759,7 +2759,6 @@ private:
|
||||||
if (checkMemleak)
|
if (checkMemleak)
|
||||||
{
|
{
|
||||||
checkMemleak->memleakError(tok, C->varname, false);
|
checkMemleak->memleakError(tok, C->varname, false);
|
||||||
foundError = true;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2767,7 +2766,7 @@ private:
|
||||||
}
|
}
|
||||||
|
|
||||||
/** parse the tokens */
|
/** parse the tokens */
|
||||||
const Token *parse(const Token &tok, bool &foundError, std::list<ExecutionPath *> &checks) const
|
const Token *parse(const Token &tok, std::list<ExecutionPath *> &checks) const
|
||||||
{
|
{
|
||||||
//std::cout << "CheckLocalLeaks::parse " << tok.str() << std::endl;
|
//std::cout << "CheckLocalLeaks::parse " << tok.str() << std::endl;
|
||||||
//printOut(checks);
|
//printOut(checks);
|
||||||
|
@ -2808,7 +2807,7 @@ private:
|
||||||
|
|
||||||
if (tok.str() == "return")
|
if (tok.str() == "return")
|
||||||
{
|
{
|
||||||
ret(checks, &tok, foundError);
|
ret(checks, &tok);
|
||||||
}
|
}
|
||||||
|
|
||||||
return &tok;
|
return &tok;
|
||||||
|
@ -2817,8 +2816,7 @@ private:
|
||||||
/** going out of scope - all execution paths end */
|
/** going out of scope - all execution paths end */
|
||||||
void end(const std::list<ExecutionPath *> &checks, const Token *tok) const
|
void end(const std::list<ExecutionPath *> &checks, const Token *tok) const
|
||||||
{
|
{
|
||||||
bool foundError = false;
|
ret(checks, tok);
|
||||||
ret(checks, tok, foundError);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1474,8 +1474,12 @@ private:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** variable is dereferenced. If the variable is null there's an error */
|
/**
|
||||||
static void dereference(bool &foundError, std::list<ExecutionPath *> &checks, const Token *tok)
|
* Dereferencing variable. Check if it is safe (if the variable is null there's an error)
|
||||||
|
* @param checks Checks
|
||||||
|
* @param tok token where dereferencing happens
|
||||||
|
*/
|
||||||
|
static void dereference(std::list<ExecutionPath *> &checks, const Token *tok)
|
||||||
{
|
{
|
||||||
const unsigned int varid(tok->varId());
|
const unsigned int varid(tok->varId());
|
||||||
|
|
||||||
|
@ -1485,19 +1489,18 @@ private:
|
||||||
CheckNullpointer *c = dynamic_cast<CheckNullpointer *>(*it);
|
CheckNullpointer *c = dynamic_cast<CheckNullpointer *>(*it);
|
||||||
if (c && c->varId == varid && c->null)
|
if (c && c->varId == varid && c->null)
|
||||||
{
|
{
|
||||||
foundError = true;
|
|
||||||
CheckOther *checkOther = dynamic_cast<CheckOther *>(c->owner);
|
CheckOther *checkOther = dynamic_cast<CheckOther *>(c->owner);
|
||||||
if (checkOther)
|
if (checkOther)
|
||||||
{
|
{
|
||||||
checkOther->nullPointerError(tok, c->varname);
|
checkOther->nullPointerError(tok, c->varname);
|
||||||
break;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** parse tokens */
|
/** parse tokens */
|
||||||
const Token *parse(const Token &tok, bool &foundError, std::list<ExecutionPath *> &checks) const
|
const Token *parse(const Token &tok, std::list<ExecutionPath *> &checks) const
|
||||||
{
|
{
|
||||||
if (Token::Match(tok.previous(), "[;{}] const| %type% * %var% ;"))
|
if (Token::Match(tok.previous(), "[;{}] const| %type% * %var% ;"))
|
||||||
{
|
{
|
||||||
|
@ -1543,7 +1546,7 @@ private:
|
||||||
std::list<const Token *> var;
|
std::list<const Token *> var;
|
||||||
parseFunctionCall(tok, var, 0);
|
parseFunctionCall(tok, var, 0);
|
||||||
for (std::list<const Token *>::const_iterator it = var.begin(); it != var.end(); ++it)
|
for (std::list<const Token *>::const_iterator it = var.begin(); it != var.end(); ++it)
|
||||||
dereference(foundError, checks, *it);
|
dereference(checks, *it);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tok.varId() != 0)
|
if (tok.varId() != 0)
|
||||||
|
@ -1551,17 +1554,17 @@ private:
|
||||||
if (Token::Match(tok.previous(), "[;{}=] %var% = 0 ;"))
|
if (Token::Match(tok.previous(), "[;{}=] %var% = 0 ;"))
|
||||||
setnull(checks, tok.varId());
|
setnull(checks, tok.varId());
|
||||||
else if (Token::Match(tok.tokAt(-2), "[;{}=+-/(,] * %var%"))
|
else if (Token::Match(tok.tokAt(-2), "[;{}=+-/(,] * %var%"))
|
||||||
dereference(foundError, checks, &tok);
|
dereference(checks, &tok);
|
||||||
else if (Token::Match(tok.tokAt(-2), "return * %var%"))
|
else if (Token::Match(tok.tokAt(-2), "return * %var%"))
|
||||||
dereference(foundError, checks, &tok);
|
dereference(checks, &tok);
|
||||||
else if (!Token::simpleMatch(tok.tokAt(-2), "& (") && Token::Match(tok.next(), ". %var%"))
|
else if (!Token::simpleMatch(tok.tokAt(-2), "& (") && Token::Match(tok.next(), ". %var%"))
|
||||||
dereference(foundError, checks, &tok);
|
dereference(checks, &tok);
|
||||||
else if (Token::Match(tok.previous(), "[;{}=+-/(,] %var% [ %any% ]"))
|
else if (Token::Match(tok.previous(), "[;{}=+-/(,] %var% [ %any% ]"))
|
||||||
dereference(foundError, checks, &tok);
|
dereference(checks, &tok);
|
||||||
else if (Token::Match(tok.previous(), "return %var% [ %any% ]"))
|
else if (Token::Match(tok.previous(), "return %var% [ %any% ]"))
|
||||||
dereference(foundError, checks, &tok);
|
dereference(checks, &tok);
|
||||||
else if (Token::Match(&tok, "%var% ("))
|
else if (Token::Match(&tok, "%var% ("))
|
||||||
dereference(foundError, checks, &tok);
|
dereference(checks, &tok);
|
||||||
else
|
else
|
||||||
bailOutVar(checks, tok.varId());
|
bailOutVar(checks, tok.varId());
|
||||||
}
|
}
|
||||||
|
@ -1575,7 +1578,6 @@ private:
|
||||||
if (checkOther)
|
if (checkOther)
|
||||||
{
|
{
|
||||||
checkOther->nullPointerError(&tok);
|
checkOther->nullPointerError(&tok);
|
||||||
foundError = true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1588,11 +1590,10 @@ private:
|
||||||
{
|
{
|
||||||
if (Token::Match(&tok, "!| %var% ("))
|
if (Token::Match(&tok, "!| %var% ("))
|
||||||
{
|
{
|
||||||
bool foundError = false;
|
|
||||||
std::list<const Token *> var;
|
std::list<const Token *> var;
|
||||||
parseFunctionCall(tok.str() == "!" ? *tok.next() : tok, var, 0);
|
parseFunctionCall(tok.str() == "!" ? *tok.next() : tok, var, 0);
|
||||||
for (std::list<const Token *>::const_iterator it = var.begin(); it != var.end(); ++it)
|
for (std::list<const Token *>::const_iterator it = var.begin(); it != var.end(); ++it)
|
||||||
dereference(foundError, checks, *it);
|
dereference(checks, *it);
|
||||||
}
|
}
|
||||||
|
|
||||||
return ExecutionPath::parseCondition(tok, checks);
|
return ExecutionPath::parseCondition(tok, checks);
|
||||||
|
@ -1656,7 +1657,7 @@ private:
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Initializing a pointer value. For example: *p = 0; */
|
/** Initializing a pointer value. For example: *p = 0; */
|
||||||
static void init_pointer(bool &foundError, std::list<ExecutionPath *> &checks, const Token *tok)
|
static void init_pointer(std::list<ExecutionPath *> &checks, const Token *tok)
|
||||||
{
|
{
|
||||||
const unsigned int varid(tok->varId());
|
const unsigned int varid(tok->varId());
|
||||||
if (!varid)
|
if (!varid)
|
||||||
|
@ -1676,7 +1677,7 @@ private:
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
use_pointer(foundError, checks, tok);
|
use_pointer(checks, tok);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1685,7 +1686,7 @@ private:
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Deallocate a pointer. For example: free(p); */
|
/** Deallocate a pointer. For example: free(p); */
|
||||||
static void dealloc_pointer(bool &foundError, std::list<ExecutionPath *> &checks, const Token *tok)
|
static void dealloc_pointer(std::list<ExecutionPath *> &checks, const Token *tok)
|
||||||
{
|
{
|
||||||
const unsigned int varid(tok->varId());
|
const unsigned int varid(tok->varId());
|
||||||
if (!varid)
|
if (!varid)
|
||||||
|
@ -1702,7 +1703,6 @@ private:
|
||||||
CheckOther *checkOther = dynamic_cast<CheckOther *>(c->owner);
|
CheckOther *checkOther = dynamic_cast<CheckOther *>(c->owner);
|
||||||
if (checkOther)
|
if (checkOther)
|
||||||
{
|
{
|
||||||
foundError = true;
|
|
||||||
checkOther->uninitvarError(tok, c->varname);
|
checkOther->uninitvarError(tok, c->varname);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -1777,16 +1777,16 @@ private:
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* use - called from the use* functions below.
|
* use - called from the use* functions below.
|
||||||
* @param foundError this is set to true if an error is found
|
|
||||||
* @param checks all available checks
|
* @param checks all available checks
|
||||||
* @param tok variable token
|
* @param tok variable token
|
||||||
* @param mode specific behaviour
|
* @param mode specific behaviour
|
||||||
|
* @return if error is found, true is returned
|
||||||
*/
|
*/
|
||||||
static void use(bool &foundError, std::list<ExecutionPath *> &checks, const Token *tok, const int mode)
|
static bool use(std::list<ExecutionPath *> &checks, const Token *tok, const int mode)
|
||||||
{
|
{
|
||||||
const unsigned int varid(tok->varId());
|
const unsigned int varid(tok->varId());
|
||||||
if (varid == 0)
|
if (varid == 0)
|
||||||
return;
|
return false;
|
||||||
|
|
||||||
std::list<ExecutionPath *>::const_iterator it;
|
std::list<ExecutionPath *>::const_iterator it;
|
||||||
for (it = checks.begin(); it != checks.end(); ++it)
|
for (it = checks.begin(); it != checks.end(); ++it)
|
||||||
|
@ -1819,56 +1819,55 @@ private:
|
||||||
checkOther->uninitdataError(tok, c->varname);
|
checkOther->uninitdataError(tok, c->varname);
|
||||||
else
|
else
|
||||||
checkOther->uninitvarError(tok, c->varname);
|
checkOther->uninitvarError(tok, c->varname);
|
||||||
foundError = true;
|
return true;
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// No error found
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reading variable. Use this function in situations when it is
|
* Reading variable. Use this function in situations when it is
|
||||||
* invalid to read the data of the variable but not the address.
|
* invalid to read the data of the variable but not the address.
|
||||||
* @param foundError this is set to true if an error is found
|
|
||||||
* @param checks all available checks
|
* @param checks all available checks
|
||||||
* @param tok variable token
|
* @param tok variable token
|
||||||
|
* @return if error is found, true is returned
|
||||||
*/
|
*/
|
||||||
static void use(bool &foundError, std::list<ExecutionPath *> &checks, const Token *tok)
|
static bool use(std::list<ExecutionPath *> &checks, const Token *tok)
|
||||||
{
|
{
|
||||||
use(foundError, checks, tok, 0);
|
return use(checks, tok, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reading array elements. If the variable is not an array then the usage is ok.
|
* Reading array elements. If the variable is not an array then the usage is ok.
|
||||||
* @param foundError this is set to true if an error is found
|
|
||||||
* @param checks all available checks
|
* @param checks all available checks
|
||||||
* @param tok variable token
|
* @param tok variable token
|
||||||
*/
|
*/
|
||||||
static void use_array(bool &foundError, std::list<ExecutionPath *> &checks, const Token *tok)
|
static void use_array(std::list<ExecutionPath *> &checks, const Token *tok)
|
||||||
{
|
{
|
||||||
use(foundError, checks, tok, 1);
|
use(checks, tok, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Bad pointer usage. If the variable is not a pointer then the usage is ok.
|
* Bad pointer usage. If the variable is not a pointer then the usage is ok.
|
||||||
* @param foundError this is set to true if an error is found
|
|
||||||
* @param checks all available checks
|
* @param checks all available checks
|
||||||
* @param tok variable token
|
* @param tok variable token
|
||||||
*/
|
*/
|
||||||
static void use_pointer(bool &foundError, std::list<ExecutionPath *> &checks, const Token *tok)
|
static void use_pointer(std::list<ExecutionPath *> &checks, const Token *tok)
|
||||||
{
|
{
|
||||||
use(foundError, checks, tok, 2);
|
use(checks, tok, 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Using variable.. if it's a dead pointer the usage is invalid.
|
* Using variable.. if it's a dead pointer the usage is invalid.
|
||||||
* @param foundError this is set to true if an error is found
|
|
||||||
* @param checks all available checks
|
* @param checks all available checks
|
||||||
* @param tok variable token
|
* @param tok variable token
|
||||||
*/
|
*/
|
||||||
static void use_dead_pointer(bool &foundError, std::list<ExecutionPath *> &checks, const Token *tok)
|
static void use_dead_pointer(std::list<ExecutionPath *> &checks, const Token *tok)
|
||||||
{
|
{
|
||||||
use(foundError, checks, tok, 3);
|
use(checks, tok, 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** declaring a variable */
|
/** declaring a variable */
|
||||||
|
@ -1916,7 +1915,7 @@ private:
|
||||||
}
|
}
|
||||||
|
|
||||||
/** parse tokens. @sa ExecutionPath::parse */
|
/** parse tokens. @sa ExecutionPath::parse */
|
||||||
const Token *parse(const Token &tok, bool &foundError, std::list<ExecutionPath *> &checks) const
|
const Token *parse(const Token &tok, std::list<ExecutionPath *> &checks) const
|
||||||
{
|
{
|
||||||
// Variable declaration..
|
// Variable declaration..
|
||||||
if (tok.str() != "return")
|
if (tok.str() != "return")
|
||||||
|
@ -1967,13 +1966,13 @@ private:
|
||||||
// Used..
|
// Used..
|
||||||
if (Token::Match(tok.previous(), "[[(,+-*/] %var% []),+-*/]"))
|
if (Token::Match(tok.previous(), "[[(,+-*/] %var% []),+-*/]"))
|
||||||
{
|
{
|
||||||
use(foundError, checks, &tok);
|
use(checks, &tok);
|
||||||
return &tok;
|
return &tok;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Token::Match(tok.previous(), "++|--") || Token::Match(tok.next(), "++|--"))
|
if (Token::Match(tok.previous(), "++|--") || Token::Match(tok.next(), "++|--"))
|
||||||
{
|
{
|
||||||
use(foundError, checks, &tok);
|
use(checks, &tok);
|
||||||
return &tok;
|
return &tok;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1989,7 +1988,13 @@ private:
|
||||||
if (tok2->varId() &&
|
if (tok2->varId() &&
|
||||||
!Token::Match(tok2->previous(), "&|::") &&
|
!Token::Match(tok2->previous(), "&|::") &&
|
||||||
!Token::simpleMatch(tok2->next(), "="))
|
!Token::simpleMatch(tok2->next(), "="))
|
||||||
use(foundError, checks, tok2);
|
{
|
||||||
|
bool foundError = use(checks, tok2);
|
||||||
|
if (foundError)
|
||||||
|
{
|
||||||
|
bailOutVar(checks, tok2->varId());
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// pointer aliasing?
|
// pointer aliasing?
|
||||||
|
@ -2001,15 +2006,15 @@ private:
|
||||||
|
|
||||||
if (Token::simpleMatch(tok.next(), "("))
|
if (Token::simpleMatch(tok.next(), "("))
|
||||||
{
|
{
|
||||||
use_pointer(foundError, checks, &tok);
|
use_pointer(checks, &tok);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Token::Match(tok.tokAt(-2), "[;{}] *"))
|
if (Token::Match(tok.tokAt(-2), "[;{}] *"))
|
||||||
{
|
{
|
||||||
if (Token::simpleMatch(tok.next(), "="))
|
if (Token::simpleMatch(tok.next(), "="))
|
||||||
init_pointer(foundError, checks, &tok);
|
init_pointer(checks, &tok);
|
||||||
else
|
else
|
||||||
use_pointer(foundError, checks, &tok);
|
use_pointer(checks, &tok);
|
||||||
return &tok;
|
return &tok;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2025,11 +2030,11 @@ private:
|
||||||
if (Token::Match(eq, "+=|-=|*=|/=|&=|^=") || eq->str() == "|=")
|
if (Token::Match(eq, "+=|-=|*=|/=|&=|^=") || eq->str() == "|=")
|
||||||
{
|
{
|
||||||
if (tok.previous()->str() == "*")
|
if (tok.previous()->str() == "*")
|
||||||
use_pointer(foundError, checks, &tok);
|
use_pointer(checks, &tok);
|
||||||
else if (tok.next()->str() == "[")
|
else if (tok.next()->str() == "[")
|
||||||
use_array(foundError, checks, &tok);
|
use_array(checks, &tok);
|
||||||
else
|
else
|
||||||
use(foundError, checks, &tok);
|
use(checks, &tok);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2059,7 +2064,7 @@ private:
|
||||||
if (Token::simpleMatch(tok.previous(), "delete") ||
|
if (Token::simpleMatch(tok.previous(), "delete") ||
|
||||||
Token::simpleMatch(tok.tokAt(-3), "delete [ ]"))
|
Token::simpleMatch(tok.tokAt(-3), "delete [ ]"))
|
||||||
{
|
{
|
||||||
dealloc_pointer(foundError, checks, &tok);
|
dealloc_pointer(checks, &tok);
|
||||||
return &tok;
|
return &tok;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2072,7 +2077,7 @@ private:
|
||||||
// deallocate pointer
|
// deallocate pointer
|
||||||
if (Token::Match(&tok, "free|kfree|fclose ( %var% )"))
|
if (Token::Match(&tok, "free|kfree|fclose ( %var% )"))
|
||||||
{
|
{
|
||||||
dealloc_pointer(foundError, checks, tok.tokAt(2));
|
dealloc_pointer(checks, tok.tokAt(2));
|
||||||
return tok.tokAt(3);
|
return tok.tokAt(3);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2081,7 +2086,7 @@ private:
|
||||||
std::list<const Token *> var;
|
std::list<const Token *> var;
|
||||||
parseFunctionCall(tok, var, 1);
|
parseFunctionCall(tok, var, 1);
|
||||||
for (std::list<const Token *>::const_iterator it = var.begin(); it != var.end(); ++it)
|
for (std::list<const Token *>::const_iterator it = var.begin(); it != var.end(); ++it)
|
||||||
use_array(foundError, checks, *it);
|
use_array(checks, *it);
|
||||||
}
|
}
|
||||||
|
|
||||||
// strncpy doesn't 0-terminate first parameter
|
// strncpy doesn't 0-terminate first parameter
|
||||||
|
@ -2122,7 +2127,7 @@ private:
|
||||||
else if (tok2->varId())
|
else if (tok2->varId())
|
||||||
{
|
{
|
||||||
if (Token::Match(tok2->tokAt(-2), "[(,] *") || Token::Match(tok2->next(), ". %var%"))
|
if (Token::Match(tok2->tokAt(-2), "[(,] *") || Token::Match(tok2->next(), ". %var%"))
|
||||||
use_dead_pointer(foundError, checks, tok2);
|
use_dead_pointer(checks, tok2);
|
||||||
|
|
||||||
// it is possible that the variable is initialized here
|
// it is possible that the variable is initialized here
|
||||||
bailouts.insert(tok2->varId());
|
bailouts.insert(tok2->varId());
|
||||||
|
@ -2163,7 +2168,7 @@ private:
|
||||||
// Todo: if (!array && ..
|
// Todo: if (!array && ..
|
||||||
if (Token::Match(tok.next(), "%var% ;"))
|
if (Token::Match(tok.next(), "%var% ;"))
|
||||||
{
|
{
|
||||||
use(foundError, checks, tok.next());
|
use(checks, tok.next());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2181,7 +2186,7 @@ private:
|
||||||
{
|
{
|
||||||
if (!Token::Match(tok.tokAt(-3), "[;{}] %var% ="))
|
if (!Token::Match(tok.tokAt(-3), "[;{}] %var% ="))
|
||||||
{
|
{
|
||||||
use(foundError, checks, &tok);
|
use(checks, &tok);
|
||||||
return &tok;
|
return &tok;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2193,7 +2198,7 @@ private:
|
||||||
if (tok2 && !Token::simpleMatch(tok2->previous(), "*"))
|
if (tok2 && !Token::simpleMatch(tok2->previous(), "*"))
|
||||||
*/
|
*/
|
||||||
{
|
{
|
||||||
use(foundError, checks, &tok);
|
use(checks, &tok);
|
||||||
return &tok;
|
return &tok;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2206,7 +2211,7 @@ private:
|
||||||
while (Token::Match(tok2, ". %var%"))
|
while (Token::Match(tok2, ". %var%"))
|
||||||
tok2 = tok2->tokAt(2);
|
tok2 = tok2->tokAt(2);
|
||||||
if (tok2 && tok2->str() != "=")
|
if (tok2 && tok2->str() != "=")
|
||||||
use_pointer(foundError, checks, &tok);
|
use_pointer(checks, &tok);
|
||||||
else
|
else
|
||||||
bailOutVar(checks, tok.varId());
|
bailOutVar(checks, tok.varId());
|
||||||
return &tok;
|
return &tok;
|
||||||
|
@ -2220,7 +2225,7 @@ private:
|
||||||
|
|
||||||
if (Token::Match(tok.tokAt(-2), "[,(=] *"))
|
if (Token::Match(tok.tokAt(-2), "[,(=] *"))
|
||||||
{
|
{
|
||||||
use_pointer(foundError, checks, &tok);
|
use_pointer(checks, &tok);
|
||||||
return &tok;
|
return &tok;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2254,7 +2259,7 @@ private:
|
||||||
{
|
{
|
||||||
// If the variable hasn't been initialized then call "use"
|
// If the variable hasn't been initialized then call "use"
|
||||||
if (varid1.find(tok2->next()->varId()) == varid1.end())
|
if (varid1.find(tok2->next()->varId()) == varid1.end())
|
||||||
use(foundError, checks, tok2->next());
|
use(checks, tok2->next());
|
||||||
}
|
}
|
||||||
|
|
||||||
// goto stepcode
|
// goto stepcode
|
||||||
|
@ -2302,7 +2307,7 @@ private:
|
||||||
tok2 = tok2->next();
|
tok2 = tok2->next();
|
||||||
|
|
||||||
// call "use"
|
// call "use"
|
||||||
use(foundError, checks, tok2);
|
use(checks, tok2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2313,22 +2318,20 @@ private:
|
||||||
|
|
||||||
bool parseCondition(const Token &tok, std::list<ExecutionPath *> &checks)
|
bool parseCondition(const Token &tok, std::list<ExecutionPath *> &checks)
|
||||||
{
|
{
|
||||||
bool foundError = false;
|
|
||||||
|
|
||||||
if (tok.varId() && Token::Match(&tok, "%var% <|<=|==|!=|)|["))
|
if (tok.varId() && Token::Match(&tok, "%var% <|<=|==|!=|)|["))
|
||||||
use(foundError, checks, &tok);
|
use(checks, &tok);
|
||||||
|
|
||||||
else if (Token::Match(&tok, "!| %var% ("))
|
else if (Token::Match(&tok, "!| %var% ("))
|
||||||
{
|
{
|
||||||
std::list<const Token *> var;
|
std::list<const Token *> var;
|
||||||
parseFunctionCall(tok.str() == "!" ? *tok.next() : tok, var, 1);
|
parseFunctionCall(tok.str() == "!" ? *tok.next() : tok, var, 1);
|
||||||
for (std::list<const Token *>::const_iterator it = var.begin(); it != var.end(); ++it)
|
for (std::list<const Token *>::const_iterator it = var.begin(); it != var.end(); ++it)
|
||||||
use_array(foundError, checks, *it);
|
use_array(checks, *it);
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (Token::Match(&tok, "! %var% )"))
|
else if (Token::Match(&tok, "! %var% )"))
|
||||||
{
|
{
|
||||||
use(foundError, checks, &tok);
|
use(checks, &tok);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -56,17 +56,17 @@ bool ExecutionPath::parseCondition(const Token &tok, std::list<ExecutionPath *>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static const Token *checkExecutionPaths_(const Token *tok, std::list<ExecutionPath *> &checks)
|
static void checkExecutionPaths_(const Token *tok, std::list<ExecutionPath *> &checks)
|
||||||
{
|
{
|
||||||
if (!tok || tok->str() == "}" || checks.empty())
|
if (!tok || tok->str() == "}" || checks.empty())
|
||||||
return 0;
|
return;
|
||||||
|
|
||||||
const std::auto_ptr<ExecutionPath> check(checks.front()->copy());
|
const std::auto_ptr<ExecutionPath> check(checks.front()->copy());
|
||||||
|
|
||||||
for (; tok; tok = tok->next())
|
for (; tok; tok = tok->next())
|
||||||
{
|
{
|
||||||
if (tok->str() == "}")
|
if (tok->str() == "}")
|
||||||
return 0;
|
return;
|
||||||
|
|
||||||
if (Token::simpleMatch(tok, "while ("))
|
if (Token::simpleMatch(tok, "while ("))
|
||||||
{
|
{
|
||||||
|
@ -74,7 +74,7 @@ static const Token *checkExecutionPaths_(const Token *tok, std::list<ExecutionPa
|
||||||
if (checks.size() > 10 || check->parseCondition(*tok->tokAt(2), checks))
|
if (checks.size() > 10 || check->parseCondition(*tok->tokAt(2), checks))
|
||||||
{
|
{
|
||||||
ExecutionPath::bailOut(checks);
|
ExecutionPath::bailOut(checks);
|
||||||
return 0;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// skip "while (fgets()!=NULL)"
|
// skip "while (fgets()!=NULL)"
|
||||||
|
@ -95,7 +95,7 @@ static const Token *checkExecutionPaths_(const Token *tok, std::list<ExecutionPa
|
||||||
if (tok->str() == "goto")
|
if (tok->str() == "goto")
|
||||||
{
|
{
|
||||||
ExecutionPath::bailOut(checks);
|
ExecutionPath::bailOut(checks);
|
||||||
return 0;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// for/while/switch/do .. bail out
|
// for/while/switch/do .. bail out
|
||||||
|
@ -110,7 +110,7 @@ static const Token *checkExecutionPaths_(const Token *tok, std::list<ExecutionPa
|
||||||
if (!tok2 || tok2->str() != "{")
|
if (!tok2 || tok2->str() != "{")
|
||||||
{
|
{
|
||||||
ExecutionPath::bailOut(checks);
|
ExecutionPath::bailOut(checks);
|
||||||
return 0;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// skip { .. }
|
// skip { .. }
|
||||||
|
@ -137,13 +137,13 @@ static const Token *checkExecutionPaths_(const Token *tok, std::list<ExecutionPa
|
||||||
if (Token::simpleMatch(tok, ") {"))
|
if (Token::simpleMatch(tok, ") {"))
|
||||||
{
|
{
|
||||||
ExecutionPath::bailOut(checks);
|
ExecutionPath::bailOut(checks);
|
||||||
return 0;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Token::Match(tok, "abort|exit ("))
|
if (Token::Match(tok, "abort|exit ("))
|
||||||
{
|
{
|
||||||
ExecutionPath::bailOut(checks);
|
ExecutionPath::bailOut(checks);
|
||||||
return 0;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// don't parse into "struct type { .."
|
// don't parse into "struct type { .."
|
||||||
|
@ -160,14 +160,14 @@ static const Token *checkExecutionPaths_(const Token *tok, std::list<ExecutionPa
|
||||||
if (Token::Match(tok->tokAt(2), ". %var% ="))
|
if (Token::Match(tok->tokAt(2), ". %var% ="))
|
||||||
{
|
{
|
||||||
ExecutionPath::bailOut(checks);
|
ExecutionPath::bailOut(checks);
|
||||||
return 0;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
tok = tok->next()->link();
|
tok = tok->next()->link();
|
||||||
if (!tok)
|
if (!tok)
|
||||||
{
|
{
|
||||||
ExecutionPath::bailOut(checks);
|
ExecutionPath::bailOut(checks);
|
||||||
return 0;
|
return;
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -175,12 +175,7 @@ static const Token *checkExecutionPaths_(const Token *tok, std::list<ExecutionPa
|
||||||
// ; { ... }
|
// ; { ... }
|
||||||
if (Token::Match(tok->previous(), "[;{}] {"))
|
if (Token::Match(tok->previous(), "[;{}] {"))
|
||||||
{
|
{
|
||||||
const Token *tokerr = checkExecutionPaths_(tok->next(), checks);
|
checkExecutionPaths_(tok->next(), checks);
|
||||||
if (tokerr)
|
|
||||||
{
|
|
||||||
ExecutionPath::bailOut(checks);
|
|
||||||
return tokerr;
|
|
||||||
}
|
|
||||||
tok = tok->link();
|
tok = tok->link();
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -198,7 +193,7 @@ static const Token *checkExecutionPaths_(const Token *tok, std::list<ExecutionPa
|
||||||
{
|
{
|
||||||
ExecutionPath::bailOut(checks);
|
ExecutionPath::bailOut(checks);
|
||||||
ExecutionPath::bailOut(newchecks);
|
ExecutionPath::bailOut(newchecks);
|
||||||
return 0;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// goto ")"
|
// goto ")"
|
||||||
|
@ -211,7 +206,7 @@ static const Token *checkExecutionPaths_(const Token *tok, std::list<ExecutionPa
|
||||||
{
|
{
|
||||||
ExecutionPath::bailOut(checks);
|
ExecutionPath::bailOut(checks);
|
||||||
ExecutionPath::bailOut(newchecks);
|
ExecutionPath::bailOut(newchecks);
|
||||||
return 0;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Recursively check into the if ..
|
// Recursively check into the if ..
|
||||||
|
@ -220,13 +215,7 @@ static const Token *checkExecutionPaths_(const Token *tok, std::list<ExecutionPa
|
||||||
std::list<ExecutionPath *>::iterator it;
|
std::list<ExecutionPath *>::iterator it;
|
||||||
for (it = checks.begin(); it != checks.end(); ++it)
|
for (it = checks.begin(); it != checks.end(); ++it)
|
||||||
c.push_back((*it)->copy());
|
c.push_back((*it)->copy());
|
||||||
const Token *tokerr = checkExecutionPaths_(tok->next(), c);
|
checkExecutionPaths_(tok->next(), c);
|
||||||
if (tokerr)
|
|
||||||
{
|
|
||||||
ExecutionPath::bailOut(c);
|
|
||||||
ExecutionPath::bailOut(newchecks);
|
|
||||||
return tokerr;
|
|
||||||
}
|
|
||||||
while (!c.empty())
|
while (!c.empty())
|
||||||
{
|
{
|
||||||
newchecks.push_back(c.back());
|
newchecks.push_back(c.back());
|
||||||
|
@ -247,18 +236,12 @@ static const Token *checkExecutionPaths_(const Token *tok, std::list<ExecutionPa
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// there is no "if"..
|
// there is no "if"..
|
||||||
const Token *tokerr = checkExecutionPaths_(tok->next(), checks);
|
checkExecutionPaths_(tok->next(), checks);
|
||||||
if (tokerr)
|
|
||||||
{
|
|
||||||
ExecutionPath::bailOut(newchecks);
|
|
||||||
return tokerr;
|
|
||||||
}
|
|
||||||
|
|
||||||
tok = tok->link();
|
tok = tok->link();
|
||||||
if (!tok)
|
if (!tok)
|
||||||
{
|
{
|
||||||
ExecutionPath::bailOut(newchecks);
|
ExecutionPath::bailOut(newchecks);
|
||||||
return 0;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -269,12 +252,9 @@ static const Token *checkExecutionPaths_(const Token *tok, std::list<ExecutionPa
|
||||||
|
|
||||||
|
|
||||||
{
|
{
|
||||||
bool foundError = false;
|
tok = check->parse(*tok, checks);
|
||||||
tok = check->parse(*tok, foundError, checks);
|
|
||||||
if (checks.empty())
|
if (checks.empty())
|
||||||
return 0;
|
return;
|
||||||
else if (foundError)
|
|
||||||
return tok;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// return/throw ends all execution paths
|
// return/throw ends all execution paths
|
||||||
|
@ -283,7 +263,6 @@ static const Token *checkExecutionPaths_(const Token *tok, std::list<ExecutionPa
|
||||||
ExecutionPath::bailOut(checks);
|
ExecutionPath::bailOut(checks);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void checkExecutionPaths(const Token *tok, ExecutionPath *c)
|
void checkExecutionPaths(const Token *tok, ExecutionPath *c)
|
||||||
|
|
|
@ -96,7 +96,7 @@ public:
|
||||||
* @param checks The execution paths. All execution paths in the list are executed in the current scope.
|
* @param checks The execution paths. All execution paths in the list are executed in the current scope.
|
||||||
* @return the token before the "next" token.
|
* @return the token before the "next" token.
|
||||||
**/
|
**/
|
||||||
virtual const Token *parse(const Token &tok, bool &foundError, std::list<ExecutionPath *> &checks) const = 0;
|
virtual const Token *parse(const Token &tok, std::list<ExecutionPath *> &checks) const = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parse condition
|
* Parse condition
|
||||||
|
|
|
@ -1040,8 +1040,8 @@ private:
|
||||||
" int r = *p;\n"
|
" int r = *p;\n"
|
||||||
" int r2 = *p2;\n"
|
" int r2 = *p2;\n"
|
||||||
"}\n");
|
"}\n");
|
||||||
TODO_ASSERT_EQUALS("[test.cpp:5]: (error) Null pointer dereference\n"
|
ASSERT_EQUALS("[test.cpp:5]: (error) Null pointer dereference\n"
|
||||||
"[test.cpp:6]: (error) Null pointer dereference\n", errout.str());
|
"[test.cpp:6]: (error) Null pointer dereference\n", errout.str());
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue