AnalysisBasedWarnings.cpp revision b414c4fae51c5792d3074b4b78fc8737b1d8387c
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/AnalysisBasedWarnings.h"
17#include "clang/Sema/SemaInternal.h"
18#include "clang/Sema/ScopeInfo.h"
19#include "clang/Basic/SourceManager.h"
20#include "clang/Lex/Preprocessor.h"
21#include "clang/AST/DeclObjC.h"
22#include "clang/AST/DeclCXX.h"
23#include "clang/AST/ExprObjC.h"
24#include "clang/AST/ExprCXX.h"
25#include "clang/AST/StmtObjC.h"
26#include "clang/AST/StmtCXX.h"
27#include "clang/AST/EvaluatedExprVisitor.h"
28#include "clang/Analysis/AnalysisContext.h"
29#include "clang/Analysis/CFG.h"
30#include "clang/Analysis/Analyses/ReachableCode.h"
31#include "clang/Analysis/Analyses/CFGReachabilityAnalysis.h"
32#include "clang/Analysis/CFGStmtMap.h"
33#include "clang/Analysis/Analyses/UninitializedValues.h"
34#include "llvm/ADT/BitVector.h"
35#include "llvm/Support/Casting.h"
36
37using namespace clang;
38
39//===----------------------------------------------------------------------===//
40// Unreachable code analysis.
41//===----------------------------------------------------------------------===//
42
43namespace {
44  class UnreachableCodeHandler : public reachable_code::Callback {
45    Sema &S;
46  public:
47    UnreachableCodeHandler(Sema &s) : S(s) {}
48
49    void HandleUnreachable(SourceLocation L, SourceRange R1, SourceRange R2) {
50      S.Diag(L, diag::warn_unreachable) << R1 << R2;
51    }
52  };
53}
54
55/// CheckUnreachable - Check for unreachable code.
56static void CheckUnreachable(Sema &S, AnalysisContext &AC) {
57  UnreachableCodeHandler UC(S);
58  reachable_code::FindUnreachableCode(AC, UC);
59}
60
61//===----------------------------------------------------------------------===//
62// Check for missing return value.
63//===----------------------------------------------------------------------===//
64
65enum ControlFlowKind {
66  UnknownFallThrough,
67  NeverFallThrough,
68  MaybeFallThrough,
69  AlwaysFallThrough,
70  NeverFallThroughOrReturn
71};
72
73/// CheckFallThrough - Check that we don't fall off the end of a
74/// Statement that should return a value.
75///
76/// \returns AlwaysFallThrough iff we always fall off the end of the statement,
77/// MaybeFallThrough iff we might or might not fall off the end,
78/// NeverFallThroughOrReturn iff we never fall off the end of the statement or
79/// return.  We assume NeverFallThrough iff we never fall off the end of the
80/// statement but we may return.  We assume that functions not marked noreturn
81/// will return.
82static ControlFlowKind CheckFallThrough(AnalysisContext &AC) {
83  CFG *cfg = AC.getCFG();
84  if (cfg == 0) return UnknownFallThrough;
85
86  // The CFG leaves in dead things, and we don't want the dead code paths to
87  // confuse us, so we mark all live things first.
88  llvm::BitVector live(cfg->getNumBlockIDs());
89  unsigned count = reachable_code::ScanReachableFromBlock(cfg->getEntry(),
90                                                          live);
91
92  bool AddEHEdges = AC.getAddEHEdges();
93  if (!AddEHEdges && count != cfg->getNumBlockIDs())
94    // When there are things remaining dead, and we didn't add EH edges
95    // from CallExprs to the catch clauses, we have to go back and
96    // mark them as live.
97    for (CFG::iterator I = cfg->begin(), E = cfg->end(); I != E; ++I) {
98      CFGBlock &b = **I;
99      if (!live[b.getBlockID()]) {
100        if (b.pred_begin() == b.pred_end()) {
101          if (b.getTerminator() && isa<CXXTryStmt>(b.getTerminator()))
102            // When not adding EH edges from calls, catch clauses
103            // can otherwise seem dead.  Avoid noting them as dead.
104            count += reachable_code::ScanReachableFromBlock(b, live);
105          continue;
106        }
107      }
108    }
109
110  // Now we know what is live, we check the live precessors of the exit block
111  // and look for fall through paths, being careful to ignore normal returns,
112  // and exceptional paths.
113  bool HasLiveReturn = false;
114  bool HasFakeEdge = false;
115  bool HasPlainEdge = false;
116  bool HasAbnormalEdge = false;
117
118  // Ignore default cases that aren't likely to be reachable because all
119  // enums in a switch(X) have explicit case statements.
120  CFGBlock::FilterOptions FO;
121  FO.IgnoreDefaultsWithCoveredEnums = 1;
122
123  for (CFGBlock::filtered_pred_iterator
124	 I = cfg->getExit().filtered_pred_start_end(FO); I.hasMore(); ++I) {
125    const CFGBlock& B = **I;
126    if (!live[B.getBlockID()])
127      continue;
128
129    // Destructors can appear after the 'return' in the CFG.  This is
130    // normal.  We need to look pass the destructors for the return
131    // statement (if it exists).
132    CFGBlock::const_reverse_iterator ri = B.rbegin(), re = B.rend();
133    bool hasNoReturnDtor = false;
134
135    for ( ; ri != re ; ++ri) {
136      CFGElement CE = *ri;
137
138      // FIXME: The right solution is to just sever the edges in the
139      // CFG itself.
140      if (const CFGImplicitDtor *iDtor = ri->getAs<CFGImplicitDtor>())
141        if (iDtor->isNoReturn(AC.getASTContext())) {
142          hasNoReturnDtor = true;
143          HasFakeEdge = true;
144          break;
145        }
146
147      if (isa<CFGStmt>(CE))
148        break;
149    }
150
151    if (hasNoReturnDtor)
152      continue;
153
154    // No more CFGElements in the block?
155    if (ri == re) {
156      if (B.getTerminator() && isa<CXXTryStmt>(B.getTerminator())) {
157        HasAbnormalEdge = true;
158        continue;
159      }
160      // A labeled empty statement, or the entry block...
161      HasPlainEdge = true;
162      continue;
163    }
164
165    CFGStmt CS = cast<CFGStmt>(*ri);
166    Stmt *S = CS.getStmt();
167    if (isa<ReturnStmt>(S)) {
168      HasLiveReturn = true;
169      continue;
170    }
171    if (isa<ObjCAtThrowStmt>(S)) {
172      HasFakeEdge = true;
173      continue;
174    }
175    if (isa<CXXThrowExpr>(S)) {
176      HasFakeEdge = true;
177      continue;
178    }
179    if (const AsmStmt *AS = dyn_cast<AsmStmt>(S)) {
180      if (AS->isMSAsm()) {
181        HasFakeEdge = true;
182        HasLiveReturn = true;
183        continue;
184      }
185    }
186    if (isa<CXXTryStmt>(S)) {
187      HasAbnormalEdge = true;
188      continue;
189    }
190
191    bool NoReturnEdge = false;
192    if (CallExpr *C = dyn_cast<CallExpr>(S)) {
193      if (std::find(B.succ_begin(), B.succ_end(), &cfg->getExit())
194            == B.succ_end()) {
195        HasAbnormalEdge = true;
196        continue;
197      }
198      Expr *CEE = C->getCallee()->IgnoreParenCasts();
199      if (getFunctionExtInfo(CEE->getType()).getNoReturn()) {
200        NoReturnEdge = true;
201        HasFakeEdge = true;
202      } else if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(CEE)) {
203        ValueDecl *VD = DRE->getDecl();
204        if (VD->hasAttr<NoReturnAttr>()) {
205          NoReturnEdge = true;
206          HasFakeEdge = true;
207        }
208      }
209    }
210    // FIXME: Add noreturn message sends.
211    if (NoReturnEdge == false)
212      HasPlainEdge = true;
213  }
214  if (!HasPlainEdge) {
215    if (HasLiveReturn)
216      return NeverFallThrough;
217    return NeverFallThroughOrReturn;
218  }
219  if (HasAbnormalEdge || HasFakeEdge || HasLiveReturn)
220    return MaybeFallThrough;
221  // This says AlwaysFallThrough for calls to functions that are not marked
222  // noreturn, that don't return.  If people would like this warning to be more
223  // accurate, such functions should be marked as noreturn.
224  return AlwaysFallThrough;
225}
226
227namespace {
228
229struct CheckFallThroughDiagnostics {
230  unsigned diag_MaybeFallThrough_HasNoReturn;
231  unsigned diag_MaybeFallThrough_ReturnsNonVoid;
232  unsigned diag_AlwaysFallThrough_HasNoReturn;
233  unsigned diag_AlwaysFallThrough_ReturnsNonVoid;
234  unsigned diag_NeverFallThroughOrReturn;
235  bool funMode;
236  SourceLocation FuncLoc;
237
238  static CheckFallThroughDiagnostics MakeForFunction(const Decl *Func) {
239    CheckFallThroughDiagnostics D;
240    D.FuncLoc = Func->getLocation();
241    D.diag_MaybeFallThrough_HasNoReturn =
242      diag::warn_falloff_noreturn_function;
243    D.diag_MaybeFallThrough_ReturnsNonVoid =
244      diag::warn_maybe_falloff_nonvoid_function;
245    D.diag_AlwaysFallThrough_HasNoReturn =
246      diag::warn_falloff_noreturn_function;
247    D.diag_AlwaysFallThrough_ReturnsNonVoid =
248      diag::warn_falloff_nonvoid_function;
249
250    // Don't suggest that virtual functions be marked "noreturn", since they
251    // might be overridden by non-noreturn functions.
252    bool isVirtualMethod = false;
253    if (const CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(Func))
254      isVirtualMethod = Method->isVirtual();
255
256    if (!isVirtualMethod)
257      D.diag_NeverFallThroughOrReturn =
258        diag::warn_suggest_noreturn_function;
259    else
260      D.diag_NeverFallThroughOrReturn = 0;
261
262    D.funMode = true;
263    return D;
264  }
265
266  static CheckFallThroughDiagnostics MakeForBlock() {
267    CheckFallThroughDiagnostics D;
268    D.diag_MaybeFallThrough_HasNoReturn =
269      diag::err_noreturn_block_has_return_expr;
270    D.diag_MaybeFallThrough_ReturnsNonVoid =
271      diag::err_maybe_falloff_nonvoid_block;
272    D.diag_AlwaysFallThrough_HasNoReturn =
273      diag::err_noreturn_block_has_return_expr;
274    D.diag_AlwaysFallThrough_ReturnsNonVoid =
275      diag::err_falloff_nonvoid_block;
276    D.diag_NeverFallThroughOrReturn =
277      diag::warn_suggest_noreturn_block;
278    D.funMode = false;
279    return D;
280  }
281
282  bool checkDiagnostics(Diagnostic &D, bool ReturnsVoid,
283                        bool HasNoReturn) const {
284    if (funMode) {
285      return (ReturnsVoid ||
286              D.getDiagnosticLevel(diag::warn_maybe_falloff_nonvoid_function,
287                                   FuncLoc) == Diagnostic::Ignored)
288        && (!HasNoReturn ||
289            D.getDiagnosticLevel(diag::warn_noreturn_function_has_return_expr,
290                                 FuncLoc) == Diagnostic::Ignored)
291        && (!ReturnsVoid ||
292            D.getDiagnosticLevel(diag::warn_suggest_noreturn_block, FuncLoc)
293              == Diagnostic::Ignored);
294    }
295
296    // For blocks.
297    return  ReturnsVoid && !HasNoReturn
298            && (!ReturnsVoid ||
299                D.getDiagnosticLevel(diag::warn_suggest_noreturn_block, FuncLoc)
300                  == Diagnostic::Ignored);
301  }
302};
303
304}
305
306/// CheckFallThroughForFunctionDef - Check that we don't fall off the end of a
307/// function that should return a value.  Check that we don't fall off the end
308/// of a noreturn function.  We assume that functions and blocks not marked
309/// noreturn will return.
310static void CheckFallThroughForBody(Sema &S, const Decl *D, const Stmt *Body,
311                                    const BlockExpr *blkExpr,
312                                    const CheckFallThroughDiagnostics& CD,
313                                    AnalysisContext &AC) {
314
315  bool ReturnsVoid = false;
316  bool HasNoReturn = false;
317
318  if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
319    ReturnsVoid = FD->getResultType()->isVoidType();
320    HasNoReturn = FD->hasAttr<NoReturnAttr>() ||
321       FD->getType()->getAs<FunctionType>()->getNoReturnAttr();
322  }
323  else if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D)) {
324    ReturnsVoid = MD->getResultType()->isVoidType();
325    HasNoReturn = MD->hasAttr<NoReturnAttr>();
326  }
327  else if (isa<BlockDecl>(D)) {
328    QualType BlockTy = blkExpr->getType();
329    if (const FunctionType *FT =
330          BlockTy->getPointeeType()->getAs<FunctionType>()) {
331      if (FT->getResultType()->isVoidType())
332        ReturnsVoid = true;
333      if (FT->getNoReturnAttr())
334        HasNoReturn = true;
335    }
336  }
337
338  Diagnostic &Diags = S.getDiagnostics();
339
340  // Short circuit for compilation speed.
341  if (CD.checkDiagnostics(Diags, ReturnsVoid, HasNoReturn))
342      return;
343
344  // FIXME: Function try block
345  if (const CompoundStmt *Compound = dyn_cast<CompoundStmt>(Body)) {
346    switch (CheckFallThrough(AC)) {
347      case UnknownFallThrough:
348        break;
349
350      case MaybeFallThrough:
351        if (HasNoReturn)
352          S.Diag(Compound->getRBracLoc(),
353                 CD.diag_MaybeFallThrough_HasNoReturn);
354        else if (!ReturnsVoid)
355          S.Diag(Compound->getRBracLoc(),
356                 CD.diag_MaybeFallThrough_ReturnsNonVoid);
357        break;
358      case AlwaysFallThrough:
359        if (HasNoReturn)
360          S.Diag(Compound->getRBracLoc(),
361                 CD.diag_AlwaysFallThrough_HasNoReturn);
362        else if (!ReturnsVoid)
363          S.Diag(Compound->getRBracLoc(),
364                 CD.diag_AlwaysFallThrough_ReturnsNonVoid);
365        break;
366      case NeverFallThroughOrReturn:
367        if (ReturnsVoid && !HasNoReturn && CD.diag_NeverFallThroughOrReturn)
368          S.Diag(Compound->getLBracLoc(),
369                 CD.diag_NeverFallThroughOrReturn);
370        break;
371      case NeverFallThrough:
372        break;
373    }
374  }
375}
376
377//===----------------------------------------------------------------------===//
378// -Wuninitialized
379//===----------------------------------------------------------------------===//
380
381namespace {
382/// ContainsReference - A visitor class to search for references to
383/// a particular declaration (the needle) within any evaluated component of an
384/// expression (recursively).
385class ContainsReference : public EvaluatedExprVisitor<ContainsReference> {
386  bool FoundReference;
387  const DeclRefExpr *Needle;
388
389public:
390  ContainsReference(ASTContext &Context, const DeclRefExpr *Needle)
391    : EvaluatedExprVisitor<ContainsReference>(Context),
392      FoundReference(false), Needle(Needle) {}
393
394  void VisitExpr(Expr *E) {
395    // Stop evaluating if we already have a reference.
396    if (FoundReference)
397      return;
398
399    EvaluatedExprVisitor<ContainsReference>::VisitExpr(E);
400  }
401
402  void VisitDeclRefExpr(DeclRefExpr *E) {
403    if (E == Needle)
404      FoundReference = true;
405    else
406      EvaluatedExprVisitor<ContainsReference>::VisitDeclRefExpr(E);
407  }
408
409  bool doesContainReference() const { return FoundReference; }
410};
411}
412
413typedef std::pair<const Expr*, bool> UninitUse;
414
415namespace {
416struct SLocSort {
417  bool operator()(const UninitUse &a, const UninitUse &b) {
418    SourceLocation aLoc = a.first->getLocStart();
419    SourceLocation bLoc = b.first->getLocStart();
420    return aLoc.getRawEncoding() < bLoc.getRawEncoding();
421  }
422};
423
424class UninitValsDiagReporter : public UninitVariablesHandler {
425  Sema &S;
426  typedef llvm::SmallVector<UninitUse, 2> UsesVec;
427  typedef llvm::DenseMap<const VarDecl *, UsesVec*> UsesMap;
428  UsesMap *uses;
429
430public:
431  UninitValsDiagReporter(Sema &S) : S(S), uses(0) {}
432  ~UninitValsDiagReporter() {
433    flushDiagnostics();
434  }
435
436  void handleUseOfUninitVariable(const Expr *ex, const VarDecl *vd,
437                                 bool isAlwaysUninit) {
438    if (!uses)
439      uses = new UsesMap();
440
441    UsesVec *&vec = (*uses)[vd];
442    if (!vec)
443      vec = new UsesVec();
444
445    vec->push_back(std::make_pair(ex, isAlwaysUninit));
446  }
447
448  void flushDiagnostics() {
449    if (!uses)
450      return;
451
452    for (UsesMap::iterator i = uses->begin(), e = uses->end(); i != e; ++i) {
453      const VarDecl *vd = i->first;
454      UsesVec *vec = i->second;
455
456      bool fixitIssued = false;
457
458      // Sort the uses by their SourceLocations.  While not strictly
459      // guaranteed to produce them in line/column order, this will provide
460      // a stable ordering.
461      std::sort(vec->begin(), vec->end(), SLocSort());
462
463      for (UsesVec::iterator vi = vec->begin(), ve = vec->end(); vi != ve; ++vi)
464      {
465        const bool isAlwaysUninit = vi->second;
466        bool isSelfInit = false;
467
468        if (const DeclRefExpr *dr = dyn_cast<DeclRefExpr>(vi->first)) {
469          if (isAlwaysUninit) {
470            // Inspect the initializer of the variable declaration which is
471            // being referenced prior to its initialization. We emit
472            // specialized diagnostics for self-initialization, and we
473            // specifically avoid warning about self references which take the
474            // form of:
475            //
476            //   int x = x;
477            //
478            // This is used to indicate to GCC that 'x' is intentionally left
479            // uninitialized. Proven code paths which access 'x' in
480            // an uninitialized state after this will still warn.
481            //
482            // TODO: Should we suppress maybe-uninitialized warnings for
483            // variables initialized in this way?
484            if (const Expr *E = vd->getInit()) {
485              if (dr == E->IgnoreParenImpCasts())
486                continue;
487
488              ContainsReference CR(S.Context, dr);
489              CR.Visit(const_cast<Expr*>(E));
490              isSelfInit = CR.doesContainReference();
491            }
492            if (isSelfInit) {
493              S.Diag(dr->getLocStart(),
494                     diag::warn_uninit_self_reference_in_init)
495              << vd->getDeclName() << vd->getLocation() << dr->getSourceRange();
496            } else {
497              S.Diag(dr->getLocStart(), diag::warn_uninit_var)
498                << vd->getDeclName() << dr->getSourceRange();
499            }
500          }
501          else {
502            S.Diag(dr->getLocStart(), diag::warn_maybe_uninit_var)
503              << vd->getDeclName() << dr->getSourceRange();
504          }
505        }
506        else {
507          const BlockExpr *be = cast<BlockExpr>(vi->first);
508          S.Diag(be->getLocStart(),
509                 isAlwaysUninit ? diag::warn_uninit_var_captured_by_block
510                                : diag::warn_maybe_uninit_var_captured_by_block)
511            << vd->getDeclName();
512        }
513
514        // Report where the variable was declared when the use wasn't within
515        // the initializer of that declaration.
516        if (!isSelfInit)
517          S.Diag(vd->getLocStart(), diag::note_uninit_var_def)
518            << vd->getDeclName();
519
520        // Only report the fixit once.
521        if (fixitIssued)
522          continue;
523
524        fixitIssued = true;
525
526        // Don't issue a fixit if there is already an initializer.
527        if (vd->getInit())
528          continue;
529
530        // Suggest possible initialization (if any).
531        const char *initialization = 0;
532        QualType vdTy = vd->getType().getCanonicalType();
533
534        if (vdTy->getAs<ObjCObjectPointerType>()) {
535          // Check if 'nil' is defined.
536          if (S.PP.getMacroInfo(&S.getASTContext().Idents.get("nil")))
537            initialization = " = nil";
538          else
539            initialization = " = 0";
540        }
541        else if (vdTy->isRealFloatingType())
542          initialization = " = 0.0";
543        else if (vdTy->isBooleanType() && S.Context.getLangOptions().CPlusPlus)
544          initialization = " = false";
545        else if (vdTy->isEnumeralType())
546          continue;
547        else if (vdTy->isScalarType())
548          initialization = " = 0";
549
550        if (initialization) {
551          SourceLocation loc = S.PP.getLocForEndOfToken(vd->getLocEnd());
552          S.Diag(loc, diag::note_var_fixit_add_initialization)
553            << FixItHint::CreateInsertion(loc, initialization);
554        }
555      }
556      delete vec;
557    }
558    delete uses;
559  }
560};
561}
562
563//===----------------------------------------------------------------------===//
564// AnalysisBasedWarnings - Worker object used by Sema to execute analysis-based
565//  warnings on a function, method, or block.
566//===----------------------------------------------------------------------===//
567
568clang::sema::AnalysisBasedWarnings::Policy::Policy() {
569  enableCheckFallThrough = 1;
570  enableCheckUnreachable = 0;
571}
572
573clang::sema::AnalysisBasedWarnings::AnalysisBasedWarnings(Sema &s) : S(s) {
574  Diagnostic &D = S.getDiagnostics();
575  DefaultPolicy.enableCheckUnreachable = (unsigned)
576    (D.getDiagnosticLevel(diag::warn_unreachable, SourceLocation()) !=
577        Diagnostic::Ignored);
578}
579
580static void flushDiagnostics(Sema &S, sema::FunctionScopeInfo *fscope) {
581  for (llvm::SmallVectorImpl<sema::PossiblyUnreachableDiag>::iterator
582       i = fscope->PossiblyUnreachableDiags.begin(),
583       e = fscope->PossiblyUnreachableDiags.end();
584       i != e; ++i) {
585    const sema::PossiblyUnreachableDiag &D = *i;
586    S.Diag(D.Loc, D.PD);
587  }
588}
589
590void clang::sema::
591AnalysisBasedWarnings::IssueWarnings(sema::AnalysisBasedWarnings::Policy P,
592                                     sema::FunctionScopeInfo *fscope,
593                                     const Decl *D, const BlockExpr *blkExpr) {
594
595  // We avoid doing analysis-based warnings when there are errors for
596  // two reasons:
597  // (1) The CFGs often can't be constructed (if the body is invalid), so
598  //     don't bother trying.
599  // (2) The code already has problems; running the analysis just takes more
600  //     time.
601  Diagnostic &Diags = S.getDiagnostics();
602
603  // Do not do any analysis for declarations in system headers if we are
604  // going to just ignore them.
605  if (Diags.getSuppressSystemWarnings() &&
606      S.SourceMgr.isInSystemHeader(D->getLocation()))
607    return;
608
609  // For code in dependent contexts, we'll do this at instantiation time.
610  if (cast<DeclContext>(D)->isDependentContext())
611    return;
612
613  if (Diags.hasErrorOccurred() || Diags.hasFatalErrorOccurred()) {
614    // Flush out any possibly unreachable diagnostics.
615    flushDiagnostics(S, fscope);
616    return;
617  }
618
619  const Stmt *Body = D->getBody();
620  assert(Body);
621
622  // Don't generate EH edges for CallExprs as we'd like to avoid the n^2
623  // explosion for destrutors that can result and the compile time hit.
624  AnalysisContext AC(D, 0, /*useUnoptimizedCFG=*/false, /*addehedges=*/false,
625                     /*addImplicitDtors=*/true, /*addInitializers=*/true);
626
627  // Emit delayed diagnostics.
628  if (!fscope->PossiblyUnreachableDiags.empty()) {
629    bool analyzed = false;
630
631    // Register the expressions with the CFGBuilder.
632    for (llvm::SmallVectorImpl<sema::PossiblyUnreachableDiag>::iterator
633         i = fscope->PossiblyUnreachableDiags.begin(),
634         e = fscope->PossiblyUnreachableDiags.end();
635         i != e; ++i) {
636      if (const Stmt *stmt = i->stmt)
637        AC.registerForcedBlockExpression(stmt);
638    }
639
640    if (AC.getCFG()) {
641      analyzed = true;
642      for (llvm::SmallVectorImpl<sema::PossiblyUnreachableDiag>::iterator
643            i = fscope->PossiblyUnreachableDiags.begin(),
644            e = fscope->PossiblyUnreachableDiags.end();
645            i != e; ++i)
646      {
647        const sema::PossiblyUnreachableDiag &D = *i;
648        bool processed = false;
649        if (const Stmt *stmt = i->stmt) {
650          const CFGBlock *block = AC.getBlockForRegisteredExpression(stmt);
651          assert(block);
652          if (CFGReverseBlockReachabilityAnalysis *cra = AC.getCFGReachablityAnalysis()) {
653            // Can this block be reached from the entrance?
654            if (cra->isReachable(&AC.getCFG()->getEntry(), block))
655              S.Diag(D.Loc, D.PD);
656            processed = true;
657          }
658        }
659        if (!processed) {
660          // Emit the warning anyway if we cannot map to a basic block.
661          S.Diag(D.Loc, D.PD);
662        }
663      }
664    }
665
666    if (!analyzed)
667      flushDiagnostics(S, fscope);
668  }
669
670
671  // Warning: check missing 'return'
672  if (P.enableCheckFallThrough) {
673    const CheckFallThroughDiagnostics &CD =
674      (isa<BlockDecl>(D) ? CheckFallThroughDiagnostics::MakeForBlock()
675                         : CheckFallThroughDiagnostics::MakeForFunction(D));
676    CheckFallThroughForBody(S, D, Body, blkExpr, CD, AC);
677  }
678
679  // Warning: check for unreachable code
680  if (P.enableCheckUnreachable)
681    CheckUnreachable(S, AC);
682
683  if (Diags.getDiagnosticLevel(diag::warn_uninit_var, D->getLocStart())
684      != Diagnostic::Ignored ||
685      Diags.getDiagnosticLevel(diag::warn_maybe_uninit_var, D->getLocStart())
686      != Diagnostic::Ignored) {
687    if (CFG *cfg = AC.getCFG()) {
688      UninitValsDiagReporter reporter(S);
689      runUninitializedVariablesAnalysis(*cast<DeclContext>(D), *cfg, AC,
690                                        reporter);
691    }
692  }
693}
694