Improved CheckOther::checkComparisonOfBoolWithInt and CheckOther::checkComparisonOfBoolExpressionWithInt:

- Added support for comparision of bool constant with number constant (-> fixed #1877) and integer variable with boolean expression
- Moved a check from checkComparisonOfBoolWithInt to checkComparisonOfBoolExpressionWithInt
- Generalized some patterns
- Made error message more accurate concnerning the "neither 0 nor 1" part.
- Reduced number of Token::Match calls
This commit is contained in:
PKEuS 2012-04-02 15:45:51 +02:00
parent fc8749e952
commit c1fc7a2218
3 changed files with 166 additions and 127 deletions

View File

@ -1671,63 +1671,55 @@ void CheckOther::checkComparisonOfBoolWithInt()
const SymbolDatabase* const symbolDatabase = _tokenizer->getSymbolDatabase(); const SymbolDatabase* const symbolDatabase = _tokenizer->getSymbolDatabase();
for (const Token *tok = _tokenizer->tokens(); tok; tok = tok->next()) { for (const Token *tok = _tokenizer->tokens(); tok; tok = tok->next()) {
if (Token::Match(tok, "%var% >|>=|==|!=|<=|< %num%")) { // Comparing variable with number if (Token::Match(tok->next(), ">|>=|==|!=|<=|<") && (!tok->previous() || !tok->previous()->isArithmeticalOp()) && (!tok->tokAt(3) || !tok->tokAt(3)->isArithmeticalOp())) {
const Token *varTok = tok; const Token* const right = tok->tokAt(2);
const Token *numTok = tok->tokAt(2); if ((tok->varId() && right->isNumber()) || (tok->isNumber() && right->varId())) { // Comparing variable with number
if (isBool(symbolDatabase->getVariableFromVarId(varTok->varId())) && // Variable has to be a boolean const Token* varTok = tok;
((tok->strAt(1) != "==" && tok->strAt(1) != "!=") || const Token* numTok = right;
(MathLib::toLongNumber(numTok->str()) != 0 && MathLib::toLongNumber(numTok->str()) != 1))) { // == 0 and != 0 are allowed, for C also == 1 and != 1 if (tok->isNumber() && right->varId()) // num with var
comparisonOfBoolWithIntError(varTok, numTok->str()); std::swap(varTok, numTok);
} if (isBool(symbolDatabase->getVariableFromVarId(varTok->varId())) && // Variable has to be a boolean
} else if (Token::Match(tok, "%num% >|>=|==|!=|<=|< %var%")) { // Comparing number with variable ((tok->strAt(1) != "==" && tok->strAt(1) != "!=") ||
const Token *varTok = tok->tokAt(2); (MathLib::toLongNumber(numTok->str()) != 0 && MathLib::toLongNumber(numTok->str()) != 1))) { // == 0 and != 0 are allowed, for C also == 1 and != 1
const Token *numTok = tok; comparisonOfBoolWithIntError(varTok, numTok->str(), tok->strAt(1) == "==" || tok->strAt(1) == "!=");
if (isBool(symbolDatabase->getVariableFromVarId(varTok->varId())) && // Variable has to be a boolean }
((tok->strAt(1) != "==" && tok->strAt(1) != "!=") || } else if (tok->isBoolean() && right->varId()) { // Comparing boolean constant with variable
(MathLib::toLongNumber(numTok->str()) != 0 && MathLib::toLongNumber(numTok->str()) != 1))) { // == 0 and != 0 are allowed, for C also == 1 and != 1 if (isNonBoolStdType(symbolDatabase->getVariableFromVarId(right->varId()))) { // Variable has to be of non-boolean standard type
comparisonOfBoolWithIntError(varTok, numTok->str()); comparisonOfBoolWithIntError(right, tok->str(), false);
} }
} else if (Token::Match(tok, "true|false >|>=|==|!=|<=|< %var%")) { // Comparing boolean constant with variable } else if (tok->varId() && right->isBoolean()) { // Comparing variable with boolean constant
const Token *varTok = tok->tokAt(2); if (isNonBoolStdType(symbolDatabase->getVariableFromVarId(tok->varId()))) { // Variable has to be of non-boolean standard type
const Token *constTok = tok; comparisonOfBoolWithIntError(tok, right->str(), false);
if (isNonBoolStdType(symbolDatabase->getVariableFromVarId(varTok->varId()))) { // Variable has to be of non-boolean standard type }
comparisonOfBoolWithIntError(varTok, constTok->str()); } else if (tok->isNumber() && right->isBoolean()) { // number constant with boolean constant
} comparisonOfBoolWithIntError(tok, right->str(), false);
} else if (Token::Match(tok, "%var% >|>=|==|!=|<=|< true|false")) { // Comparing variable with boolean constant } else if (tok->isBoolean() && right->isNumber()) { // number constant with boolean constant
const Token *varTok = tok; comparisonOfBoolWithIntError(tok, tok->str(), false);
const Token *constTok = tok->tokAt(2); } else if (tok->varId() && right->varId()) { // Comparing two variables, one of them boolean, one of them integer
if (isNonBoolStdType(symbolDatabase->getVariableFromVarId(varTok->varId()))) { // Variable has to be of non-boolean standard type const Variable* var1 = symbolDatabase->getVariableFromVarId(right->varId());
comparisonOfBoolWithIntError(varTok, constTok->str()); const Variable* var2 = symbolDatabase->getVariableFromVarId(tok->varId());
} if (isBool(var1) && isNonBoolStdType(var2)) // Comparing boolean with non-bool standard type
} else if (Token::Match(tok, "%var% >|>=|==|!=|<=|< %var%") && comparisonOfBoolWithIntError(tok, var1->name(), false);
!Token::Match(tok->tokAt(3), ".|::|(")) { // Comparing two variables, one of them boolean, one of them integer else if (isNonBoolStdType(var1) && isBool(var2)) // Comparing non-bool standard type with boolean
const Variable* var1 = symbolDatabase->getVariableFromVarId(tok->tokAt(2)->varId()); comparisonOfBoolWithIntError(tok, var2->name(), false);
const Variable* var2 = symbolDatabase->getVariableFromVarId(tok->varId());
if (isBool(var1) && isNonBoolStdType(var2)) // Comparing boolean with non-bool standard type
comparisonOfBoolWithIntError(tok, var1->name());
else if (isNonBoolStdType(var1) && isBool(var2)) // Comparing non-bool standard type with boolean
comparisonOfBoolWithIntError(tok, var2->name());
} else if (Token::Match(tok, "( ! %var% ==|!= %num% )")) {
const Token *numTok = tok->tokAt(4);
if (numTok && numTok->str() != "0" && numTok->str() != "1") {
comparisonOfBoolWithIntError(numTok, "!"+tok->strAt(2));
}
} else if (Token::Match(tok, "( %num% ==|!= ! %var% )")) {
const Token *numTok = tok->next();
if (numTok && numTok->str() != "0" && numTok->str() != "1") {
comparisonOfBoolWithIntError(numTok, "!"+tok->strAt(4));
} }
} }
} }
} }
void CheckOther::comparisonOfBoolWithIntError(const Token *tok, const std::string &expression) void CheckOther::comparisonOfBoolWithIntError(const Token *tok, const std::string &expression, bool n0o1)
{ {
reportError(tok, Severity::warning, "comparisonOfBoolWithInt", if (n0o1)
"Comparison of a boolean with integer that is neither 1 nor 0\n" reportError(tok, Severity::warning, "comparisonOfBoolWithInt",
"The expression \"" + expression + "\" is of type 'bool' " "Comparison of a boolean with an integer that is neither 1 nor 0\n"
"and it is compared against a integer value that is " "The expression \"" + expression + "\" is of type 'bool' "
"neither 1 nor 0."); "and it is compared against a integer value that is "
"neither 1 nor 0.");
else
reportError(tok, Severity::warning, "comparisonOfBoolWithInt",
"Comparison of a boolean with an integer\n"
"The expression \"" + expression + "\" is of type 'bool' "
"and it is compared against a integer value.");
} }
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
@ -3220,29 +3212,54 @@ void CheckOther::checkComparisonOfBoolExpressionWithInt()
if (!_settings->isEnabled("style")) if (!_settings->isEnabled("style"))
return; return;
const SymbolDatabase* symbolDatabase = _tokenizer->getSymbolDatabase();
for (const Token *tok = _tokenizer->tokens(); tok; tok = tok->next()) { for (const Token *tok = _tokenizer->tokens(); tok; tok = tok->next()) {
if (Token::Match(tok, "&&|%oror% %any% ) ==|!=|>|< %num%")) { const Token* numTok = 0;
const std::string& op = tok->strAt(3); const Token* opTok = 0;
const std::string& num = tok->strAt(4); char op = 0;
if ((op == "<" || num != "0") && (op == ">" || num != "1")) { if (Token::Match(tok, "&&|%oror% %any% ) >|>=|==|!=|<=|< %any%")) {
comparisonOfBoolExpressionWithIntError(tok->next()); numTok = tok->tokAt(4);
} opTok = tok->tokAt(3);
if (Token::Match(opTok, "<|>"))
op = opTok->str()[0];
} else if (Token::Match(tok, "%any% >|>=|==|!=|<=|< ( %any% &&|%oror%")) {
numTok = tok;
opTok = tok->next();
if (Token::Match(opTok, "<|>"))
op = opTok->str()[0]=='>'?'<':'>';
} }
else if (Token::Match(tok, "%num% ==|!=|>|< ( %any% &&|%oror%")) { else if (Token::Match(tok, "! %var% >|>=|==|!=|<=|< %any%")) {
const std::string& op = tok->strAt(1); numTok = tok->tokAt(3);
const std::string& num = tok->str(); opTok = tok->tokAt(2);
if ((op == ">" || num != "0") && (op == "<" || num != "1")) { if (Token::Match(opTok, "<|>"))
comparisonOfBoolExpressionWithIntError(tok->next()); op = opTok->str()[0];
} } else if (Token::Match(tok, "%any% >|>=|==|!=|<=|< ! %var%")) {
numTok = tok;
opTok = tok->next();
if (Token::Match(opTok, "<|>"))
op = opTok->str()[0]=='>'?'<':'>';
}
if (numTok && opTok) {
if (numTok->isNumber()) {
if (((numTok->str() != "0" && numTok->str() != "1") || !Token::Match(opTok, "!=|==")) && !((op == '<' && numTok->str() == "1") || (op == '>' && numTok->str() == "0")))
comparisonOfBoolExpressionWithIntError(tok, true);
} else if (isNonBoolStdType(symbolDatabase->getVariableFromVarId(numTok->varId())))
comparisonOfBoolExpressionWithIntError(tok, false);
} }
} }
} }
void CheckOther::comparisonOfBoolExpressionWithIntError(const Token *tok) void CheckOther::comparisonOfBoolExpressionWithIntError(const Token *tok, bool n0o1)
{ {
reportError(tok, Severity::warning, "compareBoolExpressionWithInt", if (n0o1)
"Comparison of a boolean expression with an integer other than 0 or 1."); reportError(tok, Severity::warning, "compareBoolExpressionWithInt",
"Comparison of a boolean expression with an integer other than 0 or 1.");
else
reportError(tok, Severity::warning, "compareBoolExpressionWithInt",
"Comparison of a boolean expression with an integer.");
} }

