Fixed #4470 (New check: redundant bitand 'x&=1; x&=2;' can be simplified to 'x=0;')
This commit is contained in:
parent
55b8ac00b0
commit
bfafd51ca1
|
@ -86,8 +86,19 @@ bool CheckAssignIf::assignIfParseScope(const Token * const assignTok,
|
|||
const MathLib::bigint num)
|
||||
{
|
||||
for (const Token *tok2 = startTok; tok2; tok2 = tok2->next()) {
|
||||
if (Token::Match(tok2, "%varid% =", varid))
|
||||
if (Token::Match(tok2->tokAt(2), "%varid% %op% %num% ;", varid) && tok2->strAt(3) == std::string(1U, bitop)) {
|
||||
const MathLib::bigint num2 = MathLib::toLongNumber(tok2->strAt(4));
|
||||
if ((bitop == '&') && (0 == (num & num2)))
|
||||
mismatchingBitAndError(assignTok, num, tok2, num2);
|
||||
}
|
||||
if (Token::Match(tok2, "%varid% =", varid)) {
|
||||
if (Token::Match(tok2->tokAt(2), "%varid% %op% %num% ;", varid) && tok2->strAt(3) == std::string(1U, bitop)) {
|
||||
const MathLib::bigint num2 = MathLib::toLongNumber(tok2->strAt(4));
|
||||
if ((bitop == '&') && (0 == (num & num2)))
|
||||
mismatchingBitAndError(assignTok, num, tok2, num2);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
if (Token::Match(tok2, "[(,] &| %varid% [,)]", varid))
|
||||
return true;
|
||||
if (tok2->str() == "}")
|
||||
|
@ -140,6 +151,21 @@ void CheckAssignIf::assignIfError(const Token *tok1, const Token *tok2, const st
|
|||
}
|
||||
|
||||
|
||||
void CheckAssignIf::mismatchingBitAndError(const Token *tok1, const MathLib::bigint num1, const Token *tok2, const MathLib::bigint num2)
|
||||
{
|
||||
std::list<const Token *> locations;
|
||||
locations.push_back(tok1);
|
||||
locations.push_back(tok2);
|
||||
|
||||
std::ostringstream msg;
|
||||
msg << "Mismatching bitmasks. Result is always 0 ("
|
||||
<< "X = Y & 0x" << std::hex << num1 << "; Z = X & 0x" << std::hex << num2 << "; => Z=0).";
|
||||
|
||||
reportError(locations,
|
||||
Severity::style,
|
||||
"mismatchingBitAnd",
|
||||
msg.str());
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -73,6 +73,8 @@ private:
|
|||
|
||||
void assignIfError(const Token *tok1, const Token *tok2, const std::string &condition, bool result);
|
||||
|
||||
void mismatchingBitAndError(const Token *tok1, const MathLib::bigint num1, const Token *tok2, const MathLib::bigint num2);
|
||||
|
||||
void comparisonError(const Token *tok,
|
||||
const std::string &bitop,
|
||||
MathLib::bigint value1,
|
||||
|
@ -87,6 +89,7 @@ private:
|
|||
c.assignIfError(0, 0, "", false);
|
||||
c.comparisonError(0, "&", 6, "==", 1, false);
|
||||
c.multiConditionError(0,1);
|
||||
c.mismatchingBitAndError(0,0xf0, 0, 1);
|
||||
}
|
||||
|
||||
static std::string myName() {
|
||||
|
@ -97,7 +100,8 @@ private:
|
|||
return "Match assignments and conditions:\n"
|
||||
"* Mismatching assignment and comparison => comparison is always true/false\n"
|
||||
"* Mismatching lhs and rhs in comparison => comparison is always true/false\n"
|
||||
"* Detect matching 'if' and 'else if' conditions\n";
|
||||
"* Detect matching 'if' and 'else if' conditions\n"
|
||||
"* Mismatching bitand (a &= 0xf0; a &= 1; => a = 0)\n";
|
||||
}
|
||||
};
|
||||
/// @}
|
||||
|
|
|
@ -34,6 +34,7 @@ private:
|
|||
|
||||
void run() {
|
||||
TEST_CASE(assignAndCompare); // assignment and comparison don't match
|
||||
TEST_CASE(mismatchingBitAnd); // overlapping bitmasks
|
||||
TEST_CASE(compare); // mismatching LHS/RHS in comparison
|
||||
TEST_CASE(multicompare); // mismatching comparisons
|
||||
}
|
||||
|
@ -164,6 +165,20 @@ private:
|
|||
ASSERT_EQUALS("", errout.str());
|
||||
}
|
||||
|
||||
void mismatchingBitAnd() {
|
||||
check("void f(int a) {\n"
|
||||
" int b = a & 0xf0;\n"
|
||||
" b &= 1;\n"
|
||||
"}");
|
||||
ASSERT_EQUALS("[test.cpp:2] -> [test.cpp:3]: (style) Mismatching bitmasks. Result is always 0 (X = Y & 0xf0; Z = X & 0x1; => Z=0).\n", errout.str());
|
||||
|
||||
check("void f(int a) {\n"
|
||||
" int b = a & 0xf0;\n"
|
||||
" int c = b & 1;\n"
|
||||
"}");
|
||||
ASSERT_EQUALS("[test.cpp:2] -> [test.cpp:3]: (style) Mismatching bitmasks. Result is always 0 (X = Y & 0xf0; Z = X & 0x1; => Z=0).\n", errout.str());
|
||||
}
|
||||
|
||||
void compare() {
|
||||
check("void foo(int x)\n"
|
||||
"{\n"
|
||||
|
|
Loading…
Reference in New Issue