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.
 | 
			
		||||
 *
 | 
			
		||||
 * 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``:
 | 
			
		||||
 *
 | 
			
		||||
 * 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``.
 | 
			
		||||
 *   for (Node const& _child: _node.children())
 | 
			
		||||
 *   for (Node const& _child: _node->children())
 | 
			
		||||
 *     // Potentially filter the children to be visited.
 | 
			
		||||
 *     _addChild(_child);
 | 
			
		||||
 *     _addChild(&_child);
 | 
			
		||||
 * }).visited;
 | 
			
		||||
 *
 | 
			
		||||
 * Note that the order of the traversal is *non-deterministic* (the children are stored in a std::set of pointers).
 | 
			
		||||
 */
 | 
			
		||||
template<typename V>
 | 
			
		||||
struct BreadthFirstSearch
 | 
			
		||||
@ -102,20 +103,20 @@ struct BreadthFirstSearch
 | 
			
		||||
	{
 | 
			
		||||
		while (!verticesToTraverse.empty())
 | 
			
		||||
		{
 | 
			
		||||
			V const* v = *verticesToTraverse.begin();
 | 
			
		||||
			V v = *verticesToTraverse.begin();
 | 
			
		||||
			verticesToTraverse.erase(verticesToTraverse.begin());
 | 
			
		||||
			visited.insert(v);
 | 
			
		||||
 | 
			
		||||
			_forEachChild(*v, [this](V const& _vertex) {
 | 
			
		||||
				if (!visited.count(&_vertex))
 | 
			
		||||
					verticesToTraverse.insert(&_vertex);
 | 
			
		||||
			_forEachChild(v, [this](V _vertex) {
 | 
			
		||||
				if (!visited.count(_vertex))
 | 
			
		||||
					verticesToTraverse.emplace(std::move(_vertex));
 | 
			
		||||
			});
 | 
			
		||||
		}
 | 
			
		||||
		return *this;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	std::set<V const*> verticesToTraverse;
 | 
			
		||||
	std::set<V const*> visited{};
 | 
			
		||||
	std::set<V> verticesToTraverse;
 | 
			
		||||
	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
 | 
			
		||||
{
 | 
			
		||||
	// 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);
 | 
			
		||||
	std::set<CFGNode const*> reachable = BreadthFirstSearch<CFGNode const*>{{_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);
 | 
			
		||||
	BreadthFirstSearch<CFGNode const*>{{_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);
 | 
			
		||||
		}
 | 
			
		||||
	);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user