diff --git a/lib/valueflow.cpp b/lib/valueflow.cpp index 360dc3e46..b43a6ff28 100644 --- a/lib/valueflow.cpp +++ b/lib/valueflow.cpp @@ -2354,7 +2354,10 @@ static void valueFlowAfterCondition(TokenList *tokenlist, SymbolDatabase* symbol const Scope * scope = symboldatabase->functionScopes[i]; std::set aliased; for (Token* tok = const_cast(scope->classStart); tok != scope->classEnd; tok = tok->next()) { - const Token *vartok, *numtok; + const Token * vartok = nullptr; + const Token * numtok = nullptr; + const Token * lowertok = nullptr; + const Token * uppertok = nullptr; if (Token::Match(tok, "= & %var% ;")) aliased.insert(tok->tokAt(2)->varId()); @@ -2372,7 +2375,35 @@ static void valueFlowAfterCondition(TokenList *tokenlist, SymbolDatabase* symbol } if (vartok->str() == "=" && vartok->astOperand1() && vartok->astOperand2()) vartok = vartok->astOperand1(); - if (!vartok->isName() || !numtok->hasKnownIntValue()) + if (!vartok->isName()) + continue; + } else if (Token::simpleMatch(tok, ">")) { + if (!tok->astOperand1() || !tok->astOperand2()) + continue; + if (tok->astOperand1()->hasKnownIntValue()) { + uppertok = tok->astOperand1(); + vartok = tok->astOperand2(); + } else { + lowertok = tok->astOperand2(); + vartok = tok->astOperand1(); + } + if (vartok->str() == "=" && vartok->astOperand1() && vartok->astOperand2()) + vartok = vartok->astOperand1(); + if (!vartok->isName()) + continue; + } else if (Token::simpleMatch(tok, "<")) { + if (!tok->astOperand1() || !tok->astOperand2()) + continue; + if (tok->astOperand1()->hasKnownIntValue()) { + lowertok = tok->astOperand1(); + vartok = tok->astOperand2(); + } else { + uppertok = tok->astOperand2(); + vartok = tok->astOperand1(); + } + if (vartok->str() == "=" && vartok->astOperand1() && vartok->astOperand2()) + vartok = vartok->astOperand1(); + if (!vartok->isName()) continue; } else if (tok->str() == "!") { vartok = tok->astOperand1(); @@ -2390,6 +2421,13 @@ static void valueFlowAfterCondition(TokenList *tokenlist, SymbolDatabase* symbol continue; } + if(numtok && !numtok->hasKnownIntValue()) + continue; + if(lowertok && !lowertok->hasKnownIntValue()) + continue; + if(uppertok && !uppertok->hasKnownIntValue()) + continue; + const unsigned int varid = vartok->varId(); if (varid == 0U) continue; @@ -2402,7 +2440,21 @@ static void valueFlowAfterCondition(TokenList *tokenlist, SymbolDatabase* symbol continue; } std::list values; - values.push_back(ValueFlow::Value(tok, numtok ? numtok->values().front().intvalue : 0LL)); + // TODO: We should add all known values + if(numtok) { + values.push_back(ValueFlow::Value(tok, numtok->values().front().intvalue)); + } else if(lowertok) { + long long v = lowertok->values().front().intvalue; + values.push_back(ValueFlow::Value(tok, v+1)); + + } else if(uppertok) { + long long v = uppertok->values().front().intvalue; + values.push_back(ValueFlow::Value(tok, v-1)); + + } else { + values.push_back(ValueFlow::Value(tok, 0LL)); + + } if (Token::Match(tok->astParent(), "%oror%|&&")) { Token *parent = const_cast(tok->astParent()); @@ -2453,7 +2505,7 @@ static void valueFlowAfterCondition(TokenList *tokenlist, SymbolDatabase* symbol // based on the comparison, should we check the if or while? int codeblock = 0; - if (Token::Match(tok, "==|>=|<=|!")) + if (Token::Match(tok, "==|>=|<=|!|>|<")) codeblock = 1; else if (Token::Match(tok, "%name%|!=")) codeblock = 2; diff --git a/test/testvalueflow.cpp b/test/testvalueflow.cpp index d8b97406c..8f422f1fb 100644 --- a/test/testvalueflow.cpp +++ b/test/testvalueflow.cpp @@ -1732,6 +1732,40 @@ private: "}"; ASSERT_EQUALS(false, testValueOfX(code, 3U, 123)); + code = "void f(int x) {\n" + " if (x > 123) {\n" + " a = x;\n" + " }\n" + "}"; + ASSERT_EQUALS(true, testValueOfX(code, 3U, 124)); + ASSERT_EQUALS(false, testValueOfX(code, 3U, 123)); + + code = "void f(int x) {\n" + " if (x < 123) {\n" + " a = x;\n" + " }\n" + "}"; + ASSERT_EQUALS(true, testValueOfX(code, 3U, 122)); + ASSERT_EQUALS(false, testValueOfX(code, 3U, 123)); + + // ---- + + code = "void f(int x) {\n" + " if (123 < x) {\n" + " a = x;\n" + " }\n" + "}"; + ASSERT_EQUALS(true, testValueOfX(code, 3U, 124)); + ASSERT_EQUALS(false, testValueOfX(code, 3U, 123)); + + code = "void f(int x) {\n" + " if (123 > x) {\n" + " a = x;\n" + " }\n" + "}"; + ASSERT_EQUALS(true, testValueOfX(code, 3U, 122)); + ASSERT_EQUALS(false, testValueOfX(code, 3U, 123)); + // in else code = "void f(int x) {\n" " if (x == 123) {}\n"