Fixed #8186 (Inner condition always false inside for loop)
This commit is contained in:
parent
d598a1c278
commit
dce942197c
|
@ -275,6 +275,17 @@ bool isOppositeCond(bool isNot, bool cpp, const Token * const cond1, const Token
|
||||||
comp2[0] = '>';
|
comp2[0] = '>';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!isNot && comp2.empty()) {
|
||||||
|
if (isSameExpression(cpp, true, cond1->astOperand1(), cond2->astOperand1(), library, pure) &&
|
||||||
|
cond1->astOperand2() && cond1->astOperand2()->hasKnownIntValue() &&
|
||||||
|
cond2->astOperand2() && cond2->astOperand2()->hasKnownIntValue()) {
|
||||||
|
const ValueFlow::Value &rhsValue1 = cond1->astOperand2()->values().front();
|
||||||
|
const ValueFlow::Value &rhsValue2 = cond2->astOperand2()->values().front();
|
||||||
|
if (comp1 == "<" && cond2->str() == "==")
|
||||||
|
return (rhsValue1.intvalue < rhsValue2.intvalue);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// is condition opposite?
|
// is condition opposite?
|
||||||
return ((comp1 == "==" && comp2 == "!=") ||
|
return ((comp1 == "==" && comp2 == "!=") ||
|
||||||
(comp1 == "!=" && comp2 == "==") ||
|
(comp1 == "!=" && comp2 == "==") ||
|
||||||
|
|
|
@ -452,15 +452,35 @@ void CheckCondition::oppositeInnerCondition()
|
||||||
const SymbolDatabase *symbolDatabase = _tokenizer->getSymbolDatabase();
|
const SymbolDatabase *symbolDatabase = _tokenizer->getSymbolDatabase();
|
||||||
|
|
||||||
for (std::list<Scope>::const_iterator scope = symbolDatabase->scopeList.begin(); scope != symbolDatabase->scopeList.end(); ++scope) {
|
for (std::list<Scope>::const_iterator scope = symbolDatabase->scopeList.begin(); scope != symbolDatabase->scopeList.end(); ++scope) {
|
||||||
if (scope->type != Scope::eIf)
|
const Token *condTok = nullptr;
|
||||||
|
if (scope->type == Scope::eIf || scope->type == Scope::eWhile)
|
||||||
|
condTok = scope->classDef->next()->astOperand2();
|
||||||
|
else if (scope->type == Scope::eFor) {
|
||||||
|
condTok = scope->classDef->next()->astOperand2();
|
||||||
|
if (!condTok || condTok->str() != ";")
|
||||||
|
continue;
|
||||||
|
condTok = condTok->astOperand2();
|
||||||
|
if (!condTok || condTok->str() != ";")
|
||||||
|
continue;
|
||||||
|
condTok = condTok->astOperand1();
|
||||||
|
}
|
||||||
|
if (!condTok)
|
||||||
continue;
|
continue;
|
||||||
|
const Token * const cond1 = condTok;
|
||||||
|
|
||||||
if (!Token::simpleMatch(scope->classDef->linkAt(1), ") {"))
|
if (!Token::simpleMatch(scope->classDef->linkAt(1), ") {"))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
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
|
||||||
for (const Token *cond = scope->classDef->linkAt(1); cond != scope->classDef; cond = cond->previous()) {
|
std::stack<const Token *> tokens;
|
||||||
|
tokens.push(condTok);
|
||||||
|
while (!tokens.empty()) {
|
||||||
|
const Token *cond = tokens.top();
|
||||||
|
tokens.pop();
|
||||||
|
if (!cond)
|
||||||
|
continue;
|
||||||
|
|
||||||
if (cond->varId()) {
|
if (cond->varId()) {
|
||||||
vars.insert(cond->varId());
|
vars.insert(cond->varId());
|
||||||
const Variable *var = cond->variable();
|
const Variable *var = cond->variable();
|
||||||
|
@ -470,6 +490,9 @@ void CheckCondition::oppositeInnerCondition()
|
||||||
} else if (!nonlocal && cond->isName()) {
|
} else if (!nonlocal && cond->isName()) {
|
||||||
// varid is 0. this is possibly a nonlocal variable..
|
// varid is 0. this is possibly a nonlocal variable..
|
||||||
nonlocal = Token::Match(cond->astParent(), "%cop%|(");
|
nonlocal = Token::Match(cond->astParent(), "%cop%|(");
|
||||||
|
} else {
|
||||||
|
tokens.push(cond->astOperand1());
|
||||||
|
tokens.push(cond->astOperand2());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -514,7 +537,6 @@ void CheckCondition::oppositeInnerCondition()
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// Condition..
|
// Condition..
|
||||||
const Token *cond1 = scope->classDef->next()->astOperand2();
|
|
||||||
const Token *cond2 = ifToken->next()->astOperand2();
|
const Token *cond2 = ifToken->next()->astOperand2();
|
||||||
|
|
||||||
if (isOppositeCond(false, _tokenizer->isCPP(), cond1, cond2, _settings->library, true))
|
if (isOppositeCond(false, _tokenizer->isCPP(), cond1, cond2, _settings->library, true))
|
||||||
|
|
|
@ -1574,6 +1574,14 @@ private:
|
||||||
" }\n"
|
" }\n"
|
||||||
"}");
|
"}");
|
||||||
ASSERT_EQUALS("", errout.str());
|
ASSERT_EQUALS("", errout.str());
|
||||||
|
|
||||||
|
// #8186
|
||||||
|
check("void f() {\n"
|
||||||
|
" for (int i=0;i<4;i++) {\n"
|
||||||
|
" if (i==5) {}\n"
|
||||||
|
" }\n"
|
||||||
|
"}");
|
||||||
|
ASSERT_EQUALS("[test.cpp:2] -> [test.cpp:3]: (warning) Opposite conditions in nested 'if' blocks lead to a dead code block.\n", errout.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
// clarify conditions with = and comparison
|
// clarify conditions with = and comparison
|
||||||
|
|
Loading…
Reference in New Issue