* @throws InternalError thrown on cyclic analysis */
| 579 | * @throws InternalError thrown on cyclic analysis |
| 580 | */ |
| 581 | Progress updateRange(Token* start, const Token* end, int depth = 20) { |
| 582 | if (depth < 0) |
| 583 | return Break(Analyzer::Terminate::Bail); |
| 584 | std::size_t i = 0; |
| 585 | for (Token* tok = start; precedes(tok, end); tok = tok->next()) { |
| 586 | Token* next = nullptr; |
| 587 | if (tok->index() <= i) |
| 588 | throw InternalError(tok, "Cyclic forward analysis."); |
| 589 | i = tok->index(); |
| 590 | |
| 591 | if (tok->link()) { |
| 592 | // Skip casts.. |
| 593 | if (tok->str() == "(" && !tok->astOperand2() && tok->isCast()) { |
| 594 | tok = tok->link(); |
| 595 | continue; |
| 596 | } |
| 597 | // Skip template arguments.. |
| 598 | if (tok->str() == "<") { |
| 599 | tok = tok->link(); |
| 600 | continue; |
| 601 | } |
| 602 | } |
| 603 | |
| 604 | // Evaluate RHS of assignment before LHS |
| 605 | if (Token* assignTok = assignExpr(tok)) { |
| 606 | if (updateRecursive(assignTok) == Progress::Break) |
| 607 | return Break(); |
| 608 | tok = nextAfterAstRightmostLeaf(assignTok); |
| 609 | if (!tok) |
| 610 | return Break(); |
| 611 | } else if (Token::simpleMatch(tok, ") {") && Token::Match(tok->link()->previous(), "for|while (") && |
| 612 | !Token::simpleMatch(tok->link()->astOperand2(), ":")) { |
| 613 | // In the middle of a loop structure so bail |
| 614 | return Break(Analyzer::Terminate::Bail); |
| 615 | } else if (tok->str() == ";" && tok->astParent()) { |
| 616 | Token* top = tok->astTop(); |
| 617 | if (Token::Match(top->previous(), "for|while (") && Token::simpleMatch(top->link(), ") {")) { |
| 618 | Token* endCond = top->link(); |
| 619 | Token* endBlock = endCond->linkAt(1); |
| 620 | Token* condTok = getCondTok(top); |
| 621 | Token* stepTok = getStepTok(top); |
| 622 | // The semicolon should belong to the initTok otherwise something went wrong, so just bail |
| 623 | if (tok->astOperand2() != condTok && !Token::simpleMatch(tok->astOperand2(), ";")) |
| 624 | return Break(Analyzer::Terminate::Bail); |
| 625 | if (updateLoop(end, endBlock, condTok, nullptr, stepTok) == Progress::Break) |
| 626 | return Break(); |
| 627 | } |
| 628 | } else if (tok->str() == "break") { |
| 629 | const Token *scopeEndToken = findNextTokenFromBreak(tok); |
| 630 | if (!scopeEndToken) |
| 631 | return Break(); |
| 632 | tok = skipTo(tok, scopeEndToken, end); |
| 633 | if (!precedes(tok, end)) |
| 634 | return Break(Analyzer::Terminate::Escape); |
| 635 | if (!analyzer->lowerToPossible()) |
| 636 | return Break(Analyzer::Terminate::Bail); |
| 637 | // TODO: Don't break, instead move to the outer scope |
| 638 | if (!tok) |
no test coverage detected