ValueFlow: Infer possible symbolic values (#4947)

This commit is contained in:
Paul Fultz II 2023-04-10 12:27:29 -05:00 committed by GitHub
parent 7cded1967d
commit ac14fd218b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 20 additions and 4 deletions

View File

@ -148,7 +148,8 @@ struct Interval {
result.setMinValue(minValue->intvalue + 1, minValue); result.setMinValue(minValue->intvalue + 1, minValue);
if (minValue->isPossible() && minValue->bound == ValueFlow::Value::Bound::Lower) if (minValue->isPossible() && minValue->bound == ValueFlow::Value::Bound::Lower)
result.setMinValue(minValue->intvalue, minValue); result.setMinValue(minValue->intvalue, minValue);
if (minValue->isKnown()) if (!minValue->isImpossible() && minValue->bound == ValueFlow::Value::Bound::Point &&
std::count_if(values.begin(), values.end(), predicate) == 1)
return Interval::fromInt(minValue->intvalue, minValue); return Interval::fromInt(minValue->intvalue, minValue);
} }
const ValueFlow::Value* maxValue = getCompareValue(values, predicate, std::greater<MathLib::bigint>{}); const ValueFlow::Value* maxValue = getCompareValue(values, predicate, std::greater<MathLib::bigint>{});

View File

@ -6767,8 +6767,6 @@ static void valueFlowInferCondition(TokenList* tokenlist,
if (result.size() != 1) if (result.size() != 1)
continue; continue;
ValueFlow::Value value = result.front(); ValueFlow::Value value = result.front();
value.intvalue = 1;
value.bound = ValueFlow::Value::Bound::Point;
setTokenValue(tok, std::move(value), settings); setTokenValue(tok, std::move(value), settings);
} }
} }

View File

@ -67,6 +67,7 @@ private:
TEST_CASE(zeroDiv15); // #8319 TEST_CASE(zeroDiv15); // #8319
TEST_CASE(zeroDiv16); // #11158 TEST_CASE(zeroDiv16); // #11158
TEST_CASE(zeroDiv17); // #9931 TEST_CASE(zeroDiv17); // #9931
TEST_CASE(zeroDiv18);
TEST_CASE(zeroDivCond); // division by zero / useless condition TEST_CASE(zeroDivCond); // division by zero / useless condition
@ -652,6 +653,17 @@ private:
ASSERT_EQUALS("", errout.str()); ASSERT_EQUALS("", errout.str());
} }
void zeroDiv18()
{
check("int f(int x, int y) {\n"
" if (x == y) {}\n"
" return 1 / (x-y);\n"
"}\n");
ASSERT_EQUALS(
"[test.cpp:2] -> [test.cpp:3]: (warning) Either the condition 'x==y' is redundant or there is division by zero at line 3.\n",
errout.str());
}
void zeroDivCond() { void zeroDivCond() {
check("void f(unsigned int x) {\n" check("void f(unsigned int x) {\n"
" int y = 17 / x;\n" " int y = 17 / x;\n"

View File

@ -5453,6 +5453,7 @@ private:
void valueFlowConditionExpressions() { void valueFlowConditionExpressions() {
const char* code; const char* code;
std::list<ValueFlow::Value> values;
// opposite condition // opposite condition
code = "void f(int i, int j) {\n" code = "void f(int i, int j) {\n"
@ -5559,7 +5560,11 @@ private:
" if (i != j) {}\n" " if (i != j) {}\n"
" }\n" " }\n"
"}\n"; "}\n";
ASSERT_EQUALS(true, removeImpossible(tokenValues(code, "!=")).empty()); values = removeImpossible(tokenValues(code, "!="));
ASSERT_EQUALS(1, values.size());
ASSERT_EQUALS(0, values.front().intvalue);
ASSERT_EQUALS(true, values.front().isIntValue());
ASSERT_EQUALS(true, values.front().isPossible());
code = "void f(bool b, int i, int j) {\n" code = "void f(bool b, int i, int j) {\n"
" if (b || i == j) {} else {\n" " if (b || i == j) {} else {\n"