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