Fix #7197 not getting expected warning in relational comparison of booleans (#4095)

* Fix #7197 not getting expected warning in relational comparison of booleans

* return nullptr
This commit is contained in:
chrchr-github 2022-05-11 08:09:32 +02:00 committed by GitHub
parent e9641e6de5
commit 942dbad11c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 35 additions and 9 deletions

View File

@ -172,7 +172,7 @@ void CheckBool::comparisonOfBoolWithInvalidComparator(const Token *tok, const st
static bool tokenIsFunctionReturningBool(const Token* tok) static bool tokenIsFunctionReturningBool(const Token* tok)
{ {
const Function* func = tok->function(); const Function* func = tok ? tok->function() : nullptr;
if (func && Token::Match(tok, "%name% (")) { if (func && Token::Match(tok, "%name% (")) {
if (func->tokenDef && Token::Match(func->tokenDef->previous(), "bool|_Bool")) { if (func->tokenDef && Token::Match(func->tokenDef->previous(), "bool|_Bool")) {
return true; return true;
@ -190,19 +190,26 @@ void CheckBool::checkComparisonOfFuncReturningBool()
return; return;
const SymbolDatabase * const symbolDatabase = mTokenizer->getSymbolDatabase(); const SymbolDatabase * const symbolDatabase = mTokenizer->getSymbolDatabase();
auto getFunctionTok = [](const Token* tok) -> const Token* {
while (Token::simpleMatch(tok, "!") || (tok && tok->isCast() && !isCPPCast(tok)))
tok = tok->astOperand1();
if (isCPPCast(tok))
tok = tok->astOperand2();
if (tok)
return tok->previous();
return nullptr;
};
for (const Scope * scope : symbolDatabase->functionScopes) { for (const Scope * scope : symbolDatabase->functionScopes) {
for (const Token* tok = scope->bodyStart->next(); tok != scope->bodyEnd; tok = tok->next()) { for (const Token* tok = scope->bodyStart->next(); tok != scope->bodyEnd; tok = tok->next()) {
if (!tok->isComparisonOp() || tok->str() == "==" || tok->str() == "!=") if (!tok->isComparisonOp() || tok->str() == "==" || tok->str() == "!=")
continue; continue;
const Token *firstToken = tok->previous();
if (tok->strAt(-1) == ")") { const Token* firstToken = getFunctionTok(tok->astOperand1());
firstToken = firstToken->link()->previous(); const Token* secondToken = getFunctionTok(tok->astOperand2());
} if (!firstToken || !secondToken)
const Token *secondToken = tok->next(); continue;
while (secondToken->str() == "!") {
secondToken = secondToken->next();
}
const bool firstIsFunctionReturningBool = tokenIsFunctionReturningBool(firstToken); const bool firstIsFunctionReturningBool = tokenIsFunctionReturningBool(firstToken);
const bool secondIsFunctionReturningBool = tokenIsFunctionReturningBool(secondToken); const bool secondIsFunctionReturningBool = tokenIsFunctionReturningBool(secondToken);
if (firstIsFunctionReturningBool && secondIsFunctionReturningBool) { if (firstIsFunctionReturningBool && secondIsFunctionReturningBool) {

View File

@ -63,6 +63,7 @@ private:
TEST_CASE(checkComparisonOfFuncReturningBool4); TEST_CASE(checkComparisonOfFuncReturningBool4);
TEST_CASE(checkComparisonOfFuncReturningBool5); TEST_CASE(checkComparisonOfFuncReturningBool5);
TEST_CASE(checkComparisonOfFuncReturningBool6); TEST_CASE(checkComparisonOfFuncReturningBool6);
TEST_CASE(checkComparisonOfFuncReturningBool7); // #7197
// Integration tests.. // Integration tests..
TEST_CASE(checkComparisonOfFuncReturningBoolIntegrationTest1); // #7798 overloaded functions TEST_CASE(checkComparisonOfFuncReturningBoolIntegrationTest1); // #7798 overloaded functions
@ -710,6 +711,24 @@ private:
ASSERT_EQUALS("", errout.str()); ASSERT_EQUALS("", errout.str());
} }
void checkComparisonOfFuncReturningBool7() { // #7197
check("struct C {\n"
" bool isEmpty();\n"
"};\n"
"void f() {\n"
" C c1, c2;\n"
" if ((c1.isEmpty()) < (c2.isEmpty())) {}\n"
" if (!c1.isEmpty() < !!c2.isEmpty()) {}\n"
" if ((int)c1.isEmpty() < (int)c2.isEmpty()) {}\n"
" if (static_cast<int>(c1.isEmpty()) < static_cast<int>(c2.isEmpty())) {}\n"
"}\n");
ASSERT_EQUALS("[test.cpp:6]: (style) Comparison of two functions returning boolean value using relational (<, >, <= or >=) operator.\n"
"[test.cpp:7]: (style) Comparison of two functions returning boolean value using relational (<, >, <= or >=) operator.\n"
"[test.cpp:8]: (style) Comparison of two functions returning boolean value using relational (<, >, <= or >=) operator.\n"
"[test.cpp:9]: (style) Comparison of two functions returning boolean value using relational (<, >, <= or >=) operator.\n",
errout.str());
}
void checkComparisonOfFuncReturningBoolIntegrationTest1() { // #7798 void checkComparisonOfFuncReturningBoolIntegrationTest1() { // #7798
check("bool eval(double *) { return false; }\n" check("bool eval(double *) { return false; }\n"
"double eval(char *) { return 1.0; }\n" "double eval(char *) { return 1.0; }\n"