Fix FP knowConditionTrueFalse (#4419)
* Fix #10426 FN (style) Condition 's.empty()' is always false * Fix test * Fix FP knowConditionTrueFalse * Check for casts * Fix FP for user-defined functions * Adjust condition detection * Tweaks
This commit is contained in:
parent
9d107d911b
commit
3925a27182
|
@ -1512,15 +1512,20 @@ void CheckCondition::alwaysTrueFalse()
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const Token* astTop = tok->astTop();
|
||||||
const bool constIfWhileExpression =
|
const bool constIfWhileExpression =
|
||||||
tok->astParent() && Token::Match(tok->astTop()->astOperand1(), "if|while") && !tok->astTop()->astOperand1()->isConstexpr() &&
|
tok->astParent() && Token::Match(astTop->astOperand1(), "if|while") && !astTop->astOperand1()->isConstexpr() &&
|
||||||
(Token::Match(tok->astParent(), "%oror%|&&") || Token::Match(tok->astParent()->astOperand1(), "if|while"));
|
(Token::Match(tok->astParent(), "%oror%|&&") || Token::Match(tok->astParent()->astOperand1(), "if|while"));
|
||||||
const bool constValExpr = tok->isNumber() && Token::Match(tok->astParent(),"%oror%|&&|?"); // just one number in boolean expression
|
const bool constValExpr = tok->isNumber() && Token::Match(tok->astParent(),"%oror%|&&|?"); // just one number in boolean expression
|
||||||
const bool compExpr = Token::Match(tok, "%comp%|!|("); // a compare expression
|
const bool compExpr = Token::Match(tok, "%comp%|!"); // a compare expression
|
||||||
const bool ternaryExpression = Token::simpleMatch(tok->astParent(), "?");
|
const bool ternaryExpression = Token::simpleMatch(tok->astParent(), "?");
|
||||||
const bool returnExpression = Token::simpleMatch(tok->astTop(), "return") && (tok->isComparisonOp() || Token::Match(tok, "&&|%oror%"));
|
const bool isReturn = Token::simpleMatch(astTop, "return");
|
||||||
|
const bool returnExpression = isReturn && (tok->isComparisonOp() || Token::Match(tok, "&&|%oror%"));
|
||||||
if (!(constIfWhileExpression || constValExpr || compExpr || ternaryExpression || returnExpression))
|
const bool callExpression = Token::simpleMatch(tok, "(");
|
||||||
|
if (!(constIfWhileExpression || constValExpr || compExpr || ternaryExpression || returnExpression || callExpression))
|
||||||
|
continue;
|
||||||
|
// only warn for functions returning bool
|
||||||
|
if (isReturn && callExpression && !(scope->function && scope->function->retDef && scope->function->retDef->str() == "bool"))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
const Token* expr1 = tok->astOperand1(), *expr2 = tok->astOperand2();
|
const Token* expr1 = tok->astOperand1(), *expr2 = tok->astOperand2();
|
||||||
|
|
|
@ -29,7 +29,7 @@ void QString1(QString s)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int QString2()
|
bool QString2()
|
||||||
{
|
{
|
||||||
QString s;
|
QString s;
|
||||||
// cppcheck-suppress knownConditionTrueFalse
|
// cppcheck-suppress knownConditionTrueFalse
|
||||||
|
|
|
@ -4307,15 +4307,38 @@ private:
|
||||||
ASSERT_EQUALS("", errout.str());
|
ASSERT_EQUALS("", errout.str());
|
||||||
|
|
||||||
// #10426
|
// #10426
|
||||||
check("void f() {\n"
|
check("int f() {\n"
|
||||||
" std::string s;\n"
|
" std::string s;\n"
|
||||||
" for (; !s.empty();) {}\n"
|
" for (; !s.empty();) {}\n"
|
||||||
" for (; s.empty();) {}\n"
|
" for (; s.empty();) {}\n"
|
||||||
" if (s.empty()) {}\n"
|
" if (s.empty()) {}\n"
|
||||||
|
" if ((bool)0) {}\n"
|
||||||
|
" return s.empty();"
|
||||||
"}\n");
|
"}\n");
|
||||||
ASSERT_EQUALS("[test.cpp:3]: (style) Condition '!s.empty()' is always false\n"
|
ASSERT_EQUALS("[test.cpp:3]: (style) Condition '!s.empty()' is always false\n"
|
||||||
"[test.cpp:4]: (style) Condition 's.empty()' is always true\n"
|
"[test.cpp:4]: (style) Condition 's.empty()' is always true\n"
|
||||||
"[test.cpp:5]: (style) Condition 's.empty()' is always true\n",
|
"[test.cpp:5]: (style) Condition 's.empty()' is always true\n"
|
||||||
|
"[test.cpp:6]: (style) Condition '(bool)0' is always false\n",
|
||||||
|
errout.str());
|
||||||
|
|
||||||
|
check("int f(bool b) {\n"
|
||||||
|
" if (b) return static_cast<int>(1);\n"
|
||||||
|
" return (int)0;\n"
|
||||||
|
"}\n"
|
||||||
|
"bool g(bool b) {\n"
|
||||||
|
" if (b) return static_cast<int>(1);\n"
|
||||||
|
" return (int)0;\n"
|
||||||
|
"}\n");
|
||||||
|
ASSERT_EQUALS("[test.cpp:6]: (style) Condition 'static_cast<int>(1)' is always true\n"
|
||||||
|
"[test.cpp:7]: (style) Condition '(int)0' is always false\n",
|
||||||
|
errout.str());
|
||||||
|
|
||||||
|
check("int f() { return 3; }\n"
|
||||||
|
"int g() { return f(); }\n"
|
||||||
|
"int h() { if (f()) {} }\n"
|
||||||
|
"int i() { return f() == 3; }\n");
|
||||||
|
ASSERT_EQUALS("[test.cpp:3]: (style) Condition 'f()' is always true\n"
|
||||||
|
"[test.cpp:4]: (style) Condition 'f()==3' is always true\n",
|
||||||
errout.str());
|
errout.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue