Refactoring, reuse and improve isVariableChangedByFunction()

This commit is contained in:
Daniel Marjamäki 2017-11-18 11:02:52 +01:00
parent 9191e6f112
commit 8fe4852b98
3 changed files with 34 additions and 25 deletions

View File

@ -398,6 +398,16 @@ bool isReturnScope(const Token * const endToken)
return false; return false;
} }
bool isVariableChangedByFunctionCall(const Token *tok, unsigned int varid, const Settings *settings, bool *inconclusive)
{
if (!tok)
return false;
if (tok->varId() == varid)
return isVariableChangedByFunctionCall(tok, settings, inconclusive);
return isVariableChangedByFunctionCall(tok->astOperand1(), varid, settings, inconclusive) ||
isVariableChangedByFunctionCall(tok->astOperand2(), varid, settings, inconclusive);
}
bool isVariableChangedByFunctionCall(const Token *tok, const Settings *settings, bool *inconclusive) bool isVariableChangedByFunctionCall(const Token *tok, const Settings *settings, bool *inconclusive)
{ {
if (!tok) if (!tok)
@ -411,7 +421,17 @@ bool isVariableChangedByFunctionCall(const Token *tok, const Settings *settings,
; ;
else if (Token::Match(tok->tokAt(addressOf?-2:-1), "[(,] &| %name% [,)]")) else if (Token::Match(tok->tokAt(addressOf?-2:-1), "[(,] &| %name% [,)]"))
; ;
else else if (Token::Match(tok->tokAt(addressOf?-2:-1), "[?:] &| %name% [:,)]")) {
const Token *parent = tok->astParent();
if (parent == tok->previous() && parent->str() == "&")
parent = parent->astParent();
while (Token::Match(parent, "[?:]"))
parent = parent->astParent();
while (Token::simpleMatch(parent, ","))
parent = parent->astParent();
if (!parent || parent->str() != "(")
return false;
} else
return false; return false;
// reinterpret_cast etc.. // reinterpret_cast etc..

View File

@ -74,6 +74,17 @@ bool isWithoutSideEffects(bool cpp, const Token* tok);
/** Is scope a return scope (scope will unconditionally return) */ /** Is scope a return scope (scope will unconditionally return) */
bool isReturnScope(const Token *endToken); bool isReturnScope(const Token *endToken);
/** Is variable changed by function call?
* In case the answer of the question is inconclusive, e.g. because the function declaration is not known
* the return value is false and the output parameter inconclusive is set to true
*
* @param tok ast tree
* @param varid Variable Id
* @param settings program settings
* @param inconclusive pointer to output variable which indicates that the answer of the question is inconclusive
*/
bool isVariableChangedByFunctionCall(const Token *tok, unsigned int varid, const Settings *settings, bool *inconclusive);
/** Is variable changed by function call? /** Is variable changed by function call?
* In case the answer of the question is inconclusive, e.g. because the function declaration is not known * In case the answer of the question is inconclusive, e.g. because the function declaration is not known
* the return value is false and the output parameter inconclusive is set to true * the return value is false and the output parameter inconclusive is set to true

View File

@ -115,27 +115,6 @@ static void changeKnownToPossible(std::list<ValueFlow::Value> &values)
it->changeKnownToPossible(); it->changeKnownToPossible();
} }
static bool mightBeNonConstPointerFunctionArg(const Token *tok)
{
// TODO: check if argument might be non-const pointer
const Token *parent = tok->astParent();
while (parent && parent->str() == ",")
parent = parent->astParent();
return (parent && Token::Match(parent->previous(), "%name% ("));
}
static const Token *findVariableInAST(const Token *tok, unsigned int varid)
{
if (!tok)
return nullptr;
if (tok->varId() == varid)
return tok;
const Token *ret1 = findVariableInAST(tok->astOperand1(), varid);
if (ret1)
return ret1;
return findVariableInAST(tok->astOperand2(), varid);
}
/** /**
* Is condition always false when variable has given value? * Is condition always false when variable has given value?
* \param condition top ast token in condition * \param condition top ast token in condition
@ -1858,7 +1837,7 @@ static bool valueFlowForward(Token * const startToken,
std::list<ValueFlow::Value>::const_iterator it; std::list<ValueFlow::Value>::const_iterator it;
for (it = values.begin(); it != values.end(); ++it) for (it = values.begin(); it != values.end(); ++it)
valueFlowAST(const_cast<Token*>(expr), varid, *it, settings); valueFlowAST(const_cast<Token*>(expr), varid, *it, settings);
if ((expr->valueType() && expr->valueType()->pointer) && mightBeNonConstPointerFunctionArg(tok2) && findVariableInAST(expr,varid)) if (isVariableChangedByFunctionCall(expr, varid, settings, nullptr))
changeKnownToPossible(values); changeKnownToPossible(values);
} else { } else {
std::list<ValueFlow::Value>::const_iterator it; std::list<ValueFlow::Value>::const_iterator it;
@ -1871,8 +1850,7 @@ static bool valueFlowForward(Token * const startToken,
else else
valueFlowAST(const_cast<Token*>(op2), varid, *it, settings); valueFlowAST(const_cast<Token*>(op2), varid, *it, settings);
} }
if (isVariableChangedByFunctionCall(op2, varid, settings, nullptr))
if (mightBeNonConstPointerFunctionArg(tok2) && findVariableInAST(op2,varid))
changeKnownToPossible(values); changeKnownToPossible(values);
} }