clang API Documentation
00001 //=- ReachableCodePathInsensitive.cpp ---------------------------*- C++ --*-==// 00002 // 00003 // The LLVM Compiler Infrastructure 00004 // 00005 // This file is distributed under the University of Illinois Open Source 00006 // License. See LICENSE.TXT for details. 00007 // 00008 //===----------------------------------------------------------------------===// 00009 // 00010 // This file implements a flow-sensitive, path-insensitive analysis of 00011 // determining reachable blocks within a CFG. 00012 // 00013 //===----------------------------------------------------------------------===// 00014 00015 #include "llvm/ADT/BitVector.h" 00016 #include "llvm/ADT/SmallVector.h" 00017 #include "clang/AST/Expr.h" 00018 #include "clang/AST/ExprCXX.h" 00019 #include "clang/AST/ExprObjC.h" 00020 #include "clang/AST/StmtCXX.h" 00021 #include "clang/Analysis/Analyses/ReachableCode.h" 00022 #include "clang/Analysis/CFG.h" 00023 #include "clang/Analysis/AnalysisContext.h" 00024 #include "clang/Basic/SourceManager.h" 00025 00026 using namespace clang; 00027 00028 namespace { 00029 class DeadCodeScan { 00030 llvm::BitVector Visited; 00031 llvm::BitVector &Reachable; 00032 llvm::SmallVector<const CFGBlock *, 10> WorkList; 00033 00034 typedef llvm::SmallVector<std::pair<const CFGBlock *, const Stmt *>, 12> 00035 DeferredLocsTy; 00036 00037 DeferredLocsTy DeferredLocs; 00038 00039 public: 00040 DeadCodeScan(llvm::BitVector &reachable) 00041 : Visited(reachable.size()), 00042 Reachable(reachable) {} 00043 00044 void enqueue(const CFGBlock *block); 00045 unsigned scanBackwards(const CFGBlock *Start, 00046 clang::reachable_code::Callback &CB); 00047 00048 bool isDeadCodeRoot(const CFGBlock *Block); 00049 00050 const Stmt *findDeadCode(const CFGBlock *Block); 00051 00052 void reportDeadCode(const Stmt *S, 00053 clang::reachable_code::Callback &CB); 00054 }; 00055 } 00056 00057 void DeadCodeScan::enqueue(const CFGBlock *block) { 00058 unsigned blockID = block->getBlockID(); 00059 if (Reachable[blockID] || Visited[blockID]) 00060 return; 00061 Visited[blockID] = true; 00062 WorkList.push_back(block); 00063 } 00064 00065 bool DeadCodeScan::isDeadCodeRoot(const clang::CFGBlock *Block) { 00066 bool isDeadRoot = true; 00067 00068 for (CFGBlock::const_pred_iterator I = Block->pred_begin(), 00069 E = Block->pred_end(); I != E; ++I) { 00070 if (const CFGBlock *PredBlock = *I) { 00071 unsigned blockID = PredBlock->getBlockID(); 00072 if (Visited[blockID]) { 00073 isDeadRoot = false; 00074 continue; 00075 } 00076 if (!Reachable[blockID]) { 00077 isDeadRoot = false; 00078 Visited[blockID] = true; 00079 WorkList.push_back(PredBlock); 00080 continue; 00081 } 00082 } 00083 } 00084 00085 return isDeadRoot; 00086 } 00087 00088 static bool isValidDeadStmt(const Stmt *S) { 00089 if (S->getLocStart().isInvalid()) 00090 return false; 00091 if (const BinaryOperator *BO = dyn_cast<BinaryOperator>(S)) 00092 return BO->getOpcode() != BO_Comma; 00093 return true; 00094 } 00095 00096 const Stmt *DeadCodeScan::findDeadCode(const clang::CFGBlock *Block) { 00097 for (CFGBlock::const_iterator I = Block->begin(), E = Block->end(); I!=E; ++I) 00098 if (const CFGStmt *CS = I->getAs<CFGStmt>()) { 00099 const Stmt *S = CS->getStmt(); 00100 if (isValidDeadStmt(S)) 00101 return S; 00102 } 00103 00104 if (CFGTerminator T = Block->getTerminator()) { 00105 const Stmt *S = T.getStmt(); 00106 if (isValidDeadStmt(S)) 00107 return S; 00108 } 00109 00110 return 0; 00111 } 00112 00113 static int SrcCmp(const void *p1, const void *p2) { 00114 return 00115 ((std::pair<const CFGBlock *, const Stmt *>*) p2)->second->getLocStart() < 00116 ((std::pair<const CFGBlock *, const Stmt *>*) p1)->second->getLocStart(); 00117 } 00118 00119 unsigned DeadCodeScan::scanBackwards(const clang::CFGBlock *Start, 00120 clang::reachable_code::Callback &CB) { 00121 00122 unsigned count = 0; 00123 enqueue(Start); 00124 00125 while (!WorkList.empty()) { 00126 const CFGBlock *Block = WorkList.pop_back_val(); 00127 00128 // It is possible that this block has been marked reachable after 00129 // it was enqueued. 00130 if (Reachable[Block->getBlockID()]) 00131 continue; 00132 00133 // Look for any dead code within the block. 00134 const Stmt *S = findDeadCode(Block); 00135 00136 if (!S) { 00137 // No dead code. Possibly an empty block. Look at dead predecessors. 00138 for (CFGBlock::const_pred_iterator I = Block->pred_begin(), 00139 E = Block->pred_end(); I != E; ++I) { 00140 if (const CFGBlock *predBlock = *I) 00141 enqueue(predBlock); 00142 } 00143 continue; 00144 } 00145 00146 // Specially handle macro-expanded code. 00147 if (S->getLocStart().isMacroID()) { 00148 count += clang::reachable_code::ScanReachableFromBlock(Block, Reachable); 00149 continue; 00150 } 00151 00152 if (isDeadCodeRoot(Block)) { 00153 reportDeadCode(S, CB); 00154 count += clang::reachable_code::ScanReachableFromBlock(Block, Reachable); 00155 } 00156 else { 00157 // Record this statement as the possibly best location in a 00158 // strongly-connected component of dead code for emitting a 00159 // warning. 00160 DeferredLocs.push_back(std::make_pair(Block, S)); 00161 } 00162 } 00163 00164 // If we didn't find a dead root, then report the dead code with the 00165 // earliest location. 00166 if (!DeferredLocs.empty()) { 00167 llvm::array_pod_sort(DeferredLocs.begin(), DeferredLocs.end(), SrcCmp); 00168 for (DeferredLocsTy::iterator I = DeferredLocs.begin(), 00169 E = DeferredLocs.end(); I != E; ++I) { 00170 const CFGBlock *block = I->first; 00171 if (Reachable[block->getBlockID()]) 00172 continue; 00173 reportDeadCode(I->second, CB); 00174 count += clang::reachable_code::ScanReachableFromBlock(block, Reachable); 00175 } 00176 } 00177 00178 return count; 00179 } 00180 00181 static SourceLocation GetUnreachableLoc(const Stmt *S, 00182 SourceRange &R1, 00183 SourceRange &R2) { 00184 R1 = R2 = SourceRange(); 00185 00186 if (const Expr *Ex = dyn_cast<Expr>(S)) 00187 S = Ex->IgnoreParenImpCasts(); 00188 00189 switch (S->getStmtClass()) { 00190 case Expr::BinaryOperatorClass: { 00191 const BinaryOperator *BO = cast<BinaryOperator>(S); 00192 return BO->getOperatorLoc(); 00193 } 00194 case Expr::UnaryOperatorClass: { 00195 const UnaryOperator *UO = cast<UnaryOperator>(S); 00196 R1 = UO->getSubExpr()->getSourceRange(); 00197 return UO->getOperatorLoc(); 00198 } 00199 case Expr::CompoundAssignOperatorClass: { 00200 const CompoundAssignOperator *CAO = cast<CompoundAssignOperator>(S); 00201 R1 = CAO->getLHS()->getSourceRange(); 00202 R2 = CAO->getRHS()->getSourceRange(); 00203 return CAO->getOperatorLoc(); 00204 } 00205 case Expr::BinaryConditionalOperatorClass: 00206 case Expr::ConditionalOperatorClass: { 00207 const AbstractConditionalOperator *CO = 00208 cast<AbstractConditionalOperator>(S); 00209 return CO->getQuestionLoc(); 00210 } 00211 case Expr::MemberExprClass: { 00212 const MemberExpr *ME = cast<MemberExpr>(S); 00213 R1 = ME->getSourceRange(); 00214 return ME->getMemberLoc(); 00215 } 00216 case Expr::ArraySubscriptExprClass: { 00217 const ArraySubscriptExpr *ASE = cast<ArraySubscriptExpr>(S); 00218 R1 = ASE->getLHS()->getSourceRange(); 00219 R2 = ASE->getRHS()->getSourceRange(); 00220 return ASE->getRBracketLoc(); 00221 } 00222 case Expr::CStyleCastExprClass: { 00223 const CStyleCastExpr *CSC = cast<CStyleCastExpr>(S); 00224 R1 = CSC->getSubExpr()->getSourceRange(); 00225 return CSC->getLParenLoc(); 00226 } 00227 case Expr::CXXFunctionalCastExprClass: { 00228 const CXXFunctionalCastExpr *CE = cast <CXXFunctionalCastExpr>(S); 00229 R1 = CE->getSubExpr()->getSourceRange(); 00230 return CE->getTypeBeginLoc(); 00231 } 00232 case Stmt::CXXTryStmtClass: { 00233 return cast<CXXTryStmt>(S)->getHandler(0)->getCatchLoc(); 00234 } 00235 case Expr::ObjCBridgedCastExprClass: { 00236 const ObjCBridgedCastExpr *CSC = cast<ObjCBridgedCastExpr>(S); 00237 R1 = CSC->getSubExpr()->getSourceRange(); 00238 return CSC->getLParenLoc(); 00239 } 00240 default: ; 00241 } 00242 R1 = S->getSourceRange(); 00243 return S->getLocStart(); 00244 } 00245 00246 void DeadCodeScan::reportDeadCode(const Stmt *S, 00247 clang::reachable_code::Callback &CB) { 00248 SourceRange R1, R2; 00249 SourceLocation Loc = GetUnreachableLoc(S, R1, R2); 00250 CB.HandleUnreachable(Loc, R1, R2); 00251 } 00252 00253 namespace clang { namespace reachable_code { 00254 00255 void Callback::anchor() { } 00256 00257 unsigned ScanReachableFromBlock(const CFGBlock *Start, 00258 llvm::BitVector &Reachable) { 00259 unsigned count = 0; 00260 00261 // Prep work queue 00262 SmallVector<const CFGBlock*, 32> WL; 00263 00264 // The entry block may have already been marked reachable 00265 // by the caller. 00266 if (!Reachable[Start->getBlockID()]) { 00267 ++count; 00268 Reachable[Start->getBlockID()] = true; 00269 } 00270 00271 WL.push_back(Start); 00272 00273 // Find the reachable blocks from 'Start'. 00274 while (!WL.empty()) { 00275 const CFGBlock *item = WL.pop_back_val(); 00276 00277 // Look at the successors and mark then reachable. 00278 for (CFGBlock::const_succ_iterator I = item->succ_begin(), 00279 E = item->succ_end(); I != E; ++I) 00280 if (const CFGBlock *B = *I) { 00281 unsigned blockID = B->getBlockID(); 00282 if (!Reachable[blockID]) { 00283 Reachable.set(blockID); 00284 WL.push_back(B); 00285 ++count; 00286 } 00287 } 00288 } 00289 return count; 00290 } 00291 00292 void FindUnreachableCode(AnalysisDeclContext &AC, Callback &CB) { 00293 CFG *cfg = AC.getCFG(); 00294 if (!cfg) 00295 return; 00296 00297 // Scan for reachable blocks from the entrance of the CFG. 00298 // If there are no unreachable blocks, we're done. 00299 llvm::BitVector reachable(cfg->getNumBlockIDs()); 00300 unsigned numReachable = ScanReachableFromBlock(&cfg->getEntry(), reachable); 00301 if (numReachable == cfg->getNumBlockIDs()) 00302 return; 00303 00304 // If there aren't explicit EH edges, we should include the 'try' dispatch 00305 // blocks as roots. 00306 if (!AC.getCFGBuildOptions().AddEHEdges) { 00307 for (CFG::try_block_iterator I = cfg->try_blocks_begin(), 00308 E = cfg->try_blocks_end() ; I != E; ++I) { 00309 numReachable += ScanReachableFromBlock(*I, reachable); 00310 } 00311 if (numReachable == cfg->getNumBlockIDs()) 00312 return; 00313 } 00314 00315 // There are some unreachable blocks. We need to find the root blocks that 00316 // contain code that should be considered unreachable. 00317 for (CFG::iterator I = cfg->begin(), E = cfg->end(); I != E; ++I) { 00318 const CFGBlock *block = *I; 00319 // A block may have been marked reachable during this loop. 00320 if (reachable[block->getBlockID()]) 00321 continue; 00322 00323 DeadCodeScan DS(reachable); 00324 numReachable += DS.scanBackwards(block, CB); 00325 00326 if (numReachable == cfg->getNumBlockIDs()) 00327 return; 00328 } 00329 } 00330 00331 }} // end namespace clang::reachable_code