diff options
author | Daniel Kirchner <daniel@ekpyron.org> | 2019-01-09 02:33:46 +0800 |
---|---|---|
committer | Daniel Kirchner <daniel@ekpyron.org> | 2019-01-10 17:36:50 +0800 |
commit | 0dfd4a726eb7e6fa8a5e886a0d80bb5bf3d9b7dc (patch) | |
tree | 8457ac70f7e9921d9825e939f2ff23ffc1259a46 /libsolidity/analysis/ControlFlowAnalyzer.cpp | |
parent | 63319cfdcd7668a75caaacd0d8f3a83a62c31525 (diff) | |
download | dexon-solidity-0dfd4a726eb7e6fa8a5e886a0d80bb5bf3d9b7dc.tar dexon-solidity-0dfd4a726eb7e6fa8a5e886a0d80bb5bf3d9b7dc.tar.gz dexon-solidity-0dfd4a726eb7e6fa8a5e886a0d80bb5bf3d9b7dc.tar.bz2 dexon-solidity-0dfd4a726eb7e6fa8a5e886a0d80bb5bf3d9b7dc.tar.lz dexon-solidity-0dfd4a726eb7e6fa8a5e886a0d80bb5bf3d9b7dc.tar.xz dexon-solidity-0dfd4a726eb7e6fa8a5e886a0d80bb5bf3d9b7dc.tar.zst dexon-solidity-0dfd4a726eb7e6fa8a5e886a0d80bb5bf3d9b7dc.zip |
Warn about unreachable code.
Diffstat (limited to 'libsolidity/analysis/ControlFlowAnalyzer.cpp')
-rw-r--r-- | libsolidity/analysis/ControlFlowAnalyzer.cpp | 34 |
1 files changed, 34 insertions, 0 deletions
diff --git a/libsolidity/analysis/ControlFlowAnalyzer.cpp b/libsolidity/analysis/ControlFlowAnalyzer.cpp index 3adf6318..b801547f 100644 --- a/libsolidity/analysis/ControlFlowAnalyzer.cpp +++ b/libsolidity/analysis/ControlFlowAnalyzer.cpp @@ -18,6 +18,7 @@ #include <libsolidity/analysis/ControlFlowAnalyzer.h> #include <liblangutil/SourceLocation.h> +#include <libdevcore/Algorithms.h> #include <boost/range/algorithm/sort.hpp> using namespace std; @@ -36,6 +37,7 @@ bool ControlFlowAnalyzer::visit(FunctionDefinition const& _function) { auto const& functionFlow = m_cfg.functionFlow(_function); checkUninitializedAccess(functionFlow.entry, functionFlow.exit); + checkUnreachable(functionFlow.entry, functionFlow.exit, functionFlow.revert); } return false; } @@ -145,3 +147,35 @@ void ControlFlowAnalyzer::checkUninitializedAccess(CFGNode const* _entry, CFGNod } } } + +void ControlFlowAnalyzer::checkUnreachable(CFGNode const* _entry, CFGNode const* _exit, CFGNode const* _revert) const +{ + // collect all nodes reachable from the entry point + std::set<CFGNode const*> reachable = BreadthFirstSearch<CFGNode>{{_entry}}.run( + [](CFGNode const& _node, auto&& _addChild) { + for (CFGNode const* exit: _node.exits) + _addChild(*exit); + } + ).visited; + + // traverse all paths backwards from exit and revert + // and extract (valid) source locations of unreachable nodes into sorted set + std::set<SourceLocation> unreachable; + BreadthFirstSearch<CFGNode>{{_exit, _revert}}.run( + [&](CFGNode const& _node, auto&& _addChild) { + if (!reachable.count(&_node) && !_node.location.isEmpty()) + unreachable.insert(_node.location); + for (CFGNode const* entry: _node.entries) + _addChild(*entry); + } + ); + + for (auto it = unreachable.begin(); it != unreachable.end();) + { + SourceLocation location = *it++; + // Extend the location, as long as the next location overlaps (unreachable is sorted). + for (; it != unreachable.end() && it->start <= location.end; ++it) + location.end = std::max(location.end, it->end); + m_errorReporter.warning(location, "Unreachable code."); + } +} |