ReachableCode.cpp 10.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331
  1. //=- ReachableCodePathInsensitive.cpp ---------------------------*- C++ --*-==//
  2. //
  3. // The LLVM Compiler Infrastructure
  4. //
  5. // This file is distributed under the University of Illinois Open Source
  6. // License. See LICENSE.TXT for details.
  7. //
  8. //===----------------------------------------------------------------------===//
  9. //
  10. // This file implements a flow-sensitive, path-insensitive analysis of
  11. // determining reachable blocks within a CFG.
  12. //
  13. //===----------------------------------------------------------------------===//
  14. #include "clang/Analysis/Analyses/ReachableCode.h"
  15. #include "clang/AST/Expr.h"
  16. #include "clang/AST/ExprCXX.h"
  17. #include "clang/AST/ExprObjC.h"
  18. #include "clang/AST/StmtCXX.h"
  19. #include "clang/Analysis/AnalysisContext.h"
  20. #include "clang/Analysis/CFG.h"
  21. #include "clang/Basic/SourceManager.h"
  22. #include "llvm/ADT/BitVector.h"
  23. #include "llvm/ADT/SmallVector.h"
  24. using namespace clang;
  25. namespace {
  26. class DeadCodeScan {
  27. llvm::BitVector Visited;
  28. llvm::BitVector &Reachable;
  29. llvm::SmallVector<const CFGBlock *, 10> WorkList;
  30. typedef llvm::SmallVector<std::pair<const CFGBlock *, const Stmt *>, 12>
  31. DeferredLocsTy;
  32. DeferredLocsTy DeferredLocs;
  33. public:
  34. DeadCodeScan(llvm::BitVector &reachable)
  35. : Visited(reachable.size()),
  36. Reachable(reachable) {}
  37. void enqueue(const CFGBlock *block);
  38. unsigned scanBackwards(const CFGBlock *Start,
  39. clang::reachable_code::Callback &CB);
  40. bool isDeadCodeRoot(const CFGBlock *Block);
  41. const Stmt *findDeadCode(const CFGBlock *Block);
  42. void reportDeadCode(const Stmt *S,
  43. clang::reachable_code::Callback &CB);
  44. };
  45. }
  46. void DeadCodeScan::enqueue(const CFGBlock *block) {
  47. unsigned blockID = block->getBlockID();
  48. if (Reachable[blockID] || Visited[blockID])
  49. return;
  50. Visited[blockID] = true;
  51. WorkList.push_back(block);
  52. }
  53. bool DeadCodeScan::isDeadCodeRoot(const clang::CFGBlock *Block) {
  54. bool isDeadRoot = true;
  55. for (CFGBlock::const_pred_iterator I = Block->pred_begin(),
  56. E = Block->pred_end(); I != E; ++I) {
  57. if (const CFGBlock *PredBlock = *I) {
  58. unsigned blockID = PredBlock->getBlockID();
  59. if (Visited[blockID]) {
  60. isDeadRoot = false;
  61. continue;
  62. }
  63. if (!Reachable[blockID]) {
  64. isDeadRoot = false;
  65. Visited[blockID] = true;
  66. WorkList.push_back(PredBlock);
  67. continue;
  68. }
  69. }
  70. }
  71. return isDeadRoot;
  72. }
  73. static bool isValidDeadStmt(const Stmt *S) {
  74. if (S->getLocStart().isInvalid())
  75. return false;
  76. if (const BinaryOperator *BO = dyn_cast<BinaryOperator>(S))
  77. return BO->getOpcode() != BO_Comma;
  78. return true;
  79. }
  80. const Stmt *DeadCodeScan::findDeadCode(const clang::CFGBlock *Block) {
  81. for (CFGBlock::const_iterator I = Block->begin(), E = Block->end(); I!=E; ++I)
  82. if (const CFGStmt *CS = I->getAs<CFGStmt>()) {
  83. const Stmt *S = CS->getStmt();
  84. if (isValidDeadStmt(S))
  85. return S;
  86. }
  87. if (CFGTerminator T = Block->getTerminator()) {
  88. const Stmt *S = T.getStmt();
  89. if (isValidDeadStmt(S))
  90. return S;
  91. }
  92. return 0;
  93. }
  94. static int SrcCmp(const void *p1, const void *p2) {
  95. return
  96. ((const std::pair<const CFGBlock *, const Stmt *>*) p2)->second->getLocStart() <
  97. ((const std::pair<const CFGBlock *, const Stmt *>*) p1)->second->getLocStart();
  98. }
  99. unsigned DeadCodeScan::scanBackwards(const clang::CFGBlock *Start,
  100. clang::reachable_code::Callback &CB) {
  101. unsigned count = 0;
  102. enqueue(Start);
  103. while (!WorkList.empty()) {
  104. const CFGBlock *Block = WorkList.pop_back_val();
  105. // It is possible that this block has been marked reachable after
  106. // it was enqueued.
  107. if (Reachable[Block->getBlockID()])
  108. continue;
  109. // Look for any dead code within the block.
  110. const Stmt *S = findDeadCode(Block);
  111. if (!S) {
  112. // No dead code. Possibly an empty block. Look at dead predecessors.
  113. for (CFGBlock::const_pred_iterator I = Block->pred_begin(),
  114. E = Block->pred_end(); I != E; ++I) {
  115. if (const CFGBlock *predBlock = *I)
  116. enqueue(predBlock);
  117. }
  118. continue;
  119. }
  120. // Specially handle macro-expanded code.
  121. if (S->getLocStart().isMacroID()) {
  122. count += clang::reachable_code::ScanReachableFromBlock(Block, Reachable);
  123. continue;
  124. }
  125. if (isDeadCodeRoot(Block)) {
  126. reportDeadCode(S, CB);
  127. count += clang::reachable_code::ScanReachableFromBlock(Block, Reachable);
  128. }
  129. else {
  130. // Record this statement as the possibly best location in a
  131. // strongly-connected component of dead code for emitting a
  132. // warning.
  133. DeferredLocs.push_back(std::make_pair(Block, S));
  134. }
  135. }
  136. // If we didn't find a dead root, then report the dead code with the
  137. // earliest location.
  138. if (!DeferredLocs.empty()) {
  139. llvm::array_pod_sort(DeferredLocs.begin(), DeferredLocs.end(), SrcCmp);
  140. for (DeferredLocsTy::iterator I = DeferredLocs.begin(),
  141. E = DeferredLocs.end(); I != E; ++I) {
  142. const CFGBlock *block = I->first;
  143. if (Reachable[block->getBlockID()])
  144. continue;
  145. reportDeadCode(I->second, CB);
  146. count += clang::reachable_code::ScanReachableFromBlock(block, Reachable);
  147. }
  148. }
  149. return count;
  150. }
  151. static SourceLocation GetUnreachableLoc(const Stmt *S,
  152. SourceRange &R1,
  153. SourceRange &R2) {
  154. R1 = R2 = SourceRange();
  155. if (const Expr *Ex = dyn_cast<Expr>(S))
  156. S = Ex->IgnoreParenImpCasts();
  157. switch (S->getStmtClass()) {
  158. case Expr::BinaryOperatorClass: {
  159. const BinaryOperator *BO = cast<BinaryOperator>(S);
  160. return BO->getOperatorLoc();
  161. }
  162. case Expr::UnaryOperatorClass: {
  163. const UnaryOperator *UO = cast<UnaryOperator>(S);
  164. R1 = UO->getSubExpr()->getSourceRange();
  165. return UO->getOperatorLoc();
  166. }
  167. case Expr::CompoundAssignOperatorClass: {
  168. const CompoundAssignOperator *CAO = cast<CompoundAssignOperator>(S);
  169. R1 = CAO->getLHS()->getSourceRange();
  170. R2 = CAO->getRHS()->getSourceRange();
  171. return CAO->getOperatorLoc();
  172. }
  173. case Expr::BinaryConditionalOperatorClass:
  174. case Expr::ConditionalOperatorClass: {
  175. const AbstractConditionalOperator *CO =
  176. cast<AbstractConditionalOperator>(S);
  177. return CO->getQuestionLoc();
  178. }
  179. case Expr::MemberExprClass: {
  180. const MemberExpr *ME = cast<MemberExpr>(S);
  181. R1 = ME->getSourceRange();
  182. return ME->getMemberLoc();
  183. }
  184. case Expr::ArraySubscriptExprClass: {
  185. const ArraySubscriptExpr *ASE = cast<ArraySubscriptExpr>(S);
  186. R1 = ASE->getLHS()->getSourceRange();
  187. R2 = ASE->getRHS()->getSourceRange();
  188. return ASE->getRBracketLoc();
  189. }
  190. case Expr::CStyleCastExprClass: {
  191. const CStyleCastExpr *CSC = cast<CStyleCastExpr>(S);
  192. R1 = CSC->getSubExpr()->getSourceRange();
  193. return CSC->getLParenLoc();
  194. }
  195. case Expr::CXXFunctionalCastExprClass: {
  196. const CXXFunctionalCastExpr *CE = cast <CXXFunctionalCastExpr>(S);
  197. R1 = CE->getSubExpr()->getSourceRange();
  198. return CE->getTypeBeginLoc();
  199. }
  200. case Stmt::CXXTryStmtClass: {
  201. return cast<CXXTryStmt>(S)->getHandler(0)->getCatchLoc();
  202. }
  203. case Expr::ObjCBridgedCastExprClass: {
  204. const ObjCBridgedCastExpr *CSC = cast<ObjCBridgedCastExpr>(S);
  205. R1 = CSC->getSubExpr()->getSourceRange();
  206. return CSC->getLParenLoc();
  207. }
  208. default: ;
  209. }
  210. R1 = S->getSourceRange();
  211. return S->getLocStart();
  212. }
  213. void DeadCodeScan::reportDeadCode(const Stmt *S,
  214. clang::reachable_code::Callback &CB) {
  215. SourceRange R1, R2;
  216. SourceLocation Loc = GetUnreachableLoc(S, R1, R2);
  217. CB.HandleUnreachable(Loc, R1, R2);
  218. }
  219. namespace clang { namespace reachable_code {
  220. void Callback::anchor() { }
  221. unsigned ScanReachableFromBlock(const CFGBlock *Start,
  222. llvm::BitVector &Reachable) {
  223. unsigned count = 0;
  224. // Prep work queue
  225. SmallVector<const CFGBlock*, 32> WL;
  226. // The entry block may have already been marked reachable
  227. // by the caller.
  228. if (!Reachable[Start->getBlockID()]) {
  229. ++count;
  230. Reachable[Start->getBlockID()] = true;
  231. }
  232. WL.push_back(Start);
  233. // Find the reachable blocks from 'Start'.
  234. while (!WL.empty()) {
  235. const CFGBlock *item = WL.pop_back_val();
  236. // Look at the successors and mark then reachable.
  237. for (CFGBlock::const_succ_iterator I = item->succ_begin(),
  238. E = item->succ_end(); I != E; ++I)
  239. if (const CFGBlock *B = *I) {
  240. unsigned blockID = B->getBlockID();
  241. if (!Reachable[blockID]) {
  242. Reachable.set(blockID);
  243. WL.push_back(B);
  244. ++count;
  245. }
  246. }
  247. }
  248. return count;
  249. }
  250. void FindUnreachableCode(AnalysisDeclContext &AC, Callback &CB) {
  251. CFG *cfg = AC.getCFG();
  252. if (!cfg)
  253. return;
  254. // Scan for reachable blocks from the entrance of the CFG.
  255. // If there are no unreachable blocks, we're done.
  256. llvm::BitVector reachable(cfg->getNumBlockIDs());
  257. unsigned numReachable = ScanReachableFromBlock(&cfg->getEntry(), reachable);
  258. if (numReachable == cfg->getNumBlockIDs())
  259. return;
  260. // If there aren't explicit EH edges, we should include the 'try' dispatch
  261. // blocks as roots.
  262. if (!AC.getCFGBuildOptions().AddEHEdges) {
  263. for (CFG::try_block_iterator I = cfg->try_blocks_begin(),
  264. E = cfg->try_blocks_end() ; I != E; ++I) {
  265. numReachable += ScanReachableFromBlock(*I, reachable);
  266. }
  267. if (numReachable == cfg->getNumBlockIDs())
  268. return;
  269. }
  270. // There are some unreachable blocks. We need to find the root blocks that
  271. // contain code that should be considered unreachable.
  272. for (CFG::iterator I = cfg->begin(), E = cfg->end(); I != E; ++I) {
  273. const CFGBlock *block = *I;
  274. // A block may have been marked reachable during this loop.
  275. if (reachable[block->getBlockID()])
  276. continue;
  277. DeadCodeScan DS(reachable);
  278. numReachable += DS.scanBackwards(block, CB);
  279. if (numReachable == cfg->getNumBlockIDs())
  280. return;
  281. }
  282. }
  283. }} // end namespace clang::reachable_code