AnalysisBasedWarnings.cpp revision 2c0abf4ae33ab2ba690ccae724b8d6f196e7cfda
1dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek//=- AnalysisBasedWarnings.cpp - Sema warnings based on libAnalysis -*- C++ -*-=//
2dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek//
3dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek//                     The LLVM Compiler Infrastructure
4dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek//
5dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek// This file is distributed under the University of Illinois Open Source
6dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek// License. See LICENSE.TXT for details.
7dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek//
8dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek//===----------------------------------------------------------------------===//
9dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek//
10dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek// This file defines analysis_warnings::[Policy,Executor].
11dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek// Together they are used by Sema to issue warnings based on inexpensive
12dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek// static analysis algorithms in libAnalysis.
13dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek//
14dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek//===----------------------------------------------------------------------===//
15dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek
16e737f5041a36d0befb39ffeed8d50ba15916d3daDouglas Gregor#include "clang/Sema/AnalysisBasedWarnings.h"
172d88708cbe4e4ec5e04e4acb6bd7f5be68557379John McCall#include "clang/Sema/SemaInternal.h"
18351ba91eaa6d30e523587b2d7ed676a5172c6e56Ted Kremenek#include "clang/Sema/ScopeInfo.h"
19d068aabc484c4009282122c6ef26e66e68cfa044Ted Kremenek#include "clang/Basic/SourceManager.h"
2075f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski#include "clang/Basic/SourceLocation.h"
21fbb178a0b47fca1b0fb78c5d41198614cf52aa70Ted Kremenek#include "clang/Lex/Preprocessor.h"
227cd088e519d7e6caa4c4c12db52e0e4ae35d25c2John McCall#include "clang/AST/DeclObjC.h"
23384aff8b94bb0d1ad6c5667b90621e5699815bb2John McCall#include "clang/AST/DeclCXX.h"
24dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek#include "clang/AST/ExprObjC.h"
25dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek#include "clang/AST/ExprCXX.h"
26dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek#include "clang/AST/StmtObjC.h"
27dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek#include "clang/AST/StmtCXX.h"
286f41715df2c6a31c0c3ab3088b8cd18a3c8321b8Ted Kremenek#include "clang/AST/EvaluatedExprVisitor.h"
293ac1fbc303d22af2e11a14023ecee7bd7b7d0bfdCaitlin Sadowski#include "clang/AST/StmtVisitor.h"
30dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek#include "clang/Analysis/AnalysisContext.h"
31dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek#include "clang/Analysis/CFG.h"
32dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek#include "clang/Analysis/Analyses/ReachableCode.h"
33351ba91eaa6d30e523587b2d7ed676a5172c6e56Ted Kremenek#include "clang/Analysis/Analyses/CFGReachabilityAnalysis.h"
34402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski#include "clang/Analysis/Analyses/ThreadSafety.h"
35351ba91eaa6d30e523587b2d7ed676a5172c6e56Ted Kremenek#include "clang/Analysis/CFGStmtMap.h"
366f34213f8d6ae8c77685b53664527e39bfaaca3bTed Kremenek#include "clang/Analysis/Analyses/UninitializedValues.h"
37dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek#include "llvm/ADT/BitVector.h"
383ac1fbc303d22af2e11a14023ecee7bd7b7d0bfdCaitlin Sadowski#include "llvm/ADT/FoldingSet.h"
393ac1fbc303d22af2e11a14023ecee7bd7b7d0bfdCaitlin Sadowski#include "llvm/ADT/ImmutableMap.h"
403ac1fbc303d22af2e11a14023ecee7bd7b7d0bfdCaitlin Sadowski#include "llvm/ADT/PostOrderIterator.h"
413ac1fbc303d22af2e11a14023ecee7bd7b7d0bfdCaitlin Sadowski#include "llvm/ADT/SmallVector.h"
4275f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski#include "llvm/ADT/StringRef.h"
43dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek#include "llvm/Support/Casting.h"
443ac1fbc303d22af2e11a14023ecee7bd7b7d0bfdCaitlin Sadowski#include <algorithm>
453ac1fbc303d22af2e11a14023ecee7bd7b7d0bfdCaitlin Sadowski#include <vector>
46dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek
47dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenekusing namespace clang;
48dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek
49dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek//===----------------------------------------------------------------------===//
50dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek// Unreachable code analysis.
51dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek//===----------------------------------------------------------------------===//
52dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek
53dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremeneknamespace {
54dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek  class UnreachableCodeHandler : public reachable_code::Callback {
55dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek    Sema &S;
56dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek  public:
57dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek    UnreachableCodeHandler(Sema &s) : S(s) {}
58dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek
59dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek    void HandleUnreachable(SourceLocation L, SourceRange R1, SourceRange R2) {
60dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek      S.Diag(L, diag::warn_unreachable) << R1 << R2;
61dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek    }
62dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek  };
63dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek}
64dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek
65dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek/// CheckUnreachable - Check for unreachable code.
661d26f48dc2eea1c07431ca1519d7034a21b9bcffTed Kremenekstatic void CheckUnreachable(Sema &S, AnalysisDeclContext &AC) {
67dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek  UnreachableCodeHandler UC(S);
68dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek  reachable_code::FindUnreachableCode(AC, UC);
69dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek}
70dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek
71dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek//===----------------------------------------------------------------------===//
72dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek// Check for missing return value.
73dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek//===----------------------------------------------------------------------===//
74dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek
7516565aa95b086fb239baf82335dccc1b1ec93942John McCallenum ControlFlowKind {
7616565aa95b086fb239baf82335dccc1b1ec93942John McCall  UnknownFallThrough,
7716565aa95b086fb239baf82335dccc1b1ec93942John McCall  NeverFallThrough,
7816565aa95b086fb239baf82335dccc1b1ec93942John McCall  MaybeFallThrough,
7916565aa95b086fb239baf82335dccc1b1ec93942John McCall  AlwaysFallThrough,
8016565aa95b086fb239baf82335dccc1b1ec93942John McCall  NeverFallThroughOrReturn
8116565aa95b086fb239baf82335dccc1b1ec93942John McCall};
82dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek
83dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek/// CheckFallThrough - Check that we don't fall off the end of a
84dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek/// Statement that should return a value.
85dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek///
86dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek/// \returns AlwaysFallThrough iff we always fall off the end of the statement,
87dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek/// MaybeFallThrough iff we might or might not fall off the end,
88dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek/// NeverFallThroughOrReturn iff we never fall off the end of the statement or
89dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek/// return.  We assume NeverFallThrough iff we never fall off the end of the
90dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek/// statement but we may return.  We assume that functions not marked noreturn
91dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek/// will return.
921d26f48dc2eea1c07431ca1519d7034a21b9bcffTed Kremenekstatic ControlFlowKind CheckFallThrough(AnalysisDeclContext &AC) {
93dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek  CFG *cfg = AC.getCFG();
9416565aa95b086fb239baf82335dccc1b1ec93942John McCall  if (cfg == 0) return UnknownFallThrough;
95dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek
96dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek  // The CFG leaves in dead things, and we don't want the dead code paths to
97dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek  // confuse us, so we mark all live things first.
98dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek  llvm::BitVector live(cfg->getNumBlockIDs());
990f3b4ca1764cd6d457f511d340fba504f41763c3Ted Kremenek  unsigned count = reachable_code::ScanReachableFromBlock(&cfg->getEntry(),
100dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek                                                          live);
101dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek
102dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek  bool AddEHEdges = AC.getAddEHEdges();
103dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek  if (!AddEHEdges && count != cfg->getNumBlockIDs())
104dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek    // When there are things remaining dead, and we didn't add EH edges
105dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek    // from CallExprs to the catch clauses, we have to go back and
106dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek    // mark them as live.
107dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek    for (CFG::iterator I = cfg->begin(), E = cfg->end(); I != E; ++I) {
108dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek      CFGBlock &b = **I;
109dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek      if (!live[b.getBlockID()]) {
110dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek        if (b.pred_begin() == b.pred_end()) {
111dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek          if (b.getTerminator() && isa<CXXTryStmt>(b.getTerminator()))
112dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek            // When not adding EH edges from calls, catch clauses
113dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek            // can otherwise seem dead.  Avoid noting them as dead.
1140f3b4ca1764cd6d457f511d340fba504f41763c3Ted Kremenek            count += reachable_code::ScanReachableFromBlock(&b, live);
115dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek          continue;
116dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek        }
117dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek      }
118dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek    }
119dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek
120dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek  // Now we know what is live, we check the live precessors of the exit block
121dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek  // and look for fall through paths, being careful to ignore normal returns,
122dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek  // and exceptional paths.
123dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek  bool HasLiveReturn = false;
124dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek  bool HasFakeEdge = false;
125dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek  bool HasPlainEdge = false;
126dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek  bool HasAbnormalEdge = false;
12790b828aa279542559f655d1af666580288cb1841Ted Kremenek
12890b828aa279542559f655d1af666580288cb1841Ted Kremenek  // Ignore default cases that aren't likely to be reachable because all
12990b828aa279542559f655d1af666580288cb1841Ted Kremenek  // enums in a switch(X) have explicit case statements.
13090b828aa279542559f655d1af666580288cb1841Ted Kremenek  CFGBlock::FilterOptions FO;
13190b828aa279542559f655d1af666580288cb1841Ted Kremenek  FO.IgnoreDefaultsWithCoveredEnums = 1;
13290b828aa279542559f655d1af666580288cb1841Ted Kremenek
13390b828aa279542559f655d1af666580288cb1841Ted Kremenek  for (CFGBlock::filtered_pred_iterator
13490b828aa279542559f655d1af666580288cb1841Ted Kremenek	 I = cfg->getExit().filtered_pred_start_end(FO); I.hasMore(); ++I) {
13590b828aa279542559f655d1af666580288cb1841Ted Kremenek    const CFGBlock& B = **I;
136dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek    if (!live[B.getBlockID()])
137dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek      continue;
1385811f5978feaa7b89bd89e174fa7ad077b48413eTed Kremenek
139e05ee6df356c25e792b0334d7a4dec3fe4f79f07Chandler Carruth    // Skip blocks which contain an element marked as no-return. They don't
140e05ee6df356c25e792b0334d7a4dec3fe4f79f07Chandler Carruth    // represent actually viable edges into the exit block, so mark them as
141e05ee6df356c25e792b0334d7a4dec3fe4f79f07Chandler Carruth    // abnormal.
142e05ee6df356c25e792b0334d7a4dec3fe4f79f07Chandler Carruth    if (B.hasNoReturnElement()) {
143e05ee6df356c25e792b0334d7a4dec3fe4f79f07Chandler Carruth      HasAbnormalEdge = true;
144e05ee6df356c25e792b0334d7a4dec3fe4f79f07Chandler Carruth      continue;
145e05ee6df356c25e792b0334d7a4dec3fe4f79f07Chandler Carruth    }
146e05ee6df356c25e792b0334d7a4dec3fe4f79f07Chandler Carruth
1475811f5978feaa7b89bd89e174fa7ad077b48413eTed Kremenek    // Destructors can appear after the 'return' in the CFG.  This is
1485811f5978feaa7b89bd89e174fa7ad077b48413eTed Kremenek    // normal.  We need to look pass the destructors for the return
1495811f5978feaa7b89bd89e174fa7ad077b48413eTed Kremenek    // statement (if it exists).
1505811f5978feaa7b89bd89e174fa7ad077b48413eTed Kremenek    CFGBlock::const_reverse_iterator ri = B.rbegin(), re = B.rend();
151e05ee6df356c25e792b0334d7a4dec3fe4f79f07Chandler Carruth
152e05ee6df356c25e792b0334d7a4dec3fe4f79f07Chandler Carruth    for ( ; ri != re ; ++ri)
153e05ee6df356c25e792b0334d7a4dec3fe4f79f07Chandler Carruth      if (isa<CFGStmt>(*ri))
1545811f5978feaa7b89bd89e174fa7ad077b48413eTed Kremenek        break;
155e05ee6df356c25e792b0334d7a4dec3fe4f79f07Chandler Carruth
1565811f5978feaa7b89bd89e174fa7ad077b48413eTed Kremenek    // No more CFGElements in the block?
1575811f5978feaa7b89bd89e174fa7ad077b48413eTed Kremenek    if (ri == re) {
158dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek      if (B.getTerminator() && isa<CXXTryStmt>(B.getTerminator())) {
159dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek        HasAbnormalEdge = true;
160dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek        continue;
161dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek      }
162dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek      // A labeled empty statement, or the entry block...
163dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek      HasPlainEdge = true;
164dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek      continue;
165dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek    }
166f39e6a388aaa2f155b46c61e655784b2473218ebTed Kremenek
1675811f5978feaa7b89bd89e174fa7ad077b48413eTed Kremenek    CFGStmt CS = cast<CFGStmt>(*ri);
168f1d10d939739f1a4544926d807e4f0f9fb64be61Ted Kremenek    const Stmt *S = CS.getStmt();
169dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek    if (isa<ReturnStmt>(S)) {
170dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek      HasLiveReturn = true;
171dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek      continue;
172dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek    }
173dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek    if (isa<ObjCAtThrowStmt>(S)) {
174dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek      HasFakeEdge = true;
175dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek      continue;
176dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek    }
177dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek    if (isa<CXXThrowExpr>(S)) {
178dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek      HasFakeEdge = true;
179dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek      continue;
180dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek    }
181dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek    if (const AsmStmt *AS = dyn_cast<AsmStmt>(S)) {
182dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek      if (AS->isMSAsm()) {
183dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek        HasFakeEdge = true;
184dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek        HasLiveReturn = true;
185dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek        continue;
186dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek      }
187dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek    }
188dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek    if (isa<CXXTryStmt>(S)) {
189dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek      HasAbnormalEdge = true;
190dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek      continue;
191dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek    }
192e05ee6df356c25e792b0334d7a4dec3fe4f79f07Chandler Carruth    if (std::find(B.succ_begin(), B.succ_end(), &cfg->getExit())
193e05ee6df356c25e792b0334d7a4dec3fe4f79f07Chandler Carruth        == B.succ_end()) {
194e05ee6df356c25e792b0334d7a4dec3fe4f79f07Chandler Carruth      HasAbnormalEdge = true;
195e05ee6df356c25e792b0334d7a4dec3fe4f79f07Chandler Carruth      continue;
196dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek    }
197e05ee6df356c25e792b0334d7a4dec3fe4f79f07Chandler Carruth
198e05ee6df356c25e792b0334d7a4dec3fe4f79f07Chandler Carruth    HasPlainEdge = true;
199dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek  }
200dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek  if (!HasPlainEdge) {
201dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek    if (HasLiveReturn)
202dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek      return NeverFallThrough;
203dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek    return NeverFallThroughOrReturn;
204dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek  }
205dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek  if (HasAbnormalEdge || HasFakeEdge || HasLiveReturn)
206dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek    return MaybeFallThrough;
207dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek  // This says AlwaysFallThrough for calls to functions that are not marked
208dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek  // noreturn, that don't return.  If people would like this warning to be more
209dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek  // accurate, such functions should be marked as noreturn.
210dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek  return AlwaysFallThrough;
211dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek}
212dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek
2133c46e8db99196179b30e7ac5c20c4efd5f3926d7Dan Gohmannamespace {
2143c46e8db99196179b30e7ac5c20c4efd5f3926d7Dan Gohman
215dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenekstruct CheckFallThroughDiagnostics {
216dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek  unsigned diag_MaybeFallThrough_HasNoReturn;
217dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek  unsigned diag_MaybeFallThrough_ReturnsNonVoid;
218dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek  unsigned diag_AlwaysFallThrough_HasNoReturn;
219dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek  unsigned diag_AlwaysFallThrough_ReturnsNonVoid;
220dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek  unsigned diag_NeverFallThroughOrReturn;
221793cd1c4cdfaafc52e2c2ad9dae959befe4bb166Douglas Gregor  enum { Function, Block, Lambda } funMode;
2220827408865e32789e0ec4b8113a302ccdc531423Argyrios Kyrtzidis  SourceLocation FuncLoc;
223d064fdc4b7b64ca55b40b70490c79d6f569df78eTed Kremenek
224ca7eaeeed817001dc7cee4852a7e41f0982da1efDouglas Gregor  static CheckFallThroughDiagnostics MakeForFunction(const Decl *Func) {
225dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek    CheckFallThroughDiagnostics D;
2260827408865e32789e0ec4b8113a302ccdc531423Argyrios Kyrtzidis    D.FuncLoc = Func->getLocation();
227dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek    D.diag_MaybeFallThrough_HasNoReturn =
228dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek      diag::warn_falloff_noreturn_function;
229dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek    D.diag_MaybeFallThrough_ReturnsNonVoid =
230dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek      diag::warn_maybe_falloff_nonvoid_function;
231dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek    D.diag_AlwaysFallThrough_HasNoReturn =
232dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek      diag::warn_falloff_noreturn_function;
233dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek    D.diag_AlwaysFallThrough_ReturnsNonVoid =
234dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek      diag::warn_falloff_nonvoid_function;
235ca7eaeeed817001dc7cee4852a7e41f0982da1efDouglas Gregor
236ca7eaeeed817001dc7cee4852a7e41f0982da1efDouglas Gregor    // Don't suggest that virtual functions be marked "noreturn", since they
237ca7eaeeed817001dc7cee4852a7e41f0982da1efDouglas Gregor    // might be overridden by non-noreturn functions.
238ca7eaeeed817001dc7cee4852a7e41f0982da1efDouglas Gregor    bool isVirtualMethod = false;
239ca7eaeeed817001dc7cee4852a7e41f0982da1efDouglas Gregor    if (const CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(Func))
240ca7eaeeed817001dc7cee4852a7e41f0982da1efDouglas Gregor      isVirtualMethod = Method->isVirtual();
241ca7eaeeed817001dc7cee4852a7e41f0982da1efDouglas Gregor
242fcdd2cb2fdf35f806dd800b369fe0772a1c8c26cDouglas Gregor    // Don't suggest that template instantiations be marked "noreturn"
243fcdd2cb2fdf35f806dd800b369fe0772a1c8c26cDouglas Gregor    bool isTemplateInstantiation = false;
24475df4eeede7b91c22c1d63fafd4dd4142844e3b9Ted Kremenek    if (const FunctionDecl *Function = dyn_cast<FunctionDecl>(Func))
24575df4eeede7b91c22c1d63fafd4dd4142844e3b9Ted Kremenek      isTemplateInstantiation = Function->isTemplateInstantiation();
246fcdd2cb2fdf35f806dd800b369fe0772a1c8c26cDouglas Gregor
247fcdd2cb2fdf35f806dd800b369fe0772a1c8c26cDouglas Gregor    if (!isVirtualMethod && !isTemplateInstantiation)
248ca7eaeeed817001dc7cee4852a7e41f0982da1efDouglas Gregor      D.diag_NeverFallThroughOrReturn =
249ca7eaeeed817001dc7cee4852a7e41f0982da1efDouglas Gregor        diag::warn_suggest_noreturn_function;
250ca7eaeeed817001dc7cee4852a7e41f0982da1efDouglas Gregor    else
251ca7eaeeed817001dc7cee4852a7e41f0982da1efDouglas Gregor      D.diag_NeverFallThroughOrReturn = 0;
252ca7eaeeed817001dc7cee4852a7e41f0982da1efDouglas Gregor
253793cd1c4cdfaafc52e2c2ad9dae959befe4bb166Douglas Gregor    D.funMode = Function;
254dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek    return D;
255dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek  }
256d064fdc4b7b64ca55b40b70490c79d6f569df78eTed Kremenek
257dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek  static CheckFallThroughDiagnostics MakeForBlock() {
258dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek    CheckFallThroughDiagnostics D;
259dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek    D.diag_MaybeFallThrough_HasNoReturn =
260dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek      diag::err_noreturn_block_has_return_expr;
261dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek    D.diag_MaybeFallThrough_ReturnsNonVoid =
262dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek      diag::err_maybe_falloff_nonvoid_block;
263dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek    D.diag_AlwaysFallThrough_HasNoReturn =
264dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek      diag::err_noreturn_block_has_return_expr;
265dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek    D.diag_AlwaysFallThrough_ReturnsNonVoid =
266dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek      diag::err_falloff_nonvoid_block;
267dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek    D.diag_NeverFallThroughOrReturn =
268dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek      diag::warn_suggest_noreturn_block;
269793cd1c4cdfaafc52e2c2ad9dae959befe4bb166Douglas Gregor    D.funMode = Block;
270793cd1c4cdfaafc52e2c2ad9dae959befe4bb166Douglas Gregor    return D;
271793cd1c4cdfaafc52e2c2ad9dae959befe4bb166Douglas Gregor  }
272793cd1c4cdfaafc52e2c2ad9dae959befe4bb166Douglas Gregor
273793cd1c4cdfaafc52e2c2ad9dae959befe4bb166Douglas Gregor  static CheckFallThroughDiagnostics MakeForLambda() {
274793cd1c4cdfaafc52e2c2ad9dae959befe4bb166Douglas Gregor    CheckFallThroughDiagnostics D;
275793cd1c4cdfaafc52e2c2ad9dae959befe4bb166Douglas Gregor    D.diag_MaybeFallThrough_HasNoReturn =
276793cd1c4cdfaafc52e2c2ad9dae959befe4bb166Douglas Gregor      diag::err_noreturn_lambda_has_return_expr;
277793cd1c4cdfaafc52e2c2ad9dae959befe4bb166Douglas Gregor    D.diag_MaybeFallThrough_ReturnsNonVoid =
278793cd1c4cdfaafc52e2c2ad9dae959befe4bb166Douglas Gregor      diag::warn_maybe_falloff_nonvoid_lambda;
279793cd1c4cdfaafc52e2c2ad9dae959befe4bb166Douglas Gregor    D.diag_AlwaysFallThrough_HasNoReturn =
280793cd1c4cdfaafc52e2c2ad9dae959befe4bb166Douglas Gregor      diag::err_noreturn_lambda_has_return_expr;
281793cd1c4cdfaafc52e2c2ad9dae959befe4bb166Douglas Gregor    D.diag_AlwaysFallThrough_ReturnsNonVoid =
282793cd1c4cdfaafc52e2c2ad9dae959befe4bb166Douglas Gregor      diag::warn_falloff_nonvoid_lambda;
283793cd1c4cdfaafc52e2c2ad9dae959befe4bb166Douglas Gregor    D.diag_NeverFallThroughOrReturn = 0;
284793cd1c4cdfaafc52e2c2ad9dae959befe4bb166Douglas Gregor    D.funMode = Lambda;
285dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek    return D;
286dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek  }
287d064fdc4b7b64ca55b40b70490c79d6f569df78eTed Kremenek
288d6471f7c1921c7802804ce3ff6fe9768310f72b9David Blaikie  bool checkDiagnostics(DiagnosticsEngine &D, bool ReturnsVoid,
289dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek                        bool HasNoReturn) const {
290793cd1c4cdfaafc52e2c2ad9dae959befe4bb166Douglas Gregor    if (funMode == Function) {
2910827408865e32789e0ec4b8113a302ccdc531423Argyrios Kyrtzidis      return (ReturnsVoid ||
2920827408865e32789e0ec4b8113a302ccdc531423Argyrios Kyrtzidis              D.getDiagnosticLevel(diag::warn_maybe_falloff_nonvoid_function,
293d6471f7c1921c7802804ce3ff6fe9768310f72b9David Blaikie                                   FuncLoc) == DiagnosticsEngine::Ignored)
2940827408865e32789e0ec4b8113a302ccdc531423Argyrios Kyrtzidis        && (!HasNoReturn ||
2950827408865e32789e0ec4b8113a302ccdc531423Argyrios Kyrtzidis            D.getDiagnosticLevel(diag::warn_noreturn_function_has_return_expr,
296d6471f7c1921c7802804ce3ff6fe9768310f72b9David Blaikie                                 FuncLoc) == DiagnosticsEngine::Ignored)
2970827408865e32789e0ec4b8113a302ccdc531423Argyrios Kyrtzidis        && (!ReturnsVoid ||
2980827408865e32789e0ec4b8113a302ccdc531423Argyrios Kyrtzidis            D.getDiagnosticLevel(diag::warn_suggest_noreturn_block, FuncLoc)
299d6471f7c1921c7802804ce3ff6fe9768310f72b9David Blaikie              == DiagnosticsEngine::Ignored);
300dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek    }
301d064fdc4b7b64ca55b40b70490c79d6f569df78eTed Kremenek
302793cd1c4cdfaafc52e2c2ad9dae959befe4bb166Douglas Gregor    // For blocks / lambdas.
303793cd1c4cdfaafc52e2c2ad9dae959befe4bb166Douglas Gregor    return ReturnsVoid && !HasNoReturn
304793cd1c4cdfaafc52e2c2ad9dae959befe4bb166Douglas Gregor            && ((funMode == Lambda) ||
3050827408865e32789e0ec4b8113a302ccdc531423Argyrios Kyrtzidis                D.getDiagnosticLevel(diag::warn_suggest_noreturn_block, FuncLoc)
306d6471f7c1921c7802804ce3ff6fe9768310f72b9David Blaikie                  == DiagnosticsEngine::Ignored);
307dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek  }
308dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek};
309dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek
3103c46e8db99196179b30e7ac5c20c4efd5f3926d7Dan Gohman}
3113c46e8db99196179b30e7ac5c20c4efd5f3926d7Dan Gohman
312dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek/// CheckFallThroughForFunctionDef - Check that we don't fall off the end of a
313dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek/// function that should return a value.  Check that we don't fall off the end
314dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek/// of a noreturn function.  We assume that functions and blocks not marked
315dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek/// noreturn will return.
316dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenekstatic void CheckFallThroughForBody(Sema &S, const Decl *D, const Stmt *Body,
3173ed6fc08a9cd293d012fa49ab2a615e618d7c3faTed Kremenek                                    const BlockExpr *blkExpr,
318dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek                                    const CheckFallThroughDiagnostics& CD,
3191d26f48dc2eea1c07431ca1519d7034a21b9bcffTed Kremenek                                    AnalysisDeclContext &AC) {
320dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek
321dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek  bool ReturnsVoid = false;
322dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek  bool HasNoReturn = false;
323dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek
324dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek  if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
325dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek    ReturnsVoid = FD->getResultType()->isVoidType();
326dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek    HasNoReturn = FD->hasAttr<NoReturnAttr>() ||
327264ba48dc98f3f843935a485d5b086f7e0fdc4f1Rafael Espindola       FD->getType()->getAs<FunctionType>()->getNoReturnAttr();
328dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek  }
329dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek  else if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D)) {
330dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek    ReturnsVoid = MD->getResultType()->isVoidType();
331dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek    HasNoReturn = MD->hasAttr<NoReturnAttr>();
332dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek  }
333dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek  else if (isa<BlockDecl>(D)) {
3343ed6fc08a9cd293d012fa49ab2a615e618d7c3faTed Kremenek    QualType BlockTy = blkExpr->getType();
335d064fdc4b7b64ca55b40b70490c79d6f569df78eTed Kremenek    if (const FunctionType *FT =
336dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek          BlockTy->getPointeeType()->getAs<FunctionType>()) {
337dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek      if (FT->getResultType()->isVoidType())
338dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek        ReturnsVoid = true;
339dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek      if (FT->getNoReturnAttr())
340dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek        HasNoReturn = true;
341dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek    }
342dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek  }
343dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek
344d6471f7c1921c7802804ce3ff6fe9768310f72b9David Blaikie  DiagnosticsEngine &Diags = S.getDiagnostics();
345dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek
346dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek  // Short circuit for compilation speed.
347dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek  if (CD.checkDiagnostics(Diags, ReturnsVoid, HasNoReturn))
348dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek      return;
349d064fdc4b7b64ca55b40b70490c79d6f569df78eTed Kremenek
350dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek  // FIXME: Function try block
351dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek  if (const CompoundStmt *Compound = dyn_cast<CompoundStmt>(Body)) {
352dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek    switch (CheckFallThrough(AC)) {
35316565aa95b086fb239baf82335dccc1b1ec93942John McCall      case UnknownFallThrough:
35416565aa95b086fb239baf82335dccc1b1ec93942John McCall        break;
35516565aa95b086fb239baf82335dccc1b1ec93942John McCall
356dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek      case MaybeFallThrough:
357dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek        if (HasNoReturn)
358dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek          S.Diag(Compound->getRBracLoc(),
359dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek                 CD.diag_MaybeFallThrough_HasNoReturn);
360dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek        else if (!ReturnsVoid)
361dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek          S.Diag(Compound->getRBracLoc(),
362dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek                 CD.diag_MaybeFallThrough_ReturnsNonVoid);
363dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek        break;
364dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek      case AlwaysFallThrough:
365dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek        if (HasNoReturn)
366dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek          S.Diag(Compound->getRBracLoc(),
367dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek                 CD.diag_AlwaysFallThrough_HasNoReturn);
368dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek        else if (!ReturnsVoid)
369dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek          S.Diag(Compound->getRBracLoc(),
370dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek                 CD.diag_AlwaysFallThrough_ReturnsNonVoid);
371dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek        break;
372dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek      case NeverFallThroughOrReturn:
373b0656ec72e25e5c8e463c2dc39914636f0cb06d1Chandler Carruth        if (ReturnsVoid && !HasNoReturn && CD.diag_NeverFallThroughOrReturn) {
374b0656ec72e25e5c8e463c2dc39914636f0cb06d1Chandler Carruth          if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
375b0656ec72e25e5c8e463c2dc39914636f0cb06d1Chandler Carruth            S.Diag(Compound->getLBracLoc(), CD.diag_NeverFallThroughOrReturn)
376b3321093f6ead084427eb4a6621832fc4ee2f5deDouglas Gregor              << 0 << FD;
377b3321093f6ead084427eb4a6621832fc4ee2f5deDouglas Gregor          } else if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D)) {
378b3321093f6ead084427eb4a6621832fc4ee2f5deDouglas Gregor            S.Diag(Compound->getLBracLoc(), CD.diag_NeverFallThroughOrReturn)
379b3321093f6ead084427eb4a6621832fc4ee2f5deDouglas Gregor              << 1 << MD;
380b0656ec72e25e5c8e463c2dc39914636f0cb06d1Chandler Carruth          } else {
381b0656ec72e25e5c8e463c2dc39914636f0cb06d1Chandler Carruth            S.Diag(Compound->getLBracLoc(), CD.diag_NeverFallThroughOrReturn);
382b0656ec72e25e5c8e463c2dc39914636f0cb06d1Chandler Carruth          }
383b0656ec72e25e5c8e463c2dc39914636f0cb06d1Chandler Carruth        }
384dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek        break;
385dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek      case NeverFallThrough:
386dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek        break;
387dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek    }
388dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek  }
389dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek}
390dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek
391dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek//===----------------------------------------------------------------------===//
392610068c8cd2321f90e147b12cf794e1f840b6405Ted Kremenek// -Wuninitialized
393610068c8cd2321f90e147b12cf794e1f840b6405Ted Kremenek//===----------------------------------------------------------------------===//
394610068c8cd2321f90e147b12cf794e1f840b6405Ted Kremenek
3956f41715df2c6a31c0c3ab3088b8cd18a3c8321b8Ted Kremeneknamespace {
3969f6494687c05fe1d334af76408ee056b5f80e027Chandler Carruth/// ContainsReference - A visitor class to search for references to
3979f6494687c05fe1d334af76408ee056b5f80e027Chandler Carruth/// a particular declaration (the needle) within any evaluated component of an
3989f6494687c05fe1d334af76408ee056b5f80e027Chandler Carruth/// expression (recursively).
3996f41715df2c6a31c0c3ab3088b8cd18a3c8321b8Ted Kremenekclass ContainsReference : public EvaluatedExprVisitor<ContainsReference> {
4009f6494687c05fe1d334af76408ee056b5f80e027Chandler Carruth  bool FoundReference;
4019f6494687c05fe1d334af76408ee056b5f80e027Chandler Carruth  const DeclRefExpr *Needle;
4029f6494687c05fe1d334af76408ee056b5f80e027Chandler Carruth
4036f41715df2c6a31c0c3ab3088b8cd18a3c8321b8Ted Kremenekpublic:
4049f6494687c05fe1d334af76408ee056b5f80e027Chandler Carruth  ContainsReference(ASTContext &Context, const DeclRefExpr *Needle)
4059f6494687c05fe1d334af76408ee056b5f80e027Chandler Carruth    : EvaluatedExprVisitor<ContainsReference>(Context),
4069f6494687c05fe1d334af76408ee056b5f80e027Chandler Carruth      FoundReference(false), Needle(Needle) {}
4079f6494687c05fe1d334af76408ee056b5f80e027Chandler Carruth
4089f6494687c05fe1d334af76408ee056b5f80e027Chandler Carruth  void VisitExpr(Expr *E) {
4096f41715df2c6a31c0c3ab3088b8cd18a3c8321b8Ted Kremenek    // Stop evaluating if we already have a reference.
4109f6494687c05fe1d334af76408ee056b5f80e027Chandler Carruth    if (FoundReference)
4116f41715df2c6a31c0c3ab3088b8cd18a3c8321b8Ted Kremenek      return;
4129f6494687c05fe1d334af76408ee056b5f80e027Chandler Carruth
4139f6494687c05fe1d334af76408ee056b5f80e027Chandler Carruth    EvaluatedExprVisitor<ContainsReference>::VisitExpr(E);
4146f41715df2c6a31c0c3ab3088b8cd18a3c8321b8Ted Kremenek  }
4159f6494687c05fe1d334af76408ee056b5f80e027Chandler Carruth
4169f6494687c05fe1d334af76408ee056b5f80e027Chandler Carruth  void VisitDeclRefExpr(DeclRefExpr *E) {
4179f6494687c05fe1d334af76408ee056b5f80e027Chandler Carruth    if (E == Needle)
4189f6494687c05fe1d334af76408ee056b5f80e027Chandler Carruth      FoundReference = true;
4199f6494687c05fe1d334af76408ee056b5f80e027Chandler Carruth    else
4209f6494687c05fe1d334af76408ee056b5f80e027Chandler Carruth      EvaluatedExprVisitor<ContainsReference>::VisitDeclRefExpr(E);
4216f41715df2c6a31c0c3ab3088b8cd18a3c8321b8Ted Kremenek  }
4229f6494687c05fe1d334af76408ee056b5f80e027Chandler Carruth
4239f6494687c05fe1d334af76408ee056b5f80e027Chandler Carruth  bool doesContainReference() const { return FoundReference; }
4246f41715df2c6a31c0c3ab3088b8cd18a3c8321b8Ted Kremenek};
4256f41715df2c6a31c0c3ab3088b8cd18a3c8321b8Ted Kremenek}
4266f41715df2c6a31c0c3ab3088b8cd18a3c8321b8Ted Kremenek
4274f4f349208b2b2307454e169ac7b039e989f003fDavid Blaikiestatic bool SuggestInitializationFixit(Sema &S, const VarDecl *VD) {
428a34194f035096dd8dce10574e3a186da968aa211Fariborz Jahanian  QualType VariableTy = VD->getType().getCanonicalType();
429a34194f035096dd8dce10574e3a186da968aa211Fariborz Jahanian  if (VariableTy->isBlockPointerType() &&
430a34194f035096dd8dce10574e3a186da968aa211Fariborz Jahanian      !VD->hasAttr<BlocksAttr>()) {
431a34194f035096dd8dce10574e3a186da968aa211Fariborz Jahanian    S.Diag(VD->getLocation(), diag::note_block_var_fixit_add_initialization) << VD->getDeclName()
432a34194f035096dd8dce10574e3a186da968aa211Fariborz Jahanian    << FixItHint::CreateInsertion(VD->getLocation(), "__block ");
433a34194f035096dd8dce10574e3a186da968aa211Fariborz Jahanian    return true;
434a34194f035096dd8dce10574e3a186da968aa211Fariborz Jahanian  }
435a34194f035096dd8dce10574e3a186da968aa211Fariborz Jahanian
4364f4f349208b2b2307454e169ac7b039e989f003fDavid Blaikie  // Don't issue a fixit if there is already an initializer.
4374f4f349208b2b2307454e169ac7b039e989f003fDavid Blaikie  if (VD->getInit())
4384f4f349208b2b2307454e169ac7b039e989f003fDavid Blaikie    return false;
439a34194f035096dd8dce10574e3a186da968aa211Fariborz Jahanian
4404f4f349208b2b2307454e169ac7b039e989f003fDavid Blaikie  // Suggest possible initialization (if any).
4412c0abf4ae33ab2ba690ccae724b8d6f196e7cfdaDavid Blaikie  std::string Init = S.getFixItZeroInitializerForType(VariableTy);
4422c0abf4ae33ab2ba690ccae724b8d6f196e7cfdaDavid Blaikie  if (Init.empty())
4434f4f349208b2b2307454e169ac7b039e989f003fDavid Blaikie    return false;
4447984de35644701c0d94336da7f2215d4c26d9f5bRichard Smith  SourceLocation Loc = S.PP.getLocForEndOfToken(VD->getLocEnd());
445a34194f035096dd8dce10574e3a186da968aa211Fariborz Jahanian
4467984de35644701c0d94336da7f2215d4c26d9f5bRichard Smith  S.Diag(Loc, diag::note_var_fixit_add_initialization) << VD->getDeclName()
4477984de35644701c0d94336da7f2215d4c26d9f5bRichard Smith    << FixItHint::CreateInsertion(Loc, Init);
4487984de35644701c0d94336da7f2215d4c26d9f5bRichard Smith  return true;
4494f4f349208b2b2307454e169ac7b039e989f003fDavid Blaikie}
4504f4f349208b2b2307454e169ac7b039e989f003fDavid Blaikie
451262d50e1dcf529317da193ad585c11c16281a7acChandler Carruth/// DiagnoseUninitializedUse -- Helper function for diagnosing uses of an
452262d50e1dcf529317da193ad585c11c16281a7acChandler Carruth/// uninitialized variable. This manages the different forms of diagnostic
453262d50e1dcf529317da193ad585c11c16281a7acChandler Carruth/// emitted for particular types of uses. Returns true if the use was diagnosed
454262d50e1dcf529317da193ad585c11c16281a7acChandler Carruth/// as a warning. If a pariticular use is one we omit warnings for, returns
455262d50e1dcf529317da193ad585c11c16281a7acChandler Carruth/// false.
456262d50e1dcf529317da193ad585c11c16281a7acChandler Carruthstatic bool DiagnoseUninitializedUse(Sema &S, const VarDecl *VD,
4579e7617220135a6f6226cf09cb242cc1b905aedb4Ted Kremenek                                     const Expr *E, bool isAlwaysUninit,
4589e7617220135a6f6226cf09cb242cc1b905aedb4Ted Kremenek                                     bool alwaysReportSelfInit = false) {
4594c4983bbd2904670a25c840b07600f14efbafd7fChandler Carruth  bool isSelfInit = false;
4604c4983bbd2904670a25c840b07600f14efbafd7fChandler Carruth
4614c4983bbd2904670a25c840b07600f14efbafd7fChandler Carruth  if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E)) {
4624c4983bbd2904670a25c840b07600f14efbafd7fChandler Carruth    if (isAlwaysUninit) {
4634c4983bbd2904670a25c840b07600f14efbafd7fChandler Carruth      // Inspect the initializer of the variable declaration which is
4644c4983bbd2904670a25c840b07600f14efbafd7fChandler Carruth      // being referenced prior to its initialization. We emit
4654c4983bbd2904670a25c840b07600f14efbafd7fChandler Carruth      // specialized diagnostics for self-initialization, and we
4664c4983bbd2904670a25c840b07600f14efbafd7fChandler Carruth      // specifically avoid warning about self references which take the
4674c4983bbd2904670a25c840b07600f14efbafd7fChandler Carruth      // form of:
4684c4983bbd2904670a25c840b07600f14efbafd7fChandler Carruth      //
4694c4983bbd2904670a25c840b07600f14efbafd7fChandler Carruth      //   int x = x;
4704c4983bbd2904670a25c840b07600f14efbafd7fChandler Carruth      //
4714c4983bbd2904670a25c840b07600f14efbafd7fChandler Carruth      // This is used to indicate to GCC that 'x' is intentionally left
4724c4983bbd2904670a25c840b07600f14efbafd7fChandler Carruth      // uninitialized. Proven code paths which access 'x' in
4734c4983bbd2904670a25c840b07600f14efbafd7fChandler Carruth      // an uninitialized state after this will still warn.
4744c4983bbd2904670a25c840b07600f14efbafd7fChandler Carruth      //
4754c4983bbd2904670a25c840b07600f14efbafd7fChandler Carruth      // TODO: Should we suppress maybe-uninitialized warnings for
4764c4983bbd2904670a25c840b07600f14efbafd7fChandler Carruth      // variables initialized in this way?
4774c4983bbd2904670a25c840b07600f14efbafd7fChandler Carruth      if (const Expr *Initializer = VD->getInit()) {
4789e7617220135a6f6226cf09cb242cc1b905aedb4Ted Kremenek        if (!alwaysReportSelfInit && DRE == Initializer->IgnoreParenImpCasts())
479262d50e1dcf529317da193ad585c11c16281a7acChandler Carruth          return false;
4804c4983bbd2904670a25c840b07600f14efbafd7fChandler Carruth
4814c4983bbd2904670a25c840b07600f14efbafd7fChandler Carruth        ContainsReference CR(S.Context, DRE);
4824c4983bbd2904670a25c840b07600f14efbafd7fChandler Carruth        CR.Visit(const_cast<Expr*>(Initializer));
4834c4983bbd2904670a25c840b07600f14efbafd7fChandler Carruth        isSelfInit = CR.doesContainReference();
4844c4983bbd2904670a25c840b07600f14efbafd7fChandler Carruth      }
4854c4983bbd2904670a25c840b07600f14efbafd7fChandler Carruth      if (isSelfInit) {
4864c4983bbd2904670a25c840b07600f14efbafd7fChandler Carruth        S.Diag(DRE->getLocStart(),
4874c4983bbd2904670a25c840b07600f14efbafd7fChandler Carruth               diag::warn_uninit_self_reference_in_init)
4884c4983bbd2904670a25c840b07600f14efbafd7fChandler Carruth        << VD->getDeclName() << VD->getLocation() << DRE->getSourceRange();
4894c4983bbd2904670a25c840b07600f14efbafd7fChandler Carruth      } else {
4904c4983bbd2904670a25c840b07600f14efbafd7fChandler Carruth        S.Diag(DRE->getLocStart(), diag::warn_uninit_var)
4914c4983bbd2904670a25c840b07600f14efbafd7fChandler Carruth          << VD->getDeclName() << DRE->getSourceRange();
4924c4983bbd2904670a25c840b07600f14efbafd7fChandler Carruth      }
4934c4983bbd2904670a25c840b07600f14efbafd7fChandler Carruth    } else {
4944c4983bbd2904670a25c840b07600f14efbafd7fChandler Carruth      S.Diag(DRE->getLocStart(), diag::warn_maybe_uninit_var)
4954c4983bbd2904670a25c840b07600f14efbafd7fChandler Carruth        << VD->getDeclName() << DRE->getSourceRange();
4964c4983bbd2904670a25c840b07600f14efbafd7fChandler Carruth    }
4974c4983bbd2904670a25c840b07600f14efbafd7fChandler Carruth  } else {
4984c4983bbd2904670a25c840b07600f14efbafd7fChandler Carruth    const BlockExpr *BE = cast<BlockExpr>(E);
499a34194f035096dd8dce10574e3a186da968aa211Fariborz Jahanian    if (VD->getType()->isBlockPointerType() &&
500a34194f035096dd8dce10574e3a186da968aa211Fariborz Jahanian        !VD->hasAttr<BlocksAttr>())
501a34194f035096dd8dce10574e3a186da968aa211Fariborz Jahanian      S.Diag(BE->getLocStart(), diag::warn_uninit_byref_blockvar_captured_by_block)
502a34194f035096dd8dce10574e3a186da968aa211Fariborz Jahanian        << VD->getDeclName();
503a34194f035096dd8dce10574e3a186da968aa211Fariborz Jahanian    else
504a34194f035096dd8dce10574e3a186da968aa211Fariborz Jahanian      S.Diag(BE->getLocStart(),
505a34194f035096dd8dce10574e3a186da968aa211Fariborz Jahanian             isAlwaysUninit ? diag::warn_uninit_var_captured_by_block
506a34194f035096dd8dce10574e3a186da968aa211Fariborz Jahanian                            : diag::warn_maybe_uninit_var_captured_by_block)
507a34194f035096dd8dce10574e3a186da968aa211Fariborz Jahanian        << VD->getDeclName();
5084c4983bbd2904670a25c840b07600f14efbafd7fChandler Carruth  }
5094c4983bbd2904670a25c840b07600f14efbafd7fChandler Carruth
5104c4983bbd2904670a25c840b07600f14efbafd7fChandler Carruth  // Report where the variable was declared when the use wasn't within
5114f4f349208b2b2307454e169ac7b039e989f003fDavid Blaikie  // the initializer of that declaration & we didn't already suggest
5124f4f349208b2b2307454e169ac7b039e989f003fDavid Blaikie  // an initialization fixit.
5134f4f349208b2b2307454e169ac7b039e989f003fDavid Blaikie  if (!isSelfInit && !SuggestInitializationFixit(S, VD))
5144c4983bbd2904670a25c840b07600f14efbafd7fChandler Carruth    S.Diag(VD->getLocStart(), diag::note_uninit_var_def)
5154c4983bbd2904670a25c840b07600f14efbafd7fChandler Carruth      << VD->getDeclName();
5164c4983bbd2904670a25c840b07600f14efbafd7fChandler Carruth
517262d50e1dcf529317da193ad585c11c16281a7acChandler Carruth  return true;
51864fb959beb3a0ecb84a58e6ff82660a7a669f7b8Chandler Carruth}
51964fb959beb3a0ecb84a58e6ff82660a7a669f7b8Chandler Carruth
520f7bafc77ba12bb1beb665243a0334cd81e024728Ted Kremenektypedef std::pair<const Expr*, bool> UninitUse;
521f7bafc77ba12bb1beb665243a0334cd81e024728Ted Kremenek
522610068c8cd2321f90e147b12cf794e1f840b6405Ted Kremeneknamespace {
52394b1b4d785bc0f09f6af4be394e59d51f35dda60Ted Kremenekstruct SLocSort {
524f7bafc77ba12bb1beb665243a0334cd81e024728Ted Kremenek  bool operator()(const UninitUse &a, const UninitUse &b) {
525f7bafc77ba12bb1beb665243a0334cd81e024728Ted Kremenek    SourceLocation aLoc = a.first->getLocStart();
526f7bafc77ba12bb1beb665243a0334cd81e024728Ted Kremenek    SourceLocation bLoc = b.first->getLocStart();
52794b1b4d785bc0f09f6af4be394e59d51f35dda60Ted Kremenek    return aLoc.getRawEncoding() < bLoc.getRawEncoding();
52894b1b4d785bc0f09f6af4be394e59d51f35dda60Ted Kremenek  }
52994b1b4d785bc0f09f6af4be394e59d51f35dda60Ted Kremenek};
53094b1b4d785bc0f09f6af4be394e59d51f35dda60Ted Kremenek
531610068c8cd2321f90e147b12cf794e1f840b6405Ted Kremenekclass UninitValsDiagReporter : public UninitVariablesHandler {
532610068c8cd2321f90e147b12cf794e1f840b6405Ted Kremenek  Sema &S;
5335f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner  typedef SmallVector<UninitUse, 2> UsesVec;
5349e7617220135a6f6226cf09cb242cc1b905aedb4Ted Kremenek  typedef llvm::DenseMap<const VarDecl *, std::pair<UsesVec*, bool> > UsesMap;
53594b1b4d785bc0f09f6af4be394e59d51f35dda60Ted Kremenek  UsesMap *uses;
53694b1b4d785bc0f09f6af4be394e59d51f35dda60Ted Kremenek
537610068c8cd2321f90e147b12cf794e1f840b6405Ted Kremenekpublic:
53894b1b4d785bc0f09f6af4be394e59d51f35dda60Ted Kremenek  UninitValsDiagReporter(Sema &S) : S(S), uses(0) {}
53994b1b4d785bc0f09f6af4be394e59d51f35dda60Ted Kremenek  ~UninitValsDiagReporter() {
54094b1b4d785bc0f09f6af4be394e59d51f35dda60Ted Kremenek    flushDiagnostics();
54194b1b4d785bc0f09f6af4be394e59d51f35dda60Ted Kremenek  }
5429e7617220135a6f6226cf09cb242cc1b905aedb4Ted Kremenek
5439e7617220135a6f6226cf09cb242cc1b905aedb4Ted Kremenek  std::pair<UsesVec*, bool> &getUses(const VarDecl *vd) {
54494b1b4d785bc0f09f6af4be394e59d51f35dda60Ted Kremenek    if (!uses)
54594b1b4d785bc0f09f6af4be394e59d51f35dda60Ted Kremenek      uses = new UsesMap();
5469e7617220135a6f6226cf09cb242cc1b905aedb4Ted Kremenek
5479e7617220135a6f6226cf09cb242cc1b905aedb4Ted Kremenek    UsesMap::mapped_type &V = (*uses)[vd];
5489e7617220135a6f6226cf09cb242cc1b905aedb4Ted Kremenek    UsesVec *&vec = V.first;
54994b1b4d785bc0f09f6af4be394e59d51f35dda60Ted Kremenek    if (!vec)
55094b1b4d785bc0f09f6af4be394e59d51f35dda60Ted Kremenek      vec = new UsesVec();
55194b1b4d785bc0f09f6af4be394e59d51f35dda60Ted Kremenek
5529e7617220135a6f6226cf09cb242cc1b905aedb4Ted Kremenek    return V;
5539e7617220135a6f6226cf09cb242cc1b905aedb4Ted Kremenek  }
5549e7617220135a6f6226cf09cb242cc1b905aedb4Ted Kremenek
5559e7617220135a6f6226cf09cb242cc1b905aedb4Ted Kremenek  void handleUseOfUninitVariable(const Expr *ex, const VarDecl *vd,
5569e7617220135a6f6226cf09cb242cc1b905aedb4Ted Kremenek                                 bool isAlwaysUninit) {
5579e7617220135a6f6226cf09cb242cc1b905aedb4Ted Kremenek    getUses(vd).first->push_back(std::make_pair(ex, isAlwaysUninit));
5589e7617220135a6f6226cf09cb242cc1b905aedb4Ted Kremenek  }
5599e7617220135a6f6226cf09cb242cc1b905aedb4Ted Kremenek
5609e7617220135a6f6226cf09cb242cc1b905aedb4Ted Kremenek  void handleSelfInit(const VarDecl *vd) {
5619e7617220135a6f6226cf09cb242cc1b905aedb4Ted Kremenek    getUses(vd).second = true;
56294b1b4d785bc0f09f6af4be394e59d51f35dda60Ted Kremenek  }
56394b1b4d785bc0f09f6af4be394e59d51f35dda60Ted Kremenek
56494b1b4d785bc0f09f6af4be394e59d51f35dda60Ted Kremenek  void flushDiagnostics() {
56594b1b4d785bc0f09f6af4be394e59d51f35dda60Ted Kremenek    if (!uses)
56694b1b4d785bc0f09f6af4be394e59d51f35dda60Ted Kremenek      return;
567609e3170841dac81c3b7b6b9eccb9c520e42c9b2Ted Kremenek
56894b1b4d785bc0f09f6af4be394e59d51f35dda60Ted Kremenek    for (UsesMap::iterator i = uses->begin(), e = uses->end(); i != e; ++i) {
56994b1b4d785bc0f09f6af4be394e59d51f35dda60Ted Kremenek      const VarDecl *vd = i->first;
5709e7617220135a6f6226cf09cb242cc1b905aedb4Ted Kremenek      const UsesMap::mapped_type &V = i->second;
5719e7617220135a6f6226cf09cb242cc1b905aedb4Ted Kremenek
5729e7617220135a6f6226cf09cb242cc1b905aedb4Ted Kremenek      UsesVec *vec = V.first;
5739e7617220135a6f6226cf09cb242cc1b905aedb4Ted Kremenek      bool hasSelfInit = V.second;
5749e7617220135a6f6226cf09cb242cc1b905aedb4Ted Kremenek
5759e7617220135a6f6226cf09cb242cc1b905aedb4Ted Kremenek      // Specially handle the case where we have uses of an uninitialized
5769e7617220135a6f6226cf09cb242cc1b905aedb4Ted Kremenek      // variable, but the root cause is an idiomatic self-init.  We want
5779e7617220135a6f6226cf09cb242cc1b905aedb4Ted Kremenek      // to report the diagnostic at the self-init since that is the root cause.
5780d381810da19dd7677b9a79fca516d298fa5addbMatt Beaumont-Gay      if (!vec->empty() && hasSelfInit && hasAlwaysUninitializedUse(vec))
5799e7617220135a6f6226cf09cb242cc1b905aedb4Ted Kremenek        DiagnoseUninitializedUse(S, vd, vd->getInit()->IgnoreParenCasts(),
5800d381810da19dd7677b9a79fca516d298fa5addbMatt Beaumont-Gay                                 /* isAlwaysUninit */ true,
5810d381810da19dd7677b9a79fca516d298fa5addbMatt Beaumont-Gay                                 /* alwaysReportSelfInit */ true);
5829e7617220135a6f6226cf09cb242cc1b905aedb4Ted Kremenek      else {
5839e7617220135a6f6226cf09cb242cc1b905aedb4Ted Kremenek        // Sort the uses by their SourceLocations.  While not strictly
5849e7617220135a6f6226cf09cb242cc1b905aedb4Ted Kremenek        // guaranteed to produce them in line/column order, this will provide
5859e7617220135a6f6226cf09cb242cc1b905aedb4Ted Kremenek        // a stable ordering.
5869e7617220135a6f6226cf09cb242cc1b905aedb4Ted Kremenek        std::sort(vec->begin(), vec->end(), SLocSort());
5879e7617220135a6f6226cf09cb242cc1b905aedb4Ted Kremenek
5889e7617220135a6f6226cf09cb242cc1b905aedb4Ted Kremenek        for (UsesVec::iterator vi = vec->begin(), ve = vec->end(); vi != ve;
5899e7617220135a6f6226cf09cb242cc1b905aedb4Ted Kremenek             ++vi) {
5909e7617220135a6f6226cf09cb242cc1b905aedb4Ted Kremenek          if (DiagnoseUninitializedUse(S, vd, vi->first,
5919e7617220135a6f6226cf09cb242cc1b905aedb4Ted Kremenek                                        /*isAlwaysUninit=*/vi->second))
5929e7617220135a6f6226cf09cb242cc1b905aedb4Ted Kremenek            // Skip further diagnostics for this variable. We try to warn only
5939e7617220135a6f6226cf09cb242cc1b905aedb4Ted Kremenek            // on the first point at which a variable is used uninitialized.
5949e7617220135a6f6226cf09cb242cc1b905aedb4Ted Kremenek            break;
5959e7617220135a6f6226cf09cb242cc1b905aedb4Ted Kremenek        }
59664fb959beb3a0ecb84a58e6ff82660a7a669f7b8Chandler Carruth      }
5979e7617220135a6f6226cf09cb242cc1b905aedb4Ted Kremenek
5989e7617220135a6f6226cf09cb242cc1b905aedb4Ted Kremenek      // Release the uses vector.
59994b1b4d785bc0f09f6af4be394e59d51f35dda60Ted Kremenek      delete vec;
60094b1b4d785bc0f09f6af4be394e59d51f35dda60Ted Kremenek    }
60194b1b4d785bc0f09f6af4be394e59d51f35dda60Ted Kremenek    delete uses;
602610068c8cd2321f90e147b12cf794e1f840b6405Ted Kremenek  }
6030d381810da19dd7677b9a79fca516d298fa5addbMatt Beaumont-Gay
6040d381810da19dd7677b9a79fca516d298fa5addbMatt Beaumont-Gayprivate:
6050d381810da19dd7677b9a79fca516d298fa5addbMatt Beaumont-Gay  static bool hasAlwaysUninitializedUse(const UsesVec* vec) {
6060d381810da19dd7677b9a79fca516d298fa5addbMatt Beaumont-Gay  for (UsesVec::const_iterator i = vec->begin(), e = vec->end(); i != e; ++i) {
6070d381810da19dd7677b9a79fca516d298fa5addbMatt Beaumont-Gay    if (i->second) {
6080d381810da19dd7677b9a79fca516d298fa5addbMatt Beaumont-Gay      return true;
6090d381810da19dd7677b9a79fca516d298fa5addbMatt Beaumont-Gay    }
6100d381810da19dd7677b9a79fca516d298fa5addbMatt Beaumont-Gay  }
6110d381810da19dd7677b9a79fca516d298fa5addbMatt Beaumont-Gay  return false;
6120d381810da19dd7677b9a79fca516d298fa5addbMatt Beaumont-Gay}
613610068c8cd2321f90e147b12cf794e1f840b6405Ted Kremenek};
614610068c8cd2321f90e147b12cf794e1f840b6405Ted Kremenek}
615610068c8cd2321f90e147b12cf794e1f840b6405Ted Kremenek
6163ac1fbc303d22af2e11a14023ecee7bd7b7d0bfdCaitlin Sadowski
6173ac1fbc303d22af2e11a14023ecee7bd7b7d0bfdCaitlin Sadowski//===----------------------------------------------------------------------===//
6183ac1fbc303d22af2e11a14023ecee7bd7b7d0bfdCaitlin Sadowski// -Wthread-safety
6193ac1fbc303d22af2e11a14023ecee7bd7b7d0bfdCaitlin Sadowski//===----------------------------------------------------------------------===//
62075f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowskinamespace clang {
62175f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowskinamespace thread_safety {
6222e5156274b8051217565b557bfa14c80f7990e9cRichard Smithtypedef llvm::SmallVector<PartialDiagnosticAt, 1> OptionalNotes;
6232e5156274b8051217565b557bfa14c80f7990e9cRichard Smithtypedef std::pair<PartialDiagnosticAt, OptionalNotes> DelayedDiag;
624ecafd309b3ed2ffc6f8ae7eecd1e7eae84b26f81Benjamin Kramertypedef std::list<DelayedDiag> DiagList;
62575f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski
62675f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowskistruct SortDiagBySourceLocation {
627ecafd309b3ed2ffc6f8ae7eecd1e7eae84b26f81Benjamin Kramer  SourceManager &SM;
628ecafd309b3ed2ffc6f8ae7eecd1e7eae84b26f81Benjamin Kramer  SortDiagBySourceLocation(SourceManager &SM) : SM(SM) {}
62975f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski
63075f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski  bool operator()(const DelayedDiag &left, const DelayedDiag &right) {
63175f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski    // Although this call will be slow, this is only called when outputting
63275f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski    // multiple warnings.
633ecafd309b3ed2ffc6f8ae7eecd1e7eae84b26f81Benjamin Kramer    return SM.isBeforeInTranslationUnit(left.first.first, right.first.first);
63475f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski  }
63575f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski};
63675f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski
63799ba9e3bd70671f3441fb974895f226a83ce0e66David Blaikienamespace {
63875f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowskiclass ThreadSafetyReporter : public clang::thread_safety::ThreadSafetyHandler {
63975f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski  Sema &S;
64075f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski  DiagList Warnings;
6412e5156274b8051217565b557bfa14c80f7990e9cRichard Smith  SourceLocation FunLocation, FunEndLocation;
64275f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski
64375f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski  // Helper functions
64475f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski  void warnLockMismatch(unsigned DiagID, Name LockName, SourceLocation Loc) {
645f1ac63702143d84db778d32eb185a77fc97db5f5DeLesley Hutchins    // Gracefully handle rare cases when the analysis can't get a more
646f1ac63702143d84db778d32eb185a77fc97db5f5DeLesley Hutchins    // precise source location.
647f1ac63702143d84db778d32eb185a77fc97db5f5DeLesley Hutchins    if (!Loc.isValid())
648f1ac63702143d84db778d32eb185a77fc97db5f5DeLesley Hutchins      Loc = FunLocation;
6492e5156274b8051217565b557bfa14c80f7990e9cRichard Smith    PartialDiagnosticAt Warning(Loc, S.PDiag(DiagID) << LockName);
6502e5156274b8051217565b557bfa14c80f7990e9cRichard Smith    Warnings.push_back(DelayedDiag(Warning, OptionalNotes()));
65175f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski  }
65275f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski
65375f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski public:
6542e5156274b8051217565b557bfa14c80f7990e9cRichard Smith  ThreadSafetyReporter(Sema &S, SourceLocation FL, SourceLocation FEL)
6552e5156274b8051217565b557bfa14c80f7990e9cRichard Smith    : S(S), FunLocation(FL), FunEndLocation(FEL) {}
65675f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski
65775f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski  /// \brief Emit all buffered diagnostics in order of sourcelocation.
65875f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski  /// We need to output diagnostics produced while iterating through
65975f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski  /// the lockset in deterministic order, so this function orders diagnostics
66075f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski  /// and outputs them.
66175f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski  void emitDiagnostics() {
662ecafd309b3ed2ffc6f8ae7eecd1e7eae84b26f81Benjamin Kramer    Warnings.sort(SortDiagBySourceLocation(S.getSourceManager()));
66375f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski    for (DiagList::iterator I = Warnings.begin(), E = Warnings.end();
6642e5156274b8051217565b557bfa14c80f7990e9cRichard Smith         I != E; ++I) {
6652e5156274b8051217565b557bfa14c80f7990e9cRichard Smith      S.Diag(I->first.first, I->first.second);
6662e5156274b8051217565b557bfa14c80f7990e9cRichard Smith      const OptionalNotes &Notes = I->second;
6672e5156274b8051217565b557bfa14c80f7990e9cRichard Smith      for (unsigned NoteI = 0, NoteN = Notes.size(); NoteI != NoteN; ++NoteI)
6682e5156274b8051217565b557bfa14c80f7990e9cRichard Smith        S.Diag(Notes[NoteI].first, Notes[NoteI].second);
6692e5156274b8051217565b557bfa14c80f7990e9cRichard Smith    }
67075f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski  }
67175f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski
67299107ebc0a5aea953b736e12757e0919d5249d43Caitlin Sadowski  void handleInvalidLockExp(SourceLocation Loc) {
6732e5156274b8051217565b557bfa14c80f7990e9cRichard Smith    PartialDiagnosticAt Warning(Loc,
6742e5156274b8051217565b557bfa14c80f7990e9cRichard Smith                                S.PDiag(diag::warn_cannot_resolve_lock) << Loc);
6752e5156274b8051217565b557bfa14c80f7990e9cRichard Smith    Warnings.push_back(DelayedDiag(Warning, OptionalNotes()));
67699107ebc0a5aea953b736e12757e0919d5249d43Caitlin Sadowski  }
67775f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski  void handleUnmatchedUnlock(Name LockName, SourceLocation Loc) {
67875f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski    warnLockMismatch(diag::warn_unlock_but_no_lock, LockName, Loc);
67975f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski  }
68075f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski
68175f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski  void handleDoubleLock(Name LockName, SourceLocation Loc) {
68275f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski    warnLockMismatch(diag::warn_double_lock, LockName, Loc);
68375f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski  }
68475f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski
6852e5156274b8051217565b557bfa14c80f7990e9cRichard Smith  void handleMutexHeldEndOfScope(Name LockName, SourceLocation LocLocked,
6862e5156274b8051217565b557bfa14c80f7990e9cRichard Smith                                 SourceLocation LocEndOfScope,
6874e4bc75d3570835e13183c66ac08974cdc016007Caitlin Sadowski                                 LockErrorKind LEK){
6884e4bc75d3570835e13183c66ac08974cdc016007Caitlin Sadowski    unsigned DiagID = 0;
6894e4bc75d3570835e13183c66ac08974cdc016007Caitlin Sadowski    switch (LEK) {
6904e4bc75d3570835e13183c66ac08974cdc016007Caitlin Sadowski      case LEK_LockedSomePredecessors:
6912e5156274b8051217565b557bfa14c80f7990e9cRichard Smith        DiagID = diag::warn_lock_some_predecessors;
6924e4bc75d3570835e13183c66ac08974cdc016007Caitlin Sadowski        break;
6934e4bc75d3570835e13183c66ac08974cdc016007Caitlin Sadowski      case LEK_LockedSomeLoopIterations:
6944e4bc75d3570835e13183c66ac08974cdc016007Caitlin Sadowski        DiagID = diag::warn_expecting_lock_held_on_loop;
6954e4bc75d3570835e13183c66ac08974cdc016007Caitlin Sadowski        break;
6964e4bc75d3570835e13183c66ac08974cdc016007Caitlin Sadowski      case LEK_LockedAtEndOfFunction:
6974e4bc75d3570835e13183c66ac08974cdc016007Caitlin Sadowski        DiagID = diag::warn_no_unlock;
6984e4bc75d3570835e13183c66ac08974cdc016007Caitlin Sadowski        break;
6994e4bc75d3570835e13183c66ac08974cdc016007Caitlin Sadowski    }
7002e5156274b8051217565b557bfa14c80f7990e9cRichard Smith    if (LocEndOfScope.isInvalid())
7012e5156274b8051217565b557bfa14c80f7990e9cRichard Smith      LocEndOfScope = FunEndLocation;
7022e5156274b8051217565b557bfa14c80f7990e9cRichard Smith
7032e5156274b8051217565b557bfa14c80f7990e9cRichard Smith    PartialDiagnosticAt Warning(LocEndOfScope, S.PDiag(DiagID) << LockName);
7042e5156274b8051217565b557bfa14c80f7990e9cRichard Smith    PartialDiagnosticAt Note(LocLocked, S.PDiag(diag::note_locked_here));
7052e5156274b8051217565b557bfa14c80f7990e9cRichard Smith    Warnings.push_back(DelayedDiag(Warning, OptionalNotes(1, Note)));
70675f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski  }
70775f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski
70875f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski
70975f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski  void handleExclusiveAndShared(Name LockName, SourceLocation Loc1,
71075f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski                                SourceLocation Loc2) {
7112e5156274b8051217565b557bfa14c80f7990e9cRichard Smith    PartialDiagnosticAt Warning(
7122e5156274b8051217565b557bfa14c80f7990e9cRichard Smith      Loc1, S.PDiag(diag::warn_lock_exclusive_and_shared) << LockName);
7132e5156274b8051217565b557bfa14c80f7990e9cRichard Smith    PartialDiagnosticAt Note(
7142e5156274b8051217565b557bfa14c80f7990e9cRichard Smith      Loc2, S.PDiag(diag::note_lock_exclusive_and_shared) << LockName);
7152e5156274b8051217565b557bfa14c80f7990e9cRichard Smith    Warnings.push_back(DelayedDiag(Warning, OptionalNotes(1, Note)));
71675f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski  }
71775f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski
71875f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski  void handleNoMutexHeld(const NamedDecl *D, ProtectedOperationKind POK,
71975f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski                         AccessKind AK, SourceLocation Loc) {
720df8327c28d293cf7c6952b86dba26863235dcc0fCaitlin Sadowski    assert((POK == POK_VarAccess || POK == POK_VarDereference)
721df8327c28d293cf7c6952b86dba26863235dcc0fCaitlin Sadowski             && "Only works for variables");
722df8327c28d293cf7c6952b86dba26863235dcc0fCaitlin Sadowski    unsigned DiagID = POK == POK_VarAccess?
723df8327c28d293cf7c6952b86dba26863235dcc0fCaitlin Sadowski                        diag::warn_variable_requires_any_lock:
724df8327c28d293cf7c6952b86dba26863235dcc0fCaitlin Sadowski                        diag::warn_var_deref_requires_any_lock;
7252e5156274b8051217565b557bfa14c80f7990e9cRichard Smith    PartialDiagnosticAt Warning(Loc, S.PDiag(DiagID)
7262e5156274b8051217565b557bfa14c80f7990e9cRichard Smith      << D->getName() << getLockKindFromAccessKind(AK));
7272e5156274b8051217565b557bfa14c80f7990e9cRichard Smith    Warnings.push_back(DelayedDiag(Warning, OptionalNotes()));
72875f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski  }
72975f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski
73075f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski  void handleMutexNotHeld(const NamedDecl *D, ProtectedOperationKind POK,
73175f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski                          Name LockName, LockKind LK, SourceLocation Loc) {
732e87158dfbca01577810f301543c3cdcfc955d8b0Caitlin Sadowski    unsigned DiagID = 0;
73375f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski    switch (POK) {
73475f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski      case POK_VarAccess:
73575f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski        DiagID = diag::warn_variable_requires_lock;
73675f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski        break;
73775f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski      case POK_VarDereference:
73875f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski        DiagID = diag::warn_var_deref_requires_lock;
73975f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski        break;
74075f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski      case POK_FunctionCall:
74175f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski        DiagID = diag::warn_fun_requires_lock;
74275f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski        break;
74375f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski    }
7442e5156274b8051217565b557bfa14c80f7990e9cRichard Smith    PartialDiagnosticAt Warning(Loc, S.PDiag(DiagID)
7452e5156274b8051217565b557bfa14c80f7990e9cRichard Smith      << D->getName() << LockName << LK);
7462e5156274b8051217565b557bfa14c80f7990e9cRichard Smith    Warnings.push_back(DelayedDiag(Warning, OptionalNotes()));
74775f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski  }
74875f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski
74975f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski  void handleFunExcludesLock(Name FunName, Name LockName, SourceLocation Loc) {
7502e5156274b8051217565b557bfa14c80f7990e9cRichard Smith    PartialDiagnosticAt Warning(Loc,
7512e5156274b8051217565b557bfa14c80f7990e9cRichard Smith      S.PDiag(diag::warn_fun_excludes_mutex) << FunName << LockName);
7522e5156274b8051217565b557bfa14c80f7990e9cRichard Smith    Warnings.push_back(DelayedDiag(Warning, OptionalNotes()));
75375f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski  }
75475f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski};
75575f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski}
75675f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski}
75799ba9e3bd70671f3441fb974895f226a83ce0e66David Blaikie}
75875f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski
759610068c8cd2321f90e147b12cf794e1f840b6405Ted Kremenek//===----------------------------------------------------------------------===//
760dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek// AnalysisBasedWarnings - Worker object used by Sema to execute analysis-based
761dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek//  warnings on a function, method, or block.
762dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek//===----------------------------------------------------------------------===//
763dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek
764d064fdc4b7b64ca55b40b70490c79d6f569df78eTed Kremenekclang::sema::AnalysisBasedWarnings::Policy::Policy() {
765dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek  enableCheckFallThrough = 1;
766d064fdc4b7b64ca55b40b70490c79d6f569df78eTed Kremenek  enableCheckUnreachable = 0;
7673ac1fbc303d22af2e11a14023ecee7bd7b7d0bfdCaitlin Sadowski  enableThreadSafetyAnalysis = 0;
768d064fdc4b7b64ca55b40b70490c79d6f569df78eTed Kremenek}
769dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek
7705d98994c7749312a43ce6adf45537979a98e7afdChandler Carruthclang::sema::AnalysisBasedWarnings::AnalysisBasedWarnings(Sema &s)
7715d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth  : S(s),
7725d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth    NumFunctionsAnalyzed(0),
77354cf341bd4145e5e31f91c5777fcdaf3f2400537Benjamin Kramer    NumFunctionsWithBadCFGs(0),
7745d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth    NumCFGBlocks(0),
77554cf341bd4145e5e31f91c5777fcdaf3f2400537Benjamin Kramer    MaxCFGBlocksPerFunction(0),
77654cf341bd4145e5e31f91c5777fcdaf3f2400537Benjamin Kramer    NumUninitAnalysisFunctions(0),
77754cf341bd4145e5e31f91c5777fcdaf3f2400537Benjamin Kramer    NumUninitAnalysisVariables(0),
77854cf341bd4145e5e31f91c5777fcdaf3f2400537Benjamin Kramer    MaxUninitAnalysisVariablesPerFunction(0),
77954cf341bd4145e5e31f91c5777fcdaf3f2400537Benjamin Kramer    NumUninitAnalysisBlockVisits(0),
78054cf341bd4145e5e31f91c5777fcdaf3f2400537Benjamin Kramer    MaxUninitAnalysisBlockVisitsPerFunction(0) {
781d6471f7c1921c7802804ce3ff6fe9768310f72b9David Blaikie  DiagnosticsEngine &D = S.getDiagnostics();
782d064fdc4b7b64ca55b40b70490c79d6f569df78eTed Kremenek  DefaultPolicy.enableCheckUnreachable = (unsigned)
7830827408865e32789e0ec4b8113a302ccdc531423Argyrios Kyrtzidis    (D.getDiagnosticLevel(diag::warn_unreachable, SourceLocation()) !=
784d6471f7c1921c7802804ce3ff6fe9768310f72b9David Blaikie        DiagnosticsEngine::Ignored);
7853ac1fbc303d22af2e11a14023ecee7bd7b7d0bfdCaitlin Sadowski  DefaultPolicy.enableThreadSafetyAnalysis = (unsigned)
7863ac1fbc303d22af2e11a14023ecee7bd7b7d0bfdCaitlin Sadowski    (D.getDiagnosticLevel(diag::warn_double_lock, SourceLocation()) !=
787d6471f7c1921c7802804ce3ff6fe9768310f72b9David Blaikie     DiagnosticsEngine::Ignored);
7883ac1fbc303d22af2e11a14023ecee7bd7b7d0bfdCaitlin Sadowski
789dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek}
790dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek
791351ba91eaa6d30e523587b2d7ed676a5172c6e56Ted Kremenekstatic void flushDiagnostics(Sema &S, sema::FunctionScopeInfo *fscope) {
7925f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner  for (SmallVectorImpl<sema::PossiblyUnreachableDiag>::iterator
793351ba91eaa6d30e523587b2d7ed676a5172c6e56Ted Kremenek       i = fscope->PossiblyUnreachableDiags.begin(),
794351ba91eaa6d30e523587b2d7ed676a5172c6e56Ted Kremenek       e = fscope->PossiblyUnreachableDiags.end();
795351ba91eaa6d30e523587b2d7ed676a5172c6e56Ted Kremenek       i != e; ++i) {
796351ba91eaa6d30e523587b2d7ed676a5172c6e56Ted Kremenek    const sema::PossiblyUnreachableDiag &D = *i;
797351ba91eaa6d30e523587b2d7ed676a5172c6e56Ted Kremenek    S.Diag(D.Loc, D.PD);
798351ba91eaa6d30e523587b2d7ed676a5172c6e56Ted Kremenek  }
799351ba91eaa6d30e523587b2d7ed676a5172c6e56Ted Kremenek}
800351ba91eaa6d30e523587b2d7ed676a5172c6e56Ted Kremenek
801d064fdc4b7b64ca55b40b70490c79d6f569df78eTed Kremenekvoid clang::sema::
802d064fdc4b7b64ca55b40b70490c79d6f569df78eTed KremenekAnalysisBasedWarnings::IssueWarnings(sema::AnalysisBasedWarnings::Policy P,
803283a358aecb75e30fcd486f2206f6c03c5e7f11dTed Kremenek                                     sema::FunctionScopeInfo *fscope,
8043ed6fc08a9cd293d012fa49ab2a615e618d7c3faTed Kremenek                                     const Decl *D, const BlockExpr *blkExpr) {
805d068aabc484c4009282122c6ef26e66e68cfa044Ted Kremenek
806dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek  // We avoid doing analysis-based warnings when there are errors for
807dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek  // two reasons:
808dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek  // (1) The CFGs often can't be constructed (if the body is invalid), so
809dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek  //     don't bother trying.
810dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek  // (2) The code already has problems; running the analysis just takes more
811dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek  //     time.
812d6471f7c1921c7802804ce3ff6fe9768310f72b9David Blaikie  DiagnosticsEngine &Diags = S.getDiagnostics();
81399e8192c4c8f1f596f9969e5f2cdafcee64ddaacTed Kremenek
814d064fdc4b7b64ca55b40b70490c79d6f569df78eTed Kremenek  // Do not do any analysis for declarations in system headers if we are
815d064fdc4b7b64ca55b40b70490c79d6f569df78eTed Kremenek  // going to just ignore them.
81699e8192c4c8f1f596f9969e5f2cdafcee64ddaacTed Kremenek  if (Diags.getSuppressSystemWarnings() &&
817d064fdc4b7b64ca55b40b70490c79d6f569df78eTed Kremenek      S.SourceMgr.isInSystemHeader(D->getLocation()))
818d064fdc4b7b64ca55b40b70490c79d6f569df78eTed Kremenek    return;
819d064fdc4b7b64ca55b40b70490c79d6f569df78eTed Kremenek
820e0054f61fd84133eb0d19c19ae9afaf117933274John McCall  // For code in dependent contexts, we'll do this at instantiation time.
82123661d3e348c5f44ae89b6848bbc331829bb46f2David Blaikie  if (cast<DeclContext>(D)->isDependentContext())
82223661d3e348c5f44ae89b6848bbc331829bb46f2David Blaikie    return;
823dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek
824351ba91eaa6d30e523587b2d7ed676a5172c6e56Ted Kremenek  if (Diags.hasErrorOccurred() || Diags.hasFatalErrorOccurred()) {
825351ba91eaa6d30e523587b2d7ed676a5172c6e56Ted Kremenek    // Flush out any possibly unreachable diagnostics.
826351ba91eaa6d30e523587b2d7ed676a5172c6e56Ted Kremenek    flushDiagnostics(S, fscope);
827351ba91eaa6d30e523587b2d7ed676a5172c6e56Ted Kremenek    return;
828351ba91eaa6d30e523587b2d7ed676a5172c6e56Ted Kremenek  }
829351ba91eaa6d30e523587b2d7ed676a5172c6e56Ted Kremenek
830dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek  const Stmt *Body = D->getBody();
831dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek  assert(Body);
832dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek
833d200187bd27f9ad68699693a6e57f9ee3ff260faJordy Rose  AnalysisDeclContext AC(/* AnalysisDeclContextManager */ 0, D);
834bc5cb8a5fe2b88f917d47ceb58b53696a121e57eTed Kremenek
835dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek  // Don't generate EH edges for CallExprs as we'd like to avoid the n^2
836dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek  // explosion for destrutors that can result and the compile time hit.
837bc5cb8a5fe2b88f917d47ceb58b53696a121e57eTed Kremenek  AC.getCFGBuildOptions().PruneTriviallyFalseEdges = true;
838bc5cb8a5fe2b88f917d47ceb58b53696a121e57eTed Kremenek  AC.getCFGBuildOptions().AddEHEdges = false;
839bc5cb8a5fe2b88f917d47ceb58b53696a121e57eTed Kremenek  AC.getCFGBuildOptions().AddInitializers = true;
840bc5cb8a5fe2b88f917d47ceb58b53696a121e57eTed Kremenek  AC.getCFGBuildOptions().AddImplicitDtors = true;
8410c8e5a0f70cbdb800d939c1807d05f380b2854d4Ted Kremenek
8420c8e5a0f70cbdb800d939c1807d05f380b2854d4Ted Kremenek  // Force that certain expressions appear as CFGElements in the CFG.  This
8430c8e5a0f70cbdb800d939c1807d05f380b2854d4Ted Kremenek  // is used to speed up various analyses.
8440c8e5a0f70cbdb800d939c1807d05f380b2854d4Ted Kremenek  // FIXME: This isn't the right factoring.  This is here for initial
8450c8e5a0f70cbdb800d939c1807d05f380b2854d4Ted Kremenek  // prototyping, but we need a way for analyses to say what expressions they
8460c8e5a0f70cbdb800d939c1807d05f380b2854d4Ted Kremenek  // expect to always be CFGElements and then fill in the BuildOptions
8470c8e5a0f70cbdb800d939c1807d05f380b2854d4Ted Kremenek  // appropriately.  This is essentially a layering violation.
8481fa3c0682a52c45c4ad0be3a82d0c85f26657072DeLesley Hutchins  if (P.enableCheckUnreachable || P.enableThreadSafetyAnalysis) {
8491fa3c0682a52c45c4ad0be3a82d0c85f26657072DeLesley Hutchins    // Unreachable code analysis and thread safety require a linearized CFG.
8500f3b4ca1764cd6d457f511d340fba504f41763c3Ted Kremenek    AC.getCFGBuildOptions().setAllAlwaysAdd();
8510f3b4ca1764cd6d457f511d340fba504f41763c3Ted Kremenek  }
8520f3b4ca1764cd6d457f511d340fba504f41763c3Ted Kremenek  else {
8530f3b4ca1764cd6d457f511d340fba504f41763c3Ted Kremenek    AC.getCFGBuildOptions()
8540f3b4ca1764cd6d457f511d340fba504f41763c3Ted Kremenek      .setAlwaysAdd(Stmt::BinaryOperatorClass)
8550f3b4ca1764cd6d457f511d340fba504f41763c3Ted Kremenek      .setAlwaysAdd(Stmt::BlockExprClass)
8560f3b4ca1764cd6d457f511d340fba504f41763c3Ted Kremenek      .setAlwaysAdd(Stmt::CStyleCastExprClass)
8570f3b4ca1764cd6d457f511d340fba504f41763c3Ted Kremenek      .setAlwaysAdd(Stmt::DeclRefExprClass)
8580f3b4ca1764cd6d457f511d340fba504f41763c3Ted Kremenek      .setAlwaysAdd(Stmt::ImplicitCastExprClass)
8590f3b4ca1764cd6d457f511d340fba504f41763c3Ted Kremenek      .setAlwaysAdd(Stmt::UnaryOperatorClass);
8600f3b4ca1764cd6d457f511d340fba504f41763c3Ted Kremenek  }
861bc5cb8a5fe2b88f917d47ceb58b53696a121e57eTed Kremenek
862bc5cb8a5fe2b88f917d47ceb58b53696a121e57eTed Kremenek  // Construct the analysis context with the specified CFG build options.
863bc5cb8a5fe2b88f917d47ceb58b53696a121e57eTed Kremenek
864351ba91eaa6d30e523587b2d7ed676a5172c6e56Ted Kremenek  // Emit delayed diagnostics.
86523661d3e348c5f44ae89b6848bbc331829bb46f2David Blaikie  if (!fscope->PossiblyUnreachableDiags.empty()) {
866351ba91eaa6d30e523587b2d7ed676a5172c6e56Ted Kremenek    bool analyzed = false;
8670d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek
8680d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek    // Register the expressions with the CFGBuilder.
8695f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner    for (SmallVectorImpl<sema::PossiblyUnreachableDiag>::iterator
8700d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek         i = fscope->PossiblyUnreachableDiags.begin(),
8710d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek         e = fscope->PossiblyUnreachableDiags.end();
8720d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek         i != e; ++i) {
8730d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek      if (const Stmt *stmt = i->stmt)
8740d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek        AC.registerForcedBlockExpression(stmt);
8750d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek    }
8760d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek
8770d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek    if (AC.getCFG()) {
8780d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek      analyzed = true;
8795f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner      for (SmallVectorImpl<sema::PossiblyUnreachableDiag>::iterator
8800d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek            i = fscope->PossiblyUnreachableDiags.begin(),
8810d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek            e = fscope->PossiblyUnreachableDiags.end();
8820d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek            i != e; ++i)
8830d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek      {
8840d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek        const sema::PossiblyUnreachableDiag &D = *i;
8850d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek        bool processed = false;
8860d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek        if (const Stmt *stmt = i->stmt) {
8870d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek          const CFGBlock *block = AC.getBlockForRegisteredExpression(stmt);
88871b8fb5d4233420d2ed2f150a54ea61431bd8684Eli Friedman          CFGReverseBlockReachabilityAnalysis *cra =
88971b8fb5d4233420d2ed2f150a54ea61431bd8684Eli Friedman              AC.getCFGReachablityAnalysis();
89071b8fb5d4233420d2ed2f150a54ea61431bd8684Eli Friedman          // FIXME: We should be able to assert that block is non-null, but
89171b8fb5d4233420d2ed2f150a54ea61431bd8684Eli Friedman          // the CFG analysis can skip potentially-evaluated expressions in
89271b8fb5d4233420d2ed2f150a54ea61431bd8684Eli Friedman          // edge cases; see test/Sema/vla-2.c.
89371b8fb5d4233420d2ed2f150a54ea61431bd8684Eli Friedman          if (block && cra) {
894351ba91eaa6d30e523587b2d7ed676a5172c6e56Ted Kremenek            // Can this block be reached from the entrance?
8950d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek            if (cra->isReachable(&AC.getCFG()->getEntry(), block))
896351ba91eaa6d30e523587b2d7ed676a5172c6e56Ted Kremenek              S.Diag(D.Loc, D.PD);
8970d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek            processed = true;
898351ba91eaa6d30e523587b2d7ed676a5172c6e56Ted Kremenek          }
8990d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek        }
9000d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek        if (!processed) {
9010d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek          // Emit the warning anyway if we cannot map to a basic block.
9020d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek          S.Diag(D.Loc, D.PD);
903351ba91eaa6d30e523587b2d7ed676a5172c6e56Ted Kremenek        }
904351ba91eaa6d30e523587b2d7ed676a5172c6e56Ted Kremenek      }
9050d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek    }
906351ba91eaa6d30e523587b2d7ed676a5172c6e56Ted Kremenek
907351ba91eaa6d30e523587b2d7ed676a5172c6e56Ted Kremenek    if (!analyzed)
908351ba91eaa6d30e523587b2d7ed676a5172c6e56Ted Kremenek      flushDiagnostics(S, fscope);
909351ba91eaa6d30e523587b2d7ed676a5172c6e56Ted Kremenek  }
910351ba91eaa6d30e523587b2d7ed676a5172c6e56Ted Kremenek
911351ba91eaa6d30e523587b2d7ed676a5172c6e56Ted Kremenek
912dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek  // Warning: check missing 'return'
91323661d3e348c5f44ae89b6848bbc331829bb46f2David Blaikie  if (P.enableCheckFallThrough) {
914dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek    const CheckFallThroughDiagnostics &CD =
915dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek      (isa<BlockDecl>(D) ? CheckFallThroughDiagnostics::MakeForBlock()
916793cd1c4cdfaafc52e2c2ad9dae959befe4bb166Douglas Gregor       : (isa<CXXMethodDecl>(D) &&
917793cd1c4cdfaafc52e2c2ad9dae959befe4bb166Douglas Gregor          cast<CXXMethodDecl>(D)->getOverloadedOperator() == OO_Call &&
918793cd1c4cdfaafc52e2c2ad9dae959befe4bb166Douglas Gregor          cast<CXXMethodDecl>(D)->getParent()->isLambda())
919793cd1c4cdfaafc52e2c2ad9dae959befe4bb166Douglas Gregor            ? CheckFallThroughDiagnostics::MakeForLambda()
920793cd1c4cdfaafc52e2c2ad9dae959befe4bb166Douglas Gregor            : CheckFallThroughDiagnostics::MakeForFunction(D));
9213ed6fc08a9cd293d012fa49ab2a615e618d7c3faTed Kremenek    CheckFallThroughForBody(S, D, Body, blkExpr, CD, AC);
922dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek  }
923dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek
924dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek  // Warning: check for unreachable code
9255dfee06daa359bbe0f3c9de055b8a02d61a05173Ted Kremenek  if (P.enableCheckUnreachable) {
9265dfee06daa359bbe0f3c9de055b8a02d61a05173Ted Kremenek    // Only check for unreachable code on non-template instantiations.
9275dfee06daa359bbe0f3c9de055b8a02d61a05173Ted Kremenek    // Different template instantiations can effectively change the control-flow
9285dfee06daa359bbe0f3c9de055b8a02d61a05173Ted Kremenek    // and it is very difficult to prove that a snippet of code in a template
9295dfee06daa359bbe0f3c9de055b8a02d61a05173Ted Kremenek    // is unreachable for all instantiations.
93075df4eeede7b91c22c1d63fafd4dd4142844e3b9Ted Kremenek    bool isTemplateInstantiation = false;
93175df4eeede7b91c22c1d63fafd4dd4142844e3b9Ted Kremenek    if (const FunctionDecl *Function = dyn_cast<FunctionDecl>(D))
93275df4eeede7b91c22c1d63fafd4dd4142844e3b9Ted Kremenek      isTemplateInstantiation = Function->isTemplateInstantiation();
93375df4eeede7b91c22c1d63fafd4dd4142844e3b9Ted Kremenek    if (!isTemplateInstantiation)
9345dfee06daa359bbe0f3c9de055b8a02d61a05173Ted Kremenek      CheckUnreachable(S, AC);
9355dfee06daa359bbe0f3c9de055b8a02d61a05173Ted Kremenek  }
93675f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski
9373ac1fbc303d22af2e11a14023ecee7bd7b7d0bfdCaitlin Sadowski  // Check for thread safety violations
93823661d3e348c5f44ae89b6848bbc331829bb46f2David Blaikie  if (P.enableThreadSafetyAnalysis) {
939f1ac63702143d84db778d32eb185a77fc97db5f5DeLesley Hutchins    SourceLocation FL = AC.getDecl()->getLocation();
9402e5156274b8051217565b557bfa14c80f7990e9cRichard Smith    SourceLocation FEL = AC.getDecl()->getLocEnd();
9412e5156274b8051217565b557bfa14c80f7990e9cRichard Smith    thread_safety::ThreadSafetyReporter Reporter(S, FL, FEL);
94275f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski    thread_safety::runThreadSafetyAnalysis(AC, Reporter);
94375f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski    Reporter.emitDiagnostics();
94475f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski  }
9453ac1fbc303d22af2e11a14023ecee7bd7b7d0bfdCaitlin Sadowski
946a8c17a5babab35f2db26bf218e7571d1af4afedfTed Kremenek  if (Diags.getDiagnosticLevel(diag::warn_uninit_var, D->getLocStart())
947d6471f7c1921c7802804ce3ff6fe9768310f72b9David Blaikie      != DiagnosticsEngine::Ignored ||
94876709bf816e5e1b70b859bb607cf3ee91db12b76Ted Kremenek      Diags.getDiagnosticLevel(diag::warn_maybe_uninit_var, D->getLocStart())
949d6471f7c1921c7802804ce3ff6fe9768310f72b9David Blaikie      != DiagnosticsEngine::Ignored) {
950c5e43c19ddb40b8a1371291f73ae66fe54951ca5Ted Kremenek    if (CFG *cfg = AC.getCFG()) {
951c21fed361c11f13db345cba69101578578d8fb79Ted Kremenek      UninitValsDiagReporter reporter(S);
95257080fbac1ccce702255423335d52e81bcf17b6bFariborz Jahanian      UninitVariablesAnalysisStats stats;
95312efd57ee474c06880a7434ece21a39ac3f34e24Benjamin Kramer      std::memset(&stats, 0, sizeof(UninitVariablesAnalysisStats));
954a8c17a5babab35f2db26bf218e7571d1af4afedfTed Kremenek      runUninitializedVariablesAnalysis(*cast<DeclContext>(D), *cfg, AC,
9555d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth                                        reporter, stats);
9565d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth
9575d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth      if (S.CollectStats && stats.NumVariablesAnalyzed > 0) {
9585d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth        ++NumUninitAnalysisFunctions;
9595d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth        NumUninitAnalysisVariables += stats.NumVariablesAnalyzed;
9605d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth        NumUninitAnalysisBlockVisits += stats.NumBlockVisits;
9615d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth        MaxUninitAnalysisVariablesPerFunction =
9625d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth            std::max(MaxUninitAnalysisVariablesPerFunction,
9635d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth                     stats.NumVariablesAnalyzed);
9645d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth        MaxUninitAnalysisBlockVisitsPerFunction =
9655d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth            std::max(MaxUninitAnalysisBlockVisitsPerFunction,
9665d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth                     stats.NumBlockVisits);
9675d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth      }
9685d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth    }
9695d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth  }
9705d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth
9715d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth  // Collect statistics about the CFG if it was built.
9725d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth  if (S.CollectStats && AC.isCFGBuilt()) {
9735d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth    ++NumFunctionsAnalyzed;
9745d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth    if (CFG *cfg = AC.getCFG()) {
9755d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth      // If we successfully built a CFG for this context, record some more
9765d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth      // detail information about it.
9773ea4c49709c5bba5f8b16c6ceb725d9b9a1c48c6Chandler Carruth      NumCFGBlocks += cfg->getNumBlockIDs();
9785d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth      MaxCFGBlocksPerFunction = std::max(MaxCFGBlocksPerFunction,
9793ea4c49709c5bba5f8b16c6ceb725d9b9a1c48c6Chandler Carruth                                         cfg->getNumBlockIDs());
9805d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth    } else {
9815d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth      ++NumFunctionsWithBadCFGs;
982610068c8cd2321f90e147b12cf794e1f840b6405Ted Kremenek    }
983610068c8cd2321f90e147b12cf794e1f840b6405Ted Kremenek  }
984dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek}
9855d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth
9865d98994c7749312a43ce6adf45537979a98e7afdChandler Carruthvoid clang::sema::AnalysisBasedWarnings::PrintStats() const {
9875d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth  llvm::errs() << "\n*** Analysis Based Warnings Stats:\n";
9885d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth
9895d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth  unsigned NumCFGsBuilt = NumFunctionsAnalyzed - NumFunctionsWithBadCFGs;
9905d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth  unsigned AvgCFGBlocksPerFunction =
9915d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth      !NumCFGsBuilt ? 0 : NumCFGBlocks/NumCFGsBuilt;
9925d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth  llvm::errs() << NumFunctionsAnalyzed << " functions analyzed ("
9935d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth               << NumFunctionsWithBadCFGs << " w/o CFGs).\n"
9945d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth               << "  " << NumCFGBlocks << " CFG blocks built.\n"
9955d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth               << "  " << AvgCFGBlocksPerFunction
9965d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth               << " average CFG blocks per function.\n"
9975d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth               << "  " << MaxCFGBlocksPerFunction
9985d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth               << " max CFG blocks per function.\n";
9995d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth
10005d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth  unsigned AvgUninitVariablesPerFunction = !NumUninitAnalysisFunctions ? 0
10015d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth      : NumUninitAnalysisVariables/NumUninitAnalysisFunctions;
10025d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth  unsigned AvgUninitBlockVisitsPerFunction = !NumUninitAnalysisFunctions ? 0
10035d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth      : NumUninitAnalysisBlockVisits/NumUninitAnalysisFunctions;
10045d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth  llvm::errs() << NumUninitAnalysisFunctions
10055d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth               << " functions analyzed for uninitialiazed variables\n"
10065d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth               << "  " << NumUninitAnalysisVariables << " variables analyzed.\n"
10075d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth               << "  " << AvgUninitVariablesPerFunction
10085d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth               << " average variables per function.\n"
10095d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth               << "  " << MaxUninitAnalysisVariablesPerFunction
10105d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth               << " max variables per function.\n"
10115d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth               << "  " << NumUninitAnalysisBlockVisits << " block visits.\n"
10125d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth               << "  " << AvgUninitBlockVisitsPerFunction
10135d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth               << " average block visits per function.\n"
10145d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth               << "  " << MaxUninitAnalysisBlockVisitsPerFunction
10155d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth               << " max block visits per function.\n";
10165d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth}
1017