blob: 79e8d8cb0180a533933afa37135fe83ebed2140c [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>()) {
Ted Kremenekec2dc732014-03-06 06:50:46 +0000254 const Stmt *S = CS->getStmt();
255 if (const ExprWithCleanups *EWC = dyn_cast<ExprWithCleanups>(S))
256 S = EWC->getSubExpr();
257 if (const CallExpr *CE = dyn_cast<CallExpr>(S)) {
Ted Kremenekcc893382014-02-27 00:24:08 +0000258 QualType CalleeType = CE->getCallee()->getType();
259 if (getFunctionExtInfo(*CalleeType).getNoReturn())
260 return true;
261 }
262 break;
263 }
264 }
265 return false;
266}
267
Ted Kremenek5441c182014-02-27 06:32:32 +0000268static bool bodyEndsWithNoReturn(const CFGBlock::AdjacentBlock &AB) {
Ted Kremenekeb862842014-03-04 21:41:38 +0000269 // If the predecessor is a normal CFG edge, then by definition
270 // the predecessor did not end with a 'noreturn'.
271 if (AB.getReachableBlock())
272 return false;
273
Ted Kremenek5441c182014-02-27 06:32:32 +0000274 const CFGBlock *Pred = AB.getPossiblyUnreachableBlock();
275 assert(!AB.isReachable() && Pred);
276 return bodyEndsWithNoReturn(Pred);
277}
278
Ted Kremenekcc893382014-02-27 00:24:08 +0000279static bool isBreakPrecededByNoReturn(const CFGBlock *B,
280 const Stmt *S) {
281 if (!isa<BreakStmt>(S) || B->pred_empty())
282 return false;
283
284 assert(B->empty());
285 assert(B->pred_size() == 1);
Ted Kremenek5441c182014-02-27 06:32:32 +0000286 return bodyEndsWithNoReturn(*B->pred_begin());
287}
288
289static bool isEnumConstant(const Expr *Ex) {
290 const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(Ex);
291 if (!DR)
292 return false;
293 return isa<EnumConstantDecl>(DR->getDecl());
294}
295
Ted Kremenekec2dc732014-03-06 06:50:46 +0000296static const Expr *stripStdStringCtor(const Expr *Ex) {
297 // Go crazy pattern matching an implicit construction of std::string("").
298 const ExprWithCleanups *EWC = dyn_cast<ExprWithCleanups>(Ex);
299 if (!EWC)
300 return 0;
301 const CXXConstructExpr *CCE = dyn_cast<CXXConstructExpr>(EWC->getSubExpr());
302 if (!CCE)
303 return 0;
304 QualType Ty = CCE->getType();
305 if (const ElaboratedType *ET = dyn_cast<ElaboratedType>(Ty))
306 Ty = ET->getNamedType();
307 const TypedefType *TT = dyn_cast<TypedefType>(Ty);
308 StringRef Name = TT->getDecl()->getName();
309 if (Name != "string")
310 return 0;
311 if (CCE->getNumArgs() != 1)
312 return 0;
313 const MaterializeTemporaryExpr *MTE =
314 dyn_cast<MaterializeTemporaryExpr>(CCE->getArg(0));
315 if (!MTE)
316 return 0;
317 CXXBindTemporaryExpr *CBT =
318 dyn_cast<CXXBindTemporaryExpr>(MTE->GetTemporaryExpr()->IgnoreParenCasts());
319 if (!CBT)
320 return 0;
321 Ex = CBT->getSubExpr()->IgnoreParenCasts();
322 CCE = dyn_cast<CXXConstructExpr>(Ex);
323 if (!CCE)
324 return 0;
325 if (CCE->getNumArgs() != 1)
326 return 0;
327 return dyn_cast<StringLiteral>(CCE->getArg(0)->IgnoreParenCasts());
328}
329
330/// Strip away "sugar" around trivial expressions that are for the
331/// purpose of this analysis considered uninteresting for dead code warnings.
332static const Expr *stripExprSugar(const Expr *Ex) {
333 Ex = Ex->IgnoreParenCasts();
334 // If 'Ex' is a constructor for a std::string, strip that
335 // away. We can only get here if the trivial expression was
336 // something like a C string literal, with the std::string
337 // just wrapping that value.
338 if (const Expr *StdStringVal = stripStdStringCtor(Ex))
339 return StdStringVal;
340 return Ex;
341}
342
Ted Kremenek5441c182014-02-27 06:32:32 +0000343static bool isTrivialExpression(const Expr *Ex) {
Ted Kremenek0a69cab2014-03-05 23:46:07 +0000344 Ex = Ex->IgnoreParenCasts();
Ted Kremenek5441c182014-02-27 06:32:32 +0000345 return isa<IntegerLiteral>(Ex) || isa<StringLiteral>(Ex) ||
346 isEnumConstant(Ex);
347}
348
Ted Kremenek1de2e142014-03-06 00:17:44 +0000349static bool isTrivialReturnOrDoWhile(const CFGBlock *B, const Stmt *S) {
Ted Kremenek5441c182014-02-27 06:32:32 +0000350 const Expr *Ex = dyn_cast<Expr>(S);
351 if (!Ex)
352 return false;
353
Ted Kremenek5441c182014-02-27 06:32:32 +0000354 if (!isTrivialExpression(Ex))
355 return false;
356
Ted Kremenek1de2e142014-03-06 00:17:44 +0000357 // Check if the block ends with a do...while() and see if 'S' is the
358 // condition.
359 if (const Stmt *Term = B->getTerminator()) {
360 if (const DoStmt *DS = dyn_cast<DoStmt>(Term))
361 if (DS->getCond() == S)
362 return true;
363 }
364
Ted Kremenek7549f0f2014-03-06 01:09:45 +0000365 if (B->pred_size() != 1)
366 return false;
Ted Kremenek1de2e142014-03-06 00:17:44 +0000367
Ted Kremenek5441c182014-02-27 06:32:32 +0000368 // Look to see if the block ends with a 'return', and see if 'S'
369 // is a substatement. The 'return' may not be the last element in
370 // the block because of destructors.
371 assert(!B->empty());
372 for (CFGBlock::const_reverse_iterator I = B->rbegin(), E = B->rend();
373 I != E; ++I) {
374 if (Optional<CFGStmt> CS = I->getAs<CFGStmt>()) {
375 if (const ReturnStmt *RS = dyn_cast<ReturnStmt>(CS->getStmt())) {
376 const Expr *RE = RS->getRetValue();
Ted Kremenekec2dc732014-03-06 06:50:46 +0000377 if (RE && stripExprSugar(RE->IgnoreParenCasts()) == Ex)
Ted Kremenek7549f0f2014-03-06 01:09:45 +0000378 return bodyEndsWithNoReturn(*B->pred_begin());
Ted Kremenek5441c182014-02-27 06:32:32 +0000379 }
Ted Kremenek7549f0f2014-03-06 01:09:45 +0000380 break;
Ted Kremenek5441c182014-02-27 06:32:32 +0000381 }
382 }
Ted Kremenek0a69cab2014-03-05 23:46:07 +0000383 return false;
Ted Kremenekcc893382014-02-27 00:24:08 +0000384}
385
386void DeadCodeScan::reportDeadCode(const CFGBlock *B,
387 const Stmt *S,
Ted Kremenekbd913712011-08-23 23:05:11 +0000388 clang::reachable_code::Callback &CB) {
Ted Kremenekcc893382014-02-27 00:24:08 +0000389 // Suppress idiomatic cases of calling a noreturn function just
390 // before executing a 'break'. If there is other code after the 'break'
391 // in the block then don't suppress the warning.
392 if (isBreakPrecededByNoReturn(B, S))
393 return;
394
Ted Kremenek5441c182014-02-27 06:32:32 +0000395 // Suppress trivial 'return' statements that are dead.
Ted Kremenek1de2e142014-03-06 00:17:44 +0000396 if (isTrivialReturnOrDoWhile(B, S))
Ted Kremenek5441c182014-02-27 06:32:32 +0000397 return;
398
Ted Kremenek552eeaa2010-02-23 05:59:20 +0000399 SourceRange R1, R2;
Ted Kremenekbd913712011-08-23 23:05:11 +0000400 SourceLocation Loc = GetUnreachableLoc(S, R1, R2);
401 CB.HandleUnreachable(Loc, R1, R2);
Ted Kremenek552eeaa2010-02-23 05:59:20 +0000402}
403
Ted Kremenek552eeaa2010-02-23 05:59:20 +0000404namespace clang { namespace reachable_code {
David Blaikie68e081d2011-12-20 02:48:34 +0000405
406void Callback::anchor() { }
407
Ted Kremenek6d9bb562014-03-05 00:01:17 +0000408/// Returns true if the statement is expanded from a configuration macro.
409static bool isExpandedFromConfigurationMacro(const Stmt *S) {
410 // FIXME: This is not very precise. Here we just check to see if the
411 // value comes from a macro, but we can do much better. This is likely
412 // to be over conservative. This logic is factored into a separate function
413 // so that we can refine it later.
414 SourceLocation L = S->getLocStart();
415 return L.isMacroID();
416}
417
418/// Returns true if the statement represents a configuration value.
419///
420/// A configuration value is something usually determined at compile-time
421/// to conditionally always execute some branch. Such guards are for
422/// "sometimes unreachable" code. Such code is usually not interesting
423/// to report as unreachable, and may mask truly unreachable code within
424/// those blocks.
425static bool isConfigurationValue(const Stmt *S) {
426 if (!S)
427 return false;
428
429 if (const Expr *Ex = dyn_cast<Expr>(S))
430 S = Ex->IgnoreParenCasts();
431
432 switch (S->getStmtClass()) {
Ted Kremenek01a39b62014-03-05 23:38:41 +0000433 case Stmt::DeclRefExprClass: {
434 const DeclRefExpr *DR = cast<DeclRefExpr>(S);
435 const EnumConstantDecl *ED = dyn_cast<EnumConstantDecl>(DR->getDecl());
436 return ED ? isConfigurationValue(ED->getInitExpr()) : false;
437 }
Ted Kremenek6d9bb562014-03-05 00:01:17 +0000438 case Stmt::IntegerLiteralClass:
439 return isExpandedFromConfigurationMacro(S);
440 case Stmt::UnaryExprOrTypeTraitExprClass:
441 return true;
442 case Stmt::BinaryOperatorClass: {
443 const BinaryOperator *B = cast<BinaryOperator>(S);
Ted Kremenek3cdbc392014-03-05 22:32:39 +0000444 return (B->isLogicalOp() || B->isComparisonOp()) &&
Ted Kremenek6d9bb562014-03-05 00:01:17 +0000445 (isConfigurationValue(B->getLHS()) ||
446 isConfigurationValue(B->getRHS()));
447 }
448 case Stmt::UnaryOperatorClass: {
449 const UnaryOperator *UO = cast<UnaryOperator>(S);
450 return UO->getOpcode() == UO_LNot &&
451 isConfigurationValue(UO->getSubExpr());
452 }
453 default:
454 return false;
455 }
456}
457
458/// Returns true if we should always explore all successors of a block.
459static bool shouldTreatSuccessorsAsReachable(const CFGBlock *B) {
460 return isConfigurationValue(B->getTerminatorCondition());
461}
462
Ted Kremenekbd913712011-08-23 23:05:11 +0000463unsigned ScanReachableFromBlock(const CFGBlock *Start,
Ted Kremenek552eeaa2010-02-23 05:59:20 +0000464 llvm::BitVector &Reachable) {
465 unsigned count = 0;
Ted Kremenekbd913712011-08-23 23:05:11 +0000466
Nico Webercc2b8712011-04-02 19:45:15 +0000467 // Prep work queue
Ted Kremenekbd913712011-08-23 23:05:11 +0000468 SmallVector<const CFGBlock*, 32> WL;
469
470 // The entry block may have already been marked reachable
471 // by the caller.
472 if (!Reachable[Start->getBlockID()]) {
473 ++count;
474 Reachable[Start->getBlockID()] = true;
475 }
476
477 WL.push_back(Start);
478
Ted Kremenekf2b0a1b2010-09-09 00:06:10 +0000479 // Find the reachable blocks from 'Start'.
Ted Kremenek552eeaa2010-02-23 05:59:20 +0000480 while (!WL.empty()) {
Ted Kremenekbd913712011-08-23 23:05:11 +0000481 const CFGBlock *item = WL.pop_back_val();
Ted Kremenek6d9bb562014-03-05 00:01:17 +0000482
483 // There are cases where we want to treat all successors as reachable.
484 // The idea is that some "sometimes unreachable" code is not interesting,
485 // and that we should forge ahead and explore those branches anyway.
486 // This allows us to potentially uncover some "always unreachable" code
487 // within the "sometimes unreachable" code.
488 bool TreatAllSuccessorsAsReachable = shouldTreatSuccessorsAsReachable(item);
489
Ted Kremenekbd913712011-08-23 23:05:11 +0000490 // Look at the successors and mark then reachable.
491 for (CFGBlock::const_succ_iterator I = item->succ_begin(),
Ted Kremenek08da9782014-02-27 21:56:47 +0000492 E = item->succ_end(); I != E; ++I) {
493 const CFGBlock *B = *I;
Ted Kremenek6d9bb562014-03-05 00:01:17 +0000494 if (!B) do {
495 const CFGBlock *UB = I->getPossiblyUnreachableBlock();
496 if (!UB)
497 break;
498
499 if (TreatAllSuccessorsAsReachable) {
500 B = UB;
501 break;
502 }
503
Ted Kremenek08da9782014-02-27 21:56:47 +0000504 // For switch statements, treat all cases as being reachable.
505 // There are many cases where a switch can contain values that
506 // are not in an enumeration but they are still reachable because
507 // other values are possible.
508 //
509 // Note that this is quite conservative. If one saw:
510 //
511 // switch (1) {
512 // case 2: ...
513 //
514 // we should be able to say that 'case 2' is unreachable. To do
515 // this we can either put more heuristics here, or possibly retain
516 // that information in the CFG itself.
517 //
Ted Kremenek6d9bb562014-03-05 00:01:17 +0000518 const Stmt *Label = UB->getLabel();
519 if (Label && isa<SwitchCase>(Label))
520 B = UB;
Ted Kremenek08da9782014-02-27 21:56:47 +0000521 }
Ted Kremenek6d9bb562014-03-05 00:01:17 +0000522 while (false);
523
Ted Kremenek08da9782014-02-27 21:56:47 +0000524 if (B) {
Ted Kremenek7296de92010-02-23 02:39:16 +0000525 unsigned blockID = B->getBlockID();
526 if (!Reachable[blockID]) {
527 Reachable.set(blockID);
Ted Kremenek7296de92010-02-23 02:39:16 +0000528 WL.push_back(B);
Ted Kremenekbd913712011-08-23 23:05:11 +0000529 ++count;
Ted Kremenek7296de92010-02-23 02:39:16 +0000530 }
531 }
Ted Kremenek08da9782014-02-27 21:56:47 +0000532 }
Ted Kremenek7296de92010-02-23 02:39:16 +0000533 }
534 return count;
535}
Ted Kremenekbd913712011-08-23 23:05:11 +0000536
Ted Kremenek81ce1c82011-10-24 01:32:45 +0000537void FindUnreachableCode(AnalysisDeclContext &AC, Callback &CB) {
Ted Kremenek552eeaa2010-02-23 05:59:20 +0000538 CFG *cfg = AC.getCFG();
539 if (!cfg)
540 return;
541
Ted Kremenekbd913712011-08-23 23:05:11 +0000542 // Scan for reachable blocks from the entrance of the CFG.
543 // If there are no unreachable blocks, we're done.
Ted Kremenek552eeaa2010-02-23 05:59:20 +0000544 llvm::BitVector reachable(cfg->getNumBlockIDs());
Ted Kremenekbd913712011-08-23 23:05:11 +0000545 unsigned numReachable = ScanReachableFromBlock(&cfg->getEntry(), reachable);
Ted Kremenek552eeaa2010-02-23 05:59:20 +0000546 if (numReachable == cfg->getNumBlockIDs())
547 return;
Ted Kremenekbd913712011-08-23 23:05:11 +0000548
549 // If there aren't explicit EH edges, we should include the 'try' dispatch
550 // blocks as roots.
551 if (!AC.getCFGBuildOptions().AddEHEdges) {
552 for (CFG::try_block_iterator I = cfg->try_blocks_begin(),
553 E = cfg->try_blocks_end() ; I != E; ++I) {
554 numReachable += ScanReachableFromBlock(*I, reachable);
555 }
556 if (numReachable == cfg->getNumBlockIDs())
557 return;
558 }
Ted Kremenek552eeaa2010-02-23 05:59:20 +0000559
Ted Kremenekbd913712011-08-23 23:05:11 +0000560 // There are some unreachable blocks. We need to find the root blocks that
561 // contain code that should be considered unreachable.
Ted Kremenek552eeaa2010-02-23 05:59:20 +0000562 for (CFG::iterator I = cfg->begin(), E = cfg->end(); I != E; ++I) {
Ted Kremenekbd913712011-08-23 23:05:11 +0000563 const CFGBlock *block = *I;
564 // A block may have been marked reachable during this loop.
565 if (reachable[block->getBlockID()])
566 continue;
567
568 DeadCodeScan DS(reachable);
569 numReachable += DS.scanBackwards(block, CB);
570
571 if (numReachable == cfg->getNumBlockIDs())
572 return;
Ted Kremenek552eeaa2010-02-23 05:59:20 +0000573 }
Ted Kremenek552eeaa2010-02-23 05:59:20 +0000574}
575
576}} // end namespace clang::reachable_code