@@ -678,11 +678,12 @@ struct ValueFlowAnalyzer : Analyzer {
678678 if (const ValueFlow::Value* v = tok->getKnownValue (ValueFlow::Value::ValueType::INT ))
679679 return {v->intvalue };
680680 std::vector<MathLib::bigint> result;
681- ProgramMemory pm = getProgramMemoryFunc ();
682681 // The tracked values are authoritative: pass them so a value cached in the program memory
683682 // that depends on a tracked value (e.g. 'h(p)' after 'p' was reassigned) is re-evaluated
684- // rather than served stale.
683+ // rather than served stale. The program memory is built from the same state, so compute it
684+ // once here and hand it to the builder.
685685 const ProgramState vars = getProgramState ();
686+ ProgramMemory pm = getProgramMemoryFunc (vars);
686687 if (Token::Match (tok, " &&|%oror%" )) {
687688 if (conditionIsTrue (tok, pm, getSettings (), vars))
688689 result.push_back (1 );
@@ -700,16 +701,16 @@ struct ValueFlowAnalyzer : Analyzer {
700701
701702 std::vector<MathLib::bigint> evaluateInt (const Token* tok) const
702703 {
703- return evaluateInt (tok, [&] {
704- return ProgramMemory{getProgramState () };
704+ return evaluateInt (tok, []( const ProgramState& vars) {
705+ return ProgramMemory{vars };
705706 });
706707 }
707708
708709 std::vector<MathLib::bigint> evaluate (Evaluate e, const Token* tok, const Token* ctx = nullptr ) const override
709710 {
710711 if (e == Evaluate::Integral) {
711- return evaluateInt (tok, [&] {
712- return pms.get (tok, ctx, getProgramState () );
712+ return evaluateInt (tok, [&]( const ProgramState& vars) {
713+ return pms.get (tok, ctx, vars );
713714 });
714715 }
715716 if (e == Evaluate::ContainerEmpty) {
@@ -734,10 +735,9 @@ struct ValueFlowAnalyzer : Analyzer {
734735 isCondBlock = Token::Match (parent->previous (), " if|while (" );
735736 }
736737
737- const Token* startBlock = nullptr ;
738738 const Token* endBlock = nullptr ;
739739 if (isCondBlock) {
740- startBlock = parent->link ()->next ();
740+ const Token* startBlock = parent->link ()->next ();
741741 if (Token::simpleMatch (startBlock, " ;" ) && Token::simpleMatch (parent->tokAt (-2 ), " } while (" ))
742742 startBlock = parent->linkAt (-2 );
743743 endBlock = startBlock->link ();
@@ -757,18 +757,14 @@ struct ValueFlowAnalyzer : Analyzer {
757757 pms.addState (anchor, getProgramState ());
758758 pms.assume (tok, state, flags & Assume::ContainerEmpty, origin);
759759
760- if (isCondBlock && !(flags & Assume::NoState) && !scopeEnd) {
761- if (state) {
762- pms.removeModifiedVars (endBlock);
763- pms.addState (endBlock->previous (), getProgramState ());
764- } else {
765- if (Token::simpleMatch (endBlock, " } else {" ))
766- pms.addState (endBlock->linkAt (2 )->previous (), getProgramState ());
767- else
768- // No else: the false path continues past the closing brace, so record the
769- // assumed state there so it is available to the rest of the enclosing scope.
770- pms.addState (endBlock, getProgramState ());
771- }
760+ // On the false path the block was already traversed (the true path is handled by scopeEnd
761+ // above), so record the assumed state where control continues: past the else block, or past
762+ // the closing brace when there is no else, so it is available to the enclosing scope.
763+ if (isCondBlock && !(flags & Assume::NoState) && !state) {
764+ if (Token::simpleMatch (endBlock, " } else {" ))
765+ pms.addState (endBlock->linkAt (2 )->previous (), getProgramState ());
766+ else
767+ pms.addState (endBlock, getProgramState ());
772768 }
773769
774770 if (!(flags & Assume::Quiet)) {
0 commit comments