aboutsummaryrefslogtreecommitdiffstats
path: root/libsolidity/analysis/ControlFlowAnalyzer.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'libsolidity/analysis/ControlFlowAnalyzer.cpp')
-rw-r--r--libsolidity/analysis/ControlFlowAnalyzer.cpp34
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.");
+ }
+}