blob: 797e02ed6f502cbedadcf23d8f459378d1490184 [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) {
266 const CFGBlock *Pred = AB.getPossiblyUnreachableBlock();
267 assert(!AB.isReachable() && Pred);
268 return bodyEndsWithNoReturn(Pred);
269}
270
Ted Kremenekcc893382014-02-27 00:24:08 +0000271static bool isBreakPrecededByNoReturn(const CFGBlock *B,
272 const Stmt *S) {
273 if (!isa<BreakStmt>(S) || B->pred_empty())
274 return false;
275
276 assert(B->empty());
277 assert(B->pred_size() == 1);
Ted Kremenek5441c182014-02-27 06:32:32 +0000278 return bodyEndsWithNoReturn(*B->pred_begin());
279}
280
281static bool isEnumConstant(const Expr *Ex) {
282 const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(Ex);
283 if (!DR)
284 return false;
285 return isa<EnumConstantDecl>(DR->getDecl());
286}
287
288static bool isTrivialExpression(const Expr *Ex) {
289 return isa<IntegerLiteral>(Ex) || isa<StringLiteral>(Ex) ||
290 isEnumConstant(Ex);
291}
292
293static bool isTrivialReturnPrecededByNoReturn(const CFGBlock *B,
294 const Stmt *S) {
295 if (B->pred_empty())
296 return false;
297
298 const Expr *Ex = dyn_cast<Expr>(S);
299 if (!Ex)
300 return false;
301
302 Ex = Ex->IgnoreParenCasts();
303
304 if (!isTrivialExpression(Ex))
305 return false;
306
307 // Look to see if the block ends with a 'return', and see if 'S'
308 // is a substatement. The 'return' may not be the last element in
309 // the block because of destructors.
310 assert(!B->empty());
311 for (CFGBlock::const_reverse_iterator I = B->rbegin(), E = B->rend();
312 I != E; ++I) {
313 if (Optional<CFGStmt> CS = I->getAs<CFGStmt>()) {
314 if (const ReturnStmt *RS = dyn_cast<ReturnStmt>(CS->getStmt())) {
315 const Expr *RE = RS->getRetValue();
316 if (RE && RE->IgnoreParenCasts() == Ex)
317 break;
318 }
319 return false;
320 }
321 }
322
323 assert(B->pred_size() == 1);
324 return bodyEndsWithNoReturn(*B->pred_begin());
Ted Kremenekcc893382014-02-27 00:24:08 +0000325}
326
327void DeadCodeScan::reportDeadCode(const CFGBlock *B,
328 const Stmt *S,
Ted Kremenekbd913712011-08-23 23:05:11 +0000329 clang::reachable_code::Callback &CB) {
Ted Kremenekcc893382014-02-27 00:24:08 +0000330 // Suppress idiomatic cases of calling a noreturn function just
331 // before executing a 'break'. If there is other code after the 'break'
332 // in the block then don't suppress the warning.
333 if (isBreakPrecededByNoReturn(B, S))
334 return;
335
Ted Kremenek5441c182014-02-27 06:32:32 +0000336 // Suppress trivial 'return' statements that are dead.
337 if (isTrivialReturnPrecededByNoReturn(B, S))
338 return;
339
Ted Kremenek35883152014-02-27 05:42:07 +0000340 // Was this an unreachable 'default' case? Such cases are covered
341 // by -Wcovered-switch-default, if the user so desires.
342 const Stmt *Label = B->getLabel();
343 if (Label && isa<DefaultStmt>(Label))
344 return;
345
Ted Kremenek552eeaa2010-02-23 05:59:20 +0000346 SourceRange R1, R2;
Ted Kremenekbd913712011-08-23 23:05:11 +0000347 SourceLocation Loc = GetUnreachableLoc(S, R1, R2);
348 CB.HandleUnreachable(Loc, R1, R2);
Ted Kremenek552eeaa2010-02-23 05:59:20 +0000349}
350
Ted Kremenek552eeaa2010-02-23 05:59:20 +0000351namespace clang { namespace reachable_code {
David Blaikie68e081d2011-12-20 02:48:34 +0000352
353void Callback::anchor() { }
354
Ted Kremenekbd913712011-08-23 23:05:11 +0000355unsigned ScanReachableFromBlock(const CFGBlock *Start,
Ted Kremenek552eeaa2010-02-23 05:59:20 +0000356 llvm::BitVector &Reachable) {
357 unsigned count = 0;
Ted Kremenekbd913712011-08-23 23:05:11 +0000358
Nico Webercc2b8712011-04-02 19:45:15 +0000359 // Prep work queue
Ted Kremenekbd913712011-08-23 23:05:11 +0000360 SmallVector<const CFGBlock*, 32> WL;
361
362 // The entry block may have already been marked reachable
363 // by the caller.
364 if (!Reachable[Start->getBlockID()]) {
365 ++count;
366 Reachable[Start->getBlockID()] = true;
367 }
368
369 WL.push_back(Start);
370
Ted Kremenekf2b0a1b2010-09-09 00:06:10 +0000371 // Find the reachable blocks from 'Start'.
Ted Kremenek552eeaa2010-02-23 05:59:20 +0000372 while (!WL.empty()) {
Ted Kremenekbd913712011-08-23 23:05:11 +0000373 const CFGBlock *item = WL.pop_back_val();
374
375 // Look at the successors and mark then reachable.
376 for (CFGBlock::const_succ_iterator I = item->succ_begin(),
377 E = item->succ_end(); I != E; ++I)
Ted Kremenek7296de92010-02-23 02:39:16 +0000378 if (const CFGBlock *B = *I) {
379 unsigned blockID = B->getBlockID();
380 if (!Reachable[blockID]) {
381 Reachable.set(blockID);
Ted Kremenek7296de92010-02-23 02:39:16 +0000382 WL.push_back(B);
Ted Kremenekbd913712011-08-23 23:05:11 +0000383 ++count;
Ted Kremenek7296de92010-02-23 02:39:16 +0000384 }
385 }
386 }
387 return count;
388}
Ted Kremenekbd913712011-08-23 23:05:11 +0000389
Ted Kremenek81ce1c82011-10-24 01:32:45 +0000390void FindUnreachableCode(AnalysisDeclContext &AC, Callback &CB) {
Ted Kremenek552eeaa2010-02-23 05:59:20 +0000391 CFG *cfg = AC.getCFG();
392 if (!cfg)
393 return;
394
Ted Kremenekbd913712011-08-23 23:05:11 +0000395 // Scan for reachable blocks from the entrance of the CFG.
396 // If there are no unreachable blocks, we're done.
Ted Kremenek552eeaa2010-02-23 05:59:20 +0000397 llvm::BitVector reachable(cfg->getNumBlockIDs());
Ted Kremenekbd913712011-08-23 23:05:11 +0000398 unsigned numReachable = ScanReachableFromBlock(&cfg->getEntry(), reachable);
Ted Kremenek552eeaa2010-02-23 05:59:20 +0000399 if (numReachable == cfg->getNumBlockIDs())
400 return;
Ted Kremenekbd913712011-08-23 23:05:11 +0000401
402 // If there aren't explicit EH edges, we should include the 'try' dispatch
403 // blocks as roots.
404 if (!AC.getCFGBuildOptions().AddEHEdges) {
405 for (CFG::try_block_iterator I = cfg->try_blocks_begin(),
406 E = cfg->try_blocks_end() ; I != E; ++I) {
407 numReachable += ScanReachableFromBlock(*I, reachable);
408 }
409 if (numReachable == cfg->getNumBlockIDs())
410 return;
411 }
Ted Kremenek552eeaa2010-02-23 05:59:20 +0000412
Ted Kremenekbd913712011-08-23 23:05:11 +0000413 // There are some unreachable blocks. We need to find the root blocks that
414 // contain code that should be considered unreachable.
Ted Kremenek552eeaa2010-02-23 05:59:20 +0000415 for (CFG::iterator I = cfg->begin(), E = cfg->end(); I != E; ++I) {
Ted Kremenekbd913712011-08-23 23:05:11 +0000416 const CFGBlock *block = *I;
417 // A block may have been marked reachable during this loop.
418 if (reachable[block->getBlockID()])
419 continue;
420
421 DeadCodeScan DS(reachable);
422 numReachable += DS.scanBackwards(block, CB);
423
424 if (numReachable == cfg->getNumBlockIDs())
425 return;
Ted Kremenek552eeaa2010-02-23 05:59:20 +0000426 }
Ted Kremenek552eeaa2010-02-23 05:59:20 +0000427}
428
429}} // end namespace clang::reachable_code