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 15 #include "clang/Analysis/Analyses/ReachableCode.h" 16 #include "clang/Lex/Preprocessor.h" 17 #include "clang/AST/Expr.h" 18 #include "clang/AST/ExprCXX.h" 19 #include "clang/AST/ExprObjC.h" 20 #include "clang/AST/StmtCXX.h" 21 #include "clang/Analysis/AnalysisContext.h" 22 #include "clang/Analysis/CFG.h" 23 #include "clang/Basic/SourceManager.h" 24 #include "llvm/ADT/BitVector.h" 25 #include "llvm/ADT/SmallVector.h" 26 27 using namespace clang; 28 29 //===----------------------------------------------------------------------===// 30 // Core Reachability Analysis routines. 31 //===----------------------------------------------------------------------===// 32 33 static bool bodyEndsWithNoReturn(const CFGBlock *B) { 34 for (CFGBlock::const_reverse_iterator I = B->rbegin(), E = B->rend(); 35 I != E; ++I) { 36 if (Optional<CFGStmt> CS = I->getAs<CFGStmt>()) { 37 const Stmt *S = CS->getStmt(); 38 if (const ExprWithCleanups *EWC = dyn_cast<ExprWithCleanups>(S)) 39 S = EWC->getSubExpr(); 40 if (const CallExpr *CE = dyn_cast<CallExpr>(S)) { 41 QualType CalleeType = CE->getCallee()->getType(); 42 if (getFunctionExtInfo(*CalleeType).getNoReturn()) 43 return true; 44 } 45 break; 46 } 47 } 48 return false; 49 } 50 51 static bool bodyEndsWithNoReturn(const CFGBlock::AdjacentBlock &AB) { 52 // If the predecessor is a normal CFG edge, then by definition 53 // the predecessor did not end with a 'noreturn'. 54 if (AB.getReachableBlock()) 55 return false; 56 57 const CFGBlock *Pred = AB.getPossiblyUnreachableBlock(); 58 assert(!AB.isReachable() && Pred); 59 return bodyEndsWithNoReturn(Pred); 60 } 61 62 static bool isBreakPrecededByNoReturn(const CFGBlock *B, 63 const Stmt *S) { 64 if (!isa<BreakStmt>(S) || B->pred_empty()) 65 return false; 66 67 assert(B->empty()); 68 assert(B->pred_size() == 1); 69 return bodyEndsWithNoReturn(*B->pred_begin()); 70 } 71 72 static bool isEnumConstant(const Expr *Ex) { 73 const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(Ex); 74 if (!DR) 75 return false; 76 return isa<EnumConstantDecl>(DR->getDecl()); 77 } 78 79 static const Expr *stripStdStringCtor(const Expr *Ex) { 80 // Go crazy pattern matching an implicit construction of std::string(""). 81 const ExprWithCleanups *EWC = dyn_cast<ExprWithCleanups>(Ex); 82 if (!EWC) 83 return 0; 84 const CXXConstructExpr *CCE = dyn_cast<CXXConstructExpr>(EWC->getSubExpr()); 85 if (!CCE) 86 return 0; 87 QualType Ty = CCE->getType(); 88 if (const ElaboratedType *ET = dyn_cast<ElaboratedType>(Ty)) 89 Ty = ET->getNamedType(); 90 const TypedefType *TT = dyn_cast<TypedefType>(Ty); 91 StringRef Name = TT->getDecl()->getName(); 92 if (Name != "string") 93 return 0; 94 if (CCE->getNumArgs() != 1) 95 return 0; 96 const MaterializeTemporaryExpr *MTE = 97 dyn_cast<MaterializeTemporaryExpr>(CCE->getArg(0)); 98 if (!MTE) 99 return 0; 100 CXXBindTemporaryExpr *CBT = 101 dyn_cast<CXXBindTemporaryExpr>(MTE->GetTemporaryExpr()->IgnoreParenCasts()); 102 if (!CBT) 103 return 0; 104 Ex = CBT->getSubExpr()->IgnoreParenCasts(); 105 CCE = dyn_cast<CXXConstructExpr>(Ex); 106 if (!CCE) 107 return 0; 108 if (CCE->getNumArgs() != 1) 109 return 0; 110 return dyn_cast<StringLiteral>(CCE->getArg(0)->IgnoreParenCasts()); 111 } 112 113 /// Strip away "sugar" around trivial expressions that are for the 114 /// purpose of this analysis considered uninteresting for dead code warnings. 115 static const Expr *stripExprSugar(const Expr *Ex) { 116 Ex = Ex->IgnoreParenCasts(); 117 // If 'Ex' is a constructor for a std::string, strip that 118 // away. We can only get here if the trivial expression was 119 // something like a C string literal, with the std::string 120 // just wrapping that value. 121 if (const Expr *StdStringVal = stripStdStringCtor(Ex)) 122 return StdStringVal; 123 return Ex; 124 } 125 126 static bool isTrivialExpression(const Expr *Ex) { 127 Ex = Ex->IgnoreParenCasts(); 128 return isa<IntegerLiteral>(Ex) || isa<StringLiteral>(Ex) || 129 isa<CXXBoolLiteralExpr>(Ex) || isa<ObjCBoolLiteralExpr>(Ex) || 130 isa<CharacterLiteral>(Ex) || 131 isEnumConstant(Ex); 132 } 133 134 static bool isTrivialReturnOrDoWhile(const CFGBlock *B, const Stmt *S) { 135 const Expr *Ex = dyn_cast<Expr>(S); 136 137 if (Ex && !isTrivialExpression(Ex)) 138 return false; 139 140 // Check if the block ends with a do...while() and see if 'S' is the 141 // condition. 142 if (const Stmt *Term = B->getTerminator()) { 143 if (const DoStmt *DS = dyn_cast<DoStmt>(Term)) 144 if (DS->getCond() == S) 145 return true; 146 } 147 148 if (B->pred_size() != 1) 149 return false; 150 151 // Look to see if the block ends with a 'return', and see if 'S' 152 // is a substatement. The 'return' may not be the last element in 153 // the block because of destructors. 154 for (CFGBlock::const_reverse_iterator I = B->rbegin(), E = B->rend(); 155 I != E; ++I) { 156 if (Optional<CFGStmt> CS = I->getAs<CFGStmt>()) { 157 if (const ReturnStmt *RS = dyn_cast<ReturnStmt>(CS->getStmt())) { 158 bool LookAtBody = false; 159 if (RS == S) 160 LookAtBody = true; 161 else { 162 const Expr *RE = RS->getRetValue(); 163 if (RE && stripExprSugar(RE->IgnoreParenCasts()) == Ex) 164 LookAtBody = true; 165 } 166 167 if (LookAtBody) 168 return bodyEndsWithNoReturn(*B->pred_begin()); 169 } 170 break; 171 } 172 } 173 return false; 174 } 175 176 static SourceLocation getTopMostMacro(SourceLocation Loc, SourceManager &SM) { 177 assert(Loc.isMacroID()); 178 SourceLocation Last; 179 while (Loc.isMacroID()) { 180 Last = Loc; 181 Loc = SM.getImmediateMacroCallerLoc(Loc); 182 } 183 return Last; 184 } 185 186 /// Returns true if the statement is expanded from a configuration macro. 187 static bool isExpandedFromConfigurationMacro(const Stmt *S, 188 Preprocessor &PP, 189 bool IgnoreYES_NO = false) { 190 // FIXME: This is not very precise. Here we just check to see if the 191 // value comes from a macro, but we can do much better. This is likely 192 // to be over conservative. This logic is factored into a separate function 193 // so that we can refine it later. 194 SourceLocation L = S->getLocStart(); 195 if (L.isMacroID()) { 196 if (IgnoreYES_NO) { 197 // The Objective-C constant 'YES' and 'NO' 198 // are defined as macros. Do not treat them 199 // as configuration values. 200 SourceManager &SM = PP.getSourceManager(); 201 SourceLocation TopL = getTopMostMacro(L, SM); 202 StringRef MacroName = PP.getImmediateMacroName(TopL); 203 if (MacroName == "YES" || MacroName == "NO") 204 return false; 205 } 206 return true; 207 } 208 return false; 209 } 210 211 /// Returns true if the statement represents a configuration value. 212 /// 213 /// A configuration value is something usually determined at compile-time 214 /// to conditionally always execute some branch. Such guards are for 215 /// "sometimes unreachable" code. Such code is usually not interesting 216 /// to report as unreachable, and may mask truly unreachable code within 217 /// those blocks. 218 static bool isConfigurationValue(const Stmt *S, 219 Preprocessor &PP, 220 bool IncludeIntegers = true) { 221 if (!S) 222 return false; 223 224 if (const Expr *Ex = dyn_cast<Expr>(S)) 225 S = Ex->IgnoreParenCasts(); 226 227 switch (S->getStmtClass()) { 228 case Stmt::DeclRefExprClass: { 229 const DeclRefExpr *DR = cast<DeclRefExpr>(S); 230 const ValueDecl *D = DR->getDecl(); 231 if (const EnumConstantDecl *ED = dyn_cast<EnumConstantDecl>(D)) 232 return isConfigurationValue(ED->getInitExpr(), PP); 233 if (const VarDecl *VD = dyn_cast<VarDecl>(D)) { 234 // As a heuristic, treat globals as configuration values. Note 235 // that we only will get here if Sema evaluated this 236 // condition to a constant expression, which means the global 237 // had to be declared in a way to be a truly constant value. 238 // We could generalize this to local variables, but it isn't 239 // clear if those truly represent configuration values that 240 // gate unreachable code. 241 return !VD->hasLocalStorage(); 242 } 243 return false; 244 } 245 case Stmt::IntegerLiteralClass: 246 return IncludeIntegers ? isExpandedFromConfigurationMacro(S, PP) 247 : false; 248 case Stmt::ObjCBoolLiteralExprClass: 249 return isExpandedFromConfigurationMacro(S, PP, /* IgnoreYES_NO */ true); 250 251 case Stmt::UnaryExprOrTypeTraitExprClass: 252 return true; 253 case Stmt::BinaryOperatorClass: { 254 const BinaryOperator *B = cast<BinaryOperator>(S); 255 // Only include raw integers (not enums) as configuration 256 // values if they are used in a logical or comparison operator 257 // (not arithmetic). 258 IncludeIntegers &= (B->isLogicalOp() || B->isComparisonOp()); 259 return isConfigurationValue(B->getLHS(), PP, IncludeIntegers) || 260 isConfigurationValue(B->getRHS(), PP, IncludeIntegers); 261 } 262 case Stmt::UnaryOperatorClass: { 263 const UnaryOperator *UO = cast<UnaryOperator>(S); 264 return UO->getOpcode() == UO_LNot && 265 isConfigurationValue(UO->getSubExpr(), PP); 266 } 267 default: 268 return false; 269 } 270 } 271 272 /// Returns true if we should always explore all successors of a block. 273 static bool shouldTreatSuccessorsAsReachable(const CFGBlock *B, 274 Preprocessor &PP) { 275 if (const Stmt *Term = B->getTerminator()) { 276 if (isa<SwitchStmt>(Term)) 277 return true; 278 // Specially handle '||' and '&&'. 279 if (isa<BinaryOperator>(Term)) 280 return isConfigurationValue(Term, PP); 281 } 282 283 return isConfigurationValue(B->getTerminatorCondition(), PP); 284 } 285 286 static unsigned scanFromBlock(const CFGBlock *Start, 287 llvm::BitVector &Reachable, 288 Preprocessor *PP, 289 bool IncludeSometimesUnreachableEdges) { 290 unsigned count = 0; 291 292 // Prep work queue 293 SmallVector<const CFGBlock*, 32> WL; 294 295 // The entry block may have already been marked reachable 296 // by the caller. 297 if (!Reachable[Start->getBlockID()]) { 298 ++count; 299 Reachable[Start->getBlockID()] = true; 300 } 301 302 WL.push_back(Start); 303 304 // Find the reachable blocks from 'Start'. 305 while (!WL.empty()) { 306 const CFGBlock *item = WL.pop_back_val(); 307 308 // There are cases where we want to treat all successors as reachable. 309 // The idea is that some "sometimes unreachable" code is not interesting, 310 // and that we should forge ahead and explore those branches anyway. 311 // This allows us to potentially uncover some "always unreachable" code 312 // within the "sometimes unreachable" code. 313 // Look at the successors and mark then reachable. 314 Optional<bool> TreatAllSuccessorsAsReachable; 315 if (!IncludeSometimesUnreachableEdges) 316 TreatAllSuccessorsAsReachable = false; 317 318 for (CFGBlock::const_succ_iterator I = item->succ_begin(), 319 E = item->succ_end(); I != E; ++I) { 320 const CFGBlock *B = *I; 321 if (!B) do { 322 const CFGBlock *UB = I->getPossiblyUnreachableBlock(); 323 if (!UB) 324 break; 325 326 if (!TreatAllSuccessorsAsReachable.hasValue()) { 327 assert(PP); 328 TreatAllSuccessorsAsReachable = 329 shouldTreatSuccessorsAsReachable(item, *PP); 330 } 331 332 if (TreatAllSuccessorsAsReachable.getValue()) { 333 B = UB; 334 break; 335 } 336 } 337 while (false); 338 339 if (B) { 340 unsigned blockID = B->getBlockID(); 341 if (!Reachable[blockID]) { 342 Reachable.set(blockID); 343 WL.push_back(B); 344 ++count; 345 } 346 } 347 } 348 } 349 return count; 350 } 351 352 static unsigned scanMaybeReachableFromBlock(const CFGBlock *Start, 353 Preprocessor &PP, 354 llvm::BitVector &Reachable) { 355 return scanFromBlock(Start, Reachable, &PP, true); 356 } 357 358 //===----------------------------------------------------------------------===// 359 // Dead Code Scanner. 360 //===----------------------------------------------------------------------===// 361 362 namespace { 363 class DeadCodeScan { 364 llvm::BitVector Visited; 365 llvm::BitVector &Reachable; 366 SmallVector<const CFGBlock *, 10> WorkList; 367 Preprocessor &PP; 368 369 typedef SmallVector<std::pair<const CFGBlock *, const Stmt *>, 12> 370 DeferredLocsTy; 371 372 DeferredLocsTy DeferredLocs; 373 374 public: 375 DeadCodeScan(llvm::BitVector &reachable, Preprocessor &PP) 376 : Visited(reachable.size()), 377 Reachable(reachable), 378 PP(PP) {} 379 380 void enqueue(const CFGBlock *block); 381 unsigned scanBackwards(const CFGBlock *Start, 382 clang::reachable_code::Callback &CB); 383 384 bool isDeadCodeRoot(const CFGBlock *Block); 385 386 const Stmt *findDeadCode(const CFGBlock *Block); 387 388 void reportDeadCode(const CFGBlock *B, 389 const Stmt *S, 390 clang::reachable_code::Callback &CB); 391 }; 392 } 393 394 void DeadCodeScan::enqueue(const CFGBlock *block) { 395 unsigned blockID = block->getBlockID(); 396 if (Reachable[blockID] || Visited[blockID]) 397 return; 398 Visited[blockID] = true; 399 WorkList.push_back(block); 400 } 401 402 bool DeadCodeScan::isDeadCodeRoot(const clang::CFGBlock *Block) { 403 bool isDeadRoot = true; 404 405 for (CFGBlock::const_pred_iterator I = Block->pred_begin(), 406 E = Block->pred_end(); I != E; ++I) { 407 if (const CFGBlock *PredBlock = *I) { 408 unsigned blockID = PredBlock->getBlockID(); 409 if (Visited[blockID]) { 410 isDeadRoot = false; 411 continue; 412 } 413 if (!Reachable[blockID]) { 414 isDeadRoot = false; 415 Visited[blockID] = true; 416 WorkList.push_back(PredBlock); 417 continue; 418 } 419 } 420 } 421 422 return isDeadRoot; 423 } 424 425 static bool isValidDeadStmt(const Stmt *S) { 426 if (S->getLocStart().isInvalid()) 427 return false; 428 if (const BinaryOperator *BO = dyn_cast<BinaryOperator>(S)) 429 return BO->getOpcode() != BO_Comma; 430 return true; 431 } 432 433 const Stmt *DeadCodeScan::findDeadCode(const clang::CFGBlock *Block) { 434 for (CFGBlock::const_iterator I = Block->begin(), E = Block->end(); I!=E; ++I) 435 if (Optional<CFGStmt> CS = I->getAs<CFGStmt>()) { 436 const Stmt *S = CS->getStmt(); 437 if (isValidDeadStmt(S)) 438 return S; 439 } 440 441 if (CFGTerminator T = Block->getTerminator()) { 442 if (!T.isTemporaryDtorsBranch()) { 443 const Stmt *S = T.getStmt(); 444 if (isValidDeadStmt(S)) 445 return S; 446 } 447 } 448 449 return 0; 450 } 451 452 static int SrcCmp(const std::pair<const CFGBlock *, const Stmt *> *p1, 453 const std::pair<const CFGBlock *, const Stmt *> *p2) { 454 if (p1->second->getLocStart() < p2->second->getLocStart()) 455 return -1; 456 if (p2->second->getLocStart() < p1->second->getLocStart()) 457 return 1; 458 return 0; 459 } 460 461 unsigned DeadCodeScan::scanBackwards(const clang::CFGBlock *Start, 462 clang::reachable_code::Callback &CB) { 463 464 unsigned count = 0; 465 enqueue(Start); 466 467 while (!WorkList.empty()) { 468 const CFGBlock *Block = WorkList.pop_back_val(); 469 470 // It is possible that this block has been marked reachable after 471 // it was enqueued. 472 if (Reachable[Block->getBlockID()]) 473 continue; 474 475 // Look for any dead code within the block. 476 const Stmt *S = findDeadCode(Block); 477 478 if (!S) { 479 // No dead code. Possibly an empty block. Look at dead predecessors. 480 for (CFGBlock::const_pred_iterator I = Block->pred_begin(), 481 E = Block->pred_end(); I != E; ++I) { 482 if (const CFGBlock *predBlock = *I) 483 enqueue(predBlock); 484 } 485 continue; 486 } 487 488 // Specially handle macro-expanded code. 489 if (S->getLocStart().isMacroID()) { 490 count += scanMaybeReachableFromBlock(Block, PP, Reachable); 491 continue; 492 } 493 494 if (isDeadCodeRoot(Block)) { 495 reportDeadCode(Block, S, CB); 496 count += scanMaybeReachableFromBlock(Block, PP, Reachable); 497 } 498 else { 499 // Record this statement as the possibly best location in a 500 // strongly-connected component of dead code for emitting a 501 // warning. 502 DeferredLocs.push_back(std::make_pair(Block, S)); 503 } 504 } 505 506 // If we didn't find a dead root, then report the dead code with the 507 // earliest location. 508 if (!DeferredLocs.empty()) { 509 llvm::array_pod_sort(DeferredLocs.begin(), DeferredLocs.end(), SrcCmp); 510 for (DeferredLocsTy::iterator I = DeferredLocs.begin(), 511 E = DeferredLocs.end(); I != E; ++I) { 512 const CFGBlock *Block = I->first; 513 if (Reachable[Block->getBlockID()]) 514 continue; 515 reportDeadCode(Block, I->second, CB); 516 count += scanMaybeReachableFromBlock(Block, PP, Reachable); 517 } 518 } 519 520 return count; 521 } 522 523 static SourceLocation GetUnreachableLoc(const Stmt *S, 524 SourceRange &R1, 525 SourceRange &R2) { 526 R1 = R2 = SourceRange(); 527 528 if (const Expr *Ex = dyn_cast<Expr>(S)) 529 S = Ex->IgnoreParenImpCasts(); 530 531 switch (S->getStmtClass()) { 532 case Expr::BinaryOperatorClass: { 533 const BinaryOperator *BO = cast<BinaryOperator>(S); 534 return BO->getOperatorLoc(); 535 } 536 case Expr::UnaryOperatorClass: { 537 const UnaryOperator *UO = cast<UnaryOperator>(S); 538 R1 = UO->getSubExpr()->getSourceRange(); 539 return UO->getOperatorLoc(); 540 } 541 case Expr::CompoundAssignOperatorClass: { 542 const CompoundAssignOperator *CAO = cast<CompoundAssignOperator>(S); 543 R1 = CAO->getLHS()->getSourceRange(); 544 R2 = CAO->getRHS()->getSourceRange(); 545 return CAO->getOperatorLoc(); 546 } 547 case Expr::BinaryConditionalOperatorClass: 548 case Expr::ConditionalOperatorClass: { 549 const AbstractConditionalOperator *CO = 550 cast<AbstractConditionalOperator>(S); 551 return CO->getQuestionLoc(); 552 } 553 case Expr::MemberExprClass: { 554 const MemberExpr *ME = cast<MemberExpr>(S); 555 R1 = ME->getSourceRange(); 556 return ME->getMemberLoc(); 557 } 558 case Expr::ArraySubscriptExprClass: { 559 const ArraySubscriptExpr *ASE = cast<ArraySubscriptExpr>(S); 560 R1 = ASE->getLHS()->getSourceRange(); 561 R2 = ASE->getRHS()->getSourceRange(); 562 return ASE->getRBracketLoc(); 563 } 564 case Expr::CStyleCastExprClass: { 565 const CStyleCastExpr *CSC = cast<CStyleCastExpr>(S); 566 R1 = CSC->getSubExpr()->getSourceRange(); 567 return CSC->getLParenLoc(); 568 } 569 case Expr::CXXFunctionalCastExprClass: { 570 const CXXFunctionalCastExpr *CE = cast <CXXFunctionalCastExpr>(S); 571 R1 = CE->getSubExpr()->getSourceRange(); 572 return CE->getLocStart(); 573 } 574 case Stmt::CXXTryStmtClass: { 575 return cast<CXXTryStmt>(S)->getHandler(0)->getCatchLoc(); 576 } 577 case Expr::ObjCBridgedCastExprClass: { 578 const ObjCBridgedCastExpr *CSC = cast<ObjCBridgedCastExpr>(S); 579 R1 = CSC->getSubExpr()->getSourceRange(); 580 return CSC->getLParenLoc(); 581 } 582 default: ; 583 } 584 R1 = S->getSourceRange(); 585 return S->getLocStart(); 586 } 587 588 void DeadCodeScan::reportDeadCode(const CFGBlock *B, 589 const Stmt *S, 590 clang::reachable_code::Callback &CB) { 591 // Suppress idiomatic cases of calling a noreturn function just 592 // before executing a 'break'. If there is other code after the 'break' 593 // in the block then don't suppress the warning. 594 if (isBreakPrecededByNoReturn(B, S)) 595 return; 596 597 // Suppress trivial 'return' statements that are dead. 598 if (isTrivialReturnOrDoWhile(B, S)) 599 return; 600 601 SourceRange R1, R2; 602 SourceLocation Loc = GetUnreachableLoc(S, R1, R2); 603 CB.HandleUnreachable(Loc, R1, R2); 604 } 605 606 //===----------------------------------------------------------------------===// 607 // Reachability APIs. 608 //===----------------------------------------------------------------------===// 609 610 namespace clang { namespace reachable_code { 611 612 void Callback::anchor() { } 613 614 unsigned ScanReachableFromBlock(const CFGBlock *Start, 615 llvm::BitVector &Reachable) { 616 return scanFromBlock(Start, Reachable, /* SourceManager* */ 0, false); 617 } 618 619 void FindUnreachableCode(AnalysisDeclContext &AC, Preprocessor &PP, 620 Callback &CB) { 621 622 CFG *cfg = AC.getCFG(); 623 if (!cfg) 624 return; 625 626 // Scan for reachable blocks from the entrance of the CFG. 627 // If there are no unreachable blocks, we're done. 628 llvm::BitVector reachable(cfg->getNumBlockIDs()); 629 unsigned numReachable = 630 scanMaybeReachableFromBlock(&cfg->getEntry(), PP, reachable); 631 if (numReachable == cfg->getNumBlockIDs()) 632 return; 633 634 // If there aren't explicit EH edges, we should include the 'try' dispatch 635 // blocks as roots. 636 if (!AC.getCFGBuildOptions().AddEHEdges) { 637 for (CFG::try_block_iterator I = cfg->try_blocks_begin(), 638 E = cfg->try_blocks_end() ; I != E; ++I) { 639 numReachable += scanMaybeReachableFromBlock(*I, PP, reachable); 640 } 641 if (numReachable == cfg->getNumBlockIDs()) 642 return; 643 } 644 645 // There are some unreachable blocks. We need to find the root blocks that 646 // contain code that should be considered unreachable. 647 for (CFG::iterator I = cfg->begin(), E = cfg->end(); I != E; ++I) { 648 const CFGBlock *block = *I; 649 // A block may have been marked reachable during this loop. 650 if (reachable[block->getBlockID()]) 651 continue; 652 653 DeadCodeScan DS(reachable, PP); 654 numReachable += DS.scanBackwards(block, CB); 655 656 if (numReachable == cfg->getNumBlockIDs()) 657 return; 658 } 659 } 660 661 }} // end namespace clang::reachable_code 662