ValueFlow: set known value for opposite condition in else if (#5503)

This commit is contained in:
Daniel Marjamäki 2016-01-30 20:03:55 +01:00
parent 112b35a49e
commit 30f2bb7796
2 changed files with 39 additions and 0 deletions

View File

@ -713,6 +713,36 @@ static void valueFlowBitAnd(TokenList *tokenlist)
}
}
static void valueFlowOppositeCondition(SymbolDatabase *symboldatabase, const Settings *settings)
{
for (std::list<Scope>::iterator scope = symboldatabase->scopeList.begin(); scope != symboldatabase->scopeList.end(); ++scope) {
if (scope->type != Scope::eIf)
continue;
Token *tok = const_cast<Token *>(scope->classDef);
if (!Token::Match(tok, "if ("))
continue;
const Token *cond1 = tok->next()->astOperand2();
if (!cond1 || !cond1->isComparisonOp())
continue;
const bool cpp = symboldatabase->isCPP();
Token *tok2 = tok->linkAt(1);
while (Token::simpleMatch(tok2, ") {")) {
tok2 = tok2->linkAt(1);
if (!Token::simpleMatch(tok2, "} else { if ("))
break;
const Token *cond2 = tok2->tokAt(4)->astOperand2();
if (!cond2 || !cond2->isComparisonOp())
continue;
if (isOppositeCond(false, cpp, cond1, cond2, settings->library.functionpure)) {
ValueFlow::Value value(1);
value.setKnown();
setTokenValue(const_cast<Token*>(cond2), value);
}
tok2 = tok2->linkAt(4);
}
}
}
static void valueFlowReverse(TokenList *tokenlist,
Token *tok,
const Token * const varToken,
@ -2341,6 +2371,7 @@ void ValueFlow::setValues(TokenList *tokenlist, SymbolDatabase* symboldatabase,
valueFlowPointerAlias(tokenlist);
valueFlowFunctionReturn(tokenlist, errorLogger, settings);
valueFlowBitAnd(tokenlist);
valueFlowOppositeCondition(symboldatabase, settings);
valueFlowForLoop(tokenlist, symboldatabase, errorLogger, settings);
valueFlowBeforeCondition(tokenlist, symboldatabase, errorLogger, settings);
valueFlowAfterAssign(tokenlist, symboldatabase, errorLogger, settings);

View File

@ -1889,6 +1889,14 @@ private:
ASSERT_EQUALS(5, value.intvalue);
ASSERT(value.isPossible());
code = "int f(int x) {\n"
" if (x < 2) {}\n"
" else if (x >= 2) {}\n" // <- known value
"}";
value = valueOfTok(code, ">=");
ASSERT_EQUALS(1, value.intvalue);
ASSERT(value.isKnown());
// function
code = "int f(int x) { return x + 1; }\n" // <- possible value
"void a() { f(12); }\b";