/* This file is part of solidity. solidity is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. solidity is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with solidity. If not, see . */ /** * Optimisation stage that removes unreachable code. */ #include #include #include #include #include using namespace std; using namespace dev; using namespace yul; namespace { bool isTerminating(yul::ExpressionStatement const& _exprStmnt) { if (_exprStmnt.expression.type() != typeid(FunctionalInstruction)) return false; auto const& funcInstr = boost::get(_exprStmnt.expression); return eth::SemanticInformation::terminatesControlFlow(funcInstr.instruction); } /// Returns an iterator to the first terminating statement or /// `_block.statements.end()()` when none was found auto findFirstTerminatingStatement(Block& _block) { return find_if( _block.statements.begin(), _block.statements.end(), [](Statement const& _stmnt) { if ( _stmnt.type() == typeid(ExpressionStatement) && isTerminating(boost::get(_stmnt)) ) return true; else if (_stmnt.type() == typeid(Break)) return true; else if (_stmnt.type() == typeid(Continue)) return true; return false; } ); } } void DeadCodeEliminator::operator()(ForLoop& _for) { yulAssert(_for.pre.statements.empty(), "DeadCodeEliminator needs ForLoopInitRewriter as a prerequisite."); ASTModifier::operator()(_for); } void DeadCodeEliminator::operator()(Block& _block) { auto& statements = _block.statements; auto firstTerminatingStatment = findFirstTerminatingStatement(_block); if ( firstTerminatingStatment != statements.end() && firstTerminatingStatment + 1 != statements.end() ) statements.erase( std::remove_if( firstTerminatingStatment + 1, statements.end(), [] (Statement const& _s) { return _s.type() != typeid(yul::FunctionDefinition); } ), statements.end() ); ASTModifier::operator()(_block); }