AnalysisConsumer.cpp revision d1e5a89226da79f7e6f43d40facc46abda9e5245
147dc457387b690c5e4df1c0c7dd8c4337b92e630Sean Callanan//===--- AnalysisConsumer.cpp - ASTConsumer for running Analyses ----------===//
247dc457387b690c5e4df1c0c7dd8c4337b92e630Sean Callanan//
347dc457387b690c5e4df1c0c7dd8c4337b92e630Sean Callanan//                     The LLVM Compiler Infrastructure
447dc457387b690c5e4df1c0c7dd8c4337b92e630Sean Callanan//
547dc457387b690c5e4df1c0c7dd8c4337b92e630Sean Callanan// This file is distributed under the University of Illinois Open Source
647dc457387b690c5e4df1c0c7dd8c4337b92e630Sean Callanan// License. See LICENSE.TXT for details.
747dc457387b690c5e4df1c0c7dd8c4337b92e630Sean Callanan//
847dc457387b690c5e4df1c0c7dd8c4337b92e630Sean Callanan//===----------------------------------------------------------------------===//
947dc457387b690c5e4df1c0c7dd8c4337b92e630Sean Callanan//
1047dc457387b690c5e4df1c0c7dd8c4337b92e630Sean Callanan// "Meta" ASTConsumer for running different source analyses.
1147dc457387b690c5e4df1c0c7dd8c4337b92e630Sean Callanan//
1247dc457387b690c5e4df1c0c7dd8c4337b92e630Sean Callanan//===----------------------------------------------------------------------===//
1347dc457387b690c5e4df1c0c7dd8c4337b92e630Sean Callanan
1452d0d027dd38518e4b0cfb135a5d50a6652c5dafSean Callanan#include "AnalysisConsumer.h"
1547dc457387b690c5e4df1c0c7dd8c4337b92e630Sean Callanan#include "clang/AST/ASTConsumer.h"
1647dc457387b690c5e4df1c0c7dd8c4337b92e630Sean Callanan#include "clang/AST/Decl.h"
1747dc457387b690c5e4df1c0c7dd8c4337b92e630Sean Callanan#include "clang/AST/DeclCXX.h"
18a80c70c22a3e25d693e1a569a5209820873d44c8Chandler Carruth#include "clang/AST/DeclObjC.h"
19a80c70c22a3e25d693e1a569a5209820873d44c8Chandler Carruth#include "clang/AST/ParentMap.h"
20a80c70c22a3e25d693e1a569a5209820873d44c8Chandler Carruth#include "clang/Analysis/CFG.h"
21a80c70c22a3e25d693e1a569a5209820873d44c8Chandler Carruth#include "clang/StaticAnalyzer/Frontend/CheckerRegistration.h"
2247dc457387b690c5e4df1c0c7dd8c4337b92e630Sean Callanan#include "clang/StaticAnalyzer/Core/CheckerManager.h"
23a80c70c22a3e25d693e1a569a5209820873d44c8Chandler Carruth#include "clang/StaticAnalyzer/Checkers/LocalCheckers.h"
2447dc457387b690c5e4df1c0c7dd8c4337b92e630Sean Callanan#include "clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h"
2547dc457387b690c5e4df1c0c7dd8c4337b92e630Sean Callanan#include "clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h"
2647dc457387b690c5e4df1c0c7dd8c4337b92e630Sean Callanan#include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h"
2747dc457387b690c5e4df1c0c7dd8c4337b92e630Sean Callanan#include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
2847dc457387b690c5e4df1c0c7dd8c4337b92e630Sean Callanan#include "clang/StaticAnalyzer/Core/PathDiagnosticClients.h"
2947dc457387b690c5e4df1c0c7dd8c4337b92e630Sean Callanan
3086d6ac2a3d920622c1ee7a68b5ca28b09dc18142Sean Callanan#include "clang/Basic/FileManager.h"
3186d6ac2a3d920622c1ee7a68b5ca28b09dc18142Sean Callanan#include "clang/Basic/SourceManager.h"
3286d6ac2a3d920622c1ee7a68b5ca28b09dc18142Sean Callanan#include "clang/Frontend/AnalyzerOptions.h"
3386d6ac2a3d920622c1ee7a68b5ca28b09dc18142Sean Callanan#include "clang/Lex/Preprocessor.h"
3447dc457387b690c5e4df1c0c7dd8c4337b92e630Sean Callanan#include "llvm/Support/raw_ostream.h"
3547dc457387b690c5e4df1c0c7dd8c4337b92e630Sean Callanan#include "llvm/Support/Path.h"
3647dc457387b690c5e4df1c0c7dd8c4337b92e630Sean Callanan#include "llvm/Support/Program.h"
3747dc457387b690c5e4df1c0c7dd8c4337b92e630Sean Callanan#include "llvm/ADT/OwningPtr.h"
3847dc457387b690c5e4df1c0c7dd8c4337b92e630Sean Callanan
3947dc457387b690c5e4df1c0c7dd8c4337b92e630Sean Callananusing namespace clang;
4047dc457387b690c5e4df1c0c7dd8c4337b92e630Sean Callananusing namespace ento;
4147dc457387b690c5e4df1c0c7dd8c4337b92e630Sean Callanan
4247dc457387b690c5e4df1c0c7dd8c4337b92e630Sean Callananstatic ExplodedNode::Auditor* CreateUbiViz();
4347dc457387b690c5e4df1c0c7dd8c4337b92e630Sean Callanan
4447dc457387b690c5e4df1c0c7dd8c4337b92e630Sean Callanan//===----------------------------------------------------------------------===//
4547dc457387b690c5e4df1c0c7dd8c4337b92e630Sean Callanan// Special PathDiagnosticClients.
4647dc457387b690c5e4df1c0c7dd8c4337b92e630Sean Callanan//===----------------------------------------------------------------------===//
4747dc457387b690c5e4df1c0c7dd8c4337b92e630Sean Callanan
4847dc457387b690c5e4df1c0c7dd8c4337b92e630Sean Callananstatic PathDiagnosticClient*
4947dc457387b690c5e4df1c0c7dd8c4337b92e630Sean CallanancreatePlistHTMLDiagnosticClient(const std::string& prefix,
5047dc457387b690c5e4df1c0c7dd8c4337b92e630Sean Callanan                                const Preprocessor &PP) {
5147dc457387b690c5e4df1c0c7dd8c4337b92e630Sean Callanan  PathDiagnosticClient *PD =
5247dc457387b690c5e4df1c0c7dd8c4337b92e630Sean Callanan    createHTMLDiagnosticClient(llvm::sys::path::parent_path(prefix), PP);
5347dc457387b690c5e4df1c0c7dd8c4337b92e630Sean Callanan  return createPlistDiagnosticClient(prefix, PP, PD);
5447dc457387b690c5e4df1c0c7dd8c4337b92e630Sean Callanan}
5547dc457387b690c5e4df1c0c7dd8c4337b92e630Sean Callanan
5647dc457387b690c5e4df1c0c7dd8c4337b92e630Sean Callanan//===----------------------------------------------------------------------===//
5747dc457387b690c5e4df1c0c7dd8c4337b92e630Sean Callanan// AnalysisConsumer declaration.
5847dc457387b690c5e4df1c0c7dd8c4337b92e630Sean Callanan//===----------------------------------------------------------------------===//
5947dc457387b690c5e4df1c0c7dd8c4337b92e630Sean Callanan
6047dc457387b690c5e4df1c0c7dd8c4337b92e630Sean Callanannamespace {
6147dc457387b690c5e4df1c0c7dd8c4337b92e630Sean Callanan
6247dc457387b690c5e4df1c0c7dd8c4337b92e630Sean Callananclass AnalysisConsumer : public ASTConsumer {
6347dc457387b690c5e4df1c0c7dd8c4337b92e630Sean Callananpublic:
6447dc457387b690c5e4df1c0c7dd8c4337b92e630Sean Callanan  ASTContext *Ctx;
6547dc457387b690c5e4df1c0c7dd8c4337b92e630Sean Callanan  const Preprocessor &PP;
6647dc457387b690c5e4df1c0c7dd8c4337b92e630Sean Callanan  const std::string OutDir;
6747dc457387b690c5e4df1c0c7dd8c4337b92e630Sean Callanan  AnalyzerOptions Opts;
6847dc457387b690c5e4df1c0c7dd8c4337b92e630Sean Callanan  ArrayRef<std::string> Plugins;
6947dc457387b690c5e4df1c0c7dd8c4337b92e630Sean Callanan
7047dc457387b690c5e4df1c0c7dd8c4337b92e630Sean Callanan  // PD is owned by AnalysisManager.
7147dc457387b690c5e4df1c0c7dd8c4337b92e630Sean Callanan  PathDiagnosticClient *PD;
7247dc457387b690c5e4df1c0c7dd8c4337b92e630Sean Callanan
7347dc457387b690c5e4df1c0c7dd8c4337b92e630Sean Callanan  StoreManagerCreator CreateStoreMgr;
7413615cfef0435af28ccc1e93e13c6161e94585edSean Callanan  ConstraintManagerCreator CreateConstraintMgr;
7547dc457387b690c5e4df1c0c7dd8c4337b92e630Sean Callanan
7647dc457387b690c5e4df1c0c7dd8c4337b92e630Sean Callanan  llvm::OwningPtr<CheckerManager> checkerMgr;
7713615cfef0435af28ccc1e93e13c6161e94585edSean Callanan  llvm::OwningPtr<AnalysisManager> Mgr;
7847dc457387b690c5e4df1c0c7dd8c4337b92e630Sean Callanan
7913615cfef0435af28ccc1e93e13c6161e94585edSean Callanan  AnalysisConsumer(const Preprocessor& pp,
8047dc457387b690c5e4df1c0c7dd8c4337b92e630Sean Callanan                   const std::string& outdir,
8113615cfef0435af28ccc1e93e13c6161e94585edSean Callanan                   const AnalyzerOptions& opts,
8213615cfef0435af28ccc1e93e13c6161e94585edSean Callanan                   ArrayRef<std::string> plugins)
8313615cfef0435af28ccc1e93e13c6161e94585edSean Callanan    : Ctx(0), PP(pp), OutDir(outdir), Opts(opts), Plugins(plugins), PD(0) {
8413615cfef0435af28ccc1e93e13c6161e94585edSean Callanan    DigestAnalyzerOptions();
8513615cfef0435af28ccc1e93e13c6161e94585edSean Callanan  }
8613615cfef0435af28ccc1e93e13c6161e94585edSean Callanan
8713615cfef0435af28ccc1e93e13c6161e94585edSean Callanan  void DigestAnalyzerOptions() {
8813615cfef0435af28ccc1e93e13c6161e94585edSean Callanan    // Create the PathDiagnosticClient.
8913615cfef0435af28ccc1e93e13c6161e94585edSean Callanan    if (!OutDir.empty()) {
9013615cfef0435af28ccc1e93e13c6161e94585edSean Callanan      switch (Opts.AnalysisDiagOpt) {
9147dc457387b690c5e4df1c0c7dd8c4337b92e630Sean Callanan      default:
9247dc457387b690c5e4df1c0c7dd8c4337b92e630Sean Callanan#define ANALYSIS_DIAGNOSTICS(NAME, CMDFLAG, DESC, CREATEFN, AUTOCREATE) \
9347dc457387b690c5e4df1c0c7dd8c4337b92e630Sean Callanan        case PD_##NAME: PD = CREATEFN(OutDir, PP); break;
9447dc457387b690c5e4df1c0c7dd8c4337b92e630Sean Callanan#include "clang/Frontend/Analyses.def"
9513615cfef0435af28ccc1e93e13c6161e94585edSean Callanan      }
9647dc457387b690c5e4df1c0c7dd8c4337b92e630Sean Callanan    } else if (Opts.AnalysisDiagOpt == PD_TEXT) {
9747dc457387b690c5e4df1c0c7dd8c4337b92e630Sean Callanan      // Create the text client even without a specified output file since
9813615cfef0435af28ccc1e93e13c6161e94585edSean Callanan      // it just uses diagnostic notes.
993051ed73a487e92f12f8b6062f8415781453da21Micah Villmow      PD = createTextPathDiagnosticClient("", PP);
10047dc457387b690c5e4df1c0c7dd8c4337b92e630Sean Callanan    }
10186d6ac2a3d920622c1ee7a68b5ca28b09dc18142Sean Callanan
10247dc457387b690c5e4df1c0c7dd8c4337b92e630Sean Callanan    // Create the analyzer component creators.
10347dc457387b690c5e4df1c0c7dd8c4337b92e630Sean Callanan    switch (Opts.AnalysisStoreOpt) {
10447dc457387b690c5e4df1c0c7dd8c4337b92e630Sean Callanan    default:
10547dc457387b690c5e4df1c0c7dd8c4337b92e630Sean Callanan      assert(0 && "Unknown store manager.");
10647dc457387b690c5e4df1c0c7dd8c4337b92e630Sean Callanan#define ANALYSIS_STORE(NAME, CMDFLAG, DESC, CREATEFN)           \
10747dc457387b690c5e4df1c0c7dd8c4337b92e630Sean Callanan      case NAME##Model: CreateStoreMgr = CREATEFN; break;
10847dc457387b690c5e4df1c0c7dd8c4337b92e630Sean Callanan#include "clang/Frontend/Analyses.def"
1093051ed73a487e92f12f8b6062f8415781453da21Micah Villmow    }
11086d6ac2a3d920622c1ee7a68b5ca28b09dc18142Sean Callanan
11186d6ac2a3d920622c1ee7a68b5ca28b09dc18142Sean Callanan    switch (Opts.AnalysisConstraintsOpt) {
11297c8957257a3e0b3ce6f46f8e5a28c965e30f357Daniel Dunbar    default:
11386d6ac2a3d920622c1ee7a68b5ca28b09dc18142Sean Callanan      assert(0 && "Unknown store manager.");
11486d6ac2a3d920622c1ee7a68b5ca28b09dc18142Sean Callanan#define ANALYSIS_CONSTRAINTS(NAME, CMDFLAG, DESC, CREATEFN)     \
11547dc457387b690c5e4df1c0c7dd8c4337b92e630Sean Callanan      case NAME##Model: CreateConstraintMgr = CREATEFN; break;
11647dc457387b690c5e4df1c0c7dd8c4337b92e630Sean Callanan#include "clang/Frontend/Analyses.def"
1174fbe61ba371bfde827b9424ebe5e14dce3d5fad3Sean Callanan    }
11847dc457387b690c5e4df1c0c7dd8c4337b92e630Sean Callanan  }
11947dc457387b690c5e4df1c0c7dd8c4337b92e630Sean Callanan
12047dc457387b690c5e4df1c0c7dd8c4337b92e630Sean Callanan  void DisplayFunction(const Decl *D) {
12147dc457387b690c5e4df1c0c7dd8c4337b92e630Sean Callanan    if (!Opts.AnalyzerDisplayProgress)
12247dc457387b690c5e4df1c0c7dd8c4337b92e630Sean Callanan      return;
12347dc457387b690c5e4df1c0c7dd8c4337b92e630Sean Callanan
12447dc457387b690c5e4df1c0c7dd8c4337b92e630Sean Callanan    SourceManager &SM = Mgr->getASTContext().getSourceManager();
12547dc457387b690c5e4df1c0c7dd8c4337b92e630Sean Callanan    PresumedLoc Loc = SM.getPresumedLoc(D->getLocation());
12647dc457387b690c5e4df1c0c7dd8c4337b92e630Sean Callanan    if (Loc.isValid()) {
12747dc457387b690c5e4df1c0c7dd8c4337b92e630Sean Callanan      llvm::errs() << "ANALYZE: " << Loc.getFilename();
12847dc457387b690c5e4df1c0c7dd8c4337b92e630Sean Callanan
12947dc457387b690c5e4df1c0c7dd8c4337b92e630Sean Callanan      if (isa<FunctionDecl>(D) || isa<ObjCMethodDecl>(D)) {
13047dc457387b690c5e4df1c0c7dd8c4337b92e630Sean Callanan        const NamedDecl *ND = cast<NamedDecl>(D);
13147dc457387b690c5e4df1c0c7dd8c4337b92e630Sean Callanan        llvm::errs() << ' ' << ND << '\n';
13247dc457387b690c5e4df1c0c7dd8c4337b92e630Sean Callanan      }
13347dc457387b690c5e4df1c0c7dd8c4337b92e630Sean Callanan      else if (isa<BlockDecl>(D)) {
13447dc457387b690c5e4df1c0c7dd8c4337b92e630Sean Callanan        llvm::errs() << ' ' << "block(line:" << Loc.getLine() << ",col:"
13547dc457387b690c5e4df1c0c7dd8c4337b92e630Sean Callanan                     << Loc.getColumn() << '\n';
13647dc457387b690c5e4df1c0c7dd8c4337b92e630Sean Callanan      }
13713615cfef0435af28ccc1e93e13c6161e94585edSean Callanan      else if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D)) {
13847dc457387b690c5e4df1c0c7dd8c4337b92e630Sean Callanan        Selector S = MD->getSelector();
13913615cfef0435af28ccc1e93e13c6161e94585edSean Callanan        llvm::errs() << ' ' << S.getAsString();
14047dc457387b690c5e4df1c0c7dd8c4337b92e630Sean Callanan      }
14147dc457387b690c5e4df1c0c7dd8c4337b92e630Sean Callanan    }
14247dc457387b690c5e4df1c0c7dd8c4337b92e630Sean Callanan  }
14347dc457387b690c5e4df1c0c7dd8c4337b92e630Sean Callanan
14447dc457387b690c5e4df1c0c7dd8c4337b92e630Sean Callanan  virtual void Initialize(ASTContext &Context) {
14547dc457387b690c5e4df1c0c7dd8c4337b92e630Sean Callanan    Ctx = &Context;
14647dc457387b690c5e4df1c0c7dd8c4337b92e630Sean Callanan    checkerMgr.reset(createCheckerManager(Opts, PP.getLangOptions(), Plugins,
14747dc457387b690c5e4df1c0c7dd8c4337b92e630Sean Callanan                                          PP.getDiagnostics()));
14847dc457387b690c5e4df1c0c7dd8c4337b92e630Sean Callanan    Mgr.reset(new AnalysisManager(*Ctx, PP.getDiagnostics(),
14947dc457387b690c5e4df1c0c7dd8c4337b92e630Sean Callanan                                  PP.getLangOptions(), PD,
15047dc457387b690c5e4df1c0c7dd8c4337b92e630Sean Callanan                                  CreateStoreMgr, CreateConstraintMgr,
15147dc457387b690c5e4df1c0c7dd8c4337b92e630Sean Callanan                                  checkerMgr.get(),
15247dc457387b690c5e4df1c0c7dd8c4337b92e630Sean Callanan                                  /* Indexer */ 0,
15347dc457387b690c5e4df1c0c7dd8c4337b92e630Sean Callanan                                  Opts.MaxNodes, Opts.MaxLoop,
15447dc457387b690c5e4df1c0c7dd8c4337b92e630Sean Callanan                                  Opts.VisualizeEGDot, Opts.VisualizeEGUbi,
15547dc457387b690c5e4df1c0c7dd8c4337b92e630Sean Callanan                                  Opts.PurgeDead, Opts.EagerlyAssume,
15647dc457387b690c5e4df1c0c7dd8c4337b92e630Sean Callanan                                  Opts.TrimGraph, Opts.InlineCall,
15747dc457387b690c5e4df1c0c7dd8c4337b92e630Sean Callanan                                  Opts.UnoptimizedCFG, Opts.CFGAddImplicitDtors,
15847dc457387b690c5e4df1c0c7dd8c4337b92e630Sean Callanan                                  Opts.CFGAddInitializers,
15947dc457387b690c5e4df1c0c7dd8c4337b92e630Sean Callanan                                  Opts.EagerlyTrimEGraph));
16047dc457387b690c5e4df1c0c7dd8c4337b92e630Sean Callanan  }
16147dc457387b690c5e4df1c0c7dd8c4337b92e630Sean Callanan
16247dc457387b690c5e4df1c0c7dd8c4337b92e630Sean Callanan  virtual void HandleTranslationUnit(ASTContext &C);
16347dc457387b690c5e4df1c0c7dd8c4337b92e630Sean Callanan  void HandleDeclContext(ASTContext &C, DeclContext *dc);
16447dc457387b690c5e4df1c0c7dd8c4337b92e630Sean Callanan  void HandleDeclContextDecl(ASTContext &C, Decl *D);
16547dc457387b690c5e4df1c0c7dd8c4337b92e630Sean Callanan
16647dc457387b690c5e4df1c0c7dd8c4337b92e630Sean Callanan  void HandleCode(Decl *D);
16747dc457387b690c5e4df1c0c7dd8c4337b92e630Sean Callanan};
16847dc457387b690c5e4df1c0c7dd8c4337b92e630Sean Callanan} // end anonymous namespace
16947dc457387b690c5e4df1c0c7dd8c4337b92e630Sean Callanan
17047dc457387b690c5e4df1c0c7dd8c4337b92e630Sean Callanan//===----------------------------------------------------------------------===//
17147dc457387b690c5e4df1c0c7dd8c4337b92e630Sean Callanan// AnalysisConsumer implementation.
17247dc457387b690c5e4df1c0c7dd8c4337b92e630Sean Callanan//===----------------------------------------------------------------------===//
17347dc457387b690c5e4df1c0c7dd8c4337b92e630Sean Callanan
17447dc457387b690c5e4df1c0c7dd8c4337b92e630Sean Callananvoid AnalysisConsumer::HandleDeclContext(ASTContext &C, DeclContext *dc) {
17547dc457387b690c5e4df1c0c7dd8c4337b92e630Sean Callanan  for (DeclContext::decl_iterator I = dc->decls_begin(), E = dc->decls_end();
17647dc457387b690c5e4df1c0c7dd8c4337b92e630Sean Callanan       I != E; ++I) {
17747dc457387b690c5e4df1c0c7dd8c4337b92e630Sean Callanan    HandleDeclContextDecl(C, *I);
17847dc457387b690c5e4df1c0c7dd8c4337b92e630Sean Callanan  }
17947dc457387b690c5e4df1c0c7dd8c4337b92e630Sean Callanan}
18047dc457387b690c5e4df1c0c7dd8c4337b92e630Sean Callanan
18147dc457387b690c5e4df1c0c7dd8c4337b92e630Sean Callananvoid AnalysisConsumer::HandleDeclContextDecl(ASTContext &C, Decl *D) {
18247dc457387b690c5e4df1c0c7dd8c4337b92e630Sean Callanan  { // Handle callbacks for arbitrary decls.
18313615cfef0435af28ccc1e93e13c6161e94585edSean Callanan    BugReporter BR(*Mgr);
18413615cfef0435af28ccc1e93e13c6161e94585edSean Callanan    checkerMgr->runCheckersOnASTDecl(D, *Mgr, BR);
18513615cfef0435af28ccc1e93e13c6161e94585edSean Callanan  }
18613615cfef0435af28ccc1e93e13c6161e94585edSean Callanan
18713615cfef0435af28ccc1e93e13c6161e94585edSean Callanan  switch (D->getKind()) {
18847dc457387b690c5e4df1c0c7dd8c4337b92e630Sean Callanan    case Decl::Namespace: {
18913615cfef0435af28ccc1e93e13c6161e94585edSean Callanan      HandleDeclContext(C, cast<NamespaceDecl>(D));
19013615cfef0435af28ccc1e93e13c6161e94585edSean Callanan      break;
19113615cfef0435af28ccc1e93e13c6161e94585edSean Callanan    }
19247dc457387b690c5e4df1c0c7dd8c4337b92e630Sean Callanan    case Decl::CXXConstructor:
19347dc457387b690c5e4df1c0c7dd8c4337b92e630Sean Callanan    case Decl::CXXDestructor:
19436da2aa6dc5ad9994b638ed09eb81c44cc05540bGreg Clayton    case Decl::CXXConversion:
19513615cfef0435af28ccc1e93e13c6161e94585edSean Callanan    case Decl::CXXMethod:
19647dc457387b690c5e4df1c0c7dd8c4337b92e630Sean Callanan    case Decl::Function: {
19747dc457387b690c5e4df1c0c7dd8c4337b92e630Sean Callanan      FunctionDecl *FD = cast<FunctionDecl>(D);
19847dc457387b690c5e4df1c0c7dd8c4337b92e630Sean Callanan      // We skip function template definitions, as their semantics is
19947dc457387b690c5e4df1c0c7dd8c4337b92e630Sean Callanan      // only determined when they are instantiated.
20047dc457387b690c5e4df1c0c7dd8c4337b92e630Sean Callanan      if (FD->isThisDeclarationADefinition() &&
20147dc457387b690c5e4df1c0c7dd8c4337b92e630Sean Callanan          !FD->isDependentContext()) {
20247dc457387b690c5e4df1c0c7dd8c4337b92e630Sean Callanan        if (!Opts.AnalyzeSpecificFunction.empty() &&
20347dc457387b690c5e4df1c0c7dd8c4337b92e630Sean Callanan            FD->getDeclName().getAsString() != Opts.AnalyzeSpecificFunction)
20447dc457387b690c5e4df1c0c7dd8c4337b92e630Sean Callanan          break;
20513615cfef0435af28ccc1e93e13c6161e94585edSean Callanan        DisplayFunction(FD);
20613615cfef0435af28ccc1e93e13c6161e94585edSean Callanan        HandleCode(FD);
20713615cfef0435af28ccc1e93e13c6161e94585edSean Callanan      }
20813615cfef0435af28ccc1e93e13c6161e94585edSean Callanan      break;
20947dc457387b690c5e4df1c0c7dd8c4337b92e630Sean Callanan    }
21047dc457387b690c5e4df1c0c7dd8c4337b92e630Sean Callanan
21147dc457387b690c5e4df1c0c7dd8c4337b92e630Sean Callanan    case Decl::ObjCCategoryImpl:
21247dc457387b690c5e4df1c0c7dd8c4337b92e630Sean Callanan    case Decl::ObjCImplementation: {
21347dc457387b690c5e4df1c0c7dd8c4337b92e630Sean Callanan      ObjCImplDecl *ID = cast<ObjCImplDecl>(D);
21413615cfef0435af28ccc1e93e13c6161e94585edSean Callanan      HandleCode(ID);
21513615cfef0435af28ccc1e93e13c6161e94585edSean Callanan
21647dc457387b690c5e4df1c0c7dd8c4337b92e630Sean Callanan      for (ObjCContainerDecl::method_iterator MI = ID->meth_begin(),
21713615cfef0435af28ccc1e93e13c6161e94585edSean Callanan           ME = ID->meth_end(); MI != ME; ++MI) {
21847dc457387b690c5e4df1c0c7dd8c4337b92e630Sean Callanan        BugReporter BR(*Mgr);
21913615cfef0435af28ccc1e93e13c6161e94585edSean Callanan        checkerMgr->runCheckersOnASTDecl(*MI, *Mgr, BR);
22047dc457387b690c5e4df1c0c7dd8c4337b92e630Sean Callanan
22113615cfef0435af28ccc1e93e13c6161e94585edSean Callanan        if ((*MI)->isThisDeclarationADefinition()) {
22247dc457387b690c5e4df1c0c7dd8c4337b92e630Sean Callanan          if (!Opts.AnalyzeSpecificFunction.empty() &&
22347dc457387b690c5e4df1c0c7dd8c4337b92e630Sean Callanan              Opts.AnalyzeSpecificFunction !=
22413615cfef0435af28ccc1e93e13c6161e94585edSean Callanan                (*MI)->getSelector().getAsString())
22547dc457387b690c5e4df1c0c7dd8c4337b92e630Sean Callanan            break;
22613615cfef0435af28ccc1e93e13c6161e94585edSean Callanan          DisplayFunction(*MI);
2275aff015bfe8ef7ae68c61801e320870471b2c4dfSean Callanan          HandleCode(*MI);
22813615cfef0435af28ccc1e93e13c6161e94585edSean Callanan        }
22947dc457387b690c5e4df1c0c7dd8c4337b92e630Sean Callanan      }
23047dc457387b690c5e4df1c0c7dd8c4337b92e630Sean Callanan      break;
2318eac77d782851ae85f821fee8eb0070b5d84b53bSean Callanan    }
23247dc457387b690c5e4df1c0c7dd8c4337b92e630Sean Callanan
23347dc457387b690c5e4df1c0c7dd8c4337b92e630Sean Callanan    default:
23447dc457387b690c5e4df1c0c7dd8c4337b92e630Sean Callanan      break;
2358eac77d782851ae85f821fee8eb0070b5d84b53bSean Callanan  }
2368eac77d782851ae85f821fee8eb0070b5d84b53bSean Callanan}
23747dc457387b690c5e4df1c0c7dd8c4337b92e630Sean Callanan
238557ccd6b47c5d4b3736e704e7f1e887a7fff6549Sean Callananvoid AnalysisConsumer::HandleTranslationUnit(ASTContext &C) {
23947dc457387b690c5e4df1c0c7dd8c4337b92e630Sean Callanan  BugReporter BR(*Mgr);
2408eac77d782851ae85f821fee8eb0070b5d84b53bSean Callanan  TranslationUnitDecl *TU = C.getTranslationUnitDecl();
2418eac77d782851ae85f821fee8eb0070b5d84b53bSean Callanan  checkerMgr->runCheckersOnASTDecl(TU, *Mgr, BR);
24247dc457387b690c5e4df1c0c7dd8c4337b92e630Sean Callanan  HandleDeclContext(C, TU);
243557ccd6b47c5d4b3736e704e7f1e887a7fff6549Sean Callanan
244557ccd6b47c5d4b3736e704e7f1e887a7fff6549Sean Callanan  // After all decls handled, run checkers on the entire TranslationUnit.
245557ccd6b47c5d4b3736e704e7f1e887a7fff6549Sean Callanan  checkerMgr->runCheckersOnEndOfTranslationUnit(TU, *Mgr, BR);
246557ccd6b47c5d4b3736e704e7f1e887a7fff6549Sean Callanan
2478eac77d782851ae85f821fee8eb0070b5d84b53bSean Callanan  // Explicitly destroy the PathDiagnosticClient.  This will flush its output.
2488eac77d782851ae85f821fee8eb0070b5d84b53bSean Callanan  // FIXME: This should be replaced with something that doesn't rely on
2498eac77d782851ae85f821fee8eb0070b5d84b53bSean Callanan  // side-effects in PathDiagnosticClient's destructor. This is required when
2506b21a9b7c854ccf1eef1753e1ce2e9ab4976e4c2Sean Callanan  // used with option -disable-free.
2518eac77d782851ae85f821fee8eb0070b5d84b53bSean Callanan  Mgr.reset(NULL);
2528eac77d782851ae85f821fee8eb0070b5d84b53bSean Callanan}
2538eac77d782851ae85f821fee8eb0070b5d84b53bSean Callanan
2548eac77d782851ae85f821fee8eb0070b5d84b53bSean Callananstatic void FindBlocks(DeclContext *D, SmallVectorImpl<Decl*> &WL) {
2558eac77d782851ae85f821fee8eb0070b5d84b53bSean Callanan  if (BlockDecl *BD = dyn_cast<BlockDecl>(D))
2568eac77d782851ae85f821fee8eb0070b5d84b53bSean Callanan    WL.push_back(BD);
2578eac77d782851ae85f821fee8eb0070b5d84b53bSean Callanan
2588eac77d782851ae85f821fee8eb0070b5d84b53bSean Callanan  for (DeclContext::decl_iterator I = D->decls_begin(), E = D->decls_end();
2598eac77d782851ae85f821fee8eb0070b5d84b53bSean Callanan       I!=E; ++I)
2608eac77d782851ae85f821fee8eb0070b5d84b53bSean Callanan    if (DeclContext *DC = dyn_cast<DeclContext>(*I))
2618eac77d782851ae85f821fee8eb0070b5d84b53bSean Callanan      FindBlocks(DC, WL);
2628eac77d782851ae85f821fee8eb0070b5d84b53bSean Callanan}
2638eac77d782851ae85f821fee8eb0070b5d84b53bSean Callanan
2648eac77d782851ae85f821fee8eb0070b5d84b53bSean Callananstatic void RunPathSensitiveChecks(AnalysisConsumer &C, AnalysisManager &mgr,
2658eac77d782851ae85f821fee8eb0070b5d84b53bSean Callanan                                   Decl *D);
2668eac77d782851ae85f821fee8eb0070b5d84b53bSean Callanan
2678eac77d782851ae85f821fee8eb0070b5d84b53bSean Callananvoid AnalysisConsumer::HandleCode(Decl *D) {
2688eac77d782851ae85f821fee8eb0070b5d84b53bSean Callanan
2698eac77d782851ae85f821fee8eb0070b5d84b53bSean Callanan  // Don't run the actions if an error has occurred with parsing the file.
2708eac77d782851ae85f821fee8eb0070b5d84b53bSean Callanan  Diagnostic &Diags = PP.getDiagnostics();
2718eac77d782851ae85f821fee8eb0070b5d84b53bSean Callanan  if (Diags.hasErrorOccurred() || Diags.hasFatalErrorOccurred())
2728eac77d782851ae85f821fee8eb0070b5d84b53bSean Callanan    return;
2738eac77d782851ae85f821fee8eb0070b5d84b53bSean Callanan
2748eac77d782851ae85f821fee8eb0070b5d84b53bSean Callanan  // Don't run the actions on declarations in header files unless
2758eac77d782851ae85f821fee8eb0070b5d84b53bSean Callanan  // otherwise specified.
2768eac77d782851ae85f821fee8eb0070b5d84b53bSean Callanan  SourceManager &SM = Ctx->getSourceManager();
2778eac77d782851ae85f821fee8eb0070b5d84b53bSean Callanan  SourceLocation SL = SM.getExpansionLoc(D->getLocation());
2788eac77d782851ae85f821fee8eb0070b5d84b53bSean Callanan  if (!Opts.AnalyzeAll && !SM.isFromMainFile(SL))
2798eac77d782851ae85f821fee8eb0070b5d84b53bSean Callanan    return;
280557ccd6b47c5d4b3736e704e7f1e887a7fff6549Sean Callanan
281557ccd6b47c5d4b3736e704e7f1e887a7fff6549Sean Callanan  // Clear the AnalysisManager of old AnalysisContexts.
28247dc457387b690c5e4df1c0c7dd8c4337b92e630Sean Callanan  Mgr->ClearContexts();
28347dc457387b690c5e4df1c0c7dd8c4337b92e630Sean Callanan
28447dc457387b690c5e4df1c0c7dd8c4337b92e630Sean Callanan  // Dispatch on the actions.
28547dc457387b690c5e4df1c0c7dd8c4337b92e630Sean Callanan  SmallVector<Decl*, 10> WL;
28613615cfef0435af28ccc1e93e13c6161e94585edSean Callanan  WL.push_back(D);
2878eac77d782851ae85f821fee8eb0070b5d84b53bSean Callanan
2888eac77d782851ae85f821fee8eb0070b5d84b53bSean Callanan  if (D->hasBody() && Opts.AnalyzeNestedBlocks)
2898eac77d782851ae85f821fee8eb0070b5d84b53bSean Callanan    FindBlocks(cast<DeclContext>(D), WL);
2908eac77d782851ae85f821fee8eb0070b5d84b53bSean Callanan
2918eac77d782851ae85f821fee8eb0070b5d84b53bSean Callanan  BugReporter BR(*Mgr);
2928eac77d782851ae85f821fee8eb0070b5d84b53bSean Callanan  for (SmallVectorImpl<Decl*>::iterator WI=WL.begin(), WE=WL.end();
2938eac77d782851ae85f821fee8eb0070b5d84b53bSean Callanan       WI != WE; ++WI)
2948eac77d782851ae85f821fee8eb0070b5d84b53bSean Callanan    if ((*WI)->hasBody()) {
2958eac77d782851ae85f821fee8eb0070b5d84b53bSean Callanan      checkerMgr->runCheckersOnASTBody(*WI, *Mgr, BR);
29613615cfef0435af28ccc1e93e13c6161e94585edSean Callanan      if (checkerMgr->hasPathSensitiveCheckers())
29713615cfef0435af28ccc1e93e13c6161e94585edSean Callanan        RunPathSensitiveChecks(*this, *Mgr, *WI);
29813615cfef0435af28ccc1e93e13c6161e94585edSean Callanan    }
29913615cfef0435af28ccc1e93e13c6161e94585edSean Callanan}
30013615cfef0435af28ccc1e93e13c6161e94585edSean Callanan
30113615cfef0435af28ccc1e93e13c6161e94585edSean Callanan//===----------------------------------------------------------------------===//
3028eac77d782851ae85f821fee8eb0070b5d84b53bSean Callanan// Path-sensitive checking.
30313615cfef0435af28ccc1e93e13c6161e94585edSean Callanan//===----------------------------------------------------------------------===//
30413615cfef0435af28ccc1e93e13c6161e94585edSean Callanan
30513615cfef0435af28ccc1e93e13c6161e94585edSean Callananstatic void ActionExprEngine(AnalysisConsumer &C, AnalysisManager &mgr,
30613615cfef0435af28ccc1e93e13c6161e94585edSean Callanan                             Decl *D, bool ObjCGCEnabled) {
30713615cfef0435af28ccc1e93e13c6161e94585edSean Callanan  // Construct the analysis engine.  We first query for the LiveVariables
30813615cfef0435af28ccc1e93e13c6161e94585edSean Callanan  // information to see if the CFG is valid.
3098eac77d782851ae85f821fee8eb0070b5d84b53bSean Callanan  // FIXME: Inter-procedural analysis will need to handle invalid CFGs.
31013615cfef0435af28ccc1e93e13c6161e94585edSean Callanan  if (!mgr.getLiveVariables(D))
31113615cfef0435af28ccc1e93e13c6161e94585edSean Callanan    return;
31213615cfef0435af28ccc1e93e13c6161e94585edSean Callanan  ExprEngine Eng(mgr, ObjCGCEnabled);
31313615cfef0435af28ccc1e93e13c6161e94585edSean Callanan
31413615cfef0435af28ccc1e93e13c6161e94585edSean Callanan  // Set the graph auditor.
31513615cfef0435af28ccc1e93e13c6161e94585edSean Callanan  llvm::OwningPtr<ExplodedNode::Auditor> Auditor;
31613615cfef0435af28ccc1e93e13c6161e94585edSean Callanan  if (mgr.shouldVisualizeUbigraph()) {
31713615cfef0435af28ccc1e93e13c6161e94585edSean Callanan    Auditor.reset(CreateUbiViz());
31813615cfef0435af28ccc1e93e13c6161e94585edSean Callanan    ExplodedNode::SetAuditor(Auditor.get());
31913615cfef0435af28ccc1e93e13c6161e94585edSean Callanan  }
32013615cfef0435af28ccc1e93e13c6161e94585edSean Callanan
32113615cfef0435af28ccc1e93e13c6161e94585edSean Callanan  // Execute the worklist algorithm.
32213615cfef0435af28ccc1e93e13c6161e94585edSean Callanan  Eng.ExecuteWorkList(mgr.getStackFrame(D, 0), mgr.getMaxNodes());
32313615cfef0435af28ccc1e93e13c6161e94585edSean Callanan
32413615cfef0435af28ccc1e93e13c6161e94585edSean Callanan  // Release the auditor (if any) so that it doesn't monitor the graph
32513615cfef0435af28ccc1e93e13c6161e94585edSean Callanan  // created BugReporter.
32613615cfef0435af28ccc1e93e13c6161e94585edSean Callanan  ExplodedNode::SetAuditor(0);
32713615cfef0435af28ccc1e93e13c6161e94585edSean Callanan
32813615cfef0435af28ccc1e93e13c6161e94585edSean Callanan  // Visualize the exploded graph.
32913615cfef0435af28ccc1e93e13c6161e94585edSean Callanan  if (mgr.shouldVisualizeGraphviz())
33013615cfef0435af28ccc1e93e13c6161e94585edSean Callanan    Eng.ViewGraph(mgr.shouldTrimGraph());
33113615cfef0435af28ccc1e93e13c6161e94585edSean Callanan
33213615cfef0435af28ccc1e93e13c6161e94585edSean Callanan  // Display warnings.
33313615cfef0435af28ccc1e93e13c6161e94585edSean Callanan  Eng.getBugReporter().FlushReports();
33413615cfef0435af28ccc1e93e13c6161e94585edSean Callanan}
33513615cfef0435af28ccc1e93e13c6161e94585edSean Callanan
33613615cfef0435af28ccc1e93e13c6161e94585edSean Callananstatic void RunPathSensitiveChecks(AnalysisConsumer &C, AnalysisManager &mgr,
33713615cfef0435af28ccc1e93e13c6161e94585edSean Callanan                                   Decl *D) {
33813615cfef0435af28ccc1e93e13c6161e94585edSean Callanan
33913615cfef0435af28ccc1e93e13c6161e94585edSean Callanan  switch (mgr.getLangOptions().getGCMode()) {
34013615cfef0435af28ccc1e93e13c6161e94585edSean Callanan  default:
34113615cfef0435af28ccc1e93e13c6161e94585edSean Callanan    llvm_unreachable("Invalid GC mode.");
34213615cfef0435af28ccc1e93e13c6161e94585edSean Callanan  case LangOptions::NonGC:
34313615cfef0435af28ccc1e93e13c6161e94585edSean Callanan    ActionExprEngine(C, mgr, D, false);
34413615cfef0435af28ccc1e93e13c6161e94585edSean Callanan    break;
34513615cfef0435af28ccc1e93e13c6161e94585edSean Callanan
34613615cfef0435af28ccc1e93e13c6161e94585edSean Callanan  case LangOptions::GCOnly:
34713615cfef0435af28ccc1e93e13c6161e94585edSean Callanan    ActionExprEngine(C, mgr, D, true);
34813615cfef0435af28ccc1e93e13c6161e94585edSean Callanan    break;
34913615cfef0435af28ccc1e93e13c6161e94585edSean Callanan
35013615cfef0435af28ccc1e93e13c6161e94585edSean Callanan  case LangOptions::HybridGC:
35113615cfef0435af28ccc1e93e13c6161e94585edSean Callanan    ActionExprEngine(C, mgr, D, false);
35213615cfef0435af28ccc1e93e13c6161e94585edSean Callanan    ActionExprEngine(C, mgr, D, true);
35313615cfef0435af28ccc1e93e13c6161e94585edSean Callanan    break;
35413615cfef0435af28ccc1e93e13c6161e94585edSean Callanan  }
35513615cfef0435af28ccc1e93e13c6161e94585edSean Callanan}
35613615cfef0435af28ccc1e93e13c6161e94585edSean Callanan
35713615cfef0435af28ccc1e93e13c6161e94585edSean Callanan//===----------------------------------------------------------------------===//
35813615cfef0435af28ccc1e93e13c6161e94585edSean Callanan// AnalysisConsumer creation.
35913615cfef0435af28ccc1e93e13c6161e94585edSean Callanan//===----------------------------------------------------------------------===//
36013615cfef0435af28ccc1e93e13c6161e94585edSean Callanan
36113615cfef0435af28ccc1e93e13c6161e94585edSean CallananASTConsumer* ento::CreateAnalysisConsumer(const Preprocessor& pp,
36213615cfef0435af28ccc1e93e13c6161e94585edSean Callanan                                          const std::string& outDir,
36313615cfef0435af28ccc1e93e13c6161e94585edSean Callanan                                          const AnalyzerOptions& opts,
36413615cfef0435af28ccc1e93e13c6161e94585edSean Callanan                                          ArrayRef<std::string> plugins) {
36513615cfef0435af28ccc1e93e13c6161e94585edSean Callanan  // Disable the effects of '-Werror' when using the AnalysisConsumer.
36613615cfef0435af28ccc1e93e13c6161e94585edSean Callanan  pp.getDiagnostics().setWarningsAsErrors(false);
36713615cfef0435af28ccc1e93e13c6161e94585edSean Callanan
36813615cfef0435af28ccc1e93e13c6161e94585edSean Callanan  return new AnalysisConsumer(pp, outDir, opts, plugins);
36913615cfef0435af28ccc1e93e13c6161e94585edSean Callanan}
37013615cfef0435af28ccc1e93e13c6161e94585edSean Callanan
37113615cfef0435af28ccc1e93e13c6161e94585edSean Callanan//===----------------------------------------------------------------------===//
37213615cfef0435af28ccc1e93e13c6161e94585edSean Callanan// Ubigraph Visualization.  FIXME: Move to separate file.
37313615cfef0435af28ccc1e93e13c6161e94585edSean Callanan//===----------------------------------------------------------------------===//
37413615cfef0435af28ccc1e93e13c6161e94585edSean Callanan
37513615cfef0435af28ccc1e93e13c6161e94585edSean Callanannamespace {
37613615cfef0435af28ccc1e93e13c6161e94585edSean Callanan
37713615cfef0435af28ccc1e93e13c6161e94585edSean Callananclass UbigraphViz : public ExplodedNode::Auditor {
37813615cfef0435af28ccc1e93e13c6161e94585edSean Callanan  llvm::OwningPtr<raw_ostream> Out;
37913615cfef0435af28ccc1e93e13c6161e94585edSean Callanan  llvm::sys::Path Dir, Filename;
38013615cfef0435af28ccc1e93e13c6161e94585edSean Callanan  unsigned Cntr;
38113615cfef0435af28ccc1e93e13c6161e94585edSean Callanan
38213615cfef0435af28ccc1e93e13c6161e94585edSean Callanan  typedef llvm::DenseMap<void*,unsigned> VMap;
38313615cfef0435af28ccc1e93e13c6161e94585edSean Callanan  VMap M;
38413615cfef0435af28ccc1e93e13c6161e94585edSean Callanan
38513615cfef0435af28ccc1e93e13c6161e94585edSean Callananpublic:
38613615cfef0435af28ccc1e93e13c6161e94585edSean Callanan  UbigraphViz(raw_ostream *out, llvm::sys::Path& dir,
38713615cfef0435af28ccc1e93e13c6161e94585edSean Callanan              llvm::sys::Path& filename);
38813615cfef0435af28ccc1e93e13c6161e94585edSean Callanan
38913615cfef0435af28ccc1e93e13c6161e94585edSean Callanan  ~UbigraphViz();
39013615cfef0435af28ccc1e93e13c6161e94585edSean Callanan
39113615cfef0435af28ccc1e93e13c6161e94585edSean Callanan  virtual void AddEdge(ExplodedNode *Src, ExplodedNode *Dst);
39213615cfef0435af28ccc1e93e13c6161e94585edSean Callanan};
39313615cfef0435af28ccc1e93e13c6161e94585edSean Callanan
39413615cfef0435af28ccc1e93e13c6161e94585edSean Callanan} // end anonymous namespace
39513615cfef0435af28ccc1e93e13c6161e94585edSean Callanan
39613615cfef0435af28ccc1e93e13c6161e94585edSean Callananstatic ExplodedNode::Auditor* CreateUbiViz() {
39713615cfef0435af28ccc1e93e13c6161e94585edSean Callanan  std::string ErrMsg;
39813615cfef0435af28ccc1e93e13c6161e94585edSean Callanan
39913615cfef0435af28ccc1e93e13c6161e94585edSean Callanan  llvm::sys::Path Dir = llvm::sys::Path::GetTemporaryDirectory(&ErrMsg);
40013615cfef0435af28ccc1e93e13c6161e94585edSean Callanan  if (!ErrMsg.empty())
40113615cfef0435af28ccc1e93e13c6161e94585edSean Callanan    return 0;
40213615cfef0435af28ccc1e93e13c6161e94585edSean Callanan
40313615cfef0435af28ccc1e93e13c6161e94585edSean Callanan  llvm::sys::Path Filename = Dir;
40413615cfef0435af28ccc1e93e13c6161e94585edSean Callanan  Filename.appendComponent("llvm_ubi");
40513615cfef0435af28ccc1e93e13c6161e94585edSean Callanan  Filename.makeUnique(true,&ErrMsg);
40613615cfef0435af28ccc1e93e13c6161e94585edSean Callanan
40713615cfef0435af28ccc1e93e13c6161e94585edSean Callanan  if (!ErrMsg.empty())
40813615cfef0435af28ccc1e93e13c6161e94585edSean Callanan    return 0;
40913615cfef0435af28ccc1e93e13c6161e94585edSean Callanan
41013615cfef0435af28ccc1e93e13c6161e94585edSean Callanan  llvm::errs() << "Writing '" << Filename.str() << "'.\n";
41113615cfef0435af28ccc1e93e13c6161e94585edSean Callanan
41213615cfef0435af28ccc1e93e13c6161e94585edSean Callanan  llvm::OwningPtr<llvm::raw_fd_ostream> Stream;
41347dc457387b690c5e4df1c0c7dd8c4337b92e630Sean Callanan  Stream.reset(new llvm::raw_fd_ostream(Filename.c_str(), ErrMsg));
41447dc457387b690c5e4df1c0c7dd8c4337b92e630Sean Callanan
41547dc457387b690c5e4df1c0c7dd8c4337b92e630Sean Callanan  if (!ErrMsg.empty())
41647dc457387b690c5e4df1c0c7dd8c4337b92e630Sean Callanan    return 0;
41747dc457387b690c5e4df1c0c7dd8c4337b92e630Sean Callanan
41847dc457387b690c5e4df1c0c7dd8c4337b92e630Sean Callanan  return new UbigraphViz(Stream.take(), Dir, Filename);
41947dc457387b690c5e4df1c0c7dd8c4337b92e630Sean Callanan}
42047dc457387b690c5e4df1c0c7dd8c4337b92e630Sean Callanan
4214b3cef072258eb17bd387ca7c7be18b6451fe09aSean Callananvoid UbigraphViz::AddEdge(ExplodedNode *Src, ExplodedNode *Dst) {
4224b3cef072258eb17bd387ca7c7be18b6451fe09aSean Callanan
4234b3cef072258eb17bd387ca7c7be18b6451fe09aSean Callanan  assert (Src != Dst && "Self-edges are not allowed.");
4244b3cef072258eb17bd387ca7c7be18b6451fe09aSean Callanan
425b31911838a69b0c0fe63e89f4d12f6efcc09bffbSean Callanan  // Lookup the Src.  If it is a new node, it's a root.
4264b3cef072258eb17bd387ca7c7be18b6451fe09aSean Callanan  VMap::iterator SrcI= M.find(Src);
427583f15dfb8f680cee0c499bcd876c5eb3b173136Sean Callanan  unsigned SrcID;
428583f15dfb8f680cee0c499bcd876c5eb3b173136Sean Callanan
429583f15dfb8f680cee0c499bcd876c5eb3b173136Sean Callanan  if (SrcI == M.end()) {
430583f15dfb8f680cee0c499bcd876c5eb3b173136Sean Callanan    M[Src] = SrcID = Cntr++;
431583f15dfb8f680cee0c499bcd876c5eb3b173136Sean Callanan    *Out << "('vertex', " << SrcID << ", ('color','#00ff00'))\n";
43247dc457387b690c5e4df1c0c7dd8c4337b92e630Sean Callanan  }
43347dc457387b690c5e4df1c0c7dd8c4337b92e630Sean Callanan  else
43447dc457387b690c5e4df1c0c7dd8c4337b92e630Sean Callanan    SrcID = SrcI->second;
43547dc457387b690c5e4df1c0c7dd8c4337b92e630Sean Callanan
43647dc457387b690c5e4df1c0c7dd8c4337b92e630Sean Callanan  // Lookup the Dst.
43747dc457387b690c5e4df1c0c7dd8c4337b92e630Sean Callanan  VMap::iterator DstI= M.find(Dst);
43847dc457387b690c5e4df1c0c7dd8c4337b92e630Sean Callanan  unsigned DstID;
43947dc457387b690c5e4df1c0c7dd8c4337b92e630Sean Callanan
44047dc457387b690c5e4df1c0c7dd8c4337b92e630Sean Callanan  if (DstI == M.end()) {
44147dc457387b690c5e4df1c0c7dd8c4337b92e630Sean Callanan    M[Dst] = DstID = Cntr++;
442952e9dc874944fcdbbb224f3ec4fc2c859376f64Greg Clayton    *Out << "('vertex', " << DstID << ")\n";
4434b3cef072258eb17bd387ca7c7be18b6451fe09aSean Callanan  }
4444b3cef072258eb17bd387ca7c7be18b6451fe09aSean Callanan  else {
4454a379b1194f3e6b308cd6e80b45d6ca5dd0aafd7Greg Clayton    // We have hit DstID before.  Change its style to reflect a cache hit.
44647dc457387b690c5e4df1c0c7dd8c4337b92e630Sean Callanan    DstID = DstI->second;
4474b3cef072258eb17bd387ca7c7be18b6451fe09aSean Callanan    *Out << "('change_vertex_style', " << DstID << ", 1)\n";
4484b3cef072258eb17bd387ca7c7be18b6451fe09aSean Callanan  }
4494b3cef072258eb17bd387ca7c7be18b6451fe09aSean Callanan
4504b3cef072258eb17bd387ca7c7be18b6451fe09aSean Callanan  // Add the edge.
4514b3cef072258eb17bd387ca7c7be18b6451fe09aSean Callanan  *Out << "('edge', " << SrcID << ", " << DstID
4524b3cef072258eb17bd387ca7c7be18b6451fe09aSean Callanan       << ", ('arrow','true'), ('oriented', 'true'))\n";
4534b3cef072258eb17bd387ca7c7be18b6451fe09aSean Callanan}
4544b3cef072258eb17bd387ca7c7be18b6451fe09aSean Callanan
455583f15dfb8f680cee0c499bcd876c5eb3b173136Sean CallananUbigraphViz::UbigraphViz(raw_ostream *out, llvm::sys::Path& dir,
4564b3cef072258eb17bd387ca7c7be18b6451fe09aSean Callanan                         llvm::sys::Path& filename)
45752d0d027dd38518e4b0cfb135a5d50a6652c5dafSean Callanan  : Out(out), Dir(dir), Filename(filename), Cntr(0) {
4584b3cef072258eb17bd387ca7c7be18b6451fe09aSean Callanan
4594b3cef072258eb17bd387ca7c7be18b6451fe09aSean Callanan  *Out << "('vertex_style_attribute', 0, ('shape', 'icosahedron'))\n";
4604b3cef072258eb17bd387ca7c7be18b6451fe09aSean Callanan  *Out << "('vertex_style', 1, 0, ('shape', 'sphere'), ('color', '#ffcc66'),"
4614b3cef072258eb17bd387ca7c7be18b6451fe09aSean Callanan          " ('size', '1.5'))\n";
4624b3cef072258eb17bd387ca7c7be18b6451fe09aSean Callanan}
463fecc09c3709262515add87254cb973ce5175f17bSean Callanan
4644b3cef072258eb17bd387ca7c7be18b6451fe09aSean CallananUbigraphViz::~UbigraphViz() {
4654b3cef072258eb17bd387ca7c7be18b6451fe09aSean Callanan  Out.reset(0);
4664b3cef072258eb17bd387ca7c7be18b6451fe09aSean Callanan  llvm::errs() << "Running 'ubiviz' program... ";
4674b3cef072258eb17bd387ca7c7be18b6451fe09aSean Callanan  std::string ErrMsg;
4685aff015bfe8ef7ae68c61801e320870471b2c4dfSean Callanan  llvm::sys::Path Ubiviz = llvm::sys::Program::FindProgramByName("ubiviz");
4694b3cef072258eb17bd387ca7c7be18b6451fe09aSean Callanan  std::vector<const char*> args;
4705aff015bfe8ef7ae68c61801e320870471b2c4dfSean Callanan  args.push_back(Ubiviz.c_str());
4715aff015bfe8ef7ae68c61801e320870471b2c4dfSean Callanan  args.push_back(Filename.c_str());
4724b3cef072258eb17bd387ca7c7be18b6451fe09aSean Callanan  args.push_back(0);
47347dc457387b690c5e4df1c0c7dd8c4337b92e630Sean Callanan
47447dc457387b690c5e4df1c0c7dd8c4337b92e630Sean Callanan  if (llvm::sys::Program::ExecuteAndWait(Ubiviz, &args[0],0,0,0,0,&ErrMsg)) {
47547dc457387b690c5e4df1c0c7dd8c4337b92e630Sean Callanan    llvm::errs() << "Error viewing graph: " << ErrMsg << "\n";
47647dc457387b690c5e4df1c0c7dd8c4337b92e630Sean Callanan  }
47747dc457387b690c5e4df1c0c7dd8c4337b92e630Sean Callanan
478b31911838a69b0c0fe63e89f4d12f6efcc09bffbSean Callanan  // Delete the directory.
47913615cfef0435af28ccc1e93e13c6161e94585edSean Callanan  Dir.eraseFromDisk(true);
48013615cfef0435af28ccc1e93e13c6161e94585edSean Callanan}
48113615cfef0435af28ccc1e93e13c6161e94585edSean Callanan