From 50ed4db17cca4f7f7f2d996f26de6c14f0ab8eb6 Mon Sep 17 00:00:00 2001 From: Paul Date: Sat, 28 Sep 2019 22:12:37 -0500 Subject: [PATCH 1/3] Forward values after assignment in valueFlowReverse --- lib/astutils.cpp | 3 ++- lib/valueflow.cpp | 46 ++++++++++++++++++++++++++++++++---------- test/testvalueflow.cpp | 19 +++++++++++++++++ 3 files changed, 56 insertions(+), 12 deletions(-) diff --git a/lib/astutils.cpp b/lib/astutils.cpp index 0ee6e8b59b3..a5f16e4d3d5 100644 --- a/lib/astutils.cpp +++ b/lib/astutils.cpp @@ -1614,7 +1614,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 &exprVarIds, bool local, bool inInnerClass) { // 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 {")) { // TODO: handle try return Result(Result::Type::BAILOUT); diff --git a/lib/valueflow.cpp b/lib/valueflow.cpp index 83face98f70..6e4d16517b0 100644 --- a/lib/valueflow.cpp +++ b/lib/valueflow.cpp @@ -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 values, + const bool constValue, + const bool subFunction, + TokenList* const tokenlist, + ErrorLogger* const errorLogger, + const Settings* settings); + static void valueFlowReverse(TokenList *tokenlist, Token *tok, const Token * const varToken, @@ -1865,8 +1875,22 @@ static void valueFlowReverse(TokenList *tokenlist, } if (tok2->varId() == varid) { + if (tok2->hasKnownValue()) + break; // bailout: assignment if (Token::Match(tok2->previous(), "!!* %name% =")) { + Token * assignTok = const_cast(tok2->next()->astOperand2()); + if (!assignTok->hasKnownValue()) { + std::list values = {val}; + setTokenValue(assignTok, val, settings); + if (val2.condition) { + setTokenValue(assignTok, val2, settings); + values.push_back(val2); + } + const Token * startToken = nextAfterAstRightmostLeaf(tok2->next()); + const Token * endToken = tok->scope() ? tok->scope()->bodyEnd : tok; + valueFlowForward(const_cast(startToken), endToken, assignTok, values, false, false, tokenlist, errorLogger, settings); + } if (settings->debugwarnings) bailout(tokenlist, errorLogger, tok2, "assignment of " + tok2->str()); break; @@ -2062,6 +2086,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) { for (const Scope * scope : symboldatabase->functionScopes) { @@ -4338,17 +4373,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& values, bool then) { if (values.empty()) diff --git a/test/testvalueflow.cpp b/test/testvalueflow.cpp index f9596ee42c9..e39a9389a00 100644 --- a/test/testvalueflow.cpp +++ b/test/testvalueflow.cpp @@ -79,6 +79,7 @@ class TestValueFlow : public TestFixture { TEST_CASE(valueFlowBeforeConditionSizeof); TEST_CASE(valueFlowBeforeConditionSwitch); TEST_CASE(valueFlowBeforeConditionTernaryOp); + TEST_CASE(valueFlowBeforeConditionForward); TEST_CASE(valueFlowAfterAssign); TEST_CASE(valueFlowAfterCondition); @@ -1410,6 +1411,24 @@ class TestValueFlow : public TestFixture { 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() { const char *code; From d496c4c0e3e84d649165cf3e778a431b403885d1 Mon Sep 17 00:00:00 2001 From: Paul Date: Sat, 28 Sep 2019 23:19:34 -0500 Subject: [PATCH 2/3] Rename variables --- lib/valueflow.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/valueflow.cpp b/lib/valueflow.cpp index 6e4d16517b0..81c9927600f 100644 --- a/lib/valueflow.cpp +++ b/lib/valueflow.cpp @@ -1887,9 +1887,9 @@ static void valueFlowReverse(TokenList *tokenlist, setTokenValue(assignTok, val2, settings); values.push_back(val2); } - const Token * startToken = nextAfterAstRightmostLeaf(tok2->next()); - const Token * endToken = tok->scope() ? tok->scope()->bodyEnd : tok; - valueFlowForward(const_cast(startToken), endToken, assignTok, values, false, false, tokenlist, errorLogger, settings); + const Token * startForwardToken = nextAfterAstRightmostLeaf(tok2->next()); + const Token * endForwardToken = tok->scope() ? tok->scope()->bodyEnd : tok; + valueFlowForward(const_cast(startForwardToken), endForwardToken, assignTok, values, false, false, tokenlist, errorLogger, settings); } if (settings->debugwarnings) bailout(tokenlist, errorLogger, tok2, "assignment of " + tok2->str()); From 4cf3ae2765d17d53b8db15eadf0cad4e1756f1f4 Mon Sep 17 00:00:00 2001 From: Paul Date: Sat, 28 Sep 2019 23:20:05 -0500 Subject: [PATCH 3/3] Format --- lib/astutils.cpp | 2 +- lib/valueflow.cpp | 18 +++++++++++++----- test/testvalueflow.cpp | 5 +++-- 3 files changed, 17 insertions(+), 8 deletions(-) diff --git a/lib/astutils.cpp b/lib/astutils.cpp index a5f16e4d3d5..74c89a60163 100644 --- a/lib/astutils.cpp +++ b/lib/astutils.cpp @@ -1615,7 +1615,7 @@ struct FwdAnalysis::Result FwdAnalysis::checkRecursive(const Token *expr, const { // Parse the given tokens - for (const Token *tok = startToken; precedes(tok, endToken); tok = tok->next()) { + for (const Token* tok = startToken; precedes(tok, endToken); tok = tok->next()) { if (Token::simpleMatch(tok, "try {")) { // TODO: handle try return Result(Result::Type::BAILOUT); diff --git a/lib/valueflow.cpp b/lib/valueflow.cpp index 81c9927600f..e7e27b7a336 100644 --- a/lib/valueflow.cpp +++ b/lib/valueflow.cpp @@ -1879,7 +1879,7 @@ static void valueFlowReverse(TokenList *tokenlist, break; // bailout: assignment if (Token::Match(tok2->previous(), "!!* %name% =")) { - Token * assignTok = const_cast(tok2->next()->astOperand2()); + Token* assignTok = const_cast(tok2->next()->astOperand2()); if (!assignTok->hasKnownValue()) { std::list values = {val}; setTokenValue(assignTok, val, settings); @@ -1887,9 +1887,17 @@ static void valueFlowReverse(TokenList *tokenlist, 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(startForwardToken), endForwardToken, assignTok, values, false, false, tokenlist, errorLogger, settings); + const Token* startForwardToken = nextAfterAstRightmostLeaf(tok2->next()); + const Token* endForwardToken = tok->scope() ? tok->scope()->bodyEnd : tok; + valueFlowForward(const_cast(startForwardToken), + endForwardToken, + assignTok, + values, + false, + false, + tokenlist, + errorLogger, + settings); } if (settings->debugwarnings) bailout(tokenlist, errorLogger, tok2, "assignment of " + tok2->str()); @@ -2088,7 +2096,7 @@ static void valueFlowReverse(TokenList *tokenlist, static bool isConditionKnown(const Token* tok, bool then) { - const char * op = "||"; + const char* op = "||"; if (then) op = "&&"; const Token* parent = tok->astParent(); diff --git a/test/testvalueflow.cpp b/test/testvalueflow.cpp index e39a9389a00..0ef8c8be0f6 100644 --- a/test/testvalueflow.cpp +++ b/test/testvalueflow.cpp @@ -1411,8 +1411,9 @@ class TestValueFlow : public TestFixture { errout.str()); } - void valueFlowBeforeConditionForward() { - const char *code; + void valueFlowBeforeConditionForward() + { + const char* code; code = "void f(int a) {\n" " int x = a;\n"