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)++;'?");
|
"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()
|
void CheckOther::checkSuspiciousSemicolon()
|
||||||
{
|
{
|
||||||
|
@ -1805,93 +1730,6 @@ void CheckOther::sprintfOverlappingDataError(const Token *tok, const std::string
|
||||||
"to sprintf() or snprintf(), the results are undefined.\"");
|
"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.:
|
// Find consecutive return, break, continue, goto or throw statements. e.g.:
|
||||||
// break; break;
|
// break; break;
|
||||||
|
@ -2580,137 +2418,6 @@ void CheckOther::misusedScopeObjectError(const Token *tok, const std::string& va
|
||||||
"unusedScopedObject", "Instance of '" + varname + "' object is destroyed immediately.");
|
"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()
|
void CheckOther::checkIncorrectStringCompare()
|
||||||
|
@ -3675,98 +3382,6 @@ void CheckOther::divideSizeofError(const Token *tok)
|
||||||
"not the size of the memory area it points to.", true);
|
"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)) {
|
if (MathLib::toLongNumber(tok->linkAt(1)->strAt(-1)) == var->dimension(0)) {
|
||||||
unsigned int size = _tokenizer->sizeOfType(var->typeStartToken());
|
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)
|
if (warning)
|
||||||
incompleteArrayFillError(tok, var->name(), tok->str(), false);
|
incompleteArrayFillError(tok, var->name(), tok->str(), false);
|
||||||
} else if (var->typeStartToken()->str() == "bool" && portability) // sizeof(bool) is not 1 on all platforms
|
} else if (var->typeStartToken()->str() == "bool" && portability) // sizeof(bool) is not 1 on all platforms
|
||||||
|
|
|
@ -75,8 +75,6 @@ public:
|
||||||
checkOther.checkSuspiciousSemicolon();
|
checkOther.checkSuspiciousSemicolon();
|
||||||
checkOther.checkVariableScope();
|
checkOther.checkVariableScope();
|
||||||
checkOther.clarifyCondition(); // not simplified because ifAssign
|
checkOther.clarifyCondition(); // not simplified because ifAssign
|
||||||
checkOther.checkComparisonOfBoolExpressionWithInt();
|
|
||||||
checkOther.checkComparisonOfBoolWithInt();
|
|
||||||
checkOther.checkSignOfUnsignedVariable(); // don't ignore casts (#3574)
|
checkOther.checkSignOfUnsignedVariable(); // don't ignore casts (#3574)
|
||||||
checkOther.checkIncompleteArrayFill();
|
checkOther.checkIncompleteArrayFill();
|
||||||
checkOther.checkSuspiciousStringCompare();
|
checkOther.checkSuspiciousStringCompare();
|
||||||
|
@ -103,18 +101,13 @@ public:
|
||||||
checkOther.redundantGetAndSetUserId();
|
checkOther.redundantGetAndSetUserId();
|
||||||
checkOther.checkIncorrectLogicOperator();
|
checkOther.checkIncorrectLogicOperator();
|
||||||
checkOther.checkMisusedScopedObject();
|
checkOther.checkMisusedScopedObject();
|
||||||
checkOther.checkComparisonOfFuncReturningBool();
|
|
||||||
checkOther.checkComparisonOfBoolWithBool();
|
|
||||||
checkOther.checkMemsetZeroBytes();
|
checkOther.checkMemsetZeroBytes();
|
||||||
checkOther.checkIncorrectStringCompare();
|
checkOther.checkIncorrectStringCompare();
|
||||||
checkOther.checkIncrementBoolean();
|
|
||||||
checkOther.checkSwitchCaseFallThrough();
|
checkOther.checkSwitchCaseFallThrough();
|
||||||
checkOther.checkAlwaysTrueOrFalseStringCompare();
|
checkOther.checkAlwaysTrueOrFalseStringCompare();
|
||||||
checkOther.checkModuloAlwaysTrueFalse();
|
checkOther.checkModuloAlwaysTrueFalse();
|
||||||
checkOther.checkPipeParameterSize();
|
checkOther.checkPipeParameterSize();
|
||||||
|
|
||||||
checkOther.checkAssignBoolToPointer();
|
|
||||||
checkOther.checkBitwiseOnBoolean();
|
|
||||||
checkOther.checkInvalidFree();
|
checkOther.checkInvalidFree();
|
||||||
checkOther.checkDoubleFree();
|
checkOther.checkDoubleFree();
|
||||||
checkOther.checkRedundantCopy();
|
checkOther.checkRedundantCopy();
|
||||||
|
@ -217,12 +210,6 @@ public:
|
||||||
/** @brief %Check for objects that are destroyed immediately */
|
/** @brief %Check for objects that are destroyed immediately */
|
||||||
void checkMisusedScopedObject();
|
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() */
|
/** @brief %Check for filling zero bytes with memset() */
|
||||||
void checkMemsetZeroBytes();
|
void checkMemsetZeroBytes();
|
||||||
|
|
||||||
|
@ -241,12 +228,6 @@ public:
|
||||||
/** @brief %Check for comparison of a string literal with a char* variable */
|
/** @brief %Check for comparison of a string literal with a char* variable */
|
||||||
void checkSuspiciousStringCompare();
|
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) { }") */
|
/** @brief %Check for suspicious code where multiple if have the same expression (e.g "if (a) { } else if (a) { }") */
|
||||||
void checkDuplicateIf();
|
void checkDuplicateIf();
|
||||||
|
|
||||||
|
@ -265,18 +246,9 @@ public:
|
||||||
/** @brief %Check for code that gets never executed, such as duplicate break statements */
|
/** @brief %Check for code that gets never executed, such as duplicate break statements */
|
||||||
void checkUnreachableCode();
|
void checkUnreachableCode();
|
||||||
|
|
||||||
/** @brief assigning bool to pointer */
|
|
||||||
void checkAssignBoolToPointer();
|
|
||||||
|
|
||||||
/** @brief %Check for testing sign of unsigned variable */
|
/** @brief %Check for testing sign of unsigned variable */
|
||||||
void checkSignOfUnsignedVariable();
|
void checkSignOfUnsignedVariable();
|
||||||
|
|
||||||
/** @brief %Check for using bool in bitwise expression */
|
|
||||||
void checkBitwiseOnBoolean();
|
|
||||||
|
|
||||||
/** @brief %Check for comparing a bool expression with an integer other than 0 or 1 */
|
|
||||||
void checkComparisonOfBoolExpressionWithInt();
|
|
||||||
|
|
||||||
/** @brief %Check for suspicious use of semicolon */
|
/** @brief %Check for suspicious use of semicolon */
|
||||||
void checkSuspiciousSemicolon();
|
void checkSuspiciousSemicolon();
|
||||||
|
|
||||||
|
@ -353,18 +325,12 @@ private:
|
||||||
void incorrectLogicOperatorError(const Token *tok, const std::string &condition, bool always);
|
void incorrectLogicOperatorError(const Token *tok, const std::string &condition, bool always);
|
||||||
void redundantConditionError(const Token *tok, const std::string &text);
|
void redundantConditionError(const Token *tok, const std::string &text);
|
||||||
void misusedScopeObjectError(const Token *tok, const std::string &varname);
|
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 memsetZeroBytesError(const Token *tok, const std::string &varname);
|
||||||
void sizeofForArrayParameterError(const Token *tok);
|
void sizeofForArrayParameterError(const Token *tok);
|
||||||
void sizeofForPointerError(const Token *tok, const std::string &varname);
|
void sizeofForPointerError(const Token *tok, const std::string &varname);
|
||||||
void sizeofForNumericParameterError(const Token *tok);
|
void sizeofForNumericParameterError(const Token *tok);
|
||||||
void incorrectStringCompareError(const Token *tok, const std::string& func, const std::string &string);
|
void incorrectStringCompareError(const Token *tok, const std::string& func, const std::string &string);
|
||||||
void incorrectStringBooleanError(const Token *tok, 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 duplicateIfError(const Token *tok1, const Token *tok2);
|
||||||
void duplicateBranchError(const Token *tok1, const Token *tok2);
|
void duplicateBranchError(const Token *tok1, const Token *tok2);
|
||||||
void duplicateExpressionError(const Token *tok1, const Token *tok2, const std::string &op);
|
void duplicateExpressionError(const Token *tok1, const Token *tok2, const std::string &op);
|
||||||
|
@ -373,13 +339,10 @@ private:
|
||||||
void suspiciousStringCompareError(const Token* tok, const std::string& var);
|
void suspiciousStringCompareError(const Token* tok, const std::string& var);
|
||||||
void duplicateBreakError(const Token *tok, bool inconclusive);
|
void duplicateBreakError(const Token *tok, bool inconclusive);
|
||||||
void unreachableCodeError(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 unsignedLessThanZeroError(const Token *tok, const std::string &varname, bool inconclusive);
|
||||||
void pointerLessThanZeroError(const Token *tok, bool inconclusive);
|
void pointerLessThanZeroError(const Token *tok, bool inconclusive);
|
||||||
void unsignedPositiveError(const Token *tok, const std::string &varname, bool inconclusive);
|
void unsignedPositiveError(const Token *tok, const std::string &varname, bool inconclusive);
|
||||||
void pointerPositiveError(const Token *tok, 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 SuspiciousSemicolonError(const Token *tok);
|
||||||
void doubleCloseDirError(const Token *tok, const std::string &varname);
|
void doubleCloseDirError(const Token *tok, const std::string &varname);
|
||||||
void moduloAlwaysTrueFalseError(const Token* tok, const std::string& maxVal);
|
void moduloAlwaysTrueFalseError(const Token* tok, const std::string& maxVal);
|
||||||
|
@ -392,15 +355,11 @@ private:
|
||||||
CheckOther c(0, settings, errorLogger);
|
CheckOther c(0, settings, errorLogger);
|
||||||
|
|
||||||
// error
|
// error
|
||||||
c.assignBoolToPointerError(0);
|
|
||||||
c.sprintfOverlappingDataError(0, "varname");
|
c.sprintfOverlappingDataError(0, "varname");
|
||||||
c.udivError(0, false);
|
c.udivError(0, false);
|
||||||
c.zerodivError(0);
|
c.zerodivError(0);
|
||||||
c.mathfunctionCallError(0);
|
c.mathfunctionCallError(0);
|
||||||
c.misusedScopeObjectError(NULL, "varname");
|
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.sizeofForArrayParameterError(0);
|
||||||
c.sizeofForPointerError(0, "varname");
|
c.sizeofForPointerError(0, "varname");
|
||||||
c.sizeofForNumericParameterError(0);
|
c.sizeofForNumericParameterError(0);
|
||||||
|
@ -446,8 +405,6 @@ private:
|
||||||
c.incorrectStringCompareError(0, "substr", "\"Hello World\"");
|
c.incorrectStringCompareError(0, "substr", "\"Hello World\"");
|
||||||
c.suspiciousStringCompareError(0, "foo");
|
c.suspiciousStringCompareError(0, "foo");
|
||||||
c.incorrectStringBooleanError(0, "\"Hello World\"");
|
c.incorrectStringBooleanError(0, "\"Hello World\"");
|
||||||
c.incrementBooleanError(0);
|
|
||||||
c.comparisonOfBoolWithIntError(0, "varname", true);
|
|
||||||
c.duplicateIfError(0, 0);
|
c.duplicateIfError(0, 0);
|
||||||
c.duplicateBranchError(0, 0);
|
c.duplicateBranchError(0, 0);
|
||||||
c.duplicateExpressionError(0, 0, "&&");
|
c.duplicateExpressionError(0, 0, "&&");
|
||||||
|
@ -459,8 +416,6 @@ private:
|
||||||
c.unsignedPositiveError(0, "varname", false);
|
c.unsignedPositiveError(0, "varname", false);
|
||||||
c.pointerLessThanZeroError(0, false);
|
c.pointerLessThanZeroError(0, false);
|
||||||
c.pointerPositiveError(0, false);
|
c.pointerPositiveError(0, false);
|
||||||
c.bitwiseOnBooleanError(0, "varname", "&&");
|
|
||||||
c.comparisonOfBoolExpressionWithIntError(0, true);
|
|
||||||
c.SuspiciousSemicolonError(0);
|
c.SuspiciousSemicolonError(0);
|
||||||
c.cctypefunctionCallError(0, "funname", "value");
|
c.cctypefunctionCallError(0, "funname", "value");
|
||||||
c.moduloAlwaysTrueFalseError(0, "1");
|
c.moduloAlwaysTrueFalseError(0, "1");
|
||||||
|
@ -520,11 +475,6 @@ private:
|
||||||
"* Suspicious equality comparisons\n"
|
"* Suspicious equality comparisons\n"
|
||||||
"* mutual exclusion over || always evaluating to true\n"
|
"* mutual exclusion over || always evaluating to true\n"
|
||||||
"* Clarify calculation with parentheses\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 (assignment+comparison)\n"
|
||||||
"* suspicious condition (runtime comparison of string literals)\n"
|
"* suspicious condition (runtime comparison of string literals)\n"
|
||||||
"* suspicious condition (string literals as boolean)\n"
|
"* suspicious condition (string literals as boolean)\n"
|
||||||
|
@ -533,7 +483,6 @@ private:
|
||||||
"* unreachable code\n"
|
"* unreachable code\n"
|
||||||
"* testing if unsigned variable is negative\n"
|
"* testing if unsigned variable is negative\n"
|
||||||
"* testing is unsigned variable is positive\n"
|
"* testing is unsigned variable is positive\n"
|
||||||
"* using bool in bitwise expression\n"
|
|
||||||
"* Suspicious use of ; at the end of 'if/for/while' statement.\n"
|
"* Suspicious use of ; at the end of 'if/for/while' statement.\n"
|
||||||
"* incorrect usage of functions from ctype library.\n"
|
"* incorrect usage of functions from ctype library.\n"
|
||||||
"* Comparisons of modulo results that are always true/false.\n"
|
"* Comparisons of modulo results that are always true/false.\n"
|
||||||
|
|
|
@ -38,6 +38,7 @@
|
||||||
<ClCompile Include="check64bit.cpp" />
|
<ClCompile Include="check64bit.cpp" />
|
||||||
<ClCompile Include="checkassignif.cpp" />
|
<ClCompile Include="checkassignif.cpp" />
|
||||||
<ClCompile Include="checkautovariables.cpp" />
|
<ClCompile Include="checkautovariables.cpp" />
|
||||||
|
<ClCompile Include="checkbool.cpp" />
|
||||||
<ClCompile Include="checkboost.cpp" />
|
<ClCompile Include="checkboost.cpp" />
|
||||||
<ClCompile Include="checkbufferoverrun.cpp" />
|
<ClCompile Include="checkbufferoverrun.cpp" />
|
||||||
<ClCompile Include="checkclass.cpp" />
|
<ClCompile Include="checkclass.cpp" />
|
||||||
|
@ -75,6 +76,7 @@
|
||||||
<ClInclude Include="check64bit.h" />
|
<ClInclude Include="check64bit.h" />
|
||||||
<ClInclude Include="checkassignif.h" />
|
<ClInclude Include="checkassignif.h" />
|
||||||
<ClInclude Include="checkautovariables.h" />
|
<ClInclude Include="checkautovariables.h" />
|
||||||
|
<ClInclude Include="checkbool.h" />
|
||||||
<ClInclude Include="checkboost.h" />
|
<ClInclude Include="checkboost.h" />
|
||||||
<ClInclude Include="checkbufferoverrun.h" />
|
<ClInclude Include="checkbufferoverrun.h" />
|
||||||
<ClInclude Include="checkclass.h" />
|
<ClInclude Include="checkclass.h" />
|
||||||
|
|
|
@ -113,6 +113,9 @@
|
||||||
<ClCompile Include="checkleakautovar.cpp">
|
<ClCompile Include="checkleakautovar.cpp">
|
||||||
<Filter>Source Files</Filter>
|
<Filter>Source Files</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="checkbool.cpp">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="checkbufferoverrun.h">
|
<ClInclude Include="checkbufferoverrun.h">
|
||||||
|
@ -226,6 +229,9 @@
|
||||||
<ClInclude Include="version.h">
|
<ClInclude Include="version.h">
|
||||||
<Filter>Header Files</Filter>
|
<Filter>Header Files</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="checkbool.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ResourceCompile Include="version.rc" />
|
<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() {
|
void run() {
|
||||||
TEST_CASE(oppositeInnerCondition);
|
TEST_CASE(oppositeInnerCondition);
|
||||||
TEST_CASE(assignBoolToPointer);
|
|
||||||
TEST_CASE(emptyBrackets);
|
TEST_CASE(emptyBrackets);
|
||||||
|
|
||||||
TEST_CASE(zeroDiv1);
|
TEST_CASE(zeroDiv1);
|
||||||
|
@ -140,31 +139,9 @@ private:
|
||||||
TEST_CASE(clarifyCondition4); // ticket #3110
|
TEST_CASE(clarifyCondition4); // ticket #3110
|
||||||
TEST_CASE(clarifyCondition5); // #3609 CWinTraits<WS_CHILD|WS_VISIBLE>..
|
TEST_CASE(clarifyCondition5); // #3609 CWinTraits<WS_CHILD|WS_VISIBLE>..
|
||||||
TEST_CASE(clarifyCondition6); // #3818
|
TEST_CASE(clarifyCondition6); // #3818
|
||||||
TEST_CASE(bitwiseOnBoolean); // if (bool & bool)
|
|
||||||
|
|
||||||
TEST_CASE(comparisonOfBoolExpressionWithInt1);
|
|
||||||
TEST_CASE(comparisonOfBoolExpressionWithInt2);
|
|
||||||
TEST_CASE(comparisonOfBoolExpressionWithInt3);
|
|
||||||
|
|
||||||
TEST_CASE(incorrectStringCompare);
|
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(duplicateIf);
|
||||||
TEST_CASE(duplicateIf1); // ticket 3689
|
TEST_CASE(duplicateIf1); // ticket 3689
|
||||||
TEST_CASE(duplicateBranch);
|
TEST_CASE(duplicateBranch);
|
||||||
|
@ -324,14 +301,6 @@ private:
|
||||||
ASSERT_EQUALS("", errout.str());
|
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() {
|
void emptyBrackets() {
|
||||||
check("{\n"
|
check("{\n"
|
||||||
"}");
|
"}");
|
||||||
|
@ -3902,265 +3871,6 @@ private:
|
||||||
ASSERT_EQUALS("", errout.str());
|
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() {
|
void memsetZeroBytes() {
|
||||||
check("void f() {\n"
|
check("void f() {\n"
|
||||||
" memset(p, 10, 0x0);\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() {
|
void sizeofForNumericParameter() {
|
||||||
check("void f() {\n"
|
check("void f() {\n"
|
||||||
" std::cout << sizeof(10) << std::endl;\n"
|
" std::cout << sizeof(10) << std::endl;\n"
|
||||||
|
@ -4788,72 +4302,6 @@ private:
|
||||||
ASSERT_EQUALS("", errout.str());
|
ASSERT_EQUALS("", errout.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
void bitwiseOnBoolean() { // 3062
|
|
||||||
check("void f(_Bool a, _Bool b) {\n"
|
|
||||||
" if(a & b) {}\n"
|
|
||||||
"}");
|
|
||||||
ASSERT_EQUALS("[test.cpp:2]: (style, 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() {
|
void incorrectStringCompare() {
|
||||||
check("int f() {\n"
|
check("int f() {\n"
|
||||||
" return test.substr( 0 , 4 ) == \"Hello\" ? : 0 : 1 ;\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() {
|
void duplicateIf() {
|
||||||
check("void f(int a, int &b) {\n"
|
check("void f(int a, int &b) {\n"
|
||||||
" if (a) { b = 1; }\n"
|
" if (a) { b = 1; }\n"
|
||||||
|
|
|
@ -33,6 +33,7 @@
|
||||||
<ClCompile Include="test64bit.cpp" />
|
<ClCompile Include="test64bit.cpp" />
|
||||||
<ClCompile Include="testassignif.cpp" />
|
<ClCompile Include="testassignif.cpp" />
|
||||||
<ClCompile Include="testautovariables.cpp" />
|
<ClCompile Include="testautovariables.cpp" />
|
||||||
|
<ClCompile Include="testbool.cpp" />
|
||||||
<ClCompile Include="testboost.cpp" />
|
<ClCompile Include="testboost.cpp" />
|
||||||
<ClCompile Include="testbufferoverrun.cpp" />
|
<ClCompile Include="testbufferoverrun.cpp" />
|
||||||
<ClCompile Include="testcharvar.cpp" />
|
<ClCompile Include="testcharvar.cpp" />
|
||||||
|
|
|
@ -166,6 +166,9 @@
|
||||||
<ClCompile Include="..\cli\cppcheckexecutor.cpp">
|
<ClCompile Include="..\cli\cppcheckexecutor.cpp">
|
||||||
<Filter>Source Files</Filter>
|
<Filter>Source Files</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="testbool.cpp">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="options.h">
|
<ClInclude Include="options.h">
|
||||||
|
|
Loading…
Reference in New Issue