| 5358 | } |
| 5359 | |
| 5360 | static void valueFlowForLoop(const TokenList &tokenlist, const SymbolDatabase& symboldatabase, ErrorLogger &errorLogger, const Settings &settings) |
| 5361 | { |
| 5362 | for (const Scope &scope : symboldatabase.scopeList) { |
| 5363 | if (scope.type != ScopeType::eFor) |
| 5364 | continue; |
| 5365 | |
| 5366 | auto* tok = const_cast<Token*>(scope.classDef); |
| 5367 | auto* const bodyStart = const_cast<Token*>(scope.bodyStart); |
| 5368 | |
| 5369 | if (!Token::simpleMatch(tok->next()->astOperand2(), ";") || |
| 5370 | !Token::simpleMatch(tok->next()->astOperand2()->astOperand2(), ";")) |
| 5371 | continue; |
| 5372 | |
| 5373 | nonneg int varid; |
| 5374 | bool knownInitValue, partialCond; |
| 5375 | MathLib::bigint initValue, stepValue, lastValue; |
| 5376 | |
| 5377 | if (extractForLoopValues(tok, varid, knownInitValue, initValue, partialCond, stepValue, lastValue)) { |
| 5378 | const bool executeBody = !knownInitValue || initValue <= lastValue; |
| 5379 | const Token* vartok = Token::findmatch(tok, "%varid%", bodyStart, varid); |
| 5380 | if (executeBody && vartok) { |
| 5381 | std::list<ValueFlow::Value> initValues; |
| 5382 | initValues.emplace_back(initValue, ValueFlow::Value::Bound::Lower); |
| 5383 | initValues.push_back(ValueFlow::asImpossible(initValues.back())); |
| 5384 | Analyzer::Result result = valueFlowForward(bodyStart, bodyStart->link(), vartok, std::move(initValues), tokenlist, errorLogger, settings); |
| 5385 | |
| 5386 | if (!result.action.isModified()) { |
| 5387 | std::list<ValueFlow::Value> lastValues; |
| 5388 | lastValues.emplace_back(lastValue, ValueFlow::Value::Bound::Upper); |
| 5389 | lastValues.back().conditional = true; |
| 5390 | lastValues.push_back(ValueFlow::asImpossible(lastValues.back())); |
| 5391 | if (stepValue != 1) |
| 5392 | lastValues.pop_front(); |
| 5393 | valueFlowForward(bodyStart, bodyStart->link(), vartok, std::move(lastValues), tokenlist, errorLogger, settings); |
| 5394 | } |
| 5395 | } |
| 5396 | const MathLib::bigint afterValue = executeBody ? lastValue + stepValue : initValue; |
| 5397 | valueFlowForLoopSimplifyAfter(tok, varid, afterValue, tokenlist, errorLogger, settings); |
| 5398 | } else { |
| 5399 | ProgramMemory mem1, mem2, memAfter; |
| 5400 | if (valueFlowForLoop2(tok, mem1, mem2, memAfter, settings)) { |
| 5401 | if (mem1 == memAfter) { // #8192 check if loop never runs |
| 5402 | Token* condTok = getCondTok(tok); |
| 5403 | if (condTok && !condTok->hasKnownIntValue()) { |
| 5404 | ValueFlow::Value v(0); |
| 5405 | v.setKnown(); |
| 5406 | ValueFlow::setTokenValue(condTok, std::move(v), settings); |
| 5407 | } |
| 5408 | } else { |
| 5409 | for (const auto& p : mem1) { |
| 5410 | if (!p.second.isIntValue()) |
| 5411 | continue; |
| 5412 | if (p.second.isImpossible()) |
| 5413 | continue; |
| 5414 | if (p.first.tok->varId() == 0) |
| 5415 | continue; |
| 5416 | valueFlowForLoopSimplify(bodyStart, p.first.tok, false, p.second.intvalue, tokenlist, errorLogger, settings); |
| 5417 | } |
no test coverage detected