View File

@ -294,7 +294,7 @@ private:
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 incorrectStringBooleanError(const Token *tok, const std::string& string); void incorrectStringBooleanError(const Token *tok, const std::string& string);
void incrementBooleanError(const Token *tok); void incrementBooleanError(const Token *tok);
void comparisonOfBoolWithIntError(const Token *tok, const std::string &expression); void comparisonOfBoolWithIntError(const Token *tok, const std::string &expression, bool n0o1);
void duplicateIfError(const Token *tok1, const Token *tok2); void duplicateIfError(const Token *tok1, const Token *tok2);
void duplicateBranchError(const Token *tok1, const Token *tok2); void duplicateBranchError(const Token *tok1, const Token *tok2);
void duplicateExpressionError(const Token *tok1, const Token *tok2, const std::string &op); void duplicateExpressionError(const Token *tok1, const Token *tok2, const std::string &op);
@ -306,7 +306,7 @@ private:
void unsignedLessThanZeroError(const Token *tok, const std::string &varname, bool inconclusive); void unsignedLessThanZeroError(const Token *tok, const std::string &varname, bool inconclusive);
void unsignedPositiveError(const Token *tok, const std::string &varname, bool inconclusive); void unsignedPositiveError(const Token *tok, const std::string &varname, bool inconclusive);
void bitwiseOnBooleanError(const Token *tok, const std::string &varname, const std::string &op); void bitwiseOnBooleanError(const Token *tok, const std::string &varname, const std::string &op);
void comparisonOfBoolExpressionWithIntError(const Token *tok); void comparisonOfBoolExpressionWithIntError(const Token *tok, bool n0o1);
void SuspiciousSemicolonError(const Token *tok); void SuspiciousSemicolonError(const Token *tok);
void doubleFreeError(const Token *tok, const std::string &varname); void doubleFreeError(const Token *tok, const std::string &varname);
void doubleCloseDirError(const Token *tok, const std::string &varname); void doubleCloseDirError(const Token *tok, const std::string &varname);
@ -353,7 +353,7 @@ private:
c.incorrectStringCompareError(0, "substr", "\"Hello World\"", "12"); c.incorrectStringCompareError(0, "substr", "\"Hello World\"", "12");
c.incorrectStringBooleanError(0, "\"Hello World\""); c.incorrectStringBooleanError(0, "\"Hello World\"");
c.incrementBooleanError(0); c.incrementBooleanError(0);
c.comparisonOfBoolWithIntError(0, "varname"); c.comparisonOfBoolWithIntError(0, "varname", true);
c.duplicateIfError(0, 0); c.duplicateIfError(0, 0);
c.duplicateBranchError(0, 0); c.duplicateBranchError(0, 0);
c.duplicateExpressionError(0, 0, "&&"); c.duplicateExpressionError(0, 0, "&&");
@ -364,7 +364,7 @@ private:
c.unsignedLessThanZeroError(0, "varname", false); c.unsignedLessThanZeroError(0, "varname", false);
c.unsignedPositiveError(0, "varname", false); c.unsignedPositiveError(0, "varname", false);
c.bitwiseOnBooleanError(0, "varname", "&&"); c.bitwiseOnBooleanError(0, "varname", "&&");
c.comparisonOfBoolExpressionWithIntError(0); c.comparisonOfBoolExpressionWithIntError(0, true);
c.SuspiciousSemicolonError(0); c.SuspiciousSemicolonError(0);
c.wrongPrintfScanfArgumentsError(0,"printf",3,2); c.wrongPrintfScanfArgumentsError(0,"printf",3,2);
c.invalidScanfArgTypeError(0, "scanf", 1); c.invalidScanfArgTypeError(0, "scanf", 1);

