AnalysisBasedWarnings.cpp revision d75fa6e1c034bf8a335fa8ce1eaf4f08065b3331
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 { NeverFallThrough = 0, MaybeFallThrough = 1,
58  AlwaysFallThrough = 2, NeverFallThroughOrReturn = 3 };
59
60/// CheckFallThrough - Check that we don't fall off the end of a
61/// Statement that should return a value.
62///
63/// \returns AlwaysFallThrough iff we always fall off the end of the statement,
64/// MaybeFallThrough iff we might or might not fall off the end,
65/// NeverFallThroughOrReturn iff we never fall off the end of the statement or
66/// return.  We assume NeverFallThrough iff we never fall off the end of the
67/// statement but we may return.  We assume that functions not marked noreturn
68/// will return.
69static ControlFlowKind CheckFallThrough(AnalysisContext &AC) {
70  CFG *cfg = AC.getCFG();
71  if (cfg == 0)
72    // FIXME: This should be NeverFallThrough
73    return NeverFallThroughOrReturn;
74
75  // The CFG leaves in dead things, and we don't want the dead code paths to
76  // confuse us, so we mark all live things first.
77  llvm::SmallVector<CFGBlock*, 20> workq;
78  llvm::BitVector live(cfg->getNumBlockIDs());
79  unsigned count = reachable_code::ScanReachableFromBlock(cfg->getEntry(),
80                                                          live);
81
82  bool AddEHEdges = AC.getAddEHEdges();
83  if (!AddEHEdges && count != cfg->getNumBlockIDs())
84    // When there are things remaining dead, and we didn't add EH edges
85    // from CallExprs to the catch clauses, we have to go back and
86    // mark them as live.
87    for (CFG::iterator I = cfg->begin(), E = cfg->end(); I != E; ++I) {
88      CFGBlock &b = **I;
89      if (!live[b.getBlockID()]) {
90        if (b.pred_begin() == b.pred_end()) {
91          if (b.getTerminator() && isa<CXXTryStmt>(b.getTerminator()))
92            // When not adding EH edges from calls, catch clauses
93            // can otherwise seem dead.  Avoid noting them as dead.
94            count += reachable_code::ScanReachableFromBlock(b, live);
95          continue;
96        }
97      }
98    }
99
100  // Now we know what is live, we check the live precessors of the exit block
101  // and look for fall through paths, being careful to ignore normal returns,
102  // and exceptional paths.
103  bool HasLiveReturn = false;
104  bool HasFakeEdge = false;
105  bool HasPlainEdge = false;
106  bool HasAbnormalEdge = false;
107  for (CFGBlock::pred_iterator I=cfg->getExit().pred_begin(),
108       E = cfg->getExit().pred_end();
109       I != E;
110       ++I) {
111    CFGBlock& B = **I;
112    if (!live[B.getBlockID()])
113      continue;
114    if (B.size() == 0) {
115      if (B.getTerminator() && isa<CXXTryStmt>(B.getTerminator())) {
116        HasAbnormalEdge = true;
117        continue;
118      }
119
120      // A labeled empty statement, or the entry block...
121      HasPlainEdge = true;
122      continue;
123    }
124    Stmt *S = B[B.size()-1];
125    if (isa<ReturnStmt>(S)) {
126      HasLiveReturn = true;
127      continue;
128    }
129    if (isa<ObjCAtThrowStmt>(S)) {
130      HasFakeEdge = true;
131      continue;
132    }
133    if (isa<CXXThrowExpr>(S)) {
134      HasFakeEdge = true;
135      continue;
136    }
137    if (const AsmStmt *AS = dyn_cast<AsmStmt>(S)) {
138      if (AS->isMSAsm()) {
139        HasFakeEdge = true;
140        HasLiveReturn = true;
141        continue;
142      }
143    }
144    if (isa<CXXTryStmt>(S)) {
145      HasAbnormalEdge = true;
146      continue;
147    }
148
149    bool NoReturnEdge = false;
150    if (CallExpr *C = dyn_cast<CallExpr>(S)) {
151      if (B.succ_begin()[0] != &cfg->getExit()) {
152        HasAbnormalEdge = true;
153        continue;
154      }
155      Expr *CEE = C->getCallee()->IgnoreParenCasts();
156      if (getFunctionExtInfo(CEE->getType()).getNoReturn()) {
157        NoReturnEdge = true;
158        HasFakeEdge = true;
159      } else if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(CEE)) {
160        ValueDecl *VD = DRE->getDecl();
161        if (VD->hasAttr<NoReturnAttr>()) {
162          NoReturnEdge = true;
163          HasFakeEdge = true;
164        }
165      }
166    }
167    // FIXME: Add noreturn message sends.
168    if (NoReturnEdge == false)
169      HasPlainEdge = true;
170  }
171  if (!HasPlainEdge) {
172    if (HasLiveReturn)
173      return NeverFallThrough;
174    return NeverFallThroughOrReturn;
175  }
176  if (HasAbnormalEdge || HasFakeEdge || HasLiveReturn)
177    return MaybeFallThrough;
178  // This says AlwaysFallThrough for calls to functions that are not marked
179  // noreturn, that don't return.  If people would like this warning to be more
180  // accurate, such functions should be marked as noreturn.
181  return AlwaysFallThrough;
182}
183
184struct CheckFallThroughDiagnostics {
185  unsigned diag_MaybeFallThrough_HasNoReturn;
186  unsigned diag_MaybeFallThrough_ReturnsNonVoid;
187  unsigned diag_AlwaysFallThrough_HasNoReturn;
188  unsigned diag_AlwaysFallThrough_ReturnsNonVoid;
189  unsigned diag_NeverFallThroughOrReturn;
190  bool funMode;
191
192  static CheckFallThroughDiagnostics MakeForFunction() {
193    CheckFallThroughDiagnostics D;
194    D.diag_MaybeFallThrough_HasNoReturn =
195      diag::warn_falloff_noreturn_function;
196    D.diag_MaybeFallThrough_ReturnsNonVoid =
197      diag::warn_maybe_falloff_nonvoid_function;
198    D.diag_AlwaysFallThrough_HasNoReturn =
199      diag::warn_falloff_noreturn_function;
200    D.diag_AlwaysFallThrough_ReturnsNonVoid =
201      diag::warn_falloff_nonvoid_function;
202    D.diag_NeverFallThroughOrReturn =
203      diag::warn_suggest_noreturn_function;
204    D.funMode = true;
205    return D;
206  }
207
208  static CheckFallThroughDiagnostics MakeForBlock() {
209    CheckFallThroughDiagnostics D;
210    D.diag_MaybeFallThrough_HasNoReturn =
211      diag::err_noreturn_block_has_return_expr;
212    D.diag_MaybeFallThrough_ReturnsNonVoid =
213      diag::err_maybe_falloff_nonvoid_block;
214    D.diag_AlwaysFallThrough_HasNoReturn =
215      diag::err_noreturn_block_has_return_expr;
216    D.diag_AlwaysFallThrough_ReturnsNonVoid =
217      diag::err_falloff_nonvoid_block;
218    D.diag_NeverFallThroughOrReturn =
219      diag::warn_suggest_noreturn_block;
220    D.funMode = false;
221    return D;
222  }
223
224  bool checkDiagnostics(Diagnostic &D, bool ReturnsVoid,
225                        bool HasNoReturn) const {
226    if (funMode) {
227      return (D.getDiagnosticLevel(diag::warn_maybe_falloff_nonvoid_function)
228              == Diagnostic::Ignored || ReturnsVoid)
229        && (D.getDiagnosticLevel(diag::warn_noreturn_function_has_return_expr)
230              == Diagnostic::Ignored || !HasNoReturn)
231        && (D.getDiagnosticLevel(diag::warn_suggest_noreturn_block)
232              == Diagnostic::Ignored || !ReturnsVoid);
233    }
234
235    // For blocks.
236    return  ReturnsVoid && !HasNoReturn
237            && (D.getDiagnosticLevel(diag::warn_suggest_noreturn_block)
238                == Diagnostic::Ignored || !ReturnsVoid);
239  }
240};
241
242/// CheckFallThroughForFunctionDef - Check that we don't fall off the end of a
243/// function that should return a value.  Check that we don't fall off the end
244/// of a noreturn function.  We assume that functions and blocks not marked
245/// noreturn will return.
246static void CheckFallThroughForBody(Sema &S, const Decl *D, const Stmt *Body,
247                                    QualType BlockTy,
248                                    const CheckFallThroughDiagnostics& CD,
249                                    AnalysisContext &AC) {
250
251  bool ReturnsVoid = false;
252  bool HasNoReturn = false;
253
254  if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
255    ReturnsVoid = FD->getResultType()->isVoidType();
256    HasNoReturn = FD->hasAttr<NoReturnAttr>() ||
257       FD->getType()->getAs<FunctionType>()->getNoReturnAttr();
258  }
259  else if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D)) {
260    ReturnsVoid = MD->getResultType()->isVoidType();
261    HasNoReturn = MD->hasAttr<NoReturnAttr>();
262  }
263  else if (isa<BlockDecl>(D)) {
264    if (const FunctionType *FT =
265          BlockTy->getPointeeType()->getAs<FunctionType>()) {
266      if (FT->getResultType()->isVoidType())
267        ReturnsVoid = true;
268      if (FT->getNoReturnAttr())
269        HasNoReturn = true;
270    }
271  }
272
273  Diagnostic &Diags = S.getDiagnostics();
274
275  // Short circuit for compilation speed.
276  if (CD.checkDiagnostics(Diags, ReturnsVoid, HasNoReturn))
277      return;
278
279  // FIXME: Function try block
280  if (const CompoundStmt *Compound = dyn_cast<CompoundStmt>(Body)) {
281    switch (CheckFallThrough(AC)) {
282      case MaybeFallThrough:
283        if (HasNoReturn)
284          S.Diag(Compound->getRBracLoc(),
285                 CD.diag_MaybeFallThrough_HasNoReturn);
286        else if (!ReturnsVoid)
287          S.Diag(Compound->getRBracLoc(),
288                 CD.diag_MaybeFallThrough_ReturnsNonVoid);
289        break;
290      case AlwaysFallThrough:
291        if (HasNoReturn)
292          S.Diag(Compound->getRBracLoc(),
293                 CD.diag_AlwaysFallThrough_HasNoReturn);
294        else if (!ReturnsVoid)
295          S.Diag(Compound->getRBracLoc(),
296                 CD.diag_AlwaysFallThrough_ReturnsNonVoid);
297        break;
298      case NeverFallThroughOrReturn:
299        if (ReturnsVoid && !HasNoReturn)
300          S.Diag(Compound->getLBracLoc(),
301                 CD.diag_NeverFallThroughOrReturn);
302        break;
303      case NeverFallThrough:
304        break;
305    }
306  }
307}
308
309//===----------------------------------------------------------------------===//
310// AnalysisBasedWarnings - Worker object used by Sema to execute analysis-based
311//  warnings on a function, method, or block.
312//===----------------------------------------------------------------------===//
313
314clang::sema::AnalysisBasedWarnings::Policy::Policy() {
315  enableCheckFallThrough = 1;
316  enableCheckUnreachable = 0;
317}
318
319clang::sema::AnalysisBasedWarnings::AnalysisBasedWarnings(Sema &s) : S(s) {
320  Diagnostic &D = S.getDiagnostics();
321  DefaultPolicy.enableCheckUnreachable = (unsigned)
322    (D.getDiagnosticLevel(diag::warn_unreachable) != Diagnostic::Ignored);
323}
324
325void clang::sema::
326AnalysisBasedWarnings::IssueWarnings(sema::AnalysisBasedWarnings::Policy P,
327                                     const Decl *D, QualType BlockTy,
328                                     const bool analyzeStaticInline) {
329
330  assert(BlockTy.isNull() || isa<BlockDecl>(D));
331
332  // We avoid doing analysis-based warnings when there are errors for
333  // two reasons:
334  // (1) The CFGs often can't be constructed (if the body is invalid), so
335  //     don't bother trying.
336  // (2) The code already has problems; running the analysis just takes more
337  //     time.
338  if (S.getDiagnostics().hasErrorOccurred())
339    return;
340
341  // Do not do any analysis for declarations in system headers if we are
342  // going to just ignore them.
343  if (S.getDiagnostics().getSuppressSystemWarnings() &&
344      S.SourceMgr.isInSystemHeader(D->getLocation()))
345    return;
346
347  if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
348    // For function templates, class templates and member function templates
349    // we'll do the analysis at instantiation time.
350    if (FD->isDependentContext())
351      return;
352
353    // Only analyze 'static inline' functions when explicitly asked.
354    if (!analyzeStaticInline && FD->isInlineSpecified() &&
355        FD->getStorageClass() == FunctionDecl::Static) {
356      FD = FD->getCanonicalDecl();
357      VisitFlag &visitFlag = VisitedFD[FD];
358      if (visitFlag == Pending)
359        visitFlag = Visited;
360      else
361        return;
362    }
363  }
364
365  const Stmt *Body = D->getBody();
366  assert(Body);
367
368  // Don't generate EH edges for CallExprs as we'd like to avoid the n^2
369  // explosion for destrutors that can result and the compile time hit.
370  AnalysisContext AC(D, false);
371  bool performedCheck = false;
372
373  // Warning: check missing 'return'
374  if (P.enableCheckFallThrough) {
375    const CheckFallThroughDiagnostics &CD =
376      (isa<BlockDecl>(D) ? CheckFallThroughDiagnostics::MakeForBlock()
377                         : CheckFallThroughDiagnostics::MakeForFunction());
378    CheckFallThroughForBody(S, D, Body, BlockTy, CD, AC);
379    performedCheck = true;
380  }
381
382  // Warning: check for unreachable code
383  if (P.enableCheckUnreachable) {
384    CheckUnreachable(S, AC);
385    performedCheck = true;
386  }
387
388  // If this block or function calls a 'static inline' function,
389  // we should analyze those functions as well.
390  if (performedCheck) {
391    // The CFG should already be constructed, so this should not
392    // incur any extra cost.  We might not have a CFG, however, for
393    // invalid code.
394    if (const CFG *cfg = AC.getCFG()) {
395      // All CallExprs are block-level expressions in the CFG.  This means
396      // that walking the basic blocks in the CFG is more efficient
397      // than walking the entire AST to find all calls.
398      for (CFG::const_iterator I=cfg->begin(), E=cfg->end(); I!=E; ++I) {
399        const CFGBlock *B = *I;
400        for (CFGBlock::const_iterator BI=B->begin(), BE=B->end(); BI!=BE; ++BI)
401          if (const CallExpr *CE = dyn_cast<CallExpr>(*BI))
402            if (const DeclRefExpr *DR =
403                dyn_cast<DeclRefExpr>(CE->getCallee()->IgnoreParenCasts()))
404              if (const FunctionDecl *calleeD =
405                  dyn_cast<FunctionDecl>(DR->getDecl())) {
406                calleeD = calleeD->getCanonicalDecl();
407                if (calleeD->isInlineSpecified() &&
408                    calleeD->getStorageClass() == FunctionDecl::Static) {
409                  // Have we analyzed this static inline function before?
410                  VisitFlag &visitFlag = VisitedFD[calleeD];
411                  if (visitFlag == NotVisited) {
412                    // Mark the callee visited prior to analyzing it
413                    // so we terminate in case of recursion.
414                    if (calleeD->getBody()) {
415                      visitFlag = Visited;
416                      IssueWarnings(DefaultPolicy, calleeD, QualType(), true);
417                    }
418                    else {
419                      // Delay warnings until we encounter the definition.
420                      visitFlag = Pending;
421                    }
422                  }
423                }
424              }
425      }
426    }
427  }
428}
429