Moved checks related to boolean type (not condition checking!) from checkother into new file
This commit is contained in:
parent
4e6d105cbd
commit
42fcb04d0c
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
#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.");
|
||||
}
|
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
#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
|
|
@ -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
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -38,6 +38,7 @@
|
|||
<ClCompile Include="check64bit.cpp" />
|
||||
<ClCompile Include="checkassignif.cpp" />
|
||||
<ClCompile Include="checkautovariables.cpp" />
|
||||
<ClCompile Include="checkbool.cpp" />
|
||||
<ClCompile Include="checkboost.cpp" />
|
||||
<ClCompile Include="checkbufferoverrun.cpp" />
|
||||
<ClCompile Include="checkclass.cpp" />
|
||||
|
@ -75,6 +76,7 @@
|
|||
<ClInclude Include="check64bit.h" />
|
||||
<ClInclude Include="checkassignif.h" />
|
||||
<ClInclude Include="checkautovariables.h" />
|
||||
<ClInclude Include="checkbool.h" />
|
||||
<ClInclude Include="checkboost.h" />
|
||||
<ClInclude Include="checkbufferoverrun.h" />
|
||||
<ClInclude Include="checkclass.h" />
|
||||
|
|
|
@ -113,6 +113,9 @@
|
|||
<ClCompile Include="checkleakautovar.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="checkbool.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="checkbufferoverrun.h">
|
||||
|
@ -226,6 +229,9 @@
|
|||
<ClInclude Include="version.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="checkbool.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ResourceCompile Include="version.rc" />
|
||||
|
|
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
|
||||
#include "tokenize.h"
|
||||
#include "checkbool.h"
|
||||
#include "testsuite.h"
|
||||
#include <sstream>
|
||||
|
||||
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<int, true> 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)
|
|
@ -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<WS_CHILD|WS_VISIBLE>..
|
||||
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<int, true> 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"
|
||||
|
|
|
@ -33,6 +33,7 @@
|
|||
<ClCompile Include="test64bit.cpp" />
|
||||
<ClCompile Include="testassignif.cpp" />
|
||||
<ClCompile Include="testautovariables.cpp" />
|
||||
<ClCompile Include="testbool.cpp" />
|
||||
<ClCompile Include="testboost.cpp" />
|
||||
<ClCompile Include="testbufferoverrun.cpp" />
|
||||
<ClCompile Include="testcharvar.cpp" />
|
||||
|
|
|
@ -166,6 +166,9 @@
|
|||
<ClCompile Include="..\cli\cppcheckexecutor.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="testbool.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="options.h">
|
||||
|
|
Loading…
Reference in New Issue