Fix 10647: FN knownConditionTrueFalse for impossible Boolean value (#3968)
* Add impossible values for bool * Fix valueflow tests * Fix assertion failure * Add test * Format
This commit is contained in:
parent
7a7b3e40eb
commit
0547cbcd26
|
@ -374,7 +374,7 @@ static const Token *getCastTypeStartToken(const Token *parent)
|
||||||
// does the operation cause a loss of information?
|
// does the operation cause a loss of information?
|
||||||
static bool isNonInvertibleOperation(const Token* tok)
|
static bool isNonInvertibleOperation(const Token* tok)
|
||||||
{
|
{
|
||||||
return tok->isComparisonOp() || Token::Match(tok, "%|/|&|%or%|<<|>>");
|
return tok->isComparisonOp() || Token::Match(tok, "%|/|&|%or%|<<|>>|%oror%|&&");
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool isComputableValue(const Token* parent, const ValueFlow::Value& value)
|
static bool isComputableValue(const Token* parent, const ValueFlow::Value& value)
|
||||||
|
@ -1549,7 +1549,19 @@ static void valueFlowImpossibleValues(TokenList* tokenList, const Settings* sett
|
||||||
for (Token* tok = tokenList->front(); tok; tok = tok->next()) {
|
for (Token* tok = tokenList->front(); tok; tok = tok->next()) {
|
||||||
if (tok->hasKnownIntValue())
|
if (tok->hasKnownIntValue())
|
||||||
continue;
|
continue;
|
||||||
if (astIsUnsigned(tok) && !astIsPointer(tok)) {
|
if (Token::Match(tok, "true|false"))
|
||||||
|
continue;
|
||||||
|
if (astIsBool(tok) || Token::Match(tok, "%comp%")) {
|
||||||
|
ValueFlow::Value lower{-1};
|
||||||
|
lower.bound = ValueFlow::Value::Bound::Upper;
|
||||||
|
lower.setImpossible();
|
||||||
|
setTokenValue(tok, lower, settings);
|
||||||
|
|
||||||
|
ValueFlow::Value upper{2};
|
||||||
|
upper.bound = ValueFlow::Value::Bound::Lower;
|
||||||
|
upper.setImpossible();
|
||||||
|
setTokenValue(tok, upper, settings);
|
||||||
|
} else if (astIsUnsigned(tok) && !astIsPointer(tok)) {
|
||||||
std::vector<MathLib::bigint> minvalue = minUnsignedValue(tok);
|
std::vector<MathLib::bigint> minvalue = minUnsignedValue(tok);
|
||||||
if (minvalue.empty())
|
if (minvalue.empty())
|
||||||
continue;
|
continue;
|
||||||
|
|
|
@ -4008,6 +4008,15 @@ private:
|
||||||
" }\n"
|
" }\n"
|
||||||
"};\n");
|
"};\n");
|
||||||
ASSERT_EQUALS("", errout.str());
|
ASSERT_EQUALS("", errout.str());
|
||||||
|
|
||||||
|
check("void f(const uint32_t u) {\n"
|
||||||
|
" const uint32_t v = u < 4;\n"
|
||||||
|
" if (v) {\n"
|
||||||
|
" const uint32_t w = v < 2;\n"
|
||||||
|
" if (w) {}\n"
|
||||||
|
" }\n"
|
||||||
|
"}\n");
|
||||||
|
ASSERT_EQUALS("[test.cpp:5]: (style) Condition 'w' is always true\n", errout.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
void alwaysTrueSymbolic()
|
void alwaysTrueSymbolic()
|
||||||
|
|
|
@ -526,7 +526,7 @@ private:
|
||||||
|
|
||||||
#define valueOfTok(code, tokstr) valueOfTok_(code, tokstr, __FILE__, __LINE__)
|
#define valueOfTok(code, tokstr) valueOfTok_(code, tokstr, __FILE__, __LINE__)
|
||||||
ValueFlow::Value valueOfTok_(const char code[], const char tokstr[], const char* file, int line) {
|
ValueFlow::Value valueOfTok_(const char code[], const char tokstr[], const char* file, int line) {
|
||||||
std::list<ValueFlow::Value> values = tokenValues_(file, line, code, tokstr);
|
std::list<ValueFlow::Value> values = removeImpossible(tokenValues_(file, line, code, tokstr));
|
||||||
return values.size() == 1U && !values.front().isTokValue() ? values.front() : ValueFlow::Value();
|
return values.size() == 1U && !values.front().isTokValue() ? values.front() : ValueFlow::Value();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -552,8 +552,7 @@ private:
|
||||||
ASSERT_EQUALS(0, valueOfTok("x(NULL);", "NULL").intvalue);
|
ASSERT_EQUALS(0, valueOfTok("x(NULL);", "NULL").intvalue);
|
||||||
ASSERT_EQUALS((int)('a'), valueOfTok("x='a';", "'a'").intvalue);
|
ASSERT_EQUALS((int)('a'), valueOfTok("x='a';", "'a'").intvalue);
|
||||||
ASSERT_EQUALS((int)('\n'), valueOfTok("x='\\n';", "'\\n'").intvalue);
|
ASSERT_EQUALS((int)('\n'), valueOfTok("x='\\n';", "'\\n'").intvalue);
|
||||||
TODO_ASSERT_EQUALS(
|
TODO_ASSERT_EQUALS(0xFFFFFFFF00000000, 0, valueOfTok("x=0xFFFFFFFF00000000;", "0xFFFFFFFF00000000").intvalue); // #7701
|
||||||
0xFFFFFFFF00000000, -1, valueOfTok("x=0xFFFFFFFF00000000;", "0xFFFFFFFF00000000").intvalue); // #7701
|
|
||||||
ASSERT_EQUALS_DOUBLE(16, valueOfTok("x=(double)16;", "(").floatValue, 1e-5);
|
ASSERT_EQUALS_DOUBLE(16, valueOfTok("x=(double)16;", "(").floatValue, 1e-5);
|
||||||
ASSERT_EQUALS_DOUBLE(0.0625, valueOfTok("x=1/(double)16;", "/").floatValue, 1e-5);
|
ASSERT_EQUALS_DOUBLE(0.0625, valueOfTok("x=1/(double)16;", "/").floatValue, 1e-5);
|
||||||
|
|
||||||
|
@ -977,7 +976,7 @@ private:
|
||||||
" a = !x;\n"
|
" a = !x;\n"
|
||||||
" if (x==0) {}\n"
|
" if (x==0) {}\n"
|
||||||
"}";
|
"}";
|
||||||
values = tokenValues(code,"!");
|
values = removeImpossible(tokenValues(code, "!"));
|
||||||
ASSERT_EQUALS(1U, values.size());
|
ASSERT_EQUALS(1U, values.size());
|
||||||
ASSERT_EQUALS(1, values.back().intvalue);
|
ASSERT_EQUALS(1, values.back().intvalue);
|
||||||
|
|
||||||
|
@ -1077,22 +1076,22 @@ private:
|
||||||
}
|
}
|
||||||
|
|
||||||
// Comparison of string
|
// Comparison of string
|
||||||
values = tokenValues("f(\"xyz\" == \"xyz\");", "=="); // implementation defined
|
values = removeImpossible(tokenValues("f(\"xyz\" == \"xyz\");", "==")); // implementation defined
|
||||||
ASSERT_EQUALS(0U, values.size()); // <- no value
|
ASSERT_EQUALS(0U, values.size()); // <- no value
|
||||||
|
|
||||||
values = tokenValues("f(\"xyz\" == 0);", "==");
|
values = removeImpossible(tokenValues("f(\"xyz\" == 0);", "=="));
|
||||||
ASSERT_EQUALS(1U, values.size());
|
ASSERT_EQUALS(1U, values.size());
|
||||||
ASSERT_EQUALS(0, values.front().intvalue);
|
ASSERT_EQUALS(0, values.front().intvalue);
|
||||||
|
|
||||||
values = tokenValues("f(0 == \"xyz\");", "==");
|
values = removeImpossible(tokenValues("f(0 == \"xyz\");", "=="));
|
||||||
ASSERT_EQUALS(1U, values.size());
|
ASSERT_EQUALS(1U, values.size());
|
||||||
ASSERT_EQUALS(0, values.front().intvalue);
|
ASSERT_EQUALS(0, values.front().intvalue);
|
||||||
|
|
||||||
values = tokenValues("f(\"xyz\" != 0);", "!=");
|
values = removeImpossible(tokenValues("f(\"xyz\" != 0);", "!="));
|
||||||
ASSERT_EQUALS(1U, values.size());
|
ASSERT_EQUALS(1U, values.size());
|
||||||
ASSERT_EQUALS(1, values.front().intvalue);
|
ASSERT_EQUALS(1, values.front().intvalue);
|
||||||
|
|
||||||
values = tokenValues("f(0 != \"xyz\");", "!=");
|
values = removeImpossible(tokenValues("f(0 != \"xyz\");", "!="));
|
||||||
ASSERT_EQUALS(1U, values.size());
|
ASSERT_EQUALS(1U, values.size());
|
||||||
ASSERT_EQUALS(1, values.front().intvalue);
|
ASSERT_EQUALS(1, values.front().intvalue);
|
||||||
}
|
}
|
||||||
|
@ -3771,7 +3770,7 @@ private:
|
||||||
" while (s.x < y)\n" // s.x does not have known value
|
" while (s.x < y)\n" // s.x does not have known value
|
||||||
" s.x++;\n"
|
" s.x++;\n"
|
||||||
"}";
|
"}";
|
||||||
values = tokenValues(code, "<");
|
values = removeImpossible(tokenValues(code, "<"));
|
||||||
ASSERT_EQUALS(1, values.size());
|
ASSERT_EQUALS(1, values.size());
|
||||||
ASSERT(values.front().isPossible());
|
ASSERT(values.front().isPossible());
|
||||||
ASSERT_EQUALS(1, values.front().intvalue);
|
ASSERT_EQUALS(1, values.front().intvalue);
|
||||||
|
@ -3811,7 +3810,7 @@ private:
|
||||||
" if (*b > 0) {\n" // *b does not have known value
|
" if (*b > 0) {\n" // *b does not have known value
|
||||||
" }\n"
|
" }\n"
|
||||||
"}";
|
"}";
|
||||||
values = tokenValues(code, ">");
|
values = removeImpossible(tokenValues(code, ">"));
|
||||||
ASSERT_EQUALS(1, values.size());
|
ASSERT_EQUALS(1, values.size());
|
||||||
ASSERT(values.front().isPossible());
|
ASSERT(values.front().isPossible());
|
||||||
ASSERT_EQUALS(1, values.front().intvalue);
|
ASSERT_EQUALS(1, values.front().intvalue);
|
||||||
|
@ -3824,7 +3823,7 @@ private:
|
||||||
" dostuff(&pvd);\n"
|
" dostuff(&pvd);\n"
|
||||||
" } while (condition)\n"
|
" } while (condition)\n"
|
||||||
"}";
|
"}";
|
||||||
values = tokenValues(code, "==");
|
values = removeImpossible(tokenValues(code, "=="));
|
||||||
ASSERT_EQUALS(1, values.size());
|
ASSERT_EQUALS(1, values.size());
|
||||||
ASSERT(values.front().isPossible());
|
ASSERT(values.front().isPossible());
|
||||||
ASSERT_EQUALS(1, values.front().intvalue);
|
ASSERT_EQUALS(1, values.front().intvalue);
|
||||||
|
@ -3834,7 +3833,7 @@ private:
|
||||||
"void foo(struct S s) {\n"
|
"void foo(struct S s) {\n"
|
||||||
" for (s.x = 0; s.x < 127; s.x++) {}\n"
|
" for (s.x = 0; s.x < 127; s.x++) {}\n"
|
||||||
"}";
|
"}";
|
||||||
values = tokenValues(code, "<"); // TODO: comparison can be true or false
|
values = removeImpossible(tokenValues(code, "<")); // TODO: comparison can be true or false
|
||||||
ASSERT_EQUALS(true, values.empty());
|
ASSERT_EQUALS(true, values.empty());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5128,7 +5127,7 @@ private:
|
||||||
" if (b && i == j) return;\n"
|
" if (b && i == j) return;\n"
|
||||||
" if(i != j) {}\n"
|
" if(i != j) {}\n"
|
||||||
"}\n";
|
"}\n";
|
||||||
ASSERT_EQUALS(true, tokenValues(code, "!=").empty());
|
ASSERT_EQUALS(true, removeImpossible(tokenValues(code, "!=")).empty());
|
||||||
|
|
||||||
code = "void f(int i, int j) {\n"
|
code = "void f(int i, int j) {\n"
|
||||||
" if (i == j) {\n"
|
" if (i == j) {\n"
|
||||||
|
@ -5156,7 +5155,7 @@ private:
|
||||||
" if (i != j) {}\n"
|
" if (i != j) {}\n"
|
||||||
" }\n"
|
" }\n"
|
||||||
"}\n";
|
"}\n";
|
||||||
ASSERT_EQUALS(true, tokenValues(code, "!=").empty());
|
ASSERT_EQUALS(true, removeImpossible(tokenValues(code, "!=")).empty());
|
||||||
|
|
||||||
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"
|
||||||
|
@ -5170,7 +5169,7 @@ private:
|
||||||
" if (i != j) {}\n"
|
" if (i != j) {}\n"
|
||||||
" }\n"
|
" }\n"
|
||||||
"}\n";
|
"}\n";
|
||||||
ASSERT_EQUALS(true, tokenValues(code, "!=").empty());
|
ASSERT_EQUALS(true, removeImpossible(tokenValues(code, "!=")).empty());
|
||||||
|
|
||||||
code = "void foo()\n" // #8924
|
code = "void foo()\n" // #8924
|
||||||
"{\n"
|
"{\n"
|
||||||
|
|
Loading…
Reference in New Issue