Skip to content

Commit c111d2e

Browse files
author
Your Name
committed
Update assume logic
1 parent e71dc89 commit c111d2e

4 files changed

Lines changed: 17 additions & 7 deletions

File tree

lib/analyzer.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,9 @@ struct Analyzer {
156156
Quiet = (1 << 0),
157157
Absolute = (1 << 1),
158158
ContainerEmpty = (1 << 2),
159+
// Do not record the program state at the branch boundaries. Used when assuming a
160+
// condition before the branch is traversed, where those states would be premature.
161+
NoState = (1 << 3),
159162
};
160163
};
161164

lib/forwardanalyzer.cpp

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -792,13 +792,16 @@ namespace {
792792
// 'if (do_write)') it does not really reach there, so fork in analyze-only
793793
// mode: the branch's effect is still tracked but nothing is reported in it.
794794
ForwardTraversal ft = fork(!analyzer->updateScope(thenBranch.endBlock, false));
795-
ft.analyzer->assume(condTok, true);
795+
// The branch is traversed below, so don't record its boundary state here.
796+
ft.analyzer->assume(condTok, true, Analyzer::Assume::NoState);
796797
Progress pThen = ft.updateBranch(thenBranch, depth - 1);
797798

798799
// Only commit the condition as false on the main path when it actually
799-
// matters
800+
// matters. With an else the else block is traversed below (so suppress the
801+
// boundary state); without one the false path continues past the closing
802+
// brace and must record the assumed state there.
800803
if (thenBranch.isDead())
801-
analyzer->assume(condTok, false);
804+
analyzer->assume(condTok, false, hasElse ? Analyzer::Assume::NoState : Analyzer::Assume::None);
802805
// The else block is traversed on the main path. If it kills the value
803806
// (modified) the main path stops, but the then-fork may still carry the
804807
// value forward, so defer the break until after the fork continues.

lib/vf_analyzers.cpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -735,7 +735,7 @@ struct ValueFlowAnalyzer : Analyzer {
735735
isCondBlock = Token::Match(parent->previous(), "if|while (");
736736
}
737737

738-
if (isCondBlock) {
738+
if (isCondBlock && !(flags & Assume::NoState)) {
739739
const Token* startBlock = parent->link()->next();
740740
if (Token::simpleMatch(startBlock, ";") && Token::simpleMatch(parent->tokAt(-2), "} while ("))
741741
startBlock = parent->linkAt(-2);
@@ -746,6 +746,10 @@ struct ValueFlowAnalyzer : Analyzer {
746746
} else {
747747
if (Token::simpleMatch(endBlock, "} else {"))
748748
pms.addState(endBlock->linkAt(2)->previous(), getProgramState());
749+
else
750+
// No else: the false path continues past the closing brace, so record the
751+
// assumed state there so it is available to the rest of the enclosing scope.
752+
pms.addState(endBlock, getProgramState());
749753
}
750754
}
751755

test/testvalueflow.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6097,9 +6097,9 @@ class TestValueFlow : public TestFixture {
60976097
" c++;\n"
60986098
"}\n";
60996099
values = tokenValues(code, "c ++ ; }");
6100-
TODO_ASSERT_EQUALS(true, false, values.size() == 2);
6101-
// ASSERT_EQUALS(true, values.front().isUninitValue() || values.back().isUninitValue());
6102-
// ASSERT_EQUALS(true, values.front().isPossible() || values.back().isPossible());
6100+
ASSERT_EQUALS(true, values.size() == 2);
6101+
ASSERT_EQUALS(true, values.front().isUninitValue() || values.back().isUninitValue());
6102+
ASSERT_EQUALS(true, values.front().isPossible() || values.back().isPossible());
61036103
// ASSERT_EQUALS(true, values.front().intvalue == 0 || values.back().intvalue == 0);
61046104

61056105
code = "void b(bool d, bool e) {\n"

0 commit comments

Comments
 (0)