blob: 5baaa006777f02b4fa08860cfc2441d93a9e5b1e [file] [log] [blame]
Ted Kremenek7296de92010-02-23 02:39:16 +00001//=- 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
Chandler Carruth3a022472012-12-04 09:13:33 +000015#include "clang/Analysis/Analyses/ReachableCode.h"
Ted Kremenek552eeaa2010-02-23 05:59:20 +000016#include "clang/AST/Expr.h"
17#include "clang/AST/ExprCXX.h"
John McCall31168b02011-06-15 23:02:42 +000018#include "clang/AST/ExprObjC.h"
Ted Kremenek552eeaa2010-02-23 05:59:20 +000019#include "clang/AST/StmtCXX.h"
Ted Kremenek552eeaa2010-02-23 05:59:20 +000020#include "clang/Analysis/AnalysisContext.h"
Chandler Carruth3a022472012-12-04 09:13:33 +000021#include "clang/Analysis/CFG.h"
Ted Kremenek552eeaa2010-02-23 05:59:20 +000022#include "clang/Basic/SourceManager.h"
Chandler Carruth3a022472012-12-04 09:13:33 +000023#include "llvm/ADT/BitVector.h"
24#include "llvm/ADT/SmallVector.h"
Ted Kremenek7296de92010-02-23 02:39:16 +000025
26using namespace clang;
27
Ted Kremenekbd913712011-08-23 23:05:11 +000028namespace {
29class DeadCodeScan {
30 llvm::BitVector Visited;
31 llvm::BitVector &Reachable;
Dmitri Gribenkof8579502013-01-12 19:30:44 +000032 SmallVector<const CFGBlock *, 10> WorkList;
Ted Kremenekbd913712011-08-23 23:05:11 +000033
Dmitri Gribenkof8579502013-01-12 19:30:44 +000034 typedef SmallVector<std::pair<const CFGBlock *, const Stmt *>, 12>
Ted Kremenekbd913712011-08-23 23:05:11 +000035 DeferredLocsTy;
36
37 DeferredLocsTy DeferredLocs;
38
39public:
40 DeadCodeScan(llvm::BitVector &reachable)
41 : Visited(reachable.size()),
42 Reachable(reachable) {}
43
44 void enqueue(const CFGBlock *block);
45 unsigned scanBackwards(const CFGBlock *Start,
46 clang::reachable_code::Callback &CB);
47
48 bool isDeadCodeRoot(const CFGBlock *Block);
49
50 const Stmt *findDeadCode(const CFGBlock *Block);
51
Ted Kremenekcc893382014-02-27 00:24:08 +000052 void reportDeadCode(const CFGBlock *B,
53 const Stmt *S,
Ted Kremenekbd913712011-08-23 23:05:11 +000054 clang::reachable_code::Callback &CB);
55};
56}
57
58void DeadCodeScan::enqueue(const CFGBlock *block) {
59 unsigned blockID = block->getBlockID();
60 if (Reachable[blockID] || Visited[blockID])
61 return;
62 Visited[blockID] = true;
63 WorkList.push_back(block);
64}
65
66bool DeadCodeScan::isDeadCodeRoot(const clang::CFGBlock *Block) {
67 bool isDeadRoot = true;
68
69 for (CFGBlock::const_pred_iterator I = Block->pred_begin(),
70 E = Block->pred_end(); I != E; ++I) {
71 if (const CFGBlock *PredBlock = *I) {
72 unsigned blockID = PredBlock->getBlockID();
73 if (Visited[blockID]) {
74 isDeadRoot = false;
75 continue;
76 }
77 if (!Reachable[blockID]) {
78 isDeadRoot = false;
79 Visited[blockID] = true;
80 WorkList.push_back(PredBlock);
81 continue;
82 }
83 }
84 }
85
86 return isDeadRoot;
87}
88
89static bool isValidDeadStmt(const Stmt *S) {
Ted Kremenek1b7f49c2011-08-25 19:28:55 +000090 if (S->getLocStart().isInvalid())
Ted Kremenekbd913712011-08-23 23:05:11 +000091 return false;
Ted Kremenek1b7f49c2011-08-25 19:28:55 +000092 if (const BinaryOperator *BO = dyn_cast<BinaryOperator>(S))
Ted Kremenekbd913712011-08-23 23:05:11 +000093 return BO->getOpcode() != BO_Comma;
Ted Kremenekbd913712011-08-23 23:05:11 +000094 return true;
95}
96
97const Stmt *DeadCodeScan::findDeadCode(const clang::CFGBlock *Block) {
98 for (CFGBlock::const_iterator I = Block->begin(), E = Block->end(); I!=E; ++I)
David Blaikie00be69a2013-02-23 00:29:34 +000099 if (Optional<CFGStmt> CS = I->getAs<CFGStmt>()) {
100 const Stmt *S = CS->getStmt();
Ted Kremenekbd913712011-08-23 23:05:11 +0000101 if (isValidDeadStmt(S))
102 return S;
103 }
104
105 if (CFGTerminator T = Block->getTerminator()) {
106 const Stmt *S = T.getStmt();
107 if (isValidDeadStmt(S))
108 return S;
109 }
110
111 return 0;
112}
113
Benjamin Kramer04bf1872013-09-22 14:10:29 +0000114static int SrcCmp(const std::pair<const CFGBlock *, const Stmt *> *p1,
115 const std::pair<const CFGBlock *, const Stmt *> *p2) {
Benjamin Kramerb8f33f12013-09-22 15:02:02 +0000116 if (p1->second->getLocStart() < p2->second->getLocStart())
117 return -1;
118 if (p2->second->getLocStart() < p1->second->getLocStart())
119 return 1;
120 return 0;
Ted Kremenekbd913712011-08-23 23:05:11 +0000121}
122
123unsigned DeadCodeScan::scanBackwards(const clang::CFGBlock *Start,
124 clang::reachable_code::Callback &CB) {
125
126 unsigned count = 0;
127 enqueue(Start);
128
129 while (!WorkList.empty()) {
130 const CFGBlock *Block = WorkList.pop_back_val();
131
132 // It is possible that this block has been marked reachable after
133 // it was enqueued.
134 if (Reachable[Block->getBlockID()])
135 continue;
136
137 // Look for any dead code within the block.
138 const Stmt *S = findDeadCode(Block);
139
140 if (!S) {
141 // No dead code. Possibly an empty block. Look at dead predecessors.
142 for (CFGBlock::const_pred_iterator I = Block->pred_begin(),
143 E = Block->pred_end(); I != E; ++I) {
144 if (const CFGBlock *predBlock = *I)
145 enqueue(predBlock);
146 }
147 continue;
148 }
Ted Kremenek1b7f49c2011-08-25 19:28:55 +0000149
150 // Specially handle macro-expanded code.
151 if (S->getLocStart().isMacroID()) {
152 count += clang::reachable_code::ScanReachableFromBlock(Block, Reachable);
153 continue;
154 }
Ted Kremenekbd913712011-08-23 23:05:11 +0000155
156 if (isDeadCodeRoot(Block)) {
Ted Kremenekcc893382014-02-27 00:24:08 +0000157 reportDeadCode(Block, S, CB);
Ted Kremenekbd913712011-08-23 23:05:11 +0000158 count += clang::reachable_code::ScanReachableFromBlock(Block, Reachable);
159 }
160 else {
161 // Record this statement as the possibly best location in a
162 // strongly-connected component of dead code for emitting a
163 // warning.
164 DeferredLocs.push_back(std::make_pair(Block, S));
165 }
166 }
167
168 // If we didn't find a dead root, then report the dead code with the
169 // earliest location.
170 if (!DeferredLocs.empty()) {
171 llvm::array_pod_sort(DeferredLocs.begin(), DeferredLocs.end(), SrcCmp);
172 for (DeferredLocsTy::iterator I = DeferredLocs.begin(),
173 E = DeferredLocs.end(); I != E; ++I) {
Ted Kremenekcc893382014-02-27 00:24:08 +0000174 const CFGBlock *Block = I->first;
175 if (Reachable[Block->getBlockID()])
Ted Kremenekbd913712011-08-23 23:05:11 +0000176 continue;
Ted Kremenekcc893382014-02-27 00:24:08 +0000177 reportDeadCode(Block, I->second, CB);
178 count += clang::reachable_code::ScanReachableFromBlock(Block, Reachable);
Ted Kremenekbd913712011-08-23 23:05:11 +0000179 }
180 }
181
182 return count;
183}
184
185static SourceLocation GetUnreachableLoc(const Stmt *S,
186 SourceRange &R1,
Ted Kremenek552eeaa2010-02-23 05:59:20 +0000187 SourceRange &R2) {
Ted Kremenek552eeaa2010-02-23 05:59:20 +0000188 R1 = R2 = SourceRange();
189
Ted Kremenek8219b822010-12-16 07:46:53 +0000190 if (const Expr *Ex = dyn_cast<Expr>(S))
191 S = Ex->IgnoreParenImpCasts();
192
Ted Kremenek552eeaa2010-02-23 05:59:20 +0000193 switch (S->getStmtClass()) {
194 case Expr::BinaryOperatorClass: {
195 const BinaryOperator *BO = cast<BinaryOperator>(S);
Ted Kremenek552eeaa2010-02-23 05:59:20 +0000196 return BO->getOperatorLoc();
197 }
198 case Expr::UnaryOperatorClass: {
199 const UnaryOperator *UO = cast<UnaryOperator>(S);
200 R1 = UO->getSubExpr()->getSourceRange();
201 return UO->getOperatorLoc();
202 }
203 case Expr::CompoundAssignOperatorClass: {
204 const CompoundAssignOperator *CAO = cast<CompoundAssignOperator>(S);
205 R1 = CAO->getLHS()->getSourceRange();
206 R2 = CAO->getRHS()->getSourceRange();
207 return CAO->getOperatorLoc();
208 }
John McCallc07a0c72011-02-17 10:25:35 +0000209 case Expr::BinaryConditionalOperatorClass:
Ted Kremenek552eeaa2010-02-23 05:59:20 +0000210 case Expr::ConditionalOperatorClass: {
John McCallc07a0c72011-02-17 10:25:35 +0000211 const AbstractConditionalOperator *CO =
212 cast<AbstractConditionalOperator>(S);
Ted Kremenek552eeaa2010-02-23 05:59:20 +0000213 return CO->getQuestionLoc();
214 }
215 case Expr::MemberExprClass: {
216 const MemberExpr *ME = cast<MemberExpr>(S);
217 R1 = ME->getSourceRange();
218 return ME->getMemberLoc();
219 }
220 case Expr::ArraySubscriptExprClass: {
221 const ArraySubscriptExpr *ASE = cast<ArraySubscriptExpr>(S);
222 R1 = ASE->getLHS()->getSourceRange();
223 R2 = ASE->getRHS()->getSourceRange();
224 return ASE->getRBracketLoc();
225 }
226 case Expr::CStyleCastExprClass: {
227 const CStyleCastExpr *CSC = cast<CStyleCastExpr>(S);
228 R1 = CSC->getSubExpr()->getSourceRange();
229 return CSC->getLParenLoc();
230 }
231 case Expr::CXXFunctionalCastExprClass: {
232 const CXXFunctionalCastExpr *CE = cast <CXXFunctionalCastExpr>(S);
233 R1 = CE->getSubExpr()->getSourceRange();
Eli Friedman89fe0d52013-08-15 22:02:56 +0000234 return CE->getLocStart();
Ted Kremenek552eeaa2010-02-23 05:59:20 +0000235 }
Ted Kremenek552eeaa2010-02-23 05:59:20 +0000236 case Stmt::CXXTryStmtClass: {
237 return cast<CXXTryStmt>(S)->getHandler(0)->getCatchLoc();
238 }
John McCall31168b02011-06-15 23:02:42 +0000239 case Expr::ObjCBridgedCastExprClass: {
240 const ObjCBridgedCastExpr *CSC = cast<ObjCBridgedCastExpr>(S);
241 R1 = CSC->getSubExpr()->getSourceRange();
242 return CSC->getLParenLoc();
243 }
Ted Kremenek552eeaa2010-02-23 05:59:20 +0000244 default: ;
245 }
246 R1 = S->getSourceRange();
247 return S->getLocStart();
248}
249
Ted Kremenekcc893382014-02-27 00:24:08 +0000250static bool bodyEndsWithNoReturn(const CFGBlock *B) {
251 for (CFGBlock::const_reverse_iterator I = B->rbegin(), E = B->rend();
252 I != E; ++I) {
253 if (Optional<CFGStmt> CS = I->getAs<CFGStmt>()) {
254 if (const CallExpr *CE = dyn_cast<CallExpr>(CS->getStmt())) {
255 QualType CalleeType = CE->getCallee()->getType();
256 if (getFunctionExtInfo(*CalleeType).getNoReturn())
257 return true;
258 }
259 break;
260 }
261 }
262 return false;
263}
264
Ted Kremenek5441c182014-02-27 06:32:32 +0000265static bool bodyEndsWithNoReturn(const CFGBlock::AdjacentBlock &AB) {
Ted Kremenekeb862842014-03-04 21:41:38 +0000266 // If the predecessor is a normal CFG edge, then by definition
267 // the predecessor did not end with a 'noreturn'.
268 if (AB.getReachableBlock())
269 return false;
270
Ted Kremenek5441c182014-02-27 06:32:32 +0000271 const CFGBlock *Pred = AB.getPossiblyUnreachableBlock();
272 assert(!AB.isReachable() && Pred);
273 return bodyEndsWithNoReturn(Pred);
274}
275
Ted Kremenekcc893382014-02-27 00:24:08 +0000276static bool isBreakPrecededByNoReturn(const CFGBlock *B,
277 const Stmt *S) {
278 if (!isa<BreakStmt>(S) || B->pred_empty())
279 return false;
280
281 assert(B->empty());
282 assert(B->pred_size() == 1);
Ted Kremenek5441c182014-02-27 06:32:32 +0000283 return bodyEndsWithNoReturn(*B->pred_begin());
284}
285
286static bool isEnumConstant(const Expr *Ex) {
287 const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(Ex);
288 if (!DR)
289 return false;
290 return isa<EnumConstantDecl>(DR->getDecl());
291}
292
293static bool isTrivialExpression(const Expr *Ex) {
294 return isa<IntegerLiteral>(Ex) || isa<StringLiteral>(Ex) ||
295 isEnumConstant(Ex);
296}
297
298static bool isTrivialReturnPrecededByNoReturn(const CFGBlock *B,
299 const Stmt *S) {
300 if (B->pred_empty())
301 return false;
302
303 const Expr *Ex = dyn_cast<Expr>(S);
304 if (!Ex)
305 return false;
306
307 Ex = Ex->IgnoreParenCasts();
308
309 if (!isTrivialExpression(Ex))
310 return false;
311
312 // Look to see if the block ends with a 'return', and see if 'S'
313 // is a substatement. The 'return' may not be the last element in
314 // the block because of destructors.
315 assert(!B->empty());
316 for (CFGBlock::const_reverse_iterator I = B->rbegin(), E = B->rend();
317 I != E; ++I) {
318 if (Optional<CFGStmt> CS = I->getAs<CFGStmt>()) {
319 if (const ReturnStmt *RS = dyn_cast<ReturnStmt>(CS->getStmt())) {
320 const Expr *RE = RS->getRetValue();
321 if (RE && RE->IgnoreParenCasts() == Ex)
322 break;
323 }
324 return false;
325 }
326 }
327
328 assert(B->pred_size() == 1);
329 return bodyEndsWithNoReturn(*B->pred_begin());
Ted Kremenekcc893382014-02-27 00:24:08 +0000330}
331
332void DeadCodeScan::reportDeadCode(const CFGBlock *B,
333 const Stmt *S,
Ted Kremenekbd913712011-08-23 23:05:11 +0000334 clang::reachable_code::Callback &CB) {
Ted Kremenekcc893382014-02-27 00:24:08 +0000335 // Suppress idiomatic cases of calling a noreturn function just
336 // before executing a 'break'. If there is other code after the 'break'
337 // in the block then don't suppress the warning.
338 if (isBreakPrecededByNoReturn(B, S))
339 return;
340
Ted Kremenek5441c182014-02-27 06:32:32 +0000341 // Suppress trivial 'return' statements that are dead.
342 if (isTrivialReturnPrecededByNoReturn(B, S))
343 return;
344
Ted Kremenek552eeaa2010-02-23 05:59:20 +0000345 SourceRange R1, R2;
Ted Kremenekbd913712011-08-23 23:05:11 +0000346 SourceLocation Loc = GetUnreachableLoc(S, R1, R2);
347 CB.HandleUnreachable(Loc, R1, R2);
Ted Kremenek552eeaa2010-02-23 05:59:20 +0000348}
349
Ted Kremenek552eeaa2010-02-23 05:59:20 +0000350namespace clang { namespace reachable_code {
David Blaikie68e081d2011-12-20 02:48:34 +0000351
352void Callback::anchor() { }
353
Ted Kremenek6d9bb562014-03-05 00:01:17 +0000354/// Returns true if the statement is expanded from a configuration macro.
355static bool isExpandedFromConfigurationMacro(const Stmt *S) {
356 // FIXME: This is not very precise. Here we just check to see if the
357 // value comes from a macro, but we can do much better. This is likely
358 // to be over conservative. This logic is factored into a separate function
359 // so that we can refine it later.
360 SourceLocation L = S->getLocStart();
361 return L.isMacroID();
362}
363
364/// Returns true if the statement represents a configuration value.
365///
366/// A configuration value is something usually determined at compile-time
367/// to conditionally always execute some branch. Such guards are for
368/// "sometimes unreachable" code. Such code is usually not interesting
369/// to report as unreachable, and may mask truly unreachable code within
370/// those blocks.
371static bool isConfigurationValue(const Stmt *S) {
372 if (!S)
373 return false;
374
375 if (const Expr *Ex = dyn_cast<Expr>(S))
376 S = Ex->IgnoreParenCasts();
377
378 switch (S->getStmtClass()) {
379 case Stmt::IntegerLiteralClass:
380 return isExpandedFromConfigurationMacro(S);
381 case Stmt::UnaryExprOrTypeTraitExprClass:
382 return true;
383 case Stmt::BinaryOperatorClass: {
384 const BinaryOperator *B = cast<BinaryOperator>(S);
385 return (B->isLogicalOp() || B->isRelationalOp()) &&
386 (isConfigurationValue(B->getLHS()) ||
387 isConfigurationValue(B->getRHS()));
388 }
389 case Stmt::UnaryOperatorClass: {
390 const UnaryOperator *UO = cast<UnaryOperator>(S);
391 return UO->getOpcode() == UO_LNot &&
392 isConfigurationValue(UO->getSubExpr());
393 }
394 default:
395 return false;
396 }
397}
398
399/// Returns true if we should always explore all successors of a block.
400static bool shouldTreatSuccessorsAsReachable(const CFGBlock *B) {
401 return isConfigurationValue(B->getTerminatorCondition());
402}
403
Ted Kremenekbd913712011-08-23 23:05:11 +0000404unsigned ScanReachableFromBlock(const CFGBlock *Start,
Ted Kremenek552eeaa2010-02-23 05:59:20 +0000405 llvm::BitVector &Reachable) {
406 unsigned count = 0;
Ted Kremenekbd913712011-08-23 23:05:11 +0000407
Nico Webercc2b8712011-04-02 19:45:15 +0000408 // Prep work queue
Ted Kremenekbd913712011-08-23 23:05:11 +0000409 SmallVector<const CFGBlock*, 32> WL;
410
411 // The entry block may have already been marked reachable
412 // by the caller.
413 if (!Reachable[Start->getBlockID()]) {
414 ++count;
415 Reachable[Start->getBlockID()] = true;
416 }
417
418 WL.push_back(Start);
419
Ted Kremenekf2b0a1b2010-09-09 00:06:10 +0000420 // Find the reachable blocks from 'Start'.
Ted Kremenek552eeaa2010-02-23 05:59:20 +0000421 while (!WL.empty()) {
Ted Kremenekbd913712011-08-23 23:05:11 +0000422 const CFGBlock *item = WL.pop_back_val();
Ted Kremenek6d9bb562014-03-05 00:01:17 +0000423
424 // There are cases where we want to treat all successors as reachable.
425 // The idea is that some "sometimes unreachable" code is not interesting,
426 // and that we should forge ahead and explore those branches anyway.
427 // This allows us to potentially uncover some "always unreachable" code
428 // within the "sometimes unreachable" code.
429 bool TreatAllSuccessorsAsReachable = shouldTreatSuccessorsAsReachable(item);
430
Ted Kremenekbd913712011-08-23 23:05:11 +0000431 // Look at the successors and mark then reachable.
432 for (CFGBlock::const_succ_iterator I = item->succ_begin(),
Ted Kremenek08da9782014-02-27 21:56:47 +0000433 E = item->succ_end(); I != E; ++I) {
434 const CFGBlock *B = *I;
Ted Kremenek6d9bb562014-03-05 00:01:17 +0000435 if (!B) do {
436 const CFGBlock *UB = I->getPossiblyUnreachableBlock();
437 if (!UB)
438 break;
439
440 if (TreatAllSuccessorsAsReachable) {
441 B = UB;
442 break;
443 }
444
Ted Kremenek08da9782014-02-27 21:56:47 +0000445 // For switch statements, treat all cases as being reachable.
446 // There are many cases where a switch can contain values that
447 // are not in an enumeration but they are still reachable because
448 // other values are possible.
449 //
450 // Note that this is quite conservative. If one saw:
451 //
452 // switch (1) {
453 // case 2: ...
454 //
455 // we should be able to say that 'case 2' is unreachable. To do
456 // this we can either put more heuristics here, or possibly retain
457 // that information in the CFG itself.
458 //
Ted Kremenek6d9bb562014-03-05 00:01:17 +0000459 const Stmt *Label = UB->getLabel();
460 if (Label && isa<SwitchCase>(Label))
461 B = UB;
Ted Kremenek08da9782014-02-27 21:56:47 +0000462 }
Ted Kremenek6d9bb562014-03-05 00:01:17 +0000463 while (false);
464
Ted Kremenek08da9782014-02-27 21:56:47 +0000465 if (B) {
Ted Kremenek7296de92010-02-23 02:39:16 +0000466 unsigned blockID = B->getBlockID();
467 if (!Reachable[blockID]) {
468 Reachable.set(blockID);
Ted Kremenek7296de92010-02-23 02:39:16 +0000469 WL.push_back(B);
Ted Kremenekbd913712011-08-23 23:05:11 +0000470 ++count;
Ted Kremenek7296de92010-02-23 02:39:16 +0000471 }
472 }
Ted Kremenek08da9782014-02-27 21:56:47 +0000473 }
Ted Kremenek7296de92010-02-23 02:39:16 +0000474 }
475 return count;
476}
Ted Kremenekbd913712011-08-23 23:05:11 +0000477
Ted Kremenek81ce1c82011-10-24 01:32:45 +0000478void FindUnreachableCode(AnalysisDeclContext &AC, Callback &CB) {
Ted Kremenek552eeaa2010-02-23 05:59:20 +0000479 CFG *cfg = AC.getCFG();
480 if (!cfg)
481 return;
482
Ted Kremenekbd913712011-08-23 23:05:11 +0000483 // Scan for reachable blocks from the entrance of the CFG.
484 // If there are no unreachable blocks, we're done.
Ted Kremenek552eeaa2010-02-23 05:59:20 +0000485 llvm::BitVector reachable(cfg->getNumBlockIDs());
Ted Kremenekbd913712011-08-23 23:05:11 +0000486 unsigned numReachable = ScanReachableFromBlock(&cfg->getEntry(), reachable);
Ted Kremenek552eeaa2010-02-23 05:59:20 +0000487 if (numReachable == cfg->getNumBlockIDs())
488 return;
Ted Kremenekbd913712011-08-23 23:05:11 +0000489
490 // If there aren't explicit EH edges, we should include the 'try' dispatch
491 // blocks as roots.
492 if (!AC.getCFGBuildOptions().AddEHEdges) {
493 for (CFG::try_block_iterator I = cfg->try_blocks_begin(),
494 E = cfg->try_blocks_end() ; I != E; ++I) {
495 numReachable += ScanReachableFromBlock(*I, reachable);
496 }
497 if (numReachable == cfg->getNumBlockIDs())
498 return;
499 }
Ted Kremenek552eeaa2010-02-23 05:59:20 +0000500
Ted Kremenekbd913712011-08-23 23:05:11 +0000501 // There are some unreachable blocks. We need to find the root blocks that
502 // contain code that should be considered unreachable.
Ted Kremenek552eeaa2010-02-23 05:59:20 +0000503 for (CFG::iterator I = cfg->begin(), E = cfg->end(); I != E; ++I) {
Ted Kremenekbd913712011-08-23 23:05:11 +0000504 const CFGBlock *block = *I;
505 // A block may have been marked reachable during this loop.
506 if (reachable[block->getBlockID()])
507 continue;
508
509 DeadCodeScan DS(reachable);
510 numReachable += DS.scanBackwards(block, CB);
511
512 if (numReachable == cfg->getNumBlockIDs())
513 return;
Ted Kremenek552eeaa2010-02-23 05:59:20 +0000514 }
Ted Kremenek552eeaa2010-02-23 05:59:20 +0000515}
516
517}} // end namespace clang::reachable_code