AnalysisConsumer.cpp revision c4bac8e376b98d633bb00ee5f510d5e58449753c
1f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek//===--- AnalysisConsumer.cpp - ASTConsumer for running Analyses ----------===//
2f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek//
3f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek//                     The LLVM Compiler Infrastructure
4f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek//
5f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek// This file is distributed under the University of Illinois Open Source
6f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek// License. See LICENSE.TXT for details.
7f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek//
8f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek//===----------------------------------------------------------------------===//
9f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek//
10f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek// "Meta" ASTConsumer for running different source analyses.
11f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek//
12f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek//===----------------------------------------------------------------------===//
13f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek
14d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks#define DEBUG_TYPE "AnalysisConsumer"
15d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks
16e6348c336fecc8da9288ea367375a1b1cd2358d2Argyrios Kyrtzidis#include "AnalysisConsumer.h"
17f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek#include "clang/AST/ASTConsumer.h"
18f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek#include "clang/AST/Decl.h"
19802be99a6817aba6edb166b93c133da4358aa783Zhongxing Xu#include "clang/AST/DeclCXX.h"
20f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek#include "clang/AST/DeclObjC.h"
21efceabd2380f49306bc0229583458e93b062094bDaniel Dunbar#include "clang/AST/ParentMap.h"
22aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks#include "clang/AST/RecursiveASTVisitor.h"
23efceabd2380f49306bc0229583458e93b062094bDaniel Dunbar#include "clang/Analysis/CFG.h"
24d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks#include "clang/Analysis/CallGraph.h"
25371b477836f289f2e9caaab58530f187b51bc86dTed Kremenek#include "clang/Analysis/Analyses/LiveVariables.h"
2627af04bcca46f8a3374586be1301477f9123f5e1Argyrios Kyrtzidis#include "clang/StaticAnalyzer/Frontend/CheckerRegistration.h"
2743dee220252ef0b42c5f8a3bb1eca97f84f2565fArgyrios Kyrtzidis#include "clang/StaticAnalyzer/Core/CheckerManager.h"
2821142581d55918beed544a757e4af3bb865b1812Ted Kremenek#include "clang/StaticAnalyzer/Checkers/LocalCheckers.h"
299b663716449b618ba0390b1dbebc54fa8e971124Ted Kremenek#include "clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h"
309b663716449b618ba0390b1dbebc54fa8e971124Ted Kremenek#include "clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h"
319b663716449b618ba0390b1dbebc54fa8e971124Ted Kremenek#include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h"
329b663716449b618ba0390b1dbebc54fa8e971124Ted Kremenek#include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
33f39d962cf84f46d2c0512157259ae1d41a1a5173David Blaikie#include "clang/StaticAnalyzer/Core/PathDiagnosticConsumers.h"
34a7af5ea88a6c5bdf87497cca6c20831e8c546751Argyrios Kyrtzidis
35efceabd2380f49306bc0229583458e93b062094bDaniel Dunbar#include "clang/Basic/FileManager.h"
36efceabd2380f49306bc0229583458e93b062094bDaniel Dunbar#include "clang/Basic/SourceManager.h"
379b414d3e2d0cb84512b55a3275a98490b090162aDaniel Dunbar#include "clang/Frontend/AnalyzerOptions.h"
38efceabd2380f49306bc0229583458e93b062094bDaniel Dunbar#include "clang/Lex/Preprocessor.h"
39f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek#include "llvm/Support/raw_ostream.h"
4003013fa9a0bf1ef4b907f5fec006c8f4000fdd21Michael J. Spencer#include "llvm/Support/Path.h"
4103013fa9a0bf1ef4b907f5fec006c8f4000fdd21Michael J. Spencer#include "llvm/Support/Program.h"
42d38f79543136ba68cd14b1dab0856474df1fbfd5Anna Zaks#include "llvm/Support/Timer.h"
43d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks#include "llvm/ADT/DepthFirstIterator.h"
446cb7c1a43b0c8f739d1f54b7fdae5ede86033496Benjamin Kramer#include "llvm/ADT/OwningPtr.h"
456a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks#include "llvm/ADT/SmallPtrSet.h"
4681fb169f42769e02c7425b23885a261c025fd5e6Anna Zaks#include "llvm/ADT/Statistic.h"
47db09a4dee28a4515438af60f2d2b4a83e4965c31Ted Kremenek
487fe8dcef71ae56e43fd7df345db2895f84f2d0caAnna Zaks#include <queue>
497fe8dcef71ae56e43fd7df345db2895f84f2d0caAnna Zaks
50f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenekusing namespace clang;
519ef6537a894c33003359b1f9b9676e9178e028b7Ted Kremenekusing namespace ento;
52d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaksusing llvm::SmallPtrSet;
53f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek
54c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xustatic ExplodedNode::Auditor* CreateUbiViz();
55ff944a8c481d6c0f1ad2633e4be9bf8b1dd2a09fZhongxing Xu
563fd5f370a28552976c52e76c3035d79012d78ddaAnna ZaksSTATISTIC(NumFunctionTopLevel, "The # of functions at top level.");
57d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna ZaksSTATISTIC(NumFunctionsAnalyzed, "The # of functions analysed (as top level).");
58e62f048960645b79363408fdead53fec2a063c52Anna ZaksSTATISTIC(NumBlocksInAnalyzedFunctions,
59e62f048960645b79363408fdead53fec2a063c52Anna Zaks                     "The # of basic blocks in the analyzed functions.");
60e62f048960645b79363408fdead53fec2a063c52Anna ZaksSTATISTIC(PercentReachableBlocks, "The % of reachable basic blocks.");
6184c1f4b1edddf74f8080cfc470796c2c498b5d43Anna ZaksSTATISTIC(MaxCFGSize, "The maximum number of basic blocks in a function.");
62d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks
63be1fe1eb12a1cb91c8e3a9fcc2db4dfe989def6cTed Kremenek//===----------------------------------------------------------------------===//
64f39d962cf84f46d2c0512157259ae1d41a1a5173David Blaikie// Special PathDiagnosticConsumers.
65f75560670bcdd59b051149bdece3eac14e313853Ted Kremenek//===----------------------------------------------------------------------===//
66f75560670bcdd59b051149bdece3eac14e313853Ted Kremenek
67c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenekstatic void createPlistHTMLDiagnosticConsumer(PathDiagnosticConsumers &C,
68c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek                                              const std::string &prefix,
69c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek                                              const Preprocessor &PP) {
70c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek  createHTMLDiagnosticConsumer(C, llvm::sys::path::parent_path(prefix), PP);
71c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek  createPlistDiagnosticConsumer(C, prefix, PP);
72f75560670bcdd59b051149bdece3eac14e313853Ted Kremenek}
73f75560670bcdd59b051149bdece3eac14e313853Ted Kremenek
74c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremeneknamespace {
75c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenekclass ClangDiagPathDiagConsumer : public PathDiagnosticConsumer {
76c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek  DiagnosticsEngine &Diag;
77c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenekpublic:
78c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek  ClangDiagPathDiagConsumer(DiagnosticsEngine &Diag) : Diag(Diag) {}
79c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek  virtual ~ClangDiagPathDiagConsumer() {}
80c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek  virtual StringRef getName() const { return "ClangDiags"; }
81c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek  virtual bool useVerboseDescription() const { return false; }
82c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek  virtual PathGenerationScheme getGenerationScheme() const { return None; }
83c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek
84c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek  void FlushDiagnosticsImpl(std::vector<const PathDiagnostic *> &Diags,
85c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek                            FilesMade *filesMade) {
86c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek    for (std::vector<const PathDiagnostic*>::iterator I = Diags.begin(),
87c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek         E = Diags.end(); I != E; ++I) {
88c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek      const PathDiagnostic *PD = *I;
89c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek      StringRef desc = PD->getDescription();
90c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek      SmallString<512> TmpStr;
91c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek      llvm::raw_svector_ostream Out(TmpStr);
92c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek      for (StringRef::iterator I=desc.begin(), E=desc.end(); I!=E; ++I) {
93c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek        if (*I == '%')
94c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek          Out << "%%";
95c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek        else
96c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek          Out << *I;
97c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek      }
98c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek      Out.flush();
99c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek      unsigned ErrorDiag = Diag.getCustomDiagID(DiagnosticsEngine::Warning,
100c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek                                                TmpStr);
101c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek      SourceLocation L = PD->getLocation().asLocation();
102c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek      DiagnosticBuilder diagBuilder = Diag.Report(L, ErrorDiag);
103c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek
104c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek      // Get the ranges from the last point in the path.
105c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek      ArrayRef<SourceRange> Ranges = PD->path.back()->getRanges();
106c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek
107c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek      for (ArrayRef<SourceRange>::iterator I = Ranges.begin(),
108c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek                                           E = Ranges.end(); I != E; ++I) {
109c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek        diagBuilder << *I;
110c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek      }
111c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek    }
112c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek  }
113c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek};
114c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek} // end anonymous namespace
115c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek
116f75560670bcdd59b051149bdece3eac14e313853Ted Kremenek//===----------------------------------------------------------------------===//
117f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek// AnalysisConsumer declaration.
118f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek//===----------------------------------------------------------------------===//
119f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek
120f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremeneknamespace {
121f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek
122aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaksclass AnalysisConsumer : public ASTConsumer,
123aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks                         public RecursiveASTVisitor<AnalysisConsumer> {
124aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks  enum AnalysisMode {
125aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks    ANALYSIS_SYNTAX,
126aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks    ANALYSIS_PATH,
127aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks    ANALYSIS_ALL
128aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks  };
129aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks
130aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks  /// Mode of the analyzes while recursively visiting Decls.
131aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks  AnalysisMode RecVisitorMode;
132aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks  /// Bug Reporter to use while recursively visiting Decls.
133aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks  BugReporter *RecVisitorBR;
134aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks
135ed8afacb8118b71bcfa8017059e51da325e7691bZhongxing Xupublic:
1369c378f705405d37f49795d5e915989de774fe11fTed Kremenek  ASTContext *Ctx;
1371d9cbeb76cf4c36acf5545028e2b2ac207086442Ted Kremenek  const Preprocessor &PP;
1381d9cbeb76cf4c36acf5545028e2b2ac207086442Ted Kremenek  const std::string OutDir;
1391d9cbeb76cf4c36acf5545028e2b2ac207086442Ted Kremenek  AnalyzerOptions Opts;
14008b86531ade68727c56918f162816075b87c864aJordy Rose  ArrayRef<std::string> Plugins;
141d07a0d0279c09d1017f8450fce575a94dc9703c0Zhongxing Xu
1426a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks  /// \brief Stores the declarations from the local translation unit.
1436a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks  /// Note, we pre-compute the local declarations at parse time as an
1446a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks  /// optimization to make sure we do not deserialize everything from disk.
1456a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks  /// The local declaration to all declarations ratio might be very small when
1466a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks  /// working with a PCH file.
1476a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks  SetOfDecls LocalTUDecls;
148cb0a5039c243f5b0c178e70f424adac334e5789bTed Kremenek
149c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek  // Set of PathDiagnosticConsumers.  Owned by AnalysisManager.
150c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek  PathDiagnosticConsumers PathConsumers;
151d07a0d0279c09d1017f8450fce575a94dc9703c0Zhongxing Xu
1521d9cbeb76cf4c36acf5545028e2b2ac207086442Ted Kremenek  StoreManagerCreator CreateStoreMgr;
1531d9cbeb76cf4c36acf5545028e2b2ac207086442Ted Kremenek  ConstraintManagerCreator CreateConstraintMgr;
154f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek
1556f42b62b6194f53bcbc349f5d17388e1936535d7Dylan Noblesmith  OwningPtr<CheckerManager> checkerMgr;
1566f42b62b6194f53bcbc349f5d17388e1936535d7Dylan Noblesmith  OwningPtr<AnalysisManager> Mgr;
157c471e7b44e63ff1b46b480e723c4130aeaef5a8aZhongxing Xu
158d38f79543136ba68cd14b1dab0856474df1fbfd5Anna Zaks  /// Time the analyzes time of each translation unit.
159d38f79543136ba68cd14b1dab0856474df1fbfd5Anna Zaks  static llvm::Timer* TUTotalTimer;
160d38f79543136ba68cd14b1dab0856474df1fbfd5Anna Zaks
1613bbd8cd831788c506f2980293eb3c7e1b3ca2501Anna Zaks  /// The information about analyzed functions shared throughout the
1623bbd8cd831788c506f2980293eb3c7e1b3ca2501Anna Zaks  /// translation unit.
1633bbd8cd831788c506f2980293eb3c7e1b3ca2501Anna Zaks  FunctionSummariesTy FunctionSummaries;
1643bbd8cd831788c506f2980293eb3c7e1b3ca2501Anna Zaks
1651d9cbeb76cf4c36acf5545028e2b2ac207086442Ted Kremenek  AnalysisConsumer(const Preprocessor& pp,
1661d9cbeb76cf4c36acf5545028e2b2ac207086442Ted Kremenek                   const std::string& outdir,
16708b86531ade68727c56918f162816075b87c864aJordy Rose                   const AnalyzerOptions& opts,
16808b86531ade68727c56918f162816075b87c864aJordy Rose                   ArrayRef<std::string> plugins)
169aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks    : RecVisitorMode(ANALYSIS_ALL), RecVisitorBR(0),
170c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek      Ctx(0), PP(pp), OutDir(outdir), Opts(opts), Plugins(plugins) {
1711d9cbeb76cf4c36acf5545028e2b2ac207086442Ted Kremenek    DigestAnalyzerOptions();
172d38f79543136ba68cd14b1dab0856474df1fbfd5Anna Zaks    if (Opts.PrintStats) {
173d38f79543136ba68cd14b1dab0856474df1fbfd5Anna Zaks      llvm::EnableStatistics();
174d38f79543136ba68cd14b1dab0856474df1fbfd5Anna Zaks      TUTotalTimer = new llvm::Timer("Analyzer Total Time");
175d38f79543136ba68cd14b1dab0856474df1fbfd5Anna Zaks    }
176d38f79543136ba68cd14b1dab0856474df1fbfd5Anna Zaks  }
177d38f79543136ba68cd14b1dab0856474df1fbfd5Anna Zaks
178d38f79543136ba68cd14b1dab0856474df1fbfd5Anna Zaks  ~AnalysisConsumer() {
179d38f79543136ba68cd14b1dab0856474df1fbfd5Anna Zaks    if (Opts.PrintStats)
180d38f79543136ba68cd14b1dab0856474df1fbfd5Anna Zaks      delete TUTotalTimer;
1811d9cbeb76cf4c36acf5545028e2b2ac207086442Ted Kremenek  }
182fda7832b000ff8927386f093b52c067641679469Zhongxing Xu
1831d9cbeb76cf4c36acf5545028e2b2ac207086442Ted Kremenek  void DigestAnalyzerOptions() {
184ef3643fbbbf66247c5e205497fae0f46e240c143David Blaikie    // Create the PathDiagnosticConsumer.
185c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek    PathConsumers.push_back(new ClangDiagPathDiagConsumer(PP.getDiagnostics()));
186c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek
1871d9cbeb76cf4c36acf5545028e2b2ac207086442Ted Kremenek    if (!OutDir.empty()) {
1881d9cbeb76cf4c36acf5545028e2b2ac207086442Ted Kremenek      switch (Opts.AnalysisDiagOpt) {
1891d9cbeb76cf4c36acf5545028e2b2ac207086442Ted Kremenek      default:
190fda7832b000ff8927386f093b52c067641679469Zhongxing Xu#define ANALYSIS_DIAGNOSTICS(NAME, CMDFLAG, DESC, CREATEFN, AUTOCREATE) \
191c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek        case PD_##NAME: CREATEFN(PathConsumers, OutDir, PP); break;
192fda7832b000ff8927386f093b52c067641679469Zhongxing Xu#include "clang/Frontend/Analyses.def"
193fda7832b000ff8927386f093b52c067641679469Zhongxing Xu      }
194a599ae8826b01c0160a519b0fc5a4871f599bf04Argyrios Kyrtzidis    } else if (Opts.AnalysisDiagOpt == PD_TEXT) {
195a599ae8826b01c0160a519b0fc5a4871f599bf04Argyrios Kyrtzidis      // Create the text client even without a specified output file since
196a599ae8826b01c0160a519b0fc5a4871f599bf04Argyrios Kyrtzidis      // it just uses diagnostic notes.
197c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek      createTextPathDiagnosticConsumer(PathConsumers, "", PP);
1981d9cbeb76cf4c36acf5545028e2b2ac207086442Ted Kremenek    }
199fda7832b000ff8927386f093b52c067641679469Zhongxing Xu
2001d9cbeb76cf4c36acf5545028e2b2ac207086442Ted Kremenek    // Create the analyzer component creators.
2015f83d6f36a7308eef21d87104fd70c421e854448Argyrios Kyrtzidis    switch (Opts.AnalysisStoreOpt) {
2025f83d6f36a7308eef21d87104fd70c421e854448Argyrios Kyrtzidis    default:
203b219cfc4d75f0a03630b7c4509ef791b7e97b2c8David Blaikie      llvm_unreachable("Unknown store manager.");
204fda7832b000ff8927386f093b52c067641679469Zhongxing Xu#define ANALYSIS_STORE(NAME, CMDFLAG, DESC, CREATEFN)           \
2055f83d6f36a7308eef21d87104fd70c421e854448Argyrios Kyrtzidis      case NAME##Model: CreateStoreMgr = CREATEFN; break;
206fda7832b000ff8927386f093b52c067641679469Zhongxing Xu#include "clang/Frontend/Analyses.def"
2071d9cbeb76cf4c36acf5545028e2b2ac207086442Ted Kremenek    }
2081eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
2095f83d6f36a7308eef21d87104fd70c421e854448Argyrios Kyrtzidis    switch (Opts.AnalysisConstraintsOpt) {
2105f83d6f36a7308eef21d87104fd70c421e854448Argyrios Kyrtzidis    default:
211b219cfc4d75f0a03630b7c4509ef791b7e97b2c8David Blaikie      llvm_unreachable("Unknown store manager.");
212fda7832b000ff8927386f093b52c067641679469Zhongxing Xu#define ANALYSIS_CONSTRAINTS(NAME, CMDFLAG, DESC, CREATEFN)     \
2135f83d6f36a7308eef21d87104fd70c421e854448Argyrios Kyrtzidis      case NAME##Model: CreateConstraintMgr = CREATEFN; break;
214fda7832b000ff8927386f093b52c067641679469Zhongxing Xu#include "clang/Frontend/Analyses.def"
215fda7832b000ff8927386f093b52c067641679469Zhongxing Xu    }
2161d9cbeb76cf4c36acf5545028e2b2ac207086442Ted Kremenek  }
217f6eafcca7734274d277afa121f2c4fb025a54218Ted Kremenek
218aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks  void DisplayFunction(const Decl *D, AnalysisMode Mode) {
219c4a1437c15da43eb8d2601cdce13161ef41a4389Ted Kremenek    if (!Opts.AnalyzerDisplayProgress)
2201d9cbeb76cf4c36acf5545028e2b2ac207086442Ted Kremenek      return;
221f6eafcca7734274d277afa121f2c4fb025a54218Ted Kremenek
222fc576514d06c46a7cac49500169411d82f38d04bTed Kremenek    SourceManager &SM = Mgr->getASTContext().getSourceManager();
223fc576514d06c46a7cac49500169411d82f38d04bTed Kremenek    PresumedLoc Loc = SM.getPresumedLoc(D->getLocation());
224cb7b1e17b63967317ab5cc55682168cf0380519aDouglas Gregor    if (Loc.isValid()) {
225aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks      llvm::errs() << "ANALYZE";
226aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks      switch (Mode) {
227aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks        case ANALYSIS_SYNTAX: llvm::errs() << "(Syntax)"; break;
228aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks        case ANALYSIS_PATH: llvm::errs() << "(Path Sensitive)"; break;
229aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks        case ANALYSIS_ALL: break;
230aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks      };
231aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks      llvm::errs() << ": " << Loc.getFilename();
232cb7b1e17b63967317ab5cc55682168cf0380519aDouglas Gregor      if (isa<FunctionDecl>(D) || isa<ObjCMethodDecl>(D)) {
233cb7b1e17b63967317ab5cc55682168cf0380519aDouglas Gregor        const NamedDecl *ND = cast<NamedDecl>(D);
234b8989f27f116ff2400e92a52c067a69846119eb5Benjamin Kramer        llvm::errs() << ' ' << *ND << '\n';
235cb7b1e17b63967317ab5cc55682168cf0380519aDouglas Gregor      }
236cb7b1e17b63967317ab5cc55682168cf0380519aDouglas Gregor      else if (isa<BlockDecl>(D)) {
237cb7b1e17b63967317ab5cc55682168cf0380519aDouglas Gregor        llvm::errs() << ' ' << "block(line:" << Loc.getLine() << ",col:"
238cb7b1e17b63967317ab5cc55682168cf0380519aDouglas Gregor                     << Loc.getColumn() << '\n';
239cb7b1e17b63967317ab5cc55682168cf0380519aDouglas Gregor      }
240cb7b1e17b63967317ab5cc55682168cf0380519aDouglas Gregor      else if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D)) {
241cb7b1e17b63967317ab5cc55682168cf0380519aDouglas Gregor        Selector S = MD->getSelector();
242cb7b1e17b63967317ab5cc55682168cf0380519aDouglas Gregor        llvm::errs() << ' ' << S.getAsString();
243cb7b1e17b63967317ab5cc55682168cf0380519aDouglas Gregor      }
24435fa76d0bb6fb8c86159a7506efd094a4fe376d2Ted Kremenek    }
2451d9cbeb76cf4c36acf5545028e2b2ac207086442Ted Kremenek  }
2461eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
2471d9cbeb76cf4c36acf5545028e2b2ac207086442Ted Kremenek  virtual void Initialize(ASTContext &Context) {
2481d9cbeb76cf4c36acf5545028e2b2ac207086442Ted Kremenek    Ctx = &Context;
2494e4d08403ca5cfd4d558fa2936215d3a4e5a528dDavid Blaikie    checkerMgr.reset(createCheckerManager(Opts, PP.getLangOpts(), Plugins,
25008b86531ade68727c56918f162816075b87c864aJordy Rose                                          PP.getDiagnostics()));
251c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek    Mgr.reset(new AnalysisManager(*Ctx,
252c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek                                  PP.getDiagnostics(),
253c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek                                  PP.getLangOpts(),
254c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek                                  PathConsumers,
255c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek                                  CreateStoreMgr,
256c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek                                  CreateConstraintMgr,
25743dee220252ef0b42c5f8a3bb1eca97f84f2565fArgyrios Kyrtzidis                                  checkerMgr.get(),
2586362b893731ccf4480a96527db9e55e04b801503Zhongxing Xu                                  Opts.MaxNodes, Opts.MaxLoop,
2591d9cbeb76cf4c36acf5545028e2b2ac207086442Ted Kremenek                                  Opts.VisualizeEGDot, Opts.VisualizeEGUbi,
260d30952838421ddfb9f7e346b2ba8213889a5f789Anna Zaks                                  Opts.AnalysisPurgeOpt, Opts.EagerlyAssume,
26166253352131e3e7a22b3bfd0e180607aa2bfb988Anna Zaks                                  Opts.TrimGraph,
2629121ba232903ebe61e7bbe14ca294cf0f07dfa96Marcin Swiderski                                  Opts.UnoptimizedCFG, Opts.CFGAddImplicitDtors,
2638235f9c9c8b3d1737d1c6bd57f7ba3f616b92392Anna Zaks                                  Opts.EagerlyTrimEGraph,
26466253352131e3e7a22b3bfd0e180607aa2bfb988Anna Zaks                                  Opts.IPAMode,
2658235f9c9c8b3d1737d1c6bd57f7ba3f616b92392Anna Zaks                                  Opts.InlineMaxStackDepth,
26666253352131e3e7a22b3bfd0e180607aa2bfb988Anna Zaks                                  Opts.InlineMaxFunctionSize,
2675903a373db3d27794c90b25687e0dd6adb0e497dAnna Zaks                                  Opts.InliningMode,
268b47dbcbc12430fdf3e5a5b9f59cdec5480e89e75Anna Zaks                                  Opts.NoRetryExhausted));
2691d9cbeb76cf4c36acf5545028e2b2ac207086442Ted Kremenek  }
2701eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
2716a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks  /// \brief Store the top level decls in the set to be processed later on.
2726a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks  /// (Doing this pre-processing avoids deserialization of data from PCH.)
2736a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks  virtual bool HandleTopLevelDecl(DeclGroupRef D);
2746a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks  virtual void HandleTopLevelDeclInObjCContainer(DeclGroupRef D);
2756a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks
2761d9cbeb76cf4c36acf5545028e2b2ac207086442Ted Kremenek  virtual void HandleTranslationUnit(ASTContext &C);
27714cc9451de4a9539bf79e4e5d63248c2377426dbTed Kremenek
2786a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks  /// \brief Build the call graph for all the top level decls of this TU and
2796a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks  /// use it to define the order in which the functions should be visited.
280694a942b0a14e02757a695142c45437eec6e3684Anna Zaks  void HandleDeclsGallGraph(const unsigned LocalTUDeclsSize);
281aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks
282aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks  /// \brief Run analyzes(syntax or path sensitive) on the given function.
283aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks  /// \param Mode - determines if we are requesting syntax only or path
284aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks  /// sensitive only analysis.
285aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks  /// \param VisitedCallees - The output parameter, which is populated with the
286aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks  /// set of functions which should be considered analyzed after analyzing the
287aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks  /// given root function.
2886a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks  void HandleCode(Decl *D, AnalysisMode Mode,
2896a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks                  SetOfConstDecls *VisitedCallees = 0);
290aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks
2916a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks  void RunPathSensitiveChecks(Decl *D, SetOfConstDecls *VisitedCallees);
2926a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks  void ActionExprEngine(Decl *D, bool ObjCGCEnabled,
2936a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks                        SetOfConstDecls *VisitedCallees);
294aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks
295aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks  /// Visitors for the RecursiveASTVisitor.
296c8848f34bbde083b8d89f445eb605eaabf30d6a8Anna Zaks  bool shouldWalkTypesOfTypeLocs() const { return false; }
297aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks
298aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks  /// Handle callbacks for arbitrary Decls.
299aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks  bool VisitDecl(Decl *D) {
300aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks    checkerMgr->runCheckersOnASTDecl(D, *Mgr, *RecVisitorBR);
301aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks    return true;
302aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks  }
303aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks
304aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks  bool VisitFunctionDecl(FunctionDecl *FD) {
305aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks    IdentifierInfo *II = FD->getIdentifier();
306aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks    if (II && II->getName().startswith("__inline"))
307aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks      return true;
308aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks
309aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks    // We skip function template definitions, as their semantics is
310aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks    // only determined when they are instantiated.
311aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks    if (FD->isThisDeclarationADefinition() &&
312aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks        !FD->isDependentContext()) {
313aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks      HandleCode(FD, RecVisitorMode);
314aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks    }
315aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks    return true;
316aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks  }
317aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks
318aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks  bool VisitObjCMethodDecl(ObjCMethodDecl *MD) {
319aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks    checkerMgr->runCheckersOnASTDecl(MD, *Mgr, *RecVisitorBR);
320aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks    if (MD->isThisDeclarationADefinition())
321aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks      HandleCode(MD, RecVisitorMode);
322aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks    return true;
323aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks  }
3246a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks
3256a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaksprivate:
3266a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks  void storeTopLevelDecls(DeclGroupRef DG);
3276a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks
3286a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks  /// \brief Check if we should skip (not analyze) the given function.
3296a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks  bool skipFunction(Decl *D);
3306a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks
3311d9cbeb76cf4c36acf5545028e2b2ac207086442Ted Kremenek};
332f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek} // end anonymous namespace
333f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek
334aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks
335f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek//===----------------------------------------------------------------------===//
336f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek// AnalysisConsumer implementation.
337f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek//===----------------------------------------------------------------------===//
338d38f79543136ba68cd14b1dab0856474df1fbfd5Anna Zaksllvm::Timer* AnalysisConsumer::TUTotalTimer = 0;
339f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek
3406a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaksbool AnalysisConsumer::HandleTopLevelDecl(DeclGroupRef DG) {
3416a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks  storeTopLevelDecls(DG);
3426a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks  return true;
3436a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks}
3446a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks
3456a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaksvoid AnalysisConsumer::HandleTopLevelDeclInObjCContainer(DeclGroupRef DG) {
3466a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks  storeTopLevelDecls(DG);
3476a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks}
3486a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks
3496a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaksvoid AnalysisConsumer::storeTopLevelDecls(DeclGroupRef DG) {
3506a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks  for (DeclGroupRef::iterator I = DG.begin(), E = DG.end(); I != E; ++I) {
3516a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks
3526a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks    // Skip ObjCMethodDecl, wait for the objc container to avoid
3536a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks    // analyzing twice.
3546a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks    if (isa<ObjCMethodDecl>(*I))
3556a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks      continue;
3566a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks
357577f14a34457032523e59dbbbacb88ca2cd4db57Ted Kremenek    LocalTUDecls.push_back(*I);
3586a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks  }
3596a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks}
3606a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks
361694a942b0a14e02757a695142c45437eec6e3684Anna Zaksvoid AnalysisConsumer::HandleDeclsGallGraph(const unsigned LocalTUDeclsSize) {
362d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks  // Otherwise, use the Callgraph to derive the order.
363d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks  // Build the Call Graph.
364d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks  CallGraph CG;
365eaa069075f060f58840af03e0bd5bd75bb27e809Anna Zaks
3666a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks  // Add all the top level declarations to the graph.
367694a942b0a14e02757a695142c45437eec6e3684Anna Zaks  // Note: CallGraph can trigger deserialization of more items from a pch
368694a942b0a14e02757a695142c45437eec6e3684Anna Zaks  // (though HandleInterestingDecl); triggering additions to LocalTUDecls.
369694a942b0a14e02757a695142c45437eec6e3684Anna Zaks  // We rely on random access to add the initially processed Decls to CG.
370694a942b0a14e02757a695142c45437eec6e3684Anna Zaks  for (unsigned i = 0 ; i < LocalTUDeclsSize ; ++i) {
371eaa069075f060f58840af03e0bd5bd75bb27e809Anna Zaks    CG.addToCallGraph(LocalTUDecls[i]);
372eaa069075f060f58840af03e0bd5bd75bb27e809Anna Zaks  }
373d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks
374d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks  // Find the top level nodes - children of root + the unreachable (parentless)
375d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks  // nodes.
3763fd5f370a28552976c52e76c3035d79012d78ddaAnna Zaks  llvm::SmallVector<CallGraphNode*, 24> TopLevelFunctions;
377b990d039c7e01ad0055dcbd1e13a691813397b96Anna Zaks  for (CallGraph::nodes_iterator TI = CG.parentless_begin(),
378b990d039c7e01ad0055dcbd1e13a691813397b96Anna Zaks                                 TE = CG.parentless_end(); TI != TE; ++TI) {
379b990d039c7e01ad0055dcbd1e13a691813397b96Anna Zaks    TopLevelFunctions.push_back(*TI);
380b990d039c7e01ad0055dcbd1e13a691813397b96Anna Zaks    NumFunctionTopLevel++;
381b990d039c7e01ad0055dcbd1e13a691813397b96Anna Zaks  }
382d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks  CallGraphNode *Entry = CG.getRoot();
383d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks  for (CallGraphNode::iterator I = Entry->begin(),
3843fd5f370a28552976c52e76c3035d79012d78ddaAnna Zaks                               E = Entry->end(); I != E; ++I) {
385d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks    TopLevelFunctions.push_back(*I);
3863fd5f370a28552976c52e76c3035d79012d78ddaAnna Zaks    NumFunctionTopLevel++;
3873fd5f370a28552976c52e76c3035d79012d78ddaAnna Zaks  }
388d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks
389b990d039c7e01ad0055dcbd1e13a691813397b96Anna Zaks  // Make sure the nodes are sorted in order reverse of their definition in the
390b990d039c7e01ad0055dcbd1e13a691813397b96Anna Zaks  // translation unit. This step is very important for performance. It ensures
391b990d039c7e01ad0055dcbd1e13a691813397b96Anna Zaks  // that we analyze the root functions before the externally available
392b990d039c7e01ad0055dcbd1e13a691813397b96Anna Zaks  // subroutines.
393cb0a5039c243f5b0c178e70f424adac334e5789bTed Kremenek  std::deque<CallGraphNode*> BFSQueue;
394b990d039c7e01ad0055dcbd1e13a691813397b96Anna Zaks  for (llvm::SmallVector<CallGraphNode*, 24>::reverse_iterator
395b990d039c7e01ad0055dcbd1e13a691813397b96Anna Zaks         TI = TopLevelFunctions.rbegin(), TE = TopLevelFunctions.rend();
3967fe8dcef71ae56e43fd7df345db2895f84f2d0caAnna Zaks         TI != TE; ++TI)
397371b477836f289f2e9caaab58530f187b51bc86dTed Kremenek    BFSQueue.push_back(*TI);
398d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks
3997fe8dcef71ae56e43fd7df345db2895f84f2d0caAnna Zaks  // BFS over all of the functions, while skipping the ones inlined into
4007fe8dcef71ae56e43fd7df345db2895f84f2d0caAnna Zaks  // the previously processed functions. Use external Visited set, which is
401d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks  // also modified when we inline a function.
402d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks  SmallPtrSet<CallGraphNode*,24> Visited;
4037fe8dcef71ae56e43fd7df345db2895f84f2d0caAnna Zaks  while(!BFSQueue.empty()) {
4047fe8dcef71ae56e43fd7df345db2895f84f2d0caAnna Zaks    CallGraphNode *N = BFSQueue.front();
405cb0a5039c243f5b0c178e70f424adac334e5789bTed Kremenek    BFSQueue.pop_front();
4067fe8dcef71ae56e43fd7df345db2895f84f2d0caAnna Zaks
407371b477836f289f2e9caaab58530f187b51bc86dTed Kremenek    // Push the children into the queue.
408371b477836f289f2e9caaab58530f187b51bc86dTed Kremenek    for (CallGraphNode::const_iterator CI = N->begin(),
409371b477836f289f2e9caaab58530f187b51bc86dTed Kremenek         CE = N->end(); CI != CE; ++CI) {
410371b477836f289f2e9caaab58530f187b51bc86dTed Kremenek      if (!Visited.count(*CI))
411371b477836f289f2e9caaab58530f187b51bc86dTed Kremenek        BFSQueue.push_back(*CI);
412371b477836f289f2e9caaab58530f187b51bc86dTed Kremenek    }
413371b477836f289f2e9caaab58530f187b51bc86dTed Kremenek
4147fe8dcef71ae56e43fd7df345db2895f84f2d0caAnna Zaks    // Skip the functions which have been processed already or previously
4157fe8dcef71ae56e43fd7df345db2895f84f2d0caAnna Zaks    // inlined.
4167fe8dcef71ae56e43fd7df345db2895f84f2d0caAnna Zaks    if (Visited.count(N))
4177fe8dcef71ae56e43fd7df345db2895f84f2d0caAnna Zaks      continue;
4187fe8dcef71ae56e43fd7df345db2895f84f2d0caAnna Zaks
4197fe8dcef71ae56e43fd7df345db2895f84f2d0caAnna Zaks    // Analyze the function.
4206a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks    SetOfConstDecls VisitedCallees;
4217fe8dcef71ae56e43fd7df345db2895f84f2d0caAnna Zaks    Decl *D = N->getDecl();
4227fe8dcef71ae56e43fd7df345db2895f84f2d0caAnna Zaks    assert(D);
4237fe8dcef71ae56e43fd7df345db2895f84f2d0caAnna Zaks    HandleCode(D, ANALYSIS_PATH,
4247fe8dcef71ae56e43fd7df345db2895f84f2d0caAnna Zaks               (Mgr->InliningMode == All ? 0 : &VisitedCallees));
4257fe8dcef71ae56e43fd7df345db2895f84f2d0caAnna Zaks
4267fe8dcef71ae56e43fd7df345db2895f84f2d0caAnna Zaks    // Add the visited callees to the global visited set.
427cb0a5039c243f5b0c178e70f424adac334e5789bTed Kremenek    for (SetOfConstDecls::iterator I = VisitedCallees.begin(),
428cb0a5039c243f5b0c178e70f424adac334e5789bTed Kremenek                                   E = VisitedCallees.end(); I != E; ++I) {
4297fe8dcef71ae56e43fd7df345db2895f84f2d0caAnna Zaks      CallGraphNode *VN = CG.getNode(*I);
4307fe8dcef71ae56e43fd7df345db2895f84f2d0caAnna Zaks      if (VN)
4317fe8dcef71ae56e43fd7df345db2895f84f2d0caAnna Zaks        Visited.insert(VN);
4327fe8dcef71ae56e43fd7df345db2895f84f2d0caAnna Zaks    }
4337fe8dcef71ae56e43fd7df345db2895f84f2d0caAnna Zaks    Visited.insert(N);
434d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks  }
435fee618af5dd7dee2caaa7347b372eb3dc5fdeffcTed Kremenek}
436fee618af5dd7dee2caaa7347b372eb3dc5fdeffcTed Kremenek
43714cc9451de4a9539bf79e4e5d63248c2377426dbTed Kremenekvoid AnalysisConsumer::HandleTranslationUnit(ASTContext &C) {
438aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks  // Don't run the actions if an error has occurred with parsing the file.
439aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks  DiagnosticsEngine &Diags = PP.getDiagnostics();
440aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks  if (Diags.hasErrorOccurred() || Diags.hasFatalErrorOccurred())
441aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks    return;
442aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks
443c5bdc556f6a65c677e0ed73f918c3000ecad33afAnna Zaks  {
444d38f79543136ba68cd14b1dab0856474df1fbfd5Anna Zaks    if (TUTotalTimer) TUTotalTimer->startTimer();
445d38f79543136ba68cd14b1dab0856474df1fbfd5Anna Zaks
446c5bdc556f6a65c677e0ed73f918c3000ecad33afAnna Zaks    // Introduce a scope to destroy BR before Mgr.
447c5bdc556f6a65c677e0ed73f918c3000ecad33afAnna Zaks    BugReporter BR(*Mgr);
448c5bdc556f6a65c677e0ed73f918c3000ecad33afAnna Zaks    TranslationUnitDecl *TU = C.getTranslationUnitDecl();
449c5bdc556f6a65c677e0ed73f918c3000ecad33afAnna Zaks    checkerMgr->runCheckersOnASTDecl(TU, *Mgr, BR);
450aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks
451aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks    // Run the AST-only checks using the order in which functions are defined.
452aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks    // If inlining is not turned on, use the simplest function order for path
453aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks    // sensitive analyzes as well.
454aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks    RecVisitorMode = (Mgr->shouldInlineCall() ? ANALYSIS_SYNTAX : ANALYSIS_ALL);
455aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks    RecVisitorBR = &BR;
4566a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks
4576a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks    // Process all the top level declarations.
458cb0a5039c243f5b0c178e70f424adac334e5789bTed Kremenek    //
459577f14a34457032523e59dbbbacb88ca2cd4db57Ted Kremenek    // Note: TraverseDecl may modify LocalTUDecls, but only by appending more
460577f14a34457032523e59dbbbacb88ca2cd4db57Ted Kremenek    // entries.  Thus we don't use an iterator, but rely on LocalTUDecls
461577f14a34457032523e59dbbbacb88ca2cd4db57Ted Kremenek    // random access.  By doing so, we automatically compensate for iterators
462577f14a34457032523e59dbbbacb88ca2cd4db57Ted Kremenek    // possibly being invalidated, although this is a bit slower.
463694a942b0a14e02757a695142c45437eec6e3684Anna Zaks    const unsigned LocalTUDeclsSize = LocalTUDecls.size();
464694a942b0a14e02757a695142c45437eec6e3684Anna Zaks    for (unsigned i = 0 ; i < LocalTUDeclsSize ; ++i) {
465577f14a34457032523e59dbbbacb88ca2cd4db57Ted Kremenek      TraverseDecl(LocalTUDecls[i]);
466cb0a5039c243f5b0c178e70f424adac334e5789bTed Kremenek    }
467aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks
468aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks    if (Mgr->shouldInlineCall())
469694a942b0a14e02757a695142c45437eec6e3684Anna Zaks      HandleDeclsGallGraph(LocalTUDeclsSize);
470b317f8f5ca8737a5bbad97a3f7566a2dbd2ed61bZhongxing Xu
471c5bdc556f6a65c677e0ed73f918c3000ecad33afAnna Zaks    // After all decls handled, run checkers on the entire TranslationUnit.
472c5bdc556f6a65c677e0ed73f918c3000ecad33afAnna Zaks    checkerMgr->runCheckersOnEndOfTranslationUnit(TU, *Mgr, BR);
473aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks
474aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks    RecVisitorBR = 0;
475c5bdc556f6a65c677e0ed73f918c3000ecad33afAnna Zaks  }
4769be6e7ce5788e50c62d40c59b0bbc2ea423683f7Ted Kremenek
477ef3643fbbbf66247c5e205497fae0f46e240c143David Blaikie  // Explicitly destroy the PathDiagnosticConsumer.  This will flush its output.
478690a7f431d6863a101711e67636d51ddd13f35c5Ted Kremenek  // FIXME: This should be replaced with something that doesn't rely on
479ef3643fbbbf66247c5e205497fae0f46e240c143David Blaikie  // side-effects in PathDiagnosticConsumer's destructor. This is required when
480da17fd50ad485fd2a1fc5c2f055caacf532992daZhongxing Xu  // used with option -disable-free.
481d07a0d0279c09d1017f8450fce575a94dc9703c0Zhongxing Xu  Mgr.reset(NULL);
482d38f79543136ba68cd14b1dab0856474df1fbfd5Anna Zaks
483d38f79543136ba68cd14b1dab0856474df1fbfd5Anna Zaks  if (TUTotalTimer) TUTotalTimer->stopTimer();
4846b77ce8824cf62c2cfb61cf2d801eb3fcfbecffeAnna Zaks
4856b77ce8824cf62c2cfb61cf2d801eb3fcfbecffeAnna Zaks  // Count how many basic blocks we have not covered.
4866b77ce8824cf62c2cfb61cf2d801eb3fcfbecffeAnna Zaks  NumBlocksInAnalyzedFunctions = FunctionSummaries.getTotalNumBasicBlocks();
4876b77ce8824cf62c2cfb61cf2d801eb3fcfbecffeAnna Zaks  if (NumBlocksInAnalyzedFunctions > 0)
4886b77ce8824cf62c2cfb61cf2d801eb3fcfbecffeAnna Zaks    PercentReachableBlocks =
4896b77ce8824cf62c2cfb61cf2d801eb3fcfbecffeAnna Zaks      (FunctionSummaries.getTotalNumVisitedBasicBlocks() * 100) /
4906b77ce8824cf62c2cfb61cf2d801eb3fcfbecffeAnna Zaks        NumBlocksInAnalyzedFunctions;
4916b77ce8824cf62c2cfb61cf2d801eb3fcfbecffeAnna Zaks
492db09a4dee28a4515438af60f2d2b4a83e4965c31Ted Kremenek}
493db09a4dee28a4515438af60f2d2b4a83e4965c31Ted Kremenek
4945f9e272e632e951b1efe824cd16acb4d96077930Chris Lattnerstatic void FindBlocks(DeclContext *D, SmallVectorImpl<Decl*> &WL) {
495fc576514d06c46a7cac49500169411d82f38d04bTed Kremenek  if (BlockDecl *BD = dyn_cast<BlockDecl>(D))
496fc576514d06c46a7cac49500169411d82f38d04bTed Kremenek    WL.push_back(BD);
497f6eafcca7734274d277afa121f2c4fb025a54218Ted Kremenek
498fc576514d06c46a7cac49500169411d82f38d04bTed Kremenek  for (DeclContext::decl_iterator I = D->decls_begin(), E = D->decls_end();
499fc576514d06c46a7cac49500169411d82f38d04bTed Kremenek       I!=E; ++I)
500fc576514d06c46a7cac49500169411d82f38d04bTed Kremenek    if (DeclContext *DC = dyn_cast<DeclContext>(*I))
501fc576514d06c46a7cac49500169411d82f38d04bTed Kremenek      FindBlocks(DC, WL);
502fc576514d06c46a7cac49500169411d82f38d04bTed Kremenek}
503fc576514d06c46a7cac49500169411d82f38d04bTed Kremenek
504d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaksstatic std::string getFunctionName(const Decl *D) {
505d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks  if (const ObjCMethodDecl *ID = dyn_cast<ObjCMethodDecl>(D)) {
506d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks    return ID->getSelector().getAsString();
507d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks  }
508d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks  if (const FunctionDecl *ND = dyn_cast<FunctionDecl>(D)) {
509d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks    IdentifierInfo *II = ND->getIdentifier();
510d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks    if (II)
511d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks      return II->getName();
512d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks  }
513d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks  return "";
514d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks}
515d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks
51698520835eb1aa091429afa06e9f4f7ebe3864d34Anna Zaksbool AnalysisConsumer::skipFunction(Decl *D) {
517d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks  if (!Opts.AnalyzeSpecificFunction.empty() &&
518d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks      getFunctionName(D) != Opts.AnalyzeSpecificFunction)
51998520835eb1aa091429afa06e9f4f7ebe3864d34Anna Zaks    return true;
5201eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
521f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek  // Don't run the actions on declarations in header files unless
522f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek  // otherwise specified.
523fcd783d583d270b7ec1ec3e0fcf83cd93d30e381Ted Kremenek  SourceManager &SM = Ctx->getSourceManager();
524402785357ab053dd53f4fdd858b9630a5e0f8badChandler Carruth  SourceLocation SL = SM.getExpansionLoc(D->getLocation());
525fcd783d583d270b7ec1ec3e0fcf83cd93d30e381Ted Kremenek  if (!Opts.AnalyzeAll && !SM.isFromMainFile(SL))
52698520835eb1aa091429afa06e9f4f7ebe3864d34Anna Zaks    return true;
52798520835eb1aa091429afa06e9f4f7ebe3864d34Anna Zaks
52898520835eb1aa091429afa06e9f4f7ebe3864d34Anna Zaks  return false;
52998520835eb1aa091429afa06e9f4f7ebe3864d34Anna Zaks}
53098520835eb1aa091429afa06e9f4f7ebe3864d34Anna Zaks
531aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaksvoid AnalysisConsumer::HandleCode(Decl *D, AnalysisMode Mode,
5326a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks                                  SetOfConstDecls *VisitedCallees) {
53398520835eb1aa091429afa06e9f4f7ebe3864d34Anna Zaks  if (skipFunction(D))
5341eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump    return;
535f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek
536aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks  DisplayFunction(D, Mode);
53784c1f4b1edddf74f8080cfc470796c2c498b5d43Anna Zaks  CFG *DeclCFG = Mgr->getCFG(D);
53884c1f4b1edddf74f8080cfc470796c2c498b5d43Anna Zaks  if (DeclCFG) {
53984c1f4b1edddf74f8080cfc470796c2c498b5d43Anna Zaks    unsigned CFGSize = DeclCFG->size();
54084c1f4b1edddf74f8080cfc470796c2c498b5d43Anna Zaks    MaxCFGSize = MaxCFGSize < CFGSize ? CFGSize : MaxCFGSize;
54184c1f4b1edddf74f8080cfc470796c2c498b5d43Anna Zaks  }
54284c1f4b1edddf74f8080cfc470796c2c498b5d43Anna Zaks
54398520835eb1aa091429afa06e9f4f7ebe3864d34Anna Zaks
5441d26f48dc2eea1c07431ca1519d7034a21b9bcffTed Kremenek  // Clear the AnalysisManager of old AnalysisDeclContexts.
54558f5ec7d56b1ebf5f90ee11226ebe7663f2821eaTed Kremenek  Mgr->ClearContexts();
546f6eafcca7734274d277afa121f2c4fb025a54218Ted Kremenek
5471eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  // Dispatch on the actions.
5485f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner  SmallVector<Decl*, 10> WL;
549fc576514d06c46a7cac49500169411d82f38d04bTed Kremenek  WL.push_back(D);
550f6eafcca7734274d277afa121f2c4fb025a54218Ted Kremenek
55106a54a38be5054c910ffc92db60edab23f9ea105Argyrios Kyrtzidis  if (D->hasBody() && Opts.AnalyzeNestedBlocks)
552fc576514d06c46a7cac49500169411d82f38d04bTed Kremenek    FindBlocks(cast<DeclContext>(D), WL);
553f6eafcca7734274d277afa121f2c4fb025a54218Ted Kremenek
5549fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis  BugReporter BR(*Mgr);
5555f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner  for (SmallVectorImpl<Decl*>::iterator WI=WL.begin(), WE=WL.end();
5569fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis       WI != WE; ++WI)
557d655ab28fdf7c940d3f79f8f287954d7f76e0977Argyrios Kyrtzidis    if ((*WI)->hasBody()) {
558aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks      if (Mode != ANALYSIS_PATH)
559aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks        checkerMgr->runCheckersOnASTBody(*WI, *Mgr, BR);
5601f5171edc9fb9b0698a75fa981c29a750b0a6082Anna Zaks      if (Mode != ANALYSIS_SYNTAX && checkerMgr->hasPathSensitiveCheckers()) {
5613fd5f370a28552976c52e76c3035d79012d78ddaAnna Zaks        RunPathSensitiveChecks(*WI, VisitedCallees);
5621f5171edc9fb9b0698a75fa981c29a750b0a6082Anna Zaks        NumFunctionsAnalyzed++;
5631f5171edc9fb9b0698a75fa981c29a750b0a6082Anna Zaks      }
564d655ab28fdf7c940d3f79f8f287954d7f76e0977Argyrios Kyrtzidis    }
565f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek}
566f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek
567f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek//===----------------------------------------------------------------------===//
568d655ab28fdf7c940d3f79f8f287954d7f76e0977Argyrios Kyrtzidis// Path-sensitive checking.
569f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek//===----------------------------------------------------------------------===//
570f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek
5713fd5f370a28552976c52e76c3035d79012d78ddaAnna Zaksvoid AnalysisConsumer::ActionExprEngine(Decl *D, bool ObjCGCEnabled,
5726a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks                                        SetOfConstDecls *VisitedCallees) {
573a5937bbfd19e61d651a58b0f0ffeef68457902a5Ted Kremenek  // Construct the analysis engine.  First check if the CFG is valid.
57475d03cffe20b5c945ef04eba208efb0437339997Ted Kremenek  // FIXME: Inter-procedural analysis will need to handle invalid CFGs.
5753fd5f370a28552976c52e76c3035d79012d78ddaAnna Zaks  if (!Mgr->getCFG(D))
576f6eafcca7734274d277afa121f2c4fb025a54218Ted Kremenek    return;
5773fd5f370a28552976c52e76c3035d79012d78ddaAnna Zaks
578d4aeb8050a1d0fe47c53a73361c8b0b8ac310f46Ted Kremenek  // See if the LiveVariables analysis scales.
579d4aeb8050a1d0fe47c53a73361c8b0b8ac310f46Ted Kremenek  if (!Mgr->getAnalysisDeclContext(D)->getAnalysis<RelaxedLiveVariables>())
580d4aeb8050a1d0fe47c53a73361c8b0b8ac310f46Ted Kremenek    return;
581d4aeb8050a1d0fe47c53a73361c8b0b8ac310f46Ted Kremenek
5823bbd8cd831788c506f2980293eb3c7e1b3ca2501Anna Zaks  ExprEngine Eng(*Mgr, ObjCGCEnabled, VisitedCallees, &FunctionSummaries);
583f6eafcca7734274d277afa121f2c4fb025a54218Ted Kremenek
584f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek  // Set the graph auditor.
5856f42b62b6194f53bcbc349f5d17388e1936535d7Dylan Noblesmith  OwningPtr<ExplodedNode::Auditor> Auditor;
5863fd5f370a28552976c52e76c3035d79012d78ddaAnna Zaks  if (Mgr->shouldVisualizeUbigraph()) {
587f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek    Auditor.reset(CreateUbiViz());
588c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu    ExplodedNode::SetAuditor(Auditor.get());
589f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek  }
5901eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
591b35a74a40c1d2656a25e560e773ed48bdf49f9c0Ted Kremenek  // Execute the worklist algorithm.
592d200187bd27f9ad68699693a6e57f9ee3ff260faJordy Rose  Eng.ExecuteWorkList(Mgr->getAnalysisDeclContextManager().getStackFrame(D),
5933fd5f370a28552976c52e76c3035d79012d78ddaAnna Zaks                      Mgr->getMaxNodes());
5941eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
595f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek  // Release the auditor (if any) so that it doesn't monitor the graph
596f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek  // created BugReporter.
597c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu  ExplodedNode::SetAuditor(0);
5983df6421150271266b5a90fd4c6bfa6566c38c036Ted Kremenek
59934d7734b6ed1d9c0f647405e065251eb67f42badTed Kremenek  // Visualize the exploded graph.
6003fd5f370a28552976c52e76c3035d79012d78ddaAnna Zaks  if (Mgr->shouldVisualizeGraphviz())
6013fd5f370a28552976c52e76c3035d79012d78ddaAnna Zaks    Eng.ViewGraph(Mgr->shouldTrimGraph());
6021eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
6033df6421150271266b5a90fd4c6bfa6566c38c036Ted Kremenek  // Display warnings.
6043df6421150271266b5a90fd4c6bfa6566c38c036Ted Kremenek  Eng.getBugReporter().FlushReports();
605bc46f345838b1c0d420dbd3655c94f5f360fb5b8Ted Kremenek}
606bc46f345838b1c0d420dbd3655c94f5f360fb5b8Ted Kremenek
6076a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaksvoid AnalysisConsumer::RunPathSensitiveChecks(Decl *D,
6086a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks                                              SetOfConstDecls *Visited) {
60917a38e2636a8b1ce473fc6504c4b16cb09db29f4Jordy Rose
6104e4d08403ca5cfd4d558fa2936215d3a4e5a528dDavid Blaikie  switch (Mgr->getLangOpts().getGC()) {
61117a38e2636a8b1ce473fc6504c4b16cb09db29f4Jordy Rose  case LangOptions::NonGC:
6123fd5f370a28552976c52e76c3035d79012d78ddaAnna Zaks    ActionExprEngine(D, false, Visited);
61317a38e2636a8b1ce473fc6504c4b16cb09db29f4Jordy Rose    break;
61417a38e2636a8b1ce473fc6504c4b16cb09db29f4Jordy Rose
61517a38e2636a8b1ce473fc6504c4b16cb09db29f4Jordy Rose  case LangOptions::GCOnly:
6163fd5f370a28552976c52e76c3035d79012d78ddaAnna Zaks    ActionExprEngine(D, true, Visited);
61717a38e2636a8b1ce473fc6504c4b16cb09db29f4Jordy Rose    break;
61817a38e2636a8b1ce473fc6504c4b16cb09db29f4Jordy Rose
61917a38e2636a8b1ce473fc6504c4b16cb09db29f4Jordy Rose  case LangOptions::HybridGC:
6203fd5f370a28552976c52e76c3035d79012d78ddaAnna Zaks    ActionExprEngine(D, false, Visited);
6213fd5f370a28552976c52e76c3035d79012d78ddaAnna Zaks    ActionExprEngine(D, true, Visited);
62217a38e2636a8b1ce473fc6504c4b16cb09db29f4Jordy Rose    break;
62317a38e2636a8b1ce473fc6504c4b16cb09db29f4Jordy Rose  }
624b35a74a40c1d2656a25e560e773ed48bdf49f9c0Ted Kremenek}
625b35a74a40c1d2656a25e560e773ed48bdf49f9c0Ted Kremenek
626f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek//===----------------------------------------------------------------------===//
627f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek// AnalysisConsumer creation.
628f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek//===----------------------------------------------------------------------===//
629f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek
6309ef6537a894c33003359b1f9b9676e9178e028b7Ted KremenekASTConsumer* ento::CreateAnalysisConsumer(const Preprocessor& pp,
63108b86531ade68727c56918f162816075b87c864aJordy Rose                                          const std::string& outDir,
63208b86531ade68727c56918f162816075b87c864aJordy Rose                                          const AnalyzerOptions& opts,
63308b86531ade68727c56918f162816075b87c864aJordy Rose                                          ArrayRef<std::string> plugins) {
63408b86531ade68727c56918f162816075b87c864aJordy Rose  // Disable the effects of '-Werror' when using the AnalysisConsumer.
635efceabd2380f49306bc0229583458e93b062094bDaniel Dunbar  pp.getDiagnostics().setWarningsAsErrors(false);
636be1fe1eb12a1cb91c8e3a9fcc2db4dfe989def6cTed Kremenek
63708b86531ade68727c56918f162816075b87c864aJordy Rose  return new AnalysisConsumer(pp, outDir, opts, plugins);
638f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek}
639f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek
640f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek//===----------------------------------------------------------------------===//
641f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek// Ubigraph Visualization.  FIXME: Move to separate file.
642f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek//===----------------------------------------------------------------------===//
643f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek
644f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremeneknamespace {
6451eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
646c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xuclass UbigraphViz : public ExplodedNode::Auditor {
6476f42b62b6194f53bcbc349f5d17388e1936535d7Dylan Noblesmith  OwningPtr<raw_ostream> Out;
648710ad9343f32b33b336369b20edad1a21a0b3299Ted Kremenek  llvm::sys::Path Dir, Filename;
649f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek  unsigned Cntr;
650f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek
651f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek  typedef llvm::DenseMap<void*,unsigned> VMap;
652f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek  VMap M;
6531eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
654f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenekpublic:
6559c378f705405d37f49795d5e915989de774fe11fTed Kremenek  UbigraphViz(raw_ostream *out, llvm::sys::Path& dir,
65656b98719b0dbebb33cb228afa888c47156be2381Ted Kremenek              llvm::sys::Path& filename);
6571eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
658710ad9343f32b33b336369b20edad1a21a0b3299Ted Kremenek  ~UbigraphViz();
6591eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
6609c378f705405d37f49795d5e915989de774fe11fTed Kremenek  virtual void AddEdge(ExplodedNode *Src, ExplodedNode *Dst);
661f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek};
6621eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
663f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek} // end anonymous namespace
664f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek
665c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xustatic ExplodedNode::Auditor* CreateUbiViz() {
666f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek  std::string ErrMsg;
6671eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
668710ad9343f32b33b336369b20edad1a21a0b3299Ted Kremenek  llvm::sys::Path Dir = llvm::sys::Path::GetTemporaryDirectory(&ErrMsg);
669f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek  if (!ErrMsg.empty())
670f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek    return 0;
671f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek
672710ad9343f32b33b336369b20edad1a21a0b3299Ted Kremenek  llvm::sys::Path Filename = Dir;
673f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek  Filename.appendComponent("llvm_ubi");
674f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek  Filename.makeUnique(true,&ErrMsg);
675f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek
676f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek  if (!ErrMsg.empty())
677f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek    return 0;
678f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek
679d57a7ef9252964bc6c8471451d7bd395b0520cb8Chris Lattner  llvm::errs() << "Writing '" << Filename.str() << "'.\n";
6801eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
6816f42b62b6194f53bcbc349f5d17388e1936535d7Dylan Noblesmith  OwningPtr<llvm::raw_fd_ostream> Stream;
682b044c473a155b7e827680635c1699cb2b5b6c0eeDan Gohman  Stream.reset(new llvm::raw_fd_ostream(Filename.c_str(), ErrMsg));
683f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek
684f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek  if (!ErrMsg.empty())
685f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek    return 0;
6861eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
687710ad9343f32b33b336369b20edad1a21a0b3299Ted Kremenek  return new UbigraphViz(Stream.take(), Dir, Filename);
688f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek}
689f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek
6909c378f705405d37f49795d5e915989de774fe11fTed Kremenekvoid UbigraphViz::AddEdge(ExplodedNode *Src, ExplodedNode *Dst) {
6911eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
69245479c88c8a44c55d27c3bd855273bb318082f37Ted Kremenek  assert (Src != Dst && "Self-edges are not allowed.");
6931eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
694f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek  // Lookup the Src.  If it is a new node, it's a root.
695f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek  VMap::iterator SrcI= M.find(Src);
696f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek  unsigned SrcID;
6971eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
698f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek  if (SrcI == M.end()) {
699f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek    M[Src] = SrcID = Cntr++;
700f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek    *Out << "('vertex', " << SrcID << ", ('color','#00ff00'))\n";
701f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek  }
702f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek  else
703f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek    SrcID = SrcI->second;
7041eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
705f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek  // Lookup the Dst.
706f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek  VMap::iterator DstI= M.find(Dst);
707f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek  unsigned DstID;
708f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek
709f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek  if (DstI == M.end()) {
710f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek    M[Dst] = DstID = Cntr++;
711f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek    *Out << "('vertex', " << DstID << ")\n";
712f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek  }
71356b98719b0dbebb33cb228afa888c47156be2381Ted Kremenek  else {
71456b98719b0dbebb33cb228afa888c47156be2381Ted Kremenek    // We have hit DstID before.  Change its style to reflect a cache hit.
715f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek    DstID = DstI->second;
71656b98719b0dbebb33cb228afa888c47156be2381Ted Kremenek    *Out << "('change_vertex_style', " << DstID << ", 1)\n";
71756b98719b0dbebb33cb228afa888c47156be2381Ted Kremenek  }
718f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek
719f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek  // Add the edge.
7201eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  *Out << "('edge', " << SrcID << ", " << DstID
721d1289327f7d2126d732e23cc189ecd0aa5d07cbbTed Kremenek       << ", ('arrow','true'), ('oriented', 'true'))\n";
722f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek}
723f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek
7249c378f705405d37f49795d5e915989de774fe11fTed KremenekUbigraphViz::UbigraphViz(raw_ostream *out, llvm::sys::Path& dir,
72556b98719b0dbebb33cb228afa888c47156be2381Ted Kremenek                         llvm::sys::Path& filename)
72656b98719b0dbebb33cb228afa888c47156be2381Ted Kremenek  : Out(out), Dir(dir), Filename(filename), Cntr(0) {
72756b98719b0dbebb33cb228afa888c47156be2381Ted Kremenek
72856b98719b0dbebb33cb228afa888c47156be2381Ted Kremenek  *Out << "('vertex_style_attribute', 0, ('shape', 'icosahedron'))\n";
72956b98719b0dbebb33cb228afa888c47156be2381Ted Kremenek  *Out << "('vertex_style', 1, 0, ('shape', 'sphere'), ('color', '#ffcc66'),"
73056b98719b0dbebb33cb228afa888c47156be2381Ted Kremenek          " ('size', '1.5'))\n";
73156b98719b0dbebb33cb228afa888c47156be2381Ted Kremenek}
73256b98719b0dbebb33cb228afa888c47156be2381Ted Kremenek
733710ad9343f32b33b336369b20edad1a21a0b3299Ted KremenekUbigraphViz::~UbigraphViz() {
734710ad9343f32b33b336369b20edad1a21a0b3299Ted Kremenek  Out.reset(0);
7356cb7c1a43b0c8f739d1f54b7fdae5ede86033496Benjamin Kramer  llvm::errs() << "Running 'ubiviz' program... ";
736710ad9343f32b33b336369b20edad1a21a0b3299Ted Kremenek  std::string ErrMsg;
737710ad9343f32b33b336369b20edad1a21a0b3299Ted Kremenek  llvm::sys::Path Ubiviz = llvm::sys::Program::FindProgramByName("ubiviz");
738710ad9343f32b33b336369b20edad1a21a0b3299Ted Kremenek  std::vector<const char*> args;
739710ad9343f32b33b336369b20edad1a21a0b3299Ted Kremenek  args.push_back(Ubiviz.c_str());
740710ad9343f32b33b336369b20edad1a21a0b3299Ted Kremenek  args.push_back(Filename.c_str());
741710ad9343f32b33b336369b20edad1a21a0b3299Ted Kremenek  args.push_back(0);
7421eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
743710ad9343f32b33b336369b20edad1a21a0b3299Ted Kremenek  if (llvm::sys::Program::ExecuteAndWait(Ubiviz, &args[0],0,0,0,0,&ErrMsg)) {
7446cb7c1a43b0c8f739d1f54b7fdae5ede86033496Benjamin Kramer    llvm::errs() << "Error viewing graph: " << ErrMsg << "\n";
745710ad9343f32b33b336369b20edad1a21a0b3299Ted Kremenek  }
7461eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
747710ad9343f32b33b336369b20edad1a21a0b3299Ted Kremenek  // Delete the directory.
7481eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  Dir.eraseFromDisk(true);
749932680ecdeab4c216ce7c0736093d3dcd2f60f6dDaniel Dunbar}
750