mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Change BreadthFirstSearch to use value types instead of pointers.
This commit is contained in:
parent
2fb442366f
commit
c047803b80
@ -78,17 +78,18 @@ private:
|
|||||||
/**
|
/**
|
||||||
* Generic breadth first search.
|
* Generic breadth first search.
|
||||||
*
|
*
|
||||||
|
* Note that V needs to be a comparable value type. If it is not, use a pointer type,
|
||||||
|
* but note that this might lead to non-deterministic traversal.
|
||||||
|
*
|
||||||
* Example: Gather all (recursive) children in a graph starting at (and including) ``root``:
|
* Example: Gather all (recursive) children in a graph starting at (and including) ``root``:
|
||||||
*
|
*
|
||||||
* Node const* root = ...;
|
* Node const* root = ...;
|
||||||
* std::set<Node> allNodes = BreadthFirstSearch<Node>{{root}}.run([](Node const& _node, auto&& _addChild) {
|
* std::set<Node const*> allNodes = BreadthFirstSearch<Node const*>{{root}}.run([](Node const* _node, auto&& _addChild) {
|
||||||
* // Potentially process ``_node``.
|
* // Potentially process ``_node``.
|
||||||
* for (Node const& _child: _node.children())
|
* for (Node const& _child: _node->children())
|
||||||
* // Potentially filter the children to be visited.
|
* // Potentially filter the children to be visited.
|
||||||
* _addChild(_child);
|
* _addChild(&_child);
|
||||||
* }).visited;
|
* }).visited;
|
||||||
*
|
|
||||||
* Note that the order of the traversal is *non-deterministic* (the children are stored in a std::set of pointers).
|
|
||||||
*/
|
*/
|
||||||
template<typename V>
|
template<typename V>
|
||||||
struct BreadthFirstSearch
|
struct BreadthFirstSearch
|
||||||
@ -102,20 +103,20 @@ struct BreadthFirstSearch
|
|||||||
{
|
{
|
||||||
while (!verticesToTraverse.empty())
|
while (!verticesToTraverse.empty())
|
||||||
{
|
{
|
||||||
V const* v = *verticesToTraverse.begin();
|
V v = *verticesToTraverse.begin();
|
||||||
verticesToTraverse.erase(verticesToTraverse.begin());
|
verticesToTraverse.erase(verticesToTraverse.begin());
|
||||||
visited.insert(v);
|
visited.insert(v);
|
||||||
|
|
||||||
_forEachChild(*v, [this](V const& _vertex) {
|
_forEachChild(v, [this](V _vertex) {
|
||||||
if (!visited.count(&_vertex))
|
if (!visited.count(_vertex))
|
||||||
verticesToTraverse.insert(&_vertex);
|
verticesToTraverse.emplace(std::move(_vertex));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::set<V const*> verticesToTraverse;
|
std::set<V> verticesToTraverse;
|
||||||
std::set<V const*> visited{};
|
std::set<V> visited{};
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -151,22 +151,22 @@ void ControlFlowAnalyzer::checkUninitializedAccess(CFGNode const* _entry, CFGNod
|
|||||||
void ControlFlowAnalyzer::checkUnreachable(CFGNode const* _entry, CFGNode const* _exit, CFGNode const* _revert) const
|
void ControlFlowAnalyzer::checkUnreachable(CFGNode const* _entry, CFGNode const* _exit, CFGNode const* _revert) const
|
||||||
{
|
{
|
||||||
// collect all nodes reachable from the entry point
|
// collect all nodes reachable from the entry point
|
||||||
std::set<CFGNode const*> reachable = BreadthFirstSearch<CFGNode>{{_entry}}.run(
|
std::set<CFGNode const*> reachable = BreadthFirstSearch<CFGNode const*>{{_entry}}.run(
|
||||||
[](CFGNode const& _node, auto&& _addChild) {
|
[](CFGNode const* _node, auto&& _addChild) {
|
||||||
for (CFGNode const* exit: _node.exits)
|
for (CFGNode const* exit: _node->exits)
|
||||||
_addChild(*exit);
|
_addChild(exit);
|
||||||
}
|
}
|
||||||
).visited;
|
).visited;
|
||||||
|
|
||||||
// traverse all paths backwards from exit and revert
|
// traverse all paths backwards from exit and revert
|
||||||
// and extract (valid) source locations of unreachable nodes into sorted set
|
// and extract (valid) source locations of unreachable nodes into sorted set
|
||||||
std::set<SourceLocation> unreachable;
|
std::set<SourceLocation> unreachable;
|
||||||
BreadthFirstSearch<CFGNode>{{_exit, _revert}}.run(
|
BreadthFirstSearch<CFGNode const*>{{_exit, _revert}}.run(
|
||||||
[&](CFGNode const& _node, auto&& _addChild) {
|
[&](CFGNode const* _node, auto&& _addChild) {
|
||||||
if (!reachable.count(&_node) && !_node.location.isEmpty())
|
if (!reachable.count(_node) && !_node->location.isEmpty())
|
||||||
unreachable.insert(_node.location);
|
unreachable.insert(_node->location);
|
||||||
for (CFGNode const* entry: _node.entries)
|
for (CFGNode const* entry: _node->entries)
|
||||||
_addChild(*entry);
|
_addChild(entry);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user