| 87 | } |
| 88 | |
| 89 | void ControlFlowSimplifier::visit(Statement& _st) |
| 90 | { |
| 91 | if (std::holds_alternative<ForLoop>(_st)) |
| 92 | { |
| 93 | ForLoop& forLoop = std::get<ForLoop>(_st); |
| 94 | yulAssert(forLoop.pre.statements.empty(), ""); |
| 95 | |
| 96 | size_t outerBreak = m_numBreakStatements; |
| 97 | size_t outerContinue = m_numContinueStatements; |
| 98 | m_numBreakStatements = 0; |
| 99 | m_numContinueStatements = 0; |
| 100 | |
| 101 | ASTModifier::visit(_st); |
| 102 | |
| 103 | if (!forLoop.body.statements.empty()) |
| 104 | { |
| 105 | bool isTerminating = false; |
| 106 | TerminationFinder::ControlFlow controlFlow = TerminationFinder{m_dialect}.controlFlowKind(forLoop.body.statements.back()); |
| 107 | if (controlFlow == TerminationFinder::ControlFlow::Break) |
| 108 | { |
| 109 | isTerminating = true; |
| 110 | --m_numBreakStatements; |
| 111 | } |
| 112 | else if ( |
| 113 | controlFlow == TerminationFinder::ControlFlow::Terminate || |
| 114 | controlFlow == TerminationFinder::ControlFlow::Leave |
| 115 | ) |
| 116 | isTerminating = true; |
| 117 | |
| 118 | if (isTerminating && m_numContinueStatements == 0 && m_numBreakStatements == 0) |
| 119 | { |
| 120 | If replacement{forLoop.debugData, std::move(forLoop.condition), std::move(forLoop.body)}; |
| 121 | if (controlFlow == TerminationFinder::ControlFlow::Break) |
| 122 | replacement.body.statements.resize(replacement.body.statements.size() - 1); |
| 123 | _st = std::move(replacement); |
| 124 | } |
| 125 | } |
| 126 | |
| 127 | m_numBreakStatements = outerBreak; |
| 128 | m_numContinueStatements = outerContinue; |
| 129 | } |
| 130 | else |
| 131 | ASTModifier::visit(_st); |
| 132 | } |
| 133 | |
| 134 | void ControlFlowSimplifier::simplify(std::vector<yul::Statement>& _statements) |
| 135 | { |
nothing calls this directly
no test coverage detected