blob: 1210fcdd3ae936c2cc837244600005eb9add989b [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 Kremenek7d47cac2014-03-07 07:14:36 +000028//===----------------------------------------------------------------------===//
29// Core Reachability Analysis routines.
30//===----------------------------------------------------------------------===//
Ted Kremenek552eeaa2010-02-23 05:59:20 +000031
Ted Kremenekcc893382014-02-27 00:24:08 +000032static bool bodyEndsWithNoReturn(const CFGBlock *B) {
33 for (CFGBlock::const_reverse_iterator I = B->rbegin(), E = B->rend();
34 I != E; ++I) {
35 if (Optional<CFGStmt> CS = I->getAs<CFGStmt>()) {
Ted Kremenekec2dc732014-03-06 06:50:46 +000036 const Stmt *S = CS->getStmt();
37 if (const ExprWithCleanups *EWC = dyn_cast<ExprWithCleanups>(S))
38 S = EWC->getSubExpr();
39 if (const CallExpr *CE = dyn_cast<CallExpr>(S)) {
Ted Kremenekcc893382014-02-27 00:24:08 +000040 QualType CalleeType = CE->getCallee()->getType();
41 if (getFunctionExtInfo(*CalleeType).getNoReturn())
42 return true;
43 }
44 break;
45 }
46 }
47 return false;
48}
49
Ted Kremenek5441c182014-02-27 06:32:32 +000050static bool bodyEndsWithNoReturn(const CFGBlock::AdjacentBlock &AB) {
Ted Kremenekeb862842014-03-04 21:41:38 +000051 // If the predecessor is a normal CFG edge, then by definition
52 // the predecessor did not end with a 'noreturn'.
53 if (AB.getReachableBlock())
54 return false;
55
Ted Kremenek5441c182014-02-27 06:32:32 +000056 const CFGBlock *Pred = AB.getPossiblyUnreachableBlock();
57 assert(!AB.isReachable() && Pred);
58 return bodyEndsWithNoReturn(Pred);
59}
60
Ted Kremenekcc893382014-02-27 00:24:08 +000061static bool isBreakPrecededByNoReturn(const CFGBlock *B,
62 const Stmt *S) {
63 if (!isa<BreakStmt>(S) || B->pred_empty())
64 return false;
65
66 assert(B->empty());
67 assert(B->pred_size() == 1);
Ted Kremenek5441c182014-02-27 06:32:32 +000068 return bodyEndsWithNoReturn(*B->pred_begin());
69}
70
71static bool isEnumConstant(const Expr *Ex) {
72 const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(Ex);
73 if (!DR)
74 return false;
75 return isa<EnumConstantDecl>(DR->getDecl());
76}
77
Ted Kremenekec2dc732014-03-06 06:50:46 +000078static const Expr *stripStdStringCtor(const Expr *Ex) {
79 // Go crazy pattern matching an implicit construction of std::string("").
80 const ExprWithCleanups *EWC = dyn_cast<ExprWithCleanups>(Ex);
81 if (!EWC)
82 return 0;
83 const CXXConstructExpr *CCE = dyn_cast<CXXConstructExpr>(EWC->getSubExpr());
84 if (!CCE)
85 return 0;
86 QualType Ty = CCE->getType();
87 if (const ElaboratedType *ET = dyn_cast<ElaboratedType>(Ty))
88 Ty = ET->getNamedType();
89 const TypedefType *TT = dyn_cast<TypedefType>(Ty);
90 StringRef Name = TT->getDecl()->getName();
91 if (Name != "string")
92 return 0;
93 if (CCE->getNumArgs() != 1)
94 return 0;
95 const MaterializeTemporaryExpr *MTE =
96 dyn_cast<MaterializeTemporaryExpr>(CCE->getArg(0));
97 if (!MTE)
98 return 0;
99 CXXBindTemporaryExpr *CBT =
100 dyn_cast<CXXBindTemporaryExpr>(MTE->GetTemporaryExpr()->IgnoreParenCasts());
101 if (!CBT)
102 return 0;
103 Ex = CBT->getSubExpr()->IgnoreParenCasts();
104 CCE = dyn_cast<CXXConstructExpr>(Ex);
105 if (!CCE)
106 return 0;
107 if (CCE->getNumArgs() != 1)
108 return 0;
109 return dyn_cast<StringLiteral>(CCE->getArg(0)->IgnoreParenCasts());
110}
111
112/// Strip away "sugar" around trivial expressions that are for the
113/// purpose of this analysis considered uninteresting for dead code warnings.
114static const Expr *stripExprSugar(const Expr *Ex) {
115 Ex = Ex->IgnoreParenCasts();
116 // If 'Ex' is a constructor for a std::string, strip that
117 // away. We can only get here if the trivial expression was
118 // something like a C string literal, with the std::string
119 // just wrapping that value.
120 if (const Expr *StdStringVal = stripStdStringCtor(Ex))
121 return StdStringVal;
122 return Ex;
123}
124
Ted Kremenek5441c182014-02-27 06:32:32 +0000125static bool isTrivialExpression(const Expr *Ex) {
Ted Kremenek0a69cab2014-03-05 23:46:07 +0000126 Ex = Ex->IgnoreParenCasts();
Ted Kremenek5441c182014-02-27 06:32:32 +0000127 return isa<IntegerLiteral>(Ex) || isa<StringLiteral>(Ex) ||
Ted Kremenekc10830b2014-03-07 02:25:50 +0000128 isa<CXXBoolLiteralExpr>(Ex) || isa<ObjCBoolLiteralExpr>(Ex) ||
129 isa<CharacterLiteral>(Ex) ||
Ted Kremenek5441c182014-02-27 06:32:32 +0000130 isEnumConstant(Ex);
131}
132
Ted Kremenek1de2e142014-03-06 00:17:44 +0000133static bool isTrivialReturnOrDoWhile(const CFGBlock *B, const Stmt *S) {
Ted Kremenek5441c182014-02-27 06:32:32 +0000134 const Expr *Ex = dyn_cast<Expr>(S);
Ted Kremenek5441c182014-02-27 06:32:32 +0000135
Ted Kremenek04bfbee2014-03-08 02:22:23 +0000136 if (Ex && !isTrivialExpression(Ex))
Ted Kremenek5441c182014-02-27 06:32:32 +0000137 return false;
138
Ted Kremenek1de2e142014-03-06 00:17:44 +0000139 // Check if the block ends with a do...while() and see if 'S' is the
140 // condition.
141 if (const Stmt *Term = B->getTerminator()) {
142 if (const DoStmt *DS = dyn_cast<DoStmt>(Term))
143 if (DS->getCond() == S)
144 return true;
145 }
146
Ted Kremenek7549f0f2014-03-06 01:09:45 +0000147 if (B->pred_size() != 1)
148 return false;
Ted Kremenek1de2e142014-03-06 00:17:44 +0000149
Ted Kremenek5441c182014-02-27 06:32:32 +0000150 // Look to see if the block ends with a 'return', and see if 'S'
151 // is a substatement. The 'return' may not be the last element in
152 // the block because of destructors.
Ted Kremenek5441c182014-02-27 06:32:32 +0000153 for (CFGBlock::const_reverse_iterator I = B->rbegin(), E = B->rend();
154 I != E; ++I) {
155 if (Optional<CFGStmt> CS = I->getAs<CFGStmt>()) {
156 if (const ReturnStmt *RS = dyn_cast<ReturnStmt>(CS->getStmt())) {
Ted Kremenek04bfbee2014-03-08 02:22:23 +0000157 bool LookAtBody = false;
158 if (RS == S)
159 LookAtBody = true;
160 else {
161 const Expr *RE = RS->getRetValue();
162 if (RE && stripExprSugar(RE->IgnoreParenCasts()) == Ex)
163 LookAtBody = true;
164 }
165
166 if (LookAtBody)
Ted Kremenek7549f0f2014-03-06 01:09:45 +0000167 return bodyEndsWithNoReturn(*B->pred_begin());
Ted Kremenek5441c182014-02-27 06:32:32 +0000168 }
Ted Kremenek7549f0f2014-03-06 01:09:45 +0000169 break;
Ted Kremenek5441c182014-02-27 06:32:32 +0000170 }
171 }
Ted Kremenek0a69cab2014-03-05 23:46:07 +0000172 return false;
Ted Kremenekcc893382014-02-27 00:24:08 +0000173}
174
Ted Kremenek6d9bb562014-03-05 00:01:17 +0000175/// Returns true if the statement is expanded from a configuration macro.
176static bool isExpandedFromConfigurationMacro(const Stmt *S) {
177 // FIXME: This is not very precise. Here we just check to see if the
178 // value comes from a macro, but we can do much better. This is likely
179 // to be over conservative. This logic is factored into a separate function
180 // so that we can refine it later.
181 SourceLocation L = S->getLocStart();
182 return L.isMacroID();
183}
184
185/// Returns true if the statement represents a configuration value.
186///
187/// A configuration value is something usually determined at compile-time
188/// to conditionally always execute some branch. Such guards are for
189/// "sometimes unreachable" code. Such code is usually not interesting
190/// to report as unreachable, and may mask truly unreachable code within
191/// those blocks.
Ted Kremenekc980afc2014-03-08 23:20:11 +0000192static bool isConfigurationValue(const Stmt *S,
193 bool IncludeIntegers = true) {
Ted Kremenek6d9bb562014-03-05 00:01:17 +0000194 if (!S)
195 return false;
196
197 if (const Expr *Ex = dyn_cast<Expr>(S))
198 S = Ex->IgnoreParenCasts();
199
200 switch (S->getStmtClass()) {
Ted Kremenek01a39b62014-03-05 23:38:41 +0000201 case Stmt::DeclRefExprClass: {
202 const DeclRefExpr *DR = cast<DeclRefExpr>(S);
Ted Kremenek94d16172014-03-07 20:51:13 +0000203 const ValueDecl *D = DR->getDecl();
204 if (const EnumConstantDecl *ED = dyn_cast<EnumConstantDecl>(D))
Ted Kremenekc980afc2014-03-08 23:20:11 +0000205 return isConfigurationValue(ED->getInitExpr());
Ted Kremenek94d16172014-03-07 20:51:13 +0000206 if (const VarDecl *VD = dyn_cast<VarDecl>(D)) {
207 // As a heuristic, treat globals as configuration values. Note
208 // that we only will get here if Sema evaluated this
209 // condition to a constant expression, which means the global
210 // had to be declared in a way to be a truly constant value.
211 // We could generalize this to local variables, but it isn't
212 // clear if those truly represent configuration values that
213 // gate unreachable code.
214 return !VD->hasLocalStorage();
215 }
216 return false;
Ted Kremenek01a39b62014-03-05 23:38:41 +0000217 }
Ted Kremenek6d9bb562014-03-05 00:01:17 +0000218 case Stmt::IntegerLiteralClass:
Ted Kremenekc980afc2014-03-08 23:20:11 +0000219 return IncludeIntegers ? isExpandedFromConfigurationMacro(S)
220 : false;
Ted Kremenek6d9bb562014-03-05 00:01:17 +0000221 case Stmt::UnaryExprOrTypeTraitExprClass:
222 return true;
223 case Stmt::BinaryOperatorClass: {
224 const BinaryOperator *B = cast<BinaryOperator>(S);
Ted Kremenekc980afc2014-03-08 23:20:11 +0000225 // Only include raw integers (not enums) as configuration
226 // values if they are used in a logical or comparison operator
227 // (not arithmetic).
228 IncludeIntegers &= (B->isLogicalOp() || B->isComparisonOp());
229 return isConfigurationValue(B->getLHS(), IncludeIntegers) ||
230 isConfigurationValue(B->getRHS(), IncludeIntegers);
Ted Kremenek6d9bb562014-03-05 00:01:17 +0000231 }
232 case Stmt::UnaryOperatorClass: {
233 const UnaryOperator *UO = cast<UnaryOperator>(S);
234 return UO->getOpcode() == UO_LNot &&
235 isConfigurationValue(UO->getSubExpr());
236 }
237 default:
238 return false;
239 }
240}
241
242/// Returns true if we should always explore all successors of a block.
243static bool shouldTreatSuccessorsAsReachable(const CFGBlock *B) {
Ted Kremenek782f0032014-03-07 02:25:53 +0000244 if (const Stmt *Term = B->getTerminator()) {
Ted Kremenek6999d022014-03-06 08:09:00 +0000245 if (isa<SwitchStmt>(Term))
246 return true;
Ted Kremenek782f0032014-03-07 02:25:53 +0000247 // Specially handle '||' and '&&'.
248 if (isa<BinaryOperator>(Term))
249 return isConfigurationValue(Term);
250 }
Ted Kremenek6999d022014-03-06 08:09:00 +0000251
Ted Kremenek6d9bb562014-03-05 00:01:17 +0000252 return isConfigurationValue(B->getTerminatorCondition());
253}
254
Ted Kremenek7d47cac2014-03-07 07:14:36 +0000255static unsigned scanFromBlock(const CFGBlock *Start,
256 llvm::BitVector &Reachable,
257 bool IncludeSometimesUnreachableEdges) {
Ted Kremenek552eeaa2010-02-23 05:59:20 +0000258 unsigned count = 0;
Ted Kremenekbd913712011-08-23 23:05:11 +0000259
Nico Webercc2b8712011-04-02 19:45:15 +0000260 // Prep work queue
Ted Kremenekbd913712011-08-23 23:05:11 +0000261 SmallVector<const CFGBlock*, 32> WL;
262
263 // The entry block may have already been marked reachable
264 // by the caller.
265 if (!Reachable[Start->getBlockID()]) {
266 ++count;
267 Reachable[Start->getBlockID()] = true;
268 }
269
270 WL.push_back(Start);
271
Ted Kremenekf2b0a1b2010-09-09 00:06:10 +0000272 // Find the reachable blocks from 'Start'.
Ted Kremenek552eeaa2010-02-23 05:59:20 +0000273 while (!WL.empty()) {
Ted Kremenekbd913712011-08-23 23:05:11 +0000274 const CFGBlock *item = WL.pop_back_val();
Ted Kremenek6d9bb562014-03-05 00:01:17 +0000275
276 // There are cases where we want to treat all successors as reachable.
277 // The idea is that some "sometimes unreachable" code is not interesting,
278 // and that we should forge ahead and explore those branches anyway.
279 // This allows us to potentially uncover some "always unreachable" code
280 // within the "sometimes unreachable" code.
Ted Kremenekbd913712011-08-23 23:05:11 +0000281 // Look at the successors and mark then reachable.
Ted Kremenek782f0032014-03-07 02:25:53 +0000282 Optional<bool> TreatAllSuccessorsAsReachable;
Ted Kremenek7d47cac2014-03-07 07:14:36 +0000283 if (!IncludeSometimesUnreachableEdges)
284 TreatAllSuccessorsAsReachable = false;
Ted Kremenek782f0032014-03-07 02:25:53 +0000285
Ted Kremenekbd913712011-08-23 23:05:11 +0000286 for (CFGBlock::const_succ_iterator I = item->succ_begin(),
Ted Kremenek08da9782014-02-27 21:56:47 +0000287 E = item->succ_end(); I != E; ++I) {
288 const CFGBlock *B = *I;
Ted Kremenek6d9bb562014-03-05 00:01:17 +0000289 if (!B) do {
290 const CFGBlock *UB = I->getPossiblyUnreachableBlock();
291 if (!UB)
292 break;
293
Ted Kremenek782f0032014-03-07 02:25:53 +0000294 if (!TreatAllSuccessorsAsReachable.hasValue())
295 TreatAllSuccessorsAsReachable =
296 shouldTreatSuccessorsAsReachable(item);
297
298 if (TreatAllSuccessorsAsReachable.getValue()) {
Ted Kremenek6d9bb562014-03-05 00:01:17 +0000299 B = UB;
300 break;
301 }
Ted Kremenek08da9782014-02-27 21:56:47 +0000302 }
Ted Kremenek6d9bb562014-03-05 00:01:17 +0000303 while (false);
304
Ted Kremenek08da9782014-02-27 21:56:47 +0000305 if (B) {
Ted Kremenek7296de92010-02-23 02:39:16 +0000306 unsigned blockID = B->getBlockID();
307 if (!Reachable[blockID]) {
308 Reachable.set(blockID);
Ted Kremenek7296de92010-02-23 02:39:16 +0000309 WL.push_back(B);
Ted Kremenekbd913712011-08-23 23:05:11 +0000310 ++count;
Ted Kremenek7296de92010-02-23 02:39:16 +0000311 }
312 }
Ted Kremenek08da9782014-02-27 21:56:47 +0000313 }
Ted Kremenek7296de92010-02-23 02:39:16 +0000314 }
315 return count;
316}
Ted Kremenek7d47cac2014-03-07 07:14:36 +0000317
318static unsigned scanMaybeReachableFromBlock(const CFGBlock *Start,
319 llvm::BitVector &Reachable) {
320 return scanFromBlock(Start, Reachable, true);
321}
322
323//===----------------------------------------------------------------------===//
324// Dead Code Scanner.
325//===----------------------------------------------------------------------===//
326
327namespace {
328 class DeadCodeScan {
329 llvm::BitVector Visited;
330 llvm::BitVector &Reachable;
331 SmallVector<const CFGBlock *, 10> WorkList;
332
333 typedef SmallVector<std::pair<const CFGBlock *, const Stmt *>, 12>
334 DeferredLocsTy;
335
336 DeferredLocsTy DeferredLocs;
337
338 public:
339 DeadCodeScan(llvm::BitVector &reachable)
340 : Visited(reachable.size()),
341 Reachable(reachable) {}
342
343 void enqueue(const CFGBlock *block);
344 unsigned scanBackwards(const CFGBlock *Start,
345 clang::reachable_code::Callback &CB);
346
347 bool isDeadCodeRoot(const CFGBlock *Block);
348
349 const Stmt *findDeadCode(const CFGBlock *Block);
350
351 void reportDeadCode(const CFGBlock *B,
352 const Stmt *S,
353 clang::reachable_code::Callback &CB);
354 };
355}
356
357void DeadCodeScan::enqueue(const CFGBlock *block) {
358 unsigned blockID = block->getBlockID();
359 if (Reachable[blockID] || Visited[blockID])
360 return;
361 Visited[blockID] = true;
362 WorkList.push_back(block);
363}
364
365bool DeadCodeScan::isDeadCodeRoot(const clang::CFGBlock *Block) {
366 bool isDeadRoot = true;
367
368 for (CFGBlock::const_pred_iterator I = Block->pred_begin(),
369 E = Block->pred_end(); I != E; ++I) {
370 if (const CFGBlock *PredBlock = *I) {
371 unsigned blockID = PredBlock->getBlockID();
372 if (Visited[blockID]) {
373 isDeadRoot = false;
374 continue;
375 }
376 if (!Reachable[blockID]) {
377 isDeadRoot = false;
378 Visited[blockID] = true;
379 WorkList.push_back(PredBlock);
380 continue;
381 }
382 }
383 }
384
385 return isDeadRoot;
386}
387
388static bool isValidDeadStmt(const Stmt *S) {
389 if (S->getLocStart().isInvalid())
390 return false;
391 if (const BinaryOperator *BO = dyn_cast<BinaryOperator>(S))
392 return BO->getOpcode() != BO_Comma;
393 return true;
394}
395
396const Stmt *DeadCodeScan::findDeadCode(const clang::CFGBlock *Block) {
397 for (CFGBlock::const_iterator I = Block->begin(), E = Block->end(); I!=E; ++I)
398 if (Optional<CFGStmt> CS = I->getAs<CFGStmt>()) {
399 const Stmt *S = CS->getStmt();
400 if (isValidDeadStmt(S))
401 return S;
402 }
403
404 if (CFGTerminator T = Block->getTerminator()) {
Ted Kremenekefea6342014-03-08 02:22:32 +0000405 if (!T.isTemporaryDtorsBranch()) {
406 const Stmt *S = T.getStmt();
407 if (isValidDeadStmt(S))
408 return S;
409 }
Ted Kremenek7d47cac2014-03-07 07:14:36 +0000410 }
411
412 return 0;
413}
414
Benjamin Kramer4cadf292014-03-07 21:51:58 +0000415static int SrcCmp(const std::pair<const CFGBlock *, const Stmt *> *p1,
416 const std::pair<const CFGBlock *, const Stmt *> *p2) {
417 if (p1->second->getLocStart() < p2->second->getLocStart())
418 return -1;
419 if (p2->second->getLocStart() < p1->second->getLocStart())
420 return 1;
421 return 0;
422}
423
Ted Kremenek7d47cac2014-03-07 07:14:36 +0000424unsigned DeadCodeScan::scanBackwards(const clang::CFGBlock *Start,
425 clang::reachable_code::Callback &CB) {
426
427 unsigned count = 0;
428 enqueue(Start);
429
430 while (!WorkList.empty()) {
431 const CFGBlock *Block = WorkList.pop_back_val();
432
433 // It is possible that this block has been marked reachable after
434 // it was enqueued.
435 if (Reachable[Block->getBlockID()])
436 continue;
437
438 // Look for any dead code within the block.
439 const Stmt *S = findDeadCode(Block);
440
441 if (!S) {
442 // No dead code. Possibly an empty block. Look at dead predecessors.
443 for (CFGBlock::const_pred_iterator I = Block->pred_begin(),
444 E = Block->pred_end(); I != E; ++I) {
445 if (const CFGBlock *predBlock = *I)
446 enqueue(predBlock);
447 }
448 continue;
449 }
450
451 // Specially handle macro-expanded code.
452 if (S->getLocStart().isMacroID()) {
453 count += scanMaybeReachableFromBlock(Block, Reachable);
454 continue;
455 }
456
457 if (isDeadCodeRoot(Block)) {
458 reportDeadCode(Block, S, CB);
459 count += scanMaybeReachableFromBlock(Block, Reachable);
460 }
461 else {
462 // Record this statement as the possibly best location in a
463 // strongly-connected component of dead code for emitting a
464 // warning.
465 DeferredLocs.push_back(std::make_pair(Block, S));
466 }
467 }
468
469 // If we didn't find a dead root, then report the dead code with the
470 // earliest location.
471 if (!DeferredLocs.empty()) {
Benjamin Kramer4cadf292014-03-07 21:51:58 +0000472 llvm::array_pod_sort(DeferredLocs.begin(), DeferredLocs.end(), SrcCmp);
Ted Kremenek7d47cac2014-03-07 07:14:36 +0000473 for (DeferredLocsTy::iterator I = DeferredLocs.begin(),
474 E = DeferredLocs.end(); I != E; ++I) {
475 const CFGBlock *Block = I->first;
476 if (Reachable[Block->getBlockID()])
477 continue;
478 reportDeadCode(Block, I->second, CB);
479 count += scanMaybeReachableFromBlock(Block, Reachable);
480 }
481 }
482
483 return count;
484}
485
486static SourceLocation GetUnreachableLoc(const Stmt *S,
487 SourceRange &R1,
488 SourceRange &R2) {
489 R1 = R2 = SourceRange();
490
491 if (const Expr *Ex = dyn_cast<Expr>(S))
492 S = Ex->IgnoreParenImpCasts();
493
494 switch (S->getStmtClass()) {
495 case Expr::BinaryOperatorClass: {
496 const BinaryOperator *BO = cast<BinaryOperator>(S);
497 return BO->getOperatorLoc();
498 }
499 case Expr::UnaryOperatorClass: {
500 const UnaryOperator *UO = cast<UnaryOperator>(S);
501 R1 = UO->getSubExpr()->getSourceRange();
502 return UO->getOperatorLoc();
503 }
504 case Expr::CompoundAssignOperatorClass: {
505 const CompoundAssignOperator *CAO = cast<CompoundAssignOperator>(S);
506 R1 = CAO->getLHS()->getSourceRange();
507 R2 = CAO->getRHS()->getSourceRange();
508 return CAO->getOperatorLoc();
509 }
510 case Expr::BinaryConditionalOperatorClass:
511 case Expr::ConditionalOperatorClass: {
512 const AbstractConditionalOperator *CO =
513 cast<AbstractConditionalOperator>(S);
514 return CO->getQuestionLoc();
515 }
516 case Expr::MemberExprClass: {
517 const MemberExpr *ME = cast<MemberExpr>(S);
518 R1 = ME->getSourceRange();
519 return ME->getMemberLoc();
520 }
521 case Expr::ArraySubscriptExprClass: {
522 const ArraySubscriptExpr *ASE = cast<ArraySubscriptExpr>(S);
523 R1 = ASE->getLHS()->getSourceRange();
524 R2 = ASE->getRHS()->getSourceRange();
525 return ASE->getRBracketLoc();
526 }
527 case Expr::CStyleCastExprClass: {
528 const CStyleCastExpr *CSC = cast<CStyleCastExpr>(S);
529 R1 = CSC->getSubExpr()->getSourceRange();
530 return CSC->getLParenLoc();
531 }
532 case Expr::CXXFunctionalCastExprClass: {
533 const CXXFunctionalCastExpr *CE = cast <CXXFunctionalCastExpr>(S);
534 R1 = CE->getSubExpr()->getSourceRange();
535 return CE->getLocStart();
536 }
537 case Stmt::CXXTryStmtClass: {
538 return cast<CXXTryStmt>(S)->getHandler(0)->getCatchLoc();
539 }
540 case Expr::ObjCBridgedCastExprClass: {
541 const ObjCBridgedCastExpr *CSC = cast<ObjCBridgedCastExpr>(S);
542 R1 = CSC->getSubExpr()->getSourceRange();
543 return CSC->getLParenLoc();
544 }
545 default: ;
546 }
547 R1 = S->getSourceRange();
548 return S->getLocStart();
549}
550
551void DeadCodeScan::reportDeadCode(const CFGBlock *B,
552 const Stmt *S,
553 clang::reachable_code::Callback &CB) {
554 // Suppress idiomatic cases of calling a noreturn function just
555 // before executing a 'break'. If there is other code after the 'break'
556 // in the block then don't suppress the warning.
557 if (isBreakPrecededByNoReturn(B, S))
558 return;
559
560 // Suppress trivial 'return' statements that are dead.
561 if (isTrivialReturnOrDoWhile(B, S))
562 return;
563
564 SourceRange R1, R2;
565 SourceLocation Loc = GetUnreachableLoc(S, R1, R2);
566 CB.HandleUnreachable(Loc, R1, R2);
567}
568
569//===----------------------------------------------------------------------===//
570// Reachability APIs.
571//===----------------------------------------------------------------------===//
572
573namespace clang { namespace reachable_code {
574
575void Callback::anchor() { }
576
577unsigned ScanReachableFromBlock(const CFGBlock *Start,
578 llvm::BitVector &Reachable) {
579 return scanFromBlock(Start, Reachable, false);
580}
581
Ted Kremenek81ce1c82011-10-24 01:32:45 +0000582void FindUnreachableCode(AnalysisDeclContext &AC, Callback &CB) {
Ted Kremenek552eeaa2010-02-23 05:59:20 +0000583 CFG *cfg = AC.getCFG();
584 if (!cfg)
585 return;
586
Ted Kremenekbd913712011-08-23 23:05:11 +0000587 // Scan for reachable blocks from the entrance of the CFG.
588 // If there are no unreachable blocks, we're done.
Ted Kremenek552eeaa2010-02-23 05:59:20 +0000589 llvm::BitVector reachable(cfg->getNumBlockIDs());
Ted Kremenek7d47cac2014-03-07 07:14:36 +0000590 unsigned numReachable =
591 scanMaybeReachableFromBlock(&cfg->getEntry(), reachable);
Ted Kremenek552eeaa2010-02-23 05:59:20 +0000592 if (numReachable == cfg->getNumBlockIDs())
593 return;
Ted Kremenekbd913712011-08-23 23:05:11 +0000594
595 // If there aren't explicit EH edges, we should include the 'try' dispatch
596 // blocks as roots.
597 if (!AC.getCFGBuildOptions().AddEHEdges) {
598 for (CFG::try_block_iterator I = cfg->try_blocks_begin(),
599 E = cfg->try_blocks_end() ; I != E; ++I) {
Ted Kremenek7d47cac2014-03-07 07:14:36 +0000600 numReachable += scanMaybeReachableFromBlock(*I, reachable);
Ted Kremenekbd913712011-08-23 23:05:11 +0000601 }
602 if (numReachable == cfg->getNumBlockIDs())
603 return;
604 }
Ted Kremenek552eeaa2010-02-23 05:59:20 +0000605
Ted Kremenekbd913712011-08-23 23:05:11 +0000606 // There are some unreachable blocks. We need to find the root blocks that
607 // contain code that should be considered unreachable.
Ted Kremenek552eeaa2010-02-23 05:59:20 +0000608 for (CFG::iterator I = cfg->begin(), E = cfg->end(); I != E; ++I) {
Ted Kremenekbd913712011-08-23 23:05:11 +0000609 const CFGBlock *block = *I;
610 // A block may have been marked reachable during this loop.
611 if (reachable[block->getBlockID()])
612 continue;
613
614 DeadCodeScan DS(reachable);
615 numReachable += DS.scanBackwards(block, CB);
616
617 if (numReachable == cfg->getNumBlockIDs())
618 return;
Ted Kremenek552eeaa2010-02-23 05:59:20 +0000619 }
Ted Kremenek552eeaa2010-02-23 05:59:20 +0000620}
621
622}} // end namespace clang::reachable_code