AssignIf: Match lhs and rhs for comparisons. Ticket: #2909

This commit is contained in:
Daniel Marjamäki 2011-07-31 11:23:38 +02:00
parent e47aac2501
commit 00e28f5c4e
3 changed files with 81 additions and 16 deletions

View File

@ -32,7 +32,7 @@ CheckAssignIf instance;
} }
void CheckAssignIf::check() void CheckAssignIf::assignIf()
{ {
if (!_settings->_checkCodingStyle) if (!_settings->_checkCodingStyle)
return; return;
@ -61,9 +61,9 @@ void CheckAssignIf::check()
const std::string op(tok2->strAt(3)); const std::string op(tok2->strAt(3));
const MathLib::bigint num2 = MathLib::toLongNumber(tok2->strAt(4)); const MathLib::bigint num2 = MathLib::toLongNumber(tok2->strAt(4));
if (op == "==" && (num & num2) != num2) if (op == "==" && (num & num2) != num2)
mismatchError(tok2, false); assignIfError(tok2, false);
else if (op == "!=" && (num & num2) != num2) else if (op == "!=" && (num & num2) != num2)
mismatchError(tok2, true); assignIfError(tok2, true);
break; break;
} }
} }
@ -71,9 +71,49 @@ void CheckAssignIf::check()
} }
} }
void CheckAssignIf::mismatchError(const Token *tok, bool result) void CheckAssignIf::assignIfError(const Token *tok, bool result)
{ {
reportError(tok, Severity::style, reportError(tok, Severity::style,
"assignIfMismatchError", "assignIfError",
"Mismatching assignment and comparison, comparison is always " + std::string(result ? "true" : "false")); "Mismatching assignment and comparison, comparison is always " + std::string(result ? "true" : "false"));
} }
void CheckAssignIf::comparison()
{
if (!_settings->_checkCodingStyle)
return;
for (const Token *tok = _tokenizer->tokens(); tok; tok = tok->next())
{
if (tok->str() != "&")
continue;
if (Token::Match(tok, "& %num% ==|!= %num% &&|%oror%|)"))
{
const MathLib::bigint num1 = MathLib::toLongNumber(tok->strAt(1));
if (num1 < 0)
continue;
const MathLib::bigint num2 = MathLib::toLongNumber(tok->strAt(3));
if (num2 < 0)
continue;
if ((num1 & num2) != num2)
{
const std::string op(tok->strAt(2));
comparisonError(tok, op=="==" ? false : true);
}
}
}
}
void CheckAssignIf::comparisonError(const Token *tok, bool result)
{
reportError(tok, Severity::style,
"comparisonError",
"Comparison is always " + std::string(result ? "true" : "false"));
}

View File

@ -50,31 +50,39 @@ public:
void runSimplifiedChecks(const Tokenizer *tokenizer, const Settings *settings, ErrorLogger *errorLogger) void runSimplifiedChecks(const Tokenizer *tokenizer, const Settings *settings, ErrorLogger *errorLogger)
{ {
CheckAssignIf checkAssignIf(tokenizer, settings, errorLogger); CheckAssignIf checkAssignIf(tokenizer, settings, errorLogger);
checkAssignIf.check(); checkAssignIf.assignIf();
checkAssignIf.comparison();
} }
/** Check for obsolete functions */ /** mismatching assignment / comparison */
void check(); void assignIf();
/** mismatching lhs and rhs in comparison */
void comparison();
private: private:
void mismatchError(const Token *tok, bool result); void assignIfError(const Token *tok, bool result);
void comparisonError(const Token *tok, bool result);
void getErrorMessages(ErrorLogger *errorLogger, const Settings *settings) void getErrorMessages(ErrorLogger *errorLogger, const Settings *settings)
{ {
CheckAssignIf c(0, settings, errorLogger); CheckAssignIf c(0, settings, errorLogger);
c.mismatchError(0, false); c.assignIfError(0, false);
c.comparisonError(0, false);
} }
std::string myName() const std::string myName() const
{ {
return "match assignment / conditions"; return "match assignments and conditions";
} }
std::string classInfo() const std::string classInfo() const
{ {
return "Match assignments and conditions:\n" return "Match assignments and conditions:\n"
" Mismatching assignment and comparison => comparison is always true/false"; " * Mismatching assignment and comparison => comparison is always true/false\n"
" * Mismatching lhs and rhs in comparison => comparison is always true/false";
} }
}; };
/// @} /// @}

View File

@ -35,7 +35,8 @@ private:
void run() void run()
{ {
TEST_CASE(testand); TEST_CASE(assignAndCompare);
TEST_CASE(compare);
} }
void check(const char code[]) void check(const char code[])
@ -54,11 +55,12 @@ private:
tokenizer.simplifyTokenList(); tokenizer.simplifyTokenList();
// Check char variable usage.. // Check char variable usage..
CheckAssignIf CheckAssignIf(&tokenizer, &settings, this); CheckAssignIf checkAssignIf(&tokenizer, &settings, this);
CheckAssignIf.check(); checkAssignIf.assignIf();
checkAssignIf.comparison();
} }
void testand() void assignAndCompare()
{ {
check("void foo(int x)\n" check("void foo(int x)\n"
"{\n" "{\n"
@ -74,6 +76,21 @@ private:
"}\n"); "}\n");
ASSERT_EQUALS("[test.cpp:4]: (style) Mismatching assignment and comparison, comparison is always true\n", errout.str()); ASSERT_EQUALS("[test.cpp:4]: (style) Mismatching assignment and comparison, comparison is always true\n", errout.str());
} }
void compare()
{
check("void foo(int x)\n"
"{\n"
" if (x & 4 == 3);\n"
"}\n");
ASSERT_EQUALS("[test.cpp:3]: (style) Comparison is always false\n", errout.str());
check("void foo(int x)\n"
"{\n"
" if (x & 4 != 3);\n"
"}\n");
ASSERT_EQUALS("[test.cpp:3]: (style) Comparison is always true\n", errout.str());
}
}; };
REGISTER_TEST(TestAssignIf) REGISTER_TEST(TestAssignIf)