View File

@ -130,7 +130,8 @@ private:
TEST_CASE(clarifyCondition4); // ticket #3110 TEST_CASE(clarifyCondition4); // ticket #3110
TEST_CASE(bitwiseOnBoolean); // if (bool & bool) TEST_CASE(bitwiseOnBoolean); // if (bool & bool)
TEST_CASE(comparisonOfBoolExpressionWithInt); TEST_CASE(comparisonOfBoolExpressionWithInt1);
TEST_CASE(comparisonOfBoolExpressionWithInt2);
TEST_CASE(incorrectStringCompare); TEST_CASE(incorrectStringCompare);
@ -140,7 +141,6 @@ private:
TEST_CASE(comparisonOfBoolWithInt3); TEST_CASE(comparisonOfBoolWithInt3);
TEST_CASE(comparisonOfBoolWithInt4); TEST_CASE(comparisonOfBoolWithInt4);
TEST_CASE(comparisonOfBoolWithInt5); TEST_CASE(comparisonOfBoolWithInt5);
TEST_CASE(comparisonOfBoolWithInt6);
TEST_CASE(duplicateIf); TEST_CASE(duplicateIf);
TEST_CASE(duplicateBranch); TEST_CASE(duplicateBranch);
@ -3023,7 +3023,7 @@ private:
ASSERT_EQUALS("[test.cpp:2]: (warning) Logical conjunction always evaluates to false: x < 1 && x > 3.\n", errout.str()); ASSERT_EQUALS("[test.cpp:2]: (warning) Logical conjunction always evaluates to false: x < 1 && x > 3.\n", errout.str());
} }
void comparisonOfBoolExpressionWithInt() { void comparisonOfBoolExpressionWithInt1() {
check("void f(int x) {\n" check("void f(int x) {\n"
" if ((x && 0x0f)==6)\n" " if ((x && 0x0f)==6)\n"
" a++;\n" " a++;\n"
@ -3043,7 +3043,8 @@ private:
" a++;\n" " a++;\n"
"}\n" "}\n"
); );
ASSERT_EQUALS("[test.cpp:2]: (warning) Comparison of a boolean expression with an integer other than 0 or 1.\n", errout.str()); ASSERT_EQUALS("[test.cpp:2]: (warning) Comparison of a boolean expression with an integer other than 0 or 1.\n"
"[test.cpp:2]: (warning) Comparison of a boolean with an integer\n", errout.str()); // The second message appears because the code is simplified to "true == 6". Its neither wrong nor necessary.
check("void f(int x) {\n" check("void f(int x) {\n"
" if ((x || 0x0f)==0)\n" " if ((x || 0x0f)==0)\n"
@ -3161,6 +3162,64 @@ private:
ASSERT_EQUALS("", errout.str()); ASSERT_EQUALS("", errout.str());
} }
void comparisonOfBoolExpressionWithInt2() {
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 expression with an integer other than 0 or 1.\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 expression with an integer other than 0 or 1.\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 expression with an integer other than 0 or 1.\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 expression with an integer other than 0 or 1.\n", errout.str());
check("void f(int x, int y) {\n"
" if (y != !x) {\n"
" printf(\"x not equal to 10\");\n"
" }\n"
"}");
ASSERT_EQUALS("[test.cpp:2]: (warning) Comparison of a boolean expression with an integer.\n", errout.str());
check("void f(int x, bool y) {\n"
" if (y != !x) {\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("", errout.str());
}
void memsetZeroBytes() { void memsetZeroBytes() {
check("void f() {\n" check("void f() {\n"
@ -3641,14 +3700,14 @@ private:
" printf(\"foo\");\n" " printf(\"foo\");\n"
" }\n" " }\n"
"}"); "}");
ASSERT_EQUALS("[test.cpp:2]: (warning) Comparison of a boolean with integer that is neither 1 nor 0\n", errout.str()); ASSERT_EQUALS("[test.cpp:2]: (warning) Comparison of a boolean with an integer\n", errout.str());
check("void f(bool x) {\n" check("void f(bool x) {\n"
" if (10 >= x) {\n" " if (10 >= x) {\n"
" printf(\"foo\");\n" " printf(\"foo\");\n"
" }\n" " }\n"
"}"); "}");
ASSERT_EQUALS("[test.cpp:2]: (warning) Comparison of a boolean with integer that is neither 1 nor 0\n", errout.str()); ASSERT_EQUALS("[test.cpp:2]: (warning) Comparison of a boolean with an integer\n", errout.str());
check("void f(bool x) {\n" check("void f(bool x) {\n"
" if (x != 0) {\n" " if (x != 0) {\n"
@ -3668,14 +3727,14 @@ private:
" printf(\"foo\");\n" " printf(\"foo\");\n"
" }\n" " }\n"
"}"); "}");
ASSERT_EQUALS("[test.cpp:2]: (warning) Comparison of a boolean with integer that is neither 1 nor 0\n", errout.str()); ASSERT_EQUALS("[test.cpp:2]: (warning) Comparison of a boolean with an integer that is neither 1 nor 0\n", errout.str());
check("void f(bool x) {\n" check("void f(bool x) {\n"
" if (x == 10) {\n" " if (x == 10) {\n"
" printf(\"foo\");\n" " printf(\"foo\");\n"
" }\n" " }\n"
"}"); "}");
ASSERT_EQUALS("[test.cpp:2]: (warning) Comparison of a boolean with integer that is neither 1 nor 0\n", errout.str()); ASSERT_EQUALS("[test.cpp:2]: (warning) Comparison of a boolean with an integer that is neither 1 nor 0\n", errout.str());
check("void f(bool x) {\n" check("void f(bool x) {\n"
" if (x == 0) {\n" " if (x == 0) {\n"
@ -3691,14 +3750,14 @@ private:
" printf(\"foo\");\n" " printf(\"foo\");\n"
" }\n" " }\n"
"}"); "}");
ASSERT_EQUALS("[test.cpp:2]: (warning) Comparison of a boolean with integer that is neither 1 nor 0\n", errout.str()); ASSERT_EQUALS("[test.cpp:2]: (warning) Comparison of a boolean with an integer\n", errout.str());
check("void f(int x, bool y) {\n" check("void f(int x, bool y) {\n"
" if (x == y) {\n" " if (x == y) {\n"
" printf(\"foo\");\n" " printf(\"foo\");\n"
" }\n" " }\n"
"}"); "}");
ASSERT_EQUALS("[test.cpp:2]: (warning) Comparison of a boolean with integer that is neither 1 nor 0\n", errout.str()); ASSERT_EQUALS("[test.cpp:2]: (warning) Comparison of a boolean with an integer\n", errout.str());
check("void f(bool x, bool y) {\n" check("void f(bool x, bool y) {\n"
" if (x == y) {\n" " if (x == y) {\n"
@ -3721,14 +3780,14 @@ private:
" printf(\"foo\");\n" " printf(\"foo\");\n"
" }\n" " }\n"
"}"); "}");
ASSERT_EQUALS("[test.cpp:2]: (warning) Comparison of a boolean with integer that is neither 1 nor 0\n", errout.str()); ASSERT_EQUALS("[test.cpp:2]: (warning) Comparison of a boolean with an integer\n", errout.str());
check("void f(int y) {\n" check("void f(int y) {\n"
" if (true == y) {\n" " if (true == y) {\n"
" printf(\"foo\");\n" " printf(\"foo\");\n"
" }\n" " }\n"
"}"); "}");
ASSERT_EQUALS("[test.cpp:2]: (warning) Comparison of a boolean with integer that is neither 1 nor 0\n", errout.str()); ASSERT_EQUALS("[test.cpp:2]: (warning) Comparison of a boolean with an integer\n", errout.str());
check("void f(bool y) {\n" check("void f(bool y) {\n"
" if (y == true) {\n" " if (y == true) {\n"
@ -3736,60 +3795,23 @@ private:
" }\n" " }\n"
"}"); "}");
ASSERT_EQUALS("", errout.str()); ASSERT_EQUALS("", errout.str());
check("void f(bool y) {\n"
" if (false < 5) {\n"
" printf(\"foo\");\n"
" }\n"
"}");
ASSERT_EQUALS("[test.cpp:2]: (warning) Comparison of a boolean with an integer\n", errout.str());
} }
void comparisonOfBoolWithInt4() { void comparisonOfBoolWithInt4() {
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 integer that is neither 1 nor 0\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 integer that is neither 1 nor 0\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 integer that is neither 1 nor 0\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 integer that is neither 1 nor 0\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());
}
void comparisonOfBoolWithInt5() {
check("void f(int x) {\n" check("void f(int x) {\n"
" if (!x == 1) { }\n" " if (!x == 1) { }\n"
"}"); "}");
ASSERT_EQUALS("", errout.str()); ASSERT_EQUALS("", errout.str());
} }
void comparisonOfBoolWithInt6() { void comparisonOfBoolWithInt5() {
check("void SetVisible(int index, bool visible) {\n" check("void SetVisible(int index, bool visible) {\n"
" bool (SciTEBase::*ischarforsel)(char ch);\n" " bool (SciTEBase::*ischarforsel)(char ch);\n"
" if (visible != GetVisible(index)) { }\n" " if (visible != GetVisible(index)) { }\n"