Moved checks related to boolean type (not condition checking!) from checkother into new file

This commit is contained in:
PKEuS 2013-04-10 09:25:50 -07:00
parent 4e6d105cbd
commit 42fcb04d0c
10 changed files with 1332 additions and 1144 deletions

417
lib/checkbool.cpp Normal file
View File

@ -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.");
}

134
lib/checkbool.h Normal file
View File

@ -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

View File

@ -111,40 +111,6 @@ void CheckOther::checkCastIntToCharAndBackError(const Token *tok, const std::str
);
}
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
void CheckOther::checkIncrementBoolean()
{
if (!_settings->isEnabled("style"))
return;
const SymbolDatabase *symbolDatabase = _tokenizer->getSymbolDatabase();
const std::size_t functions = symbolDatabase->functionScopes.size();
for (std::size_t i = 0; i < functions; ++i) {
const Scope * scope = symbolDatabase->functionScopes[i];
for (const Token* tok = scope->classStart->next(); tok != scope->classEnd; tok = tok->next()) {
if (Token::Match(tok, "%var% ++")) {
if (tok->varId()) {
const Variable *var = tok->variable();
if (var && var->typeEndToken()->str() == "bool")
incrementBooleanError(tok);
}
}
}
}
}
void CheckOther::incrementBooleanError(const Token *tok)
{
reportError(
tok,
Severity::style,
"incrementboolean",
"Incrementing a variable of type 'bool' with postfix operator++ is deprecated by the C++ Standard. You should assign it the value 'true' instead.\n"
"The operand of a postfix increment operator may be of type bool but it is deprecated by C++ Standard (Annex D-1) and the operand is always set to true. You should assign it the value 'true' instead."
);
}
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
@ -373,47 +339,6 @@ void CheckOther::clarifyStatementError(const Token *tok)
"Thus, the dereference is meaningless. Did you intend to write '(*A)++;'?");
}
//---------------------------------------------------------------------------
// if (bool & bool) -> if (bool && bool)
// if (bool | bool) -> if (bool || bool)
//---------------------------------------------------------------------------
void CheckOther::checkBitwiseOnBoolean()
{
if (!_settings->isEnabled("style"))
return;
// danmar: this is inconclusive because I don't like that there are
// warnings for calculations. Example: set_flag(a & b);
if (!_settings->inconclusive)
return;
const SymbolDatabase *symbolDatabase = _tokenizer->getSymbolDatabase();
const std::size_t functions = symbolDatabase->functionScopes.size();
for (std::size_t i = 0; i < functions; ++i) {
const Scope * scope = symbolDatabase->functionScopes[i];
for (const Token* tok = scope->classStart->next(); tok != scope->classEnd; tok = tok->next()) {
if (Token::Match(tok, "(|.|return|&&|%oror%|throw|, %var% [&|]")) {
const Variable *var = tok->next()->variable();
if (var && var->typeEndToken()->str() == "bool") {
bitwiseOnBooleanError(tok->next(), var->name(), tok->strAt(2) == "&" ? "&&" : "||");
tok = tok->tokAt(2);
}
} else if (Token::Match(tok, "[&|] %var% )|.|return|&&|%oror%|throw|,") && (!tok->previous() || !tok->previous()->isExtendedOp() || tok->strAt(-1) == ")" || tok->strAt(-1) == "]")) {
const Variable *var = tok->next()->variable();
if (var && var->typeEndToken()->str() == "bool") {
bitwiseOnBooleanError(tok->next(), var->name(), tok->str() == "&" ? "&&" : "||");
tok = tok->tokAt(2);
}
}
}
}
}
void CheckOther::bitwiseOnBooleanError(const Token *tok, const std::string &varname, const std::string &op)
{
reportError(tok, Severity::style, "bitwiseOnBoolean",
"Boolean variable '" + varname + "' is used in bitwise operation. Did you mean '" + op + "'?", true);
}
void CheckOther::checkSuspiciousSemicolon()
{
@ -1805,93 +1730,6 @@ void CheckOther::sprintfOverlappingDataError(const Token *tok, const std::string
"to sprintf() or snprintf(), the results are undefined.\"");
}
//---------------------------------------------------------------------------
// if (!x==3) <- Probably meant to be "x!=3"
//---------------------------------------------------------------------------
static bool isBool(const Variable* var)
{
return(var && var->typeEndToken()->str() == "bool");
}
static bool isNonBoolStdType(const Variable* var)
{
return(var && var->typeEndToken()->isStandardType() && var->typeEndToken()->str() != "bool");
}
void CheckOther::checkComparisonOfBoolWithInt()
{
if (!_settings->isEnabled("warning"))
return;
const SymbolDatabase* const symbolDatabase = _tokenizer->getSymbolDatabase();
const std::size_t functions = symbolDatabase->functionScopes.size();
for (std::size_t i = 0; i < functions; ++i) {
const Scope * scope = symbolDatabase->functionScopes[i];
for (const Token* tok = scope->classStart->next(); tok != scope->classEnd; tok = tok->next()) {
if (tok->next() && tok->next()->type() == Token::eComparisonOp && (!tok->previous() || !tok->previous()->isArithmeticalOp()) && (!tok->tokAt(3) || !tok->tokAt(3)->isArithmeticalOp())) {
const Token* const right = tok->tokAt(2);
if ((tok->varId() && right->isNumber()) || (tok->isNumber() && right->varId())) { // Comparing variable with number
const Token* varTok = tok;
const Token* numTok = right;
if (tok->isNumber() && right->varId()) // num with var
std::swap(varTok, numTok);
if (isBool(varTok->variable()) && // Variable has to be a boolean
((tok->strAt(1) != "==" && tok->strAt(1) != "!=") ||
(MathLib::toLongNumber(numTok->str()) != 0 && MathLib::toLongNumber(numTok->str()) != 1))) { // == 0 and != 0 are allowed, for C also == 1 and != 1
comparisonOfBoolWithIntError(varTok, numTok->str(), tok->strAt(1) == "==" || tok->strAt(1) == "!=");
}
} else if (tok->isBoolean() && right->varId()) { // Comparing boolean constant with variable
if (isNonBoolStdType(right->variable())) { // Variable has to be of non-boolean standard type
comparisonOfBoolWithIntError(right, tok->str(), false);
} else if (tok->strAt(1) != "==" && tok->strAt(1) != "!=") {
comparisonOfBoolWithInvalidComparator(right, tok->str());
}
} else if (tok->varId() && right->isBoolean()) { // Comparing variable with boolean constant
if (isNonBoolStdType(tok->variable())) { // Variable has to be of non-boolean standard type
comparisonOfBoolWithIntError(tok, right->str(), false);
} else if (tok->strAt(1) != "==" && tok->strAt(1) != "!=") {
comparisonOfBoolWithInvalidComparator(right, tok->str());
}
} else if (tok->isNumber() && right->isBoolean()) { // number constant with boolean constant
comparisonOfBoolWithIntError(tok, right->str(), false);
} else if (tok->isBoolean() && right->isNumber()) { // number constant with boolean constant
comparisonOfBoolWithIntError(tok, tok->str(), false);
} else if (tok->varId() && right->varId()) { // Comparing two variables, one of them boolean, one of them integer
const Variable* var1 = right->variable();
const Variable* var2 = tok->variable();
if (isBool(var1) && isNonBoolStdType(var2)) // Comparing boolean with non-bool standard type
comparisonOfBoolWithIntError(tok, var1->name(), false);
else if (isNonBoolStdType(var1) && isBool(var2)) // Comparing non-bool standard type with boolean
comparisonOfBoolWithIntError(tok, var2->name(), false);
}
}
}
}
}
void CheckOther::comparisonOfBoolWithIntError(const Token *tok, const std::string &expression, bool n0o1)
{
if (n0o1)
reportError(tok, Severity::warning, "comparisonOfBoolWithInt",
"Comparison of a boolean with an integer that is neither 1 nor 0.\n"
"The expression '" + expression + "' is of type 'bool' "
"and it is compared against an integer value that is "
"neither 1 nor 0.");
else
reportError(tok, Severity::warning, "comparisonOfBoolWithInt",
"Comparison of a boolean with an integer.\n"
"The expression '" + expression + "' is of type 'bool' "
"and it is compared against an integer value.");
}
void CheckOther::comparisonOfBoolWithInvalidComparator(const Token *tok, const std::string &expression)
{
reportError(tok, Severity::warning, "comparisonOfBoolWithInvalidComparator",
"Comparison of a boolean value using relational operator (<, >, <= or >=).\n"
"The result of the expression '" + expression + "' is of type 'bool'. "
"Comparing 'bool' value using relational (<, >, <= or >=)"
" operator could cause unexpected results.");
}
//---------------------------------------------------------------------------
// Find consecutive return, break, continue, goto or throw statements. e.g.:
// break; break;
@ -2580,137 +2418,6 @@ void CheckOther::misusedScopeObjectError(const Token *tok, const std::string& va
"unusedScopedObject", "Instance of '" + varname + "' object is destroyed immediately.");
}
//-------------------------------------------------------------------------------
// Comparing functions which are returning value of type bool
//-------------------------------------------------------------------------------
void CheckOther::checkComparisonOfFuncReturningBool()
{
if (!_settings->isEnabled("style"))
return;
if (!_tokenizer->isCPP())
return;
const SymbolDatabase * const symbolDatabase = _tokenizer->getSymbolDatabase();
const std::size_t functions = symbolDatabase->functionScopes.size();
for (std::size_t i = 0; i < functions; ++i) {
const Scope * scope = symbolDatabase->functionScopes[i];
for (const Token* tok = scope->classStart->next(); tok != scope->classEnd; tok = tok->next()) {
if (tok->type() != Token::eComparisonOp || tok->str() == "==" || tok->str() == "!=")
continue;
const Token *first_token;
bool first_token_func_of_type_bool = false;
if (tok->strAt(-1) == ")") {
first_token = tok->previous()->link()->previous();
} else {
first_token = tok->previous();
}
if (Token::Match(first_token, "%var% (") && !Token::Match(first_token->previous(), "::|.")) {
const Function* func = first_token->function();
if (func && func->tokenDef && func->tokenDef->strAt(-1) == "bool") {
first_token_func_of_type_bool = true;
}
}
Token *second_token = tok->next();
bool second_token_func_of_type_bool = false;
while (second_token->str()=="!") {
second_token = second_token->next();
}
if (Token::Match(second_token, "%var% (") && !Token::Match(second_token->previous(), "::|.")) {
const Function* func = second_token->function();
if (func && func->tokenDef && func->tokenDef->strAt(-1) == "bool") {
second_token_func_of_type_bool = true;
}
}
if ((first_token_func_of_type_bool == true) && (second_token_func_of_type_bool == true)) {
comparisonOfTwoFuncsReturningBoolError(first_token->next(), first_token->str(), second_token->str());
} else if (first_token_func_of_type_bool == true) {
comparisonOfFuncReturningBoolError(first_token->next(), first_token->str());
} else if (second_token_func_of_type_bool == true) {
comparisonOfFuncReturningBoolError(second_token->previous(), second_token->str());
}
}
}
}
void CheckOther::comparisonOfFuncReturningBoolError(const Token *tok, const std::string &expression)
{
reportError(tok, Severity::style, "comparisonOfFuncReturningBoolError",
"Comparison of a function returning boolean value using relational (<, >, <= or >=) operator.\n"
"The return type of function '" + expression + "' is 'bool' "
"and result is of type 'bool'. Comparing 'bool' value using relational (<, >, <= or >=)"
" operator could cause unexpected results.");
}
void CheckOther::comparisonOfTwoFuncsReturningBoolError(const Token *tok, const std::string &expression1, const std::string &expression2)
{
reportError(tok, Severity::style, "comparisonOfTwoFuncsReturningBoolError",
"Comparison of two functions returning boolean value using relational (<, >, <= or >=) operator.\n"
"The return type of function '" + expression1 + "' and function '" + expression2 + "' is 'bool' "
"and result is of type 'bool'. Comparing 'bool' value using relational (<, >, <= or >=)"
" operator could cause unexpected results.");
}
//-------------------------------------------------------------------------------
// Comparison of bool with bool
//-------------------------------------------------------------------------------
void CheckOther::checkComparisonOfBoolWithBool()
{
// FIXME: This checking is "experimental" because of the false positives
// when self checking lib/tokenize.cpp (#2617)
if (!_settings->experimental)
return;
if (!_settings->isEnabled("style"))
return;
if (!_tokenizer->isCPP())
return;
const SymbolDatabase* const symbolDatabase = _tokenizer->getSymbolDatabase();
const std::size_t functions = symbolDatabase->functionScopes.size();
for (std::size_t i = 0; i < functions; ++i) {
const Scope * scope = symbolDatabase->functionScopes[i];
for (const Token* tok = scope->classStart->next(); tok != scope->classEnd; tok = tok->next()) {
if (tok->type() != Token::eComparisonOp || tok->str() == "==" || tok->str() == "!=")
continue;
bool first_token_bool = false;
bool second_token_bool = false;
const Token *first_token = tok->previous();
if (first_token->varId()) {
if (isBool(first_token->variable())) {
first_token_bool = true;
}
}
const Token *second_token = tok->next();
if (second_token->varId()) {
if (isBool(second_token->variable())) {
second_token_bool = true;
}
}
if ((first_token_bool == true) && (second_token_bool == true)) {
comparisonOfBoolWithBoolError(first_token->next(), first_token->str());
}
}
}
}
void CheckOther::comparisonOfBoolWithBoolError(const Token *tok, const std::string &expression)
{
reportError(tok, Severity::style, "comparisonOfBoolWithBoolError",
"Comparison of a variable having boolean value using relational (<, >, <= or >=) operator.\n"
"The variable '" + expression + "' is of type 'bool' "
"and comparing 'bool' value using relational (<, >, <= or >=)"
" operator could cause unexpected results.");
}
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
void CheckOther::checkIncorrectStringCompare()
@ -3675,98 +3382,6 @@ void CheckOther::divideSizeofError(const Token *tok)
"not the size of the memory area it points to.", true);
}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
void CheckOther::checkAssignBoolToPointer()
{
const SymbolDatabase *symbolDatabase = _tokenizer->getSymbolDatabase();
const std::size_t functions = symbolDatabase->functionScopes.size();
for (std::size_t i = 0; i < functions; ++i) {
const Scope * scope = symbolDatabase->functionScopes[i];
for (const Token* tok = scope->classStart; tok != scope->classEnd; tok = tok->next()) {
if (Token::Match(tok, "!!* %var% = %bool% ;")) {
const Variable *var1(tok->next()->variable());
// Is variable a pointer?
if (var1 && var1->isPointer())
assignBoolToPointerError(tok->next());
}
}
}
}
void CheckOther::assignBoolToPointerError(const Token *tok)
{
reportError(tok, Severity::error, "assignBoolToPointer",
"Boolean value assigned to pointer.");
}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
void CheckOther::checkComparisonOfBoolExpressionWithInt()
{
if (!_settings->isEnabled("warning"))
return;
const SymbolDatabase* symbolDatabase = _tokenizer->getSymbolDatabase();
const std::size_t functions = symbolDatabase->functionScopes.size();
for (std::size_t i = 0; i < functions; ++i) {
const Scope * scope = symbolDatabase->functionScopes[i];
for (const Token* tok = scope->classStart->next(); tok != scope->classEnd; tok = tok->next()) {
// Skip template parameters
if (tok->str() == "<" && tok->link()) {
tok = tok->link();
continue;
}
const Token* numTok = 0;
const Token* opTok = 0;
char op = 0;
if (Token::Match(tok, "&&|%oror% %any% ) %comp% %any%")) {
numTok = tok->tokAt(4);
opTok = tok->tokAt(3);
if (Token::Match(opTok, "<|>"))
op = opTok->str()[0];
} else if (Token::Match(tok, "%any% %comp% ( %any% &&|%oror%")) {
numTok = tok;
opTok = tok->next();
if (Token::Match(opTok, "<|>"))
op = opTok->str()[0]=='>'?'<':'>';
}
else if (Token::Match(tok, "! %var% %comp% %any%")) {
numTok = tok->tokAt(3);
opTok = tok->tokAt(2);
if (Token::Match(opTok, "<|>"))
op = opTok->str()[0];
} else if (Token::Match(tok, "%any% %comp% ! %var%")) {
numTok = tok;
opTok = tok->next();
if (Token::Match(opTok, "<|>"))
op = opTok->str()[0]=='>'?'<':'>';
}
if (numTok && opTok) {
if (numTok->isNumber()) {
if (((numTok->str() != "0" && numTok->str() != "1") || !Token::Match(opTok, "!=|==")) && !((op == '<' && numTok->str() == "1") || (op == '>' && numTok->str() == "0")))
comparisonOfBoolExpressionWithIntError(tok, true);
} else if (isNonBoolStdType(numTok->variable()))
comparisonOfBoolExpressionWithIntError(tok, false);
}
}
}
}
void CheckOther::comparisonOfBoolExpressionWithIntError(const Token *tok, bool n0o1)
{
if (n0o1)
reportError(tok, Severity::warning, "compareBoolExpressionWithInt",
"Comparison of a boolean expression with an integer other than 0 or 1.");
else
reportError(tok, Severity::warning, "compareBoolExpressionWithInt",
"Comparison of a boolean expression with an integer.");
}
//---------------------------------------------------------------------------
@ -3965,7 +3580,7 @@ void CheckOther::checkIncompleteArrayFill()
if (MathLib::toLongNumber(tok->linkAt(1)->strAt(-1)) == var->dimension(0)) {
unsigned int size = _tokenizer->sizeOfType(var->typeStartToken());
if ((size != 1 && size != 100 && size != 0) || var->typeEndToken()->str() == "*") {
if ((size != 1 && size != 100 && size != 0) || var->isPointer()) {
if (warning)
incompleteArrayFillError(tok, var->name(), tok->str(), false);
} else if (var->typeStartToken()->str() == "bool" && portability) // sizeof(bool) is not 1 on all platforms

View File

@ -75,8 +75,6 @@ public:
checkOther.checkSuspiciousSemicolon();
checkOther.checkVariableScope();
checkOther.clarifyCondition(); // not simplified because ifAssign
checkOther.checkComparisonOfBoolExpressionWithInt();
checkOther.checkComparisonOfBoolWithInt();
checkOther.checkSignOfUnsignedVariable(); // don't ignore casts (#3574)
checkOther.checkIncompleteArrayFill();
checkOther.checkSuspiciousStringCompare();
@ -103,18 +101,13 @@ public:
checkOther.redundantGetAndSetUserId();
checkOther.checkIncorrectLogicOperator();
checkOther.checkMisusedScopedObject();
checkOther.checkComparisonOfFuncReturningBool();
checkOther.checkComparisonOfBoolWithBool();
checkOther.checkMemsetZeroBytes();
checkOther.checkIncorrectStringCompare();
checkOther.checkIncrementBoolean();
checkOther.checkSwitchCaseFallThrough();
checkOther.checkAlwaysTrueOrFalseStringCompare();
checkOther.checkModuloAlwaysTrueFalse();
checkOther.checkPipeParameterSize();
checkOther.checkAssignBoolToPointer();
checkOther.checkBitwiseOnBoolean();
checkOther.checkInvalidFree();
checkOther.checkDoubleFree();
checkOther.checkRedundantCopy();
@ -217,12 +210,6 @@ public:
/** @brief %Check for objects that are destroyed immediately */
void checkMisusedScopedObject();
/** @brief %Check for comparison of function returning bool*/
void checkComparisonOfFuncReturningBool();
/** @brief %Check for comparison of variable of type bool*/
void checkComparisonOfBoolWithBool();
/** @brief %Check for filling zero bytes with memset() */
void checkMemsetZeroBytes();
@ -241,12 +228,6 @@ public:
/** @brief %Check for comparison of a string literal with a char* variable */
void checkSuspiciousStringCompare();
/** @brief %Check for using postfix increment on bool */
void checkIncrementBoolean();
/** @brief %Check for suspicious comparison of a bool and a non-zero (and non-one) value (e.g. "if (!x==4)") */
void checkComparisonOfBoolWithInt();
/** @brief %Check for suspicious code where multiple if have the same expression (e.g "if (a) { } else if (a) { }") */
void checkDuplicateIf();
@ -265,18 +246,9 @@ public:
/** @brief %Check for code that gets never executed, such as duplicate break statements */
void checkUnreachableCode();
/** @brief assigning bool to pointer */
void checkAssignBoolToPointer();
/** @brief %Check for testing sign of unsigned variable */
void checkSignOfUnsignedVariable();
/** @brief %Check for using bool in bitwise expression */
void checkBitwiseOnBoolean();
/** @brief %Check for comparing a bool expression with an integer other than 0 or 1 */
void checkComparisonOfBoolExpressionWithInt();
/** @brief %Check for suspicious use of semicolon */
void checkSuspiciousSemicolon();
@ -353,18 +325,12 @@ private:
void incorrectLogicOperatorError(const Token *tok, const std::string &condition, bool always);
void redundantConditionError(const Token *tok, const std::string &text);
void misusedScopeObjectError(const Token *tok, const std::string &varname);
void comparisonOfFuncReturningBoolError(const Token *tok, const std::string &expression);
void comparisonOfTwoFuncsReturningBoolError(const Token *tok, const std::string &expression1, const std::string &expression2);
void comparisonOfBoolWithBoolError(const Token *tok, const std::string &expression);
void memsetZeroBytesError(const Token *tok, const std::string &varname);
void sizeofForArrayParameterError(const Token *tok);
void sizeofForPointerError(const Token *tok, const std::string &varname);
void sizeofForNumericParameterError(const Token *tok);
void incorrectStringCompareError(const Token *tok, const std::string& func, const std::string &string);
void incorrectStringBooleanError(const Token *tok, const std::string& string);
void incrementBooleanError(const Token *tok);
void comparisonOfBoolWithIntError(const Token *tok, const std::string &expression, bool n0o1);
void comparisonOfBoolWithInvalidComparator(const Token *tok, const std::string &expression);
void duplicateIfError(const Token *tok1, const Token *tok2);
void duplicateBranchError(const Token *tok1, const Token *tok2);
void duplicateExpressionError(const Token *tok1, const Token *tok2, const std::string &op);
@ -373,13 +339,10 @@ private:
void suspiciousStringCompareError(const Token* tok, const std::string& var);
void duplicateBreakError(const Token *tok, bool inconclusive);
void unreachableCodeError(const Token* tok, bool inconclusive);
void assignBoolToPointerError(const Token *tok);
void unsignedLessThanZeroError(const Token *tok, const std::string &varname, bool inconclusive);
void pointerLessThanZeroError(const Token *tok, bool inconclusive);
void unsignedPositiveError(const Token *tok, const std::string &varname, bool inconclusive);
void pointerPositiveError(const Token *tok, bool inconclusive);
void bitwiseOnBooleanError(const Token *tok, const std::string &varname, const std::string &op);
void comparisonOfBoolExpressionWithIntError(const Token *tok, bool n0o1);
void SuspiciousSemicolonError(const Token *tok);
void doubleCloseDirError(const Token *tok, const std::string &varname);
void moduloAlwaysTrueFalseError(const Token* tok, const std::string& maxVal);
@ -392,15 +355,11 @@ private:
CheckOther c(0, settings, errorLogger);
// error
c.assignBoolToPointerError(0);
c.sprintfOverlappingDataError(0, "varname");
c.udivError(0, false);
c.zerodivError(0);
c.mathfunctionCallError(0);
c.misusedScopeObjectError(NULL, "varname");
c.comparisonOfFuncReturningBoolError(0, "func_name");
c.comparisonOfTwoFuncsReturningBoolError(0, "func_name1", "func_name2");
c.comparisonOfBoolWithBoolError(0, "var_name");
c.sizeofForArrayParameterError(0);
c.sizeofForPointerError(0, "varname");
c.sizeofForNumericParameterError(0);
@ -446,8 +405,6 @@ private:
c.incorrectStringCompareError(0, "substr", "\"Hello World\"");
c.suspiciousStringCompareError(0, "foo");
c.incorrectStringBooleanError(0, "\"Hello World\"");
c.incrementBooleanError(0);
c.comparisonOfBoolWithIntError(0, "varname", true);
c.duplicateIfError(0, 0);
c.duplicateBranchError(0, 0);
c.duplicateExpressionError(0, 0, "&&");
@ -459,8 +416,6 @@ private:
c.unsignedPositiveError(0, "varname", false);
c.pointerLessThanZeroError(0, false);
c.pointerPositiveError(0, false);
c.bitwiseOnBooleanError(0, "varname", "&&");
c.comparisonOfBoolExpressionWithIntError(0, true);
c.SuspiciousSemicolonError(0);
c.cctypefunctionCallError(0, "funname", "value");
c.moduloAlwaysTrueFalseError(0, "1");
@ -520,11 +475,6 @@ private:
"* Suspicious equality comparisons\n"
"* mutual exclusion over || always evaluating to true\n"
"* Clarify calculation with parentheses\n"
"* using increment on boolean\n"
"* comparison of a boolean with a non-zero integer\n"
"* comparison of a boolean expression with an integer other than 0 or 1\n"
"* comparison of a function returning boolean value using relational operator\n"
"* comparison of a boolean value with boolean value using relational operator\n"
"* suspicious condition (assignment+comparison)\n"
"* suspicious condition (runtime comparison of string literals)\n"
"* suspicious condition (string literals as boolean)\n"
@ -533,7 +483,6 @@ private:
"* unreachable code\n"
"* testing if unsigned variable is negative\n"
"* testing is unsigned variable is positive\n"
"* using bool in bitwise expression\n"
"* Suspicious use of ; at the end of 'if/for/while' statement.\n"
"* incorrect usage of functions from ctype library.\n"
"* Comparisons of modulo results that are always true/false.\n"

View File

@ -38,6 +38,7 @@
<ClCompile Include="check64bit.cpp" />
<ClCompile Include="checkassignif.cpp" />
<ClCompile Include="checkautovariables.cpp" />
<ClCompile Include="checkbool.cpp" />
<ClCompile Include="checkboost.cpp" />
<ClCompile Include="checkbufferoverrun.cpp" />
<ClCompile Include="checkclass.cpp" />
@ -75,6 +76,7 @@
<ClInclude Include="check64bit.h" />
<ClInclude Include="checkassignif.h" />
<ClInclude Include="checkautovariables.h" />
<ClInclude Include="checkbool.h" />
<ClInclude Include="checkboost.h" />
<ClInclude Include="checkbufferoverrun.h" />
<ClInclude Include="checkclass.h" />

View File

@ -113,6 +113,9 @@
<ClCompile Include="checkleakautovar.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="checkbool.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="checkbufferoverrun.h">
@ -226,6 +229,9 @@
<ClInclude Include="version.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="checkbool.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="version.rc" />

768
test/testbool.cpp Normal file
View File

@ -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)

View File

@ -34,7 +34,6 @@ private:
void run() {
TEST_CASE(oppositeInnerCondition);
TEST_CASE(assignBoolToPointer);
TEST_CASE(emptyBrackets);
TEST_CASE(zeroDiv1);
@ -140,31 +139,9 @@ private:
TEST_CASE(clarifyCondition4); // ticket #3110
TEST_CASE(clarifyCondition5); // #3609 CWinTraits<WS_CHILD|WS_VISIBLE>..
TEST_CASE(clarifyCondition6); // #3818
TEST_CASE(bitwiseOnBoolean); // if (bool & bool)
TEST_CASE(comparisonOfBoolExpressionWithInt1);
TEST_CASE(comparisonOfBoolExpressionWithInt2);
TEST_CASE(comparisonOfBoolExpressionWithInt3);
TEST_CASE(incorrectStringCompare);
TEST_CASE(incrementBoolean);
TEST_CASE(comparisonOfBoolWithInt1);
TEST_CASE(comparisonOfBoolWithInt2);
TEST_CASE(comparisonOfBoolWithInt3);
TEST_CASE(comparisonOfBoolWithInt4);
TEST_CASE(comparisonOfBoolWithInt5);
TEST_CASE(comparisonOfBoolWithInt6); // #4224 - integer is casted to bool
TEST_CASE(checkComparisonOfFuncReturningBool1);
TEST_CASE(checkComparisonOfFuncReturningBool2);
TEST_CASE(checkComparisonOfFuncReturningBool3);
TEST_CASE(checkComparisonOfFuncReturningBool4);
TEST_CASE(checkComparisonOfFuncReturningBool5);
TEST_CASE(checkComparisonOfFuncReturningBool6);
TEST_CASE(checkComparisonOfBoolWithBool);
TEST_CASE(duplicateIf);
TEST_CASE(duplicateIf1); // ticket 3689
TEST_CASE(duplicateBranch);
@ -324,14 +301,6 @@ private:
ASSERT_EQUALS("", errout.str());
}
void assignBoolToPointer() {
check("void foo(bool *p) {\n"
" p = false;\n"
"}");
ASSERT_EQUALS("[test.cpp:2]: (error) Boolean value assigned to pointer.\n", errout.str());
}
void emptyBrackets() {
check("{\n"
"}");
@ -3902,265 +3871,6 @@ private:
ASSERT_EQUALS("", errout.str());
}
void comparisonOfBoolExpressionWithInt1() {
check("void f(int x) {\n"
" if ((x && 0x0f)==6)\n"
" a++;\n"
"}\n"
);
ASSERT_EQUALS("[test.cpp:2]: (warning) Comparison of a boolean expression with an integer other than 0 or 1.\n", errout.str());
check("void f(int x) {\n"
" if ((x && 0x0f)==0)\n"
" a++;\n"
"}\n"
);
ASSERT_EQUALS("", errout.str());
check("void f(int x) {\n"
" if ((x || 0x0f)==6)\n"
" a++;\n"
"}\n"
);
ASSERT_EQUALS("[test.cpp:2]: (warning) Comparison of a boolean expression with an integer other than 0 or 1.\n", errout.str());
check("void f(int x) {\n"
" if ((x || 0x0f)==0)\n"
" a++;\n"
"}\n"
);
ASSERT_EQUALS("", errout.str());
check("void f(int x) {\n"
" if ((x & 0x0f)==6)\n"
" a++;\n"
"}\n"
);
ASSERT_EQUALS("", errout.str());
check("void f(int x) {\n"
" if ((x | 0x0f)==6)\n"
" a++;\n"
"}\n"
);
ASSERT_EQUALS("", errout.str());
check("void f(int x) {\n"
" if ((5 && x)==3)\n"
" a++;\n"
"}\n"
);
ASSERT_EQUALS("[test.cpp:2]: (warning) Comparison of a boolean expression with an integer other than 0 or 1.\n", errout.str());
check("void f(int x) {\n"
" if ((5 && x)==3 || (8 && x)==9)\n"
" a++;\n"
"}\n"
);
ASSERT_EQUALS("[test.cpp:2]: (warning) Comparison of a boolean expression with an integer other than 0 or 1.\n", errout.str());
check("void f(int x) {\n"
" if ((5 && x)!=3)\n"
" a++;\n"
"}\n"
);
ASSERT_EQUALS("[test.cpp:2]: (warning) Comparison of a boolean expression with an integer other than 0 or 1.\n", errout.str());
check("void f(int x) {\n"
" if ((5 && x) > 3)\n"
" a++;\n"
"}\n"
);
ASSERT_EQUALS("[test.cpp:2]: (warning) Comparison of a boolean expression with an integer other than 0 or 1.\n", errout.str());
check("void f(int x) {\n"
" if ((5 && x) > 0)\n"
" a++;\n"
"}\n"
);
ASSERT_EQUALS("", errout.str());
check("void f(int x) {\n"
" if ((5 && x) < 0)\n"
" a++;\n"
"}\n"
);
ASSERT_EQUALS("[test.cpp:2]: (warning) Comparison of a boolean expression with an integer other than 0 or 1.\n", errout.str());
check("void f(int x) {\n"
" if ((5 && x) < 1)\n"
" a++;\n"
"}\n"
);
ASSERT_EQUALS("", errout.str());
check("void f(int x) {\n"
" if ((5 && x) > 1)\n"
" a++;\n"
"}\n"
);
ASSERT_EQUALS("[test.cpp:2]: (warning) Comparison of a boolean expression with an integer other than 0 or 1.\n", errout.str());
check("void f(int x) {\n"
" if (0 < (5 && x))\n"
" a++;\n"
"}\n"
);
ASSERT_EQUALS("", errout.str());
check("void f(int x) {\n"
" if (0 > (5 && x))\n"
" a++;\n"
"}\n"
);
ASSERT_EQUALS("[test.cpp:2]: (warning) Comparison of a boolean expression with an integer other than 0 or 1.\n", errout.str());
check("void f(int x) {\n"
" if (1 > (5 && x))\n"
" a++;\n"
"}\n"
);
ASSERT_EQUALS("", errout.str());
check("void f(int x) {\n"
" if (1 < (5 && x))\n"
" a++;\n"
"}\n"
);
ASSERT_EQUALS("[test.cpp:2]: (warning) Comparison of a boolean expression with an integer other than 0 or 1.\n", errout.str());
check("void f(bool x ) {\n"
" if ( x > false )\n"
" a++;\n"
"}\n"
);
ASSERT_EQUALS("[test.cpp:2]: (warning) Comparison of a boolean value using relational operator (<, >, <= or >=).\n", errout.str());
check("void f(bool x ) {\n"
" if ( false < x )\n"
" a++;\n"
"}\n"
);
ASSERT_EQUALS("[test.cpp:2]: (warning) Comparison of a boolean value using relational operator (<, >, <= or >=).\n", errout.str());
check("void f(bool x ) {\n"
" if ( x < false )\n"
" a++;\n"
"}\n"
);
ASSERT_EQUALS("[test.cpp:2]: (warning) Comparison of a boolean value using relational operator (<, >, <= or >=).\n", errout.str());
check("void f(bool x ) {\n"
" if ( false > x )\n"
" a++;\n"
"}\n"
);
ASSERT_EQUALS("[test.cpp:2]: (warning) Comparison of a boolean value using relational operator (<, >, <= or >=).\n", errout.str());
check("void f(bool x ) {\n"
" if ( x >= false )\n"
" a++;\n"
"}\n"
);
ASSERT_EQUALS("[test.cpp:2]: (warning) Comparison of a boolean value using relational operator (<, >, <= or >=).\n", errout.str());
check("void f(bool x ) {\n"
" if ( false >= x )\n"
" a++;\n"
"}\n"
);
ASSERT_EQUALS("[test.cpp:2]: (warning) Comparison of a boolean value using relational operator (<, >, <= or >=).\n", errout.str());
check("void f(bool x ) {\n"
" if ( x <= false )\n"
" a++;\n"
"}\n"
);
ASSERT_EQUALS("[test.cpp:2]: (warning) Comparison of a boolean value using relational operator (<, >, <= or >=).\n", errout.str());
check("void f(bool x ) {\n"
" if ( false <= x )\n"
" a++;\n"
"}\n"
);
ASSERT_EQUALS("[test.cpp:2]: (warning) Comparison of a boolean value using relational operator (<, >, <= or >=).\n", errout.str());
check("typedef int (*func)(bool invert);\n"
"void x(int, func f);\n"
"void foo(int error) {\n"
" if (error == ABC) { }\n"
"}");
ASSERT_EQUALS("", errout.str());
}
void comparisonOfBoolExpressionWithInt2() {
check("void f(int x) {\n"
" if (!x == 10) {\n"
" printf(\"x not equal to 10\");\n"
" }\n"
"}");
ASSERT_EQUALS("[test.cpp:2]: (warning) Comparison of a boolean expression with an integer other than 0 or 1.\n", errout.str());
check("void f(int x) {\n"
" if (!x != 10) {\n"
" printf(\"x not equal to 10\");\n"
" }\n"
"}");
ASSERT_EQUALS("[test.cpp:2]: (warning) Comparison of a boolean expression with an integer other than 0 or 1.\n", errout.str());
check("void f(int x) {\n"
" if (x != 10) {\n"
" printf(\"x not equal to 10\");\n"
" }\n"
"}");
ASSERT_EQUALS("", errout.str());
check("void f(int x) {\n"
" if (10 == !x) {\n"
" printf(\"x not equal to 10\");\n"
" }\n"
"}");
ASSERT_EQUALS("[test.cpp:2]: (warning) Comparison of a boolean expression with an integer other than 0 or 1.\n", errout.str());
check("void f(int x) {\n"
" if (10 != !x) {\n"
" printf(\"x not equal to 10\");\n"
" }\n"
"}");
ASSERT_EQUALS("[test.cpp:2]: (warning) Comparison of a boolean expression with an integer other than 0 or 1.\n", errout.str());
check("void f(int x, int y) {\n"
" if (y != !x) {\n"
" printf(\"x not equal to 10\");\n"
" }\n"
"}");
ASSERT_EQUALS("[test.cpp:2]: (warning) Comparison of a boolean expression with an integer.\n", errout.str());
check("void f(int x, bool y) {\n"
" if (y != !x) {\n"
" printf(\"x not equal to 10\");\n"
" }\n"
"}");
ASSERT_EQUALS("", errout.str());
check("void f(int x) {\n"
" if (10 != x) {\n"
" printf(\"x not equal to 10\");\n"
" }\n"
"}");
ASSERT_EQUALS("", errout.str());
}
void comparisonOfBoolExpressionWithInt3() {
check("int f(int x) {\n"
" return t<0>() && x;\n"
"}");
ASSERT_EQUALS("", errout.str());
}
void memsetZeroBytes() {
check("void f() {\n"
" memset(p, 10, 0x0);\n"
@ -4313,202 +4023,6 @@ private:
}
void checkComparisonOfFuncReturningBool1() {
check("void f(){\n"
" int temp = 4;\n"
" if(compare1(temp) > compare2(temp)){\n"
" printf(\"foo\");\n"
" }\n"
"}\n"
"bool compare1(int temp){\n"
" if(temp==4){\n"
" return true;\n"
" }\n"
" else\n"
" return false;\n"
"}\n"
"bool compare2(int temp){\n"
" if(temp==4){\n"
" return false;\n"
" }\n"
" else\n"
" return true;\n"
"}");
ASSERT_EQUALS("[test.cpp:3]: (style) Comparison of two functions returning boolean value using relational (<, >, <= or >=) operator.\n", errout.str());
}
void checkComparisonOfFuncReturningBool2() {
check("void f(){\n"
" int temp = 4;\n"
" bool a = true;\n"
" if(compare(temp) > a){\n"
" printf(\"foo\");\n"
" }\n"
"}\n"
"bool compare(int temp){\n"
" if(temp==4){\n"
" return true;\n"
" }\n"
" else\n"
" return false;\n"
"}");
ASSERT_EQUALS("[test.cpp:4]: (style) Comparison of a function returning boolean value using relational (<, >, <= or >=) operator.\n", errout.str());
}
void checkComparisonOfFuncReturningBool3() {
check("void f(){\n"
" int temp = 4;\n"
" if(compare(temp) > temp){\n"
" printf(\"foo\");\n"
" }\n"
"}\n"
"bool compare(int temp){\n"
" if(temp==4){\n"
" return true;\n"
" }\n"
" else\n"
" return false;\n"
"}");
ASSERT_EQUALS("[test.cpp:3]: (style) Comparison of a function returning boolean value using relational (<, >, <= or >=) operator.\n", errout.str());
}
void checkComparisonOfFuncReturningBool4() {
check("void f(){\n"
" int temp = 4;\n"
" bool b = compare2(6);\n"
" if(compare1(temp)> b){\n"
" printf(\"foo\");\n"
" }\n"
"}\n"
"bool compare1(int temp){\n"
" if(temp==4){\n"
" return true;\n"
" }\n"
" else\n"
" return false;\n"
"}\n"
"bool compare2(int temp){\n"
" if(temp == 5){\n"
" return true;\n"
" }\n"
" else\n"
" return false;\n"
"}");
ASSERT_EQUALS("[test.cpp:4]: (style) Comparison of a function returning boolean value using relational (<, >, <= or >=) operator.\n", errout.str());
}
void checkComparisonOfFuncReturningBool5() {
check("void f(){\n"
" int temp = 4;\n"
" if(compare1(temp) > !compare2(temp)){\n"
" printf(\"foo\");\n"
" }\n"
"}\n"
"bool compare1(int temp){\n"
" if(temp==4){\n"
" return true;\n"
" }\n"
" else\n"
" return false;\n"
"}\n"
"bool compare2(int temp){\n"
" if(temp==4){\n"
" return false;\n"
" }\n"
" else\n"
" return true;\n"
"}");
ASSERT_EQUALS("[test.cpp:3]: (style) Comparison of two functions returning boolean value using relational (<, >, <= or >=) operator.\n", errout.str());
}
void checkComparisonOfFuncReturningBool6() {
check("int compare1(int temp);\n"
"namespace Foo {\n"
" bool compare1(int temp);\n"
"}\n"
"void f(){\n"
" int temp = 4;\n"
" if(compare1(temp) > compare2(temp)){\n"
" printf(\"foo\");\n"
" }\n"
"}");
ASSERT_EQUALS("", errout.str());
check("namespace Foo {\n"
" bool compare1(int temp);\n"
"}\n"
"int compare1(int temp);\n"
"void f(){\n"
" int temp = 4;\n"
" if(compare1(temp) > compare2(temp)){\n"
" printf(\"foo\");\n"
" }\n"
"}");
ASSERT_EQUALS("", errout.str());
check("int compare1(int temp);\n"
"namespace Foo {\n"
" bool compare1(int temp);\n"
" void f(){\n"
" int temp = 4;\n"
" if(compare1(temp) > compare2(temp)){\n"
" printf(\"foo\");\n"
" }\n"
" }\n"
"}");
ASSERT_EQUALS("[test.cpp:6]: (style) Comparison of a function returning boolean value using relational (<, >, <= or >=) operator.\n", errout.str());
check("int compare1(int temp);\n"
"namespace Foo {\n"
" bool compare1(int temp);\n"
" void f(){\n"
" int temp = 4;\n"
" if(::compare1(temp) > compare2(temp)){\n"
" printf(\"foo\");\n"
" }\n"
" }\n"
"}");
ASSERT_EQUALS("", errout.str());
check("bool compare1(int temp);\n"
"void f(){\n"
" int temp = 4;\n"
" if(foo.compare1(temp) > compare2(temp)){\n"
" printf(\"foo\");\n"
" }\n"
"}");
ASSERT_EQUALS("", errout.str());
}
void checkComparisonOfBoolWithBool() {
const char code[] = "void f(){\n"
" int temp = 4;\n"
" bool b = compare2(6);\n"
" bool a = compare1(4);\n"
" if(b > a){\n"
" printf(\"foo\");\n"
" }\n"
"}\n"
"bool compare1(int temp){\n"
" if(temp==4){\n"
" return true;\n"
" }\n"
" else\n"
" return false;\n"
"}\n"
"bool compare2(int temp){\n"
" if(temp == 5){\n"
" return true;\n"
" }\n"
" else\n"
" return false;\n"
"}\n";
check(code, "test.cpp", true);
ASSERT_EQUALS("[test.cpp:5]: (style) Comparison of a variable having boolean value using relational (<, >, <= or >=) operator.\n", errout.str());
check(code, "test.cpp");
ASSERT_EQUALS("", errout.str());
}
void sizeofForNumericParameter() {
check("void f() {\n"
" std::cout << sizeof(10) << std::endl;\n"
@ -4788,72 +4302,6 @@ private:
ASSERT_EQUALS("", errout.str());
}
void bitwiseOnBoolean() { // 3062
check("void f(_Bool a, _Bool b) {\n"
" if(a & b) {}\n"
"}");
ASSERT_EQUALS("[test.cpp:2]: (style, inconclusive) Boolean variable 'a' is used in bitwise operation. Did you mean '&&'?\n", errout.str());
check("void f(_Bool a, _Bool b) {\n"
" if(a | b) {}\n"
"}");
ASSERT_EQUALS("[test.cpp:2]: (style, inconclusive) Boolean variable 'a' is used in bitwise operation. Did you mean '||'?\n", errout.str());
check("void f(bool a, bool b) {\n"
" if(a & !b) {}\n"
"}");
ASSERT_EQUALS("[test.cpp:2]: (style, inconclusive) Boolean variable 'a' is used in bitwise operation. Did you mean '&&'?\n", errout.str());
check("void f(bool a, bool b) {\n"
" if(a | !b) {}\n"
"}");
ASSERT_EQUALS("[test.cpp:2]: (style, inconclusive) Boolean variable 'a' is used in bitwise operation. Did you mean '||'?\n", errout.str());
check("bool a, b;\n"
"void f() {\n"
" if(a & b) {}\n"
"}");
ASSERT_EQUALS("[test.cpp:3]: (style, inconclusive) Boolean variable 'a' is used in bitwise operation. Did you mean '&&'?\n", errout.str());
check("bool a, b;\n"
"void f() {\n"
" if(a & !b) {}\n"
"}");
ASSERT_EQUALS("[test.cpp:3]: (style, inconclusive) Boolean variable 'a' is used in bitwise operation. Did you mean '&&'?\n", errout.str());
check("bool a, b;\n"
"void f() {\n"
" if(a | b) {}\n"
"}");
ASSERT_EQUALS("[test.cpp:3]: (style, inconclusive) Boolean variable 'a' is used in bitwise operation. Did you mean '||'?\n", errout.str());
check("bool a, b;\n"
"void f() {\n"
" if(a | !b) {}\n"
"}");
ASSERT_EQUALS("[test.cpp:3]: (style, inconclusive) Boolean variable 'a' is used in bitwise operation. Did you mean '||'?\n", errout.str());
check("void f(bool a, int b) {\n"
" if(a & b) {}\n"
"}");
ASSERT_EQUALS("[test.cpp:2]: (style, inconclusive) Boolean variable 'a' is used in bitwise operation. Did you mean '&&'?\n", errout.str());
check("void f(int a, bool b) {\n"
" if(a & b) {}\n"
"}");
ASSERT_EQUALS("[test.cpp:2]: (style, inconclusive) Boolean variable 'b' is used in bitwise operation. Did you mean '&&'?\n", errout.str());
check("void f(int a, int b) {\n"
" if(a & b) {}\n"
"}");
ASSERT_EQUALS("", errout.str());
check("void f(bool b) {\n"
" foo(bar, &b);\n"
"}");
ASSERT_EQUALS("", errout.str());
}
void incorrectStringCompare() {
check("int f() {\n"
" return test.substr( 0 , 4 ) == \"Hello\" ? : 0 : 1 ;\n"
@ -4932,161 +4380,6 @@ private:
}
void incrementBoolean() {
check("bool bValue = true;\n"
"void f() { bValue++; }");
ASSERT_EQUALS("[test.cpp:2]: (style) Incrementing a variable of type 'bool' with postfix operator++ is deprecated by the C++ Standard. You should assign it the value 'true' instead.\n", errout.str());
check("_Bool bValue = true;\n"
"void f() { bValue++; }");
ASSERT_EQUALS("[test.cpp:2]: (style) Incrementing a variable of type 'bool' with postfix operator++ is deprecated by the C++ Standard. You should assign it the value 'true' instead.\n", errout.str());
check("void f(bool test){\n"
" test++;\n"
"}");
ASSERT_EQUALS("[test.cpp:2]: (style) Incrementing a variable of type 'bool' with postfix operator++ is deprecated by the C++ Standard. You should assign it the value 'true' instead.\n", errout.str());
check("void f(int test){\n"
" test++;\n"
"}");
ASSERT_EQUALS("", errout.str());
}
void comparisonOfBoolWithInt1() {
check("void f(bool x) {\n"
" if (x < 10) {\n"
" printf(\"foo\");\n"
" }\n"
"}");
ASSERT_EQUALS("[test.cpp:2]: (warning) Comparison of a boolean with an integer.\n", errout.str());
check("void f(bool x) {\n"
" if (10 >= x) {\n"
" printf(\"foo\");\n"
" }\n"
"}");
ASSERT_EQUALS("[test.cpp:2]: (warning) Comparison of a boolean with an integer.\n", errout.str());
check("void f(bool x) {\n"
" if (x != 0) {\n"
" printf(\"foo\");\n"
" }\n"
"}");
ASSERT_EQUALS("", errout.str());
check("void f(bool x) {\n" // #3356
" if (x == 1) {\n"
" }\n"
"}");
ASSERT_EQUALS("", errout.str());
check("void f(bool x) {\n"
" if (x != 10) {\n"
" printf(\"foo\");\n"
" }\n"
"}");
ASSERT_EQUALS("[test.cpp:2]: (warning) Comparison of a boolean with an integer that is neither 1 nor 0.\n", errout.str());
check("void f(bool x) {\n"
" if (x == 10) {\n"
" printf(\"foo\");\n"
" }\n"
"}");
ASSERT_EQUALS("[test.cpp:2]: (warning) Comparison of a boolean with an integer that is neither 1 nor 0.\n", errout.str());
check("void f(bool x) {\n"
" if (x == 0) {\n"
" printf(\"foo\");\n"
" }\n"
"}");
ASSERT_EQUALS("", errout.str());
check("DensePropertyMap<int, true> visited;"); // #4075
ASSERT_EQUALS("", errout.str());
}
void comparisonOfBoolWithInt2() {
check("void f(bool x, int y) {\n"
" if (x == y) {\n"
" printf(\"foo\");\n"
" }\n"
"}");
ASSERT_EQUALS("[test.cpp:2]: (warning) Comparison of a boolean with an integer.\n", errout.str());
check("void f(int x, bool y) {\n"
" if (x == y) {\n"
" printf(\"foo\");\n"
" }\n"
"}");
ASSERT_EQUALS("[test.cpp:2]: (warning) Comparison of a boolean with an integer.\n", errout.str());
check("void f(bool x, bool y) {\n"
" if (x == y) {\n"
" printf(\"foo\");\n"
" }\n"
"}");
ASSERT_EQUALS("", errout.str());
check("void f(bool x, fooClass y) {\n"
" if (x == y) {\n"
" printf(\"foo\");\n"
" }\n"
"}");
ASSERT_EQUALS("", errout.str());
}
void comparisonOfBoolWithInt3() {
check("void f(int y) {\n"
" if (y > false) {\n"
" printf(\"foo\");\n"
" }\n"
"}");
ASSERT_EQUALS("[test.cpp:2]: (warning) Comparison of a boolean with an integer.\n", errout.str());
check("void f(int y) {\n"
" if (true == y) {\n"
" printf(\"foo\");\n"
" }\n"
"}");
ASSERT_EQUALS("[test.cpp:2]: (warning) Comparison of a boolean with an integer.\n", errout.str());
check("void f(bool y) {\n"
" if (y == true) {\n"
" printf(\"foo\");\n"
" }\n"
"}");
ASSERT_EQUALS("", errout.str());
check("void f(bool y) {\n"
" if (false < 5) {\n"
" printf(\"foo\");\n"
" }\n"
"}");
ASSERT_EQUALS("[test.cpp:2]: (warning) Comparison of a boolean with an integer.\n", errout.str());
}
void comparisonOfBoolWithInt4() {
check("void f(int x) {\n"
" if (!x == 1) { }\n"
"}");
ASSERT_EQUALS("", errout.str());
}
void comparisonOfBoolWithInt5() {
check("void SetVisible(int index, bool visible) {\n"
" bool (SciTEBase::*ischarforsel)(char ch);\n"
" if (visible != GetVisible(index)) { }\n"
"}");
ASSERT_EQUALS("", errout.str());
}
void comparisonOfBoolWithInt6() { // #4224 - integer is casted to bool
check("void SetVisible(bool b, int i) {\n"
" if (b == (bool)i) { }\n"
"}");
ASSERT_EQUALS("", errout.str());
}
void duplicateIf() {
check("void f(int a, int &b) {\n"
" if (a) { b = 1; }\n"

View File

@ -33,6 +33,7 @@
<ClCompile Include="test64bit.cpp" />
<ClCompile Include="testassignif.cpp" />
<ClCompile Include="testautovariables.cpp" />
<ClCompile Include="testbool.cpp" />
<ClCompile Include="testboost.cpp" />
<ClCompile Include="testbufferoverrun.cpp" />
<ClCompile Include="testcharvar.cpp" />

View File

@ -166,6 +166,9 @@
<ClCompile Include="..\cli\cppcheckexecutor.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="testbool.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="options.h">