Fixed #3923 (valueFlowForward: assignment in if should not cause bailout for code in else)
This commit is contained in:
parent
9a847d7b14
commit
04f9b71281
|
@ -1148,11 +1148,29 @@ static bool valueFlowForward(Token * const startToken,
|
||||||
const bool condAlwaysTrue = (condTok && condTok->values.size() == 1U && condTok->values.front().isKnown() && condTok->values.front().intvalue != 0);
|
const bool condAlwaysTrue = (condTok && condTok->values.size() == 1U && condTok->values.front().isKnown() && condTok->values.front().intvalue != 0);
|
||||||
|
|
||||||
// Should scope be skipped because variable value is checked?
|
// Should scope be skipped because variable value is checked?
|
||||||
std::list<ValueFlow::Value> truevalues;
|
std::list<ValueFlow::Value> truevalues, falsevalues;
|
||||||
for (std::list<ValueFlow::Value>::const_iterator it = values.begin(); it != values.end(); ++it) {
|
for (std::list<ValueFlow::Value>::const_iterator it = values.begin(); it != values.end(); ++it) {
|
||||||
if (condAlwaysTrue || !conditionIsFalse(condTok, getProgramMemory(tok2, varid, *it)))
|
if (condAlwaysTrue || !conditionIsFalse(condTok, getProgramMemory(tok2, varid, *it)))
|
||||||
truevalues.push_back(*it);
|
truevalues.push_back(*it);
|
||||||
|
if (!condAlwaysTrue && !conditionIsTrue(condTok, getProgramMemory(tok2, varid, *it)))
|
||||||
|
falsevalues.push_back(*it);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!falsevalues.empty() && Token::simpleMatch(tok2->linkAt(1)->linkAt(1), "} else {")) {
|
||||||
|
// '{'
|
||||||
|
Token * const startToken1 = tok2->linkAt(1)->linkAt(1)->tokAt(2);
|
||||||
|
|
||||||
|
valueFlowForward(startToken1->next(),
|
||||||
|
startToken1->link(),
|
||||||
|
var,
|
||||||
|
varid,
|
||||||
|
falsevalues,
|
||||||
|
constValue,
|
||||||
|
tokenlist,
|
||||||
|
errorLogger,
|
||||||
|
settings);
|
||||||
|
}
|
||||||
|
|
||||||
if (truevalues.size() != values.size() || condAlwaysTrue) {
|
if (truevalues.size() != values.size() || condAlwaysTrue) {
|
||||||
// '{'
|
// '{'
|
||||||
Token * const startToken1 = tok2->linkAt(1)->next();
|
Token * const startToken1 = tok2->linkAt(1)->next();
|
||||||
|
|
|
@ -900,6 +900,13 @@ private:
|
||||||
"}";
|
"}";
|
||||||
ASSERT_EQUALS(false, testValueOfX(code, 4U, 4));
|
ASSERT_EQUALS(false, testValueOfX(code, 4U, 4));
|
||||||
|
|
||||||
|
code = "void f(int y) {\n" // #3923
|
||||||
|
" int x = 6;\n"
|
||||||
|
" if (y) { x = 0; }\n"
|
||||||
|
" else { a = x; }\n" // <- x is 6
|
||||||
|
"}";
|
||||||
|
ASSERT_EQUALS(true, testValueOfX(code, 4U, 6));
|
||||||
|
|
||||||
code = "void f() {\n"
|
code = "void f() {\n"
|
||||||
" int x = 32;\n"
|
" int x = 32;\n"
|
||||||
" if (x>=32) return;\n"
|
" if (x>=32) return;\n"
|
||||||
|
|
Loading…
Reference in New Issue