Fixed #4470 (New check: redundant bitand 'x&=1; x&=2;' can be simplified to 'x=0;')

This commit is contained in:
Daniel Marjamäki 2013-01-21 19:59:34 +01:00
parent 55b8ac00b0
commit bfafd51ca1
3 changed files with 47 additions and 2 deletions

View File

@ -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());
}

View File

@ -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";
}
};
/// @}

View File

@ -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"