Fixed #7567 ("(a | 7) > 6U" is always true)
This commit is contained in:
parent
f337838917
commit
09a83f2cc8
|
@ -281,36 +281,55 @@ void CheckCondition::comparison()
|
||||||
return;
|
return;
|
||||||
|
|
||||||
for (const Token *tok = _tokenizer->tokens(); tok; tok = tok->next()) {
|
for (const Token *tok = _tokenizer->tokens(); tok; tok = tok->next()) {
|
||||||
if (Token::Match(tok, "==|!=|>")) {
|
if (!tok->isComparisonOp())
|
||||||
const Token *expr1 = tok->astOperand1();
|
continue;
|
||||||
const Token *expr2 = tok->astOperand2();
|
|
||||||
if (!expr1 || !expr2)
|
const Token *expr1 = tok->astOperand1();
|
||||||
|
const Token *expr2 = tok->astOperand2();
|
||||||
|
if (!expr1 || !expr2)
|
||||||
|
continue;
|
||||||
|
if (expr1->isNumber())
|
||||||
|
std::swap(expr1,expr2);
|
||||||
|
if (!expr2->isNumber())
|
||||||
|
continue;
|
||||||
|
const MathLib::bigint num2 = MathLib::toLongNumber(expr2->str());
|
||||||
|
if (num2 < 0)
|
||||||
|
continue;
|
||||||
|
if (!Token::Match(expr1,"[&|]"))
|
||||||
|
continue;
|
||||||
|
std::list<MathLib::bigint> numbers;
|
||||||
|
getnumchildren(expr1, numbers);
|
||||||
|
for (std::list<MathLib::bigint>::const_iterator num = numbers.begin(); num != numbers.end(); ++num) {
|
||||||
|
const MathLib::bigint num1 = *num;
|
||||||
|
if (num1 < 0)
|
||||||
continue;
|
continue;
|
||||||
if (expr1->isNumber())
|
if (Token::Match(tok, "==|!=")) {
|
||||||
std::swap(expr1,expr2);
|
if ((expr1->str() == "&" && (num1 & num2) != num2) ||
|
||||||
if (!expr2->isNumber())
|
(expr1->str() == "|" && (num1 | num2) != num2)) {
|
||||||
continue;
|
const std::string& op(tok->str());
|
||||||
const MathLib::bigint num2 = MathLib::toLongNumber(expr2->str());
|
comparisonError(expr1, expr1->str(), num1, op, num2, op=="==" ? false : true);
|
||||||
if (num2 < 0)
|
}
|
||||||
continue;
|
} else if (expr1->str() == "&") {
|
||||||
if (!Token::Match(expr1,"[&|]"))
|
const bool or_equal = Token::Match(tok, ">=|<=");
|
||||||
continue;
|
const std::string& op(tok->str());
|
||||||
std::list<MathLib::bigint> numbers;
|
if ((Token::Match(tok, ">=|<")) && (num1 < num2)) {
|
||||||
getnumchildren(expr1, numbers);
|
comparisonError(expr1, expr1->str(), num1, op, num2, or_equal ? false : true);
|
||||||
for (std::list<MathLib::bigint>::const_iterator num = numbers.begin(); num != numbers.end(); ++num) {
|
} else if ((Token::Match(tok, "<=|>")) && (num1 <= num2)) {
|
||||||
const MathLib::bigint num1 = *num;
|
comparisonError(expr1, expr1->str(), num1, op, num2, or_equal ? true : false);
|
||||||
if (num1 < 0)
|
}
|
||||||
continue;
|
} else if (expr1->str() == "|") {
|
||||||
if (Token::Match(tok, "==|!=")) {
|
if ((expr1->astOperand1()->valueType()) &&
|
||||||
if ((expr1->str() == "&" && (num1 & num2) != num2) ||
|
(expr1->astOperand1()->valueType()->sign == ValueType::Sign::UNSIGNED)) {
|
||||||
(expr1->str() == "|" && (num1 | num2) != num2)) {
|
const bool or_equal = Token::Match(tok, ">=|<=");
|
||||||
const std::string& op(tok->str());
|
const std::string& op(tok->str());
|
||||||
comparisonError(expr1, expr1->str(), num1, op, num2, op=="==" ? false : true);
|
if ((Token::Match(tok, ">=|<")) && (num1 >= num2)) {
|
||||||
}
|
//"(a | 0x07) >= 7U" is always true for unsigned a
|
||||||
} else if (Token::simpleMatch(tok, ">")) {
|
//"(a | 0x07) < 7U" is always false for unsigned a
|
||||||
if ((expr1->str() == "&" && (num1 <= num2))) {
|
comparisonError(expr1, expr1->str(), num1, op, num2, or_equal ? true : false);
|
||||||
const std::string& op(tok->str());
|
} else if ((Token::Match(tok, "<=|>")) && (num1 > num2)) {
|
||||||
comparisonError(expr1, expr1->str(), num1, op, num2, false);
|
//"(a | 0x08) <= 7U" is always false for unsigned a
|
||||||
|
//"(a | 0x07) > 6U" is always true for unsigned a
|
||||||
|
comparisonError(expr1, expr1->str(), num1, op, num2, or_equal ? false : true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -47,7 +47,7 @@ private:
|
||||||
|
|
||||||
TEST_CASE(assignAndCompare); // assignment and comparison don't match
|
TEST_CASE(assignAndCompare); // assignment and comparison don't match
|
||||||
TEST_CASE(mismatchingBitAnd); // overlapping bitmasks
|
TEST_CASE(mismatchingBitAnd); // overlapping bitmasks
|
||||||
TEST_CASE(compare); // mismatching LHS/RHS in comparison
|
TEST_CASE(comparison); // CheckCondition::comparison test cases
|
||||||
TEST_CASE(multicompare); // mismatching comparisons
|
TEST_CASE(multicompare); // mismatching comparisons
|
||||||
TEST_CASE(duplicateIf); // duplicate conditions in if and else-if
|
TEST_CASE(duplicateIf); // duplicate conditions in if and else-if
|
||||||
|
|
||||||
|
@ -318,30 +318,64 @@ private:
|
||||||
ASSERT_EQUALS("", errout.str());
|
ASSERT_EQUALS("", errout.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
void compare() {
|
void comparison() {
|
||||||
check("void foo(int x)\n"
|
// CheckCondition::comparison test cases
|
||||||
"{\n"
|
// '=='
|
||||||
" if ((x & 4) == 3);\n"
|
check("void f(int a) {\n assert( (a & 0x07) == 8U );\n}");
|
||||||
"}");
|
ASSERT_EQUALS("[test.cpp:2]: (style) Expression '(X & 0x7) == 0x8' is always false.\n",errout.str());
|
||||||
ASSERT_EQUALS("[test.cpp:3]: (style) Expression '(X & 0x4) == 0x3' is always false.\n", errout.str());
|
check("void f(int a) {\n assert( (a & b & 4 & c ) == 3 );\n}");
|
||||||
|
ASSERT_EQUALS("[test.cpp:2]: (style) Expression '(X & 0x4) == 0x3' is always false.\n", errout.str());
|
||||||
check("void foo(int x)\n"
|
check("void f(int a) {\n assert( (a | 0x07) == 8U );\n}");
|
||||||
"{\n"
|
ASSERT_EQUALS("[test.cpp:2]: (style) Expression '(X | 0x7) == 0x8' is always false.\n",errout.str());
|
||||||
" if ((x | 4) == 3);\n"
|
check("void f(int a) {\n assert( (a & 0x07) == 7U );\n}");
|
||||||
"}");
|
ASSERT_EQUALS("", errout.str());
|
||||||
ASSERT_EQUALS("[test.cpp:3]: (style) Expression '(X | 0x4) == 0x3' is always false.\n", errout.str());
|
check("void f(int a) {\n assert( (a | 0x01) == -15 );\n}");
|
||||||
|
ASSERT_EQUALS("", errout.str());
|
||||||
check("void foo(int x)\n"
|
// '!='
|
||||||
"{\n"
|
check("void f(int a) {\n assert( (a & 0x07) != 8U );\n}");
|
||||||
" if ((x | 4) != 3);\n"
|
ASSERT_EQUALS("[test.cpp:2]: (style) Expression '(X & 0x7) != 0x8' is always true.\n",errout.str());
|
||||||
"}");
|
check("void f(int a) {\n assert( (a | 0x07) != 8U );\n}");
|
||||||
ASSERT_EQUALS("[test.cpp:3]: (style) Expression '(X | 0x4) != 0x3' is always true.\n", errout.str());
|
ASSERT_EQUALS("[test.cpp:2]: (style) Expression '(X | 0x7) != 0x8' is always true.\n",errout.str());
|
||||||
|
check("void f(int a) {\n assert( (a & 0x07) != 7U );\n}");
|
||||||
check("void foo(int x)\n"
|
ASSERT_EQUALS("", errout.str());
|
||||||
"{\n"
|
check("void f(int a) {\n assert( (a | 0x07) != 7U );\n}");
|
||||||
" if ((x & y & 4 & z ) == 3);\n"
|
ASSERT_EQUALS("", errout.str());
|
||||||
"}");
|
// '>='
|
||||||
ASSERT_EQUALS("[test.cpp:3]: (style) Expression '(X & 0x4) == 0x3' is always false.\n", errout.str());
|
check("void f(int a) {\n assert( (a & 0x07) >= 8U );\n}");
|
||||||
|
ASSERT_EQUALS("[test.cpp:2]: (style) Expression '(X & 0x7) >= 0x8' is always false.\n",errout.str());
|
||||||
|
check("void f(unsigned int a) {\n assert( (a | 0x7) >= 7U );\n}");
|
||||||
|
ASSERT_EQUALS("[test.cpp:2]: (style) Expression '(X | 0x7) >= 0x7' is always true.\n",errout.str());
|
||||||
|
check("void f(int a) {\n assert( (a & 0x07) >= 7U );\n}");
|
||||||
|
ASSERT_EQUALS("",errout.str());
|
||||||
|
check("void f(int a) {\n assert( (a | 0x07) >= 8U );\n}");
|
||||||
|
ASSERT_EQUALS("",errout.str()); //correct for negative 'a'
|
||||||
|
// '>'
|
||||||
|
check("void f(int a) {\n assert( (a & 0x07) > 7U );\n}");
|
||||||
|
ASSERT_EQUALS("[test.cpp:2]: (style) Expression '(X & 0x7) > 0x7' is always false.\n",errout.str());
|
||||||
|
check("void f(unsigned int a) {\n assert( (a | 0x7) > 6U );\n}");
|
||||||
|
ASSERT_EQUALS("[test.cpp:2]: (style) Expression '(X | 0x7) > 0x6' is always true.\n",errout.str());
|
||||||
|
check("void f(int a) {\n assert( (a & 0x07) > 6U );\n}");
|
||||||
|
ASSERT_EQUALS("",errout.str());
|
||||||
|
check("void f(int a) {\n assert( (a | 0x07) > 7U );\n}");
|
||||||
|
ASSERT_EQUALS("",errout.str()); //correct for negative 'a'
|
||||||
|
// '<='
|
||||||
|
check("void f(int a) {\n assert( (a & 0x07) <= 7U );\n}");
|
||||||
|
ASSERT_EQUALS("[test.cpp:2]: (style) Expression '(X & 0x7) <= 0x7' is always true.\n",errout.str());
|
||||||
|
check("void f(unsigned int a) {\n assert( (a | 0x08) <= 7U );\n}");
|
||||||
|
ASSERT_EQUALS("[test.cpp:2]: (style) Expression '(X | 0x8) <= 0x7' is always false.\n",errout.str());
|
||||||
|
check("void f(int a) {\n assert( (a & 0x07) <= 6U );\n}");
|
||||||
|
ASSERT_EQUALS("",errout.str());
|
||||||
|
check("void f(int a) {\n assert( (a | 0x08) <= 7U );\n}");
|
||||||
|
ASSERT_EQUALS("",errout.str()); //correct for negative 'a'
|
||||||
|
// '<'
|
||||||
|
check("void f(int a) {\n assert( (a & 0x07) < 8U );\n}");
|
||||||
|
ASSERT_EQUALS("[test.cpp:2]: (style) Expression '(X & 0x7) < 0x8' is always true.\n",errout.str());
|
||||||
|
check("void f(unsigned int a) {\n assert( (a | 0x07) < 7U );\n}");
|
||||||
|
ASSERT_EQUALS("[test.cpp:2]: (style) Expression '(X | 0x7) < 0x7' is always false.\n",errout.str());
|
||||||
|
check("void f(int a) {\n assert( (a & 0x07) < 3U );\n}");
|
||||||
|
ASSERT_EQUALS("",errout.str());
|
||||||
|
check("void f(int a) {\n assert( (a | 0x07) < 7U );\n}");
|
||||||
|
ASSERT_EQUALS("",errout.str()); //correct for negative 'a'
|
||||||
}
|
}
|
||||||
|
|
||||||
void multicompare() {
|
void multicompare() {
|
||||||
|
@ -592,75 +626,6 @@ private:
|
||||||
" }\n"
|
" }\n"
|
||||||
"}");
|
"}");
|
||||||
ASSERT_EQUALS("", errout.str());
|
ASSERT_EQUALS("", errout.str());
|
||||||
|
|
||||||
//Various bitmask comparison checks
|
|
||||||
//#7428 false negative: condition '(a&7)>7U' is always false
|
|
||||||
//#7522 false positive: condition '(X|7)>=6' is correct
|
|
||||||
|
|
||||||
check("void f() {\n"
|
|
||||||
"assert( (a & 0x07) == 8U );\n" // statement always false
|
|
||||||
"}");
|
|
||||||
ASSERT_EQUALS("[test.cpp:2]: (style) Expression '(X & 0x7) == 0x8' is always false.\n",
|
|
||||||
errout.str());
|
|
||||||
|
|
||||||
check("void f() {\n"
|
|
||||||
"assert( (a & 0x07) == 7U );\n" // statement correct
|
|
||||||
"assert( (a & 0x07) == 6U );\n" // statement correct
|
|
||||||
"}");
|
|
||||||
ASSERT_EQUALS("", errout.str());
|
|
||||||
|
|
||||||
check("void f() {\n"
|
|
||||||
"assert( (a | 0x07) == 8U );\n" // statement always false
|
|
||||||
"}");
|
|
||||||
ASSERT_EQUALS("[test.cpp:2]: (style) Expression '(X | 0x7) == 0x8' is always false.\n",
|
|
||||||
errout.str());
|
|
||||||
|
|
||||||
check("void f() {\n"
|
|
||||||
"assert( (a | 0x07) == 7U );\n" // statement correct
|
|
||||||
"assert( (a | 0x07) == 23U );\n" // statement correct
|
|
||||||
"}");
|
|
||||||
ASSERT_EQUALS("", errout.str());
|
|
||||||
|
|
||||||
check("void f() {\n"
|
|
||||||
"assert( (a & 0x07) != 8U );\n" // statement always true
|
|
||||||
"}");
|
|
||||||
ASSERT_EQUALS("[test.cpp:2]: (style) Expression '(X & 0x7) != 0x8' is always true.\n",
|
|
||||||
errout.str());
|
|
||||||
|
|
||||||
check("void f() {\n"
|
|
||||||
"assert( (a & 0x07) != 7U );\n" // statement correct
|
|
||||||
"assert( (a & 0x07) != 0U );\n" // statement correct
|
|
||||||
"}");
|
|
||||||
ASSERT_EQUALS("", errout.str());
|
|
||||||
|
|
||||||
check("void f() {\n"
|
|
||||||
"assert( (a | 0x07) != 8U );\n" // statement always true
|
|
||||||
"}");
|
|
||||||
ASSERT_EQUALS("[test.cpp:2]: (style) Expression '(X | 0x7) != 0x8' is always true.\n",
|
|
||||||
errout.str());
|
|
||||||
|
|
||||||
check("void f() {\n"
|
|
||||||
"assert( (a | 0x07) != 7U );\n" // statement correct
|
|
||||||
"}");
|
|
||||||
ASSERT_EQUALS("", errout.str());
|
|
||||||
|
|
||||||
//TRAC #7428 false negative: condition '(X&7)>7' is always false
|
|
||||||
check("void f() {\n"
|
|
||||||
"assert( (a & 0x07) > 7U );\n" // statement always false
|
|
||||||
"}");
|
|
||||||
ASSERT_EQUALS("[test.cpp:2]: (style) Expression '(X & 0x7) > 0x7' is always false.\n",
|
|
||||||
errout.str());
|
|
||||||
|
|
||||||
check("void f() {\n"
|
|
||||||
"assert( (a & 0x07) > 6U );\n" // statement correct
|
|
||||||
"}");
|
|
||||||
ASSERT_EQUALS("", errout.str());
|
|
||||||
|
|
||||||
//TRAC #7522 false positive: condition '(X|7)>=6' is correct (X can be negative)
|
|
||||||
check("void f() {\n"
|
|
||||||
"assert( (a | 0x07) >= 6U );\n" // statement correct (X can be negative)
|
|
||||||
"}");
|
|
||||||
ASSERT_EQUALS("",errout.str());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue