AssignIf: Match lhs and rhs for comparisons. Ticket: #2909
This commit is contained in:
parent
e47aac2501
commit
00e28f5c4e
|
@ -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"));
|
||||||
|
}
|
||||||
|
|
|
@ -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";
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
/// @}
|
/// @}
|
||||||
|
|
|
@ -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)
|
||||||
|
|
Loading…
Reference in New Issue