CheckCondition: Fix FP when there are method calls in condition
This commit is contained in:
parent
68f6cad2aa
commit
e0c7f7f8f2
|
@ -481,6 +481,7 @@ void CheckCondition::multiCondition2()
|
||||||
if (!Token::simpleMatch(scope->classDef->linkAt(1), ") {"))
|
if (!Token::simpleMatch(scope->classDef->linkAt(1), ") {"))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
bool nonConstFunctionCall = false;
|
||||||
bool nonlocal = false; // nonlocal variable used in condition
|
bool nonlocal = false; // nonlocal variable used in condition
|
||||||
std::set<unsigned int> vars; // variables used in condition
|
std::set<unsigned int> vars; // variables used in condition
|
||||||
std::stack<const Token *> tokens;
|
std::stack<const Token *> tokens;
|
||||||
|
@ -491,6 +492,22 @@ void CheckCondition::multiCondition2()
|
||||||
if (!cond)
|
if (!cond)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
if (Token::Match(cond, "%name% (")) {
|
||||||
|
const Token *obj = cond->next()->astOperand1();
|
||||||
|
while (obj && obj->str() == ".")
|
||||||
|
obj = obj->astOperand1();
|
||||||
|
if (!obj)
|
||||||
|
nonConstFunctionCall = true;
|
||||||
|
else if (obj->variable() && obj->variable()->isConst())
|
||||||
|
;
|
||||||
|
else if (cond->function() && cond->function()->isConst())
|
||||||
|
;
|
||||||
|
else
|
||||||
|
nonConstFunctionCall = true;
|
||||||
|
if (nonConstFunctionCall)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
if (cond->varId()) {
|
if (cond->varId()) {
|
||||||
vars.insert(cond->varId());
|
vars.insert(cond->varId());
|
||||||
const Variable *var = cond->variable();
|
const Variable *var = cond->variable();
|
||||||
|
@ -510,6 +527,9 @@ void CheckCondition::multiCondition2()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (nonConstFunctionCall)
|
||||||
|
continue;
|
||||||
|
|
||||||
// parse until second condition is reached..
|
// parse until second condition is reached..
|
||||||
enum MULTICONDITIONTYPE { INNER, AFTER } type;
|
enum MULTICONDITIONTYPE { INNER, AFTER } type;
|
||||||
const Token *tok;
|
const Token *tok;
|
||||||
|
|
|
@ -1542,7 +1542,7 @@ private:
|
||||||
"}");
|
"}");
|
||||||
ASSERT_EQUALS("[test.cpp:3] -> [test.cpp:5]: (warning) Opposite inner 'if' condition leads to a dead code block.\n", errout.str());
|
ASSERT_EQUALS("[test.cpp:3] -> [test.cpp:5]: (warning) Opposite inner 'if' condition leads to a dead code block.\n", errout.str());
|
||||||
|
|
||||||
check("class Fred { public: void dostuff() const; };\n"
|
check("class Fred { public: bool isValid() const; void dostuff() const; };\n"
|
||||||
"void f() {\n"
|
"void f() {\n"
|
||||||
" Fred fred;\n"
|
" Fred fred;\n"
|
||||||
" if (fred.isValid()) {\n"
|
" if (fred.isValid()) {\n"
|
||||||
|
@ -1804,6 +1804,22 @@ private:
|
||||||
" if (!i) {}\n"
|
" if (!i) {}\n"
|
||||||
"}");
|
"}");
|
||||||
ASSERT_EQUALS("[test.cpp:2] -> [test.cpp:4]: (warning) Same condition '!i', second condition is always false\n", errout.str());
|
ASSERT_EQUALS("[test.cpp:2] -> [test.cpp:4]: (warning) Same condition '!i', second condition is always false\n", errout.str());
|
||||||
|
|
||||||
|
check("void C::f(Tree &coreTree) {\n"
|
||||||
|
" if(!coreTree.build())\n"
|
||||||
|
" return;\n"
|
||||||
|
" coreTree.dostuff();\n"
|
||||||
|
" if(!coreTree.build()) {}\n"
|
||||||
|
"}\n");
|
||||||
|
ASSERT_EQUALS("", errout.str());
|
||||||
|
|
||||||
|
check("void C::f(const Tree &coreTree) {\n"
|
||||||
|
" if(!coreTree.build())\n"
|
||||||
|
" return;\n"
|
||||||
|
" coreTree.dostuff();\n"
|
||||||
|
" if(!coreTree.build()) {}\n"
|
||||||
|
"}\n");
|
||||||
|
TODO_ASSERT_EQUALS("error", "", errout.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
// clarify conditions with = and comparison
|
// clarify conditions with = and comparison
|
||||||
|
|
Loading…
Reference in New Issue