Fix 11412: False positive: uninitvar (#4624)

* Dont remove modified variables from dead code

* Add test for 11412

* Format
This commit is contained in:
Paul Fultz II 2022-12-09 00:15:47 -06:00 committed by GitHub
parent c150317f02
commit 7acbb656f3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 30 additions and 13 deletions

View File

@ -394,24 +394,24 @@ struct ForwardTraversal {
return true;
if (Token::simpleMatch(condTok, ":"))
return true;
bool changed = false;
bool stepChangesCond = false;
if (stepTok) {
std::pair<const Token*, const Token*> exprToks = stepTok->findExpressionStartEndTokens();
if (exprToks.first != nullptr && exprToks.second != nullptr)
changed |= isExpressionChanged(condTok, exprToks.first, exprToks.second->next(), settings, true);
stepChangesCond |= isExpressionChanged(condTok, exprToks.first, exprToks.second->next(), settings, true);
}
changed |= isExpressionChanged(condTok, endBlock->link(), endBlock, settings, true);
const bool bodyChangesCond = isExpressionChanged(condTok, endBlock->link(), endBlock, settings, true);
// Check for mutation in the condition
changed |= nullptr !=
findAstNode(condTok, [&](const Token* tok) {
const bool condChanged =
nullptr != findAstNode(condTok, [&](const Token* tok) {
return isVariableChanged(tok, 0, settings, true);
});
const bool changed = stepChangesCond || bodyChangesCond || condChanged;
if (!changed)
return true;
ForwardTraversal ft = fork(true);
ft.analyzer->assume(condTok, false, Analyzer::Assume::Absolute);
ft.updateScope(endBlock);
return ft.isConditionTrue(condTok);
return ft.isConditionTrue(condTok) && bodyChangesCond;
}
Progress updateInnerLoop(Token* endBlock, Token* stepTok, Token* condTok) {

View File

@ -461,8 +461,12 @@ void ProgramMemoryState::assume(const Token* tok, bool b, bool isEmpty)
programMemoryParseCondition(pm, tok, nullptr, settings, b);
const Token* origin = tok;
const Token* top = tok->astTop();
if (top && Token::Match(top->previous(), "for|while ("))
origin = top->link();
if (top && Token::Match(top->previous(), "for|while|if (") && !Token::simpleMatch(tok->astParent(), "?")) {
origin = top->link()->next();
if (!b && origin->link()) {
origin = origin->link();
}
}
replace(pm, origin);
}

View File

@ -2790,11 +2790,13 @@ struct ValueFlowAnalyzer : Analyzer {
if (Token::simpleMatch(startBlock, ";") && Token::simpleMatch(parent->tokAt(-2), "} while ("))
startBlock = parent->linkAt(-2);
const Token* endBlock = startBlock->link();
pms.removeModifiedVars(endBlock);
if (state)
if (state) {
pms.removeModifiedVars(endBlock);
pms.addState(endBlock->previous(), getProgramState());
else if (Token::simpleMatch(endBlock, "} else {"))
pms.addState(endBlock->linkAt(2)->previous(), getProgramState());
} else {
if (Token::simpleMatch(endBlock, "} else {"))
pms.addState(endBlock->linkAt(2)->previous(), getProgramState());
}
}
if (!(flags & Assume::Quiet)) {

View File

@ -5396,6 +5396,17 @@ private:
" return n;\n"
"}\n");
ASSERT_EQUALS("[test.cpp:4] -> [test.cpp:1]: (warning) Uninitialized variable: i\n", errout.str());
// #11412
valueFlowUninit("void f(int n) {\n"
" short* p;\n"
" if (n) {\n"
" p = g(n);\n"
" }\n"
" for (int i = 0; i < n; i++)\n"
" (void)p[i];\n"
"}\n");
ASSERT_EQUALS("", errout.str());
}
void valueFlowUninitBreak() { // Do not show duplicate warnings about the same uninitialized value