* Fix #4233 FN: Bitwise operation with bool and int * Format
This commit is contained in:
parent
8fc75402a1
commit
c5dcd49dae
|
@ -99,30 +99,43 @@ void CheckBool::checkBitwiseOnBoolean()
|
||||||
const SymbolDatabase *symbolDatabase = mTokenizer->getSymbolDatabase();
|
const SymbolDatabase *symbolDatabase = mTokenizer->getSymbolDatabase();
|
||||||
for (const Scope * scope : symbolDatabase->functionScopes) {
|
for (const Scope * scope : symbolDatabase->functionScopes) {
|
||||||
for (const Token* tok = scope->bodyStart->next(); tok != scope->bodyEnd; tok = tok->next()) {
|
for (const Token* tok = scope->bodyStart->next(); tok != scope->bodyEnd; tok = tok->next()) {
|
||||||
if (tok->isBinaryOp() && (tok->str() == "&" || tok->str() == "|")) {
|
if (tok->isBinaryOp()) {
|
||||||
if (!(astIsBool(tok->astOperand1()) || astIsBool(tok->astOperand2())))
|
bool isCompound{};
|
||||||
|
if (tok->str() == "&" || tok->str() == "|")
|
||||||
|
isCompound = false;
|
||||||
|
else if (tok->str() == "&=" || tok->str() == "|=")
|
||||||
|
isCompound = true;
|
||||||
|
else
|
||||||
continue;
|
continue;
|
||||||
if (tok->str() == "|" && !isConvertedToBool(tok) && !(astIsBool(tok->astOperand1()) && astIsBool(tok->astOperand2())))
|
const bool isBoolOp1 = astIsBool(tok->astOperand1());
|
||||||
|
const bool isBoolOp2 = astIsBool(tok->astOperand2());
|
||||||
|
if (!(isBoolOp1 || isBoolOp2))
|
||||||
|
continue;
|
||||||
|
if (isCompound && !isBoolOp1)
|
||||||
|
continue;
|
||||||
|
if (tok->str() == "|" && !isConvertedToBool(tok) && !(isBoolOp1 && isBoolOp2))
|
||||||
continue;
|
continue;
|
||||||
// first operand will always be evaluated
|
// first operand will always be evaluated
|
||||||
if (!isConstExpression(tok->astOperand2(), mSettings->library, true, mTokenizer->isCPP()))
|
if (!isConstExpression(tok->astOperand2(), mSettings->library, true, mTokenizer->isCPP()))
|
||||||
continue;
|
continue;
|
||||||
if (tok->astOperand2()->variable() && tok->astOperand2()->variable()->nameToken() == tok->astOperand2())
|
if (tok->astOperand2()->variable() && tok->astOperand2()->variable()->nameToken() == tok->astOperand2())
|
||||||
continue;
|
continue;
|
||||||
const std::string expression = astIsBool(tok->astOperand1()) ? tok->astOperand1()->expressionString()
|
const std::string expression = (isBoolOp1 ? tok->astOperand1() : tok->astOperand2())->expressionString();
|
||||||
: tok->astOperand2()->expressionString();
|
bitwiseOnBooleanError(tok, expression, tok->str() == "&" ? "&&" : "||", isCompound);
|
||||||
bitwiseOnBooleanError(tok, expression, tok->str() == "&" ? "&&" : "||");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CheckBool::bitwiseOnBooleanError(const Token* tok, const std::string& expression, const std::string& op)
|
void CheckBool::bitwiseOnBooleanError(const Token* tok, const std::string& expression, const std::string& op, bool isCompound)
|
||||||
{
|
{
|
||||||
|
std::string msg = "Boolean expression '" + expression + "' is used in bitwise operation.";
|
||||||
|
if (!isCompound)
|
||||||
|
msg += " Did you mean '" + op + "'?";
|
||||||
reportError(tok,
|
reportError(tok,
|
||||||
Severity::style,
|
Severity::style,
|
||||||
"bitwiseOnBoolean",
|
"bitwiseOnBoolean",
|
||||||
"Boolean expression '" + expression + "' is used in bitwise operation. Did you mean '" + op + "'?",
|
msg,
|
||||||
CWE398,
|
CWE398,
|
||||||
Certainty::inconclusive);
|
Certainty::inconclusive);
|
||||||
}
|
}
|
||||||
|
|
|
@ -104,7 +104,7 @@ private:
|
||||||
void comparisonOfBoolWithInvalidComparator(const Token *tok, const std::string &expression);
|
void comparisonOfBoolWithInvalidComparator(const Token *tok, const std::string &expression);
|
||||||
void assignBoolToPointerError(const Token *tok);
|
void assignBoolToPointerError(const Token *tok);
|
||||||
void assignBoolToFloatError(const Token *tok);
|
void assignBoolToFloatError(const Token *tok);
|
||||||
void bitwiseOnBooleanError(const Token* tok, const std::string& expression, const std::string& op);
|
void bitwiseOnBooleanError(const Token* tok, const std::string& expression, const std::string& op, bool isCompound = false);
|
||||||
void comparisonOfBoolExpressionWithIntError(const Token *tok, bool not0or1);
|
void comparisonOfBoolExpressionWithIntError(const Token *tok, bool not0or1);
|
||||||
void pointerArithBoolError(const Token *tok);
|
void pointerArithBoolError(const Token *tok);
|
||||||
void returnValueBoolError(const Token *tok);
|
void returnValueBoolError(const Token *tok);
|
||||||
|
|
|
@ -932,6 +932,23 @@ private:
|
||||||
" return b | g() | c;\n"
|
" return b | g() | c;\n"
|
||||||
"}\n");
|
"}\n");
|
||||||
ASSERT_EQUALS("[test.cpp:3]: (style, inconclusive) Boolean expression 'c' is used in bitwise operation. Did you mean '||'?\n", errout.str());
|
ASSERT_EQUALS("[test.cpp:3]: (style, inconclusive) Boolean expression 'c' is used in bitwise operation. Did you mean '||'?\n", errout.str());
|
||||||
|
|
||||||
|
check("void f(int i) {\n" // #4233
|
||||||
|
" bool b = true, c = false;\n"
|
||||||
|
" b &= i;\n"
|
||||||
|
" c |= i;\n"
|
||||||
|
" if (b || c) {}\n"
|
||||||
|
"}\n");
|
||||||
|
ASSERT_EQUALS("[test.cpp:3]: (style, inconclusive) Boolean expression 'b' is used in bitwise operation.\n"
|
||||||
|
"[test.cpp:4]: (style, inconclusive) Boolean expression 'c' is used in bitwise operation.\n",
|
||||||
|
errout.str());
|
||||||
|
|
||||||
|
check("void f(int i, int j, bool b) {\n"
|
||||||
|
" i &= b;\n"
|
||||||
|
" j |= b;\n"
|
||||||
|
" if (b || c) {}\n"
|
||||||
|
"}\n");
|
||||||
|
ASSERT_EQUALS("", errout.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
void incrementBoolean() {
|
void incrementBoolean() {
|
||||||
|
|
Loading…
Reference in New Issue