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; return true;
if (Token::simpleMatch(condTok, ":")) if (Token::simpleMatch(condTok, ":"))
return true; return true;
bool changed = false; bool stepChangesCond = false;
if (stepTok) { if (stepTok) {
std::pair<const Token*, const Token*> exprToks = stepTok->findExpressionStartEndTokens(); std::pair<const Token*, const Token*> exprToks = stepTok->findExpressionStartEndTokens();
if (exprToks.first != nullptr && exprToks.second != nullptr) 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 // Check for mutation in the condition
changed |= nullptr != const bool condChanged =
findAstNode(condTok, [&](const Token* tok) { nullptr != findAstNode(condTok, [&](const Token* tok) {
return isVariableChanged(tok, 0, settings, true); return isVariableChanged(tok, 0, settings, true);
}); });
const bool changed = stepChangesCond || bodyChangesCond || condChanged;
if (!changed) if (!changed)
return true; return true;
ForwardTraversal ft = fork(true); ForwardTraversal ft = fork(true);
ft.analyzer->assume(condTok, false, Analyzer::Assume::Absolute);
ft.updateScope(endBlock); ft.updateScope(endBlock);
return ft.isConditionTrue(condTok); return ft.isConditionTrue(condTok) && bodyChangesCond;
} }
Progress updateInnerLoop(Token* endBlock, Token* stepTok, Token* condTok) { 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); programMemoryParseCondition(pm, tok, nullptr, settings, b);
const Token* origin = tok; const Token* origin = tok;
const Token* top = tok->astTop(); const Token* top = tok->astTop();
if (top && Token::Match(top->previous(), "for|while (")) if (top && Token::Match(top->previous(), "for|while|if (") && !Token::simpleMatch(tok->astParent(), "?")) {
origin = top->link(); origin = top->link()->next();
if (!b && origin->link()) {
origin = origin->link();
}
}
replace(pm, origin); replace(pm, origin);
} }

View File

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

View File

@ -5396,6 +5396,17 @@ private:
" return n;\n" " return n;\n"
"}\n"); "}\n");
ASSERT_EQUALS("[test.cpp:4] -> [test.cpp:1]: (warning) Uninitialized variable: i\n", errout.str()); 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 void valueFlowUninitBreak() { // Do not show duplicate warnings about the same uninitialized value