AnalysisConsumer.cpp revision e62f048960645b79363408fdead53fec2a063c52
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"
4481fb169f42769e02c7425b23885a261c025fd5e6Anna Zaks#include "llvm/ADT/Statistic.h"
45db09a4dee28a4515438af60f2d2b4a83e4965c31Ted Kremenek
467fe8dcef71ae56e43fd7df345db2895f84f2d0caAnna Zaks#include <queue>
477fe8dcef71ae56e43fd7df345db2895f84f2d0caAnna Zaks
48f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenekusing namespace clang;
499ef6537a894c33003359b1f9b9676e9178e028b7Ted Kremenekusing namespace ento;
50d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaksusing llvm::SmallPtrSet;
51f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek
52c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xustatic ExplodedNode::Auditor* CreateUbiViz();
53ff944a8c481d6c0f1ad2633e4be9bf8b1dd2a09fZhongxing Xu
543fd5f370a28552976c52e76c3035d79012d78ddaAnna ZaksSTATISTIC(NumFunctionTopLevel, "The # of functions at top level.");
55d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna ZaksSTATISTIC(NumFunctionsAnalyzed, "The # of functions analysed (as top level).");
56e62f048960645b79363408fdead53fec2a063c52Anna ZaksSTATISTIC(NumBlocksInAnalyzedFunctions,
57e62f048960645b79363408fdead53fec2a063c52Anna Zaks                     "The # of basic blocks in the analyzed functions.");
58e62f048960645b79363408fdead53fec2a063c52Anna ZaksSTATISTIC(PercentReachableBlocks, "The % of reachable basic blocks.");
59d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks
60be1fe1eb12a1cb91c8e3a9fcc2db4dfe989def6cTed Kremenek//===----------------------------------------------------------------------===//
61f39d962cf84f46d2c0512157259ae1d41a1a5173David Blaikie// Special PathDiagnosticConsumers.
62f75560670bcdd59b051149bdece3eac14e313853Ted Kremenek//===----------------------------------------------------------------------===//
63f75560670bcdd59b051149bdece3eac14e313853Ted Kremenek
64ef3643fbbbf66247c5e205497fae0f46e240c143David Blaikiestatic PathDiagnosticConsumer*
65ef3643fbbbf66247c5e205497fae0f46e240c143David BlaikiecreatePlistHTMLDiagnosticConsumer(const std::string& prefix,
66efceabd2380f49306bc0229583458e93b062094bDaniel Dunbar                                const Preprocessor &PP) {
67ef3643fbbbf66247c5e205497fae0f46e240c143David Blaikie  PathDiagnosticConsumer *PD =
68ef3643fbbbf66247c5e205497fae0f46e240c143David Blaikie    createHTMLDiagnosticConsumer(llvm::sys::path::parent_path(prefix), PP);
69ef3643fbbbf66247c5e205497fae0f46e240c143David Blaikie  return createPlistDiagnosticConsumer(prefix, PP, PD);
70f75560670bcdd59b051149bdece3eac14e313853Ted Kremenek}
71f75560670bcdd59b051149bdece3eac14e313853Ted Kremenek
72f75560670bcdd59b051149bdece3eac14e313853Ted Kremenek//===----------------------------------------------------------------------===//
73f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek// AnalysisConsumer declaration.
74f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek//===----------------------------------------------------------------------===//
75f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek
76f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremeneknamespace {
77f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek
78aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaksclass AnalysisConsumer : public ASTConsumer,
79aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks                         public RecursiveASTVisitor<AnalysisConsumer> {
80aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks  enum AnalysisMode {
81aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks    ANALYSIS_SYNTAX,
82aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks    ANALYSIS_PATH,
83aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks    ANALYSIS_ALL
84aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks  };
85aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks
86aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks  /// Mode of the analyzes while recursively visiting Decls.
87aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks  AnalysisMode RecVisitorMode;
88aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks  /// Bug Reporter to use while recursively visiting Decls.
89aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks  BugReporter *RecVisitorBR;
90aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks
91ed8afacb8118b71bcfa8017059e51da325e7691bZhongxing Xupublic:
929c378f705405d37f49795d5e915989de774fe11fTed Kremenek  ASTContext *Ctx;
931d9cbeb76cf4c36acf5545028e2b2ac207086442Ted Kremenek  const Preprocessor &PP;
941d9cbeb76cf4c36acf5545028e2b2ac207086442Ted Kremenek  const std::string OutDir;
951d9cbeb76cf4c36acf5545028e2b2ac207086442Ted Kremenek  AnalyzerOptions Opts;
9608b86531ade68727c56918f162816075b87c864aJordy Rose  ArrayRef<std::string> Plugins;
97d07a0d0279c09d1017f8450fce575a94dc9703c0Zhongxing Xu
981d9cbeb76cf4c36acf5545028e2b2ac207086442Ted Kremenek  // PD is owned by AnalysisManager.
99ef3643fbbbf66247c5e205497fae0f46e240c143David Blaikie  PathDiagnosticConsumer *PD;
100d07a0d0279c09d1017f8450fce575a94dc9703c0Zhongxing Xu
1011d9cbeb76cf4c36acf5545028e2b2ac207086442Ted Kremenek  StoreManagerCreator CreateStoreMgr;
1021d9cbeb76cf4c36acf5545028e2b2ac207086442Ted Kremenek  ConstraintManagerCreator CreateConstraintMgr;
103f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek
1046f42b62b6194f53bcbc349f5d17388e1936535d7Dylan Noblesmith  OwningPtr<CheckerManager> checkerMgr;
1056f42b62b6194f53bcbc349f5d17388e1936535d7Dylan Noblesmith  OwningPtr<AnalysisManager> Mgr;
106c471e7b44e63ff1b46b480e723c4130aeaef5a8aZhongxing Xu
107d38f79543136ba68cd14b1dab0856474df1fbfd5Anna Zaks  /// Time the analyzes time of each translation unit.
108d38f79543136ba68cd14b1dab0856474df1fbfd5Anna Zaks  static llvm::Timer* TUTotalTimer;
109d38f79543136ba68cd14b1dab0856474df1fbfd5Anna Zaks
1103bbd8cd831788c506f2980293eb3c7e1b3ca2501Anna Zaks  /// The information about analyzed functions shared throughout the
1113bbd8cd831788c506f2980293eb3c7e1b3ca2501Anna Zaks  /// translation unit.
1123bbd8cd831788c506f2980293eb3c7e1b3ca2501Anna Zaks  FunctionSummariesTy FunctionSummaries;
1133bbd8cd831788c506f2980293eb3c7e1b3ca2501Anna Zaks
1141d9cbeb76cf4c36acf5545028e2b2ac207086442Ted Kremenek  AnalysisConsumer(const Preprocessor& pp,
1151d9cbeb76cf4c36acf5545028e2b2ac207086442Ted Kremenek                   const std::string& outdir,
11608b86531ade68727c56918f162816075b87c864aJordy Rose                   const AnalyzerOptions& opts,
11708b86531ade68727c56918f162816075b87c864aJordy Rose                   ArrayRef<std::string> plugins)
118aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks    : RecVisitorMode(ANALYSIS_ALL), RecVisitorBR(0),
119aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks      Ctx(0), PP(pp), OutDir(outdir), Opts(opts), Plugins(plugins), PD(0) {
1201d9cbeb76cf4c36acf5545028e2b2ac207086442Ted Kremenek    DigestAnalyzerOptions();
121d38f79543136ba68cd14b1dab0856474df1fbfd5Anna Zaks    if (Opts.PrintStats) {
122d38f79543136ba68cd14b1dab0856474df1fbfd5Anna Zaks      llvm::EnableStatistics();
123d38f79543136ba68cd14b1dab0856474df1fbfd5Anna Zaks      TUTotalTimer = new llvm::Timer("Analyzer Total Time");
124d38f79543136ba68cd14b1dab0856474df1fbfd5Anna Zaks    }
125d38f79543136ba68cd14b1dab0856474df1fbfd5Anna Zaks  }
126d38f79543136ba68cd14b1dab0856474df1fbfd5Anna Zaks
127d38f79543136ba68cd14b1dab0856474df1fbfd5Anna Zaks  ~AnalysisConsumer() {
128e62f048960645b79363408fdead53fec2a063c52Anna Zaks    // Count how many basic blocks we have not covered.
129e62f048960645b79363408fdead53fec2a063c52Anna Zaks    NumBlocksInAnalyzedFunctions = FunctionSummaries.getTotalNumBasicBlocks();
130e62f048960645b79363408fdead53fec2a063c52Anna Zaks    if (NumBlocksInAnalyzedFunctions > 0)
131e62f048960645b79363408fdead53fec2a063c52Anna Zaks      PercentReachableBlocks =
132e62f048960645b79363408fdead53fec2a063c52Anna Zaks        (FunctionSummaries.getTotalNumVisitedBasicBlocks() * 100) /
133e62f048960645b79363408fdead53fec2a063c52Anna Zaks          NumBlocksInAnalyzedFunctions;
134e62f048960645b79363408fdead53fec2a063c52Anna Zaks
135d38f79543136ba68cd14b1dab0856474df1fbfd5Anna Zaks    if (Opts.PrintStats)
136d38f79543136ba68cd14b1dab0856474df1fbfd5Anna Zaks      delete TUTotalTimer;
1371d9cbeb76cf4c36acf5545028e2b2ac207086442Ted Kremenek  }
138fda7832b000ff8927386f093b52c067641679469Zhongxing Xu
1391d9cbeb76cf4c36acf5545028e2b2ac207086442Ted Kremenek  void DigestAnalyzerOptions() {
140ef3643fbbbf66247c5e205497fae0f46e240c143David Blaikie    // Create the PathDiagnosticConsumer.
1411d9cbeb76cf4c36acf5545028e2b2ac207086442Ted Kremenek    if (!OutDir.empty()) {
1421d9cbeb76cf4c36acf5545028e2b2ac207086442Ted Kremenek      switch (Opts.AnalysisDiagOpt) {
1431d9cbeb76cf4c36acf5545028e2b2ac207086442Ted Kremenek      default:
144fda7832b000ff8927386f093b52c067641679469Zhongxing Xu#define ANALYSIS_DIAGNOSTICS(NAME, CMDFLAG, DESC, CREATEFN, AUTOCREATE) \
1451d9cbeb76cf4c36acf5545028e2b2ac207086442Ted Kremenek        case PD_##NAME: PD = CREATEFN(OutDir, PP); break;
146fda7832b000ff8927386f093b52c067641679469Zhongxing Xu#include "clang/Frontend/Analyses.def"
147fda7832b000ff8927386f093b52c067641679469Zhongxing Xu      }
148a599ae8826b01c0160a519b0fc5a4871f599bf04Argyrios Kyrtzidis    } else if (Opts.AnalysisDiagOpt == PD_TEXT) {
149a599ae8826b01c0160a519b0fc5a4871f599bf04Argyrios Kyrtzidis      // Create the text client even without a specified output file since
150a599ae8826b01c0160a519b0fc5a4871f599bf04Argyrios Kyrtzidis      // it just uses diagnostic notes.
151ef3643fbbbf66247c5e205497fae0f46e240c143David Blaikie      PD = createTextPathDiagnosticConsumer("", PP);
1521d9cbeb76cf4c36acf5545028e2b2ac207086442Ted Kremenek    }
153fda7832b000ff8927386f093b52c067641679469Zhongxing Xu
1541d9cbeb76cf4c36acf5545028e2b2ac207086442Ted Kremenek    // Create the analyzer component creators.
1555f83d6f36a7308eef21d87104fd70c421e854448Argyrios Kyrtzidis    switch (Opts.AnalysisStoreOpt) {
1565f83d6f36a7308eef21d87104fd70c421e854448Argyrios Kyrtzidis    default:
157b219cfc4d75f0a03630b7c4509ef791b7e97b2c8David Blaikie      llvm_unreachable("Unknown store manager.");
158fda7832b000ff8927386f093b52c067641679469Zhongxing Xu#define ANALYSIS_STORE(NAME, CMDFLAG, DESC, CREATEFN)           \
1595f83d6f36a7308eef21d87104fd70c421e854448Argyrios Kyrtzidis      case NAME##Model: CreateStoreMgr = CREATEFN; break;
160fda7832b000ff8927386f093b52c067641679469Zhongxing Xu#include "clang/Frontend/Analyses.def"
1611d9cbeb76cf4c36acf5545028e2b2ac207086442Ted Kremenek    }
1621eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
1635f83d6f36a7308eef21d87104fd70c421e854448Argyrios Kyrtzidis    switch (Opts.AnalysisConstraintsOpt) {
1645f83d6f36a7308eef21d87104fd70c421e854448Argyrios Kyrtzidis    default:
165b219cfc4d75f0a03630b7c4509ef791b7e97b2c8David Blaikie      llvm_unreachable("Unknown store manager.");
166fda7832b000ff8927386f093b52c067641679469Zhongxing Xu#define ANALYSIS_CONSTRAINTS(NAME, CMDFLAG, DESC, CREATEFN)     \
1675f83d6f36a7308eef21d87104fd70c421e854448Argyrios Kyrtzidis      case NAME##Model: CreateConstraintMgr = CREATEFN; break;
168fda7832b000ff8927386f093b52c067641679469Zhongxing Xu#include "clang/Frontend/Analyses.def"
169fda7832b000ff8927386f093b52c067641679469Zhongxing Xu    }
1701d9cbeb76cf4c36acf5545028e2b2ac207086442Ted Kremenek  }
171f6eafcca7734274d277afa121f2c4fb025a54218Ted Kremenek
172aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks  void DisplayFunction(const Decl *D, AnalysisMode Mode) {
173c4a1437c15da43eb8d2601cdce13161ef41a4389Ted Kremenek    if (!Opts.AnalyzerDisplayProgress)
1741d9cbeb76cf4c36acf5545028e2b2ac207086442Ted Kremenek      return;
175f6eafcca7734274d277afa121f2c4fb025a54218Ted Kremenek
176fc576514d06c46a7cac49500169411d82f38d04bTed Kremenek    SourceManager &SM = Mgr->getASTContext().getSourceManager();
177fc576514d06c46a7cac49500169411d82f38d04bTed Kremenek    PresumedLoc Loc = SM.getPresumedLoc(D->getLocation());
178cb7b1e17b63967317ab5cc55682168cf0380519aDouglas Gregor    if (Loc.isValid()) {
179aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks      llvm::errs() << "ANALYZE";
180aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks      switch (Mode) {
181aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks        case ANALYSIS_SYNTAX: llvm::errs() << "(Syntax)"; break;
182aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks        case ANALYSIS_PATH: llvm::errs() << "(Path Sensitive)"; break;
183aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks        case ANALYSIS_ALL: break;
184aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks      };
185aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks      llvm::errs() << ": " << Loc.getFilename();
186cb7b1e17b63967317ab5cc55682168cf0380519aDouglas Gregor      if (isa<FunctionDecl>(D) || isa<ObjCMethodDecl>(D)) {
187cb7b1e17b63967317ab5cc55682168cf0380519aDouglas Gregor        const NamedDecl *ND = cast<NamedDecl>(D);
188b8989f27f116ff2400e92a52c067a69846119eb5Benjamin Kramer        llvm::errs() << ' ' << *ND << '\n';
189cb7b1e17b63967317ab5cc55682168cf0380519aDouglas Gregor      }
190cb7b1e17b63967317ab5cc55682168cf0380519aDouglas Gregor      else if (isa<BlockDecl>(D)) {
191cb7b1e17b63967317ab5cc55682168cf0380519aDouglas Gregor        llvm::errs() << ' ' << "block(line:" << Loc.getLine() << ",col:"
192cb7b1e17b63967317ab5cc55682168cf0380519aDouglas Gregor                     << Loc.getColumn() << '\n';
193cb7b1e17b63967317ab5cc55682168cf0380519aDouglas Gregor      }
194cb7b1e17b63967317ab5cc55682168cf0380519aDouglas Gregor      else if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D)) {
195cb7b1e17b63967317ab5cc55682168cf0380519aDouglas Gregor        Selector S = MD->getSelector();
196cb7b1e17b63967317ab5cc55682168cf0380519aDouglas Gregor        llvm::errs() << ' ' << S.getAsString();
197cb7b1e17b63967317ab5cc55682168cf0380519aDouglas Gregor      }
19835fa76d0bb6fb8c86159a7506efd094a4fe376d2Ted Kremenek    }
1991d9cbeb76cf4c36acf5545028e2b2ac207086442Ted Kremenek  }
2001eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
2011d9cbeb76cf4c36acf5545028e2b2ac207086442Ted Kremenek  virtual void Initialize(ASTContext &Context) {
2021d9cbeb76cf4c36acf5545028e2b2ac207086442Ted Kremenek    Ctx = &Context;
2034e4d08403ca5cfd4d558fa2936215d3a4e5a528dDavid Blaikie    checkerMgr.reset(createCheckerManager(Opts, PP.getLangOpts(), Plugins,
20408b86531ade68727c56918f162816075b87c864aJordy Rose                                          PP.getDiagnostics()));
2051d9cbeb76cf4c36acf5545028e2b2ac207086442Ted Kremenek    Mgr.reset(new AnalysisManager(*Ctx, PP.getDiagnostics(),
2064e4d08403ca5cfd4d558fa2936215d3a4e5a528dDavid Blaikie                                  PP.getLangOpts(), PD,
2071d9cbeb76cf4c36acf5545028e2b2ac207086442Ted Kremenek                                  CreateStoreMgr, CreateConstraintMgr,
20843dee220252ef0b42c5f8a3bb1eca97f84f2565fArgyrios Kyrtzidis                                  checkerMgr.get(),
209c6238d2786cfd961b94580b3d3675a1b3ff0721cZhongxing Xu                                  /* Indexer */ 0,
2106362b893731ccf4480a96527db9e55e04b801503Zhongxing Xu                                  Opts.MaxNodes, Opts.MaxLoop,
2111d9cbeb76cf4c36acf5545028e2b2ac207086442Ted Kremenek                                  Opts.VisualizeEGDot, Opts.VisualizeEGUbi,
212d30952838421ddfb9f7e346b2ba8213889a5f789Anna Zaks                                  Opts.AnalysisPurgeOpt, Opts.EagerlyAssume,
21366253352131e3e7a22b3bfd0e180607aa2bfb988Anna Zaks                                  Opts.TrimGraph,
2149121ba232903ebe61e7bbe14ca294cf0f07dfa96Marcin Swiderski                                  Opts.UnoptimizedCFG, Opts.CFGAddImplicitDtors,
215d767d81290288c030f3be0be1d3e62b9c8df51dcTed Kremenek                                  Opts.CFGAddInitializers,
2168235f9c9c8b3d1737d1c6bd57f7ba3f616b92392Anna Zaks                                  Opts.EagerlyTrimEGraph,
21766253352131e3e7a22b3bfd0e180607aa2bfb988Anna Zaks                                  Opts.IPAMode,
2188235f9c9c8b3d1737d1c6bd57f7ba3f616b92392Anna Zaks                                  Opts.InlineMaxStackDepth,
21966253352131e3e7a22b3bfd0e180607aa2bfb988Anna Zaks                                  Opts.InlineMaxFunctionSize,
2205903a373db3d27794c90b25687e0dd6adb0e497dAnna Zaks                                  Opts.InliningMode,
221b47dbcbc12430fdf3e5a5b9f59cdec5480e89e75Anna Zaks                                  Opts.NoRetryExhausted));
2221d9cbeb76cf4c36acf5545028e2b2ac207086442Ted Kremenek  }
2231eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
2241d9cbeb76cf4c36acf5545028e2b2ac207086442Ted Kremenek  virtual void HandleTranslationUnit(ASTContext &C);
22514cc9451de4a9539bf79e4e5d63248c2377426dbTed Kremenek
226a2e589e60d147f4f04cee5682b8389b55c410244Anna Zaks  /// \brief Build the call graph for the TU and use it to define the order
227aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks  /// in which the functions should be visited.
228a2e589e60d147f4f04cee5682b8389b55c410244Anna Zaks  void HandleDeclsGallGraph(TranslationUnitDecl *TU);
229aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks
230aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks  /// \brief Run analyzes(syntax or path sensitive) on the given function.
231aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks  /// \param Mode - determines if we are requesting syntax only or path
232aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks  /// sensitive only analysis.
233aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks  /// \param VisitedCallees - The output parameter, which is populated with the
234aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks  /// set of functions which should be considered analyzed after analyzing the
235aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks  /// given root function.
236aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks  void HandleCode(Decl *D, AnalysisMode Mode, SetOfDecls *VisitedCallees = 0);
237aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks
238aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks  /// \brief Check if we should skip (not analyze) the given function.
23998520835eb1aa091429afa06e9f4f7ebe3864d34Anna Zaks  bool skipFunction(Decl *D);
240aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks
2413fd5f370a28552976c52e76c3035d79012d78ddaAnna Zaks  void RunPathSensitiveChecks(Decl *D, SetOfDecls *VisitedCallees);
2423fd5f370a28552976c52e76c3035d79012d78ddaAnna Zaks  void ActionExprEngine(Decl *D, bool ObjCGCEnabled, SetOfDecls *VisitedCallees);
243aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks
244aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks  /// Visitors for the RecursiveASTVisitor.
245aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks
246aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks  /// Handle callbacks for arbitrary Decls.
247aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks  bool VisitDecl(Decl *D) {
248aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks    checkerMgr->runCheckersOnASTDecl(D, *Mgr, *RecVisitorBR);
249aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks    return true;
250aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks  }
251aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks
252aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks  bool VisitFunctionDecl(FunctionDecl *FD) {
253aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks    IdentifierInfo *II = FD->getIdentifier();
254aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks    if (II && II->getName().startswith("__inline"))
255aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks      return true;
256aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks
257aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks    // We skip function template definitions, as their semantics is
258aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks    // only determined when they are instantiated.
259aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks    if (FD->isThisDeclarationADefinition() &&
260aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks        !FD->isDependentContext()) {
261aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks      HandleCode(FD, RecVisitorMode);
262aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks    }
263aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks    return true;
264aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks  }
265aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks
266aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks  bool VisitObjCMethodDecl(ObjCMethodDecl *MD) {
267aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks    checkerMgr->runCheckersOnASTDecl(MD, *Mgr, *RecVisitorBR);
268aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks    if (MD->isThisDeclarationADefinition())
269aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks      HandleCode(MD, RecVisitorMode);
270aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks    return true;
271aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks  }
2721d9cbeb76cf4c36acf5545028e2b2ac207086442Ted Kremenek};
273f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek} // end anonymous namespace
274f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek
275aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks
276f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek//===----------------------------------------------------------------------===//
277f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek// AnalysisConsumer implementation.
278f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek//===----------------------------------------------------------------------===//
279d38f79543136ba68cd14b1dab0856474df1fbfd5Anna Zaksllvm::Timer* AnalysisConsumer::TUTotalTimer = 0;
280f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek
281a2e589e60d147f4f04cee5682b8389b55c410244Anna Zaksvoid AnalysisConsumer::HandleDeclsGallGraph(TranslationUnitDecl *TU) {
282d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks  // Otherwise, use the Callgraph to derive the order.
283d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks  // Build the Call Graph.
284d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks  CallGraph CG;
285a2e589e60d147f4f04cee5682b8389b55c410244Anna Zaks  CG.addToCallGraph(TU);
286d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks
287d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks  // Find the top level nodes - children of root + the unreachable (parentless)
288d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks  // nodes.
2893fd5f370a28552976c52e76c3035d79012d78ddaAnna Zaks  llvm::SmallVector<CallGraphNode*, 24> TopLevelFunctions;
290b990d039c7e01ad0055dcbd1e13a691813397b96Anna Zaks  for (CallGraph::nodes_iterator TI = CG.parentless_begin(),
291b990d039c7e01ad0055dcbd1e13a691813397b96Anna Zaks                                 TE = CG.parentless_end(); TI != TE; ++TI) {
292b990d039c7e01ad0055dcbd1e13a691813397b96Anna Zaks    TopLevelFunctions.push_back(*TI);
293b990d039c7e01ad0055dcbd1e13a691813397b96Anna Zaks    NumFunctionTopLevel++;
294b990d039c7e01ad0055dcbd1e13a691813397b96Anna Zaks  }
295d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks  CallGraphNode *Entry = CG.getRoot();
296d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks  for (CallGraphNode::iterator I = Entry->begin(),
2973fd5f370a28552976c52e76c3035d79012d78ddaAnna Zaks                               E = Entry->end(); I != E; ++I) {
298d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks    TopLevelFunctions.push_back(*I);
2993fd5f370a28552976c52e76c3035d79012d78ddaAnna Zaks    NumFunctionTopLevel++;
3003fd5f370a28552976c52e76c3035d79012d78ddaAnna Zaks  }
301d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks
302b990d039c7e01ad0055dcbd1e13a691813397b96Anna Zaks  // Make sure the nodes are sorted in order reverse of their definition in the
303b990d039c7e01ad0055dcbd1e13a691813397b96Anna Zaks  // translation unit. This step is very important for performance. It ensures
304b990d039c7e01ad0055dcbd1e13a691813397b96Anna Zaks  // that we analyze the root functions before the externally available
305b990d039c7e01ad0055dcbd1e13a691813397b96Anna Zaks  // subroutines.
3067fe8dcef71ae56e43fd7df345db2895f84f2d0caAnna Zaks  std::queue<CallGraphNode*> BFSQueue;
307b990d039c7e01ad0055dcbd1e13a691813397b96Anna Zaks  for (llvm::SmallVector<CallGraphNode*, 24>::reverse_iterator
308b990d039c7e01ad0055dcbd1e13a691813397b96Anna Zaks         TI = TopLevelFunctions.rbegin(), TE = TopLevelFunctions.rend();
3097fe8dcef71ae56e43fd7df345db2895f84f2d0caAnna Zaks         TI != TE; ++TI)
3107fe8dcef71ae56e43fd7df345db2895f84f2d0caAnna Zaks    BFSQueue.push(*TI);
311d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks
3127fe8dcef71ae56e43fd7df345db2895f84f2d0caAnna Zaks  // BFS over all of the functions, while skipping the ones inlined into
3137fe8dcef71ae56e43fd7df345db2895f84f2d0caAnna Zaks  // the previously processed functions. Use external Visited set, which is
314d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks  // also modified when we inline a function.
315d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks  SmallPtrSet<CallGraphNode*,24> Visited;
3167fe8dcef71ae56e43fd7df345db2895f84f2d0caAnna Zaks  while(!BFSQueue.empty()) {
3177fe8dcef71ae56e43fd7df345db2895f84f2d0caAnna Zaks    CallGraphNode *N = BFSQueue.front();
3187fe8dcef71ae56e43fd7df345db2895f84f2d0caAnna Zaks    BFSQueue.pop();
3197fe8dcef71ae56e43fd7df345db2895f84f2d0caAnna Zaks
3207fe8dcef71ae56e43fd7df345db2895f84f2d0caAnna Zaks    // Skip the functions which have been processed already or previously
3217fe8dcef71ae56e43fd7df345db2895f84f2d0caAnna Zaks    // inlined.
3227fe8dcef71ae56e43fd7df345db2895f84f2d0caAnna Zaks    if (Visited.count(N))
3237fe8dcef71ae56e43fd7df345db2895f84f2d0caAnna Zaks      continue;
3247fe8dcef71ae56e43fd7df345db2895f84f2d0caAnna Zaks
3257fe8dcef71ae56e43fd7df345db2895f84f2d0caAnna Zaks    // Analyze the function.
3267fe8dcef71ae56e43fd7df345db2895f84f2d0caAnna Zaks    SetOfDecls VisitedCallees;
3277fe8dcef71ae56e43fd7df345db2895f84f2d0caAnna Zaks    Decl *D = N->getDecl();
3287fe8dcef71ae56e43fd7df345db2895f84f2d0caAnna Zaks    assert(D);
3297fe8dcef71ae56e43fd7df345db2895f84f2d0caAnna Zaks    HandleCode(D, ANALYSIS_PATH,
3307fe8dcef71ae56e43fd7df345db2895f84f2d0caAnna Zaks               (Mgr->InliningMode == All ? 0 : &VisitedCallees));
3317fe8dcef71ae56e43fd7df345db2895f84f2d0caAnna Zaks
3327fe8dcef71ae56e43fd7df345db2895f84f2d0caAnna Zaks    // Add the visited callees to the global visited set.
3337fe8dcef71ae56e43fd7df345db2895f84f2d0caAnna Zaks    for (SetOfDecls::const_iterator I = VisitedCallees.begin(),
3347fe8dcef71ae56e43fd7df345db2895f84f2d0caAnna Zaks                                    E = VisitedCallees.end(); I != E; ++I) {
3357fe8dcef71ae56e43fd7df345db2895f84f2d0caAnna Zaks      CallGraphNode *VN = CG.getNode(*I);
3367fe8dcef71ae56e43fd7df345db2895f84f2d0caAnna Zaks      if (VN)
3377fe8dcef71ae56e43fd7df345db2895f84f2d0caAnna Zaks        Visited.insert(VN);
3387fe8dcef71ae56e43fd7df345db2895f84f2d0caAnna Zaks    }
3397fe8dcef71ae56e43fd7df345db2895f84f2d0caAnna Zaks    Visited.insert(N);
3407fe8dcef71ae56e43fd7df345db2895f84f2d0caAnna Zaks
3417fe8dcef71ae56e43fd7df345db2895f84f2d0caAnna Zaks    // Push the children into the queue.
3427fe8dcef71ae56e43fd7df345db2895f84f2d0caAnna Zaks    for (CallGraphNode::const_iterator CI = N->begin(),
3437fe8dcef71ae56e43fd7df345db2895f84f2d0caAnna Zaks                                       CE = N->end(); CI != CE; ++CI) {
3447fe8dcef71ae56e43fd7df345db2895f84f2d0caAnna Zaks      BFSQueue.push(*CI);
345d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks    }
346d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks  }
347fee618af5dd7dee2caaa7347b372eb3dc5fdeffcTed Kremenek}
348fee618af5dd7dee2caaa7347b372eb3dc5fdeffcTed Kremenek
34914cc9451de4a9539bf79e4e5d63248c2377426dbTed Kremenekvoid AnalysisConsumer::HandleTranslationUnit(ASTContext &C) {
350aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks  // Don't run the actions if an error has occurred with parsing the file.
351aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks  DiagnosticsEngine &Diags = PP.getDiagnostics();
352aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks  if (Diags.hasErrorOccurred() || Diags.hasFatalErrorOccurred())
353aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks    return;
354aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks
355c5bdc556f6a65c677e0ed73f918c3000ecad33afAnna Zaks  {
356d38f79543136ba68cd14b1dab0856474df1fbfd5Anna Zaks    if (TUTotalTimer) TUTotalTimer->startTimer();
357d38f79543136ba68cd14b1dab0856474df1fbfd5Anna Zaks
358c5bdc556f6a65c677e0ed73f918c3000ecad33afAnna Zaks    // Introduce a scope to destroy BR before Mgr.
359c5bdc556f6a65c677e0ed73f918c3000ecad33afAnna Zaks    BugReporter BR(*Mgr);
360c5bdc556f6a65c677e0ed73f918c3000ecad33afAnna Zaks    TranslationUnitDecl *TU = C.getTranslationUnitDecl();
361c5bdc556f6a65c677e0ed73f918c3000ecad33afAnna Zaks    checkerMgr->runCheckersOnASTDecl(TU, *Mgr, BR);
362aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks
363aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks    // Run the AST-only checks using the order in which functions are defined.
364aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks    // If inlining is not turned on, use the simplest function order for path
365aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks    // sensitive analyzes as well.
366aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks    RecVisitorMode = (Mgr->shouldInlineCall() ? ANALYSIS_SYNTAX : ANALYSIS_ALL);
367aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks    RecVisitorBR = &BR;
368aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks    TraverseDecl(TU);
369aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks
370aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks    if (Mgr->shouldInlineCall())
371a2e589e60d147f4f04cee5682b8389b55c410244Anna Zaks      HandleDeclsGallGraph(TU);
372b317f8f5ca8737a5bbad97a3f7566a2dbd2ed61bZhongxing Xu
373c5bdc556f6a65c677e0ed73f918c3000ecad33afAnna Zaks    // After all decls handled, run checkers on the entire TranslationUnit.
374c5bdc556f6a65c677e0ed73f918c3000ecad33afAnna Zaks    checkerMgr->runCheckersOnEndOfTranslationUnit(TU, *Mgr, BR);
375aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks
376aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks    RecVisitorBR = 0;
377c5bdc556f6a65c677e0ed73f918c3000ecad33afAnna Zaks  }
3789be6e7ce5788e50c62d40c59b0bbc2ea423683f7Ted Kremenek
379ef3643fbbbf66247c5e205497fae0f46e240c143David Blaikie  // Explicitly destroy the PathDiagnosticConsumer.  This will flush its output.
380690a7f431d6863a101711e67636d51ddd13f35c5Ted Kremenek  // FIXME: This should be replaced with something that doesn't rely on
381ef3643fbbbf66247c5e205497fae0f46e240c143David Blaikie  // side-effects in PathDiagnosticConsumer's destructor. This is required when
382da17fd50ad485fd2a1fc5c2f055caacf532992daZhongxing Xu  // used with option -disable-free.
383d07a0d0279c09d1017f8450fce575a94dc9703c0Zhongxing Xu  Mgr.reset(NULL);
384d38f79543136ba68cd14b1dab0856474df1fbfd5Anna Zaks
385d38f79543136ba68cd14b1dab0856474df1fbfd5Anna Zaks  if (TUTotalTimer) TUTotalTimer->stopTimer();
386db09a4dee28a4515438af60f2d2b4a83e4965c31Ted Kremenek}
387db09a4dee28a4515438af60f2d2b4a83e4965c31Ted Kremenek
3885f9e272e632e951b1efe824cd16acb4d96077930Chris Lattnerstatic void FindBlocks(DeclContext *D, SmallVectorImpl<Decl*> &WL) {
389fc576514d06c46a7cac49500169411d82f38d04bTed Kremenek  if (BlockDecl *BD = dyn_cast<BlockDecl>(D))
390fc576514d06c46a7cac49500169411d82f38d04bTed Kremenek    WL.push_back(BD);
391f6eafcca7734274d277afa121f2c4fb025a54218Ted Kremenek
392fc576514d06c46a7cac49500169411d82f38d04bTed Kremenek  for (DeclContext::decl_iterator I = D->decls_begin(), E = D->decls_end();
393fc576514d06c46a7cac49500169411d82f38d04bTed Kremenek       I!=E; ++I)
394fc576514d06c46a7cac49500169411d82f38d04bTed Kremenek    if (DeclContext *DC = dyn_cast<DeclContext>(*I))
395fc576514d06c46a7cac49500169411d82f38d04bTed Kremenek      FindBlocks(DC, WL);
396fc576514d06c46a7cac49500169411d82f38d04bTed Kremenek}
397fc576514d06c46a7cac49500169411d82f38d04bTed Kremenek
398d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaksstatic std::string getFunctionName(const Decl *D) {
399d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks  if (const ObjCMethodDecl *ID = dyn_cast<ObjCMethodDecl>(D)) {
400d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks    return ID->getSelector().getAsString();
401d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks  }
402d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks  if (const FunctionDecl *ND = dyn_cast<FunctionDecl>(D)) {
403d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks    IdentifierInfo *II = ND->getIdentifier();
404d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks    if (II)
405d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks      return II->getName();
406d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks  }
407d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks  return "";
408d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks}
409d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks
41098520835eb1aa091429afa06e9f4f7ebe3864d34Anna Zaksbool AnalysisConsumer::skipFunction(Decl *D) {
411d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks  if (!Opts.AnalyzeSpecificFunction.empty() &&
412d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks      getFunctionName(D) != Opts.AnalyzeSpecificFunction)
41398520835eb1aa091429afa06e9f4f7ebe3864d34Anna Zaks    return true;
4141eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
415f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek  // Don't run the actions on declarations in header files unless
416f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek  // otherwise specified.
417fcd783d583d270b7ec1ec3e0fcf83cd93d30e381Ted Kremenek  SourceManager &SM = Ctx->getSourceManager();
418402785357ab053dd53f4fdd858b9630a5e0f8badChandler Carruth  SourceLocation SL = SM.getExpansionLoc(D->getLocation());
419fcd783d583d270b7ec1ec3e0fcf83cd93d30e381Ted Kremenek  if (!Opts.AnalyzeAll && !SM.isFromMainFile(SL))
42098520835eb1aa091429afa06e9f4f7ebe3864d34Anna Zaks    return true;
42198520835eb1aa091429afa06e9f4f7ebe3864d34Anna Zaks
42298520835eb1aa091429afa06e9f4f7ebe3864d34Anna Zaks  return false;
42398520835eb1aa091429afa06e9f4f7ebe3864d34Anna Zaks}
42498520835eb1aa091429afa06e9f4f7ebe3864d34Anna Zaks
425aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaksvoid AnalysisConsumer::HandleCode(Decl *D, AnalysisMode Mode,
426aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks                                  SetOfDecls *VisitedCallees) {
42798520835eb1aa091429afa06e9f4f7ebe3864d34Anna Zaks  if (skipFunction(D))
4281eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump    return;
429f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek
430aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks  DisplayFunction(D, Mode);
43198520835eb1aa091429afa06e9f4f7ebe3864d34Anna Zaks
4321d26f48dc2eea1c07431ca1519d7034a21b9bcffTed Kremenek  // Clear the AnalysisManager of old AnalysisDeclContexts.
43358f5ec7d56b1ebf5f90ee11226ebe7663f2821eaTed Kremenek  Mgr->ClearContexts();
434f6eafcca7734274d277afa121f2c4fb025a54218Ted Kremenek
4351eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  // Dispatch on the actions.
4365f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner  SmallVector<Decl*, 10> WL;
437fc576514d06c46a7cac49500169411d82f38d04bTed Kremenek  WL.push_back(D);
438f6eafcca7734274d277afa121f2c4fb025a54218Ted Kremenek
43906a54a38be5054c910ffc92db60edab23f9ea105Argyrios Kyrtzidis  if (D->hasBody() && Opts.AnalyzeNestedBlocks)
440fc576514d06c46a7cac49500169411d82f38d04bTed Kremenek    FindBlocks(cast<DeclContext>(D), WL);
441f6eafcca7734274d277afa121f2c4fb025a54218Ted Kremenek
4429fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis  BugReporter BR(*Mgr);
4435f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner  for (SmallVectorImpl<Decl*>::iterator WI=WL.begin(), WE=WL.end();
4449fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis       WI != WE; ++WI)
445d655ab28fdf7c940d3f79f8f287954d7f76e0977Argyrios Kyrtzidis    if ((*WI)->hasBody()) {
446aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks      if (Mode != ANALYSIS_PATH)
447aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks        checkerMgr->runCheckersOnASTBody(*WI, *Mgr, BR);
4481f5171edc9fb9b0698a75fa981c29a750b0a6082Anna Zaks      if (Mode != ANALYSIS_SYNTAX && checkerMgr->hasPathSensitiveCheckers()) {
4493fd5f370a28552976c52e76c3035d79012d78ddaAnna Zaks        RunPathSensitiveChecks(*WI, VisitedCallees);
4501f5171edc9fb9b0698a75fa981c29a750b0a6082Anna Zaks        NumFunctionsAnalyzed++;
4511f5171edc9fb9b0698a75fa981c29a750b0a6082Anna Zaks      }
452d655ab28fdf7c940d3f79f8f287954d7f76e0977Argyrios Kyrtzidis    }
453f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek}
454f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek
455f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek//===----------------------------------------------------------------------===//
456d655ab28fdf7c940d3f79f8f287954d7f76e0977Argyrios Kyrtzidis// Path-sensitive checking.
457f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek//===----------------------------------------------------------------------===//
458f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek
4593fd5f370a28552976c52e76c3035d79012d78ddaAnna Zaksvoid AnalysisConsumer::ActionExprEngine(Decl *D, bool ObjCGCEnabled,
4603fd5f370a28552976c52e76c3035d79012d78ddaAnna Zaks                                        SetOfDecls *VisitedCallees) {
461a5937bbfd19e61d651a58b0f0ffeef68457902a5Ted Kremenek  // Construct the analysis engine.  First check if the CFG is valid.
46275d03cffe20b5c945ef04eba208efb0437339997Ted Kremenek  // FIXME: Inter-procedural analysis will need to handle invalid CFGs.
4633fd5f370a28552976c52e76c3035d79012d78ddaAnna Zaks  if (!Mgr->getCFG(D))
464f6eafcca7734274d277afa121f2c4fb025a54218Ted Kremenek    return;
4653fd5f370a28552976c52e76c3035d79012d78ddaAnna Zaks
4663bbd8cd831788c506f2980293eb3c7e1b3ca2501Anna Zaks  ExprEngine Eng(*Mgr, ObjCGCEnabled, VisitedCallees, &FunctionSummaries);
467f6eafcca7734274d277afa121f2c4fb025a54218Ted Kremenek
468f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek  // Set the graph auditor.
4696f42b62b6194f53bcbc349f5d17388e1936535d7Dylan Noblesmith  OwningPtr<ExplodedNode::Auditor> Auditor;
4703fd5f370a28552976c52e76c3035d79012d78ddaAnna Zaks  if (Mgr->shouldVisualizeUbigraph()) {
471f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek    Auditor.reset(CreateUbiViz());
472c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu    ExplodedNode::SetAuditor(Auditor.get());
473f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek  }
4741eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
475b35a74a40c1d2656a25e560e773ed48bdf49f9c0Ted Kremenek  // Execute the worklist algorithm.
4763fd5f370a28552976c52e76c3035d79012d78ddaAnna Zaks  Eng.ExecuteWorkList(Mgr->getAnalysisDeclContextManager().getStackFrame(D, 0),
4773fd5f370a28552976c52e76c3035d79012d78ddaAnna Zaks                      Mgr->getMaxNodes());
4781eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
479f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek  // Release the auditor (if any) so that it doesn't monitor the graph
480f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek  // created BugReporter.
481c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu  ExplodedNode::SetAuditor(0);
4823df6421150271266b5a90fd4c6bfa6566c38c036Ted Kremenek
48334d7734b6ed1d9c0f647405e065251eb67f42badTed Kremenek  // Visualize the exploded graph.
4843fd5f370a28552976c52e76c3035d79012d78ddaAnna Zaks  if (Mgr->shouldVisualizeGraphviz())
4853fd5f370a28552976c52e76c3035d79012d78ddaAnna Zaks    Eng.ViewGraph(Mgr->shouldTrimGraph());
4861eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
4873df6421150271266b5a90fd4c6bfa6566c38c036Ted Kremenek  // Display warnings.
4883df6421150271266b5a90fd4c6bfa6566c38c036Ted Kremenek  Eng.getBugReporter().FlushReports();
489bc46f345838b1c0d420dbd3655c94f5f360fb5b8Ted Kremenek}
490bc46f345838b1c0d420dbd3655c94f5f360fb5b8Ted Kremenek
4913fd5f370a28552976c52e76c3035d79012d78ddaAnna Zaksvoid AnalysisConsumer::RunPathSensitiveChecks(Decl *D, SetOfDecls *Visited) {
49217a38e2636a8b1ce473fc6504c4b16cb09db29f4Jordy Rose
4934e4d08403ca5cfd4d558fa2936215d3a4e5a528dDavid Blaikie  switch (Mgr->getLangOpts().getGC()) {
49417a38e2636a8b1ce473fc6504c4b16cb09db29f4Jordy Rose  case LangOptions::NonGC:
4953fd5f370a28552976c52e76c3035d79012d78ddaAnna Zaks    ActionExprEngine(D, false, Visited);
49617a38e2636a8b1ce473fc6504c4b16cb09db29f4Jordy Rose    break;
49717a38e2636a8b1ce473fc6504c4b16cb09db29f4Jordy Rose
49817a38e2636a8b1ce473fc6504c4b16cb09db29f4Jordy Rose  case LangOptions::GCOnly:
4993fd5f370a28552976c52e76c3035d79012d78ddaAnna Zaks    ActionExprEngine(D, true, Visited);
50017a38e2636a8b1ce473fc6504c4b16cb09db29f4Jordy Rose    break;
50117a38e2636a8b1ce473fc6504c4b16cb09db29f4Jordy Rose
50217a38e2636a8b1ce473fc6504c4b16cb09db29f4Jordy Rose  case LangOptions::HybridGC:
5033fd5f370a28552976c52e76c3035d79012d78ddaAnna Zaks    ActionExprEngine(D, false, Visited);
5043fd5f370a28552976c52e76c3035d79012d78ddaAnna Zaks    ActionExprEngine(D, true, Visited);
50517a38e2636a8b1ce473fc6504c4b16cb09db29f4Jordy Rose    break;
50617a38e2636a8b1ce473fc6504c4b16cb09db29f4Jordy Rose  }
507b35a74a40c1d2656a25e560e773ed48bdf49f9c0Ted Kremenek}
508b35a74a40c1d2656a25e560e773ed48bdf49f9c0Ted Kremenek
509f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek//===----------------------------------------------------------------------===//
510f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek// AnalysisConsumer creation.
511f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek//===----------------------------------------------------------------------===//
512f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek
5139ef6537a894c33003359b1f9b9676e9178e028b7Ted KremenekASTConsumer* ento::CreateAnalysisConsumer(const Preprocessor& pp,
51408b86531ade68727c56918f162816075b87c864aJordy Rose                                          const std::string& outDir,
51508b86531ade68727c56918f162816075b87c864aJordy Rose                                          const AnalyzerOptions& opts,
51608b86531ade68727c56918f162816075b87c864aJordy Rose                                          ArrayRef<std::string> plugins) {
51708b86531ade68727c56918f162816075b87c864aJordy Rose  // Disable the effects of '-Werror' when using the AnalysisConsumer.
518efceabd2380f49306bc0229583458e93b062094bDaniel Dunbar  pp.getDiagnostics().setWarningsAsErrors(false);
519be1fe1eb12a1cb91c8e3a9fcc2db4dfe989def6cTed Kremenek
52008b86531ade68727c56918f162816075b87c864aJordy Rose  return new AnalysisConsumer(pp, outDir, opts, plugins);
521f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek}
522f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek
523f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek//===----------------------------------------------------------------------===//
524f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek// Ubigraph Visualization.  FIXME: Move to separate file.
525f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek//===----------------------------------------------------------------------===//
526f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek
527f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremeneknamespace {
5281eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
529c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xuclass UbigraphViz : public ExplodedNode::Auditor {
5306f42b62b6194f53bcbc349f5d17388e1936535d7Dylan Noblesmith  OwningPtr<raw_ostream> Out;
531710ad9343f32b33b336369b20edad1a21a0b3299Ted Kremenek  llvm::sys::Path Dir, Filename;
532f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek  unsigned Cntr;
533f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek
534f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek  typedef llvm::DenseMap<void*,unsigned> VMap;
535f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek  VMap M;
5361eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
537f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenekpublic:
5389c378f705405d37f49795d5e915989de774fe11fTed Kremenek  UbigraphViz(raw_ostream *out, llvm::sys::Path& dir,
53956b98719b0dbebb33cb228afa888c47156be2381Ted Kremenek              llvm::sys::Path& filename);
5401eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
541710ad9343f32b33b336369b20edad1a21a0b3299Ted Kremenek  ~UbigraphViz();
5421eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
5439c378f705405d37f49795d5e915989de774fe11fTed Kremenek  virtual void AddEdge(ExplodedNode *Src, ExplodedNode *Dst);
544f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek};
5451eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
546f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek} // end anonymous namespace
547f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek
548c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xustatic ExplodedNode::Auditor* CreateUbiViz() {
549f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek  std::string ErrMsg;
5501eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
551710ad9343f32b33b336369b20edad1a21a0b3299Ted Kremenek  llvm::sys::Path Dir = llvm::sys::Path::GetTemporaryDirectory(&ErrMsg);
552f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek  if (!ErrMsg.empty())
553f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek    return 0;
554f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek
555710ad9343f32b33b336369b20edad1a21a0b3299Ted Kremenek  llvm::sys::Path Filename = Dir;
556f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek  Filename.appendComponent("llvm_ubi");
557f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek  Filename.makeUnique(true,&ErrMsg);
558f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek
559f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek  if (!ErrMsg.empty())
560f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek    return 0;
561f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek
562d57a7ef9252964bc6c8471451d7bd395b0520cb8Chris Lattner  llvm::errs() << "Writing '" << Filename.str() << "'.\n";
5631eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
5646f42b62b6194f53bcbc349f5d17388e1936535d7Dylan Noblesmith  OwningPtr<llvm::raw_fd_ostream> Stream;
565b044c473a155b7e827680635c1699cb2b5b6c0eeDan Gohman  Stream.reset(new llvm::raw_fd_ostream(Filename.c_str(), ErrMsg));
566f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek
567f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek  if (!ErrMsg.empty())
568f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek    return 0;
5691eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
570710ad9343f32b33b336369b20edad1a21a0b3299Ted Kremenek  return new UbigraphViz(Stream.take(), Dir, Filename);
571f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek}
572f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek
5739c378f705405d37f49795d5e915989de774fe11fTed Kremenekvoid UbigraphViz::AddEdge(ExplodedNode *Src, ExplodedNode *Dst) {
5741eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
57545479c88c8a44c55d27c3bd855273bb318082f37Ted Kremenek  assert (Src != Dst && "Self-edges are not allowed.");
5761eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
577f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek  // Lookup the Src.  If it is a new node, it's a root.
578f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek  VMap::iterator SrcI= M.find(Src);
579f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek  unsigned SrcID;
5801eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
581f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek  if (SrcI == M.end()) {
582f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek    M[Src] = SrcID = Cntr++;
583f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek    *Out << "('vertex', " << SrcID << ", ('color','#00ff00'))\n";
584f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek  }
585f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek  else
586f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek    SrcID = SrcI->second;
5871eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
588f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek  // Lookup the Dst.
589f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek  VMap::iterator DstI= M.find(Dst);
590f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek  unsigned DstID;
591f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek
592f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek  if (DstI == M.end()) {
593f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek    M[Dst] = DstID = Cntr++;
594f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek    *Out << "('vertex', " << DstID << ")\n";
595f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek  }
59656b98719b0dbebb33cb228afa888c47156be2381Ted Kremenek  else {
59756b98719b0dbebb33cb228afa888c47156be2381Ted Kremenek    // We have hit DstID before.  Change its style to reflect a cache hit.
598f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek    DstID = DstI->second;
59956b98719b0dbebb33cb228afa888c47156be2381Ted Kremenek    *Out << "('change_vertex_style', " << DstID << ", 1)\n";
60056b98719b0dbebb33cb228afa888c47156be2381Ted Kremenek  }
601f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek
602f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek  // Add the edge.
6031eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  *Out << "('edge', " << SrcID << ", " << DstID
604d1289327f7d2126d732e23cc189ecd0aa5d07cbbTed Kremenek       << ", ('arrow','true'), ('oriented', 'true'))\n";
605f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek}
606f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek
6079c378f705405d37f49795d5e915989de774fe11fTed KremenekUbigraphViz::UbigraphViz(raw_ostream *out, llvm::sys::Path& dir,
60856b98719b0dbebb33cb228afa888c47156be2381Ted Kremenek                         llvm::sys::Path& filename)
60956b98719b0dbebb33cb228afa888c47156be2381Ted Kremenek  : Out(out), Dir(dir), Filename(filename), Cntr(0) {
61056b98719b0dbebb33cb228afa888c47156be2381Ted Kremenek
61156b98719b0dbebb33cb228afa888c47156be2381Ted Kremenek  *Out << "('vertex_style_attribute', 0, ('shape', 'icosahedron'))\n";
61256b98719b0dbebb33cb228afa888c47156be2381Ted Kremenek  *Out << "('vertex_style', 1, 0, ('shape', 'sphere'), ('color', '#ffcc66'),"
61356b98719b0dbebb33cb228afa888c47156be2381Ted Kremenek          " ('size', '1.5'))\n";
61456b98719b0dbebb33cb228afa888c47156be2381Ted Kremenek}
61556b98719b0dbebb33cb228afa888c47156be2381Ted Kremenek
616710ad9343f32b33b336369b20edad1a21a0b3299Ted KremenekUbigraphViz::~UbigraphViz() {
617710ad9343f32b33b336369b20edad1a21a0b3299Ted Kremenek  Out.reset(0);
6186cb7c1a43b0c8f739d1f54b7fdae5ede86033496Benjamin Kramer  llvm::errs() << "Running 'ubiviz' program... ";
619710ad9343f32b33b336369b20edad1a21a0b3299Ted Kremenek  std::string ErrMsg;
620710ad9343f32b33b336369b20edad1a21a0b3299Ted Kremenek  llvm::sys::Path Ubiviz = llvm::sys::Program::FindProgramByName("ubiviz");
621710ad9343f32b33b336369b20edad1a21a0b3299Ted Kremenek  std::vector<const char*> args;
622710ad9343f32b33b336369b20edad1a21a0b3299Ted Kremenek  args.push_back(Ubiviz.c_str());
623710ad9343f32b33b336369b20edad1a21a0b3299Ted Kremenek  args.push_back(Filename.c_str());
624710ad9343f32b33b336369b20edad1a21a0b3299Ted Kremenek  args.push_back(0);
6251eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
626710ad9343f32b33b336369b20edad1a21a0b3299Ted Kremenek  if (llvm::sys::Program::ExecuteAndWait(Ubiviz, &args[0],0,0,0,0,&ErrMsg)) {
6276cb7c1a43b0c8f739d1f54b7fdae5ede86033496Benjamin Kramer    llvm::errs() << "Error viewing graph: " << ErrMsg << "\n";
628710ad9343f32b33b336369b20edad1a21a0b3299Ted Kremenek  }
6291eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
630710ad9343f32b33b336369b20edad1a21a0b3299Ted Kremenek  // Delete the directory.
6311eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  Dir.eraseFromDisk(true);
632932680ecdeab4c216ce7c0736093d3dcd2f60f6dDaniel Dunbar}
633