ValueFlowBeforeCondition: Fix wrong value in do-while condition when there is a break in the loop body

This commit is contained in:
Daniel Marjamäki 2018-02-24 22:07:34 +01:00
parent 1b53e3ec1d
commit 7701e4594a
2 changed files with 40 additions and 0 deletions

View File

@ -1126,6 +1126,36 @@ static void valueFlowReverse(TokenList *tokenlist,
continue;
}
// do-while condition, break in the loop body
{
const Token *parent = tok2->astParent();
while (parent && !Token::simpleMatch(parent->previous(), "while ("))
parent = parent->astParent();
if (parent && Token::simpleMatch(parent->tokAt(-2), "} while (") && Token::simpleMatch(parent->linkAt(-2)->previous(), "do {")) {
bool breakBailout = false;
for (const Token *iftok = parent->linkAt(-2); iftok != parent; iftok = iftok->next()) {
if (!Token::simpleMatch(iftok, "if ("))
continue;
if (!Token::Match(iftok->linkAt(1), ") { break"))
continue;
ProgramMemory programMemory;
programMemory.setIntValue(varid, num);
if (conditionIsTrue(iftok->next()->astOperand2(), programMemory)) {
breakBailout = true;
break;
}
}
if (breakBailout) {
if (settings->debugwarnings)
bailout(tokenlist,
errorLogger,
tok2,
"no simplification of " + tok2->str() + " in do-while condition since there is a break in the loop body");
break;
}
}
}
setTokenValue(tok2, val, settings);
if (val2.condition)
setTokenValue(tok2,val2, settings);

View File

@ -707,6 +707,16 @@ private:
" if (x == 123) {}\n"
"}";
ASSERT_EQUALS(true, testValueOfX(code, 3U, 123));
// after loop
code = "void f(struct X *x) {\n"
" do {\n"
" if (!x)\n"
" break;\n"
" } while (x->a);\n"
" if (x) {}\n"
"}\n";
ASSERT_EQUALS(false, testValueOfX(code, 5U, 0));
}
void valueFlowBeforeConditionAssignIncDec() { // assignment / increment