File tree Expand file tree Collapse file tree
Expand file tree Collapse file tree Original file line number Diff line number Diff 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
Original file line number Diff line number Diff 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.
Original file line number Diff line number Diff 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
Original file line number Diff line number Diff 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 "
You can’t perform that action at this time.
0 commit comments