diff --git a/lib/checkbool.cpp b/lib/checkbool.cpp
new file mode 100644
index 000000000..33aef2a83
--- /dev/null
+++ b/lib/checkbool.cpp
@@ -0,0 +1,417 @@
+/*
+ * Cppcheck - A tool for static C/C++ code analysis
+ * Copyright (C) 2007-2013 Daniel Marjamäki and Cppcheck team.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+
+//---------------------------------------------------------------------------
+#include "checkbool.h"
+#include "mathlib.h"
+#include "symboldatabase.h"
+//---------------------------------------------------------------------------
+
+// Register this check class (by creating a static instance of it)
+namespace {
+ CheckBool instance;
+}
+
+//---------------------------------------------------------------------------
+//---------------------------------------------------------------------------
+void CheckBool::checkIncrementBoolean()
+{
+ if (!_settings->isEnabled("style"))
+ return;
+
+ const SymbolDatabase *symbolDatabase = _tokenizer->getSymbolDatabase();
+ const std::size_t functions = symbolDatabase->functionScopes.size();
+ for (std::size_t i = 0; i < functions; ++i) {
+ const Scope * scope = symbolDatabase->functionScopes[i];
+ for (const Token* tok = scope->classStart->next(); tok != scope->classEnd; tok = tok->next()) {
+ if (Token::Match(tok, "%var% ++")) {
+ if (tok->varId()) {
+ const Variable *var = tok->variable();
+
+ if (var && var->typeEndToken()->str() == "bool")
+ incrementBooleanError(tok);
+ }
+ }
+ }
+ }
+}
+
+void CheckBool::incrementBooleanError(const Token *tok)
+{
+ reportError(
+ tok,
+ Severity::style,
+ "incrementboolean",
+ "Incrementing a variable of type 'bool' with postfix operator++ is deprecated by the C++ Standard. You should assign it the value 'true' instead.\n"
+ "The operand of a postfix increment operator may be of type bool but it is deprecated by C++ Standard (Annex D-1) and the operand is always set to true. You should assign it the value 'true' instead."
+ );
+}
+
+//---------------------------------------------------------------------------
+// if (bool & bool) -> if (bool && bool)
+// if (bool | bool) -> if (bool || bool)
+//---------------------------------------------------------------------------
+void CheckBool::checkBitwiseOnBoolean()
+{
+ if (!_settings->isEnabled("style"))
+ return;
+
+ // danmar: this is inconclusive because I don't like that there are
+ // warnings for calculations. Example: set_flag(a & b);
+ if (!_settings->inconclusive)
+ return;
+
+ const SymbolDatabase *symbolDatabase = _tokenizer->getSymbolDatabase();
+ const std::size_t functions = symbolDatabase->functionScopes.size();
+ for (std::size_t i = 0; i < functions; ++i) {
+ const Scope * scope = symbolDatabase->functionScopes[i];
+ for (const Token* tok = scope->classStart->next(); tok != scope->classEnd; tok = tok->next()) {
+ if (Token::Match(tok, "(|.|return|&&|%oror%|throw|, %var% [&|]")) {
+ const Variable *var = tok->next()->variable();
+ if (var && var->typeEndToken()->str() == "bool") {
+ bitwiseOnBooleanError(tok->next(), var->name(), tok->strAt(2) == "&" ? "&&" : "||");
+ tok = tok->tokAt(2);
+ }
+ } else if (Token::Match(tok, "[&|] %var% )|.|return|&&|%oror%|throw|,") && (!tok->previous() || !tok->previous()->isExtendedOp() || tok->strAt(-1) == ")" || tok->strAt(-1) == "]")) {
+ const Variable *var = tok->next()->variable();
+ if (var && var->typeEndToken()->str() == "bool") {
+ bitwiseOnBooleanError(tok->next(), var->name(), tok->str() == "&" ? "&&" : "||");
+ tok = tok->tokAt(2);
+ }
+ }
+ }
+ }
+}
+
+void CheckBool::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 + "'?", true);
+}
+
+//---------------------------------------------------------------------------
+// if (!x==3) <- Probably meant to be "x!=3"
+//---------------------------------------------------------------------------
+
+static bool isBool(const Variable* var)
+{
+ return(var && var->typeEndToken()->str() == "bool");
+}
+static bool isNonBoolStdType(const Variable* var)
+{
+ return(var && var->typeEndToken()->isStandardType() && var->typeEndToken()->str() != "bool");
+}
+void CheckBool::checkComparisonOfBoolWithInt()
+{
+ if (!_settings->isEnabled("warning"))
+ return;
+
+ const SymbolDatabase* const symbolDatabase = _tokenizer->getSymbolDatabase();
+ const std::size_t functions = symbolDatabase->functionScopes.size();
+ for (std::size_t i = 0; i < functions; ++i) {
+ const Scope * scope = symbolDatabase->functionScopes[i];
+ for (const Token* tok = scope->classStart->next(); tok != scope->classEnd; tok = tok->next()) {
+ if (tok->next() && tok->next()->type() == Token::eComparisonOp && (!tok->previous() || !tok->previous()->isArithmeticalOp()) && (!tok->tokAt(3) || !tok->tokAt(3)->isArithmeticalOp())) {
+ const Token* const right = tok->tokAt(2);
+ if ((tok->varId() && right->isNumber()) || (tok->isNumber() && right->varId())) { // Comparing variable with number
+ const Token* varTok = tok;
+ const Token* numTok = right;
+ if (tok->isNumber() && right->varId()) // num with var
+ std::swap(varTok, numTok);
+ if (isBool(varTok->variable()) && // Variable has to be a boolean
+ ((tok->strAt(1) != "==" && tok->strAt(1) != "!=") ||
+ (MathLib::toLongNumber(numTok->str()) != 0 && MathLib::toLongNumber(numTok->str()) != 1))) { // == 0 and != 0 are allowed, for C also == 1 and != 1
+ comparisonOfBoolWithIntError(varTok, numTok->str(), tok->strAt(1) == "==" || tok->strAt(1) == "!=");
+ }
+ } else if (tok->isBoolean() && right->varId()) { // Comparing boolean constant with variable
+ if (isNonBoolStdType(right->variable())) { // Variable has to be of non-boolean standard type
+ comparisonOfBoolWithIntError(right, tok->str(), false);
+ } else if (tok->strAt(1) != "==" && tok->strAt(1) != "!=") {
+ comparisonOfBoolWithInvalidComparator(right, tok->str());
+ }
+ } else if (tok->varId() && right->isBoolean()) { // Comparing variable with boolean constant
+ if (isNonBoolStdType(tok->variable())) { // Variable has to be of non-boolean standard type
+ comparisonOfBoolWithIntError(tok, right->str(), false);
+ } else if (tok->strAt(1) != "==" && tok->strAt(1) != "!=") {
+ comparisonOfBoolWithInvalidComparator(right, tok->str());
+ }
+ } else if (tok->isNumber() && right->isBoolean()) { // number constant with boolean constant
+ comparisonOfBoolWithIntError(tok, right->str(), false);
+ } else if (tok->isBoolean() && right->isNumber()) { // number constant with boolean constant
+ comparisonOfBoolWithIntError(tok, tok->str(), false);
+ } else if (tok->varId() && right->varId()) { // Comparing two variables, one of them boolean, one of them integer
+ const Variable* var1 = right->variable();
+ const Variable* var2 = tok->variable();
+ if (isBool(var1) && isNonBoolStdType(var2)) // Comparing boolean with non-bool standard type
+ comparisonOfBoolWithIntError(tok, var1->name(), false);
+ else if (isNonBoolStdType(var1) && isBool(var2)) // Comparing non-bool standard type with boolean
+ comparisonOfBoolWithIntError(tok, var2->name(), false);
+ }
+ }
+ }
+ }
+}
+
+void CheckBool::comparisonOfBoolWithIntError(const Token *tok, const std::string &expression, bool n0o1)
+{
+ if (n0o1)
+ reportError(tok, Severity::warning, "comparisonOfBoolWithInt",
+ "Comparison of a boolean with an integer that is neither 1 nor 0.\n"
+ "The expression '" + expression + "' is of type 'bool' "
+ "and it is compared against an 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 an integer value.");
+}
+
+void CheckBool::comparisonOfBoolWithInvalidComparator(const Token *tok, const std::string &expression)
+{
+ reportError(tok, Severity::warning, "comparisonOfBoolWithInvalidComparator",
+ "Comparison of a boolean value using relational operator (<, >, <= or >=).\n"
+ "The result of the expression '" + expression + "' is of type 'bool'. "
+ "Comparing 'bool' value using relational (<, >, <= or >=)"
+ " operator could cause unexpected results.");
+}
+
+//-------------------------------------------------------------------------------
+// Comparing functions which are returning value of type bool
+//-------------------------------------------------------------------------------
+
+void CheckBool::checkComparisonOfFuncReturningBool()
+{
+ if (!_settings->isEnabled("style"))
+ return;
+
+ if (!_tokenizer->isCPP())
+ return;
+
+ const SymbolDatabase * const symbolDatabase = _tokenizer->getSymbolDatabase();
+
+ const std::size_t functions = symbolDatabase->functionScopes.size();
+ for (std::size_t i = 0; i < functions; ++i) {
+ const Scope * scope = symbolDatabase->functionScopes[i];
+ for (const Token* tok = scope->classStart->next(); tok != scope->classEnd; tok = tok->next()) {
+ if (tok->type() != Token::eComparisonOp || tok->str() == "==" || tok->str() == "!=")
+ continue;
+ const Token *first_token;
+ bool first_token_func_of_type_bool = false;
+ if (tok->strAt(-1) == ")") {
+ first_token = tok->previous()->link()->previous();
+ } else {
+ first_token = tok->previous();
+ }
+ if (Token::Match(first_token, "%var% (") && !Token::Match(first_token->previous(), "::|.")) {
+ const Function* func = first_token->function();
+ if (func && func->tokenDef && func->tokenDef->strAt(-1) == "bool") {
+ first_token_func_of_type_bool = true;
+ }
+ }
+
+ Token *second_token = tok->next();
+ bool second_token_func_of_type_bool = false;
+ while (second_token->str()=="!") {
+ second_token = second_token->next();
+ }
+ if (Token::Match(second_token, "%var% (") && !Token::Match(second_token->previous(), "::|.")) {
+ const Function* func = second_token->function();
+ if (func && func->tokenDef && func->tokenDef->strAt(-1) == "bool") {
+ second_token_func_of_type_bool = true;
+ }
+ }
+
+ if ((first_token_func_of_type_bool == true) && (second_token_func_of_type_bool == true)) {
+ comparisonOfTwoFuncsReturningBoolError(first_token->next(), first_token->str(), second_token->str());
+ } else if (first_token_func_of_type_bool == true) {
+ comparisonOfFuncReturningBoolError(first_token->next(), first_token->str());
+ } else if (second_token_func_of_type_bool == true) {
+ comparisonOfFuncReturningBoolError(second_token->previous(), second_token->str());
+ }
+ }
+ }
+}
+
+void CheckBool::comparisonOfFuncReturningBoolError(const Token *tok, const std::string &expression)
+{
+ reportError(tok, Severity::style, "comparisonOfFuncReturningBoolError",
+ "Comparison of a function returning boolean value using relational (<, >, <= or >=) operator.\n"
+ "The return type of function '" + expression + "' is 'bool' "
+ "and result is of type 'bool'. Comparing 'bool' value using relational (<, >, <= or >=)"
+ " operator could cause unexpected results.");
+}
+
+void CheckBool::comparisonOfTwoFuncsReturningBoolError(const Token *tok, const std::string &expression1, const std::string &expression2)
+{
+ reportError(tok, Severity::style, "comparisonOfTwoFuncsReturningBoolError",
+ "Comparison of two functions returning boolean value using relational (<, >, <= or >=) operator.\n"
+ "The return type of function '" + expression1 + "' and function '" + expression2 + "' is 'bool' "
+ "and result is of type 'bool'. Comparing 'bool' value using relational (<, >, <= or >=)"
+ " operator could cause unexpected results.");
+}
+
+//-------------------------------------------------------------------------------
+// Comparison of bool with bool
+//-------------------------------------------------------------------------------
+
+void CheckBool::checkComparisonOfBoolWithBool()
+{
+ // FIXME: This checking is "experimental" because of the false positives
+ // when self checking lib/tokenize.cpp (#2617)
+ if (!_settings->experimental)
+ return;
+
+ if (!_settings->isEnabled("style"))
+ return;
+
+ if (!_tokenizer->isCPP())
+ return;
+
+ const SymbolDatabase* const symbolDatabase = _tokenizer->getSymbolDatabase();
+
+ const std::size_t functions = symbolDatabase->functionScopes.size();
+ for (std::size_t i = 0; i < functions; ++i) {
+ const Scope * scope = symbolDatabase->functionScopes[i];
+ for (const Token* tok = scope->classStart->next(); tok != scope->classEnd; tok = tok->next()) {
+ if (tok->type() != Token::eComparisonOp || tok->str() == "==" || tok->str() == "!=")
+ continue;
+ bool first_token_bool = false;
+ bool second_token_bool = false;
+
+ const Token *first_token = tok->previous();
+ if (first_token->varId()) {
+ if (isBool(first_token->variable())) {
+ first_token_bool = true;
+ }
+ }
+ const Token *second_token = tok->next();
+ if (second_token->varId()) {
+ if (isBool(second_token->variable())) {
+ second_token_bool = true;
+ }
+ }
+ if ((first_token_bool == true) && (second_token_bool == true)) {
+ comparisonOfBoolWithBoolError(first_token->next(), first_token->str());
+ }
+ }
+ }
+}
+
+void CheckBool::comparisonOfBoolWithBoolError(const Token *tok, const std::string &expression)
+{
+ reportError(tok, Severity::style, "comparisonOfBoolWithBoolError",
+ "Comparison of a variable having boolean value using relational (<, >, <= or >=) operator.\n"
+ "The variable '" + expression + "' is of type 'bool' "
+ "and comparing 'bool' value using relational (<, >, <= or >=)"
+ " operator could cause unexpected results.");
+}
+
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+void CheckBool::checkAssignBoolToPointer()
+{
+ const SymbolDatabase *symbolDatabase = _tokenizer->getSymbolDatabase();
+ const std::size_t functions = symbolDatabase->functionScopes.size();
+ for (std::size_t i = 0; i < functions; ++i) {
+ const Scope * scope = symbolDatabase->functionScopes[i];
+ for (const Token* tok = scope->classStart; tok != scope->classEnd; tok = tok->next()) {
+ if (Token::Match(tok, "!!* %var% = %bool% ;")) {
+ const Variable *var1(tok->next()->variable());
+
+ // Is variable a pointer?
+ if (var1 && var1->isPointer())
+ assignBoolToPointerError(tok->next());
+ }
+ }
+ }
+}
+
+void CheckBool::assignBoolToPointerError(const Token *tok)
+{
+ reportError(tok, Severity::error, "assignBoolToPointer",
+ "Boolean value assigned to pointer.");
+}
+
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+void CheckBool::checkComparisonOfBoolExpressionWithInt()
+{
+ if (!_settings->isEnabled("warning"))
+ return;
+
+ const SymbolDatabase* symbolDatabase = _tokenizer->getSymbolDatabase();
+
+ const std::size_t functions = symbolDatabase->functionScopes.size();
+ for (std::size_t i = 0; i < functions; ++i) {
+ const Scope * scope = symbolDatabase->functionScopes[i];
+ for (const Token* tok = scope->classStart->next(); tok != scope->classEnd; tok = tok->next()) {
+ // Skip template parameters
+ if (tok->str() == "<" && tok->link()) {
+ tok = tok->link();
+ continue;
+ }
+
+ const Token* numTok = 0;
+ const Token* opTok = 0;
+ char op = 0;
+ if (Token::Match(tok, "&&|%oror% %any% ) %comp% %any%")) {
+ numTok = tok->tokAt(4);
+ opTok = tok->tokAt(3);
+ if (Token::Match(opTok, "<|>"))
+ op = opTok->str()[0];
+ } else if (Token::Match(tok, "%any% %comp% ( %any% &&|%oror%")) {
+ numTok = tok;
+ opTok = tok->next();
+ if (Token::Match(opTok, "<|>"))
+ op = opTok->str()[0]=='>'?'<':'>';
+ }
+
+ else if (Token::Match(tok, "! %var% %comp% %any%")) {
+ numTok = tok->tokAt(3);
+ opTok = tok->tokAt(2);
+ if (Token::Match(opTok, "<|>"))
+ op = opTok->str()[0];
+ } else if (Token::Match(tok, "%any% %comp% ! %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(numTok->variable()))
+ comparisonOfBoolExpressionWithIntError(tok, false);
+ }
+ }
+ }
+}
+
+void CheckBool::comparisonOfBoolExpressionWithIntError(const Token *tok, bool n0o1)
+{
+ if (n0o1)
+ 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.");
+}
diff --git a/lib/checkbool.h b/lib/checkbool.h
new file mode 100644
index 000000000..af9171fc2
--- /dev/null
+++ b/lib/checkbool.h
@@ -0,0 +1,134 @@
+/*
+ * Cppcheck - A tool for static C/C++ code analysis
+ * Copyright (C) 2007-2013 Daniel Marjamäki and Cppcheck team.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+
+//---------------------------------------------------------------------------
+#ifndef CheckBoolH
+#define CheckBoolH
+//---------------------------------------------------------------------------
+
+#include "config.h"
+#include "check.h"
+#include "settings.h"
+
+class Token;
+class Function;
+class Variable;
+
+/// @addtogroup Checks
+/// @{
+
+
+/** @brief checks dealing with suspicous usage of boolean type (not for evaluating conditions) */
+
+class CPPCHECKLIB CheckBool : public Check {
+public:
+ /** @brief This constructor is used when registering the CheckClass */
+ CheckBool() : Check(myName())
+ { }
+
+ /** @brief This constructor is used when running checks. */
+ CheckBool(const Tokenizer *tokenizer, const Settings *settings, ErrorLogger *errorLogger)
+ : Check(myName(), tokenizer, settings, errorLogger)
+ { }
+
+ /** @brief Run checks against the normal token list */
+ void runChecks(const Tokenizer *tokenizer, const Settings *settings, ErrorLogger *errorLogger) {
+ CheckBool checkBool(tokenizer, settings, errorLogger);
+
+ // Checks
+ checkBool.checkComparisonOfBoolExpressionWithInt();
+ checkBool.checkComparisonOfBoolWithInt();
+ }
+
+ /** @brief Run checks against the simplified token list */
+ void runSimplifiedChecks(const Tokenizer *tokenizer, const Settings *settings, ErrorLogger *errorLogger) {
+ CheckBool checkBool(tokenizer, settings, errorLogger);
+
+ // Checks
+ checkBool.checkComparisonOfFuncReturningBool();
+ checkBool.checkComparisonOfBoolWithBool();
+ checkBool.checkIncrementBoolean();
+ checkBool.checkAssignBoolToPointer();
+ checkBool.checkBitwiseOnBoolean();
+ }
+
+ /** @brief %Check for comparison of function returning bool*/
+ void checkComparisonOfFuncReturningBool();
+
+ /** @brief %Check for comparison of variable of type bool*/
+ void checkComparisonOfBoolWithBool();
+
+ /** @brief %Check for using postfix increment on bool */
+ 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();
+
+ /** @brief assigning bool to pointer */
+ void checkAssignBoolToPointer();
+
+ /** @brief %Check for using bool in bitwise expression */
+ void checkBitwiseOnBoolean();
+
+ /** @brief %Check for comparing a bool expression with an integer other than 0 or 1 */
+ void checkComparisonOfBoolExpressionWithInt();
+
+private:
+ // Error messages..
+ void comparisonOfFuncReturningBoolError(const Token *tok, const std::string &expression);
+ void comparisonOfTwoFuncsReturningBoolError(const Token *tok, const std::string &expression1, const std::string &expression2);
+ void comparisonOfBoolWithBoolError(const Token *tok, const std::string &expression);
+ void incrementBooleanError(const Token *tok);
+ void comparisonOfBoolWithIntError(const Token *tok, const std::string &expression, bool n0o1);
+ void comparisonOfBoolWithInvalidComparator(const Token *tok, const std::string &expression);
+ void assignBoolToPointerError(const Token *tok);
+ void bitwiseOnBooleanError(const Token *tok, const std::string &varname, const std::string &op);
+ void comparisonOfBoolExpressionWithIntError(const Token *tok, bool n0o1);
+
+ void getErrorMessages(ErrorLogger *errorLogger, const Settings *settings) const {
+ CheckBool c(0, settings, errorLogger);
+
+ c.assignBoolToPointerError(0);
+ c.comparisonOfFuncReturningBoolError(0, "func_name");
+ c.comparisonOfTwoFuncsReturningBoolError(0, "func_name1", "func_name2");
+ c.comparisonOfBoolWithBoolError(0, "var_name");
+ c.incrementBooleanError(0);
+ c.comparisonOfBoolWithIntError(0, "varname", true);
+ c.bitwiseOnBooleanError(0, "varname", "&&");
+ c.comparisonOfBoolExpressionWithIntError(0, true);
+ }
+
+ static std::string myName() {
+ return "Boolean";
+ }
+
+ std::string classInfo() const {
+ return "Boolean type checks\n"
+
+ "* using increment on boolean\n"
+ "* comparison of a boolean with a non-zero integer\n"
+ "* comparison of a boolean expression with an integer other than 0 or 1\n"
+ "* comparison of a function returning boolean value using relational operator\n"
+ "* comparison of a boolean value with boolean value using relational operator\n"
+ "* using bool in bitwise expression\n";
+ }
+};
+/// @}
+//---------------------------------------------------------------------------
+#endif
diff --git a/lib/checkother.cpp b/lib/checkother.cpp
index d378c1926..a862f9c9c 100644
--- a/lib/checkother.cpp
+++ b/lib/checkother.cpp
@@ -111,40 +111,6 @@ void CheckOther::checkCastIntToCharAndBackError(const Token *tok, const std::str
);
}
-//---------------------------------------------------------------------------
-//---------------------------------------------------------------------------
-void CheckOther::checkIncrementBoolean()
-{
- if (!_settings->isEnabled("style"))
- return;
-
- const SymbolDatabase *symbolDatabase = _tokenizer->getSymbolDatabase();
- const std::size_t functions = symbolDatabase->functionScopes.size();
- for (std::size_t i = 0; i < functions; ++i) {
- const Scope * scope = symbolDatabase->functionScopes[i];
- for (const Token* tok = scope->classStart->next(); tok != scope->classEnd; tok = tok->next()) {
- if (Token::Match(tok, "%var% ++")) {
- if (tok->varId()) {
- const Variable *var = tok->variable();
-
- if (var && var->typeEndToken()->str() == "bool")
- incrementBooleanError(tok);
- }
- }
- }
- }
-}
-
-void CheckOther::incrementBooleanError(const Token *tok)
-{
- reportError(
- tok,
- Severity::style,
- "incrementboolean",
- "Incrementing a variable of type 'bool' with postfix operator++ is deprecated by the C++ Standard. You should assign it the value 'true' instead.\n"
- "The operand of a postfix increment operator may be of type bool but it is deprecated by C++ Standard (Annex D-1) and the operand is always set to true. You should assign it the value 'true' instead."
- );
-}
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
@@ -373,47 +339,6 @@ void CheckOther::clarifyStatementError(const Token *tok)
"Thus, the dereference is meaningless. Did you intend to write '(*A)++;'?");
}
-//---------------------------------------------------------------------------
-// if (bool & bool) -> if (bool && bool)
-// if (bool | bool) -> if (bool || bool)
-//---------------------------------------------------------------------------
-void CheckOther::checkBitwiseOnBoolean()
-{
- if (!_settings->isEnabled("style"))
- return;
-
- // danmar: this is inconclusive because I don't like that there are
- // warnings for calculations. Example: set_flag(a & b);
- if (!_settings->inconclusive)
- return;
-
- const SymbolDatabase *symbolDatabase = _tokenizer->getSymbolDatabase();
- const std::size_t functions = symbolDatabase->functionScopes.size();
- for (std::size_t i = 0; i < functions; ++i) {
- const Scope * scope = symbolDatabase->functionScopes[i];
- for (const Token* tok = scope->classStart->next(); tok != scope->classEnd; tok = tok->next()) {
- if (Token::Match(tok, "(|.|return|&&|%oror%|throw|, %var% [&|]")) {
- const Variable *var = tok->next()->variable();
- if (var && var->typeEndToken()->str() == "bool") {
- bitwiseOnBooleanError(tok->next(), var->name(), tok->strAt(2) == "&" ? "&&" : "||");
- tok = tok->tokAt(2);
- }
- } else if (Token::Match(tok, "[&|] %var% )|.|return|&&|%oror%|throw|,") && (!tok->previous() || !tok->previous()->isExtendedOp() || tok->strAt(-1) == ")" || tok->strAt(-1) == "]")) {
- const Variable *var = tok->next()->variable();
- if (var && var->typeEndToken()->str() == "bool") {
- bitwiseOnBooleanError(tok->next(), var->name(), tok->str() == "&" ? "&&" : "||");
- tok = tok->tokAt(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 + "'?", true);
-}
void CheckOther::checkSuspiciousSemicolon()
{
@@ -1805,93 +1730,6 @@ void CheckOther::sprintfOverlappingDataError(const Token *tok, const std::string
"to sprintf() or snprintf(), the results are undefined.\"");
}
-//---------------------------------------------------------------------------
-// if (!x==3) <- Probably meant to be "x!=3"
-//---------------------------------------------------------------------------
-
-static bool isBool(const Variable* var)
-{
- return(var && var->typeEndToken()->str() == "bool");
-}
-static bool isNonBoolStdType(const Variable* var)
-{
- return(var && var->typeEndToken()->isStandardType() && var->typeEndToken()->str() != "bool");
-}
-void CheckOther::checkComparisonOfBoolWithInt()
-{
- if (!_settings->isEnabled("warning"))
- return;
-
- const SymbolDatabase* const symbolDatabase = _tokenizer->getSymbolDatabase();
- const std::size_t functions = symbolDatabase->functionScopes.size();
- for (std::size_t i = 0; i < functions; ++i) {
- const Scope * scope = symbolDatabase->functionScopes[i];
- for (const Token* tok = scope->classStart->next(); tok != scope->classEnd; tok = tok->next()) {
- if (tok->next() && tok->next()->type() == Token::eComparisonOp && (!tok->previous() || !tok->previous()->isArithmeticalOp()) && (!tok->tokAt(3) || !tok->tokAt(3)->isArithmeticalOp())) {
- const Token* const right = tok->tokAt(2);
- if ((tok->varId() && right->isNumber()) || (tok->isNumber() && right->varId())) { // Comparing variable with number
- const Token* varTok = tok;
- const Token* numTok = right;
- if (tok->isNumber() && right->varId()) // num with var
- std::swap(varTok, numTok);
- if (isBool(varTok->variable()) && // Variable has to be a boolean
- ((tok->strAt(1) != "==" && tok->strAt(1) != "!=") ||
- (MathLib::toLongNumber(numTok->str()) != 0 && MathLib::toLongNumber(numTok->str()) != 1))) { // == 0 and != 0 are allowed, for C also == 1 and != 1
- comparisonOfBoolWithIntError(varTok, numTok->str(), tok->strAt(1) == "==" || tok->strAt(1) == "!=");
- }
- } else if (tok->isBoolean() && right->varId()) { // Comparing boolean constant with variable
- if (isNonBoolStdType(right->variable())) { // Variable has to be of non-boolean standard type
- comparisonOfBoolWithIntError(right, tok->str(), false);
- } else if (tok->strAt(1) != "==" && tok->strAt(1) != "!=") {
- comparisonOfBoolWithInvalidComparator(right, tok->str());
- }
- } else if (tok->varId() && right->isBoolean()) { // Comparing variable with boolean constant
- if (isNonBoolStdType(tok->variable())) { // Variable has to be of non-boolean standard type
- comparisonOfBoolWithIntError(tok, right->str(), false);
- } else if (tok->strAt(1) != "==" && tok->strAt(1) != "!=") {
- comparisonOfBoolWithInvalidComparator(right, tok->str());
- }
- } else if (tok->isNumber() && right->isBoolean()) { // number constant with boolean constant
- comparisonOfBoolWithIntError(tok, right->str(), false);
- } else if (tok->isBoolean() && right->isNumber()) { // number constant with boolean constant
- comparisonOfBoolWithIntError(tok, tok->str(), false);
- } else if (tok->varId() && right->varId()) { // Comparing two variables, one of them boolean, one of them integer
- const Variable* var1 = right->variable();
- const Variable* var2 = tok->variable();
- if (isBool(var1) && isNonBoolStdType(var2)) // Comparing boolean with non-bool standard type
- comparisonOfBoolWithIntError(tok, var1->name(), false);
- else if (isNonBoolStdType(var1) && isBool(var2)) // Comparing non-bool standard type with boolean
- comparisonOfBoolWithIntError(tok, var2->name(), false);
- }
- }
- }
- }
-}
-
-void CheckOther::comparisonOfBoolWithIntError(const Token *tok, const std::string &expression, bool n0o1)
-{
- if (n0o1)
- reportError(tok, Severity::warning, "comparisonOfBoolWithInt",
- "Comparison of a boolean with an integer that is neither 1 nor 0.\n"
- "The expression '" + expression + "' is of type 'bool' "
- "and it is compared against an 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 an integer value.");
-}
-
-void CheckOther::comparisonOfBoolWithInvalidComparator(const Token *tok, const std::string &expression)
-{
- reportError(tok, Severity::warning, "comparisonOfBoolWithInvalidComparator",
- "Comparison of a boolean value using relational operator (<, >, <= or >=).\n"
- "The result of the expression '" + expression + "' is of type 'bool'. "
- "Comparing 'bool' value using relational (<, >, <= or >=)"
- " operator could cause unexpected results.");
-}
-
//---------------------------------------------------------------------------
// Find consecutive return, break, continue, goto or throw statements. e.g.:
// break; break;
@@ -2580,137 +2418,6 @@ void CheckOther::misusedScopeObjectError(const Token *tok, const std::string& va
"unusedScopedObject", "Instance of '" + varname + "' object is destroyed immediately.");
}
-//-------------------------------------------------------------------------------
-// Comparing functions which are returning value of type bool
-//-------------------------------------------------------------------------------
-
-void CheckOther::checkComparisonOfFuncReturningBool()
-{
- if (!_settings->isEnabled("style"))
- return;
-
- if (!_tokenizer->isCPP())
- return;
-
- const SymbolDatabase * const symbolDatabase = _tokenizer->getSymbolDatabase();
-
- const std::size_t functions = symbolDatabase->functionScopes.size();
- for (std::size_t i = 0; i < functions; ++i) {
- const Scope * scope = symbolDatabase->functionScopes[i];
- for (const Token* tok = scope->classStart->next(); tok != scope->classEnd; tok = tok->next()) {
- if (tok->type() != Token::eComparisonOp || tok->str() == "==" || tok->str() == "!=")
- continue;
- const Token *first_token;
- bool first_token_func_of_type_bool = false;
- if (tok->strAt(-1) == ")") {
- first_token = tok->previous()->link()->previous();
- } else {
- first_token = tok->previous();
- }
- if (Token::Match(first_token, "%var% (") && !Token::Match(first_token->previous(), "::|.")) {
- const Function* func = first_token->function();
- if (func && func->tokenDef && func->tokenDef->strAt(-1) == "bool") {
- first_token_func_of_type_bool = true;
- }
- }
-
- Token *second_token = tok->next();
- bool second_token_func_of_type_bool = false;
- while (second_token->str()=="!") {
- second_token = second_token->next();
- }
- if (Token::Match(second_token, "%var% (") && !Token::Match(second_token->previous(), "::|.")) {
- const Function* func = second_token->function();
- if (func && func->tokenDef && func->tokenDef->strAt(-1) == "bool") {
- second_token_func_of_type_bool = true;
- }
- }
-
- if ((first_token_func_of_type_bool == true) && (second_token_func_of_type_bool == true)) {
- comparisonOfTwoFuncsReturningBoolError(first_token->next(), first_token->str(), second_token->str());
- } else if (first_token_func_of_type_bool == true) {
- comparisonOfFuncReturningBoolError(first_token->next(), first_token->str());
- } else if (second_token_func_of_type_bool == true) {
- comparisonOfFuncReturningBoolError(second_token->previous(), second_token->str());
- }
- }
- }
-}
-
-void CheckOther::comparisonOfFuncReturningBoolError(const Token *tok, const std::string &expression)
-{
- reportError(tok, Severity::style, "comparisonOfFuncReturningBoolError",
- "Comparison of a function returning boolean value using relational (<, >, <= or >=) operator.\n"
- "The return type of function '" + expression + "' is 'bool' "
- "and result is of type 'bool'. Comparing 'bool' value using relational (<, >, <= or >=)"
- " operator could cause unexpected results.");
-}
-
-void CheckOther::comparisonOfTwoFuncsReturningBoolError(const Token *tok, const std::string &expression1, const std::string &expression2)
-{
- reportError(tok, Severity::style, "comparisonOfTwoFuncsReturningBoolError",
- "Comparison of two functions returning boolean value using relational (<, >, <= or >=) operator.\n"
- "The return type of function '" + expression1 + "' and function '" + expression2 + "' is 'bool' "
- "and result is of type 'bool'. Comparing 'bool' value using relational (<, >, <= or >=)"
- " operator could cause unexpected results.");
-}
-
-//-------------------------------------------------------------------------------
-// Comparison of bool with bool
-//-------------------------------------------------------------------------------
-
-void CheckOther::checkComparisonOfBoolWithBool()
-{
- // FIXME: This checking is "experimental" because of the false positives
- // when self checking lib/tokenize.cpp (#2617)
- if (!_settings->experimental)
- return;
-
- if (!_settings->isEnabled("style"))
- return;
-
- if (!_tokenizer->isCPP())
- return;
-
- const SymbolDatabase* const symbolDatabase = _tokenizer->getSymbolDatabase();
-
- const std::size_t functions = symbolDatabase->functionScopes.size();
- for (std::size_t i = 0; i < functions; ++i) {
- const Scope * scope = symbolDatabase->functionScopes[i];
- for (const Token* tok = scope->classStart->next(); tok != scope->classEnd; tok = tok->next()) {
- if (tok->type() != Token::eComparisonOp || tok->str() == "==" || tok->str() == "!=")
- continue;
- bool first_token_bool = false;
- bool second_token_bool = false;
-
- const Token *first_token = tok->previous();
- if (first_token->varId()) {
- if (isBool(first_token->variable())) {
- first_token_bool = true;
- }
- }
- const Token *second_token = tok->next();
- if (second_token->varId()) {
- if (isBool(second_token->variable())) {
- second_token_bool = true;
- }
- }
- if ((first_token_bool == true) && (second_token_bool == true)) {
- comparisonOfBoolWithBoolError(first_token->next(), first_token->str());
- }
- }
- }
-}
-
-void CheckOther::comparisonOfBoolWithBoolError(const Token *tok, const std::string &expression)
-{
- reportError(tok, Severity::style, "comparisonOfBoolWithBoolError",
- "Comparison of a variable having boolean value using relational (<, >, <= or >=) operator.\n"
- "The variable '" + expression + "' is of type 'bool' "
- "and comparing 'bool' value using relational (<, >, <= or >=)"
- " operator could cause unexpected results.");
-}
-
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
void CheckOther::checkIncorrectStringCompare()
@@ -3675,98 +3382,6 @@ void CheckOther::divideSizeofError(const Token *tok)
"not the size of the memory area it points to.", true);
}
-//-----------------------------------------------------------------------------
-//-----------------------------------------------------------------------------
-void CheckOther::checkAssignBoolToPointer()
-{
- const SymbolDatabase *symbolDatabase = _tokenizer->getSymbolDatabase();
- const std::size_t functions = symbolDatabase->functionScopes.size();
- for (std::size_t i = 0; i < functions; ++i) {
- const Scope * scope = symbolDatabase->functionScopes[i];
- for (const Token* tok = scope->classStart; tok != scope->classEnd; tok = tok->next()) {
- if (Token::Match(tok, "!!* %var% = %bool% ;")) {
- const Variable *var1(tok->next()->variable());
-
- // Is variable a pointer?
- if (var1 && var1->isPointer())
- assignBoolToPointerError(tok->next());
- }
- }
- }
-}
-
-void CheckOther::assignBoolToPointerError(const Token *tok)
-{
- reportError(tok, Severity::error, "assignBoolToPointer",
- "Boolean value assigned to pointer.");
-}
-
-//-----------------------------------------------------------------------------
-//-----------------------------------------------------------------------------
-void CheckOther::checkComparisonOfBoolExpressionWithInt()
-{
- if (!_settings->isEnabled("warning"))
- return;
-
- const SymbolDatabase* symbolDatabase = _tokenizer->getSymbolDatabase();
-
- const std::size_t functions = symbolDatabase->functionScopes.size();
- for (std::size_t i = 0; i < functions; ++i) {
- const Scope * scope = symbolDatabase->functionScopes[i];
- for (const Token* tok = scope->classStart->next(); tok != scope->classEnd; tok = tok->next()) {
- // Skip template parameters
- if (tok->str() == "<" && tok->link()) {
- tok = tok->link();
- continue;
- }
-
- const Token* numTok = 0;
- const Token* opTok = 0;
- char op = 0;
- if (Token::Match(tok, "&&|%oror% %any% ) %comp% %any%")) {
- numTok = tok->tokAt(4);
- opTok = tok->tokAt(3);
- if (Token::Match(opTok, "<|>"))
- op = opTok->str()[0];
- } else if (Token::Match(tok, "%any% %comp% ( %any% &&|%oror%")) {
- numTok = tok;
- opTok = tok->next();
- if (Token::Match(opTok, "<|>"))
- op = opTok->str()[0]=='>'?'<':'>';
- }
-
- else if (Token::Match(tok, "! %var% %comp% %any%")) {
- numTok = tok->tokAt(3);
- opTok = tok->tokAt(2);
- if (Token::Match(opTok, "<|>"))
- op = opTok->str()[0];
- } else if (Token::Match(tok, "%any% %comp% ! %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(numTok->variable()))
- comparisonOfBoolExpressionWithIntError(tok, false);
- }
- }
- }
-}
-
-void CheckOther::comparisonOfBoolExpressionWithIntError(const Token *tok, bool n0o1)
-{
- if (n0o1)
- 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.");
-}
//---------------------------------------------------------------------------
@@ -3965,7 +3580,7 @@ void CheckOther::checkIncompleteArrayFill()
if (MathLib::toLongNumber(tok->linkAt(1)->strAt(-1)) == var->dimension(0)) {
unsigned int size = _tokenizer->sizeOfType(var->typeStartToken());
- if ((size != 1 && size != 100 && size != 0) || var->typeEndToken()->str() == "*") {
+ if ((size != 1 && size != 100 && size != 0) || var->isPointer()) {
if (warning)
incompleteArrayFillError(tok, var->name(), tok->str(), false);
} else if (var->typeStartToken()->str() == "bool" && portability) // sizeof(bool) is not 1 on all platforms
diff --git a/lib/checkother.h b/lib/checkother.h
index edcd3c762..67e173e24 100644
--- a/lib/checkother.h
+++ b/lib/checkother.h
@@ -75,8 +75,6 @@ public:
checkOther.checkSuspiciousSemicolon();
checkOther.checkVariableScope();
checkOther.clarifyCondition(); // not simplified because ifAssign
- checkOther.checkComparisonOfBoolExpressionWithInt();
- checkOther.checkComparisonOfBoolWithInt();
checkOther.checkSignOfUnsignedVariable(); // don't ignore casts (#3574)
checkOther.checkIncompleteArrayFill();
checkOther.checkSuspiciousStringCompare();
@@ -103,18 +101,13 @@ public:
checkOther.redundantGetAndSetUserId();
checkOther.checkIncorrectLogicOperator();
checkOther.checkMisusedScopedObject();
- checkOther.checkComparisonOfFuncReturningBool();
- checkOther.checkComparisonOfBoolWithBool();
checkOther.checkMemsetZeroBytes();
checkOther.checkIncorrectStringCompare();
- checkOther.checkIncrementBoolean();
checkOther.checkSwitchCaseFallThrough();
checkOther.checkAlwaysTrueOrFalseStringCompare();
checkOther.checkModuloAlwaysTrueFalse();
checkOther.checkPipeParameterSize();
- checkOther.checkAssignBoolToPointer();
- checkOther.checkBitwiseOnBoolean();
checkOther.checkInvalidFree();
checkOther.checkDoubleFree();
checkOther.checkRedundantCopy();
@@ -217,12 +210,6 @@ public:
/** @brief %Check for objects that are destroyed immediately */
void checkMisusedScopedObject();
- /** @brief %Check for comparison of function returning bool*/
- void checkComparisonOfFuncReturningBool();
-
- /** @brief %Check for comparison of variable of type bool*/
- void checkComparisonOfBoolWithBool();
-
/** @brief %Check for filling zero bytes with memset() */
void checkMemsetZeroBytes();
@@ -241,12 +228,6 @@ public:
/** @brief %Check for comparison of a string literal with a char* variable */
void checkSuspiciousStringCompare();
- /** @brief %Check for using postfix increment on bool */
- 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();
-
/** @brief %Check for suspicious code where multiple if have the same expression (e.g "if (a) { } else if (a) { }") */
void checkDuplicateIf();
@@ -265,18 +246,9 @@ public:
/** @brief %Check for code that gets never executed, such as duplicate break statements */
void checkUnreachableCode();
- /** @brief assigning bool to pointer */
- void checkAssignBoolToPointer();
-
/** @brief %Check for testing sign of unsigned variable */
void checkSignOfUnsignedVariable();
- /** @brief %Check for using bool in bitwise expression */
- void checkBitwiseOnBoolean();
-
- /** @brief %Check for comparing a bool expression with an integer other than 0 or 1 */
- void checkComparisonOfBoolExpressionWithInt();
-
/** @brief %Check for suspicious use of semicolon */
void checkSuspiciousSemicolon();
@@ -353,18 +325,12 @@ private:
void incorrectLogicOperatorError(const Token *tok, const std::string &condition, bool always);
void redundantConditionError(const Token *tok, const std::string &text);
void misusedScopeObjectError(const Token *tok, const std::string &varname);
- void comparisonOfFuncReturningBoolError(const Token *tok, const std::string &expression);
- void comparisonOfTwoFuncsReturningBoolError(const Token *tok, const std::string &expression1, const std::string &expression2);
- void comparisonOfBoolWithBoolError(const Token *tok, const std::string &expression);
void memsetZeroBytesError(const Token *tok, const std::string &varname);
void sizeofForArrayParameterError(const Token *tok);
void sizeofForPointerError(const Token *tok, const std::string &varname);
void sizeofForNumericParameterError(const Token *tok);
void incorrectStringCompareError(const Token *tok, const std::string& func, const std::string &string);
void incorrectStringBooleanError(const Token *tok, const std::string& string);
- void incrementBooleanError(const Token *tok);
- void comparisonOfBoolWithIntError(const Token *tok, const std::string &expression, bool n0o1);
- void comparisonOfBoolWithInvalidComparator(const Token *tok, const std::string &expression);
void duplicateIfError(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);
@@ -373,13 +339,10 @@ private:
void suspiciousStringCompareError(const Token* tok, const std::string& var);
void duplicateBreakError(const Token *tok, bool inconclusive);
void unreachableCodeError(const Token* tok, bool inconclusive);
- void assignBoolToPointerError(const Token *tok);
void unsignedLessThanZeroError(const Token *tok, const std::string &varname, bool inconclusive);
void pointerLessThanZeroError(const Token *tok, bool inconclusive);
void unsignedPositiveError(const Token *tok, const std::string &varname, bool inconclusive);
void pointerPositiveError(const Token *tok, bool inconclusive);
- void bitwiseOnBooleanError(const Token *tok, const std::string &varname, const std::string &op);
- void comparisonOfBoolExpressionWithIntError(const Token *tok, bool n0o1);
void SuspiciousSemicolonError(const Token *tok);
void doubleCloseDirError(const Token *tok, const std::string &varname);
void moduloAlwaysTrueFalseError(const Token* tok, const std::string& maxVal);
@@ -392,15 +355,11 @@ private:
CheckOther c(0, settings, errorLogger);
// error
- c.assignBoolToPointerError(0);
c.sprintfOverlappingDataError(0, "varname");
c.udivError(0, false);
c.zerodivError(0);
c.mathfunctionCallError(0);
c.misusedScopeObjectError(NULL, "varname");
- c.comparisonOfFuncReturningBoolError(0, "func_name");
- c.comparisonOfTwoFuncsReturningBoolError(0, "func_name1", "func_name2");
- c.comparisonOfBoolWithBoolError(0, "var_name");
c.sizeofForArrayParameterError(0);
c.sizeofForPointerError(0, "varname");
c.sizeofForNumericParameterError(0);
@@ -446,8 +405,6 @@ private:
c.incorrectStringCompareError(0, "substr", "\"Hello World\"");
c.suspiciousStringCompareError(0, "foo");
c.incorrectStringBooleanError(0, "\"Hello World\"");
- c.incrementBooleanError(0);
- c.comparisonOfBoolWithIntError(0, "varname", true);
c.duplicateIfError(0, 0);
c.duplicateBranchError(0, 0);
c.duplicateExpressionError(0, 0, "&&");
@@ -459,8 +416,6 @@ private:
c.unsignedPositiveError(0, "varname", false);
c.pointerLessThanZeroError(0, false);
c.pointerPositiveError(0, false);
- c.bitwiseOnBooleanError(0, "varname", "&&");
- c.comparisonOfBoolExpressionWithIntError(0, true);
c.SuspiciousSemicolonError(0);
c.cctypefunctionCallError(0, "funname", "value");
c.moduloAlwaysTrueFalseError(0, "1");
@@ -520,11 +475,6 @@ private:
"* Suspicious equality comparisons\n"
"* mutual exclusion over || always evaluating to true\n"
"* Clarify calculation with parentheses\n"
- "* using increment on boolean\n"
- "* comparison of a boolean with a non-zero integer\n"
- "* comparison of a boolean expression with an integer other than 0 or 1\n"
- "* comparison of a function returning boolean value using relational operator\n"
- "* comparison of a boolean value with boolean value using relational operator\n"
"* suspicious condition (assignment+comparison)\n"
"* suspicious condition (runtime comparison of string literals)\n"
"* suspicious condition (string literals as boolean)\n"
@@ -533,7 +483,6 @@ private:
"* unreachable code\n"
"* testing if unsigned variable is negative\n"
"* testing is unsigned variable is positive\n"
- "* using bool in bitwise expression\n"
"* Suspicious use of ; at the end of 'if/for/while' statement.\n"
"* incorrect usage of functions from ctype library.\n"
"* Comparisons of modulo results that are always true/false.\n"
diff --git a/lib/cppcheck.vcxproj b/lib/cppcheck.vcxproj
index db1a20f6b..7d2fe4bcf 100644
--- a/lib/cppcheck.vcxproj
+++ b/lib/cppcheck.vcxproj
@@ -38,6 +38,7 @@
+
@@ -75,6 +76,7 @@
+
diff --git a/lib/cppcheck.vcxproj.filters b/lib/cppcheck.vcxproj.filters
index f44d60a28..b6646dd44 100644
--- a/lib/cppcheck.vcxproj.filters
+++ b/lib/cppcheck.vcxproj.filters
@@ -113,6 +113,9 @@
Source Files
+
+ Source Files
+
@@ -226,6 +229,9 @@
Header Files
+
+ Header Files
+
diff --git a/test/testbool.cpp b/test/testbool.cpp
new file mode 100644
index 000000000..006d9606a
--- /dev/null
+++ b/test/testbool.cpp
@@ -0,0 +1,768 @@
+/*
+ * Cppcheck - A tool for static C/C++ code analysis
+ * Copyright (C) 2007-2013 Daniel Marjamäki and Cppcheck team.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+
+#include "tokenize.h"
+#include "checkbool.h"
+#include "testsuite.h"
+#include
+
+extern std::ostringstream errout;
+
+class TestBool : public TestFixture {
+public:
+ TestBool() : TestFixture("TestBool")
+ { }
+
+private:
+
+
+ void run() {
+ TEST_CASE(bitwiseOnBoolean); // if (bool & bool)
+ TEST_CASE(incrementBoolean);
+ TEST_CASE(assignBoolToPointer);
+
+ TEST_CASE(comparisonOfBoolExpressionWithInt1);
+ TEST_CASE(comparisonOfBoolExpressionWithInt2);
+ TEST_CASE(comparisonOfBoolExpressionWithInt3);
+
+ TEST_CASE(comparisonOfBoolWithInt1);
+ TEST_CASE(comparisonOfBoolWithInt2);
+ TEST_CASE(comparisonOfBoolWithInt3);
+ TEST_CASE(comparisonOfBoolWithInt4);
+ TEST_CASE(comparisonOfBoolWithInt5);
+ TEST_CASE(comparisonOfBoolWithInt6); // #4224 - integer is casted to bool
+
+ TEST_CASE(checkComparisonOfFuncReturningBool1);
+ TEST_CASE(checkComparisonOfFuncReturningBool2);
+ TEST_CASE(checkComparisonOfFuncReturningBool3);
+ TEST_CASE(checkComparisonOfFuncReturningBool4);
+ TEST_CASE(checkComparisonOfFuncReturningBool5);
+ TEST_CASE(checkComparisonOfFuncReturningBool6);
+ }
+
+ void check(const char code[], bool experimental = false) {
+ // Clear the error buffer..
+ errout.str("");
+
+ Settings settings;
+ settings.addEnabled("style");
+ settings.addEnabled("warning");
+ settings.inconclusive = true;
+ settings.experimental = experimental;
+
+ // Tokenize..
+ Tokenizer tokenizer(&settings, this);
+ std::istringstream istr(code);
+ tokenizer.tokenize(istr, "test.cpp");
+
+ // Check...
+ CheckBool checkBool(&tokenizer, &settings, this);
+ checkBool.runChecks(&tokenizer, &settings, this);
+
+ // Simplify token list..
+ tokenizer.simplifyTokenList();
+ checkBool.runSimplifiedChecks(&tokenizer, &settings, this);
+ }
+
+
+ void assignBoolToPointer() {
+ check("void foo(bool *p) {\n"
+ " p = false;\n"
+ "}");
+ ASSERT_EQUALS("[test.cpp:2]: (error) Boolean value assigned to pointer.\n", errout.str());
+ }
+
+ void comparisonOfBoolExpressionWithInt1() {
+ check("void f(int x) {\n"
+ " if ((x && 0x0f)==6)\n"
+ " a++;\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 && 0x0f)==0)\n"
+ " a++;\n"
+ "}\n"
+ );
+ ASSERT_EQUALS("", errout.str());
+
+ check("void f(int x) {\n"
+ " if ((x || 0x0f)==6)\n"
+ " a++;\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 || 0x0f)==0)\n"
+ " a++;\n"
+ "}\n"
+ );
+ ASSERT_EQUALS("", errout.str());
+
+ check("void f(int x) {\n"
+ " if ((x & 0x0f)==6)\n"
+ " a++;\n"
+ "}\n"
+ );
+ ASSERT_EQUALS("", errout.str());
+
+ check("void f(int x) {\n"
+ " if ((x | 0x0f)==6)\n"
+ " a++;\n"
+ "}\n"
+ );
+ ASSERT_EQUALS("", errout.str());
+
+
+ check("void f(int x) {\n"
+ " if ((5 && x)==3)\n"
+ " a++;\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 ((5 && x)==3 || (8 && x)==9)\n"
+ " a++;\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 ((5 && x)!=3)\n"
+ " a++;\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 ((5 && x) > 3)\n"
+ " a++;\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 ((5 && x) > 0)\n"
+ " a++;\n"
+ "}\n"
+ );
+ ASSERT_EQUALS("", errout.str());
+
+ check("void f(int x) {\n"
+ " if ((5 && x) < 0)\n"
+ " a++;\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 ((5 && x) < 1)\n"
+ " a++;\n"
+ "}\n"
+ );
+ ASSERT_EQUALS("", errout.str());
+
+ check("void f(int x) {\n"
+ " if ((5 && x) > 1)\n"
+ " a++;\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 (0 < (5 && x))\n"
+ " a++;\n"
+ "}\n"
+ );
+ ASSERT_EQUALS("", errout.str());
+
+ check("void f(int x) {\n"
+ " if (0 > (5 && x))\n"
+ " a++;\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 (1 > (5 && x))\n"
+ " a++;\n"
+ "}\n"
+ );
+ ASSERT_EQUALS("", errout.str());
+
+ check("void f(int x) {\n"
+ " if (1 < (5 && x))\n"
+ " a++;\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(bool x ) {\n"
+ " if ( x > false )\n"
+ " a++;\n"
+ "}\n"
+ );
+ ASSERT_EQUALS("[test.cpp:2]: (warning) Comparison of a boolean value using relational operator (<, >, <= or >=).\n", errout.str());
+
+ check("void f(bool x ) {\n"
+ " if ( false < x )\n"
+ " a++;\n"
+ "}\n"
+ );
+ ASSERT_EQUALS("[test.cpp:2]: (warning) Comparison of a boolean value using relational operator (<, >, <= or >=).\n", errout.str());
+
+ check("void f(bool x ) {\n"
+ " if ( x < false )\n"
+ " a++;\n"
+ "}\n"
+ );
+ ASSERT_EQUALS("[test.cpp:2]: (warning) Comparison of a boolean value using relational operator (<, >, <= or >=).\n", errout.str());
+
+ check("void f(bool x ) {\n"
+ " if ( false > x )\n"
+ " a++;\n"
+ "}\n"
+ );
+ ASSERT_EQUALS("[test.cpp:2]: (warning) Comparison of a boolean value using relational operator (<, >, <= or >=).\n", errout.str());
+
+ check("void f(bool x ) {\n"
+ " if ( x >= false )\n"
+ " a++;\n"
+ "}\n"
+ );
+ ASSERT_EQUALS("[test.cpp:2]: (warning) Comparison of a boolean value using relational operator (<, >, <= or >=).\n", errout.str());
+
+ check("void f(bool x ) {\n"
+ " if ( false >= x )\n"
+ " a++;\n"
+ "}\n"
+ );
+ ASSERT_EQUALS("[test.cpp:2]: (warning) Comparison of a boolean value using relational operator (<, >, <= or >=).\n", errout.str());
+
+ check("void f(bool x ) {\n"
+ " if ( x <= false )\n"
+ " a++;\n"
+ "}\n"
+ );
+ ASSERT_EQUALS("[test.cpp:2]: (warning) Comparison of a boolean value using relational operator (<, >, <= or >=).\n", errout.str());
+
+ check("void f(bool x ) {\n"
+ " if ( false <= x )\n"
+ " a++;\n"
+ "}\n"
+ );
+ ASSERT_EQUALS("[test.cpp:2]: (warning) Comparison of a boolean value using relational operator (<, >, <= or >=).\n", errout.str());
+
+ check("typedef int (*func)(bool invert);\n"
+ "void x(int, func f);\n"
+ "void foo(int error) {\n"
+ " if (error == ABC) { }\n"
+ "}");
+ 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 comparisonOfBoolExpressionWithInt3() {
+ check("int f(int x) {\n"
+ " return t<0>() && x;\n"
+ "}");
+ ASSERT_EQUALS("", errout.str());
+ }
+
+ void checkComparisonOfFuncReturningBool1() {
+ check("void f(){\n"
+ " int temp = 4;\n"
+ " if(compare1(temp) > compare2(temp)){\n"
+ " printf(\"foo\");\n"
+ " }\n"
+ "}\n"
+ "bool compare1(int temp){\n"
+ " if(temp==4){\n"
+ " return true;\n"
+ " }\n"
+ " else\n"
+ " return false;\n"
+ "}\n"
+ "bool compare2(int temp){\n"
+ " if(temp==4){\n"
+ " return false;\n"
+ " }\n"
+ " else\n"
+ " return true;\n"
+ "}");
+ ASSERT_EQUALS("[test.cpp:3]: (style) Comparison of two functions returning boolean value using relational (<, >, <= or >=) operator.\n", errout.str());
+ }
+
+ void checkComparisonOfFuncReturningBool2() {
+ check("void f(){\n"
+ " int temp = 4;\n"
+ " bool a = true;\n"
+ " if(compare(temp) > a){\n"
+ " printf(\"foo\");\n"
+ " }\n"
+ "}\n"
+ "bool compare(int temp){\n"
+ " if(temp==4){\n"
+ " return true;\n"
+ " }\n"
+ " else\n"
+ " return false;\n"
+ "}");
+ ASSERT_EQUALS("[test.cpp:4]: (style) Comparison of a function returning boolean value using relational (<, >, <= or >=) operator.\n", errout.str());
+ }
+
+ void checkComparisonOfFuncReturningBool3() {
+ check("void f(){\n"
+ " int temp = 4;\n"
+ " if(compare(temp) > temp){\n"
+ " printf(\"foo\");\n"
+ " }\n"
+ "}\n"
+ "bool compare(int temp){\n"
+ " if(temp==4){\n"
+ " return true;\n"
+ " }\n"
+ " else\n"
+ " return false;\n"
+ "}");
+ ASSERT_EQUALS("[test.cpp:3]: (style) Comparison of a function returning boolean value using relational (<, >, <= or >=) operator.\n", errout.str());
+ }
+
+ void checkComparisonOfFuncReturningBool4() {
+ check("void f(){\n"
+ " int temp = 4;\n"
+ " bool b = compare2(6);\n"
+ " if(compare1(temp)> b){\n"
+ " printf(\"foo\");\n"
+ " }\n"
+ "}\n"
+ "bool compare1(int temp){\n"
+ " if(temp==4){\n"
+ " return true;\n"
+ " }\n"
+ " else\n"
+ " return false;\n"
+ "}\n"
+ "bool compare2(int temp){\n"
+ " if(temp == 5){\n"
+ " return true;\n"
+ " }\n"
+ " else\n"
+ " return false;\n"
+ "}");
+ ASSERT_EQUALS("[test.cpp:4]: (style) Comparison of a function returning boolean value using relational (<, >, <= or >=) operator.\n", errout.str());
+ }
+
+ void checkComparisonOfFuncReturningBool5() {
+ check("void f(){\n"
+ " int temp = 4;\n"
+ " if(compare1(temp) > !compare2(temp)){\n"
+ " printf(\"foo\");\n"
+ " }\n"
+ "}\n"
+ "bool compare1(int temp){\n"
+ " if(temp==4){\n"
+ " return true;\n"
+ " }\n"
+ " else\n"
+ " return false;\n"
+ "}\n"
+ "bool compare2(int temp){\n"
+ " if(temp==4){\n"
+ " return false;\n"
+ " }\n"
+ " else\n"
+ " return true;\n"
+ "}");
+ ASSERT_EQUALS("[test.cpp:3]: (style) Comparison of two functions returning boolean value using relational (<, >, <= or >=) operator.\n", errout.str());
+ }
+
+ void checkComparisonOfFuncReturningBool6() {
+ check("int compare1(int temp);\n"
+ "namespace Foo {\n"
+ " bool compare1(int temp);\n"
+ "}\n"
+ "void f(){\n"
+ " int temp = 4;\n"
+ " if(compare1(temp) > compare2(temp)){\n"
+ " printf(\"foo\");\n"
+ " }\n"
+ "}");
+ ASSERT_EQUALS("", errout.str());
+
+ check("namespace Foo {\n"
+ " bool compare1(int temp);\n"
+ "}\n"
+ "int compare1(int temp);\n"
+ "void f(){\n"
+ " int temp = 4;\n"
+ " if(compare1(temp) > compare2(temp)){\n"
+ " printf(\"foo\");\n"
+ " }\n"
+ "}");
+ ASSERT_EQUALS("", errout.str());
+
+ check("int compare1(int temp);\n"
+ "namespace Foo {\n"
+ " bool compare1(int temp);\n"
+ " void f(){\n"
+ " int temp = 4;\n"
+ " if(compare1(temp) > compare2(temp)){\n"
+ " printf(\"foo\");\n"
+ " }\n"
+ " }\n"
+ "}");
+ ASSERT_EQUALS("[test.cpp:6]: (style) Comparison of a function returning boolean value using relational (<, >, <= or >=) operator.\n", errout.str());
+
+ check("int compare1(int temp);\n"
+ "namespace Foo {\n"
+ " bool compare1(int temp);\n"
+ " void f(){\n"
+ " int temp = 4;\n"
+ " if(::compare1(temp) > compare2(temp)){\n"
+ " printf(\"foo\");\n"
+ " }\n"
+ " }\n"
+ "}");
+ ASSERT_EQUALS("", errout.str());
+
+ check("bool compare1(int temp);\n"
+ "void f(){\n"
+ " int temp = 4;\n"
+ " if(foo.compare1(temp) > compare2(temp)){\n"
+ " printf(\"foo\");\n"
+ " }\n"
+ "}");
+ ASSERT_EQUALS("", errout.str());
+ }
+
+ void checkComparisonOfBoolWithBool() {
+ const char code[] = "void f(){\n"
+ " int temp = 4;\n"
+ " bool b = compare2(6);\n"
+ " bool a = compare1(4);\n"
+ " if(b > a){\n"
+ " printf(\"foo\");\n"
+ " }\n"
+ "}\n"
+ "bool compare1(int temp){\n"
+ " if(temp==4){\n"
+ " return true;\n"
+ " }\n"
+ " else\n"
+ " return false;\n"
+ "}\n"
+ "bool compare2(int temp){\n"
+ " if(temp == 5){\n"
+ " return true;\n"
+ " }\n"
+ " else\n"
+ " return false;\n"
+ "}\n";
+ check(code, true);
+ ASSERT_EQUALS("[test.cpp:5]: (style) Comparison of a variable having boolean value using relational (<, >, <= or >=) operator.\n", errout.str());
+ check(code, false);
+ 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, inconclusive) 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, inconclusive) 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, inconclusive) 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, inconclusive) 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, inconclusive) 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, inconclusive) 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, inconclusive) 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, inconclusive) Boolean variable 'a' is used in bitwise operation. Did you mean '||'?\n", errout.str());
+
+ check("void f(bool a, int b) {\n"
+ " if(a & b) {}\n"
+ "}");
+ ASSERT_EQUALS("[test.cpp:2]: (style, inconclusive) Boolean variable 'a' is used in bitwise operation. Did you mean '&&'?\n", errout.str());
+
+ check("void f(int a, bool b) {\n"
+ " if(a & b) {}\n"
+ "}");
+ ASSERT_EQUALS("[test.cpp:2]: (style, inconclusive) Boolean variable 'b' is used in bitwise operation. Did you mean '&&'?\n", errout.str());
+
+ check("void f(int a, int b) {\n"
+ " if(a & b) {}\n"
+ "}");
+ ASSERT_EQUALS("", errout.str());
+
+ check("void f(bool b) {\n"
+ " foo(bar, &b);\n"
+ "}");
+ ASSERT_EQUALS("", errout.str());
+ }
+
+ void incrementBoolean() {
+ check("bool bValue = true;\n"
+ "void f() { bValue++; }");
+ ASSERT_EQUALS("[test.cpp:2]: (style) Incrementing a variable of type 'bool' with postfix operator++ is deprecated by the C++ Standard. You should assign it the value 'true' instead.\n", errout.str());
+
+ check("_Bool bValue = true;\n"
+ "void f() { bValue++; }");
+ ASSERT_EQUALS("[test.cpp:2]: (style) Incrementing a variable of type 'bool' with postfix operator++ is deprecated by the C++ Standard. You should assign it the value 'true' instead.\n", errout.str());
+
+ check("void f(bool test){\n"
+ " test++;\n"
+ "}");
+ ASSERT_EQUALS("[test.cpp:2]: (style) Incrementing a variable of type 'bool' with postfix operator++ is deprecated by the C++ Standard. You should assign it the value 'true' instead.\n", errout.str());
+
+ check("void f(int test){\n"
+ " test++;\n"
+ "}");
+ ASSERT_EQUALS("", errout.str());
+ }
+
+ void comparisonOfBoolWithInt1() {
+ check("void f(bool x) {\n"
+ " if (x < 10) {\n"
+ " printf(\"foo\");\n"
+ " }\n"
+ "}");
+ ASSERT_EQUALS("[test.cpp:2]: (warning) Comparison of a boolean with an integer.\n", errout.str());
+
+ check("void f(bool x) {\n"
+ " if (10 >= x) {\n"
+ " printf(\"foo\");\n"
+ " }\n"
+ "}");
+ ASSERT_EQUALS("[test.cpp:2]: (warning) Comparison of a boolean with an integer.\n", errout.str());
+
+ check("void f(bool x) {\n"
+ " if (x != 0) {\n"
+ " printf(\"foo\");\n"
+ " }\n"
+ "}");
+ ASSERT_EQUALS("", errout.str());
+
+ check("void f(bool x) {\n" // #3356
+ " if (x == 1) {\n"
+ " }\n"
+ "}");
+ ASSERT_EQUALS("", errout.str());
+
+ check("void f(bool x) {\n"
+ " if (x != 10) {\n"
+ " printf(\"foo\");\n"
+ " }\n"
+ "}");
+ 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"
+ " if (x == 10) {\n"
+ " printf(\"foo\");\n"
+ " }\n"
+ "}");
+ 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"
+ " if (x == 0) {\n"
+ " printf(\"foo\");\n"
+ " }\n"
+ "}");
+ ASSERT_EQUALS("", errout.str());
+
+ check("DensePropertyMap visited;"); // #4075
+ ASSERT_EQUALS("", errout.str());
+ }
+
+ void comparisonOfBoolWithInt2() {
+ check("void f(bool x, int y) {\n"
+ " if (x == y) {\n"
+ " printf(\"foo\");\n"
+ " }\n"
+ "}");
+ ASSERT_EQUALS("[test.cpp:2]: (warning) Comparison of a boolean with an integer.\n", errout.str());
+
+ check("void f(int x, bool y) {\n"
+ " if (x == y) {\n"
+ " printf(\"foo\");\n"
+ " }\n"
+ "}");
+ ASSERT_EQUALS("[test.cpp:2]: (warning) Comparison of a boolean with an integer.\n", errout.str());
+
+ check("void f(bool x, bool y) {\n"
+ " if (x == y) {\n"
+ " printf(\"foo\");\n"
+ " }\n"
+ "}");
+ ASSERT_EQUALS("", errout.str());
+
+ check("void f(bool x, fooClass y) {\n"
+ " if (x == y) {\n"
+ " printf(\"foo\");\n"
+ " }\n"
+ "}");
+ ASSERT_EQUALS("", errout.str());
+ }
+
+ void comparisonOfBoolWithInt3() {
+ check("void f(int y) {\n"
+ " if (y > false) {\n"
+ " printf(\"foo\");\n"
+ " }\n"
+ "}");
+ ASSERT_EQUALS("[test.cpp:2]: (warning) Comparison of a boolean with an integer.\n", errout.str());
+
+ check("void f(int y) {\n"
+ " if (true == y) {\n"
+ " printf(\"foo\");\n"
+ " }\n"
+ "}");
+ ASSERT_EQUALS("[test.cpp:2]: (warning) Comparison of a boolean with an integer.\n", errout.str());
+
+ check("void f(bool y) {\n"
+ " if (y == true) {\n"
+ " printf(\"foo\");\n"
+ " }\n"
+ "}");
+ 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() {
+ check("void f(int x) {\n"
+ " if (!x == 1) { }\n"
+ "}");
+ ASSERT_EQUALS("", errout.str());
+ }
+
+ void comparisonOfBoolWithInt5() {
+ check("void SetVisible(int index, bool visible) {\n"
+ " bool (SciTEBase::*ischarforsel)(char ch);\n"
+ " if (visible != GetVisible(index)) { }\n"
+ "}");
+ ASSERT_EQUALS("", errout.str());
+ }
+
+ void comparisonOfBoolWithInt6() { // #4224 - integer is casted to bool
+ check("void SetVisible(bool b, int i) {\n"
+ " if (b == (bool)i) { }\n"
+ "}");
+ ASSERT_EQUALS("", errout.str());
+ }
+};
+
+REGISTER_TEST(TestBool)
diff --git a/test/testother.cpp b/test/testother.cpp
index 2d384c926..98a479e2e 100644
--- a/test/testother.cpp
+++ b/test/testother.cpp
@@ -34,7 +34,6 @@ private:
void run() {
TEST_CASE(oppositeInnerCondition);
- TEST_CASE(assignBoolToPointer);
TEST_CASE(emptyBrackets);
TEST_CASE(zeroDiv1);
@@ -140,31 +139,9 @@ private:
TEST_CASE(clarifyCondition4); // ticket #3110
TEST_CASE(clarifyCondition5); // #3609 CWinTraits..
TEST_CASE(clarifyCondition6); // #3818
- TEST_CASE(bitwiseOnBoolean); // if (bool & bool)
-
- TEST_CASE(comparisonOfBoolExpressionWithInt1);
- TEST_CASE(comparisonOfBoolExpressionWithInt2);
- TEST_CASE(comparisonOfBoolExpressionWithInt3);
TEST_CASE(incorrectStringCompare);
- TEST_CASE(incrementBoolean);
- TEST_CASE(comparisonOfBoolWithInt1);
- TEST_CASE(comparisonOfBoolWithInt2);
- TEST_CASE(comparisonOfBoolWithInt3);
- TEST_CASE(comparisonOfBoolWithInt4);
- TEST_CASE(comparisonOfBoolWithInt5);
- TEST_CASE(comparisonOfBoolWithInt6); // #4224 - integer is casted to bool
-
- TEST_CASE(checkComparisonOfFuncReturningBool1);
- TEST_CASE(checkComparisonOfFuncReturningBool2);
- TEST_CASE(checkComparisonOfFuncReturningBool3);
- TEST_CASE(checkComparisonOfFuncReturningBool4);
- TEST_CASE(checkComparisonOfFuncReturningBool5);
- TEST_CASE(checkComparisonOfFuncReturningBool6);
-
- TEST_CASE(checkComparisonOfBoolWithBool);
-
TEST_CASE(duplicateIf);
TEST_CASE(duplicateIf1); // ticket 3689
TEST_CASE(duplicateBranch);
@@ -324,14 +301,6 @@ private:
ASSERT_EQUALS("", errout.str());
}
-
- void assignBoolToPointer() {
- check("void foo(bool *p) {\n"
- " p = false;\n"
- "}");
- ASSERT_EQUALS("[test.cpp:2]: (error) Boolean value assigned to pointer.\n", errout.str());
- }
-
void emptyBrackets() {
check("{\n"
"}");
@@ -3902,265 +3871,6 @@ private:
ASSERT_EQUALS("", errout.str());
}
- void comparisonOfBoolExpressionWithInt1() {
- check("void f(int x) {\n"
- " if ((x && 0x0f)==6)\n"
- " a++;\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 && 0x0f)==0)\n"
- " a++;\n"
- "}\n"
- );
- ASSERT_EQUALS("", errout.str());
-
- check("void f(int x) {\n"
- " if ((x || 0x0f)==6)\n"
- " a++;\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 || 0x0f)==0)\n"
- " a++;\n"
- "}\n"
- );
- ASSERT_EQUALS("", errout.str());
-
- check("void f(int x) {\n"
- " if ((x & 0x0f)==6)\n"
- " a++;\n"
- "}\n"
- );
- ASSERT_EQUALS("", errout.str());
-
- check("void f(int x) {\n"
- " if ((x | 0x0f)==6)\n"
- " a++;\n"
- "}\n"
- );
- ASSERT_EQUALS("", errout.str());
-
-
- check("void f(int x) {\n"
- " if ((5 && x)==3)\n"
- " a++;\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 ((5 && x)==3 || (8 && x)==9)\n"
- " a++;\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 ((5 && x)!=3)\n"
- " a++;\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 ((5 && x) > 3)\n"
- " a++;\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 ((5 && x) > 0)\n"
- " a++;\n"
- "}\n"
- );
- ASSERT_EQUALS("", errout.str());
-
- check("void f(int x) {\n"
- " if ((5 && x) < 0)\n"
- " a++;\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 ((5 && x) < 1)\n"
- " a++;\n"
- "}\n"
- );
- ASSERT_EQUALS("", errout.str());
-
- check("void f(int x) {\n"
- " if ((5 && x) > 1)\n"
- " a++;\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 (0 < (5 && x))\n"
- " a++;\n"
- "}\n"
- );
- ASSERT_EQUALS("", errout.str());
-
- check("void f(int x) {\n"
- " if (0 > (5 && x))\n"
- " a++;\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 (1 > (5 && x))\n"
- " a++;\n"
- "}\n"
- );
- ASSERT_EQUALS("", errout.str());
-
- check("void f(int x) {\n"
- " if (1 < (5 && x))\n"
- " a++;\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(bool x ) {\n"
- " if ( x > false )\n"
- " a++;\n"
- "}\n"
- );
- ASSERT_EQUALS("[test.cpp:2]: (warning) Comparison of a boolean value using relational operator (<, >, <= or >=).\n", errout.str());
-
- check("void f(bool x ) {\n"
- " if ( false < x )\n"
- " a++;\n"
- "}\n"
- );
- ASSERT_EQUALS("[test.cpp:2]: (warning) Comparison of a boolean value using relational operator (<, >, <= or >=).\n", errout.str());
-
- check("void f(bool x ) {\n"
- " if ( x < false )\n"
- " a++;\n"
- "}\n"
- );
- ASSERT_EQUALS("[test.cpp:2]: (warning) Comparison of a boolean value using relational operator (<, >, <= or >=).\n", errout.str());
-
- check("void f(bool x ) {\n"
- " if ( false > x )\n"
- " a++;\n"
- "}\n"
- );
- ASSERT_EQUALS("[test.cpp:2]: (warning) Comparison of a boolean value using relational operator (<, >, <= or >=).\n", errout.str());
-
- check("void f(bool x ) {\n"
- " if ( x >= false )\n"
- " a++;\n"
- "}\n"
- );
- ASSERT_EQUALS("[test.cpp:2]: (warning) Comparison of a boolean value using relational operator (<, >, <= or >=).\n", errout.str());
-
- check("void f(bool x ) {\n"
- " if ( false >= x )\n"
- " a++;\n"
- "}\n"
- );
- ASSERT_EQUALS("[test.cpp:2]: (warning) Comparison of a boolean value using relational operator (<, >, <= or >=).\n", errout.str());
-
- check("void f(bool x ) {\n"
- " if ( x <= false )\n"
- " a++;\n"
- "}\n"
- );
- ASSERT_EQUALS("[test.cpp:2]: (warning) Comparison of a boolean value using relational operator (<, >, <= or >=).\n", errout.str());
-
- check("void f(bool x ) {\n"
- " if ( false <= x )\n"
- " a++;\n"
- "}\n"
- );
- ASSERT_EQUALS("[test.cpp:2]: (warning) Comparison of a boolean value using relational operator (<, >, <= or >=).\n", errout.str());
-
- check("typedef int (*func)(bool invert);\n"
- "void x(int, func f);\n"
- "void foo(int error) {\n"
- " if (error == ABC) { }\n"
- "}");
- 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 comparisonOfBoolExpressionWithInt3() {
- check("int f(int x) {\n"
- " return t<0>() && x;\n"
- "}");
- ASSERT_EQUALS("", errout.str());
- }
-
void memsetZeroBytes() {
check("void f() {\n"
" memset(p, 10, 0x0);\n"
@@ -4313,202 +4023,6 @@ private:
}
- void checkComparisonOfFuncReturningBool1() {
- check("void f(){\n"
- " int temp = 4;\n"
- " if(compare1(temp) > compare2(temp)){\n"
- " printf(\"foo\");\n"
- " }\n"
- "}\n"
- "bool compare1(int temp){\n"
- " if(temp==4){\n"
- " return true;\n"
- " }\n"
- " else\n"
- " return false;\n"
- "}\n"
- "bool compare2(int temp){\n"
- " if(temp==4){\n"
- " return false;\n"
- " }\n"
- " else\n"
- " return true;\n"
- "}");
- ASSERT_EQUALS("[test.cpp:3]: (style) Comparison of two functions returning boolean value using relational (<, >, <= or >=) operator.\n", errout.str());
- }
-
- void checkComparisonOfFuncReturningBool2() {
- check("void f(){\n"
- " int temp = 4;\n"
- " bool a = true;\n"
- " if(compare(temp) > a){\n"
- " printf(\"foo\");\n"
- " }\n"
- "}\n"
- "bool compare(int temp){\n"
- " if(temp==4){\n"
- " return true;\n"
- " }\n"
- " else\n"
- " return false;\n"
- "}");
- ASSERT_EQUALS("[test.cpp:4]: (style) Comparison of a function returning boolean value using relational (<, >, <= or >=) operator.\n", errout.str());
- }
-
- void checkComparisonOfFuncReturningBool3() {
- check("void f(){\n"
- " int temp = 4;\n"
- " if(compare(temp) > temp){\n"
- " printf(\"foo\");\n"
- " }\n"
- "}\n"
- "bool compare(int temp){\n"
- " if(temp==4){\n"
- " return true;\n"
- " }\n"
- " else\n"
- " return false;\n"
- "}");
- ASSERT_EQUALS("[test.cpp:3]: (style) Comparison of a function returning boolean value using relational (<, >, <= or >=) operator.\n", errout.str());
- }
-
- void checkComparisonOfFuncReturningBool4() {
- check("void f(){\n"
- " int temp = 4;\n"
- " bool b = compare2(6);\n"
- " if(compare1(temp)> b){\n"
- " printf(\"foo\");\n"
- " }\n"
- "}\n"
- "bool compare1(int temp){\n"
- " if(temp==4){\n"
- " return true;\n"
- " }\n"
- " else\n"
- " return false;\n"
- "}\n"
- "bool compare2(int temp){\n"
- " if(temp == 5){\n"
- " return true;\n"
- " }\n"
- " else\n"
- " return false;\n"
- "}");
- ASSERT_EQUALS("[test.cpp:4]: (style) Comparison of a function returning boolean value using relational (<, >, <= or >=) operator.\n", errout.str());
- }
-
- void checkComparisonOfFuncReturningBool5() {
- check("void f(){\n"
- " int temp = 4;\n"
- " if(compare1(temp) > !compare2(temp)){\n"
- " printf(\"foo\");\n"
- " }\n"
- "}\n"
- "bool compare1(int temp){\n"
- " if(temp==4){\n"
- " return true;\n"
- " }\n"
- " else\n"
- " return false;\n"
- "}\n"
- "bool compare2(int temp){\n"
- " if(temp==4){\n"
- " return false;\n"
- " }\n"
- " else\n"
- " return true;\n"
- "}");
- ASSERT_EQUALS("[test.cpp:3]: (style) Comparison of two functions returning boolean value using relational (<, >, <= or >=) operator.\n", errout.str());
- }
-
- void checkComparisonOfFuncReturningBool6() {
- check("int compare1(int temp);\n"
- "namespace Foo {\n"
- " bool compare1(int temp);\n"
- "}\n"
- "void f(){\n"
- " int temp = 4;\n"
- " if(compare1(temp) > compare2(temp)){\n"
- " printf(\"foo\");\n"
- " }\n"
- "}");
- ASSERT_EQUALS("", errout.str());
-
- check("namespace Foo {\n"
- " bool compare1(int temp);\n"
- "}\n"
- "int compare1(int temp);\n"
- "void f(){\n"
- " int temp = 4;\n"
- " if(compare1(temp) > compare2(temp)){\n"
- " printf(\"foo\");\n"
- " }\n"
- "}");
- ASSERT_EQUALS("", errout.str());
-
- check("int compare1(int temp);\n"
- "namespace Foo {\n"
- " bool compare1(int temp);\n"
- " void f(){\n"
- " int temp = 4;\n"
- " if(compare1(temp) > compare2(temp)){\n"
- " printf(\"foo\");\n"
- " }\n"
- " }\n"
- "}");
- ASSERT_EQUALS("[test.cpp:6]: (style) Comparison of a function returning boolean value using relational (<, >, <= or >=) operator.\n", errout.str());
-
- check("int compare1(int temp);\n"
- "namespace Foo {\n"
- " bool compare1(int temp);\n"
- " void f(){\n"
- " int temp = 4;\n"
- " if(::compare1(temp) > compare2(temp)){\n"
- " printf(\"foo\");\n"
- " }\n"
- " }\n"
- "}");
- ASSERT_EQUALS("", errout.str());
-
- check("bool compare1(int temp);\n"
- "void f(){\n"
- " int temp = 4;\n"
- " if(foo.compare1(temp) > compare2(temp)){\n"
- " printf(\"foo\");\n"
- " }\n"
- "}");
- ASSERT_EQUALS("", errout.str());
- }
-
- void checkComparisonOfBoolWithBool() {
- const char code[] = "void f(){\n"
- " int temp = 4;\n"
- " bool b = compare2(6);\n"
- " bool a = compare1(4);\n"
- " if(b > a){\n"
- " printf(\"foo\");\n"
- " }\n"
- "}\n"
- "bool compare1(int temp){\n"
- " if(temp==4){\n"
- " return true;\n"
- " }\n"
- " else\n"
- " return false;\n"
- "}\n"
- "bool compare2(int temp){\n"
- " if(temp == 5){\n"
- " return true;\n"
- " }\n"
- " else\n"
- " return false;\n"
- "}\n";
- check(code, "test.cpp", true);
- ASSERT_EQUALS("[test.cpp:5]: (style) Comparison of a variable having boolean value using relational (<, >, <= or >=) operator.\n", errout.str());
- check(code, "test.cpp");
- ASSERT_EQUALS("", errout.str());
- }
-
void sizeofForNumericParameter() {
check("void f() {\n"
" std::cout << sizeof(10) << std::endl;\n"
@@ -4788,72 +4302,6 @@ private:
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, inconclusive) 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, inconclusive) 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, inconclusive) 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, inconclusive) 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, inconclusive) 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, inconclusive) 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, inconclusive) 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, inconclusive) Boolean variable 'a' is used in bitwise operation. Did you mean '||'?\n", errout.str());
-
- check("void f(bool a, int b) {\n"
- " if(a & b) {}\n"
- "}");
- ASSERT_EQUALS("[test.cpp:2]: (style, inconclusive) Boolean variable 'a' is used in bitwise operation. Did you mean '&&'?\n", errout.str());
-
- check("void f(int a, bool b) {\n"
- " if(a & b) {}\n"
- "}");
- ASSERT_EQUALS("[test.cpp:2]: (style, inconclusive) Boolean variable 'b' is used in bitwise operation. Did you mean '&&'?\n", errout.str());
-
- check("void f(int a, int b) {\n"
- " if(a & b) {}\n"
- "}");
- ASSERT_EQUALS("", errout.str());
-
- check("void f(bool b) {\n"
- " foo(bar, &b);\n"
- "}");
- ASSERT_EQUALS("", errout.str());
- }
-
void incorrectStringCompare() {
check("int f() {\n"
" return test.substr( 0 , 4 ) == \"Hello\" ? : 0 : 1 ;\n"
@@ -4932,161 +4380,6 @@ private:
}
- void incrementBoolean() {
- check("bool bValue = true;\n"
- "void f() { bValue++; }");
- ASSERT_EQUALS("[test.cpp:2]: (style) Incrementing a variable of type 'bool' with postfix operator++ is deprecated by the C++ Standard. You should assign it the value 'true' instead.\n", errout.str());
-
- check("_Bool bValue = true;\n"
- "void f() { bValue++; }");
- ASSERT_EQUALS("[test.cpp:2]: (style) Incrementing a variable of type 'bool' with postfix operator++ is deprecated by the C++ Standard. You should assign it the value 'true' instead.\n", errout.str());
-
- check("void f(bool test){\n"
- " test++;\n"
- "}");
- ASSERT_EQUALS("[test.cpp:2]: (style) Incrementing a variable of type 'bool' with postfix operator++ is deprecated by the C++ Standard. You should assign it the value 'true' instead.\n", errout.str());
-
- check("void f(int test){\n"
- " test++;\n"
- "}");
- ASSERT_EQUALS("", errout.str());
- }
-
- void comparisonOfBoolWithInt1() {
- check("void f(bool x) {\n"
- " if (x < 10) {\n"
- " printf(\"foo\");\n"
- " }\n"
- "}");
- ASSERT_EQUALS("[test.cpp:2]: (warning) Comparison of a boolean with an integer.\n", errout.str());
-
- check("void f(bool x) {\n"
- " if (10 >= x) {\n"
- " printf(\"foo\");\n"
- " }\n"
- "}");
- ASSERT_EQUALS("[test.cpp:2]: (warning) Comparison of a boolean with an integer.\n", errout.str());
-
- check("void f(bool x) {\n"
- " if (x != 0) {\n"
- " printf(\"foo\");\n"
- " }\n"
- "}");
- ASSERT_EQUALS("", errout.str());
-
- check("void f(bool x) {\n" // #3356
- " if (x == 1) {\n"
- " }\n"
- "}");
- ASSERT_EQUALS("", errout.str());
-
- check("void f(bool x) {\n"
- " if (x != 10) {\n"
- " printf(\"foo\");\n"
- " }\n"
- "}");
- 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"
- " if (x == 10) {\n"
- " printf(\"foo\");\n"
- " }\n"
- "}");
- 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"
- " if (x == 0) {\n"
- " printf(\"foo\");\n"
- " }\n"
- "}");
- ASSERT_EQUALS("", errout.str());
-
- check("DensePropertyMap visited;"); // #4075
- ASSERT_EQUALS("", errout.str());
- }
-
- void comparisonOfBoolWithInt2() {
- check("void f(bool x, int y) {\n"
- " if (x == y) {\n"
- " printf(\"foo\");\n"
- " }\n"
- "}");
- ASSERT_EQUALS("[test.cpp:2]: (warning) Comparison of a boolean with an integer.\n", errout.str());
-
- check("void f(int x, bool y) {\n"
- " if (x == y) {\n"
- " printf(\"foo\");\n"
- " }\n"
- "}");
- ASSERT_EQUALS("[test.cpp:2]: (warning) Comparison of a boolean with an integer.\n", errout.str());
-
- check("void f(bool x, bool y) {\n"
- " if (x == y) {\n"
- " printf(\"foo\");\n"
- " }\n"
- "}");
- ASSERT_EQUALS("", errout.str());
-
- check("void f(bool x, fooClass y) {\n"
- " if (x == y) {\n"
- " printf(\"foo\");\n"
- " }\n"
- "}");
- ASSERT_EQUALS("", errout.str());
- }
-
- void comparisonOfBoolWithInt3() {
- check("void f(int y) {\n"
- " if (y > false) {\n"
- " printf(\"foo\");\n"
- " }\n"
- "}");
- ASSERT_EQUALS("[test.cpp:2]: (warning) Comparison of a boolean with an integer.\n", errout.str());
-
- check("void f(int y) {\n"
- " if (true == y) {\n"
- " printf(\"foo\");\n"
- " }\n"
- "}");
- ASSERT_EQUALS("[test.cpp:2]: (warning) Comparison of a boolean with an integer.\n", errout.str());
-
- check("void f(bool y) {\n"
- " if (y == true) {\n"
- " printf(\"foo\");\n"
- " }\n"
- "}");
- 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() {
- check("void f(int x) {\n"
- " if (!x == 1) { }\n"
- "}");
- ASSERT_EQUALS("", errout.str());
- }
-
- void comparisonOfBoolWithInt5() {
- check("void SetVisible(int index, bool visible) {\n"
- " bool (SciTEBase::*ischarforsel)(char ch);\n"
- " if (visible != GetVisible(index)) { }\n"
- "}");
- ASSERT_EQUALS("", errout.str());
- }
-
- void comparisonOfBoolWithInt6() { // #4224 - integer is casted to bool
- check("void SetVisible(bool b, int i) {\n"
- " if (b == (bool)i) { }\n"
- "}");
- ASSERT_EQUALS("", errout.str());
- }
-
void duplicateIf() {
check("void f(int a, int &b) {\n"
" if (a) { b = 1; }\n"
diff --git a/test/testrunner.vcxproj b/test/testrunner.vcxproj
index 3b3223bfe..204318eb7 100644
--- a/test/testrunner.vcxproj
+++ b/test/testrunner.vcxproj
@@ -33,6 +33,7 @@
+
diff --git a/test/testrunner.vcxproj.filters b/test/testrunner.vcxproj.filters
index 77fcfda72..6d3b86624 100644
--- a/test/testrunner.vcxproj.filters
+++ b/test/testrunner.vcxproj.filters
@@ -166,6 +166,9 @@
Source Files
+
+ Source Files
+