blob: 7958840b89d0c638bccb042c7037c13f9a308eeb [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) {
Ted Kremenek0a69cab2014-03-05 23:46:07 +0000294 Ex = Ex->IgnoreParenCasts();
Ted Kremenek5441c182014-02-27 06:32:32 +0000295 return isa<IntegerLiteral>(Ex) || isa<StringLiteral>(Ex) ||
296 isEnumConstant(Ex);
297}
298
Ted Kremenek0a69cab2014-03-05 23:46:07 +0000299static bool isTrivialReturn(const CFGBlock *B, const Stmt *S) {
Ted Kremenek5441c182014-02-27 06:32:32 +0000300 if (B->pred_empty())
301 return false;
302
303 const Expr *Ex = dyn_cast<Expr>(S);
304 if (!Ex)
305 return false;
306
Ted Kremenek5441c182014-02-27 06:32:32 +0000307 if (!isTrivialExpression(Ex))
308 return false;
309
310 // Look to see if the block ends with a 'return', and see if 'S'
311 // is a substatement. The 'return' may not be the last element in
312 // the block because of destructors.
313 assert(!B->empty());
314 for (CFGBlock::const_reverse_iterator I = B->rbegin(), E = B->rend();
315 I != E; ++I) {
316 if (Optional<CFGStmt> CS = I->getAs<CFGStmt>()) {
317 if (const ReturnStmt *RS = dyn_cast<ReturnStmt>(CS->getStmt())) {
318 const Expr *RE = RS->getRetValue();
319 if (RE && RE->IgnoreParenCasts() == Ex)
Ted Kremenek0a69cab2014-03-05 23:46:07 +0000320 return true;
Ted Kremenek5441c182014-02-27 06:32:32 +0000321 }
Ted Kremenek0a69cab2014-03-05 23:46:07 +0000322 break;
Ted Kremenek5441c182014-02-27 06:32:32 +0000323 }
324 }
325
Ted Kremenek0a69cab2014-03-05 23:46:07 +0000326 return false;
Ted Kremenekcc893382014-02-27 00:24:08 +0000327}
328
329void DeadCodeScan::reportDeadCode(const CFGBlock *B,
330 const Stmt *S,
Ted Kremenekbd913712011-08-23 23:05:11 +0000331 clang::reachable_code::Callback &CB) {
Ted Kremenekcc893382014-02-27 00:24:08 +0000332 // Suppress idiomatic cases of calling a noreturn function just
333 // before executing a 'break'. If there is other code after the 'break'
334 // in the block then don't suppress the warning.
335 if (isBreakPrecededByNoReturn(B, S))
336 return;
337
Ted Kremenek5441c182014-02-27 06:32:32 +0000338 // Suppress trivial 'return' statements that are dead.
Ted Kremenek0a69cab2014-03-05 23:46:07 +0000339 if (isTrivialReturn(B, S))
Ted Kremenek5441c182014-02-27 06:32:32 +0000340 return;
341
Ted Kremenek552eeaa2010-02-23 05:59:20 +0000342 SourceRange R1, R2;
Ted Kremenekbd913712011-08-23 23:05:11 +0000343 SourceLocation Loc = GetUnreachableLoc(S, R1, R2);
344 CB.HandleUnreachable(Loc, R1, R2);
Ted Kremenek552eeaa2010-02-23 05:59:20 +0000345}
346
Ted Kremenek552eeaa2010-02-23 05:59:20 +0000347namespace clang { namespace reachable_code {
David Blaikie68e081d2011-12-20 02:48:34 +0000348
349void Callback::anchor() { }
350
Ted Kremenek6d9bb562014-03-05 00:01:17 +0000351/// Returns true if the statement is expanded from a configuration macro.
352static bool isExpandedFromConfigurationMacro(const Stmt *S) {
353 // FIXME: This is not very precise. Here we just check to see if the
354 // value comes from a macro, but we can do much better. This is likely
355 // to be over conservative. This logic is factored into a separate function
356 // so that we can refine it later.
357 SourceLocation L = S->getLocStart();
358 return L.isMacroID();
359}
360
361/// Returns true if the statement represents a configuration value.
362///
363/// A configuration value is something usually determined at compile-time
364/// to conditionally always execute some branch. Such guards are for
365/// "sometimes unreachable" code. Such code is usually not interesting
366/// to report as unreachable, and may mask truly unreachable code within
367/// those blocks.
368static bool isConfigurationValue(const Stmt *S) {
369 if (!S)
370 return false;
371
372 if (const Expr *Ex = dyn_cast<Expr>(S))
373 S = Ex->IgnoreParenCasts();
374
375 switch (S->getStmtClass()) {
Ted Kremenek01a39b62014-03-05 23:38:41 +0000376 case Stmt::DeclRefExprClass: {
377 const DeclRefExpr *DR = cast<DeclRefExpr>(S);
378 const EnumConstantDecl *ED = dyn_cast<EnumConstantDecl>(DR->getDecl());
379 return ED ? isConfigurationValue(ED->getInitExpr()) : false;
380 }
Ted Kremenek6d9bb562014-03-05 00:01:17 +0000381 case Stmt::IntegerLiteralClass:
382 return isExpandedFromConfigurationMacro(S);
383 case Stmt::UnaryExprOrTypeTraitExprClass:
384 return true;
385 case Stmt::BinaryOperatorClass: {
386 const BinaryOperator *B = cast<BinaryOperator>(S);
Ted Kremenek3cdbc392014-03-05 22:32:39 +0000387 return (B->isLogicalOp() || B->isComparisonOp()) &&
Ted Kremenek6d9bb562014-03-05 00:01:17 +0000388 (isConfigurationValue(B->getLHS()) ||
389 isConfigurationValue(B->getRHS()));
390 }
391 case Stmt::UnaryOperatorClass: {
392 const UnaryOperator *UO = cast<UnaryOperator>(S);
393 return UO->getOpcode() == UO_LNot &&
394 isConfigurationValue(UO->getSubExpr());
395 }
396 default:
397 return false;
398 }
399}
400
401/// Returns true if we should always explore all successors of a block.
402static bool shouldTreatSuccessorsAsReachable(const CFGBlock *B) {
403 return isConfigurationValue(B->getTerminatorCondition());
404}
405
Ted Kremenekbd913712011-08-23 23:05:11 +0000406unsigned ScanReachableFromBlock(const CFGBlock *Start,
Ted Kremenek552eeaa2010-02-23 05:59:20 +0000407 llvm::BitVector &Reachable) {
408 unsigned count = 0;
Ted Kremenekbd913712011-08-23 23:05:11 +0000409
Nico Webercc2b8712011-04-02 19:45:15 +0000410 // Prep work queue
Ted Kremenekbd913712011-08-23 23:05:11 +0000411 SmallVector<const CFGBlock*, 32> WL;
412
413 // The entry block may have already been marked reachable
414 // by the caller.
415 if (!Reachable[Start->getBlockID()]) {
416 ++count;
417 Reachable[Start->getBlockID()] = true;
418 }
419
420 WL.push_back(Start);
421
Ted Kremenekf2b0a1b2010-09-09 00:06:10 +0000422 // Find the reachable blocks from 'Start'.
Ted Kremenek552eeaa2010-02-23 05:59:20 +0000423 while (!WL.empty()) {
Ted Kremenekbd913712011-08-23 23:05:11 +0000424 const CFGBlock *item = WL.pop_back_val();
Ted Kremenek6d9bb562014-03-05 00:01:17 +0000425
426 // There are cases where we want to treat all successors as reachable.
427 // The idea is that some "sometimes unreachable" code is not interesting,
428 // and that we should forge ahead and explore those branches anyway.
429 // This allows us to potentially uncover some "always unreachable" code
430 // within the "sometimes unreachable" code.
431 bool TreatAllSuccessorsAsReachable = shouldTreatSuccessorsAsReachable(item);
432
Ted Kremenekbd913712011-08-23 23:05:11 +0000433 // Look at the successors and mark then reachable.
434 for (CFGBlock::const_succ_iterator I = item->succ_begin(),
Ted Kremenek08da9782014-02-27 21:56:47 +0000435 E = item->succ_end(); I != E; ++I) {
436 const CFGBlock *B = *I;
Ted Kremenek6d9bb562014-03-05 00:01:17 +0000437 if (!B) do {
438 const CFGBlock *UB = I->getPossiblyUnreachableBlock();
439 if (!UB)
440 break;
441
442 if (TreatAllSuccessorsAsReachable) {
443 B = UB;
444 break;
445 }
446
Ted Kremenek08da9782014-02-27 21:56:47 +0000447 // For switch statements, treat all cases as being reachable.
448 // There are many cases where a switch can contain values that
449 // are not in an enumeration but they are still reachable because
450 // other values are possible.
451 //
452 // Note that this is quite conservative. If one saw:
453 //
454 // switch (1) {
455 // case 2: ...
456 //
457 // we should be able to say that 'case 2' is unreachable. To do
458 // this we can either put more heuristics here, or possibly retain
459 // that information in the CFG itself.
460 //
Ted Kremenek6d9bb562014-03-05 00:01:17 +0000461 const Stmt *Label = UB->getLabel();
462 if (Label && isa<SwitchCase>(Label))
463 B = UB;
Ted Kremenek08da9782014-02-27 21:56:47 +0000464 }
Ted Kremenek6d9bb562014-03-05 00:01:17 +0000465 while (false);
466
Ted Kremenek08da9782014-02-27 21:56:47 +0000467 if (B) {
Ted Kremenek7296de92010-02-23 02:39:16 +0000468 unsigned blockID = B->getBlockID();
469 if (!Reachable[blockID]) {
470 Reachable.set(blockID);
Ted Kremenek7296de92010-02-23 02:39:16 +0000471 WL.push_back(B);
Ted Kremenekbd913712011-08-23 23:05:11 +0000472 ++count;
Ted Kremenek7296de92010-02-23 02:39:16 +0000473 }
474 }
Ted Kremenek08da9782014-02-27 21:56:47 +0000475 }
Ted Kremenek7296de92010-02-23 02:39:16 +0000476 }
477 return count;
478}
Ted Kremenekbd913712011-08-23 23:05:11 +0000479
Ted Kremenek81ce1c82011-10-24 01:32:45 +0000480void FindUnreachableCode(AnalysisDeclContext &AC, Callback &CB) {
Ted Kremenek552eeaa2010-02-23 05:59:20 +0000481 CFG *cfg = AC.getCFG();
482 if (!cfg)
483 return;
484
Ted Kremenekbd913712011-08-23 23:05:11 +0000485 // Scan for reachable blocks from the entrance of the CFG.
486 // If there are no unreachable blocks, we're done.
Ted Kremenek552eeaa2010-02-23 05:59:20 +0000487 llvm::BitVector reachable(cfg->getNumBlockIDs());
Ted Kremenekbd913712011-08-23 23:05:11 +0000488 unsigned numReachable = ScanReachableFromBlock(&cfg->getEntry(), reachable);
Ted Kremenek552eeaa2010-02-23 05:59:20 +0000489 if (numReachable == cfg->getNumBlockIDs())
490 return;
Ted Kremenekbd913712011-08-23 23:05:11 +0000491
492 // If there aren't explicit EH edges, we should include the 'try' dispatch
493 // blocks as roots.
494 if (!AC.getCFGBuildOptions().AddEHEdges) {
495 for (CFG::try_block_iterator I = cfg->try_blocks_begin(),
496 E = cfg->try_blocks_end() ; I != E; ++I) {
497 numReachable += ScanReachableFromBlock(*I, reachable);
498 }
499 if (numReachable == cfg->getNumBlockIDs())
500 return;
501 }
Ted Kremenek552eeaa2010-02-23 05:59:20 +0000502
Ted Kremenekbd913712011-08-23 23:05:11 +0000503 // There are some unreachable blocks. We need to find the root blocks that
504 // contain code that should be considered unreachable.
Ted Kremenek552eeaa2010-02-23 05:59:20 +0000505 for (CFG::iterator I = cfg->begin(), E = cfg->end(); I != E; ++I) {
Ted Kremenekbd913712011-08-23 23:05:11 +0000506 const CFGBlock *block = *I;
507 // A block may have been marked reachable during this loop.
508 if (reachable[block->getBlockID()])
509 continue;
510
511 DeadCodeScan DS(reachable);
512 numReachable += DS.scanBackwards(block, CB);
513
514 if (numReachable == cfg->getNumBlockIDs())
515 return;
Ted Kremenek552eeaa2010-02-23 05:59:20 +0000516 }
Ted Kremenek552eeaa2010-02-23 05:59:20 +0000517}
518
519}} // end namespace clang::reachable_code