Fixed #7599 (valueFlowAST: handle && and || better)

This commit is contained in:
Daniel Marjamäki 2016-07-17 21:51:20 +02:00
parent 0162f33d3f
commit 4f051bf9dd
2 changed files with 34 additions and 0 deletions

View File

@ -1069,6 +1069,23 @@ static void valueFlowAST(Token *tok, unsigned int varid, const ValueFlow::Value
if (tok->varId() == varid)
setTokenValue(tok, value);
valueFlowAST(const_cast<Token*>(tok->astOperand1()), varid, value);
if (tok->str() == "&&" && tok->astOperand1() && tok->astOperand1()->getValue(0)) {
ProgramMemory pm;
pm.setValue(varid,value);
if (conditionIsFalse(tok->astOperand1(), pm))
return;
} else if (tok->str() == "||" && tok->astOperand1()) {
bool nonzero = false;
for (std::list<ValueFlow::Value>::const_iterator it = tok->astOperand1()->values.begin(); it != tok->astOperand1()->values.end(); ++it) {
nonzero |= (it->intvalue != 0);
}
if (!nonzero)
return;
ProgramMemory pm;
pm.setValue(varid,value);
if (conditionIsTrue(tok->astOperand1(), pm))
return;
}
valueFlowAST(const_cast<Token*>(tok->astOperand2()), varid, value);
}
@ -1446,6 +1463,7 @@ static bool valueFlowForward(Token * const startToken,
valueFlowAST(const_cast<Token*>(op2), varid, *it);
}
}
// Skip conditional expressions..
while (tok2->astOperand1() || tok2->astOperand2()) {
if (tok2->astOperand2())

View File

@ -838,6 +838,22 @@ private:
ASSERT_EQUALS(false, testValueOfX(code, 8U, "\"\""));
ASSERT_EQUALS(false, testValueOfX(code, 9U, "\"\""));
code = "void f() {\n" // #7599
" t *x = 0;\n"
" y = (a ? 1 : x\n" // <- x is 0
" && x->y ? 1 : 2);" // <- x is not 0
"}";
ASSERT_EQUALS(true, testValueOfX(code, 3U, 0));
ASSERT_EQUALS(false, testValueOfX(code, 4U, 0));
code = "void f() {\n" // #7599
" t *x = 0;\n"
" y = (a ? 1 : !x\n" // <- x is 0
" || x->y ? 1 : 2);" // <- x is not 0
"}";
ASSERT_EQUALS(true, testValueOfX(code, 3U, 0));
ASSERT_EQUALS(false, testValueOfX(code, 4U, 0));
// if/else
code = "void f() {\n"
" int x = 123;\n"