Fixed #432 (New check: wrong usage of ! operator in conditions)

This commit is contained in:
Zachary Blair 2011-02-27 12:30:22 -08:00
parent 3db0e7ef8f
commit e1b2569b81
3 changed files with 90 additions and 0 deletions

View File

@ -608,6 +608,35 @@ void CheckOther::invalidScanf()
} }
} }
//---------------------------------------------------------------------------
// if (!x==3) <- Probably meant to be "x!=3"
//---------------------------------------------------------------------------
void CheckOther::checkComparisonOfBoolWithInt()
{
if (!_settings->_checkCodingStyle)
return;
for (const Token *tok = _tokenizer->tokens(); tok; tok = tok->next())
{
if (Token::Match(tok, "( ! %var% ==|!= %num% )"))
{
const Token *numTok = tok->tokAt(4);
if (numTok && numTok->str() != "0")
{
comparisonOfBoolWithIntError(numTok, tok->strAt(2));
}
}
else if (Token::Match(tok, "( %num% ==|!= ! %var% )"))
{
const Token *numTok = tok->tokAt(1);
if (numTok && numTok->str() != "0")
{
comparisonOfBoolWithIntError(numTok, tok->strAt(4));
}
}
}
}
void CheckOther::sizeofForArrayParameterError(const Token *tok) void CheckOther::sizeofForArrayParameterError(const Token *tok)
{ {
reportError(tok, Severity::error, reportError(tok, Severity::error,
@ -3016,3 +3045,10 @@ void CheckOther::incorrectStringCompareError(const Token *tok, const std::string
{ {
reportError(tok, Severity::warning, "incorrectStringCompare", "String literal " + string + " doesn't match length argument for " + func + "(" + len + ")."); reportError(tok, Severity::warning, "incorrectStringCompare", "String literal " + string + " doesn't match length argument for " + func + "(" + len + ").");
} }
void CheckOther::comparisonOfBoolWithIntError(const Token *tok, const std::string &varname)
{
reportError(tok, Severity::warning, "comparisonOfBoolWithInt",
"Comparison of a boolean with a non-zero integer\n"
"The expression \"!" + varname + "\" is of type 'bool' but is compared against a non-zero 'int'.");
}

View File

@ -89,6 +89,7 @@ public:
checkOther.checkMemsetZeroBytes(); checkOther.checkMemsetZeroBytes();
checkOther.checkIncorrectStringCompare(); checkOther.checkIncorrectStringCompare();
checkOther.checkIncrementBoolean(); checkOther.checkIncrementBoolean();
checkOther.checkComparisonOfBoolWithInt();
} }
/** @brief Clarify calculation for ".. a * b ? .." */ /** @brief Clarify calculation for ".. a * b ? .." */
@ -188,6 +189,9 @@ public:
/** @brief %Check for using postfix increment on bool */ /** @brief %Check for using postfix increment on bool */
void checkIncrementBoolean(); void checkIncrementBoolean();
/** @brief %Check for suspicious comparison of a bool and a non-zero (and non-one) value (e.g. "if (!x==4)") */
void checkComparisonOfBoolWithInt();
// Error messages.. // Error messages..
void cstyleCastError(const Token *tok); void cstyleCastError(const Token *tok);
void dangerousUsageStrtolError(const Token *tok); void dangerousUsageStrtolError(const Token *tok);
@ -214,6 +218,7 @@ public:
void sizeofForArrayParameterError(const Token *tok); void sizeofForArrayParameterError(const Token *tok);
void incorrectStringCompareError(const Token *tok, const std::string& func, const std::string &string, const std::string &len); void incorrectStringCompareError(const Token *tok, const std::string& func, const std::string &string, const std::string &len);
void incrementBooleanError(const Token *tok); void incrementBooleanError(const Token *tok);
void comparisonOfBoolWithIntError(const Token *tok, const std::string &varname);
void getErrorMessages(ErrorLogger *errorLogger, const Settings *settings) void getErrorMessages(ErrorLogger *errorLogger, const Settings *settings)
{ {
@ -255,6 +260,7 @@ public:
c.clarifyCalculationError(0); c.clarifyCalculationError(0);
c.incorrectStringCompareError(0, "substr", "\"Hello World\"", "12"); c.incorrectStringCompareError(0, "substr", "\"Hello World\"", "12");
c.incrementBooleanError(0); c.incrementBooleanError(0);
c.comparisonOfBoolWithIntError(0, "varname");
} }
std::string myName() const std::string myName() const
@ -296,6 +302,7 @@ public:
"* exception caught by value instead of by reference\n" "* exception caught by value instead of by reference\n"
"* Clarify calculation with parantheses\n" "* Clarify calculation with parantheses\n"
"* using increment on boolean\n" "* using increment on boolean\n"
"* comparison of a boolean with a non-zero integer\n"
// optimisations // optimisations
"* optimisation: detect post increment/decrement\n"; "* optimisation: detect post increment/decrement\n";

View File

@ -106,6 +106,7 @@ private:
TEST_CASE(incorrectStringCompare); TEST_CASE(incorrectStringCompare);
TEST_CASE(incrementBoolean); TEST_CASE(incrementBoolean);
TEST_CASE(comparisonOfBoolWithInt);
} }
void check(const char code[], const char *filename = NULL) void check(const char code[], const char *filename = NULL)
@ -144,6 +145,7 @@ private:
checkOther.clarifyCalculation(); checkOther.clarifyCalculation();
checkOther.checkIncorrectStringCompare(); checkOther.checkIncorrectStringCompare();
checkOther.checkIncrementBoolean(); checkOther.checkIncrementBoolean();
checkOther.checkComparisonOfBoolWithInt();
} }
@ -1923,6 +1925,51 @@ private:
"}"); "}");
ASSERT_EQUALS("", errout.str()); ASSERT_EQUALS("", errout.str());
} }
void comparisonOfBoolWithInt()
{
check("void f(int x) {\n"
" if (!x == 10) {\n"
" printf(\"x not equal to 10\");\n"
" }\n"
"}");
ASSERT_EQUALS("[test.cpp:2]: (warning) Comparison of a boolean with a non-zero integer\n", errout.str());
check("void f(int x) {\n"
" if (!x != 10) {\n"
" printf(\"x not equal to 10\");\n"
" }\n"
"}");
ASSERT_EQUALS("[test.cpp:2]: (warning) Comparison of a boolean with a non-zero integer\n", errout.str());
check("void f(int x) {\n"
" if (x != 10) {\n"
" printf(\"x not equal to 10\");\n"
" }\n"
"}");
ASSERT_EQUALS("", errout.str());
check("void f(int x) {\n"
" if (10 == !x) {\n"
" printf(\"x not equal to 10\");\n"
" }\n"
"}");
ASSERT_EQUALS("[test.cpp:2]: (warning) Comparison of a boolean with a non-zero integer\n", errout.str());
check("void f(int x) {\n"
" if (10 != !x) {\n"
" printf(\"x not equal to 10\");\n"
" }\n"
"}");
ASSERT_EQUALS("[test.cpp:2]: (warning) Comparison of a boolean with a non-zero integer\n", errout.str());
check("void f(int x) {\n"
" if (10 != x) {\n"
" printf(\"x not equal to 10\");\n"
" }\n"
"}");
ASSERT_EQUALS("", errout.str());
}
}; };
REGISTER_TEST(TestOther) REGISTER_TEST(TestOther)