* Fix #7197 not getting expected warning in relational comparison of booleans * return nullptr
This commit is contained in:
parent
e9641e6de5
commit
942dbad11c
|
@ -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) {
|
||||||
|
|
|
@ -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"
|
||||||
|
|
Loading…
Reference in New Issue