fix #3062 (false negative: Boolean variable is used in bitwise operation)
This commit is contained in:
parent
e19cbf0cdd
commit
f29b7f9f08
|
@ -220,6 +220,38 @@ void CheckOther::clarifyConditionError(const Token *tok, bool assign, bool boolo
|
||||||
errmsg);
|
errmsg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
// if (bool & bool) -> if (bool && bool)
|
||||||
|
// if (bool | bool) -> if (bool || bool)
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
void CheckOther::checkBitwiseOnBoolean()
|
||||||
|
{
|
||||||
|
if (!_settings->isEnabled("style"))
|
||||||
|
return;
|
||||||
|
|
||||||
|
for (const Token *tok = _tokenizer->tokens(); tok; tok = tok->next())
|
||||||
|
{
|
||||||
|
if (Token::Match(tok, "(|.|return %var% [&|]"))
|
||||||
|
{
|
||||||
|
if (tok->next()->varId())
|
||||||
|
{
|
||||||
|
const Variable *var = _tokenizer->getSymbolDatabase()->getVariableFromVarId(tok->next()->varId());
|
||||||
|
if (var && (var->typeStartToken() == var->typeEndToken()) &&
|
||||||
|
Token::Match(var->typeStartToken(), "bool|_Bool"))
|
||||||
|
{
|
||||||
|
bitwiseOnBooleanError(tok->next(), tok->next()->str(), tok->strAt(2) == "&" ? "&&" : "||");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CheckOther::bitwiseOnBooleanError(const Token *tok, const std::string &varname, const std::string &op)
|
||||||
|
{
|
||||||
|
reportError(tok, Severity::style, "bitwiseOnBoolean",
|
||||||
|
"Boolean variable '" + varname + "' is used in bitwise operation. Did you mean " + op + " ?");
|
||||||
|
}
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
void CheckOther::warningOldStylePointerCast()
|
void CheckOther::warningOldStylePointerCast()
|
||||||
|
|
|
@ -102,6 +102,7 @@ public:
|
||||||
|
|
||||||
checkOther.checkAssignBoolToPointer();
|
checkOther.checkAssignBoolToPointer();
|
||||||
checkOther.checkSignOfUnsignedVariable();
|
checkOther.checkSignOfUnsignedVariable();
|
||||||
|
checkOther.checkBitwiseOnBoolean();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @brief Clarify calculation for ".. a * b ? .." */
|
/** @brief Clarify calculation for ".. a * b ? .." */
|
||||||
|
@ -225,6 +226,9 @@ public:
|
||||||
/** @brief %Check for testing sign of unsigned variable */
|
/** @brief %Check for testing sign of unsigned variable */
|
||||||
void checkSignOfUnsignedVariable();
|
void checkSignOfUnsignedVariable();
|
||||||
|
|
||||||
|
/** @brief %Check for using bool in bitwise expression */
|
||||||
|
void checkBitwiseOnBoolean();
|
||||||
|
|
||||||
// Error messages..
|
// Error messages..
|
||||||
void cstyleCastError(const Token *tok);
|
void cstyleCastError(const Token *tok);
|
||||||
void dangerousUsageStrtolError(const Token *tok);
|
void dangerousUsageStrtolError(const Token *tok);
|
||||||
|
@ -261,6 +265,7 @@ public:
|
||||||
void assignBoolToPointerError(const Token *tok);
|
void assignBoolToPointerError(const Token *tok);
|
||||||
void unsignedLessThanZeroError(const Token *tok, const std::string &varname);
|
void unsignedLessThanZeroError(const Token *tok, const std::string &varname);
|
||||||
void unsignedPositiveError(const Token *tok, const std::string &varname);
|
void unsignedPositiveError(const Token *tok, const std::string &varname);
|
||||||
|
void bitwiseOnBooleanError(const Token *tok, const std::string &varname, const std::string &op);
|
||||||
|
|
||||||
void getErrorMessages(ErrorLogger *errorLogger, const Settings *settings)
|
void getErrorMessages(ErrorLogger *errorLogger, const Settings *settings)
|
||||||
{
|
{
|
||||||
|
@ -309,6 +314,7 @@ public:
|
||||||
c.duplicateBreakError(0);
|
c.duplicateBreakError(0);
|
||||||
c.unsignedLessThanZeroError(0, "varname");
|
c.unsignedLessThanZeroError(0, "varname");
|
||||||
c.unsignedPositiveError(0, "varname");
|
c.unsignedPositiveError(0, "varname");
|
||||||
|
c.bitwiseOnBooleanError(0, "varname", "&&");
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string myName() const
|
std::string myName() const
|
||||||
|
@ -357,6 +363,7 @@ public:
|
||||||
"* duplicate break statement\n"
|
"* duplicate break statement\n"
|
||||||
"* testing if unsigned variable is negative\n"
|
"* testing if unsigned variable is negative\n"
|
||||||
"* testing is unsigned variable is positive\n"
|
"* testing is unsigned variable is positive\n"
|
||||||
|
"* using bool in bitwise expression\n"
|
||||||
|
|
||||||
// optimisations
|
// optimisations
|
||||||
"* optimisation: detect post increment/decrement\n";
|
"* optimisation: detect post increment/decrement\n";
|
||||||
|
|
|
@ -119,6 +119,7 @@ private:
|
||||||
TEST_CASE(clarifyCondition1); // if (a = b() < 0)
|
TEST_CASE(clarifyCondition1); // if (a = b() < 0)
|
||||||
TEST_CASE(clarifyCondition2); // if (a & b == c)
|
TEST_CASE(clarifyCondition2); // if (a & b == c)
|
||||||
TEST_CASE(clarifyCondition3); // if (! a & b)
|
TEST_CASE(clarifyCondition3); // if (! a & b)
|
||||||
|
TEST_CASE(bitwiseOnBoolean); // if (bool & bool)
|
||||||
|
|
||||||
TEST_CASE(incorrectStringCompare);
|
TEST_CASE(incorrectStringCompare);
|
||||||
|
|
||||||
|
@ -160,6 +161,7 @@ private:
|
||||||
checkOther.checkDuplicateIf();
|
checkOther.checkDuplicateIf();
|
||||||
checkOther.checkDuplicateBranch();
|
checkOther.checkDuplicateBranch();
|
||||||
checkOther.checkDuplicateExpression();
|
checkOther.checkDuplicateExpression();
|
||||||
|
checkOther.checkBitwiseOnBoolean();
|
||||||
|
|
||||||
// Simplify token list..
|
// Simplify token list..
|
||||||
tokenizer.simplifyTokenList();
|
tokenizer.simplifyTokenList();
|
||||||
|
@ -2815,6 +2817,63 @@ private:
|
||||||
ASSERT_EQUALS("", errout.str());
|
ASSERT_EQUALS("", errout.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void bitwiseOnBoolean() // 3062
|
||||||
|
{
|
||||||
|
check("void f(_Bool a, _Bool b) {\n"
|
||||||
|
" if(a & b) {}\n"
|
||||||
|
"}");
|
||||||
|
ASSERT_EQUALS("[test.cpp:2]: (style) Boolean variable 'a' is used in bitwise operation. Did you mean && ?\n", errout.str());
|
||||||
|
|
||||||
|
check("void f(_Bool a, _Bool b) {\n"
|
||||||
|
" if(a | b) {}\n"
|
||||||
|
"}");
|
||||||
|
ASSERT_EQUALS("[test.cpp:2]: (style) Boolean variable 'a' is used in bitwise operation. Did you mean || ?\n", errout.str());
|
||||||
|
|
||||||
|
check("void f(bool a, bool b) {\n"
|
||||||
|
" if(a & b) {}\n"
|
||||||
|
"}");
|
||||||
|
ASSERT_EQUALS("[test.cpp:2]: (style) Boolean variable 'a' is used in bitwise operation. Did you mean && ?\n", errout.str());
|
||||||
|
|
||||||
|
check("void f(bool a, bool b) {\n"
|
||||||
|
" if(a & !b) {}\n"
|
||||||
|
"}");
|
||||||
|
ASSERT_EQUALS("[test.cpp:2]: (style) Boolean variable 'a' is used in bitwise operation. Did you mean && ?\n", errout.str());
|
||||||
|
|
||||||
|
check("void f(bool a, bool b) {\n"
|
||||||
|
" if(a | b) {}\n"
|
||||||
|
"}");
|
||||||
|
ASSERT_EQUALS("[test.cpp:2]: (style) Boolean variable 'a' is used in bitwise operation. Did you mean || ?\n", errout.str());
|
||||||
|
|
||||||
|
check("void f(bool a, bool b) {\n"
|
||||||
|
" if(a | !b) {}\n"
|
||||||
|
"}");
|
||||||
|
ASSERT_EQUALS("[test.cpp:2]: (style) Boolean variable 'a' is used in bitwise operation. Did you mean || ?\n", errout.str());
|
||||||
|
|
||||||
|
check("bool a, b;\n"
|
||||||
|
"void f() {\n"
|
||||||
|
" if(a & b) {}\n"
|
||||||
|
"}");
|
||||||
|
ASSERT_EQUALS("[test.cpp:3]: (style) Boolean variable 'a' is used in bitwise operation. Did you mean && ?\n", errout.str());
|
||||||
|
|
||||||
|
check("bool a, b;\n"
|
||||||
|
"void f() {\n"
|
||||||
|
" if(a & !b) {}\n"
|
||||||
|
"}");
|
||||||
|
ASSERT_EQUALS("[test.cpp:3]: (style) Boolean variable 'a' is used in bitwise operation. Did you mean && ?\n", errout.str());
|
||||||
|
|
||||||
|
check("bool a, b;\n"
|
||||||
|
"void f() {\n"
|
||||||
|
" if(a | b) {}\n"
|
||||||
|
"}");
|
||||||
|
ASSERT_EQUALS("[test.cpp:3]: (style) Boolean variable 'a' is used in bitwise operation. Did you mean || ?\n", errout.str());
|
||||||
|
|
||||||
|
check("bool a, b;\n"
|
||||||
|
"void f() {\n"
|
||||||
|
" if(a | !b) {}\n"
|
||||||
|
"}");
|
||||||
|
ASSERT_EQUALS("[test.cpp:3]: (style) Boolean variable 'a' is used in bitwise operation. Did you mean || ?\n", errout.str());
|
||||||
|
}
|
||||||
|
|
||||||
void incorrectStringCompare()
|
void incorrectStringCompare()
|
||||||
{
|
{
|
||||||
check("int f() {\n"
|
check("int f() {\n"
|
||||||
|
|
Loading…
Reference in New Issue