@@ -2432,6 +2432,7 @@ static void valueFlowReverse(TokenList* tokenlist,
24322432}
24332433
24342434static void valueFlowReverse (Token* tok,
2435+ const Token* const endToken,
24352436 const Token* const varToken,
24362437 const std::list<ValueFlow::Value>& values,
24372438 TokenList* tokenlist,
@@ -2442,16 +2443,25 @@ static void valueFlowReverse(Token* tok,
24422443 auto aliases = getAliasesFromValues (values);
24432444 for (const ValueFlow::Value& v : values) {
24442445 VariableAnalyzer a (var, v, aliases, tokenlist);
2445- valueFlowGenericReverse (tok, a, settings);
2446+ valueFlowGenericReverse (tok, endToken, a, settings);
24462447 }
24472448 } else {
24482449 for (const ValueFlow::Value& v : values) {
24492450 ExpressionAnalyzer a (varToken, v, tokenlist);
2450- valueFlowGenericReverse (tok, a, settings);
2451+ valueFlowGenericReverse (tok, endToken, a, settings);
24512452 }
24522453 }
24532454}
24542455
2456+ static void valueFlowReverse (Token* tok,
2457+ const Token* const varToken,
2458+ const std::list<ValueFlow::Value>& values,
2459+ TokenList* tokenlist,
2460+ const Settings* settings)
2461+ {
2462+ valueFlowReverse (tok, nullptr , varToken, values, tokenlist, settings);
2463+ }
2464+
24552465std::string lifetimeType (const Token *tok, const ValueFlow::Value *val)
24562466{
24572467 std::string result;
@@ -4058,6 +4068,7 @@ struct ConditionHandler {
40584068 const Settings* settings) const = 0;
40594069
40604070 virtual void reverse (Token* start,
4071+ const Token* endToken,
40614072 const Token* exprTok,
40624073 const std::list<ValueFlow::Value>& values,
40634074 TokenList* tokenlist,
@@ -4139,6 +4150,8 @@ struct ConditionHandler {
41394150
41404151 if (Token::Match (top, " %assign%" ))
41414152 return ;
4153+ if (Token::Match (cond.vartok ->astParent (), " %assign%|++|--" ))
4154+ return ;
41424155
41434156 if (Token::simpleMatch (tok->astParent (), " ?" ) && tok->astParent ()->isExpandedMacro ()) {
41444157 if (settings->debugwarnings )
@@ -4159,6 +4172,23 @@ struct ConditionHandler {
41594172 return ;
41604173 }
41614174
4175+ std::list<ValueFlow::Value> values = cond.true_values ;
4176+ if (cond.true_values != cond.false_values )
4177+ values.insert (values.end (), cond.false_values .begin (), cond.false_values .end ());
4178+
4179+ // extra logic for unsigned variables 'i>=1' => possible value can also be 0
4180+ if (Token::Match (tok, " <|>" )) {
4181+ values.remove_if ([](const ValueFlow::Value& v) {
4182+ if (v.isIntValue ())
4183+ return v.intvalue != 0 ;
4184+ return false ;
4185+ });
4186+ if (cond.vartok ->valueType () && cond.vartok ->valueType ()->sign != ValueType::Sign::UNSIGNED )
4187+ return ;
4188+ }
4189+ if (values.empty ())
4190+ return ;
4191+
41624192 // bailout: for/while-condition, variable is changed in while loop
41634193 if (Token::Match (top->previous (), " for|while (" ) && Token::simpleMatch (top->link (), " ) {" )) {
41644194
@@ -4177,40 +4207,31 @@ struct ConditionHandler {
41774207 }
41784208
41794209 // Variable changed in loop code
4180- if (Token::Match (top->previous (), " for|while (" )) {
4181- const Token* const start = top;
4182- const Token* const block = top->link ()->next ();
4183- const Token* const end = block->link ();
4184-
4185- if (isExpressionChanged (cond.vartok , start, end, settings, tokenlist->isCPP ())) {
4186- if (settings->debugwarnings )
4187- bailout (tokenlist,
4188- errorLogger,
4189- tok,
4190- " variable '" + cond.vartok ->expressionString () + " ' used in loop" );
4191- return ;
4210+ const Token* const start = top;
4211+ const Token* const block = top->link ()->next ();
4212+ const Token* const end = block->link ();
4213+
4214+ if (isExpressionChanged (cond.vartok , start, end, settings, tokenlist->isCPP ())) {
4215+ // If its reassigned in loop then analyze from the end
4216+ if (!Token::Match (tok, " %assign%|++|--" ) &&
4217+ findExpression (cond.vartok ->exprId (), start, end, [&](const Token* tok2) {
4218+ return Token::Match (tok2->astParent (), " %assign%" ) && astIsLHS (tok2);
4219+ })) {
4220+ // Start at the end of the loop body
4221+ Token* bodyTok = top->link ()->next ();
4222+ reverse (bodyTok->link (), bodyTok, cond.vartok , values, tokenlist, settings);
41924223 }
4224+ if (settings->debugwarnings )
4225+ bailout (tokenlist,
4226+ errorLogger,
4227+ tok,
4228+ " variable '" + cond.vartok ->expressionString () + " ' used in loop" );
4229+ return ;
41934230 }
41944231 }
41954232
4196- std::list<ValueFlow::Value> values = cond.true_values ;
4197- if (cond.true_values != cond.false_values )
4198- values.insert (values.end (), cond.false_values .begin (), cond.false_values .end ());
4199-
4200- // extra logic for unsigned variables 'i>=1' => possible value can also be 0
4201- if (Token::Match (tok, " <|>" )) {
4202- values.remove_if ([](const ValueFlow::Value& v) {
4203- if (v.isIntValue ())
4204- return v.intvalue != 0 ;
4205- return false ;
4206- });
4207- if (cond.vartok ->valueType () && cond.vartok ->valueType ()->sign != ValueType::Sign::UNSIGNED )
4208- return ;
4209- }
4210- if (values.empty ())
4211- return ;
42124233 Token* startTok = tok->astParent () ? tok->astParent () : tok->previous ();
4213- reverse (startTok, cond.vartok , values, tokenlist, settings);
4234+ reverse (startTok, nullptr , cond.vartok , values, tokenlist, settings);
42144235 });
42154236 }
42164237
@@ -4453,11 +4474,13 @@ struct SimpleConditionHandler : ConditionHandler {
44534474 }
44544475
44554476 virtual void reverse (Token* start,
4477+ const Token* endToken,
44564478 const Token* exprTok,
44574479 const std::list<ValueFlow::Value>& values,
44584480 TokenList* tokenlist,
4459- const Settings* settings) const OVERRIDE {
4460- return valueFlowReverse (start, exprTok, values, tokenlist, settings);
4481+ const Settings* settings) const OVERRIDE
4482+ {
4483+ return valueFlowReverse (start, endToken, exprTok, values, tokenlist, settings);
44614484 }
44624485
44634486 virtual Condition parse (const Token* tok, const Settings*) const OVERRIDE {
@@ -5803,6 +5826,7 @@ static Analyzer::Action valueFlowContainerForward(Token* tok,
58035826}
58045827
58055828static void valueFlowContainerReverse (Token* tok,
5829+ const Token* const endToken,
58065830 const Token* const varToken,
58075831 const std::list<ValueFlow::Value>& values,
58085832 TokenList* tokenlist,
@@ -5812,10 +5836,19 @@ static void valueFlowContainerReverse(Token* tok,
58125836 auto aliases = getAliasesFromValues (values);
58135837 for (const ValueFlow::Value& value : values) {
58145838 ContainerVariableAnalyzer a (var, value, aliases, tokenlist);
5815- valueFlowGenericReverse (tok, a, settings);
5839+ valueFlowGenericReverse (tok, endToken, a, settings);
58165840 }
58175841}
58185842
5843+ static void valueFlowContainerReverse (Token* tok,
5844+ const Token* const varToken,
5845+ const std::list<ValueFlow::Value>& values,
5846+ TokenList* tokenlist,
5847+ const Settings* settings)
5848+ {
5849+ valueFlowContainerReverse (tok, nullptr , varToken, values, tokenlist, settings);
5850+ }
5851+
58195852static bool isContainerSizeChanged (const Token *tok, int depth)
58205853{
58215854 if (!tok)
@@ -6162,15 +6195,17 @@ struct ContainerConditionHandler : ConditionHandler {
61626195 }
61636196
61646197 virtual void reverse (Token* start,
6198+ const Token* endTok,
61656199 const Token* exprTok,
61666200 const std::list<ValueFlow::Value>& values,
61676201 TokenList* tokenlist,
6168- const Settings* settings) const OVERRIDE {
6202+ const Settings* settings) const OVERRIDE
6203+ {
61696204 if (values.empty ())
61706205 return ;
61716206 if (!exprTok->variable ())
61726207 return ;
6173- return valueFlowContainerReverse (start, exprTok, values, tokenlist, settings);
6208+ return valueFlowContainerReverse (start, endTok, exprTok, values, tokenlist, settings);
61746209 }
61756210
61766211 virtual Condition parse (const Token* tok, const Settings*) const OVERRIDE {
0 commit comments