Fix 11412: False positive: uninitvar (#4624)
* Dont remove modified variables from dead code * Add test for 11412 * Format
This commit is contained in:
parent
c150317f02
commit
7acbb656f3
|
@ -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) {
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Reference in New Issue