Skip to content

Commit 942dbad

Browse files
Fix cppcheck-opensource#7197 not getting expected warning in relational comparison of booleans (cppcheck-opensource#4095)
* Fix cppcheck-opensource#7197 not getting expected warning in relational comparison of booleans * return nullptr
1 parent e9641e6 commit 942dbad

2 files changed

Lines changed: 35 additions & 9 deletions

File tree

lib/checkbool.cpp

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -172,7 +172,7 @@ void CheckBool::comparisonOfBoolWithInvalidComparator(const Token *tok, const st
172172

173173
static bool tokenIsFunctionReturningBool(const Token* tok)
174174
{
175-
const Function* func = tok->function();
175+
const Function* func = tok ? tok->function() : nullptr;
176176
if (func && Token::Match(tok, "%name% (")) {
177177
if (func->tokenDef && Token::Match(func->tokenDef->previous(), "bool|_Bool")) {
178178
return true;
@@ -190,19 +190,26 @@ void CheckBool::checkComparisonOfFuncReturningBool()
190190
return;
191191

192192
const SymbolDatabase * const symbolDatabase = mTokenizer->getSymbolDatabase();
193+
auto getFunctionTok = [](const Token* tok) -> const Token* {
194+
while (Token::simpleMatch(tok, "!") || (tok && tok->isCast() && !isCPPCast(tok)))
195+
tok = tok->astOperand1();
196+
if (isCPPCast(tok))
197+
tok = tok->astOperand2();
198+
if (tok)
199+
return tok->previous();
200+
return nullptr;
201+
};
193202

194203
for (const Scope * scope : symbolDatabase->functionScopes) {
195204
for (const Token* tok = scope->bodyStart->next(); tok != scope->bodyEnd; tok = tok->next()) {
196205
if (!tok->isComparisonOp() || tok->str() == "==" || tok->str() == "!=")
197206
continue;
198-
const Token *firstToken = tok->previous();
199-
if (tok->strAt(-1) == ")") {
200-
firstToken = firstToken->link()->previous();
201-
}
202-
const Token *secondToken = tok->next();
203-
while (secondToken->str() == "!") {
204-
secondToken = secondToken->next();
205-
}
207+
208+
const Token* firstToken = getFunctionTok(tok->astOperand1());
209+
const Token* secondToken = getFunctionTok(tok->astOperand2());
210+
if (!firstToken || !secondToken)
211+
continue;
212+
206213
const bool firstIsFunctionReturningBool = tokenIsFunctionReturningBool(firstToken);
207214
const bool secondIsFunctionReturningBool = tokenIsFunctionReturningBool(secondToken);
208215
if (firstIsFunctionReturningBool && secondIsFunctionReturningBool) {

test/testbool.cpp

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ class TestBool : public TestFixture {
6363
TEST_CASE(checkComparisonOfFuncReturningBool4);
6464
TEST_CASE(checkComparisonOfFuncReturningBool5);
6565
TEST_CASE(checkComparisonOfFuncReturningBool6);
66+
TEST_CASE(checkComparisonOfFuncReturningBool7); // #7197
6667
// Integration tests..
6768
TEST_CASE(checkComparisonOfFuncReturningBoolIntegrationTest1); // #7798 overloaded functions
6869

@@ -710,6 +711,24 @@ class TestBool : public TestFixture {
710711
ASSERT_EQUALS("", errout.str());
711712
}
712713

714+
void checkComparisonOfFuncReturningBool7() { // #7197
715+
check("struct C {\n"
716+
" bool isEmpty();\n"
717+
"};\n"
718+
"void f() {\n"
719+
" C c1, c2;\n"
720+
" if ((c1.isEmpty()) < (c2.isEmpty())) {}\n"
721+
" if (!c1.isEmpty() < !!c2.isEmpty()) {}\n"
722+
" if ((int)c1.isEmpty() < (int)c2.isEmpty()) {}\n"
723+
" if (static_cast<int>(c1.isEmpty()) < static_cast<int>(c2.isEmpty())) {}\n"
724+
"}\n");
725+
ASSERT_EQUALS("[test.cpp:6]: (style) Comparison of two functions returning boolean value using relational (<, >, <= or >=) operator.\n"
726+
"[test.cpp:7]: (style) Comparison of two functions returning boolean value using relational (<, >, <= or >=) operator.\n"
727+
"[test.cpp:8]: (style) Comparison of two functions returning boolean value using relational (<, >, <= or >=) operator.\n"
728+
"[test.cpp:9]: (style) Comparison of two functions returning boolean value using relational (<, >, <= or >=) operator.\n",
729+
errout.str());
730+
}
731+
713732
void checkComparisonOfFuncReturningBoolIntegrationTest1() { // #7798
714733
check("bool eval(double *) { return false; }\n"
715734
"double eval(char *) { return 1.0; }\n"

0 commit comments

Comments
 (0)