AnalysisBasedWarnings.cpp revision 212904
1205408Srdivacky//=- AnalysisBasedWarnings.cpp - Sema warnings based on libAnalysis -*- C++ -*-=//
2205408Srdivacky//
3205408Srdivacky//                     The LLVM Compiler Infrastructure
4205408Srdivacky//
5205408Srdivacky// This file is distributed under the University of Illinois Open Source
6205408Srdivacky// License. See LICENSE.TXT for details.
7205408Srdivacky//
8205408Srdivacky//===----------------------------------------------------------------------===//
9205408Srdivacky//
10205408Srdivacky// This file defines analysis_warnings::[Policy,Executor].
11205408Srdivacky// Together they are used by Sema to issue warnings based on inexpensive
12205408Srdivacky// static analysis algorithms in libAnalysis.
13205408Srdivacky//
14205408Srdivacky//===----------------------------------------------------------------------===//
15205408Srdivacky
16212904Sdim#include "clang/Sema/AnalysisBasedWarnings.h"
17212904Sdim#include "clang/Sema/SemaInternal.h"
18205408Srdivacky#include "clang/Basic/SourceManager.h"
19212904Sdim#include "clang/AST/DeclObjC.h"
20212904Sdim#include "clang/AST/DeclCXX.h"
21205408Srdivacky#include "clang/AST/ExprObjC.h"
22205408Srdivacky#include "clang/AST/ExprCXX.h"
23205408Srdivacky#include "clang/AST/StmtObjC.h"
24205408Srdivacky#include "clang/AST/StmtCXX.h"
25205408Srdivacky#include "clang/Analysis/AnalysisContext.h"
26205408Srdivacky#include "clang/Analysis/CFG.h"
27205408Srdivacky#include "clang/Analysis/Analyses/ReachableCode.h"
28205408Srdivacky#include "llvm/ADT/BitVector.h"
29205408Srdivacky#include "llvm/Support/Casting.h"
30205408Srdivacky
31205408Srdivackyusing namespace clang;
32205408Srdivacky
33205408Srdivacky//===----------------------------------------------------------------------===//
34205408Srdivacky// Unreachable code analysis.
35205408Srdivacky//===----------------------------------------------------------------------===//
36205408Srdivacky
37205408Srdivackynamespace {
38205408Srdivacky  class UnreachableCodeHandler : public reachable_code::Callback {
39205408Srdivacky    Sema &S;
40205408Srdivacky  public:
41205408Srdivacky    UnreachableCodeHandler(Sema &s) : S(s) {}
42205408Srdivacky
43205408Srdivacky    void HandleUnreachable(SourceLocation L, SourceRange R1, SourceRange R2) {
44205408Srdivacky      S.Diag(L, diag::warn_unreachable) << R1 << R2;
45205408Srdivacky    }
46205408Srdivacky  };
47205408Srdivacky}
48205408Srdivacky
49205408Srdivacky/// CheckUnreachable - Check for unreachable code.
50205408Srdivackystatic void CheckUnreachable(Sema &S, AnalysisContext &AC) {
51205408Srdivacky  UnreachableCodeHandler UC(S);
52205408Srdivacky  reachable_code::FindUnreachableCode(AC, UC);
53205408Srdivacky}
54205408Srdivacky
55205408Srdivacky//===----------------------------------------------------------------------===//
56205408Srdivacky// Check for missing return value.
57205408Srdivacky//===----------------------------------------------------------------------===//
58205408Srdivacky
59208600Srdivackyenum ControlFlowKind {
60208600Srdivacky  UnknownFallThrough,
61208600Srdivacky  NeverFallThrough,
62208600Srdivacky  MaybeFallThrough,
63208600Srdivacky  AlwaysFallThrough,
64208600Srdivacky  NeverFallThroughOrReturn
65208600Srdivacky};
66205408Srdivacky
67205408Srdivacky/// CheckFallThrough - Check that we don't fall off the end of a
68205408Srdivacky/// Statement that should return a value.
69205408Srdivacky///
70205408Srdivacky/// \returns AlwaysFallThrough iff we always fall off the end of the statement,
71205408Srdivacky/// MaybeFallThrough iff we might or might not fall off the end,
72205408Srdivacky/// NeverFallThroughOrReturn iff we never fall off the end of the statement or
73205408Srdivacky/// return.  We assume NeverFallThrough iff we never fall off the end of the
74205408Srdivacky/// statement but we may return.  We assume that functions not marked noreturn
75205408Srdivacky/// will return.
76205408Srdivackystatic ControlFlowKind CheckFallThrough(AnalysisContext &AC) {
77205408Srdivacky  CFG *cfg = AC.getCFG();
78208600Srdivacky  if (cfg == 0) return UnknownFallThrough;
79205408Srdivacky
80205408Srdivacky  // The CFG leaves in dead things, and we don't want the dead code paths to
81205408Srdivacky  // confuse us, so we mark all live things first.
82205408Srdivacky  llvm::BitVector live(cfg->getNumBlockIDs());
83205408Srdivacky  unsigned count = reachable_code::ScanReachableFromBlock(cfg->getEntry(),
84205408Srdivacky                                                          live);
85205408Srdivacky
86205408Srdivacky  bool AddEHEdges = AC.getAddEHEdges();
87205408Srdivacky  if (!AddEHEdges && count != cfg->getNumBlockIDs())
88205408Srdivacky    // When there are things remaining dead, and we didn't add EH edges
89205408Srdivacky    // from CallExprs to the catch clauses, we have to go back and
90205408Srdivacky    // mark them as live.
91205408Srdivacky    for (CFG::iterator I = cfg->begin(), E = cfg->end(); I != E; ++I) {
92205408Srdivacky      CFGBlock &b = **I;
93205408Srdivacky      if (!live[b.getBlockID()]) {
94205408Srdivacky        if (b.pred_begin() == b.pred_end()) {
95205408Srdivacky          if (b.getTerminator() && isa<CXXTryStmt>(b.getTerminator()))
96205408Srdivacky            // When not adding EH edges from calls, catch clauses
97205408Srdivacky            // can otherwise seem dead.  Avoid noting them as dead.
98205408Srdivacky            count += reachable_code::ScanReachableFromBlock(b, live);
99205408Srdivacky          continue;
100205408Srdivacky        }
101205408Srdivacky      }
102205408Srdivacky    }
103205408Srdivacky
104205408Srdivacky  // Now we know what is live, we check the live precessors of the exit block
105205408Srdivacky  // and look for fall through paths, being careful to ignore normal returns,
106205408Srdivacky  // and exceptional paths.
107205408Srdivacky  bool HasLiveReturn = false;
108205408Srdivacky  bool HasFakeEdge = false;
109205408Srdivacky  bool HasPlainEdge = false;
110205408Srdivacky  bool HasAbnormalEdge = false;
111205408Srdivacky  for (CFGBlock::pred_iterator I=cfg->getExit().pred_begin(),
112205408Srdivacky       E = cfg->getExit().pred_end();
113205408Srdivacky       I != E;
114205408Srdivacky       ++I) {
115205408Srdivacky    CFGBlock& B = **I;
116205408Srdivacky    if (!live[B.getBlockID()])
117205408Srdivacky      continue;
118205408Srdivacky    if (B.size() == 0) {
119205408Srdivacky      if (B.getTerminator() && isa<CXXTryStmt>(B.getTerminator())) {
120205408Srdivacky        HasAbnormalEdge = true;
121205408Srdivacky        continue;
122205408Srdivacky      }
123205408Srdivacky
124205408Srdivacky      // A labeled empty statement, or the entry block...
125205408Srdivacky      HasPlainEdge = true;
126205408Srdivacky      continue;
127205408Srdivacky    }
128205408Srdivacky    Stmt *S = B[B.size()-1];
129205408Srdivacky    if (isa<ReturnStmt>(S)) {
130205408Srdivacky      HasLiveReturn = true;
131205408Srdivacky      continue;
132205408Srdivacky    }
133205408Srdivacky    if (isa<ObjCAtThrowStmt>(S)) {
134205408Srdivacky      HasFakeEdge = true;
135205408Srdivacky      continue;
136205408Srdivacky    }
137205408Srdivacky    if (isa<CXXThrowExpr>(S)) {
138205408Srdivacky      HasFakeEdge = true;
139205408Srdivacky      continue;
140205408Srdivacky    }
141205408Srdivacky    if (const AsmStmt *AS = dyn_cast<AsmStmt>(S)) {
142205408Srdivacky      if (AS->isMSAsm()) {
143205408Srdivacky        HasFakeEdge = true;
144205408Srdivacky        HasLiveReturn = true;
145205408Srdivacky        continue;
146205408Srdivacky      }
147205408Srdivacky    }
148205408Srdivacky    if (isa<CXXTryStmt>(S)) {
149205408Srdivacky      HasAbnormalEdge = true;
150205408Srdivacky      continue;
151205408Srdivacky    }
152205408Srdivacky
153205408Srdivacky    bool NoReturnEdge = false;
154205408Srdivacky    if (CallExpr *C = dyn_cast<CallExpr>(S)) {
155207619Srdivacky      if (std::find(B.succ_begin(), B.succ_end(), &cfg->getExit())
156207619Srdivacky            == B.succ_end()) {
157205408Srdivacky        HasAbnormalEdge = true;
158205408Srdivacky        continue;
159205408Srdivacky      }
160205408Srdivacky      Expr *CEE = C->getCallee()->IgnoreParenCasts();
161206084Srdivacky      if (getFunctionExtInfo(CEE->getType()).getNoReturn()) {
162205408Srdivacky        NoReturnEdge = true;
163205408Srdivacky        HasFakeEdge = true;
164205408Srdivacky      } else if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(CEE)) {
165205408Srdivacky        ValueDecl *VD = DRE->getDecl();
166205408Srdivacky        if (VD->hasAttr<NoReturnAttr>()) {
167205408Srdivacky          NoReturnEdge = true;
168205408Srdivacky          HasFakeEdge = true;
169205408Srdivacky        }
170205408Srdivacky      }
171205408Srdivacky    }
172208600Srdivacky    // FIXME: Remove this hack once temporaries and their destructors are
173208600Srdivacky    // modeled correctly by the CFG.
174208600Srdivacky    if (CXXExprWithTemporaries *E = dyn_cast<CXXExprWithTemporaries>(S)) {
175208600Srdivacky      for (unsigned I = 0, N = E->getNumTemporaries(); I != N; ++I) {
176208600Srdivacky        const FunctionDecl *FD = E->getTemporary(I)->getDestructor();
177208600Srdivacky        if (FD->hasAttr<NoReturnAttr>() ||
178208600Srdivacky            FD->getType()->getAs<FunctionType>()->getNoReturnAttr()) {
179208600Srdivacky          NoReturnEdge = true;
180208600Srdivacky          HasFakeEdge = true;
181208600Srdivacky          break;
182208600Srdivacky        }
183208600Srdivacky      }
184208600Srdivacky    }
185205408Srdivacky    // FIXME: Add noreturn message sends.
186205408Srdivacky    if (NoReturnEdge == false)
187205408Srdivacky      HasPlainEdge = true;
188205408Srdivacky  }
189205408Srdivacky  if (!HasPlainEdge) {
190205408Srdivacky    if (HasLiveReturn)
191205408Srdivacky      return NeverFallThrough;
192205408Srdivacky    return NeverFallThroughOrReturn;
193205408Srdivacky  }
194205408Srdivacky  if (HasAbnormalEdge || HasFakeEdge || HasLiveReturn)
195205408Srdivacky    return MaybeFallThrough;
196205408Srdivacky  // This says AlwaysFallThrough for calls to functions that are not marked
197205408Srdivacky  // noreturn, that don't return.  If people would like this warning to be more
198205408Srdivacky  // accurate, such functions should be marked as noreturn.
199205408Srdivacky  return AlwaysFallThrough;
200205408Srdivacky}
201205408Srdivacky
202212904Sdimnamespace {
203212904Sdim
204205408Srdivackystruct CheckFallThroughDiagnostics {
205205408Srdivacky  unsigned diag_MaybeFallThrough_HasNoReturn;
206205408Srdivacky  unsigned diag_MaybeFallThrough_ReturnsNonVoid;
207205408Srdivacky  unsigned diag_AlwaysFallThrough_HasNoReturn;
208205408Srdivacky  unsigned diag_AlwaysFallThrough_ReturnsNonVoid;
209205408Srdivacky  unsigned diag_NeverFallThroughOrReturn;
210205408Srdivacky  bool funMode;
211206084Srdivacky
212207619Srdivacky  static CheckFallThroughDiagnostics MakeForFunction(const Decl *Func) {
213205408Srdivacky    CheckFallThroughDiagnostics D;
214205408Srdivacky    D.diag_MaybeFallThrough_HasNoReturn =
215205408Srdivacky      diag::warn_falloff_noreturn_function;
216205408Srdivacky    D.diag_MaybeFallThrough_ReturnsNonVoid =
217205408Srdivacky      diag::warn_maybe_falloff_nonvoid_function;
218205408Srdivacky    D.diag_AlwaysFallThrough_HasNoReturn =
219205408Srdivacky      diag::warn_falloff_noreturn_function;
220205408Srdivacky    D.diag_AlwaysFallThrough_ReturnsNonVoid =
221205408Srdivacky      diag::warn_falloff_nonvoid_function;
222207619Srdivacky
223207619Srdivacky    // Don't suggest that virtual functions be marked "noreturn", since they
224207619Srdivacky    // might be overridden by non-noreturn functions.
225207619Srdivacky    bool isVirtualMethod = false;
226207619Srdivacky    if (const CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(Func))
227207619Srdivacky      isVirtualMethod = Method->isVirtual();
228207619Srdivacky
229207619Srdivacky    if (!isVirtualMethod)
230207619Srdivacky      D.diag_NeverFallThroughOrReturn =
231207619Srdivacky        diag::warn_suggest_noreturn_function;
232207619Srdivacky    else
233207619Srdivacky      D.diag_NeverFallThroughOrReturn = 0;
234207619Srdivacky
235205408Srdivacky    D.funMode = true;
236205408Srdivacky    return D;
237205408Srdivacky  }
238206084Srdivacky
239205408Srdivacky  static CheckFallThroughDiagnostics MakeForBlock() {
240205408Srdivacky    CheckFallThroughDiagnostics D;
241205408Srdivacky    D.diag_MaybeFallThrough_HasNoReturn =
242205408Srdivacky      diag::err_noreturn_block_has_return_expr;
243205408Srdivacky    D.diag_MaybeFallThrough_ReturnsNonVoid =
244205408Srdivacky      diag::err_maybe_falloff_nonvoid_block;
245205408Srdivacky    D.diag_AlwaysFallThrough_HasNoReturn =
246205408Srdivacky      diag::err_noreturn_block_has_return_expr;
247205408Srdivacky    D.diag_AlwaysFallThrough_ReturnsNonVoid =
248205408Srdivacky      diag::err_falloff_nonvoid_block;
249205408Srdivacky    D.diag_NeverFallThroughOrReturn =
250205408Srdivacky      diag::warn_suggest_noreturn_block;
251205408Srdivacky    D.funMode = false;
252205408Srdivacky    return D;
253205408Srdivacky  }
254206084Srdivacky
255205408Srdivacky  bool checkDiagnostics(Diagnostic &D, bool ReturnsVoid,
256205408Srdivacky                        bool HasNoReturn) const {
257205408Srdivacky    if (funMode) {
258205408Srdivacky      return (D.getDiagnosticLevel(diag::warn_maybe_falloff_nonvoid_function)
259205408Srdivacky              == Diagnostic::Ignored || ReturnsVoid)
260205408Srdivacky        && (D.getDiagnosticLevel(diag::warn_noreturn_function_has_return_expr)
261205408Srdivacky              == Diagnostic::Ignored || !HasNoReturn)
262205408Srdivacky        && (D.getDiagnosticLevel(diag::warn_suggest_noreturn_block)
263205408Srdivacky              == Diagnostic::Ignored || !ReturnsVoid);
264205408Srdivacky    }
265206084Srdivacky
266205408Srdivacky    // For blocks.
267205408Srdivacky    return  ReturnsVoid && !HasNoReturn
268205408Srdivacky            && (D.getDiagnosticLevel(diag::warn_suggest_noreturn_block)
269205408Srdivacky                == Diagnostic::Ignored || !ReturnsVoid);
270205408Srdivacky  }
271205408Srdivacky};
272205408Srdivacky
273212904Sdim}
274212904Sdim
275205408Srdivacky/// CheckFallThroughForFunctionDef - Check that we don't fall off the end of a
276205408Srdivacky/// function that should return a value.  Check that we don't fall off the end
277205408Srdivacky/// of a noreturn function.  We assume that functions and blocks not marked
278205408Srdivacky/// noreturn will return.
279205408Srdivackystatic void CheckFallThroughForBody(Sema &S, const Decl *D, const Stmt *Body,
280205408Srdivacky                                    QualType BlockTy,
281205408Srdivacky                                    const CheckFallThroughDiagnostics& CD,
282205408Srdivacky                                    AnalysisContext &AC) {
283205408Srdivacky
284205408Srdivacky  bool ReturnsVoid = false;
285205408Srdivacky  bool HasNoReturn = false;
286205408Srdivacky
287205408Srdivacky  if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
288205408Srdivacky    ReturnsVoid = FD->getResultType()->isVoidType();
289205408Srdivacky    HasNoReturn = FD->hasAttr<NoReturnAttr>() ||
290206084Srdivacky       FD->getType()->getAs<FunctionType>()->getNoReturnAttr();
291205408Srdivacky  }
292205408Srdivacky  else if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D)) {
293205408Srdivacky    ReturnsVoid = MD->getResultType()->isVoidType();
294205408Srdivacky    HasNoReturn = MD->hasAttr<NoReturnAttr>();
295205408Srdivacky  }
296205408Srdivacky  else if (isa<BlockDecl>(D)) {
297206084Srdivacky    if (const FunctionType *FT =
298205408Srdivacky          BlockTy->getPointeeType()->getAs<FunctionType>()) {
299205408Srdivacky      if (FT->getResultType()->isVoidType())
300205408Srdivacky        ReturnsVoid = true;
301205408Srdivacky      if (FT->getNoReturnAttr())
302205408Srdivacky        HasNoReturn = true;
303205408Srdivacky    }
304205408Srdivacky  }
305205408Srdivacky
306205408Srdivacky  Diagnostic &Diags = S.getDiagnostics();
307205408Srdivacky
308205408Srdivacky  // Short circuit for compilation speed.
309205408Srdivacky  if (CD.checkDiagnostics(Diags, ReturnsVoid, HasNoReturn))
310205408Srdivacky      return;
311206084Srdivacky
312205408Srdivacky  // FIXME: Function try block
313205408Srdivacky  if (const CompoundStmt *Compound = dyn_cast<CompoundStmt>(Body)) {
314205408Srdivacky    switch (CheckFallThrough(AC)) {
315208600Srdivacky      case UnknownFallThrough:
316208600Srdivacky        break;
317208600Srdivacky
318205408Srdivacky      case MaybeFallThrough:
319205408Srdivacky        if (HasNoReturn)
320205408Srdivacky          S.Diag(Compound->getRBracLoc(),
321205408Srdivacky                 CD.diag_MaybeFallThrough_HasNoReturn);
322205408Srdivacky        else if (!ReturnsVoid)
323205408Srdivacky          S.Diag(Compound->getRBracLoc(),
324205408Srdivacky                 CD.diag_MaybeFallThrough_ReturnsNonVoid);
325205408Srdivacky        break;
326205408Srdivacky      case AlwaysFallThrough:
327205408Srdivacky        if (HasNoReturn)
328205408Srdivacky          S.Diag(Compound->getRBracLoc(),
329205408Srdivacky                 CD.diag_AlwaysFallThrough_HasNoReturn);
330205408Srdivacky        else if (!ReturnsVoid)
331205408Srdivacky          S.Diag(Compound->getRBracLoc(),
332205408Srdivacky                 CD.diag_AlwaysFallThrough_ReturnsNonVoid);
333205408Srdivacky        break;
334205408Srdivacky      case NeverFallThroughOrReturn:
335207619Srdivacky        if (ReturnsVoid && !HasNoReturn && CD.diag_NeverFallThroughOrReturn)
336205408Srdivacky          S.Diag(Compound->getLBracLoc(),
337205408Srdivacky                 CD.diag_NeverFallThroughOrReturn);
338205408Srdivacky        break;
339205408Srdivacky      case NeverFallThrough:
340205408Srdivacky        break;
341205408Srdivacky    }
342205408Srdivacky  }
343205408Srdivacky}
344205408Srdivacky
345205408Srdivacky//===----------------------------------------------------------------------===//
346205408Srdivacky// AnalysisBasedWarnings - Worker object used by Sema to execute analysis-based
347205408Srdivacky//  warnings on a function, method, or block.
348205408Srdivacky//===----------------------------------------------------------------------===//
349205408Srdivacky
350206084Srdivackyclang::sema::AnalysisBasedWarnings::Policy::Policy() {
351206084Srdivacky  enableCheckFallThrough = 1;
352206084Srdivacky  enableCheckUnreachable = 0;
353206084Srdivacky}
354206084Srdivacky
355205408Srdivackyclang::sema::AnalysisBasedWarnings::AnalysisBasedWarnings(Sema &s) : S(s) {
356205408Srdivacky  Diagnostic &D = S.getDiagnostics();
357206084Srdivacky  DefaultPolicy.enableCheckUnreachable = (unsigned)
358205408Srdivacky    (D.getDiagnosticLevel(diag::warn_unreachable) != Diagnostic::Ignored);
359205408Srdivacky}
360205408Srdivacky
361206084Srdivackyvoid clang::sema::
362206084SrdivackyAnalysisBasedWarnings::IssueWarnings(sema::AnalysisBasedWarnings::Policy P,
363207619Srdivacky                                     const Decl *D, QualType BlockTy) {
364206084Srdivacky
365205408Srdivacky  assert(BlockTy.isNull() || isa<BlockDecl>(D));
366205408Srdivacky
367205408Srdivacky  // We avoid doing analysis-based warnings when there are errors for
368205408Srdivacky  // two reasons:
369205408Srdivacky  // (1) The CFGs often can't be constructed (if the body is invalid), so
370205408Srdivacky  //     don't bother trying.
371205408Srdivacky  // (2) The code already has problems; running the analysis just takes more
372205408Srdivacky  //     time.
373207619Srdivacky  Diagnostic &Diags = S.getDiagnostics();
374207619Srdivacky
375207619Srdivacky  if (Diags.hasErrorOccurred() || Diags.hasFatalErrorOccurred())
376206084Srdivacky    return;
377206084Srdivacky
378206084Srdivacky  // Do not do any analysis for declarations in system headers if we are
379206084Srdivacky  // going to just ignore them.
380207619Srdivacky  if (Diags.getSuppressSystemWarnings() &&
381206084Srdivacky      S.SourceMgr.isInSystemHeader(D->getLocation()))
382206084Srdivacky    return;
383206084Srdivacky
384212904Sdim  // For code in dependent contexts, we'll do this at instantiation time.
385212904Sdim  if (cast<DeclContext>(D)->isDependentContext())
386212904Sdim    return;
387205408Srdivacky
388205408Srdivacky  const Stmt *Body = D->getBody();
389205408Srdivacky  assert(Body);
390205408Srdivacky
391205408Srdivacky  // Don't generate EH edges for CallExprs as we'd like to avoid the n^2
392205408Srdivacky  // explosion for destrutors that can result and the compile time hit.
393212904Sdim  AnalysisContext AC(D, 0, false);
394205408Srdivacky
395205408Srdivacky  // Warning: check missing 'return'
396206084Srdivacky  if (P.enableCheckFallThrough) {
397205408Srdivacky    const CheckFallThroughDiagnostics &CD =
398205408Srdivacky      (isa<BlockDecl>(D) ? CheckFallThroughDiagnostics::MakeForBlock()
399207619Srdivacky                         : CheckFallThroughDiagnostics::MakeForFunction(D));
400205408Srdivacky    CheckFallThroughForBody(S, D, Body, BlockTy, CD, AC);
401205408Srdivacky  }
402205408Srdivacky
403205408Srdivacky  // Warning: check for unreachable code
404207619Srdivacky  if (P.enableCheckUnreachable)
405205408Srdivacky    CheckUnreachable(S, AC);
406205408Srdivacky}
407212904Sdim
408212904Sdimvoid clang::sema::
409212904SdimAnalysisBasedWarnings::IssueWarnings(sema::AnalysisBasedWarnings::Policy P,
410212904Sdim                                     const BlockExpr *E) {
411212904Sdim  return IssueWarnings(P, E->getBlockDecl(), E->getType());
412212904Sdim}
413212904Sdim
414212904Sdimvoid clang::sema::
415212904SdimAnalysisBasedWarnings::IssueWarnings(sema::AnalysisBasedWarnings::Policy P,
416212904Sdim                                     const ObjCMethodDecl *D) {
417212904Sdim  return IssueWarnings(P, D, QualType());
418212904Sdim}
419212904Sdim
420212904Sdimvoid clang::sema::
421212904SdimAnalysisBasedWarnings::IssueWarnings(sema::AnalysisBasedWarnings::Policy P,
422212904Sdim                                     const FunctionDecl *D) {
423212904Sdim  return IssueWarnings(P, D, QualType());
424212904Sdim}
425