Forward values after assignment in valueFlowReverse (#2226)

* Forward values after assignment in valueFlowReverse

* Rename variables

* Format
This commit is contained in:
Paul Fultz II 2019-10-03 02:58:57 -05:00 committed by Daniel Marjamäki
parent b79283306f
commit 997803869d
3 changed files with 65 additions and 12 deletions

View File

@ -1625,7 +1625,8 @@ static bool isUnchanged(const Token *startToken, const Token *endToken, const st
struct FwdAnalysis::Result FwdAnalysis::checkRecursive(const Token *expr, const Token *startToken, const Token *endToken, const std::set<int> &exprVarIds, bool local, bool inInnerClass) struct FwdAnalysis::Result FwdAnalysis::checkRecursive(const Token *expr, const Token *startToken, const Token *endToken, const std::set<int> &exprVarIds, bool local, bool inInnerClass)
{ {
// Parse the given tokens // Parse the given tokens
for (const Token *tok = startToken; tok != endToken; tok = tok->next()) {
for (const Token* tok = startToken; precedes(tok, endToken); tok = tok->next()) {
if (Token::simpleMatch(tok, "try {")) { if (Token::simpleMatch(tok, "try {")) {
// TODO: handle try // TODO: handle try
return Result(Result::Type::BAILOUT); return Result(Result::Type::BAILOUT);

View File

@ -1841,6 +1841,16 @@ static void valueFlowGlobalStaticVar(TokenList *tokenList, const Settings *setti
} }
} }
static void valueFlowForward(Token* startToken,
const Token* endToken,
const Token* exprTok,
std::list<ValueFlow::Value> values,
const bool constValue,
const bool subFunction,
TokenList* const tokenlist,
ErrorLogger* const errorLogger,
const Settings* settings);
static void valueFlowReverse(TokenList *tokenlist, static void valueFlowReverse(TokenList *tokenlist,
Token *tok, Token *tok,
const Token * const varToken, const Token * const varToken,
@ -1865,8 +1875,30 @@ static void valueFlowReverse(TokenList *tokenlist,
} }
if (tok2->varId() == varid) { if (tok2->varId() == varid) {
if (tok2->hasKnownValue())
break;
// bailout: assignment // bailout: assignment
if (Token::Match(tok2->previous(), "!!* %name% =")) { if (Token::Match(tok2->previous(), "!!* %name% =")) {
Token* assignTok = const_cast<Token*>(tok2->next()->astOperand2());
if (!assignTok->hasKnownValue()) {
std::list<ValueFlow::Value> values = {val};
setTokenValue(assignTok, val, settings);
if (val2.condition) {
setTokenValue(assignTok, val2, settings);
values.push_back(val2);
}
const Token* startForwardToken = nextAfterAstRightmostLeaf(tok2->next());
const Token* endForwardToken = tok->scope() ? tok->scope()->bodyEnd : tok;
valueFlowForward(const_cast<Token*>(startForwardToken),
endForwardToken,
assignTok,
values,
false,
false,
tokenlist,
errorLogger,
settings);
}
if (settings->debugwarnings) if (settings->debugwarnings)
bailout(tokenlist, errorLogger, tok2, "assignment of " + tok2->str()); bailout(tokenlist, errorLogger, tok2, "assignment of " + tok2->str());
break; break;
@ -2062,6 +2094,17 @@ static void valueFlowReverse(TokenList *tokenlist,
} }
} }
static bool isConditionKnown(const Token* tok, bool then)
{
const char* op = "||";
if (then)
op = "&&";
const Token* parent = tok->astParent();
while (parent && parent->str() == op)
parent = parent->astParent();
return (parent && parent->str() == "(");
}
static void valueFlowBeforeCondition(TokenList *tokenlist, SymbolDatabase *symboldatabase, ErrorLogger *errorLogger, const Settings *settings) static void valueFlowBeforeCondition(TokenList *tokenlist, SymbolDatabase *symboldatabase, ErrorLogger *errorLogger, const Settings *settings)
{ {
for (const Scope * scope : symboldatabase->functionScopes) { for (const Scope * scope : symboldatabase->functionScopes) {
@ -4311,17 +4354,6 @@ static void valueFlowAfterAssign(TokenList *tokenlist, SymbolDatabase* symboldat
} }
} }
static bool isConditionKnown(const Token* tok, bool then)
{
const char * op = "||";
if (then)
op = "&&";
const Token* parent = tok->astParent();
while (parent && parent->str() == op)
parent = parent->astParent();
return (parent && parent->str() == "(");
}
static void valueFlowSetConditionToKnown(const Token* tok, std::list<ValueFlow::Value>& values, bool then) static void valueFlowSetConditionToKnown(const Token* tok, std::list<ValueFlow::Value>& values, bool then)
{ {
if (values.empty()) if (values.empty())

View File

@ -79,6 +79,7 @@ private:
TEST_CASE(valueFlowBeforeConditionSizeof); TEST_CASE(valueFlowBeforeConditionSizeof);
TEST_CASE(valueFlowBeforeConditionSwitch); TEST_CASE(valueFlowBeforeConditionSwitch);
TEST_CASE(valueFlowBeforeConditionTernaryOp); TEST_CASE(valueFlowBeforeConditionTernaryOp);
TEST_CASE(valueFlowBeforeConditionForward);
TEST_CASE(valueFlowAfterAssign); TEST_CASE(valueFlowAfterAssign);
TEST_CASE(valueFlowAfterCondition); TEST_CASE(valueFlowAfterCondition);
@ -1410,6 +1411,25 @@ private:
errout.str()); errout.str());
} }
void valueFlowBeforeConditionForward()
{
const char* code;
code = "void f(int a) {\n"
" int x = a;\n"
" if (a == 123) {}\n"
" int b = x;\n"
"}";
ASSERT_EQUALS(true, testValueOfX(code, 4U, 123));
code = "void f(int a) {\n"
" int x = a;\n"
" if (a != 123) {}\n"
" int b = x;\n"
"}";
ASSERT_EQUALS(true, testValueOfX(code, 4U, 123));
}
void valueFlowAfterAssign() { void valueFlowAfterAssign() {
const char *code; const char *code;