Fixed #8186 (Inner condition always false inside for loop)

This commit is contained in:
Daniel Marjamäki 2017-08-31 16:00:12 +02:00
parent d598a1c278
commit dce942197c
3 changed files with 44 additions and 3 deletions

View File

@ -275,6 +275,17 @@ bool isOppositeCond(bool isNot, bool cpp, const Token * const cond1, const Token
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?
return ((comp1 == "==" && comp2 == "!=") ||
(comp1 == "!=" && comp2 == "==") ||

View File

@ -452,15 +452,35 @@ void CheckCondition::oppositeInnerCondition()
const SymbolDatabase *symbolDatabase = _tokenizer->getSymbolDatabase();
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;
const Token * const cond1 = condTok;
if (!Token::simpleMatch(scope->classDef->linkAt(1), ") {"))
continue;
bool nonlocal = false; // nonlocal variable 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()) {
vars.insert(cond->varId());
const Variable *var = cond->variable();
@ -470,6 +490,9 @@ void CheckCondition::oppositeInnerCondition()
} else if (!nonlocal && cond->isName()) {
// varid is 0. this is possibly a nonlocal variable..
nonlocal = Token::Match(cond->astParent(), "%cop%|(");
} else {
tokens.push(cond->astOperand1());
tokens.push(cond->astOperand2());
}
}
@ -514,7 +537,6 @@ void CheckCondition::oppositeInnerCondition()
continue;
// Condition..
const Token *cond1 = scope->classDef->next()->astOperand2();
const Token *cond2 = ifToken->next()->astOperand2();
if (isOppositeCond(false, _tokenizer->isCPP(), cond1, cond2, _settings->library, true))

View File

@ -1574,6 +1574,14 @@ private:
" }\n"
"}");
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