| 5229 | } |
| 5230 | |
| 5231 | static void valueFlowForLoopSimplify(Token* const bodyStart, |
| 5232 | const Token* expr, |
| 5233 | bool globalvar, |
| 5234 | const MathLib::bigint value, |
| 5235 | const TokenList& tokenlist, |
| 5236 | ErrorLogger& errorLogger, |
| 5237 | const Settings& settings) |
| 5238 | { |
| 5239 | // TODO: Refactor this to use arbitrary expressions |
| 5240 | assert(expr->varId() > 0); |
| 5241 | const Token * const bodyEnd = bodyStart->link(); |
| 5242 | |
| 5243 | // Is variable modified inside for loop |
| 5244 | if (isVariableChanged(bodyStart, bodyEnd, expr->varId(), globalvar, settings)) |
| 5245 | return; |
| 5246 | |
| 5247 | if (const Token* escape = findEscapeStatement(bodyStart->scope(), settings.library)) { |
| 5248 | if (settings.debugwarnings) |
| 5249 | bailout(tokenlist, errorLogger, escape, "For loop variable bailout on escape statement"); |
| 5250 | return; |
| 5251 | } |
| 5252 | |
| 5253 | for (Token *tok2 = bodyStart->next(); tok2 != bodyEnd; tok2 = tok2->next()) { |
| 5254 | if (tok2->varId() == expr->varId()) { |
| 5255 | const Token * parent = tok2->astParent(); |
| 5256 | while (parent) { |
| 5257 | const Token * const p = parent; |
| 5258 | parent = parent->astParent(); |
| 5259 | if (!parent || parent->str() == ":") |
| 5260 | break; |
| 5261 | if (parent->str() == "?") { |
| 5262 | if (parent->astOperand2() != p) |
| 5263 | parent = nullptr; |
| 5264 | break; |
| 5265 | } |
| 5266 | } |
| 5267 | if (parent) { |
| 5268 | if (settings.debugwarnings) |
| 5269 | bailout(tokenlist, errorLogger, tok2, "For loop variable " + tok2->str() + " stopping on ?"); |
| 5270 | continue; |
| 5271 | } |
| 5272 | |
| 5273 | ValueFlow::Value value1(value); |
| 5274 | value1.varId = tok2->varId(); |
| 5275 | setTokenValue(tok2, std::move(value1), settings); |
| 5276 | } |
| 5277 | |
| 5278 | if (Token::Match(tok2, "%oror%|&&")) { |
| 5279 | const ProgramMemory programMemory(getProgramMemory(tok2->astTop(), expr, ValueFlow::Value(value), settings)); |
| 5280 | if ((tok2->str() == "&&" && !conditionIsTrue(tok2->astOperand1(), programMemory, settings)) || |
| 5281 | (tok2->str() == "||" && !conditionIsFalse(tok2->astOperand1(), programMemory, settings))) { |
| 5282 | // Skip second expression.. |
| 5283 | Token *parent = tok2; |
| 5284 | while (parent && parent->str() == tok2->str()) |
| 5285 | parent = parent->astParent(); |
| 5286 | // Jump to end of condition |
| 5287 | if (parent && parent->str() == "(") { |
| 5288 | tok2 = parent->link(); |
no test coverage detected