1bbe25317SEugene Zelenko //===- CFGReachabilityAnalysis.cpp - Basic reachability analysis ----------===//
280861ca9STed Kremenek //
3*2946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*2946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
5*2946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
680861ca9STed Kremenek //
780861ca9STed Kremenek //===----------------------------------------------------------------------===//
880861ca9STed Kremenek //
980861ca9STed Kremenek // This file defines a flow-sensitive, (mostly) path-insensitive reachability
1080861ca9STed Kremenek // analysis based on Clang's CFGs. Clients can query if a given basic block
1180861ca9STed Kremenek // is reachable within the CFG.
1280861ca9STed Kremenek //
1380861ca9STed Kremenek //===----------------------------------------------------------------------===//
1480861ca9STed Kremenek
1580861ca9STed Kremenek #include "clang/Analysis/Analyses/CFGReachabilityAnalysis.h"
1680861ca9STed Kremenek #include "clang/Analysis/CFG.h"
17bbe25317SEugene Zelenko #include "llvm/ADT/BitVector.h"
18bbe25317SEugene Zelenko #include "llvm/ADT/SmallVector.h"
1980861ca9STed Kremenek
2080861ca9STed Kremenek using namespace clang;
2180861ca9STed Kremenek
CFGReverseBlockReachabilityAnalysis(const CFG & cfg)22bbe25317SEugene Zelenko CFGReverseBlockReachabilityAnalysis::CFGReverseBlockReachabilityAnalysis(
23bbe25317SEugene Zelenko const CFG &cfg)
2480861ca9STed Kremenek : analyzed(cfg.getNumBlockIDs(), false) {}
2580861ca9STed Kremenek
isReachable(const CFGBlock * Src,const CFGBlock * Dst)26ddc06d0bSTed Kremenek bool CFGReverseBlockReachabilityAnalysis::isReachable(const CFGBlock *Src,
2780861ca9STed Kremenek const CFGBlock *Dst) {
2880861ca9STed Kremenek const unsigned DstBlockID = Dst->getBlockID();
2980861ca9STed Kremenek
3080861ca9STed Kremenek // If we haven't analyzed the destination node, run the analysis now
3180861ca9STed Kremenek if (!analyzed[DstBlockID]) {
3280861ca9STed Kremenek mapReachability(Dst);
3380861ca9STed Kremenek analyzed[DstBlockID] = true;
3480861ca9STed Kremenek }
3580861ca9STed Kremenek
3680861ca9STed Kremenek // Return the cached result
3780861ca9STed Kremenek return reachable[DstBlockID][Src->getBlockID()];
3880861ca9STed Kremenek }
3980861ca9STed Kremenek
4080861ca9STed Kremenek // Maps reachability to a common node by walking the predecessors of the
4180861ca9STed Kremenek // destination node.
mapReachability(const CFGBlock * Dst)42ddc06d0bSTed Kremenek void CFGReverseBlockReachabilityAnalysis::mapReachability(const CFGBlock *Dst) {
430e62c1ccSChris Lattner SmallVector<const CFGBlock *, 11> worklist;
4480861ca9STed Kremenek llvm::BitVector visited(analyzed.size());
4580861ca9STed Kremenek
4680861ca9STed Kremenek ReachableSet &DstReachability = reachable[Dst->getBlockID()];
4780861ca9STed Kremenek DstReachability.resize(analyzed.size(), false);
4880861ca9STed Kremenek
4980861ca9STed Kremenek // Start searching from the destination node, since we commonly will perform
5080861ca9STed Kremenek // multiple queries relating to a destination node.
5180861ca9STed Kremenek worklist.push_back(Dst);
5280861ca9STed Kremenek bool firstRun = true;
5380861ca9STed Kremenek
5480861ca9STed Kremenek while (!worklist.empty()) {
5525284cc9SRobert Wilhelm const CFGBlock *block = worklist.pop_back_val();
5680861ca9STed Kremenek
5780861ca9STed Kremenek if (visited[block->getBlockID()])
5880861ca9STed Kremenek continue;
5980861ca9STed Kremenek visited[block->getBlockID()] = true;
6080861ca9STed Kremenek
6180861ca9STed Kremenek // Update reachability information for this node -> Dst
6280861ca9STed Kremenek if (!firstRun) {
6380861ca9STed Kremenek // Don't insert Dst -> Dst unless it was a predecessor of itself
6480861ca9STed Kremenek DstReachability[block->getBlockID()] = true;
6580861ca9STed Kremenek }
6680861ca9STed Kremenek else
6780861ca9STed Kremenek firstRun = false;
6880861ca9STed Kremenek
6980861ca9STed Kremenek // Add the predecessors to the worklist.
7080861ca9STed Kremenek for (CFGBlock::const_pred_iterator i = block->pred_begin(),
7180861ca9STed Kremenek e = block->pred_end(); i != e; ++i) {
724b6fee6cSTed Kremenek if (*i)
7380861ca9STed Kremenek worklist.push_back(*i);
7480861ca9STed Kremenek }
7580861ca9STed Kremenek }
7680861ca9STed Kremenek }
77