AnalysisConsumer.cpp revision cb0a5039c243f5b0c178e70f424adac334e5789b
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"
2527af04bcca46f8a3374586be1301477f9123f5e1Argyrios Kyrtzidis#include "clang/StaticAnalyzer/Frontend/CheckerRegistration.h"
2643dee220252ef0b42c5f8a3bb1eca97f84f2565fArgyrios Kyrtzidis#include "clang/StaticAnalyzer/Core/CheckerManager.h"
2721142581d55918beed544a757e4af3bb865b1812Ted Kremenek#include "clang/StaticAnalyzer/Checkers/LocalCheckers.h"
289b663716449b618ba0390b1dbebc54fa8e971124Ted Kremenek#include "clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h"
299b663716449b618ba0390b1dbebc54fa8e971124Ted Kremenek#include "clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h"
309b663716449b618ba0390b1dbebc54fa8e971124Ted Kremenek#include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h"
319b663716449b618ba0390b1dbebc54fa8e971124Ted Kremenek#include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
32f39d962cf84f46d2c0512157259ae1d41a1a5173David Blaikie#include "clang/StaticAnalyzer/Core/PathDiagnosticConsumers.h"
33a7af5ea88a6c5bdf87497cca6c20831e8c546751Argyrios Kyrtzidis
34efceabd2380f49306bc0229583458e93b062094bDaniel Dunbar#include "clang/Basic/FileManager.h"
35efceabd2380f49306bc0229583458e93b062094bDaniel Dunbar#include "clang/Basic/SourceManager.h"
369b414d3e2d0cb84512b55a3275a98490b090162aDaniel Dunbar#include "clang/Frontend/AnalyzerOptions.h"
37efceabd2380f49306bc0229583458e93b062094bDaniel Dunbar#include "clang/Lex/Preprocessor.h"
38f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek#include "llvm/Support/raw_ostream.h"
3903013fa9a0bf1ef4b907f5fec006c8f4000fdd21Michael J. Spencer#include "llvm/Support/Path.h"
4003013fa9a0bf1ef4b907f5fec006c8f4000fdd21Michael J. Spencer#include "llvm/Support/Program.h"
41d38f79543136ba68cd14b1dab0856474df1fbfd5Anna Zaks#include "llvm/Support/Timer.h"
42d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks#include "llvm/ADT/DepthFirstIterator.h"
436cb7c1a43b0c8f739d1f54b7fdae5ede86033496Benjamin Kramer#include "llvm/ADT/OwningPtr.h"
446a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks#include "llvm/ADT/SmallPtrSet.h"
4581fb169f42769e02c7425b23885a261c025fd5e6Anna Zaks#include "llvm/ADT/Statistic.h"
46db09a4dee28a4515438af60f2d2b4a83e4965c31Ted Kremenek
477fe8dcef71ae56e43fd7df345db2895f84f2d0caAnna Zaks#include <queue>
487fe8dcef71ae56e43fd7df345db2895f84f2d0caAnna Zaks
49f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenekusing namespace clang;
509ef6537a894c33003359b1f9b9676e9178e028b7Ted Kremenekusing namespace ento;
51d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaksusing llvm::SmallPtrSet;
52f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek
53c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xustatic ExplodedNode::Auditor* CreateUbiViz();
54ff944a8c481d6c0f1ad2633e4be9bf8b1dd2a09fZhongxing Xu
553fd5f370a28552976c52e76c3035d79012d78ddaAnna ZaksSTATISTIC(NumFunctionTopLevel, "The # of functions at top level.");
56d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna ZaksSTATISTIC(NumFunctionsAnalyzed, "The # of functions analysed (as top level).");
57e62f048960645b79363408fdead53fec2a063c52Anna ZaksSTATISTIC(NumBlocksInAnalyzedFunctions,
58e62f048960645b79363408fdead53fec2a063c52Anna Zaks                     "The # of basic blocks in the analyzed functions.");
59e62f048960645b79363408fdead53fec2a063c52Anna ZaksSTATISTIC(PercentReachableBlocks, "The % of reachable basic blocks.");
60d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks
61be1fe1eb12a1cb91c8e3a9fcc2db4dfe989def6cTed Kremenek//===----------------------------------------------------------------------===//
62f39d962cf84f46d2c0512157259ae1d41a1a5173David Blaikie// Special PathDiagnosticConsumers.
63f75560670bcdd59b051149bdece3eac14e313853Ted Kremenek//===----------------------------------------------------------------------===//
64f75560670bcdd59b051149bdece3eac14e313853Ted Kremenek
65ef3643fbbbf66247c5e205497fae0f46e240c143David Blaikiestatic PathDiagnosticConsumer*
66ef3643fbbbf66247c5e205497fae0f46e240c143David BlaikiecreatePlistHTMLDiagnosticConsumer(const std::string& prefix,
67efceabd2380f49306bc0229583458e93b062094bDaniel Dunbar                                const Preprocessor &PP) {
68ef3643fbbbf66247c5e205497fae0f46e240c143David Blaikie  PathDiagnosticConsumer *PD =
69ef3643fbbbf66247c5e205497fae0f46e240c143David Blaikie    createHTMLDiagnosticConsumer(llvm::sys::path::parent_path(prefix), PP);
70ef3643fbbbf66247c5e205497fae0f46e240c143David Blaikie  return createPlistDiagnosticConsumer(prefix, PP, PD);
71f75560670bcdd59b051149bdece3eac14e313853Ted Kremenek}
72f75560670bcdd59b051149bdece3eac14e313853Ted Kremenek
73f75560670bcdd59b051149bdece3eac14e313853Ted Kremenek//===----------------------------------------------------------------------===//
74f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek// AnalysisConsumer declaration.
75f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek//===----------------------------------------------------------------------===//
76f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek
77f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremeneknamespace {
78f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek
79aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaksclass AnalysisConsumer : public ASTConsumer,
80aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks                         public RecursiveASTVisitor<AnalysisConsumer> {
81aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks  enum AnalysisMode {
82aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks    ANALYSIS_SYNTAX,
83aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks    ANALYSIS_PATH,
84aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks    ANALYSIS_ALL
85aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks  };
86aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks
87aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks  /// Mode of the analyzes while recursively visiting Decls.
88aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks  AnalysisMode RecVisitorMode;
89aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks  /// Bug Reporter to use while recursively visiting Decls.
90aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks  BugReporter *RecVisitorBR;
91aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks
92ed8afacb8118b71bcfa8017059e51da325e7691bZhongxing Xupublic:
939c378f705405d37f49795d5e915989de774fe11fTed Kremenek  ASTContext *Ctx;
941d9cbeb76cf4c36acf5545028e2b2ac207086442Ted Kremenek  const Preprocessor &PP;
951d9cbeb76cf4c36acf5545028e2b2ac207086442Ted Kremenek  const std::string OutDir;
961d9cbeb76cf4c36acf5545028e2b2ac207086442Ted Kremenek  AnalyzerOptions Opts;
9708b86531ade68727c56918f162816075b87c864aJordy Rose  ArrayRef<std::string> Plugins;
98d07a0d0279c09d1017f8450fce575a94dc9703c0Zhongxing Xu
996a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks  /// \brief Stores the declarations from the local translation unit.
1006a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks  /// Note, we pre-compute the local declarations at parse time as an
1016a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks  /// optimization to make sure we do not deserialize everything from disk.
1026a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks  /// The local declaration to all declarations ratio might be very small when
1036a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks  /// working with a PCH file.
1046a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks  SetOfDecls LocalTUDecls;
1056a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks
106cb0a5039c243f5b0c178e70f424adac334e5789bTed Kremenek  SetOfDecls::Factory LocalTUDeclsFactory;
107cb0a5039c243f5b0c178e70f424adac334e5789bTed Kremenek
1081d9cbeb76cf4c36acf5545028e2b2ac207086442Ted Kremenek  // PD is owned by AnalysisManager.
109ef3643fbbbf66247c5e205497fae0f46e240c143David Blaikie  PathDiagnosticConsumer *PD;
110d07a0d0279c09d1017f8450fce575a94dc9703c0Zhongxing Xu
1111d9cbeb76cf4c36acf5545028e2b2ac207086442Ted Kremenek  StoreManagerCreator CreateStoreMgr;
1121d9cbeb76cf4c36acf5545028e2b2ac207086442Ted Kremenek  ConstraintManagerCreator CreateConstraintMgr;
113f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek
1146f42b62b6194f53bcbc349f5d17388e1936535d7Dylan Noblesmith  OwningPtr<CheckerManager> checkerMgr;
1156f42b62b6194f53bcbc349f5d17388e1936535d7Dylan Noblesmith  OwningPtr<AnalysisManager> Mgr;
116c471e7b44e63ff1b46b480e723c4130aeaef5a8aZhongxing Xu
117d38f79543136ba68cd14b1dab0856474df1fbfd5Anna Zaks  /// Time the analyzes time of each translation unit.
118d38f79543136ba68cd14b1dab0856474df1fbfd5Anna Zaks  static llvm::Timer* TUTotalTimer;
119d38f79543136ba68cd14b1dab0856474df1fbfd5Anna Zaks
1203bbd8cd831788c506f2980293eb3c7e1b3ca2501Anna Zaks  /// The information about analyzed functions shared throughout the
1213bbd8cd831788c506f2980293eb3c7e1b3ca2501Anna Zaks  /// translation unit.
1223bbd8cd831788c506f2980293eb3c7e1b3ca2501Anna Zaks  FunctionSummariesTy FunctionSummaries;
1233bbd8cd831788c506f2980293eb3c7e1b3ca2501Anna Zaks
1241d9cbeb76cf4c36acf5545028e2b2ac207086442Ted Kremenek  AnalysisConsumer(const Preprocessor& pp,
1251d9cbeb76cf4c36acf5545028e2b2ac207086442Ted Kremenek                   const std::string& outdir,
12608b86531ade68727c56918f162816075b87c864aJordy Rose                   const AnalyzerOptions& opts,
12708b86531ade68727c56918f162816075b87c864aJordy Rose                   ArrayRef<std::string> plugins)
128aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks    : RecVisitorMode(ANALYSIS_ALL), RecVisitorBR(0),
129aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks      Ctx(0), PP(pp), OutDir(outdir), Opts(opts), Plugins(plugins), PD(0) {
1301d9cbeb76cf4c36acf5545028e2b2ac207086442Ted Kremenek    DigestAnalyzerOptions();
131d38f79543136ba68cd14b1dab0856474df1fbfd5Anna Zaks    if (Opts.PrintStats) {
132d38f79543136ba68cd14b1dab0856474df1fbfd5Anna Zaks      llvm::EnableStatistics();
133d38f79543136ba68cd14b1dab0856474df1fbfd5Anna Zaks      TUTotalTimer = new llvm::Timer("Analyzer Total Time");
134d38f79543136ba68cd14b1dab0856474df1fbfd5Anna Zaks    }
135d38f79543136ba68cd14b1dab0856474df1fbfd5Anna Zaks  }
136d38f79543136ba68cd14b1dab0856474df1fbfd5Anna Zaks
137d38f79543136ba68cd14b1dab0856474df1fbfd5Anna Zaks  ~AnalysisConsumer() {
138d38f79543136ba68cd14b1dab0856474df1fbfd5Anna Zaks    if (Opts.PrintStats)
139d38f79543136ba68cd14b1dab0856474df1fbfd5Anna Zaks      delete TUTotalTimer;
1401d9cbeb76cf4c36acf5545028e2b2ac207086442Ted Kremenek  }
141fda7832b000ff8927386f093b52c067641679469Zhongxing Xu
1421d9cbeb76cf4c36acf5545028e2b2ac207086442Ted Kremenek  void DigestAnalyzerOptions() {
143ef3643fbbbf66247c5e205497fae0f46e240c143David Blaikie    // Create the PathDiagnosticConsumer.
1441d9cbeb76cf4c36acf5545028e2b2ac207086442Ted Kremenek    if (!OutDir.empty()) {
1451d9cbeb76cf4c36acf5545028e2b2ac207086442Ted Kremenek      switch (Opts.AnalysisDiagOpt) {
1461d9cbeb76cf4c36acf5545028e2b2ac207086442Ted Kremenek      default:
147fda7832b000ff8927386f093b52c067641679469Zhongxing Xu#define ANALYSIS_DIAGNOSTICS(NAME, CMDFLAG, DESC, CREATEFN, AUTOCREATE) \
1481d9cbeb76cf4c36acf5545028e2b2ac207086442Ted Kremenek        case PD_##NAME: PD = CREATEFN(OutDir, PP); break;
149fda7832b000ff8927386f093b52c067641679469Zhongxing Xu#include "clang/Frontend/Analyses.def"
150fda7832b000ff8927386f093b52c067641679469Zhongxing Xu      }
151a599ae8826b01c0160a519b0fc5a4871f599bf04Argyrios Kyrtzidis    } else if (Opts.AnalysisDiagOpt == PD_TEXT) {
152a599ae8826b01c0160a519b0fc5a4871f599bf04Argyrios Kyrtzidis      // Create the text client even without a specified output file since
153a599ae8826b01c0160a519b0fc5a4871f599bf04Argyrios Kyrtzidis      // it just uses diagnostic notes.
154ef3643fbbbf66247c5e205497fae0f46e240c143David Blaikie      PD = createTextPathDiagnosticConsumer("", PP);
1551d9cbeb76cf4c36acf5545028e2b2ac207086442Ted Kremenek    }
156fda7832b000ff8927386f093b52c067641679469Zhongxing Xu
1571d9cbeb76cf4c36acf5545028e2b2ac207086442Ted Kremenek    // Create the analyzer component creators.
1585f83d6f36a7308eef21d87104fd70c421e854448Argyrios Kyrtzidis    switch (Opts.AnalysisStoreOpt) {
1595f83d6f36a7308eef21d87104fd70c421e854448Argyrios Kyrtzidis    default:
160b219cfc4d75f0a03630b7c4509ef791b7e97b2c8David Blaikie      llvm_unreachable("Unknown store manager.");
161fda7832b000ff8927386f093b52c067641679469Zhongxing Xu#define ANALYSIS_STORE(NAME, CMDFLAG, DESC, CREATEFN)           \
1625f83d6f36a7308eef21d87104fd70c421e854448Argyrios Kyrtzidis      case NAME##Model: CreateStoreMgr = CREATEFN; break;
163fda7832b000ff8927386f093b52c067641679469Zhongxing Xu#include "clang/Frontend/Analyses.def"
1641d9cbeb76cf4c36acf5545028e2b2ac207086442Ted Kremenek    }
1651eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
1665f83d6f36a7308eef21d87104fd70c421e854448Argyrios Kyrtzidis    switch (Opts.AnalysisConstraintsOpt) {
1675f83d6f36a7308eef21d87104fd70c421e854448Argyrios Kyrtzidis    default:
168b219cfc4d75f0a03630b7c4509ef791b7e97b2c8David Blaikie      llvm_unreachable("Unknown store manager.");
169fda7832b000ff8927386f093b52c067641679469Zhongxing Xu#define ANALYSIS_CONSTRAINTS(NAME, CMDFLAG, DESC, CREATEFN)     \
1705f83d6f36a7308eef21d87104fd70c421e854448Argyrios Kyrtzidis      case NAME##Model: CreateConstraintMgr = CREATEFN; break;
171fda7832b000ff8927386f093b52c067641679469Zhongxing Xu#include "clang/Frontend/Analyses.def"
172fda7832b000ff8927386f093b52c067641679469Zhongxing Xu    }
1731d9cbeb76cf4c36acf5545028e2b2ac207086442Ted Kremenek  }
174f6eafcca7734274d277afa121f2c4fb025a54218Ted Kremenek
175aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks  void DisplayFunction(const Decl *D, AnalysisMode Mode) {
176c4a1437c15da43eb8d2601cdce13161ef41a4389Ted Kremenek    if (!Opts.AnalyzerDisplayProgress)
1771d9cbeb76cf4c36acf5545028e2b2ac207086442Ted Kremenek      return;
178f6eafcca7734274d277afa121f2c4fb025a54218Ted Kremenek
179fc576514d06c46a7cac49500169411d82f38d04bTed Kremenek    SourceManager &SM = Mgr->getASTContext().getSourceManager();
180fc576514d06c46a7cac49500169411d82f38d04bTed Kremenek    PresumedLoc Loc = SM.getPresumedLoc(D->getLocation());
181cb7b1e17b63967317ab5cc55682168cf0380519aDouglas Gregor    if (Loc.isValid()) {
182aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks      llvm::errs() << "ANALYZE";
183aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks      switch (Mode) {
184aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks        case ANALYSIS_SYNTAX: llvm::errs() << "(Syntax)"; break;
185aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks        case ANALYSIS_PATH: llvm::errs() << "(Path Sensitive)"; break;
186aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks        case ANALYSIS_ALL: break;
187aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks      };
188aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks      llvm::errs() << ": " << Loc.getFilename();
189cb7b1e17b63967317ab5cc55682168cf0380519aDouglas Gregor      if (isa<FunctionDecl>(D) || isa<ObjCMethodDecl>(D)) {
190cb7b1e17b63967317ab5cc55682168cf0380519aDouglas Gregor        const NamedDecl *ND = cast<NamedDecl>(D);
191b8989f27f116ff2400e92a52c067a69846119eb5Benjamin Kramer        llvm::errs() << ' ' << *ND << '\n';
192cb7b1e17b63967317ab5cc55682168cf0380519aDouglas Gregor      }
193cb7b1e17b63967317ab5cc55682168cf0380519aDouglas Gregor      else if (isa<BlockDecl>(D)) {
194cb7b1e17b63967317ab5cc55682168cf0380519aDouglas Gregor        llvm::errs() << ' ' << "block(line:" << Loc.getLine() << ",col:"
195cb7b1e17b63967317ab5cc55682168cf0380519aDouglas Gregor                     << Loc.getColumn() << '\n';
196cb7b1e17b63967317ab5cc55682168cf0380519aDouglas Gregor      }
197cb7b1e17b63967317ab5cc55682168cf0380519aDouglas Gregor      else if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D)) {
198cb7b1e17b63967317ab5cc55682168cf0380519aDouglas Gregor        Selector S = MD->getSelector();
199cb7b1e17b63967317ab5cc55682168cf0380519aDouglas Gregor        llvm::errs() << ' ' << S.getAsString();
200cb7b1e17b63967317ab5cc55682168cf0380519aDouglas Gregor      }
20135fa76d0bb6fb8c86159a7506efd094a4fe376d2Ted Kremenek    }
2021d9cbeb76cf4c36acf5545028e2b2ac207086442Ted Kremenek  }
2031eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
2041d9cbeb76cf4c36acf5545028e2b2ac207086442Ted Kremenek  virtual void Initialize(ASTContext &Context) {
2051d9cbeb76cf4c36acf5545028e2b2ac207086442Ted Kremenek    Ctx = &Context;
2064e4d08403ca5cfd4d558fa2936215d3a4e5a528dDavid Blaikie    checkerMgr.reset(createCheckerManager(Opts, PP.getLangOpts(), Plugins,
20708b86531ade68727c56918f162816075b87c864aJordy Rose                                          PP.getDiagnostics()));
2081d9cbeb76cf4c36acf5545028e2b2ac207086442Ted Kremenek    Mgr.reset(new AnalysisManager(*Ctx, PP.getDiagnostics(),
2094e4d08403ca5cfd4d558fa2936215d3a4e5a528dDavid Blaikie                                  PP.getLangOpts(), PD,
2101d9cbeb76cf4c36acf5545028e2b2ac207086442Ted Kremenek                                  CreateStoreMgr, CreateConstraintMgr,
21143dee220252ef0b42c5f8a3bb1eca97f84f2565fArgyrios Kyrtzidis                                  checkerMgr.get(),
2126362b893731ccf4480a96527db9e55e04b801503Zhongxing Xu                                  Opts.MaxNodes, Opts.MaxLoop,
2131d9cbeb76cf4c36acf5545028e2b2ac207086442Ted Kremenek                                  Opts.VisualizeEGDot, Opts.VisualizeEGUbi,
214d30952838421ddfb9f7e346b2ba8213889a5f789Anna Zaks                                  Opts.AnalysisPurgeOpt, Opts.EagerlyAssume,
21566253352131e3e7a22b3bfd0e180607aa2bfb988Anna Zaks                                  Opts.TrimGraph,
2169121ba232903ebe61e7bbe14ca294cf0f07dfa96Marcin Swiderski                                  Opts.UnoptimizedCFG, Opts.CFGAddImplicitDtors,
217d767d81290288c030f3be0be1d3e62b9c8df51dcTed Kremenek                                  Opts.CFGAddInitializers,
2188235f9c9c8b3d1737d1c6bd57f7ba3f616b92392Anna Zaks                                  Opts.EagerlyTrimEGraph,
21966253352131e3e7a22b3bfd0e180607aa2bfb988Anna Zaks                                  Opts.IPAMode,
2208235f9c9c8b3d1737d1c6bd57f7ba3f616b92392Anna Zaks                                  Opts.InlineMaxStackDepth,
22166253352131e3e7a22b3bfd0e180607aa2bfb988Anna Zaks                                  Opts.InlineMaxFunctionSize,
2225903a373db3d27794c90b25687e0dd6adb0e497dAnna Zaks                                  Opts.InliningMode,
223b47dbcbc12430fdf3e5a5b9f59cdec5480e89e75Anna Zaks                                  Opts.NoRetryExhausted));
2241d9cbeb76cf4c36acf5545028e2b2ac207086442Ted Kremenek  }
2251eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
2266a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks  /// \brief Store the top level decls in the set to be processed later on.
2276a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks  /// (Doing this pre-processing avoids deserialization of data from PCH.)
2286a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks  virtual bool HandleTopLevelDecl(DeclGroupRef D);
2296a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks  virtual void HandleTopLevelDeclInObjCContainer(DeclGroupRef D);
2306a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks
2311d9cbeb76cf4c36acf5545028e2b2ac207086442Ted Kremenek  virtual void HandleTranslationUnit(ASTContext &C);
23214cc9451de4a9539bf79e4e5d63248c2377426dbTed Kremenek
2336a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks  /// \brief Build the call graph for all the top level decls of this TU and
2346a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks  /// use it to define the order in which the functions should be visited.
2356a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks  void HandleDeclsGallGraph();
236aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks
237aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks  /// \brief Run analyzes(syntax or path sensitive) on the given function.
238aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks  /// \param Mode - determines if we are requesting syntax only or path
239aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks  /// sensitive only analysis.
240aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks  /// \param VisitedCallees - The output parameter, which is populated with the
241aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks  /// set of functions which should be considered analyzed after analyzing the
242aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks  /// given root function.
2436a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks  void HandleCode(Decl *D, AnalysisMode Mode,
2446a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks                  SetOfConstDecls *VisitedCallees = 0);
245aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks
2466a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks  void RunPathSensitiveChecks(Decl *D, SetOfConstDecls *VisitedCallees);
2476a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks  void ActionExprEngine(Decl *D, bool ObjCGCEnabled,
2486a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks                        SetOfConstDecls *VisitedCallees);
249aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks
250aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks  /// Visitors for the RecursiveASTVisitor.
251aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks
252aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks  /// Handle callbacks for arbitrary Decls.
253aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks  bool VisitDecl(Decl *D) {
254aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks    checkerMgr->runCheckersOnASTDecl(D, *Mgr, *RecVisitorBR);
255aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks    return true;
256aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks  }
257aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks
258aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks  bool VisitFunctionDecl(FunctionDecl *FD) {
259aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks    IdentifierInfo *II = FD->getIdentifier();
260aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks    if (II && II->getName().startswith("__inline"))
261aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks      return true;
262aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks
263aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks    // We skip function template definitions, as their semantics is
264aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks    // only determined when they are instantiated.
265aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks    if (FD->isThisDeclarationADefinition() &&
266aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks        !FD->isDependentContext()) {
267aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks      HandleCode(FD, RecVisitorMode);
268aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks    }
269aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks    return true;
270aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks  }
271aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks
272aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks  bool VisitObjCMethodDecl(ObjCMethodDecl *MD) {
273aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks    checkerMgr->runCheckersOnASTDecl(MD, *Mgr, *RecVisitorBR);
274aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks    if (MD->isThisDeclarationADefinition())
275aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks      HandleCode(MD, RecVisitorMode);
276aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks    return true;
277aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks  }
2786a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks
2796a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaksprivate:
2806a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks  void storeTopLevelDecls(DeclGroupRef DG);
2816a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks
2826a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks  /// \brief Check if we should skip (not analyze) the given function.
2836a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks  bool skipFunction(Decl *D);
2846a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks
2851d9cbeb76cf4c36acf5545028e2b2ac207086442Ted Kremenek};
286f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek} // end anonymous namespace
287f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek
288aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks
289f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek//===----------------------------------------------------------------------===//
290f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek// AnalysisConsumer implementation.
291f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek//===----------------------------------------------------------------------===//
292d38f79543136ba68cd14b1dab0856474df1fbfd5Anna Zaksllvm::Timer* AnalysisConsumer::TUTotalTimer = 0;
293f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek
2946a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaksbool AnalysisConsumer::HandleTopLevelDecl(DeclGroupRef DG) {
2956a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks  storeTopLevelDecls(DG);
2966a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks  return true;
2976a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks}
2986a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks
2996a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaksvoid AnalysisConsumer::HandleTopLevelDeclInObjCContainer(DeclGroupRef DG) {
3006a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks  storeTopLevelDecls(DG);
3016a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks}
3026a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks
3036a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaksvoid AnalysisConsumer::storeTopLevelDecls(DeclGroupRef DG) {
3046a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks  for (DeclGroupRef::iterator I = DG.begin(), E = DG.end(); I != E; ++I) {
3056a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks
3066a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks    // Skip ObjCMethodDecl, wait for the objc container to avoid
3076a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks    // analyzing twice.
3086a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks    if (isa<ObjCMethodDecl>(*I))
3096a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks      continue;
3106a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks
311cb0a5039c243f5b0c178e70f424adac334e5789bTed Kremenek    // We use an ImmutableList to avoid issues with invalidating iterators
312cb0a5039c243f5b0c178e70f424adac334e5789bTed Kremenek    // to the list while we are traversing it.
313cb0a5039c243f5b0c178e70f424adac334e5789bTed Kremenek    LocalTUDecls = LocalTUDeclsFactory.add(*I, LocalTUDecls);
3146a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks  }
3156a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks}
3166a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks
3176a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaksvoid AnalysisConsumer::HandleDeclsGallGraph() {
318d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks  // Otherwise, use the Callgraph to derive the order.
319d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks  // Build the Call Graph.
320d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks  CallGraph CG;
3216a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks  // Add all the top level declarations to the graph.
322cb0a5039c243f5b0c178e70f424adac334e5789bTed Kremenek  //
323cb0a5039c243f5b0c178e70f424adac334e5789bTed Kremenek  // NOTE: We use an ImmutableList to avoid issues with invalidating iterators
324cb0a5039c243f5b0c178e70f424adac334e5789bTed Kremenek  // to the list while we are traversing it.
3256a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks  for (SetOfDecls::iterator I = LocalTUDecls.begin(),
3266a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks                            E = LocalTUDecls.end(); I != E; ++I)
3276a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks    CG.addToCallGraph(*I);
328d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks
329d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks  // Find the top level nodes - children of root + the unreachable (parentless)
330d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks  // nodes.
3313fd5f370a28552976c52e76c3035d79012d78ddaAnna Zaks  llvm::SmallVector<CallGraphNode*, 24> TopLevelFunctions;
332b990d039c7e01ad0055dcbd1e13a691813397b96Anna Zaks  for (CallGraph::nodes_iterator TI = CG.parentless_begin(),
333b990d039c7e01ad0055dcbd1e13a691813397b96Anna Zaks                                 TE = CG.parentless_end(); TI != TE; ++TI) {
334b990d039c7e01ad0055dcbd1e13a691813397b96Anna Zaks    TopLevelFunctions.push_back(*TI);
335b990d039c7e01ad0055dcbd1e13a691813397b96Anna Zaks    NumFunctionTopLevel++;
336b990d039c7e01ad0055dcbd1e13a691813397b96Anna Zaks  }
337d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks  CallGraphNode *Entry = CG.getRoot();
338d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks  for (CallGraphNode::iterator I = Entry->begin(),
3393fd5f370a28552976c52e76c3035d79012d78ddaAnna Zaks                               E = Entry->end(); I != E; ++I) {
340d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks    TopLevelFunctions.push_back(*I);
3413fd5f370a28552976c52e76c3035d79012d78ddaAnna Zaks    NumFunctionTopLevel++;
3423fd5f370a28552976c52e76c3035d79012d78ddaAnna Zaks  }
343d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks
344b990d039c7e01ad0055dcbd1e13a691813397b96Anna Zaks  // Make sure the nodes are sorted in order reverse of their definition in the
345b990d039c7e01ad0055dcbd1e13a691813397b96Anna Zaks  // translation unit. This step is very important for performance. It ensures
346b990d039c7e01ad0055dcbd1e13a691813397b96Anna Zaks  // that we analyze the root functions before the externally available
347b990d039c7e01ad0055dcbd1e13a691813397b96Anna Zaks  // subroutines.
348cb0a5039c243f5b0c178e70f424adac334e5789bTed Kremenek  std::deque<CallGraphNode*> BFSQueue;
349b990d039c7e01ad0055dcbd1e13a691813397b96Anna Zaks  for (llvm::SmallVector<CallGraphNode*, 24>::reverse_iterator
350b990d039c7e01ad0055dcbd1e13a691813397b96Anna Zaks         TI = TopLevelFunctions.rbegin(), TE = TopLevelFunctions.rend();
3517fe8dcef71ae56e43fd7df345db2895f84f2d0caAnna Zaks         TI != TE; ++TI)
352cb0a5039c243f5b0c178e70f424adac334e5789bTed Kremenek    BFSQueue.push_front(*TI);
353d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks
3547fe8dcef71ae56e43fd7df345db2895f84f2d0caAnna Zaks  // BFS over all of the functions, while skipping the ones inlined into
3557fe8dcef71ae56e43fd7df345db2895f84f2d0caAnna Zaks  // the previously processed functions. Use external Visited set, which is
356d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks  // also modified when we inline a function.
357d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks  SmallPtrSet<CallGraphNode*,24> Visited;
3587fe8dcef71ae56e43fd7df345db2895f84f2d0caAnna Zaks  while(!BFSQueue.empty()) {
3597fe8dcef71ae56e43fd7df345db2895f84f2d0caAnna Zaks    CallGraphNode *N = BFSQueue.front();
360cb0a5039c243f5b0c178e70f424adac334e5789bTed Kremenek    BFSQueue.pop_front();
3617fe8dcef71ae56e43fd7df345db2895f84f2d0caAnna Zaks
3627fe8dcef71ae56e43fd7df345db2895f84f2d0caAnna Zaks    // Skip the functions which have been processed already or previously
3637fe8dcef71ae56e43fd7df345db2895f84f2d0caAnna Zaks    // inlined.
3647fe8dcef71ae56e43fd7df345db2895f84f2d0caAnna Zaks    if (Visited.count(N))
3657fe8dcef71ae56e43fd7df345db2895f84f2d0caAnna Zaks      continue;
3667fe8dcef71ae56e43fd7df345db2895f84f2d0caAnna Zaks
3677fe8dcef71ae56e43fd7df345db2895f84f2d0caAnna Zaks    // Analyze the function.
3686a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks    SetOfConstDecls VisitedCallees;
3697fe8dcef71ae56e43fd7df345db2895f84f2d0caAnna Zaks    Decl *D = N->getDecl();
3707fe8dcef71ae56e43fd7df345db2895f84f2d0caAnna Zaks    assert(D);
3717fe8dcef71ae56e43fd7df345db2895f84f2d0caAnna Zaks    HandleCode(D, ANALYSIS_PATH,
3727fe8dcef71ae56e43fd7df345db2895f84f2d0caAnna Zaks               (Mgr->InliningMode == All ? 0 : &VisitedCallees));
3737fe8dcef71ae56e43fd7df345db2895f84f2d0caAnna Zaks
3747fe8dcef71ae56e43fd7df345db2895f84f2d0caAnna Zaks    // Add the visited callees to the global visited set.
375cb0a5039c243f5b0c178e70f424adac334e5789bTed Kremenek    for (SetOfConstDecls::iterator I = VisitedCallees.begin(),
376cb0a5039c243f5b0c178e70f424adac334e5789bTed Kremenek                                   E = VisitedCallees.end(); I != E; ++I) {
3777fe8dcef71ae56e43fd7df345db2895f84f2d0caAnna Zaks      CallGraphNode *VN = CG.getNode(*I);
3787fe8dcef71ae56e43fd7df345db2895f84f2d0caAnna Zaks      if (VN)
3797fe8dcef71ae56e43fd7df345db2895f84f2d0caAnna Zaks        Visited.insert(VN);
3807fe8dcef71ae56e43fd7df345db2895f84f2d0caAnna Zaks    }
3817fe8dcef71ae56e43fd7df345db2895f84f2d0caAnna Zaks    Visited.insert(N);
3827fe8dcef71ae56e43fd7df345db2895f84f2d0caAnna Zaks
3837fe8dcef71ae56e43fd7df345db2895f84f2d0caAnna Zaks    // Push the children into the queue.
3847fe8dcef71ae56e43fd7df345db2895f84f2d0caAnna Zaks    for (CallGraphNode::const_iterator CI = N->begin(),
3857fe8dcef71ae56e43fd7df345db2895f84f2d0caAnna Zaks                                       CE = N->end(); CI != CE; ++CI) {
386cb0a5039c243f5b0c178e70f424adac334e5789bTed Kremenek      BFSQueue.push_front(*CI);
387d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks    }
388d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks  }
389fee618af5dd7dee2caaa7347b372eb3dc5fdeffcTed Kremenek}
390fee618af5dd7dee2caaa7347b372eb3dc5fdeffcTed Kremenek
39114cc9451de4a9539bf79e4e5d63248c2377426dbTed Kremenekvoid AnalysisConsumer::HandleTranslationUnit(ASTContext &C) {
392aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks  // Don't run the actions if an error has occurred with parsing the file.
393aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks  DiagnosticsEngine &Diags = PP.getDiagnostics();
394aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks  if (Diags.hasErrorOccurred() || Diags.hasFatalErrorOccurred())
395aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks    return;
396aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks
397c5bdc556f6a65c677e0ed73f918c3000ecad33afAnna Zaks  {
398d38f79543136ba68cd14b1dab0856474df1fbfd5Anna Zaks    if (TUTotalTimer) TUTotalTimer->startTimer();
399d38f79543136ba68cd14b1dab0856474df1fbfd5Anna Zaks
400c5bdc556f6a65c677e0ed73f918c3000ecad33afAnna Zaks    // Introduce a scope to destroy BR before Mgr.
401c5bdc556f6a65c677e0ed73f918c3000ecad33afAnna Zaks    BugReporter BR(*Mgr);
402c5bdc556f6a65c677e0ed73f918c3000ecad33afAnna Zaks    TranslationUnitDecl *TU = C.getTranslationUnitDecl();
403c5bdc556f6a65c677e0ed73f918c3000ecad33afAnna Zaks    checkerMgr->runCheckersOnASTDecl(TU, *Mgr, BR);
404aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks
405aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks    // Run the AST-only checks using the order in which functions are defined.
406aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks    // If inlining is not turned on, use the simplest function order for path
407aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks    // sensitive analyzes as well.
408aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks    RecVisitorMode = (Mgr->shouldInlineCall() ? ANALYSIS_SYNTAX : ANALYSIS_ALL);
409aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks    RecVisitorBR = &BR;
4106a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks
4116a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks    // Process all the top level declarations.
412cb0a5039c243f5b0c178e70f424adac334e5789bTed Kremenek    //
413cb0a5039c243f5b0c178e70f424adac334e5789bTed Kremenek    // NOTE: We use an ImmutableList to avoid issues with invalidating iterators
414cb0a5039c243f5b0c178e70f424adac334e5789bTed Kremenek    // to the list while we are traversing it.
415cb0a5039c243f5b0c178e70f424adac334e5789bTed Kremenek    //
4166a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks    for (SetOfDecls::iterator I = LocalTUDecls.begin(),
417cb0a5039c243f5b0c178e70f424adac334e5789bTed Kremenek         E = LocalTUDecls.end(); I != E; ++I) {
4186a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks      TraverseDecl(*I);
419cb0a5039c243f5b0c178e70f424adac334e5789bTed Kremenek    }
420aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks
421aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks    if (Mgr->shouldInlineCall())
4226a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks      HandleDeclsGallGraph();
423b317f8f5ca8737a5bbad97a3f7566a2dbd2ed61bZhongxing Xu
424c5bdc556f6a65c677e0ed73f918c3000ecad33afAnna Zaks    // After all decls handled, run checkers on the entire TranslationUnit.
425c5bdc556f6a65c677e0ed73f918c3000ecad33afAnna Zaks    checkerMgr->runCheckersOnEndOfTranslationUnit(TU, *Mgr, BR);
426aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks
427aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks    RecVisitorBR = 0;
428c5bdc556f6a65c677e0ed73f918c3000ecad33afAnna Zaks  }
4299be6e7ce5788e50c62d40c59b0bbc2ea423683f7Ted Kremenek
430ef3643fbbbf66247c5e205497fae0f46e240c143David Blaikie  // Explicitly destroy the PathDiagnosticConsumer.  This will flush its output.
431690a7f431d6863a101711e67636d51ddd13f35c5Ted Kremenek  // FIXME: This should be replaced with something that doesn't rely on
432ef3643fbbbf66247c5e205497fae0f46e240c143David Blaikie  // side-effects in PathDiagnosticConsumer's destructor. This is required when
433da17fd50ad485fd2a1fc5c2f055caacf532992daZhongxing Xu  // used with option -disable-free.
434d07a0d0279c09d1017f8450fce575a94dc9703c0Zhongxing Xu  Mgr.reset(NULL);
435d38f79543136ba68cd14b1dab0856474df1fbfd5Anna Zaks
436d38f79543136ba68cd14b1dab0856474df1fbfd5Anna Zaks  if (TUTotalTimer) TUTotalTimer->stopTimer();
4376b77ce8824cf62c2cfb61cf2d801eb3fcfbecffeAnna Zaks
4386b77ce8824cf62c2cfb61cf2d801eb3fcfbecffeAnna Zaks  // Count how many basic blocks we have not covered.
4396b77ce8824cf62c2cfb61cf2d801eb3fcfbecffeAnna Zaks  NumBlocksInAnalyzedFunctions = FunctionSummaries.getTotalNumBasicBlocks();
4406b77ce8824cf62c2cfb61cf2d801eb3fcfbecffeAnna Zaks  if (NumBlocksInAnalyzedFunctions > 0)
4416b77ce8824cf62c2cfb61cf2d801eb3fcfbecffeAnna Zaks    PercentReachableBlocks =
4426b77ce8824cf62c2cfb61cf2d801eb3fcfbecffeAnna Zaks      (FunctionSummaries.getTotalNumVisitedBasicBlocks() * 100) /
4436b77ce8824cf62c2cfb61cf2d801eb3fcfbecffeAnna Zaks        NumBlocksInAnalyzedFunctions;
4446b77ce8824cf62c2cfb61cf2d801eb3fcfbecffeAnna Zaks
445db09a4dee28a4515438af60f2d2b4a83e4965c31Ted Kremenek}
446db09a4dee28a4515438af60f2d2b4a83e4965c31Ted Kremenek
4475f9e272e632e951b1efe824cd16acb4d96077930Chris Lattnerstatic void FindBlocks(DeclContext *D, SmallVectorImpl<Decl*> &WL) {
448fc576514d06c46a7cac49500169411d82f38d04bTed Kremenek  if (BlockDecl *BD = dyn_cast<BlockDecl>(D))
449fc576514d06c46a7cac49500169411d82f38d04bTed Kremenek    WL.push_back(BD);
450f6eafcca7734274d277afa121f2c4fb025a54218Ted Kremenek
451fc576514d06c46a7cac49500169411d82f38d04bTed Kremenek  for (DeclContext::decl_iterator I = D->decls_begin(), E = D->decls_end();
452fc576514d06c46a7cac49500169411d82f38d04bTed Kremenek       I!=E; ++I)
453fc576514d06c46a7cac49500169411d82f38d04bTed Kremenek    if (DeclContext *DC = dyn_cast<DeclContext>(*I))
454fc576514d06c46a7cac49500169411d82f38d04bTed Kremenek      FindBlocks(DC, WL);
455fc576514d06c46a7cac49500169411d82f38d04bTed Kremenek}
456fc576514d06c46a7cac49500169411d82f38d04bTed Kremenek
457d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaksstatic std::string getFunctionName(const Decl *D) {
458d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks  if (const ObjCMethodDecl *ID = dyn_cast<ObjCMethodDecl>(D)) {
459d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks    return ID->getSelector().getAsString();
460d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks  }
461d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks  if (const FunctionDecl *ND = dyn_cast<FunctionDecl>(D)) {
462d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks    IdentifierInfo *II = ND->getIdentifier();
463d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks    if (II)
464d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks      return II->getName();
465d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks  }
466d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks  return "";
467d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks}
468d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks
46998520835eb1aa091429afa06e9f4f7ebe3864d34Anna Zaksbool AnalysisConsumer::skipFunction(Decl *D) {
470d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks  if (!Opts.AnalyzeSpecificFunction.empty() &&
471d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks      getFunctionName(D) != Opts.AnalyzeSpecificFunction)
47298520835eb1aa091429afa06e9f4f7ebe3864d34Anna Zaks    return true;
4731eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
474f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek  // Don't run the actions on declarations in header files unless
475f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek  // otherwise specified.
476fcd783d583d270b7ec1ec3e0fcf83cd93d30e381Ted Kremenek  SourceManager &SM = Ctx->getSourceManager();
477402785357ab053dd53f4fdd858b9630a5e0f8badChandler Carruth  SourceLocation SL = SM.getExpansionLoc(D->getLocation());
478fcd783d583d270b7ec1ec3e0fcf83cd93d30e381Ted Kremenek  if (!Opts.AnalyzeAll && !SM.isFromMainFile(SL))
47998520835eb1aa091429afa06e9f4f7ebe3864d34Anna Zaks    return true;
48098520835eb1aa091429afa06e9f4f7ebe3864d34Anna Zaks
48198520835eb1aa091429afa06e9f4f7ebe3864d34Anna Zaks  return false;
48298520835eb1aa091429afa06e9f4f7ebe3864d34Anna Zaks}
48398520835eb1aa091429afa06e9f4f7ebe3864d34Anna Zaks
484aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaksvoid AnalysisConsumer::HandleCode(Decl *D, AnalysisMode Mode,
4856a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks                                  SetOfConstDecls *VisitedCallees) {
48698520835eb1aa091429afa06e9f4f7ebe3864d34Anna Zaks  if (skipFunction(D))
4871eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump    return;
488f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek
489aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks  DisplayFunction(D, Mode);
49098520835eb1aa091429afa06e9f4f7ebe3864d34Anna Zaks
4911d26f48dc2eea1c07431ca1519d7034a21b9bcffTed Kremenek  // Clear the AnalysisManager of old AnalysisDeclContexts.
49258f5ec7d56b1ebf5f90ee11226ebe7663f2821eaTed Kremenek  Mgr->ClearContexts();
493f6eafcca7734274d277afa121f2c4fb025a54218Ted Kremenek
4941eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  // Dispatch on the actions.
4955f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner  SmallVector<Decl*, 10> WL;
496fc576514d06c46a7cac49500169411d82f38d04bTed Kremenek  WL.push_back(D);
497f6eafcca7734274d277afa121f2c4fb025a54218Ted Kremenek
49806a54a38be5054c910ffc92db60edab23f9ea105Argyrios Kyrtzidis  if (D->hasBody() && Opts.AnalyzeNestedBlocks)
499fc576514d06c46a7cac49500169411d82f38d04bTed Kremenek    FindBlocks(cast<DeclContext>(D), WL);
500f6eafcca7734274d277afa121f2c4fb025a54218Ted Kremenek
5019fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis  BugReporter BR(*Mgr);
5025f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner  for (SmallVectorImpl<Decl*>::iterator WI=WL.begin(), WE=WL.end();
5039fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis       WI != WE; ++WI)
504d655ab28fdf7c940d3f79f8f287954d7f76e0977Argyrios Kyrtzidis    if ((*WI)->hasBody()) {
505aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks      if (Mode != ANALYSIS_PATH)
506aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks        checkerMgr->runCheckersOnASTBody(*WI, *Mgr, BR);
5071f5171edc9fb9b0698a75fa981c29a750b0a6082Anna Zaks      if (Mode != ANALYSIS_SYNTAX && checkerMgr->hasPathSensitiveCheckers()) {
5083fd5f370a28552976c52e76c3035d79012d78ddaAnna Zaks        RunPathSensitiveChecks(*WI, VisitedCallees);
5091f5171edc9fb9b0698a75fa981c29a750b0a6082Anna Zaks        NumFunctionsAnalyzed++;
5101f5171edc9fb9b0698a75fa981c29a750b0a6082Anna Zaks      }
511d655ab28fdf7c940d3f79f8f287954d7f76e0977Argyrios Kyrtzidis    }
512f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek}
513f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek
514f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek//===----------------------------------------------------------------------===//
515d655ab28fdf7c940d3f79f8f287954d7f76e0977Argyrios Kyrtzidis// Path-sensitive checking.
516f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek//===----------------------------------------------------------------------===//
517f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek
5183fd5f370a28552976c52e76c3035d79012d78ddaAnna Zaksvoid AnalysisConsumer::ActionExprEngine(Decl *D, bool ObjCGCEnabled,
5196a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks                                        SetOfConstDecls *VisitedCallees) {
520a5937bbfd19e61d651a58b0f0ffeef68457902a5Ted Kremenek  // Construct the analysis engine.  First check if the CFG is valid.
52175d03cffe20b5c945ef04eba208efb0437339997Ted Kremenek  // FIXME: Inter-procedural analysis will need to handle invalid CFGs.
5223fd5f370a28552976c52e76c3035d79012d78ddaAnna Zaks  if (!Mgr->getCFG(D))
523f6eafcca7734274d277afa121f2c4fb025a54218Ted Kremenek    return;
5243fd5f370a28552976c52e76c3035d79012d78ddaAnna Zaks
5253bbd8cd831788c506f2980293eb3c7e1b3ca2501Anna Zaks  ExprEngine Eng(*Mgr, ObjCGCEnabled, VisitedCallees, &FunctionSummaries);
526f6eafcca7734274d277afa121f2c4fb025a54218Ted Kremenek
527f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek  // Set the graph auditor.
5286f42b62b6194f53bcbc349f5d17388e1936535d7Dylan Noblesmith  OwningPtr<ExplodedNode::Auditor> Auditor;
5293fd5f370a28552976c52e76c3035d79012d78ddaAnna Zaks  if (Mgr->shouldVisualizeUbigraph()) {
530f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek    Auditor.reset(CreateUbiViz());
531c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu    ExplodedNode::SetAuditor(Auditor.get());
532f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek  }
5331eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
534b35a74a40c1d2656a25e560e773ed48bdf49f9c0Ted Kremenek  // Execute the worklist algorithm.
5353fd5f370a28552976c52e76c3035d79012d78ddaAnna Zaks  Eng.ExecuteWorkList(Mgr->getAnalysisDeclContextManager().getStackFrame(D, 0),
5363fd5f370a28552976c52e76c3035d79012d78ddaAnna Zaks                      Mgr->getMaxNodes());
5371eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
538f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek  // Release the auditor (if any) so that it doesn't monitor the graph
539f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek  // created BugReporter.
540c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu  ExplodedNode::SetAuditor(0);
5413df6421150271266b5a90fd4c6bfa6566c38c036Ted Kremenek
54234d7734b6ed1d9c0f647405e065251eb67f42badTed Kremenek  // Visualize the exploded graph.
5433fd5f370a28552976c52e76c3035d79012d78ddaAnna Zaks  if (Mgr->shouldVisualizeGraphviz())
5443fd5f370a28552976c52e76c3035d79012d78ddaAnna Zaks    Eng.ViewGraph(Mgr->shouldTrimGraph());
5451eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
5463df6421150271266b5a90fd4c6bfa6566c38c036Ted Kremenek  // Display warnings.
5473df6421150271266b5a90fd4c6bfa6566c38c036Ted Kremenek  Eng.getBugReporter().FlushReports();
548bc46f345838b1c0d420dbd3655c94f5f360fb5b8Ted Kremenek}
549bc46f345838b1c0d420dbd3655c94f5f360fb5b8Ted Kremenek
5506a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaksvoid AnalysisConsumer::RunPathSensitiveChecks(Decl *D,
5516a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks                                              SetOfConstDecls *Visited) {
55217a38e2636a8b1ce473fc6504c4b16cb09db29f4Jordy Rose
5534e4d08403ca5cfd4d558fa2936215d3a4e5a528dDavid Blaikie  switch (Mgr->getLangOpts().getGC()) {
55417a38e2636a8b1ce473fc6504c4b16cb09db29f4Jordy Rose  case LangOptions::NonGC:
5553fd5f370a28552976c52e76c3035d79012d78ddaAnna Zaks    ActionExprEngine(D, false, Visited);
55617a38e2636a8b1ce473fc6504c4b16cb09db29f4Jordy Rose    break;
55717a38e2636a8b1ce473fc6504c4b16cb09db29f4Jordy Rose
55817a38e2636a8b1ce473fc6504c4b16cb09db29f4Jordy Rose  case LangOptions::GCOnly:
5593fd5f370a28552976c52e76c3035d79012d78ddaAnna Zaks    ActionExprEngine(D, true, Visited);
56017a38e2636a8b1ce473fc6504c4b16cb09db29f4Jordy Rose    break;
56117a38e2636a8b1ce473fc6504c4b16cb09db29f4Jordy Rose
56217a38e2636a8b1ce473fc6504c4b16cb09db29f4Jordy Rose  case LangOptions::HybridGC:
5633fd5f370a28552976c52e76c3035d79012d78ddaAnna Zaks    ActionExprEngine(D, false, Visited);
5643fd5f370a28552976c52e76c3035d79012d78ddaAnna Zaks    ActionExprEngine(D, true, Visited);
56517a38e2636a8b1ce473fc6504c4b16cb09db29f4Jordy Rose    break;
56617a38e2636a8b1ce473fc6504c4b16cb09db29f4Jordy Rose  }
567b35a74a40c1d2656a25e560e773ed48bdf49f9c0Ted Kremenek}
568b35a74a40c1d2656a25e560e773ed48bdf49f9c0Ted Kremenek
569f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek//===----------------------------------------------------------------------===//
570f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek// AnalysisConsumer creation.
571f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek//===----------------------------------------------------------------------===//
572f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek
5739ef6537a894c33003359b1f9b9676e9178e028b7Ted KremenekASTConsumer* ento::CreateAnalysisConsumer(const Preprocessor& pp,
57408b86531ade68727c56918f162816075b87c864aJordy Rose                                          const std::string& outDir,
57508b86531ade68727c56918f162816075b87c864aJordy Rose                                          const AnalyzerOptions& opts,
57608b86531ade68727c56918f162816075b87c864aJordy Rose                                          ArrayRef<std::string> plugins) {
57708b86531ade68727c56918f162816075b87c864aJordy Rose  // Disable the effects of '-Werror' when using the AnalysisConsumer.
578efceabd2380f49306bc0229583458e93b062094bDaniel Dunbar  pp.getDiagnostics().setWarningsAsErrors(false);
579be1fe1eb12a1cb91c8e3a9fcc2db4dfe989def6cTed Kremenek
58008b86531ade68727c56918f162816075b87c864aJordy Rose  return new AnalysisConsumer(pp, outDir, opts, plugins);
581f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek}
582f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek
583f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek//===----------------------------------------------------------------------===//
584f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek// Ubigraph Visualization.  FIXME: Move to separate file.
585f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek//===----------------------------------------------------------------------===//
586f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek
587f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremeneknamespace {
5881eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
589c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xuclass UbigraphViz : public ExplodedNode::Auditor {
5906f42b62b6194f53bcbc349f5d17388e1936535d7Dylan Noblesmith  OwningPtr<raw_ostream> Out;
591710ad9343f32b33b336369b20edad1a21a0b3299Ted Kremenek  llvm::sys::Path Dir, Filename;
592f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek  unsigned Cntr;
593f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek
594f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek  typedef llvm::DenseMap<void*,unsigned> VMap;
595f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek  VMap M;
5961eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
597f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenekpublic:
5989c378f705405d37f49795d5e915989de774fe11fTed Kremenek  UbigraphViz(raw_ostream *out, llvm::sys::Path& dir,
59956b98719b0dbebb33cb228afa888c47156be2381Ted Kremenek              llvm::sys::Path& filename);
6001eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
601710ad9343f32b33b336369b20edad1a21a0b3299Ted Kremenek  ~UbigraphViz();
6021eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
6039c378f705405d37f49795d5e915989de774fe11fTed Kremenek  virtual void AddEdge(ExplodedNode *Src, ExplodedNode *Dst);
604f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek};
6051eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
606f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek} // end anonymous namespace
607f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek
608c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xustatic ExplodedNode::Auditor* CreateUbiViz() {
609f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek  std::string ErrMsg;
6101eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
611710ad9343f32b33b336369b20edad1a21a0b3299Ted Kremenek  llvm::sys::Path Dir = llvm::sys::Path::GetTemporaryDirectory(&ErrMsg);
612f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek  if (!ErrMsg.empty())
613f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek    return 0;
614f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek
615710ad9343f32b33b336369b20edad1a21a0b3299Ted Kremenek  llvm::sys::Path Filename = Dir;
616f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek  Filename.appendComponent("llvm_ubi");
617f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek  Filename.makeUnique(true,&ErrMsg);
618f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek
619f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek  if (!ErrMsg.empty())
620f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek    return 0;
621f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek
622d57a7ef9252964bc6c8471451d7bd395b0520cb8Chris Lattner  llvm::errs() << "Writing '" << Filename.str() << "'.\n";
6231eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
6246f42b62b6194f53bcbc349f5d17388e1936535d7Dylan Noblesmith  OwningPtr<llvm::raw_fd_ostream> Stream;
625b044c473a155b7e827680635c1699cb2b5b6c0eeDan Gohman  Stream.reset(new llvm::raw_fd_ostream(Filename.c_str(), ErrMsg));
626f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek
627f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek  if (!ErrMsg.empty())
628f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek    return 0;
6291eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
630710ad9343f32b33b336369b20edad1a21a0b3299Ted Kremenek  return new UbigraphViz(Stream.take(), Dir, Filename);
631f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek}
632f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek
6339c378f705405d37f49795d5e915989de774fe11fTed Kremenekvoid UbigraphViz::AddEdge(ExplodedNode *Src, ExplodedNode *Dst) {
6341eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
63545479c88c8a44c55d27c3bd855273bb318082f37Ted Kremenek  assert (Src != Dst && "Self-edges are not allowed.");
6361eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
637f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek  // Lookup the Src.  If it is a new node, it's a root.
638f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek  VMap::iterator SrcI= M.find(Src);
639f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek  unsigned SrcID;
6401eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
641f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek  if (SrcI == M.end()) {
642f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek    M[Src] = SrcID = Cntr++;
643f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek    *Out << "('vertex', " << SrcID << ", ('color','#00ff00'))\n";
644f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek  }
645f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek  else
646f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek    SrcID = SrcI->second;
6471eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
648f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek  // Lookup the Dst.
649f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek  VMap::iterator DstI= M.find(Dst);
650f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek  unsigned DstID;
651f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek
652f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek  if (DstI == M.end()) {
653f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek    M[Dst] = DstID = Cntr++;
654f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek    *Out << "('vertex', " << DstID << ")\n";
655f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek  }
65656b98719b0dbebb33cb228afa888c47156be2381Ted Kremenek  else {
65756b98719b0dbebb33cb228afa888c47156be2381Ted Kremenek    // We have hit DstID before.  Change its style to reflect a cache hit.
658f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek    DstID = DstI->second;
65956b98719b0dbebb33cb228afa888c47156be2381Ted Kremenek    *Out << "('change_vertex_style', " << DstID << ", 1)\n";
66056b98719b0dbebb33cb228afa888c47156be2381Ted Kremenek  }
661f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek
662f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek  // Add the edge.
6631eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  *Out << "('edge', " << SrcID << ", " << DstID
664d1289327f7d2126d732e23cc189ecd0aa5d07cbbTed Kremenek       << ", ('arrow','true'), ('oriented', 'true'))\n";
665f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek}
666f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek
6679c378f705405d37f49795d5e915989de774fe11fTed KremenekUbigraphViz::UbigraphViz(raw_ostream *out, llvm::sys::Path& dir,
66856b98719b0dbebb33cb228afa888c47156be2381Ted Kremenek                         llvm::sys::Path& filename)
66956b98719b0dbebb33cb228afa888c47156be2381Ted Kremenek  : Out(out), Dir(dir), Filename(filename), Cntr(0) {
67056b98719b0dbebb33cb228afa888c47156be2381Ted Kremenek
67156b98719b0dbebb33cb228afa888c47156be2381Ted Kremenek  *Out << "('vertex_style_attribute', 0, ('shape', 'icosahedron'))\n";
67256b98719b0dbebb33cb228afa888c47156be2381Ted Kremenek  *Out << "('vertex_style', 1, 0, ('shape', 'sphere'), ('color', '#ffcc66'),"
67356b98719b0dbebb33cb228afa888c47156be2381Ted Kremenek          " ('size', '1.5'))\n";
67456b98719b0dbebb33cb228afa888c47156be2381Ted Kremenek}
67556b98719b0dbebb33cb228afa888c47156be2381Ted Kremenek
676710ad9343f32b33b336369b20edad1a21a0b3299Ted KremenekUbigraphViz::~UbigraphViz() {
677710ad9343f32b33b336369b20edad1a21a0b3299Ted Kremenek  Out.reset(0);
6786cb7c1a43b0c8f739d1f54b7fdae5ede86033496Benjamin Kramer  llvm::errs() << "Running 'ubiviz' program... ";
679710ad9343f32b33b336369b20edad1a21a0b3299Ted Kremenek  std::string ErrMsg;
680710ad9343f32b33b336369b20edad1a21a0b3299Ted Kremenek  llvm::sys::Path Ubiviz = llvm::sys::Program::FindProgramByName("ubiviz");
681710ad9343f32b33b336369b20edad1a21a0b3299Ted Kremenek  std::vector<const char*> args;
682710ad9343f32b33b336369b20edad1a21a0b3299Ted Kremenek  args.push_back(Ubiviz.c_str());
683710ad9343f32b33b336369b20edad1a21a0b3299Ted Kremenek  args.push_back(Filename.c_str());
684710ad9343f32b33b336369b20edad1a21a0b3299Ted Kremenek  args.push_back(0);
6851eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
686710ad9343f32b33b336369b20edad1a21a0b3299Ted Kremenek  if (llvm::sys::Program::ExecuteAndWait(Ubiviz, &args[0],0,0,0,0,&ErrMsg)) {
6876cb7c1a43b0c8f739d1f54b7fdae5ede86033496Benjamin Kramer    llvm::errs() << "Error viewing graph: " << ErrMsg << "\n";
688710ad9343f32b33b336369b20edad1a21a0b3299Ted Kremenek  }
6891eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
690710ad9343f32b33b336369b20edad1a21a0b3299Ted Kremenek  // Delete the directory.
6911eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  Dir.eraseFromDisk(true);
692932680ecdeab4c216ce7c0736093d3dcd2f60f6dDaniel Dunbar}
693