blob: 09abcc9b7dcb881fbbd4ec105000deedd6d3bff0 [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) ||
Ted Kremenekc10830b2014-03-07 02:25:50 +0000346 isa<CXXBoolLiteralExpr>(Ex) || isa<ObjCBoolLiteralExpr>(Ex) ||
347 isa<CharacterLiteral>(Ex) ||
Ted Kremenek5441c182014-02-27 06:32:32 +0000348 isEnumConstant(Ex);
349}
350
Ted Kremenek1de2e142014-03-06 00:17:44 +0000351static bool isTrivialReturnOrDoWhile(const CFGBlock *B, const Stmt *S) {
Ted Kremenek5441c182014-02-27 06:32:32 +0000352 const Expr *Ex = dyn_cast<Expr>(S);
353 if (!Ex)
354 return false;
355
Ted Kremenek5441c182014-02-27 06:32:32 +0000356 if (!isTrivialExpression(Ex))
357 return false;
358
Ted Kremenek1de2e142014-03-06 00:17:44 +0000359 // Check if the block ends with a do...while() and see if 'S' is the
360 // condition.
361 if (const Stmt *Term = B->getTerminator()) {
362 if (const DoStmt *DS = dyn_cast<DoStmt>(Term))
363 if (DS->getCond() == S)
364 return true;
365 }
366
Ted Kremenek7549f0f2014-03-06 01:09:45 +0000367 if (B->pred_size() != 1)
368 return false;
Ted Kremenek1de2e142014-03-06 00:17:44 +0000369
Ted Kremenek5441c182014-02-27 06:32:32 +0000370 // Look to see if the block ends with a 'return', and see if 'S'
371 // is a substatement. The 'return' may not be the last element in
372 // the block because of destructors.
373 assert(!B->empty());
374 for (CFGBlock::const_reverse_iterator I = B->rbegin(), E = B->rend();
375 I != E; ++I) {
376 if (Optional<CFGStmt> CS = I->getAs<CFGStmt>()) {
377 if (const ReturnStmt *RS = dyn_cast<ReturnStmt>(CS->getStmt())) {
378 const Expr *RE = RS->getRetValue();
Ted Kremenekec2dc732014-03-06 06:50:46 +0000379 if (RE && stripExprSugar(RE->IgnoreParenCasts()) == Ex)
Ted Kremenek7549f0f2014-03-06 01:09:45 +0000380 return bodyEndsWithNoReturn(*B->pred_begin());
Ted Kremenek5441c182014-02-27 06:32:32 +0000381 }
Ted Kremenek7549f0f2014-03-06 01:09:45 +0000382 break;
Ted Kremenek5441c182014-02-27 06:32:32 +0000383 }
384 }
Ted Kremenek0a69cab2014-03-05 23:46:07 +0000385 return false;
Ted Kremenekcc893382014-02-27 00:24:08 +0000386}
387
388void DeadCodeScan::reportDeadCode(const CFGBlock *B,
389 const Stmt *S,
Ted Kremenekbd913712011-08-23 23:05:11 +0000390 clang::reachable_code::Callback &CB) {
Ted Kremenekcc893382014-02-27 00:24:08 +0000391 // Suppress idiomatic cases of calling a noreturn function just
392 // before executing a 'break'. If there is other code after the 'break'
393 // in the block then don't suppress the warning.
394 if (isBreakPrecededByNoReturn(B, S))
395 return;
396
Ted Kremenek5441c182014-02-27 06:32:32 +0000397 // Suppress trivial 'return' statements that are dead.
Ted Kremenek1de2e142014-03-06 00:17:44 +0000398 if (isTrivialReturnOrDoWhile(B, S))
Ted Kremenek5441c182014-02-27 06:32:32 +0000399 return;
400
Ted Kremenek552eeaa2010-02-23 05:59:20 +0000401 SourceRange R1, R2;
Ted Kremenekbd913712011-08-23 23:05:11 +0000402 SourceLocation Loc = GetUnreachableLoc(S, R1, R2);
403 CB.HandleUnreachable(Loc, R1, R2);
Ted Kremenek552eeaa2010-02-23 05:59:20 +0000404}
405
Ted Kremenek552eeaa2010-02-23 05:59:20 +0000406namespace clang { namespace reachable_code {
David Blaikie68e081d2011-12-20 02:48:34 +0000407
408void Callback::anchor() { }
409
Ted Kremenek6d9bb562014-03-05 00:01:17 +0000410/// Returns true if the statement is expanded from a configuration macro.
411static bool isExpandedFromConfigurationMacro(const Stmt *S) {
412 // FIXME: This is not very precise. Here we just check to see if the
413 // value comes from a macro, but we can do much better. This is likely
414 // to be over conservative. This logic is factored into a separate function
415 // so that we can refine it later.
416 SourceLocation L = S->getLocStart();
417 return L.isMacroID();
418}
419
420/// Returns true if the statement represents a configuration value.
421///
422/// A configuration value is something usually determined at compile-time
423/// to conditionally always execute some branch. Such guards are for
424/// "sometimes unreachable" code. Such code is usually not interesting
425/// to report as unreachable, and may mask truly unreachable code within
426/// those blocks.
427static bool isConfigurationValue(const Stmt *S) {
428 if (!S)
429 return false;
430
431 if (const Expr *Ex = dyn_cast<Expr>(S))
432 S = Ex->IgnoreParenCasts();
433
434 switch (S->getStmtClass()) {
Ted Kremenek01a39b62014-03-05 23:38:41 +0000435 case Stmt::DeclRefExprClass: {
436 const DeclRefExpr *DR = cast<DeclRefExpr>(S);
437 const EnumConstantDecl *ED = dyn_cast<EnumConstantDecl>(DR->getDecl());
438 return ED ? isConfigurationValue(ED->getInitExpr()) : false;
439 }
Ted Kremenek6d9bb562014-03-05 00:01:17 +0000440 case Stmt::IntegerLiteralClass:
441 return isExpandedFromConfigurationMacro(S);
442 case Stmt::UnaryExprOrTypeTraitExprClass:
443 return true;
444 case Stmt::BinaryOperatorClass: {
445 const BinaryOperator *B = cast<BinaryOperator>(S);
Ted Kremenek3cdbc392014-03-05 22:32:39 +0000446 return (B->isLogicalOp() || B->isComparisonOp()) &&
Ted Kremenek6d9bb562014-03-05 00:01:17 +0000447 (isConfigurationValue(B->getLHS()) ||
448 isConfigurationValue(B->getRHS()));
449 }
450 case Stmt::UnaryOperatorClass: {
451 const UnaryOperator *UO = cast<UnaryOperator>(S);
452 return UO->getOpcode() == UO_LNot &&
453 isConfigurationValue(UO->getSubExpr());
454 }
455 default:
456 return false;
457 }
458}
459
460/// Returns true if we should always explore all successors of a block.
461static bool shouldTreatSuccessorsAsReachable(const CFGBlock *B) {
Ted Kremenek782f0032014-03-07 02:25:53 +0000462 if (const Stmt *Term = B->getTerminator()) {
Ted Kremenek6999d022014-03-06 08:09:00 +0000463 if (isa<SwitchStmt>(Term))
464 return true;
Ted Kremenek782f0032014-03-07 02:25:53 +0000465 // Specially handle '||' and '&&'.
466 if (isa<BinaryOperator>(Term))
467 return isConfigurationValue(Term);
468 }
Ted Kremenek6999d022014-03-06 08:09:00 +0000469
Ted Kremenek6d9bb562014-03-05 00:01:17 +0000470 return isConfigurationValue(B->getTerminatorCondition());
471}
472
Ted Kremenekbd913712011-08-23 23:05:11 +0000473unsigned ScanReachableFromBlock(const CFGBlock *Start,
Ted Kremenek552eeaa2010-02-23 05:59:20 +0000474 llvm::BitVector &Reachable) {
475 unsigned count = 0;
Ted Kremenekbd913712011-08-23 23:05:11 +0000476
Nico Webercc2b8712011-04-02 19:45:15 +0000477 // Prep work queue
Ted Kremenekbd913712011-08-23 23:05:11 +0000478 SmallVector<const CFGBlock*, 32> WL;
479
480 // The entry block may have already been marked reachable
481 // by the caller.
482 if (!Reachable[Start->getBlockID()]) {
483 ++count;
484 Reachable[Start->getBlockID()] = true;
485 }
486
487 WL.push_back(Start);
488
Ted Kremenekf2b0a1b2010-09-09 00:06:10 +0000489 // Find the reachable blocks from 'Start'.
Ted Kremenek552eeaa2010-02-23 05:59:20 +0000490 while (!WL.empty()) {
Ted Kremenekbd913712011-08-23 23:05:11 +0000491 const CFGBlock *item = WL.pop_back_val();
Ted Kremenek6d9bb562014-03-05 00:01:17 +0000492
493 // There are cases where we want to treat all successors as reachable.
494 // The idea is that some "sometimes unreachable" code is not interesting,
495 // and that we should forge ahead and explore those branches anyway.
496 // This allows us to potentially uncover some "always unreachable" code
497 // within the "sometimes unreachable" code.
Ted Kremenekbd913712011-08-23 23:05:11 +0000498 // Look at the successors and mark then reachable.
Ted Kremenek782f0032014-03-07 02:25:53 +0000499 Optional<bool> TreatAllSuccessorsAsReachable;
500
Ted Kremenekbd913712011-08-23 23:05:11 +0000501 for (CFGBlock::const_succ_iterator I = item->succ_begin(),
Ted Kremenek08da9782014-02-27 21:56:47 +0000502 E = item->succ_end(); I != E; ++I) {
503 const CFGBlock *B = *I;
Ted Kremenek6d9bb562014-03-05 00:01:17 +0000504 if (!B) do {
505 const CFGBlock *UB = I->getPossiblyUnreachableBlock();
506 if (!UB)
507 break;
508
Ted Kremenek782f0032014-03-07 02:25:53 +0000509 if (!TreatAllSuccessorsAsReachable.hasValue())
510 TreatAllSuccessorsAsReachable =
511 shouldTreatSuccessorsAsReachable(item);
512
513 if (TreatAllSuccessorsAsReachable.getValue()) {
Ted Kremenek6d9bb562014-03-05 00:01:17 +0000514 B = UB;
515 break;
516 }
Ted Kremenek08da9782014-02-27 21:56:47 +0000517 }
Ted Kremenek6d9bb562014-03-05 00:01:17 +0000518 while (false);
519
Ted Kremenek08da9782014-02-27 21:56:47 +0000520 if (B) {
Ted Kremenek7296de92010-02-23 02:39:16 +0000521 unsigned blockID = B->getBlockID();
522 if (!Reachable[blockID]) {
523 Reachable.set(blockID);
Ted Kremenek7296de92010-02-23 02:39:16 +0000524 WL.push_back(B);
Ted Kremenekbd913712011-08-23 23:05:11 +0000525 ++count;
Ted Kremenek7296de92010-02-23 02:39:16 +0000526 }
527 }
Ted Kremenek08da9782014-02-27 21:56:47 +0000528 }
Ted Kremenek7296de92010-02-23 02:39:16 +0000529 }
530 return count;
531}
Ted Kremenekbd913712011-08-23 23:05:11 +0000532
Ted Kremenek81ce1c82011-10-24 01:32:45 +0000533void FindUnreachableCode(AnalysisDeclContext &AC, Callback &CB) {
Ted Kremenek552eeaa2010-02-23 05:59:20 +0000534 CFG *cfg = AC.getCFG();
535 if (!cfg)
536 return;
537
Ted Kremenekbd913712011-08-23 23:05:11 +0000538 // Scan for reachable blocks from the entrance of the CFG.
539 // If there are no unreachable blocks, we're done.
Ted Kremenek552eeaa2010-02-23 05:59:20 +0000540 llvm::BitVector reachable(cfg->getNumBlockIDs());
Ted Kremenekbd913712011-08-23 23:05:11 +0000541 unsigned numReachable = ScanReachableFromBlock(&cfg->getEntry(), reachable);
Ted Kremenek552eeaa2010-02-23 05:59:20 +0000542 if (numReachable == cfg->getNumBlockIDs())
543 return;
Ted Kremenekbd913712011-08-23 23:05:11 +0000544
545 // If there aren't explicit EH edges, we should include the 'try' dispatch
546 // blocks as roots.
547 if (!AC.getCFGBuildOptions().AddEHEdges) {
548 for (CFG::try_block_iterator I = cfg->try_blocks_begin(),
549 E = cfg->try_blocks_end() ; I != E; ++I) {
550 numReachable += ScanReachableFromBlock(*I, reachable);
551 }
552 if (numReachable == cfg->getNumBlockIDs())
553 return;
554 }
Ted Kremenek552eeaa2010-02-23 05:59:20 +0000555
Ted Kremenekbd913712011-08-23 23:05:11 +0000556 // There are some unreachable blocks. We need to find the root blocks that
557 // contain code that should be considered unreachable.
Ted Kremenek552eeaa2010-02-23 05:59:20 +0000558 for (CFG::iterator I = cfg->begin(), E = cfg->end(); I != E; ++I) {
Ted Kremenekbd913712011-08-23 23:05:11 +0000559 const CFGBlock *block = *I;
560 // A block may have been marked reachable during this loop.
561 if (reachable[block->getBlockID()])
562 continue;
563
564 DeadCodeScan DS(reachable);
565 numReachable += DS.scanBackwards(block, CB);
566
567 if (numReachable == cfg->getNumBlockIDs())
568 return;
Ted Kremenek552eeaa2010-02-23 05:59:20 +0000569 }
Ted Kremenek552eeaa2010-02-23 05:59:20 +0000570}
571
572}} // end namespace clang::reachable_code