AnalysisBasedWarnings.cpp revision 6a42ee9c92db87ccad2b90ed11a5aa4d13481f4b
1//=- AnalysisBasedWarnings.cpp - Sema warnings based on libAnalysis -*- 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 defines analysis_warnings::[Policy,Executor].
11// Together they are used by Sema to issue warnings based on inexpensive
12// static analysis algorithms in libAnalysis.
13//
14//===----------------------------------------------------------------------===//
15
16#include "clang/Sema/Sema.h"
17#include "clang/Sema/AnalysisBasedWarnings.h"
18#include "clang/Basic/SourceManager.h"
19#include "clang/AST/DeclObjC.h"
20#include "clang/AST/ExprObjC.h"
21#include "clang/AST/ExprCXX.h"
22#include "clang/AST/StmtObjC.h"
23#include "clang/AST/StmtCXX.h"
24#include "clang/Analysis/AnalysisContext.h"
25#include "clang/Analysis/CFG.h"
26#include "clang/Analysis/Analyses/ReachableCode.h"
27#include "llvm/ADT/BitVector.h"
28#include "llvm/Support/Casting.h"
29
30using namespace clang;
31
32//===----------------------------------------------------------------------===//
33// Unreachable code analysis.
34//===----------------------------------------------------------------------===//
35
36namespace {
37  class UnreachableCodeHandler : public reachable_code::Callback {
38    Sema &S;
39  public:
40    UnreachableCodeHandler(Sema &s) : S(s) {}
41
42    void HandleUnreachable(SourceLocation L, SourceRange R1, SourceRange R2) {
43      S.Diag(L, diag::warn_unreachable) << R1 << R2;
44    }
45  };
46}
47
48/// CheckUnreachable - Check for unreachable code.
49static void CheckUnreachable(Sema &S, AnalysisContext &AC) {
50  UnreachableCodeHandler UC(S);
51  reachable_code::FindUnreachableCode(AC, UC);
52}
53
54//===----------------------------------------------------------------------===//
55// Check for missing return value.
56//===----------------------------------------------------------------------===//
57
58enum ControlFlowKind {
59  UnknownFallThrough,
60  NeverFallThrough,
61  MaybeFallThrough,
62  AlwaysFallThrough,
63  NeverFallThroughOrReturn
64};
65
66/// CheckFallThrough - Check that we don't fall off the end of a
67/// Statement that should return a value.
68///
69/// \returns AlwaysFallThrough iff we always fall off the end of the statement,
70/// MaybeFallThrough iff we might or might not fall off the end,
71/// NeverFallThroughOrReturn iff we never fall off the end of the statement or
72/// return.  We assume NeverFallThrough iff we never fall off the end of the
73/// statement but we may return.  We assume that functions not marked noreturn
74/// will return.
75static ControlFlowKind CheckFallThrough(AnalysisContext &AC) {
76  CFG *cfg = AC.getCFG();
77  if (cfg == 0) return UnknownFallThrough;
78
79  // The CFG leaves in dead things, and we don't want the dead code paths to
80  // confuse us, so we mark all live things first.
81  llvm::BitVector live(cfg->getNumBlockIDs());
82  unsigned count = reachable_code::ScanReachableFromBlock(cfg->getEntry(),
83                                                          live);
84
85  bool AddEHEdges = AC.getAddEHEdges();
86  if (!AddEHEdges && count != cfg->getNumBlockIDs())
87    // When there are things remaining dead, and we didn't add EH edges
88    // from CallExprs to the catch clauses, we have to go back and
89    // mark them as live.
90    for (CFG::iterator I = cfg->begin(), E = cfg->end(); I != E; ++I) {
91      CFGBlock &b = **I;
92      if (!live[b.getBlockID()]) {
93        if (b.pred_begin() == b.pred_end()) {
94          if (b.getTerminator() && isa<CXXTryStmt>(b.getTerminator()))
95            // When not adding EH edges from calls, catch clauses
96            // can otherwise seem dead.  Avoid noting them as dead.
97            count += reachable_code::ScanReachableFromBlock(b, live);
98          continue;
99        }
100      }
101    }
102
103  // Now we know what is live, we check the live precessors of the exit block
104  // and look for fall through paths, being careful to ignore normal returns,
105  // and exceptional paths.
106  bool HasLiveReturn = false;
107  bool HasFakeEdge = false;
108  bool HasPlainEdge = false;
109  bool HasAbnormalEdge = false;
110  for (CFGBlock::pred_iterator I=cfg->getExit().pred_begin(),
111       E = cfg->getExit().pred_end();
112       I != E;
113       ++I) {
114    CFGBlock& B = **I;
115    if (!live[B.getBlockID()])
116      continue;
117    if (B.size() == 0) {
118      if (B.getTerminator() && isa<CXXTryStmt>(B.getTerminator())) {
119        HasAbnormalEdge = true;
120        continue;
121      }
122
123      // A labeled empty statement, or the entry block...
124      HasPlainEdge = true;
125      continue;
126    }
127    Stmt *S = B[B.size()-1];
128    if (isa<ReturnStmt>(S)) {
129      HasLiveReturn = true;
130      continue;
131    }
132    if (isa<ObjCAtThrowStmt>(S)) {
133      HasFakeEdge = true;
134      continue;
135    }
136    if (isa<CXXThrowExpr>(S)) {
137      HasFakeEdge = true;
138      continue;
139    }
140    if (const AsmStmt *AS = dyn_cast<AsmStmt>(S)) {
141      if (AS->isMSAsm()) {
142        HasFakeEdge = true;
143        HasLiveReturn = true;
144        continue;
145      }
146    }
147    if (isa<CXXTryStmt>(S)) {
148      HasAbnormalEdge = true;
149      continue;
150    }
151
152    bool NoReturnEdge = false;
153    if (CallExpr *C = dyn_cast<CallExpr>(S)) {
154      if (std::find(B.succ_begin(), B.succ_end(), &cfg->getExit())
155            == B.succ_end()) {
156        HasAbnormalEdge = true;
157        continue;
158      }
159      Expr *CEE = C->getCallee()->IgnoreParenCasts();
160      if (getFunctionExtInfo(CEE->getType()).getNoReturn()) {
161        NoReturnEdge = true;
162        HasFakeEdge = true;
163      } else if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(CEE)) {
164        ValueDecl *VD = DRE->getDecl();
165        if (VD->hasAttr<NoReturnAttr>()) {
166          NoReturnEdge = true;
167          HasFakeEdge = true;
168        }
169      }
170    }
171    // FIXME: Remove this hack once temporaries and their destructors are
172    // modeled correctly by the CFG.
173    if (CXXExprWithTemporaries *E = dyn_cast<CXXExprWithTemporaries>(S)) {
174      for (unsigned I = 0, N = E->getNumTemporaries(); I != N; ++I) {
175        const FunctionDecl *FD = E->getTemporary(I)->getDestructor();
176        if (FD->hasAttr<NoReturnAttr>() ||
177            FD->getType()->getAs<FunctionType>()->getNoReturnAttr()) {
178          NoReturnEdge = true;
179          HasFakeEdge = true;
180          break;
181        }
182      }
183    }
184    // FIXME: Add noreturn message sends.
185    if (NoReturnEdge == false)
186      HasPlainEdge = true;
187  }
188  if (!HasPlainEdge) {
189    if (HasLiveReturn)
190      return NeverFallThrough;
191    return NeverFallThroughOrReturn;
192  }
193  if (HasAbnormalEdge || HasFakeEdge || HasLiveReturn)
194    return MaybeFallThrough;
195  // This says AlwaysFallThrough for calls to functions that are not marked
196  // noreturn, that don't return.  If people would like this warning to be more
197  // accurate, such functions should be marked as noreturn.
198  return AlwaysFallThrough;
199}
200
201namespace {
202
203struct CheckFallThroughDiagnostics {
204  unsigned diag_MaybeFallThrough_HasNoReturn;
205  unsigned diag_MaybeFallThrough_ReturnsNonVoid;
206  unsigned diag_AlwaysFallThrough_HasNoReturn;
207  unsigned diag_AlwaysFallThrough_ReturnsNonVoid;
208  unsigned diag_NeverFallThroughOrReturn;
209  bool funMode;
210
211  static CheckFallThroughDiagnostics MakeForFunction(const Decl *Func) {
212    CheckFallThroughDiagnostics D;
213    D.diag_MaybeFallThrough_HasNoReturn =
214      diag::warn_falloff_noreturn_function;
215    D.diag_MaybeFallThrough_ReturnsNonVoid =
216      diag::warn_maybe_falloff_nonvoid_function;
217    D.diag_AlwaysFallThrough_HasNoReturn =
218      diag::warn_falloff_noreturn_function;
219    D.diag_AlwaysFallThrough_ReturnsNonVoid =
220      diag::warn_falloff_nonvoid_function;
221
222    // Don't suggest that virtual functions be marked "noreturn", since they
223    // might be overridden by non-noreturn functions.
224    bool isVirtualMethod = false;
225    if (const CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(Func))
226      isVirtualMethod = Method->isVirtual();
227
228    if (!isVirtualMethod)
229      D.diag_NeverFallThroughOrReturn =
230        diag::warn_suggest_noreturn_function;
231    else
232      D.diag_NeverFallThroughOrReturn = 0;
233
234    D.funMode = true;
235    return D;
236  }
237
238  static CheckFallThroughDiagnostics MakeForBlock() {
239    CheckFallThroughDiagnostics D;
240    D.diag_MaybeFallThrough_HasNoReturn =
241      diag::err_noreturn_block_has_return_expr;
242    D.diag_MaybeFallThrough_ReturnsNonVoid =
243      diag::err_maybe_falloff_nonvoid_block;
244    D.diag_AlwaysFallThrough_HasNoReturn =
245      diag::err_noreturn_block_has_return_expr;
246    D.diag_AlwaysFallThrough_ReturnsNonVoid =
247      diag::err_falloff_nonvoid_block;
248    D.diag_NeverFallThroughOrReturn =
249      diag::warn_suggest_noreturn_block;
250    D.funMode = false;
251    return D;
252  }
253
254  bool checkDiagnostics(Diagnostic &D, bool ReturnsVoid,
255                        bool HasNoReturn) const {
256    if (funMode) {
257      return (D.getDiagnosticLevel(diag::warn_maybe_falloff_nonvoid_function)
258              == Diagnostic::Ignored || ReturnsVoid)
259        && (D.getDiagnosticLevel(diag::warn_noreturn_function_has_return_expr)
260              == Diagnostic::Ignored || !HasNoReturn)
261        && (D.getDiagnosticLevel(diag::warn_suggest_noreturn_block)
262              == Diagnostic::Ignored || !ReturnsVoid);
263    }
264
265    // For blocks.
266    return  ReturnsVoid && !HasNoReturn
267            && (D.getDiagnosticLevel(diag::warn_suggest_noreturn_block)
268                == Diagnostic::Ignored || !ReturnsVoid);
269  }
270};
271
272}
273
274/// CheckFallThroughForFunctionDef - Check that we don't fall off the end of a
275/// function that should return a value.  Check that we don't fall off the end
276/// of a noreturn function.  We assume that functions and blocks not marked
277/// noreturn will return.
278static void CheckFallThroughForBody(Sema &S, const Decl *D, const Stmt *Body,
279                                    QualType BlockTy,
280                                    const CheckFallThroughDiagnostics& CD,
281                                    AnalysisContext &AC) {
282
283  bool ReturnsVoid = false;
284  bool HasNoReturn = false;
285
286  if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
287    ReturnsVoid = FD->getResultType()->isVoidType();
288    HasNoReturn = FD->hasAttr<NoReturnAttr>() ||
289       FD->getType()->getAs<FunctionType>()->getNoReturnAttr();
290  }
291  else if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D)) {
292    ReturnsVoid = MD->getResultType()->isVoidType();
293    HasNoReturn = MD->hasAttr<NoReturnAttr>();
294  }
295  else if (isa<BlockDecl>(D)) {
296    if (const FunctionType *FT =
297          BlockTy->getPointeeType()->getAs<FunctionType>()) {
298      if (FT->getResultType()->isVoidType())
299        ReturnsVoid = true;
300      if (FT->getNoReturnAttr())
301        HasNoReturn = true;
302    }
303  }
304
305  Diagnostic &Diags = S.getDiagnostics();
306
307  // Short circuit for compilation speed.
308  if (CD.checkDiagnostics(Diags, ReturnsVoid, HasNoReturn))
309      return;
310
311  // FIXME: Function try block
312  if (const CompoundStmt *Compound = dyn_cast<CompoundStmt>(Body)) {
313    switch (CheckFallThrough(AC)) {
314      case UnknownFallThrough:
315        break;
316
317      case MaybeFallThrough:
318        if (HasNoReturn)
319          S.Diag(Compound->getRBracLoc(),
320                 CD.diag_MaybeFallThrough_HasNoReturn);
321        else if (!ReturnsVoid)
322          S.Diag(Compound->getRBracLoc(),
323                 CD.diag_MaybeFallThrough_ReturnsNonVoid);
324        break;
325      case AlwaysFallThrough:
326        if (HasNoReturn)
327          S.Diag(Compound->getRBracLoc(),
328                 CD.diag_AlwaysFallThrough_HasNoReturn);
329        else if (!ReturnsVoid)
330          S.Diag(Compound->getRBracLoc(),
331                 CD.diag_AlwaysFallThrough_ReturnsNonVoid);
332        break;
333      case NeverFallThroughOrReturn:
334        if (ReturnsVoid && !HasNoReturn && CD.diag_NeverFallThroughOrReturn)
335          S.Diag(Compound->getLBracLoc(),
336                 CD.diag_NeverFallThroughOrReturn);
337        break;
338      case NeverFallThrough:
339        break;
340    }
341  }
342}
343
344//===----------------------------------------------------------------------===//
345// AnalysisBasedWarnings - Worker object used by Sema to execute analysis-based
346//  warnings on a function, method, or block.
347//===----------------------------------------------------------------------===//
348
349clang::sema::AnalysisBasedWarnings::Policy::Policy() {
350  enableCheckFallThrough = 1;
351  enableCheckUnreachable = 0;
352}
353
354clang::sema::AnalysisBasedWarnings::AnalysisBasedWarnings(Sema &s) : S(s) {
355  Diagnostic &D = S.getDiagnostics();
356  DefaultPolicy.enableCheckUnreachable = (unsigned)
357    (D.getDiagnosticLevel(diag::warn_unreachable) != Diagnostic::Ignored);
358}
359
360void clang::sema::
361AnalysisBasedWarnings::IssueWarnings(sema::AnalysisBasedWarnings::Policy P,
362                                     const Decl *D, QualType BlockTy) {
363
364  assert(BlockTy.isNull() || isa<BlockDecl>(D));
365
366  // We avoid doing analysis-based warnings when there are errors for
367  // two reasons:
368  // (1) The CFGs often can't be constructed (if the body is invalid), so
369  //     don't bother trying.
370  // (2) The code already has problems; running the analysis just takes more
371  //     time.
372  Diagnostic &Diags = S.getDiagnostics();
373
374  if (Diags.hasErrorOccurred() || Diags.hasFatalErrorOccurred())
375    return;
376
377  // Do not do any analysis for declarations in system headers if we are
378  // going to just ignore them.
379  if (Diags.getSuppressSystemWarnings() &&
380      S.SourceMgr.isInSystemHeader(D->getLocation()))
381    return;
382
383  // For code in dependent contexts, we'll do this at instantiation time.
384  if (cast<DeclContext>(D)->isDependentContext())
385    return;
386
387  const Stmt *Body = D->getBody();
388  assert(Body);
389
390  // Don't generate EH edges for CallExprs as we'd like to avoid the n^2
391  // explosion for destrutors that can result and the compile time hit.
392  AnalysisContext AC(D, 0, false);
393
394  // Warning: check missing 'return'
395  if (P.enableCheckFallThrough) {
396    const CheckFallThroughDiagnostics &CD =
397      (isa<BlockDecl>(D) ? CheckFallThroughDiagnostics::MakeForBlock()
398                         : CheckFallThroughDiagnostics::MakeForFunction(D));
399    CheckFallThroughForBody(S, D, Body, BlockTy, CD, AC);
400  }
401
402  // Warning: check for unreachable code
403  if (P.enableCheckUnreachable)
404    CheckUnreachable(S, AC);
405}
406
407void clang::sema::
408AnalysisBasedWarnings::IssueWarnings(sema::AnalysisBasedWarnings::Policy P,
409                                     const BlockExpr *E) {
410  return IssueWarnings(P, E->getBlockDecl(), E->getType());
411}
412
413void clang::sema::
414AnalysisBasedWarnings::IssueWarnings(sema::AnalysisBasedWarnings::Policy P,
415                                     const ObjCMethodDecl *D) {
416  return IssueWarnings(P, D, QualType());
417}
418
419void clang::sema::
420AnalysisBasedWarnings::IssueWarnings(sema::AnalysisBasedWarnings::Policy P,
421                                     const FunctionDecl *D) {
422  return IssueWarnings(P, D, QualType());
423}
424