Skip to content

Commit 4d9e69e

Browse files
authored
Fix 11985: False positive: uninitvar (valueflow) (#5781)
1 parent b6e1574 commit 4d9e69e

4 files changed

Lines changed: 60 additions & 7 deletions

File tree

lib/analyzer.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,8 @@ struct Analyzer {
181181
virtual bool stopOnCondition(const Token* condTok) const = 0;
182182
/// The condition that will be assumed during analysis
183183
virtual void assume(const Token* tok, bool state, unsigned int flags = 0) = 0;
184+
/// Update the state of the program at the token
185+
virtual void updateState(const Token* tok) = 0;
184186
/// Return analyzer for expression at token
185187
virtual ValuePtr<Analyzer> reanalyze(Token* tok, const std::string& msg = emptyString) const = 0;
186188
virtual bool invalid() const {

lib/forwardanalyzer.cpp

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -443,7 +443,7 @@ namespace {
443443
if (checkElse && isDoWhile &&
444444
(condTok->hasKnownIntValue() ||
445445
(!bodyAnalysis.isModified() && !condAnalysis.isModified() && condAnalysis.isRead()))) {
446-
if (updateRange(endBlock->link(), endBlock) == Progress::Break)
446+
if (updateScope(endBlock) == Progress::Break)
447447
return Break();
448448
return updateRecursive(condTok);
449449
}
@@ -519,8 +519,17 @@ namespace {
519519
return updateLoop(endToken, endBlock, condTok, initTok, stepTok, true);
520520
}
521521

522-
Progress updateScope(Token* endBlock) {
523-
return updateRange(endBlock->link(), endBlock);
522+
Progress updateScope(Token* endBlock, int depth = 20)
523+
{
524+
if (!endBlock)
525+
return Break();
526+
assert(endBlock->link());
527+
Token* ctx = endBlock->link()->previous();
528+
if (Token::simpleMatch(ctx, ")"))
529+
ctx = ctx->link()->previous();
530+
if (ctx)
531+
analyzer->updateState(ctx);
532+
return updateRange(endBlock->link(), endBlock, depth);
524533
}
525534

526535
Progress updateRange(Token* start, const Token* end, int depth = 20) {
@@ -682,7 +691,7 @@ namespace {
682691
thenBranch.escape = isEscapeScope(endBlock, thenBranch.escapeUnknown);
683692
if (thenBranch.check) {
684693
thenBranch.active = true;
685-
if (updateRange(endCond->next(), endBlock, depth - 1) == Progress::Break)
694+
if (updateScope(endBlock, depth - 1) == Progress::Break)
686695
return Break();
687696
} else if (!elseBranch.check) {
688697
thenBranch.active = true;
@@ -694,7 +703,7 @@ namespace {
694703
elseBranch.escape = isEscapeScope(endBlock->linkAt(2), elseBranch.escapeUnknown);
695704
if (elseBranch.check) {
696705
elseBranch.active = true;
697-
const Progress result = updateRange(endBlock->tokAt(2), endBlock->linkAt(2), depth - 1);
706+
const Progress result = updateScope(endBlock->linkAt(2), depth - 1);
698707
if (result == Progress::Break)
699708
return Break();
700709
} else if (!thenBranch.check) {
@@ -746,7 +755,7 @@ namespace {
746755
} else if (Token::simpleMatch(tok, "try {")) {
747756
Token* endBlock = tok->next()->link();
748757
ForwardTraversal tryTraversal = fork();
749-
tryTraversal.updateRange(tok->next(), endBlock, depth - 1);
758+
tryTraversal.updateScope(endBlock, depth - 1);
750759
bool bail = tryTraversal.actions.isModified();
751760
if (bail) {
752761
actions = tryTraversal.actions;
@@ -760,7 +769,7 @@ namespace {
760769
return Break();
761770
endBlock = endCatch->linkAt(1);
762771
ForwardTraversal ft = fork();
763-
ft.updateRange(endBlock->link(), endBlock, depth - 1);
772+
ft.updateScope(endBlock, depth - 1);
764773
bail |= ft.terminate != Analyzer::Terminate::None || ft.actions.isModified();
765774
}
766775
if (bail)
@@ -880,6 +889,8 @@ Analyzer::Result valueFlowGenericForward(Token* start, const Token* end, const V
880889
if (a->invalid())
881890
return Analyzer::Result{Analyzer::Action::None, Analyzer::Terminate::Bail};
882891
ForwardTraversal ft{a, settings};
892+
if (start)
893+
ft.analyzer->updateState(start);
883894
ft.updateRange(start, end);
884895
return Analyzer::Result{ ft.actions, ft.terminate };
885896
}

lib/valueflow.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2969,6 +2969,13 @@ struct ValueFlowAnalyzer : Analyzer {
29692969
makeConditional();
29702970
}
29712971

2972+
void updateState(const Token* tok) override
2973+
{
2974+
// Update program state
2975+
pms.removeModifiedVars(tok);
2976+
pms.addState(tok, getProgramState());
2977+
}
2978+
29722979
virtual void internalUpdate(Token* /*tok*/, const ValueFlow::Value& /*v*/, Direction /*d*/)
29732980
{
29742981
assert(false && "Internal update unimplemented.");

test/testvalueflow.cpp

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -876,6 +876,23 @@ class TestValueFlow : public TestFixture {
876876
" y=x;\n"
877877
"}";
878878
ASSERT_EQUALS(false, testValueOfX(code, 3U, ValueFlow::Value::MoveKind::MovedVariable));
879+
880+
code = "void g(std::string);\n"
881+
"void foo(std::string x) {\n"
882+
" g(std::move(x));\n"
883+
" int counter = 0;\n"
884+
"\n"
885+
" for (int i = 0; i < 5; i++) {\n"
886+
" if (i % 2 == 0) {\n"
887+
" x = std::to_string(i);\n"
888+
" counter++;\n"
889+
" }\n"
890+
" }\n"
891+
" for (int i = 0; i < counter; i++) {\n"
892+
" if(x > 5) {}\n"
893+
" }\n"
894+
"}\n";
895+
ASSERT_EQUALS(false, testValueOfX(code, 13U, ValueFlow::Value::MoveKind::MovedVariable));
879896
}
880897

881898
void valueFlowCalculations() {
@@ -5671,6 +5688,22 @@ class TestValueFlow : public TestFixture {
56715688
"}";
56725689
values = tokenValues(code, "buflen >=", ValueFlow::Value::ValueType::UNINIT);
56735690
ASSERT_EQUALS(1, values.size());
5691+
5692+
code = "void foo() {\n"
5693+
" int counter = 0;\n"
5694+
" int x;\n"
5695+
" for (int i = 0; i < 5; i++) {\n"
5696+
" if (i % 2 == 0) {\n"
5697+
" x = i;\n"
5698+
" counter++;\n"
5699+
" }\n"
5700+
" }\n"
5701+
" for (int i = 0; i < counter; i++) {\n"
5702+
" if(x > 5) {}\n"
5703+
" }\n"
5704+
"}\n";
5705+
values = tokenValues(code, "x > 5", ValueFlow::Value::ValueType::UNINIT);
5706+
ASSERT_EQUALS(0, values.size());
56745707
}
56755708

56765709
void valueFlowConditionExpressions() {

0 commit comments

Comments
 (0)