@@ -262,26 +262,26 @@ ProgramMemory::Map::iterator ProgramMemory::find(nonneg int exprid)
262262 return mValues ->find (ExprIdToken::create (exprid));
263263}
264264
265- static ValueFlow::Value execute (const Token* expr, ProgramMemory& pm, const Settings& settings);
265+ static ValueFlow::Value execute (const Token* expr, ProgramMemory& pm, const Settings& settings, const ProgramMemory::Map& vars = {} );
266266
267- static bool evaluateCondition (MathLib::bigint r, const Token* condition, ProgramMemory& pm, const Settings& settings)
267+ static bool evaluateCondition (MathLib::bigint r, const Token* condition, ProgramMemory& pm, const Settings& settings, const ProgramMemory::Map& vars = {} )
268268{
269269 if (!condition)
270270 return false ;
271271 MathLib::bigint result = 0 ;
272272 bool error = false ;
273- execute (condition, pm, &result, &error, settings);
273+ execute (condition, pm, &result, &error, settings, vars );
274274 return !error && result == r;
275275}
276276
277- bool conditionIsFalse (const Token* condition, ProgramMemory pm, const Settings& settings)
277+ bool conditionIsFalse (const Token* condition, ProgramMemory pm, const Settings& settings, const ProgramMemory::Map& vars )
278278{
279- return evaluateCondition (0 , condition, pm, settings);
279+ return evaluateCondition (0 , condition, pm, settings, vars );
280280}
281281
282- bool conditionIsTrue (const Token* condition, ProgramMemory pm, const Settings& settings)
282+ bool conditionIsTrue (const Token* condition, ProgramMemory pm, const Settings& settings, const ProgramMemory::Map& vars )
283283{
284- return evaluateCondition (1 , condition, pm, settings);
284+ return evaluateCondition (1 , condition, pm, settings, vars );
285285}
286286
287287static bool frontIs (const std::vector<MathLib::bigint>& v, bool i)
@@ -443,7 +443,7 @@ static void fillProgramMemoryFromAssignments(ProgramMemory& pm, const Token* tok
443443 if (!pm.hasValue (vartok->exprId ())) {
444444 const Token* valuetok = tok2->astOperand2 ();
445445 ProgramMemory local = state;
446- pm.setValue (vartok, execute (valuetok, local, settings));
446+ pm.setValue (vartok, execute (valuetok, local, settings, vars ));
447447 }
448448 }
449449 } else if (Token::simpleMatch (tok2, " )" ) && tok2->link () &&
@@ -547,19 +547,21 @@ void ProgramMemoryState::addState(const Token* tok, const ProgramMemory::Map& va
547547 replace (std::move (local), tok);
548548}
549549
550- void ProgramMemoryState::assume (const Token* tok, bool b, bool isEmpty)
550+ void ProgramMemoryState::assume (const Token* tok, bool b, bool isEmpty, const Token* origin )
551551{
552552 ProgramMemory pm = state;
553553 if (isEmpty)
554554 pm.setContainerSizeValue (tok, 0 , b);
555555 else
556556 programMemoryParseCondition (pm, tok, nullptr , settings, b);
557- const Token* origin = tok;
558- const Token* top = tok->astTop ();
559- if (Token::Match (top->previous (), " for|while|if (" ) && !Token::simpleMatch (tok->astParent (), " ?" )) {
560- origin = top->link ()->next ();
561- if (!b && origin->link ()) {
562- origin = origin->link ();
557+ if (!origin) {
558+ origin = tok;
559+ const Token* top = tok->astTop ();
560+ if (Token::Match (top->previous (), " for|while|if (" ) && !Token::simpleMatch (tok->astParent (), " ?" )) {
561+ origin = top->link ()->next ();
562+ if (!b && origin->link ()) {
563+ origin = origin->link ();
564+ }
563565 }
564566 }
565567 replace (std::move (pm), origin);
@@ -1316,6 +1318,10 @@ namespace {
13161318 struct Executor {
13171319 ProgramMemory* pm;
13181320 const Settings& settings;
1321+ // The values that are being tracked by the forward/reverse analysis. These take precedence
1322+ // over what is stored in the program memory: a tracked value is the authoritative current
1323+ // value of its expression, so any cached value that depends on it must be re-evaluated.
1324+ const ProgramMemory::Map* vars = nullptr ;
13191325 int fdepth = 4 ;
13201326 int depth = 10 ;
13211327
@@ -1324,6 +1330,25 @@ namespace {
13241330 assert (pm != nullptr );
13251331 }
13261332
1333+ // Is the tracked value for this expression available?
1334+ const ValueFlow::Value* getTrackedValue (const Token* expr) const {
1335+ if (!vars || expr->exprId () == 0 )
1336+ return nullptr ;
1337+ const auto it = vars->find (ExprIdToken::create (expr->exprId ()));
1338+ return it == vars->end () ? nullptr : &it->second ;
1339+ }
1340+
1341+ // Does the expression read a tracked value? If so, any value cached in the program memory
1342+ // for it may be stale (the tracked value may have changed since it was cached), so it must
1343+ // be re-evaluated rather than served from the cache.
1344+ bool dependsOnTrackedValue (const Token* expr) const {
1345+ if (!vars || vars->empty ())
1346+ return false ;
1347+ return findAstNode (expr, [&](const Token* tok) {
1348+ return getTrackedValue (tok) != nullptr ;
1349+ }) != nullptr ;
1350+ }
1351+
13271352 static ValueFlow::Value unknown () {
13281353 return ValueFlow::Value::unknown ();
13291354 }
@@ -1622,7 +1647,10 @@ namespace {
16221647 }
16231648 return execute (expr->astOperand1 ());
16241649 }
1625- if (expr->exprId () > 0 && pm->hasValue (expr->exprId ())) {
1650+ // A tracked value is the authoritative current value of its expression.
1651+ if (const ValueFlow::Value* tracked = getTrackedValue (expr))
1652+ return *tracked;
1653+ if (expr->exprId () > 0 && pm->hasValue (expr->exprId ()) && !dependsOnTrackedValue (expr)) {
16261654 ValueFlow::Value result = utils::as_const (*pm).at (expr->exprId ());
16271655 if (result.isImpossible () && result.isIntValue () && result.intvalue == 0 && isUsedAsBool (expr, settings)) {
16281656 result.intvalue = !result.intvalue ;
@@ -1815,9 +1843,10 @@ namespace {
18151843 };
18161844} // namespace
18171845
1818- static ValueFlow::Value execute (const Token* expr, ProgramMemory& pm, const Settings& settings)
1846+ static ValueFlow::Value execute (const Token* expr, ProgramMemory& pm, const Settings& settings, const ProgramMemory::Map& vars )
18191847{
18201848 Executor ex{&pm, settings};
1849+ ex.vars = &vars;
18211850 return ex.execute (expr);
18221851}
18231852
@@ -1907,9 +1936,10 @@ void execute(const Token* expr,
19071936 ProgramMemory& programMemory,
19081937 MathLib::bigint* result,
19091938 bool * error,
1910- const Settings& settings)
1939+ const Settings& settings,
1940+ const ProgramMemory::Map& vars)
19111941{
1912- ValueFlow::Value v = execute (expr, programMemory, settings);
1942+ ValueFlow::Value v = execute (expr, programMemory, settings, vars );
19131943 if (!v.isIntValue () || v.isImpossible ()) {
19141944 if (error)
19151945 *error = true ;
0 commit comments