AnalysisBasedWarnings.cpp revision d837c0dc361a000b951593eaaa80c46b73d15b1d
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      QualType calleeType = CEE->getType();
200      if (calleeType == AC.getASTContext().BoundMemberTy) {
201        calleeType = Expr::findBoundMemberType(CEE);
202        assert(!calleeType.isNull() && "analyzing unresolved call?");
203      }
204      if (getFunctionExtInfo(calleeType).getNoReturn()) {
205        NoReturnEdge = true;
206        HasFakeEdge = true;
207      } else if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(CEE)) {
208        ValueDecl *VD = DRE->getDecl();
209        if (VD->hasAttr<NoReturnAttr>()) {
210          NoReturnEdge = true;
211          HasFakeEdge = true;
212        }
213      }
214    }
215    // FIXME: Add noreturn message sends.
216    if (NoReturnEdge == false)
217      HasPlainEdge = true;
218  }
219  if (!HasPlainEdge) {
220    if (HasLiveReturn)
221      return NeverFallThrough;
222    return NeverFallThroughOrReturn;
223  }
224  if (HasAbnormalEdge || HasFakeEdge || HasLiveReturn)
225    return MaybeFallThrough;
226  // This says AlwaysFallThrough for calls to functions that are not marked
227  // noreturn, that don't return.  If people would like this warning to be more
228  // accurate, such functions should be marked as noreturn.
229  return AlwaysFallThrough;
230}
231
232namespace {
233
234struct CheckFallThroughDiagnostics {
235  unsigned diag_MaybeFallThrough_HasNoReturn;
236  unsigned diag_MaybeFallThrough_ReturnsNonVoid;
237  unsigned diag_AlwaysFallThrough_HasNoReturn;
238  unsigned diag_AlwaysFallThrough_ReturnsNonVoid;
239  unsigned diag_NeverFallThroughOrReturn;
240  bool funMode;
241  SourceLocation FuncLoc;
242
243  static CheckFallThroughDiagnostics MakeForFunction(const Decl *Func) {
244    CheckFallThroughDiagnostics D;
245    D.FuncLoc = Func->getLocation();
246    D.diag_MaybeFallThrough_HasNoReturn =
247      diag::warn_falloff_noreturn_function;
248    D.diag_MaybeFallThrough_ReturnsNonVoid =
249      diag::warn_maybe_falloff_nonvoid_function;
250    D.diag_AlwaysFallThrough_HasNoReturn =
251      diag::warn_falloff_noreturn_function;
252    D.diag_AlwaysFallThrough_ReturnsNonVoid =
253      diag::warn_falloff_nonvoid_function;
254
255    // Don't suggest that virtual functions be marked "noreturn", since they
256    // might be overridden by non-noreturn functions.
257    bool isVirtualMethod = false;
258    if (const CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(Func))
259      isVirtualMethod = Method->isVirtual();
260
261    if (!isVirtualMethod)
262      D.diag_NeverFallThroughOrReturn =
263        diag::warn_suggest_noreturn_function;
264    else
265      D.diag_NeverFallThroughOrReturn = 0;
266
267    D.funMode = true;
268    return D;
269  }
270
271  static CheckFallThroughDiagnostics MakeForBlock() {
272    CheckFallThroughDiagnostics D;
273    D.diag_MaybeFallThrough_HasNoReturn =
274      diag::err_noreturn_block_has_return_expr;
275    D.diag_MaybeFallThrough_ReturnsNonVoid =
276      diag::err_maybe_falloff_nonvoid_block;
277    D.diag_AlwaysFallThrough_HasNoReturn =
278      diag::err_noreturn_block_has_return_expr;
279    D.diag_AlwaysFallThrough_ReturnsNonVoid =
280      diag::err_falloff_nonvoid_block;
281    D.diag_NeverFallThroughOrReturn =
282      diag::warn_suggest_noreturn_block;
283    D.funMode = false;
284    return D;
285  }
286
287  bool checkDiagnostics(Diagnostic &D, bool ReturnsVoid,
288                        bool HasNoReturn) const {
289    if (funMode) {
290      return (ReturnsVoid ||
291              D.getDiagnosticLevel(diag::warn_maybe_falloff_nonvoid_function,
292                                   FuncLoc) == Diagnostic::Ignored)
293        && (!HasNoReturn ||
294            D.getDiagnosticLevel(diag::warn_noreturn_function_has_return_expr,
295                                 FuncLoc) == Diagnostic::Ignored)
296        && (!ReturnsVoid ||
297            D.getDiagnosticLevel(diag::warn_suggest_noreturn_block, FuncLoc)
298              == Diagnostic::Ignored);
299    }
300
301    // For blocks.
302    return  ReturnsVoid && !HasNoReturn
303            && (!ReturnsVoid ||
304                D.getDiagnosticLevel(diag::warn_suggest_noreturn_block, FuncLoc)
305                  == Diagnostic::Ignored);
306  }
307};
308
309}
310
311/// CheckFallThroughForFunctionDef - Check that we don't fall off the end of a
312/// function that should return a value.  Check that we don't fall off the end
313/// of a noreturn function.  We assume that functions and blocks not marked
314/// noreturn will return.
315static void CheckFallThroughForBody(Sema &S, const Decl *D, const Stmt *Body,
316                                    const BlockExpr *blkExpr,
317                                    const CheckFallThroughDiagnostics& CD,
318                                    AnalysisContext &AC) {
319
320  bool ReturnsVoid = false;
321  bool HasNoReturn = false;
322
323  if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
324    ReturnsVoid = FD->getResultType()->isVoidType();
325    HasNoReturn = FD->hasAttr<NoReturnAttr>() ||
326       FD->getType()->getAs<FunctionType>()->getNoReturnAttr();
327  }
328  else if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D)) {
329    ReturnsVoid = MD->getResultType()->isVoidType();
330    HasNoReturn = MD->hasAttr<NoReturnAttr>();
331  }
332  else if (isa<BlockDecl>(D)) {
333    QualType BlockTy = blkExpr->getType();
334    if (const FunctionType *FT =
335          BlockTy->getPointeeType()->getAs<FunctionType>()) {
336      if (FT->getResultType()->isVoidType())
337        ReturnsVoid = true;
338      if (FT->getNoReturnAttr())
339        HasNoReturn = true;
340    }
341  }
342
343  Diagnostic &Diags = S.getDiagnostics();
344
345  // Short circuit for compilation speed.
346  if (CD.checkDiagnostics(Diags, ReturnsVoid, HasNoReturn))
347      return;
348
349  // FIXME: Function try block
350  if (const CompoundStmt *Compound = dyn_cast<CompoundStmt>(Body)) {
351    switch (CheckFallThrough(AC)) {
352      case UnknownFallThrough:
353        break;
354
355      case MaybeFallThrough:
356        if (HasNoReturn)
357          S.Diag(Compound->getRBracLoc(),
358                 CD.diag_MaybeFallThrough_HasNoReturn);
359        else if (!ReturnsVoid)
360          S.Diag(Compound->getRBracLoc(),
361                 CD.diag_MaybeFallThrough_ReturnsNonVoid);
362        break;
363      case AlwaysFallThrough:
364        if (HasNoReturn)
365          S.Diag(Compound->getRBracLoc(),
366                 CD.diag_AlwaysFallThrough_HasNoReturn);
367        else if (!ReturnsVoid)
368          S.Diag(Compound->getRBracLoc(),
369                 CD.diag_AlwaysFallThrough_ReturnsNonVoid);
370        break;
371      case NeverFallThroughOrReturn:
372        if (ReturnsVoid && !HasNoReturn && CD.diag_NeverFallThroughOrReturn)
373          S.Diag(Compound->getLBracLoc(),
374                 CD.diag_NeverFallThroughOrReturn);
375        break;
376      case NeverFallThrough:
377        break;
378    }
379  }
380}
381
382//===----------------------------------------------------------------------===//
383// -Wuninitialized
384//===----------------------------------------------------------------------===//
385
386namespace {
387/// ContainsReference - A visitor class to search for references to
388/// a particular declaration (the needle) within any evaluated component of an
389/// expression (recursively).
390class ContainsReference : public EvaluatedExprVisitor<ContainsReference> {
391  bool FoundReference;
392  const DeclRefExpr *Needle;
393
394public:
395  ContainsReference(ASTContext &Context, const DeclRefExpr *Needle)
396    : EvaluatedExprVisitor<ContainsReference>(Context),
397      FoundReference(false), Needle(Needle) {}
398
399  void VisitExpr(Expr *E) {
400    // Stop evaluating if we already have a reference.
401    if (FoundReference)
402      return;
403
404    EvaluatedExprVisitor<ContainsReference>::VisitExpr(E);
405  }
406
407  void VisitDeclRefExpr(DeclRefExpr *E) {
408    if (E == Needle)
409      FoundReference = true;
410    else
411      EvaluatedExprVisitor<ContainsReference>::VisitDeclRefExpr(E);
412  }
413
414  bool doesContainReference() const { return FoundReference; }
415};
416}
417
418/// DiagnoseUninitializedUse -- Helper function for diagnosing uses of an
419/// uninitialized variable. This manages the different forms of diagnostic
420/// emitted for particular types of uses. Returns true if the use was diagnosed
421/// as a warning. If a pariticular use is one we omit warnings for, returns
422/// false.
423static bool DiagnoseUninitializedUse(Sema &S, const VarDecl *VD,
424                                     const Expr *E, bool isAlwaysUninit) {
425  bool isSelfInit = false;
426
427  if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E)) {
428    if (isAlwaysUninit) {
429      // Inspect the initializer of the variable declaration which is
430      // being referenced prior to its initialization. We emit
431      // specialized diagnostics for self-initialization, and we
432      // specifically avoid warning about self references which take the
433      // form of:
434      //
435      //   int x = x;
436      //
437      // This is used to indicate to GCC that 'x' is intentionally left
438      // uninitialized. Proven code paths which access 'x' in
439      // an uninitialized state after this will still warn.
440      //
441      // TODO: Should we suppress maybe-uninitialized warnings for
442      // variables initialized in this way?
443      if (const Expr *Initializer = VD->getInit()) {
444        if (DRE == Initializer->IgnoreParenImpCasts())
445          return false;
446
447        ContainsReference CR(S.Context, DRE);
448        CR.Visit(const_cast<Expr*>(Initializer));
449        isSelfInit = CR.doesContainReference();
450      }
451      if (isSelfInit) {
452        S.Diag(DRE->getLocStart(),
453               diag::warn_uninit_self_reference_in_init)
454        << VD->getDeclName() << VD->getLocation() << DRE->getSourceRange();
455      } else {
456        S.Diag(DRE->getLocStart(), diag::warn_uninit_var)
457          << VD->getDeclName() << DRE->getSourceRange();
458      }
459    } else {
460      S.Diag(DRE->getLocStart(), diag::warn_maybe_uninit_var)
461        << VD->getDeclName() << DRE->getSourceRange();
462    }
463  } else {
464    const BlockExpr *BE = cast<BlockExpr>(E);
465    S.Diag(BE->getLocStart(),
466           isAlwaysUninit ? diag::warn_uninit_var_captured_by_block
467                          : diag::warn_maybe_uninit_var_captured_by_block)
468      << VD->getDeclName();
469  }
470
471  // Report where the variable was declared when the use wasn't within
472  // the initializer of that declaration.
473  if (!isSelfInit)
474    S.Diag(VD->getLocStart(), diag::note_uninit_var_def)
475      << VD->getDeclName();
476
477  return true;
478}
479
480static void SuggestInitializationFixit(Sema &S, const VarDecl *VD) {
481  // Don't issue a fixit if there is already an initializer.
482  if (VD->getInit())
483    return;
484
485  // Suggest possible initialization (if any).
486  const char *initialization = 0;
487  QualType VariableTy = VD->getType().getCanonicalType();
488
489  if (VariableTy->isObjCObjectPointerType() ||
490      VariableTy->isBlockPointerType()) {
491    // Check if 'nil' is defined.
492    if (S.PP.getMacroInfo(&S.getASTContext().Idents.get("nil")))
493      initialization = " = nil";
494    else
495      initialization = " = 0";
496  }
497  else if (VariableTy->isRealFloatingType())
498    initialization = " = 0.0";
499  else if (VariableTy->isBooleanType() && S.Context.getLangOptions().CPlusPlus)
500    initialization = " = false";
501  else if (VariableTy->isEnumeralType())
502    return;
503  else if (VariableTy->isPointerType() || VariableTy->isMemberPointerType()) {
504    // Check if 'NULL' is defined.
505    if (S.PP.getMacroInfo(&S.getASTContext().Idents.get("NULL")))
506      initialization = " = NULL";
507    else
508      initialization = " = 0";
509  }
510  else if (VariableTy->isScalarType())
511    initialization = " = 0";
512
513  if (initialization) {
514    SourceLocation loc = S.PP.getLocForEndOfToken(VD->getLocEnd());
515    S.Diag(loc, diag::note_var_fixit_add_initialization)
516      << FixItHint::CreateInsertion(loc, initialization);
517  }
518}
519
520typedef std::pair<const Expr*, bool> UninitUse;
521
522namespace {
523struct SLocSort {
524  bool operator()(const UninitUse &a, const UninitUse &b) {
525    SourceLocation aLoc = a.first->getLocStart();
526    SourceLocation bLoc = b.first->getLocStart();
527    return aLoc.getRawEncoding() < bLoc.getRawEncoding();
528  }
529};
530
531class UninitValsDiagReporter : public UninitVariablesHandler {
532  Sema &S;
533  typedef llvm::SmallVector<UninitUse, 2> UsesVec;
534  typedef llvm::DenseMap<const VarDecl *, UsesVec*> UsesMap;
535  UsesMap *uses;
536
537public:
538  UninitValsDiagReporter(Sema &S) : S(S), uses(0) {}
539  ~UninitValsDiagReporter() {
540    flushDiagnostics();
541  }
542
543  void handleUseOfUninitVariable(const Expr *ex, const VarDecl *vd,
544                                 bool isAlwaysUninit) {
545    if (!uses)
546      uses = new UsesMap();
547
548    UsesVec *&vec = (*uses)[vd];
549    if (!vec)
550      vec = new UsesVec();
551
552    vec->push_back(std::make_pair(ex, isAlwaysUninit));
553  }
554
555  void flushDiagnostics() {
556    if (!uses)
557      return;
558
559    for (UsesMap::iterator i = uses->begin(), e = uses->end(); i != e; ++i) {
560      const VarDecl *vd = i->first;
561      UsesVec *vec = i->second;
562
563      // Sort the uses by their SourceLocations.  While not strictly
564      // guaranteed to produce them in line/column order, this will provide
565      // a stable ordering.
566      std::sort(vec->begin(), vec->end(), SLocSort());
567
568      for (UsesVec::iterator vi = vec->begin(), ve = vec->end(); vi != ve;
569           ++vi) {
570        if (!DiagnoseUninitializedUse(S, vd, vi->first,
571                                      /*isAlwaysUninit=*/vi->second))
572          continue;
573
574        SuggestInitializationFixit(S, vd);
575
576        // Skip further diagnostics for this variable. We try to warn only on
577        // the first point at which a variable is used uninitialized.
578        break;
579      }
580
581      delete vec;
582    }
583    delete uses;
584  }
585};
586}
587
588//===----------------------------------------------------------------------===//
589// AnalysisBasedWarnings - Worker object used by Sema to execute analysis-based
590//  warnings on a function, method, or block.
591//===----------------------------------------------------------------------===//
592
593clang::sema::AnalysisBasedWarnings::Policy::Policy() {
594  enableCheckFallThrough = 1;
595  enableCheckUnreachable = 0;
596}
597
598clang::sema::AnalysisBasedWarnings::AnalysisBasedWarnings(Sema &s)
599  : S(s),
600    NumFunctionsAnalyzed(0),
601    NumFunctionsWithBadCFGs(0),
602    NumCFGBlocks(0),
603    MaxCFGBlocksPerFunction(0),
604    NumUninitAnalysisFunctions(0),
605    NumUninitAnalysisVariables(0),
606    MaxUninitAnalysisVariablesPerFunction(0),
607    NumUninitAnalysisBlockVisits(0),
608    MaxUninitAnalysisBlockVisitsPerFunction(0) {
609  Diagnostic &D = S.getDiagnostics();
610  DefaultPolicy.enableCheckUnreachable = (unsigned)
611    (D.getDiagnosticLevel(diag::warn_unreachable, SourceLocation()) !=
612        Diagnostic::Ignored);
613}
614
615static void flushDiagnostics(Sema &S, sema::FunctionScopeInfo *fscope) {
616  for (llvm::SmallVectorImpl<sema::PossiblyUnreachableDiag>::iterator
617       i = fscope->PossiblyUnreachableDiags.begin(),
618       e = fscope->PossiblyUnreachableDiags.end();
619       i != e; ++i) {
620    const sema::PossiblyUnreachableDiag &D = *i;
621    S.Diag(D.Loc, D.PD);
622  }
623}
624
625void clang::sema::
626AnalysisBasedWarnings::IssueWarnings(sema::AnalysisBasedWarnings::Policy P,
627                                     sema::FunctionScopeInfo *fscope,
628                                     const Decl *D, const BlockExpr *blkExpr) {
629
630  // We avoid doing analysis-based warnings when there are errors for
631  // two reasons:
632  // (1) The CFGs often can't be constructed (if the body is invalid), so
633  //     don't bother trying.
634  // (2) The code already has problems; running the analysis just takes more
635  //     time.
636  Diagnostic &Diags = S.getDiagnostics();
637
638  // Do not do any analysis for declarations in system headers if we are
639  // going to just ignore them.
640  if (Diags.getSuppressSystemWarnings() &&
641      S.SourceMgr.isInSystemHeader(D->getLocation()))
642    return;
643
644  // For code in dependent contexts, we'll do this at instantiation time.
645  if (cast<DeclContext>(D)->isDependentContext())
646    return;
647
648  if (Diags.hasErrorOccurred() || Diags.hasFatalErrorOccurred()) {
649    // Flush out any possibly unreachable diagnostics.
650    flushDiagnostics(S, fscope);
651    return;
652  }
653
654  const Stmt *Body = D->getBody();
655  assert(Body);
656
657  AnalysisContext AC(D, 0);
658
659  // Don't generate EH edges for CallExprs as we'd like to avoid the n^2
660  // explosion for destrutors that can result and the compile time hit.
661  AC.getCFGBuildOptions().PruneTriviallyFalseEdges = true;
662  AC.getCFGBuildOptions().AddEHEdges = false;
663  AC.getCFGBuildOptions().AddInitializers = true;
664  AC.getCFGBuildOptions().AddImplicitDtors = true;
665
666  // Force that certain expressions appear as CFGElements in the CFG.  This
667  // is used to speed up various analyses.
668  // FIXME: This isn't the right factoring.  This is here for initial
669  // prototyping, but we need a way for analyses to say what expressions they
670  // expect to always be CFGElements and then fill in the BuildOptions
671  // appropriately.  This is essentially a layering violation.
672  AC.getCFGBuildOptions()
673    .setAlwaysAdd(Stmt::BinaryOperatorClass)
674    .setAlwaysAdd(Stmt::BlockExprClass)
675    .setAlwaysAdd(Stmt::CStyleCastExprClass)
676    .setAlwaysAdd(Stmt::DeclRefExprClass)
677    .setAlwaysAdd(Stmt::ImplicitCastExprClass)
678    .setAlwaysAdd(Stmt::UnaryOperatorClass);
679
680  // Construct the analysis context with the specified CFG build options.
681
682  // Emit delayed diagnostics.
683  if (!fscope->PossiblyUnreachableDiags.empty()) {
684    bool analyzed = false;
685
686    // Register the expressions with the CFGBuilder.
687    for (llvm::SmallVectorImpl<sema::PossiblyUnreachableDiag>::iterator
688         i = fscope->PossiblyUnreachableDiags.begin(),
689         e = fscope->PossiblyUnreachableDiags.end();
690         i != e; ++i) {
691      if (const Stmt *stmt = i->stmt)
692        AC.registerForcedBlockExpression(stmt);
693    }
694
695    if (AC.getCFG()) {
696      analyzed = true;
697      for (llvm::SmallVectorImpl<sema::PossiblyUnreachableDiag>::iterator
698            i = fscope->PossiblyUnreachableDiags.begin(),
699            e = fscope->PossiblyUnreachableDiags.end();
700            i != e; ++i)
701      {
702        const sema::PossiblyUnreachableDiag &D = *i;
703        bool processed = false;
704        if (const Stmt *stmt = i->stmt) {
705          const CFGBlock *block = AC.getBlockForRegisteredExpression(stmt);
706          assert(block);
707          if (CFGReverseBlockReachabilityAnalysis *cra = AC.getCFGReachablityAnalysis()) {
708            // Can this block be reached from the entrance?
709            if (cra->isReachable(&AC.getCFG()->getEntry(), block))
710              S.Diag(D.Loc, D.PD);
711            processed = true;
712          }
713        }
714        if (!processed) {
715          // Emit the warning anyway if we cannot map to a basic block.
716          S.Diag(D.Loc, D.PD);
717        }
718      }
719    }
720
721    if (!analyzed)
722      flushDiagnostics(S, fscope);
723  }
724
725
726  // Warning: check missing 'return'
727  if (P.enableCheckFallThrough) {
728    const CheckFallThroughDiagnostics &CD =
729      (isa<BlockDecl>(D) ? CheckFallThroughDiagnostics::MakeForBlock()
730                         : CheckFallThroughDiagnostics::MakeForFunction(D));
731    CheckFallThroughForBody(S, D, Body, blkExpr, CD, AC);
732  }
733
734  // Warning: check for unreachable code
735  if (P.enableCheckUnreachable)
736    CheckUnreachable(S, AC);
737
738  if (Diags.getDiagnosticLevel(diag::warn_uninit_var, D->getLocStart())
739      != Diagnostic::Ignored ||
740      Diags.getDiagnosticLevel(diag::warn_maybe_uninit_var, D->getLocStart())
741      != Diagnostic::Ignored) {
742    if (CFG *cfg = AC.getCFG()) {
743      UninitValsDiagReporter reporter(S);
744      UninitVariablesAnalysisStats stats;
745      std::memset(&stats, 0, sizeof(UninitVariablesAnalysisStats));
746      runUninitializedVariablesAnalysis(*cast<DeclContext>(D), *cfg, AC,
747                                        reporter, stats);
748
749      if (S.CollectStats && stats.NumVariablesAnalyzed > 0) {
750        ++NumUninitAnalysisFunctions;
751        NumUninitAnalysisVariables += stats.NumVariablesAnalyzed;
752        NumUninitAnalysisBlockVisits += stats.NumBlockVisits;
753        MaxUninitAnalysisVariablesPerFunction =
754            std::max(MaxUninitAnalysisVariablesPerFunction,
755                     stats.NumVariablesAnalyzed);
756        MaxUninitAnalysisBlockVisitsPerFunction =
757            std::max(MaxUninitAnalysisBlockVisitsPerFunction,
758                     stats.NumBlockVisits);
759      }
760    }
761  }
762
763  // Collect statistics about the CFG if it was built.
764  if (S.CollectStats && AC.isCFGBuilt()) {
765    ++NumFunctionsAnalyzed;
766    if (CFG *cfg = AC.getCFG()) {
767      // If we successfully built a CFG for this context, record some more
768      // detail information about it.
769      NumCFGBlocks += cfg->getNumBlockIDs();
770      MaxCFGBlocksPerFunction = std::max(MaxCFGBlocksPerFunction,
771                                         cfg->getNumBlockIDs());
772    } else {
773      ++NumFunctionsWithBadCFGs;
774    }
775  }
776}
777
778void clang::sema::AnalysisBasedWarnings::PrintStats() const {
779  llvm::errs() << "\n*** Analysis Based Warnings Stats:\n";
780
781  unsigned NumCFGsBuilt = NumFunctionsAnalyzed - NumFunctionsWithBadCFGs;
782  unsigned AvgCFGBlocksPerFunction =
783      !NumCFGsBuilt ? 0 : NumCFGBlocks/NumCFGsBuilt;
784  llvm::errs() << NumFunctionsAnalyzed << " functions analyzed ("
785               << NumFunctionsWithBadCFGs << " w/o CFGs).\n"
786               << "  " << NumCFGBlocks << " CFG blocks built.\n"
787               << "  " << AvgCFGBlocksPerFunction
788               << " average CFG blocks per function.\n"
789               << "  " << MaxCFGBlocksPerFunction
790               << " max CFG blocks per function.\n";
791
792  unsigned AvgUninitVariablesPerFunction = !NumUninitAnalysisFunctions ? 0
793      : NumUninitAnalysisVariables/NumUninitAnalysisFunctions;
794  unsigned AvgUninitBlockVisitsPerFunction = !NumUninitAnalysisFunctions ? 0
795      : NumUninitAnalysisBlockVisits/NumUninitAnalysisFunctions;
796  llvm::errs() << NumUninitAnalysisFunctions
797               << " functions analyzed for uninitialiazed variables\n"
798               << "  " << NumUninitAnalysisVariables << " variables analyzed.\n"
799               << "  " << AvgUninitVariablesPerFunction
800               << " average variables per function.\n"
801               << "  " << MaxUninitAnalysisVariablesPerFunction
802               << " max variables per function.\n"
803               << "  " << NumUninitAnalysisBlockVisits << " block visits.\n"
804               << "  " << AvgUninitBlockVisitsPerFunction
805               << " average block visits per function.\n"
806               << "  " << MaxUninitAnalysisBlockVisitsPerFunction
807               << " max block visits per function.\n";
808}
809