AnalysisConsumer.cpp revision 9c378f705405d37f49795d5e915989de774fe11f
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
14e6348c336fecc8da9288ea367375a1b1cd2358d2Argyrios Kyrtzidis#include "AnalysisConsumer.h"
15f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek#include "clang/AST/ASTConsumer.h"
16f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek#include "clang/AST/Decl.h"
17802be99a6817aba6edb166b93c133da4358aa783Zhongxing Xu#include "clang/AST/DeclCXX.h"
18f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek#include "clang/AST/DeclObjC.h"
19efceabd2380f49306bc0229583458e93b062094bDaniel Dunbar#include "clang/AST/ParentMap.h"
20efceabd2380f49306bc0229583458e93b062094bDaniel Dunbar#include "clang/Analysis/CFG.h"
2127af04bcca46f8a3374586be1301477f9123f5e1Argyrios Kyrtzidis#include "clang/StaticAnalyzer/Frontend/CheckerRegistration.h"
2243dee220252ef0b42c5f8a3bb1eca97f84f2565fArgyrios Kyrtzidis#include "clang/StaticAnalyzer/Core/CheckerManager.h"
2321142581d55918beed544a757e4af3bb865b1812Ted Kremenek#include "clang/StaticAnalyzer/Checkers/LocalCheckers.h"
249b663716449b618ba0390b1dbebc54fa8e971124Ted Kremenek#include "clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h"
259b663716449b618ba0390b1dbebc54fa8e971124Ted Kremenek#include "clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h"
269b663716449b618ba0390b1dbebc54fa8e971124Ted Kremenek#include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h"
279b663716449b618ba0390b1dbebc54fa8e971124Ted Kremenek#include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
289b663716449b618ba0390b1dbebc54fa8e971124Ted Kremenek#include "clang/StaticAnalyzer/Core/PathSensitive/TransferFuncs.h"
299b663716449b618ba0390b1dbebc54fa8e971124Ted Kremenek#include "clang/StaticAnalyzer/Core/PathDiagnosticClients.h"
30a7af5ea88a6c5bdf87497cca6c20831e8c546751Argyrios Kyrtzidis
31efceabd2380f49306bc0229583458e93b062094bDaniel Dunbar#include "clang/Basic/FileManager.h"
32efceabd2380f49306bc0229583458e93b062094bDaniel Dunbar#include "clang/Basic/SourceManager.h"
339b414d3e2d0cb84512b55a3275a98490b090162aDaniel Dunbar#include "clang/Frontend/AnalyzerOptions.h"
34efceabd2380f49306bc0229583458e93b062094bDaniel Dunbar#include "clang/Lex/Preprocessor.h"
35f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek#include "llvm/Support/raw_ostream.h"
3603013fa9a0bf1ef4b907f5fec006c8f4000fdd21Michael J. Spencer#include "llvm/Support/Path.h"
3703013fa9a0bf1ef4b907f5fec006c8f4000fdd21Michael J. Spencer#include "llvm/Support/Program.h"
386cb7c1a43b0c8f739d1f54b7fdae5ede86033496Benjamin Kramer#include "llvm/ADT/OwningPtr.h"
39db09a4dee28a4515438af60f2d2b4a83e4965c31Ted Kremenek
40f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenekusing namespace clang;
419ef6537a894c33003359b1f9b9676e9178e028b7Ted Kremenekusing namespace ento;
42f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek
43c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xustatic ExplodedNode::Auditor* CreateUbiViz();
44ff944a8c481d6c0f1ad2633e4be9bf8b1dd2a09fZhongxing Xu
45be1fe1eb12a1cb91c8e3a9fcc2db4dfe989def6cTed Kremenek//===----------------------------------------------------------------------===//
46f75560670bcdd59b051149bdece3eac14e313853Ted Kremenek// Special PathDiagnosticClients.
47f75560670bcdd59b051149bdece3eac14e313853Ted Kremenek//===----------------------------------------------------------------------===//
48f75560670bcdd59b051149bdece3eac14e313853Ted Kremenek
49f75560670bcdd59b051149bdece3eac14e313853Ted Kremenekstatic PathDiagnosticClient*
50f928dca56542cf8f981a684f090d2c79bdcb2a10Argyrios KyrtzidiscreatePlistHTMLDiagnosticClient(const std::string& prefix,
51efceabd2380f49306bc0229583458e93b062094bDaniel Dunbar                                const Preprocessor &PP) {
52d5b08bee799d4f77f1a25fa5977ca77b983ab031Michael J. Spencer  PathDiagnosticClient *PD =
53d5b08bee799d4f77f1a25fa5977ca77b983ab031Michael J. Spencer    createHTMLDiagnosticClient(llvm::sys::path::parent_path(prefix), PP);
54f928dca56542cf8f981a684f090d2c79bdcb2a10Argyrios Kyrtzidis  return createPlistDiagnosticClient(prefix, PP, PD);
55f75560670bcdd59b051149bdece3eac14e313853Ted Kremenek}
56f75560670bcdd59b051149bdece3eac14e313853Ted Kremenek
57f75560670bcdd59b051149bdece3eac14e313853Ted Kremenek//===----------------------------------------------------------------------===//
58f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek// AnalysisConsumer declaration.
59f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek//===----------------------------------------------------------------------===//
60f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek
61f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremeneknamespace {
62f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek
63ed8afacb8118b71bcfa8017059e51da325e7691bZhongxing Xuclass AnalysisConsumer : public ASTConsumer {
64ed8afacb8118b71bcfa8017059e51da325e7691bZhongxing Xupublic:
659c378f705405d37f49795d5e915989de774fe11fTed Kremenek  ASTContext *Ctx;
661d9cbeb76cf4c36acf5545028e2b2ac207086442Ted Kremenek  const Preprocessor &PP;
671d9cbeb76cf4c36acf5545028e2b2ac207086442Ted Kremenek  const std::string OutDir;
681d9cbeb76cf4c36acf5545028e2b2ac207086442Ted Kremenek  AnalyzerOptions Opts;
69d07a0d0279c09d1017f8450fce575a94dc9703c0Zhongxing Xu
701d9cbeb76cf4c36acf5545028e2b2ac207086442Ted Kremenek  // PD is owned by AnalysisManager.
711d9cbeb76cf4c36acf5545028e2b2ac207086442Ted Kremenek  PathDiagnosticClient *PD;
72d07a0d0279c09d1017f8450fce575a94dc9703c0Zhongxing Xu
731d9cbeb76cf4c36acf5545028e2b2ac207086442Ted Kremenek  StoreManagerCreator CreateStoreMgr;
741d9cbeb76cf4c36acf5545028e2b2ac207086442Ted Kremenek  ConstraintManagerCreator CreateConstraintMgr;
75f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek
7643dee220252ef0b42c5f8a3bb1eca97f84f2565fArgyrios Kyrtzidis  llvm::OwningPtr<CheckerManager> checkerMgr;
771d9cbeb76cf4c36acf5545028e2b2ac207086442Ted Kremenek  llvm::OwningPtr<AnalysisManager> Mgr;
78c471e7b44e63ff1b46b480e723c4130aeaef5a8aZhongxing Xu
791d9cbeb76cf4c36acf5545028e2b2ac207086442Ted Kremenek  AnalysisConsumer(const Preprocessor& pp,
801d9cbeb76cf4c36acf5545028e2b2ac207086442Ted Kremenek                   const std::string& outdir,
811d9cbeb76cf4c36acf5545028e2b2ac207086442Ted Kremenek                   const AnalyzerOptions& opts)
821d9cbeb76cf4c36acf5545028e2b2ac207086442Ted Kremenek    : Ctx(0), PP(pp), OutDir(outdir),
83c4a1437c15da43eb8d2601cdce13161ef41a4389Ted Kremenek      Opts(opts), PD(0) {
841d9cbeb76cf4c36acf5545028e2b2ac207086442Ted Kremenek    DigestAnalyzerOptions();
851d9cbeb76cf4c36acf5545028e2b2ac207086442Ted Kremenek  }
86fda7832b000ff8927386f093b52c067641679469Zhongxing Xu
871d9cbeb76cf4c36acf5545028e2b2ac207086442Ted Kremenek  void DigestAnalyzerOptions() {
881d9cbeb76cf4c36acf5545028e2b2ac207086442Ted Kremenek    // Create the PathDiagnosticClient.
891d9cbeb76cf4c36acf5545028e2b2ac207086442Ted Kremenek    if (!OutDir.empty()) {
901d9cbeb76cf4c36acf5545028e2b2ac207086442Ted Kremenek      switch (Opts.AnalysisDiagOpt) {
911d9cbeb76cf4c36acf5545028e2b2ac207086442Ted Kremenek      default:
92fda7832b000ff8927386f093b52c067641679469Zhongxing Xu#define ANALYSIS_DIAGNOSTICS(NAME, CMDFLAG, DESC, CREATEFN, AUTOCREATE) \
931d9cbeb76cf4c36acf5545028e2b2ac207086442Ted Kremenek        case PD_##NAME: PD = CREATEFN(OutDir, PP); break;
94fda7832b000ff8927386f093b52c067641679469Zhongxing Xu#include "clang/Frontend/Analyses.def"
95fda7832b000ff8927386f093b52c067641679469Zhongxing Xu      }
96a599ae8826b01c0160a519b0fc5a4871f599bf04Argyrios Kyrtzidis    } else if (Opts.AnalysisDiagOpt == PD_TEXT) {
97a599ae8826b01c0160a519b0fc5a4871f599bf04Argyrios Kyrtzidis      // Create the text client even without a specified output file since
98a599ae8826b01c0160a519b0fc5a4871f599bf04Argyrios Kyrtzidis      // it just uses diagnostic notes.
99a599ae8826b01c0160a519b0fc5a4871f599bf04Argyrios Kyrtzidis      PD = createTextPathDiagnosticClient("", PP);
1001d9cbeb76cf4c36acf5545028e2b2ac207086442Ted Kremenek    }
101fda7832b000ff8927386f093b52c067641679469Zhongxing Xu
1021d9cbeb76cf4c36acf5545028e2b2ac207086442Ted Kremenek    // Create the analyzer component creators.
1035f83d6f36a7308eef21d87104fd70c421e854448Argyrios Kyrtzidis    switch (Opts.AnalysisStoreOpt) {
1045f83d6f36a7308eef21d87104fd70c421e854448Argyrios Kyrtzidis    default:
1055f83d6f36a7308eef21d87104fd70c421e854448Argyrios Kyrtzidis      assert(0 && "Unknown store manager.");
106fda7832b000ff8927386f093b52c067641679469Zhongxing Xu#define ANALYSIS_STORE(NAME, CMDFLAG, DESC, CREATEFN)           \
1075f83d6f36a7308eef21d87104fd70c421e854448Argyrios Kyrtzidis      case NAME##Model: CreateStoreMgr = CREATEFN; break;
108fda7832b000ff8927386f093b52c067641679469Zhongxing Xu#include "clang/Frontend/Analyses.def"
1091d9cbeb76cf4c36acf5545028e2b2ac207086442Ted Kremenek    }
1101eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
1115f83d6f36a7308eef21d87104fd70c421e854448Argyrios Kyrtzidis    switch (Opts.AnalysisConstraintsOpt) {
1125f83d6f36a7308eef21d87104fd70c421e854448Argyrios Kyrtzidis    default:
1135f83d6f36a7308eef21d87104fd70c421e854448Argyrios Kyrtzidis      assert(0 && "Unknown store manager.");
114fda7832b000ff8927386f093b52c067641679469Zhongxing Xu#define ANALYSIS_CONSTRAINTS(NAME, CMDFLAG, DESC, CREATEFN)     \
1155f83d6f36a7308eef21d87104fd70c421e854448Argyrios Kyrtzidis      case NAME##Model: CreateConstraintMgr = CREATEFN; break;
116fda7832b000ff8927386f093b52c067641679469Zhongxing Xu#include "clang/Frontend/Analyses.def"
117fda7832b000ff8927386f093b52c067641679469Zhongxing Xu    }
1181d9cbeb76cf4c36acf5545028e2b2ac207086442Ted Kremenek  }
119f6eafcca7734274d277afa121f2c4fb025a54218Ted Kremenek
1201d9cbeb76cf4c36acf5545028e2b2ac207086442Ted Kremenek  void DisplayFunction(const Decl *D) {
121c4a1437c15da43eb8d2601cdce13161ef41a4389Ted Kremenek    if (!Opts.AnalyzerDisplayProgress)
1221d9cbeb76cf4c36acf5545028e2b2ac207086442Ted Kremenek      return;
123f6eafcca7734274d277afa121f2c4fb025a54218Ted Kremenek
124fc576514d06c46a7cac49500169411d82f38d04bTed Kremenek    SourceManager &SM = Mgr->getASTContext().getSourceManager();
125fc576514d06c46a7cac49500169411d82f38d04bTed Kremenek    PresumedLoc Loc = SM.getPresumedLoc(D->getLocation());
126cb7b1e17b63967317ab5cc55682168cf0380519aDouglas Gregor    if (Loc.isValid()) {
127cb7b1e17b63967317ab5cc55682168cf0380519aDouglas Gregor      llvm::errs() << "ANALYZE: " << Loc.getFilename();
128fc576514d06c46a7cac49500169411d82f38d04bTed Kremenek
129cb7b1e17b63967317ab5cc55682168cf0380519aDouglas Gregor      if (isa<FunctionDecl>(D) || isa<ObjCMethodDecl>(D)) {
130cb7b1e17b63967317ab5cc55682168cf0380519aDouglas Gregor        const NamedDecl *ND = cast<NamedDecl>(D);
131cb7b1e17b63967317ab5cc55682168cf0380519aDouglas Gregor        llvm::errs() << ' ' << ND << '\n';
132cb7b1e17b63967317ab5cc55682168cf0380519aDouglas Gregor      }
133cb7b1e17b63967317ab5cc55682168cf0380519aDouglas Gregor      else if (isa<BlockDecl>(D)) {
134cb7b1e17b63967317ab5cc55682168cf0380519aDouglas Gregor        llvm::errs() << ' ' << "block(line:" << Loc.getLine() << ",col:"
135cb7b1e17b63967317ab5cc55682168cf0380519aDouglas Gregor                     << Loc.getColumn() << '\n';
136cb7b1e17b63967317ab5cc55682168cf0380519aDouglas Gregor      }
137cb7b1e17b63967317ab5cc55682168cf0380519aDouglas Gregor      else if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D)) {
138cb7b1e17b63967317ab5cc55682168cf0380519aDouglas Gregor        Selector S = MD->getSelector();
139cb7b1e17b63967317ab5cc55682168cf0380519aDouglas Gregor        llvm::errs() << ' ' << S.getAsString();
140cb7b1e17b63967317ab5cc55682168cf0380519aDouglas Gregor      }
14135fa76d0bb6fb8c86159a7506efd094a4fe376d2Ted Kremenek    }
1421d9cbeb76cf4c36acf5545028e2b2ac207086442Ted Kremenek  }
1431eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
1441d9cbeb76cf4c36acf5545028e2b2ac207086442Ted Kremenek  virtual void Initialize(ASTContext &Context) {
1451d9cbeb76cf4c36acf5545028e2b2ac207086442Ted Kremenek    Ctx = &Context;
1462e471a3e476396be1ddca4ab8b9df721bcfc9437Argyrios Kyrtzidis    checkerMgr.reset(registerCheckers(Opts, PP.getLangOptions(),
1472e471a3e476396be1ddca4ab8b9df721bcfc9437Argyrios Kyrtzidis                                      PP.getDiagnostics()));
1481d9cbeb76cf4c36acf5545028e2b2ac207086442Ted Kremenek    Mgr.reset(new AnalysisManager(*Ctx, PP.getDiagnostics(),
1491d9cbeb76cf4c36acf5545028e2b2ac207086442Ted Kremenek                                  PP.getLangOptions(), PD,
1501d9cbeb76cf4c36acf5545028e2b2ac207086442Ted Kremenek                                  CreateStoreMgr, CreateConstraintMgr,
15143dee220252ef0b42c5f8a3bb1eca97f84f2565fArgyrios Kyrtzidis                                  checkerMgr.get(),
152c6238d2786cfd961b94580b3d3675a1b3ff0721cZhongxing Xu                                  /* Indexer */ 0,
1536362b893731ccf4480a96527db9e55e04b801503Zhongxing Xu                                  Opts.MaxNodes, Opts.MaxLoop,
1541d9cbeb76cf4c36acf5545028e2b2ac207086442Ted Kremenek                                  Opts.VisualizeEGDot, Opts.VisualizeEGUbi,
1551d9cbeb76cf4c36acf5545028e2b2ac207086442Ted Kremenek                                  Opts.PurgeDead, Opts.EagerlyAssume,
1569b823e8e1ccb8a2cb49923bad22a80ca96f41f92Ted Kremenek                                  Opts.TrimGraph, Opts.InlineCall,
1579121ba232903ebe61e7bbe14ca294cf0f07dfa96Marcin Swiderski                                  Opts.UnoptimizedCFG, Opts.CFGAddImplicitDtors,
158d767d81290288c030f3be0be1d3e62b9c8df51dcTed Kremenek                                  Opts.CFGAddInitializers,
159d767d81290288c030f3be0be1d3e62b9c8df51dcTed Kremenek                                  Opts.EagerlyTrimEGraph));
1601d9cbeb76cf4c36acf5545028e2b2ac207086442Ted Kremenek  }
1611eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
1621d9cbeb76cf4c36acf5545028e2b2ac207086442Ted Kremenek  virtual void HandleTranslationUnit(ASTContext &C);
16314cc9451de4a9539bf79e4e5d63248c2377426dbTed Kremenek  void HandleDeclContext(ASTContext &C, DeclContext *dc);
16414cc9451de4a9539bf79e4e5d63248c2377426dbTed Kremenek
165c367a876d0abcf32cb443712ce2709a0491be00bArgyrios Kyrtzidis  void HandleCode(Decl *D);
1661d9cbeb76cf4c36acf5545028e2b2ac207086442Ted Kremenek};
167f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek} // end anonymous namespace
168f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek
169f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek//===----------------------------------------------------------------------===//
170f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek// AnalysisConsumer implementation.
171f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek//===----------------------------------------------------------------------===//
172f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek
17314cc9451de4a9539bf79e4e5d63248c2377426dbTed Kremenekvoid AnalysisConsumer::HandleDeclContext(ASTContext &C, DeclContext *dc) {
1749fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis  BugReporter BR(*Mgr);
17514cc9451de4a9539bf79e4e5d63248c2377426dbTed Kremenek  for (DeclContext::decl_iterator I = dc->decls_begin(), E = dc->decls_end();
176ed8afacb8118b71bcfa8017059e51da325e7691bZhongxing Xu       I != E; ++I) {
177ed8afacb8118b71bcfa8017059e51da325e7691bZhongxing Xu    Decl *D = *I;
1789fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis    checkerMgr->runCheckersOnASTDecl(D, *Mgr, BR);
1799fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis
180ed8afacb8118b71bcfa8017059e51da325e7691bZhongxing Xu    switch (D->getKind()) {
18114cc9451de4a9539bf79e4e5d63248c2377426dbTed Kremenek      case Decl::Namespace: {
18214cc9451de4a9539bf79e4e5d63248c2377426dbTed Kremenek        HandleDeclContext(C, cast<NamespaceDecl>(D));
18314cc9451de4a9539bf79e4e5d63248c2377426dbTed Kremenek        break;
184ed8afacb8118b71bcfa8017059e51da325e7691bZhongxing Xu      }
18514cc9451de4a9539bf79e4e5d63248c2377426dbTed Kremenek      case Decl::CXXConstructor:
18614cc9451de4a9539bf79e4e5d63248c2377426dbTed Kremenek      case Decl::CXXDestructor:
18714cc9451de4a9539bf79e4e5d63248c2377426dbTed Kremenek      case Decl::CXXConversion:
18814cc9451de4a9539bf79e4e5d63248c2377426dbTed Kremenek      case Decl::CXXMethod:
18914cc9451de4a9539bf79e4e5d63248c2377426dbTed Kremenek      case Decl::Function: {
1909c378f705405d37f49795d5e915989de774fe11fTed Kremenek        FunctionDecl *FD = cast<FunctionDecl>(D);
19114cc9451de4a9539bf79e4e5d63248c2377426dbTed Kremenek        // We skip function template definitions, as their semantics is
19214cc9451de4a9539bf79e4e5d63248c2377426dbTed Kremenek        // only determined when they are instantiated.
19314cc9451de4a9539bf79e4e5d63248c2377426dbTed Kremenek        if (FD->isThisDeclarationADefinition() &&
19414cc9451de4a9539bf79e4e5d63248c2377426dbTed Kremenek            !FD->isDependentContext()) {
195ed8afacb8118b71bcfa8017059e51da325e7691bZhongxing Xu          if (!Opts.AnalyzeSpecificFunction.empty() &&
19614cc9451de4a9539bf79e4e5d63248c2377426dbTed Kremenek              FD->getDeclName().getAsString() != Opts.AnalyzeSpecificFunction)
197ed8afacb8118b71bcfa8017059e51da325e7691bZhongxing Xu            break;
19814cc9451de4a9539bf79e4e5d63248c2377426dbTed Kremenek          DisplayFunction(FD);
199c367a876d0abcf32cb443712ce2709a0491be00bArgyrios Kyrtzidis          HandleCode(FD);
200ed8afacb8118b71bcfa8017059e51da325e7691bZhongxing Xu        }
20114cc9451de4a9539bf79e4e5d63248c2377426dbTed Kremenek        break;
202ed8afacb8118b71bcfa8017059e51da325e7691bZhongxing Xu      }
2036e744db7c294f357e7e0af628275331f3a6c1b6bTed Kremenek
2046e744db7c294f357e7e0af628275331f3a6c1b6bTed Kremenek      case Decl::ObjCCategoryImpl:
20514cc9451de4a9539bf79e4e5d63248c2377426dbTed Kremenek      case Decl::ObjCImplementation: {
2069c378f705405d37f49795d5e915989de774fe11fTed Kremenek        ObjCImplDecl *ID = cast<ObjCImplDecl>(*I);
207c367a876d0abcf32cb443712ce2709a0491be00bArgyrios Kyrtzidis        HandleCode(ID);
20814cc9451de4a9539bf79e4e5d63248c2377426dbTed Kremenek
2096e744db7c294f357e7e0af628275331f3a6c1b6bTed Kremenek        for (ObjCContainerDecl::method_iterator MI = ID->meth_begin(),
21014cc9451de4a9539bf79e4e5d63248c2377426dbTed Kremenek             ME = ID->meth_end(); MI != ME; ++MI) {
211b742dfde440c8bb0f7e655715e9413fa69f0fefdArgyrios Kyrtzidis          checkerMgr->runCheckersOnASTDecl(*MI, *Mgr, BR);
212b742dfde440c8bb0f7e655715e9413fa69f0fefdArgyrios Kyrtzidis
21314cc9451de4a9539bf79e4e5d63248c2377426dbTed Kremenek          if ((*MI)->isThisDeclarationADefinition()) {
21414cc9451de4a9539bf79e4e5d63248c2377426dbTed Kremenek            if (!Opts.AnalyzeSpecificFunction.empty() &&
2156e744db7c294f357e7e0af628275331f3a6c1b6bTed Kremenek                Opts.AnalyzeSpecificFunction !=
2166e744db7c294f357e7e0af628275331f3a6c1b6bTed Kremenek                  (*MI)->getSelector().getAsString())
21714cc9451de4a9539bf79e4e5d63248c2377426dbTed Kremenek              break;
21814cc9451de4a9539bf79e4e5d63248c2377426dbTed Kremenek            DisplayFunction(*MI);
219c367a876d0abcf32cb443712ce2709a0491be00bArgyrios Kyrtzidis            HandleCode(*MI);
22014cc9451de4a9539bf79e4e5d63248c2377426dbTed Kremenek          }
22114cc9451de4a9539bf79e4e5d63248c2377426dbTed Kremenek        }
22214cc9451de4a9539bf79e4e5d63248c2377426dbTed Kremenek        break;
22314cc9451de4a9539bf79e4e5d63248c2377426dbTed Kremenek      }
22414cc9451de4a9539bf79e4e5d63248c2377426dbTed Kremenek
22514cc9451de4a9539bf79e4e5d63248c2377426dbTed Kremenek      default:
22614cc9451de4a9539bf79e4e5d63248c2377426dbTed Kremenek        break;
227ed8afacb8118b71bcfa8017059e51da325e7691bZhongxing Xu    }
22814cc9451de4a9539bf79e4e5d63248c2377426dbTed Kremenek  }
22914cc9451de4a9539bf79e4e5d63248c2377426dbTed Kremenek}
230f6eafcca7734274d277afa121f2c4fb025a54218Ted Kremenek
23114cc9451de4a9539bf79e4e5d63248c2377426dbTed Kremenekvoid AnalysisConsumer::HandleTranslationUnit(ASTContext &C) {
2329fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis  BugReporter BR(*Mgr);
23314cc9451de4a9539bf79e4e5d63248c2377426dbTed Kremenek  TranslationUnitDecl *TU = C.getTranslationUnitDecl();
2349fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis  checkerMgr->runCheckersOnASTDecl(TU, *Mgr, BR);
23514cc9451de4a9539bf79e4e5d63248c2377426dbTed Kremenek  HandleDeclContext(C, TU);
236b317f8f5ca8737a5bbad97a3f7566a2dbd2ed61bZhongxing Xu
2379be6e7ce5788e50c62d40c59b0bbc2ea423683f7Ted Kremenek  // After all decls handled, run checkers on the entire TranslationUnit.
2389be6e7ce5788e50c62d40c59b0bbc2ea423683f7Ted Kremenek  checkerMgr->runCheckersOnEndOfTranslationUnit(TU, *Mgr, BR);
2399be6e7ce5788e50c62d40c59b0bbc2ea423683f7Ted Kremenek
240690a7f431d6863a101711e67636d51ddd13f35c5Ted Kremenek  // Explicitly destroy the PathDiagnosticClient.  This will flush its output.
241690a7f431d6863a101711e67636d51ddd13f35c5Ted Kremenek  // FIXME: This should be replaced with something that doesn't rely on
242da17fd50ad485fd2a1fc5c2f055caacf532992daZhongxing Xu  // side-effects in PathDiagnosticClient's destructor. This is required when
243da17fd50ad485fd2a1fc5c2f055caacf532992daZhongxing Xu  // used with option -disable-free.
244d07a0d0279c09d1017f8450fce575a94dc9703c0Zhongxing Xu  Mgr.reset(NULL);
245db09a4dee28a4515438af60f2d2b4a83e4965c31Ted Kremenek}
246db09a4dee28a4515438af60f2d2b4a83e4965c31Ted Kremenek
2475f9e272e632e951b1efe824cd16acb4d96077930Chris Lattnerstatic void FindBlocks(DeclContext *D, SmallVectorImpl<Decl*> &WL) {
248fc576514d06c46a7cac49500169411d82f38d04bTed Kremenek  if (BlockDecl *BD = dyn_cast<BlockDecl>(D))
249fc576514d06c46a7cac49500169411d82f38d04bTed Kremenek    WL.push_back(BD);
250f6eafcca7734274d277afa121f2c4fb025a54218Ted Kremenek
251fc576514d06c46a7cac49500169411d82f38d04bTed Kremenek  for (DeclContext::decl_iterator I = D->decls_begin(), E = D->decls_end();
252fc576514d06c46a7cac49500169411d82f38d04bTed Kremenek       I!=E; ++I)
253fc576514d06c46a7cac49500169411d82f38d04bTed Kremenek    if (DeclContext *DC = dyn_cast<DeclContext>(*I))
254fc576514d06c46a7cac49500169411d82f38d04bTed Kremenek      FindBlocks(DC, WL);
255fc576514d06c46a7cac49500169411d82f38d04bTed Kremenek}
256fc576514d06c46a7cac49500169411d82f38d04bTed Kremenek
257d655ab28fdf7c940d3f79f8f287954d7f76e0977Argyrios Kyrtzidisstatic void ActionObjCMemChecker(AnalysisConsumer &C, AnalysisManager& mgr,
258d655ab28fdf7c940d3f79f8f287954d7f76e0977Argyrios Kyrtzidis                                 Decl *D);
259d655ab28fdf7c940d3f79f8f287954d7f76e0977Argyrios Kyrtzidis
260c367a876d0abcf32cb443712ce2709a0491be00bArgyrios Kyrtzidisvoid AnalysisConsumer::HandleCode(Decl *D) {
2611eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
262fc8f0e14ad142ed811e90fbd9a30e419e301c717Chris Lattner  // Don't run the actions if an error has occurred with parsing the file.
26399e8192c4c8f1f596f9969e5f2cdafcee64ddaacTed Kremenek  Diagnostic &Diags = PP.getDiagnostics();
26499e8192c4c8f1f596f9969e5f2cdafcee64ddaacTed Kremenek  if (Diags.hasErrorOccurred() || Diags.hasFatalErrorOccurred())
265f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek    return;
26681922f01352aceeb923c0c3cc8c96b6527322384Ted Kremenek
267f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek  // Don't run the actions on declarations in header files unless
268f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek  // otherwise specified.
269fcd783d583d270b7ec1ec3e0fcf83cd93d30e381Ted Kremenek  SourceManager &SM = Ctx->getSourceManager();
270402785357ab053dd53f4fdd858b9630a5e0f8badChandler Carruth  SourceLocation SL = SM.getExpansionLoc(D->getLocation());
271fcd783d583d270b7ec1ec3e0fcf83cd93d30e381Ted Kremenek  if (!Opts.AnalyzeAll && !SM.isFromMainFile(SL))
2721eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump    return;
273f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek
27458f5ec7d56b1ebf5f90ee11226ebe7663f2821eaTed Kremenek  // Clear the AnalysisManager of old AnalysisContexts.
27558f5ec7d56b1ebf5f90ee11226ebe7663f2821eaTed Kremenek  Mgr->ClearContexts();
276f6eafcca7734274d277afa121f2c4fb025a54218Ted Kremenek
2771eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  // Dispatch on the actions.
2785f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner  SmallVector<Decl*, 10> WL;
279fc576514d06c46a7cac49500169411d82f38d04bTed Kremenek  WL.push_back(D);
280f6eafcca7734274d277afa121f2c4fb025a54218Ted Kremenek
28106a54a38be5054c910ffc92db60edab23f9ea105Argyrios Kyrtzidis  if (D->hasBody() && Opts.AnalyzeNestedBlocks)
282fc576514d06c46a7cac49500169411d82f38d04bTed Kremenek    FindBlocks(cast<DeclContext>(D), WL);
283f6eafcca7734274d277afa121f2c4fb025a54218Ted Kremenek
2849fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis  BugReporter BR(*Mgr);
2855f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner  for (SmallVectorImpl<Decl*>::iterator WI=WL.begin(), WE=WL.end();
2869fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis       WI != WE; ++WI)
287d655ab28fdf7c940d3f79f8f287954d7f76e0977Argyrios Kyrtzidis    if ((*WI)->hasBody()) {
2889fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis      checkerMgr->runCheckersOnASTBody(*WI, *Mgr, BR);
289d655ab28fdf7c940d3f79f8f287954d7f76e0977Argyrios Kyrtzidis      if (checkerMgr->hasPathSensitiveCheckers())
290d655ab28fdf7c940d3f79f8f287954d7f76e0977Argyrios Kyrtzidis        ActionObjCMemChecker(*this, *Mgr, *WI);
291d655ab28fdf7c940d3f79f8f287954d7f76e0977Argyrios Kyrtzidis    }
292f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek}
293f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek
294f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek//===----------------------------------------------------------------------===//
295d655ab28fdf7c940d3f79f8f287954d7f76e0977Argyrios Kyrtzidis// Path-sensitive checking.
296f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek//===----------------------------------------------------------------------===//
297f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek
298d2592a34a059e7cbb2b11dc53649ac4912422909Argyrios Kyrtzidisstatic void ActionExprEngine(AnalysisConsumer &C, AnalysisManager& mgr,
299f6eafcca7734274d277afa121f2c4fb025a54218Ted Kremenek                               Decl *D,
300d2592a34a059e7cbb2b11dc53649ac4912422909Argyrios Kyrtzidis                               TransferFuncs* tf) {
3011eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
302d2592a34a059e7cbb2b11dc53649ac4912422909Argyrios Kyrtzidis  llvm::OwningPtr<TransferFuncs> TF(tf);
3037032f460fc9828f386056e75933da5af61e88638Ted Kremenek
30475d03cffe20b5c945ef04eba208efb0437339997Ted Kremenek  // Construct the analysis engine.  We first query for the LiveVariables
30575d03cffe20b5c945ef04eba208efb0437339997Ted Kremenek  // information to see if the CFG is valid.
30675d03cffe20b5c945ef04eba208efb0437339997Ted Kremenek  // FIXME: Inter-procedural analysis will need to handle invalid CFGs.
30775d03cffe20b5c945ef04eba208efb0437339997Ted Kremenek  if (!mgr.getLiveVariables(D))
308f6eafcca7734274d277afa121f2c4fb025a54218Ted Kremenek    return;
309d2592a34a059e7cbb2b11dc53649ac4912422909Argyrios Kyrtzidis  ExprEngine Eng(mgr, TF.take());
310f6eafcca7734274d277afa121f2c4fb025a54218Ted Kremenek
311f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek  // Set the graph auditor.
312c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu  llvm::OwningPtr<ExplodedNode::Auditor> Auditor;
313f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek  if (mgr.shouldVisualizeUbigraph()) {
314f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek    Auditor.reset(CreateUbiViz());
315c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu    ExplodedNode::SetAuditor(Auditor.get());
316f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek  }
3171eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
318b35a74a40c1d2656a25e560e773ed48bdf49f9c0Ted Kremenek  // Execute the worklist algorithm.
319c6238d2786cfd961b94580b3d3675a1b3ff0721cZhongxing Xu  Eng.ExecuteWorkList(mgr.getStackFrame(D, 0), mgr.getMaxNodes());
3201eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
321f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek  // Release the auditor (if any) so that it doesn't monitor the graph
322f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek  // created BugReporter.
323c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu  ExplodedNode::SetAuditor(0);
3243df6421150271266b5a90fd4c6bfa6566c38c036Ted Kremenek
32534d7734b6ed1d9c0f647405e065251eb67f42badTed Kremenek  // Visualize the exploded graph.
326f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek  if (mgr.shouldVisualizeGraphviz())
32734d7734b6ed1d9c0f647405e065251eb67f42badTed Kremenek    Eng.ViewGraph(mgr.shouldTrimGraph());
3281eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
3293df6421150271266b5a90fd4c6bfa6566c38c036Ted Kremenek  // Display warnings.
3303df6421150271266b5a90fd4c6bfa6566c38c036Ted Kremenek  Eng.getBugReporter().FlushReports();
331bc46f345838b1c0d420dbd3655c94f5f360fb5b8Ted Kremenek}
332bc46f345838b1c0d420dbd3655c94f5f360fb5b8Ted Kremenek
333565e465c6d0093f1bf8414b2cabdc842022385a9Ted Kremenekstatic void ActionObjCMemCheckerAux(AnalysisConsumer &C, AnalysisManager& mgr,
3341d9cbeb76cf4c36acf5545028e2b2ac207086442Ted Kremenek                                  Decl *D, bool GCEnabled) {
3351eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
336d2592a34a059e7cbb2b11dc53649ac4912422909Argyrios Kyrtzidis  TransferFuncs* TF = MakeCFRefCountTF(mgr.getASTContext(),
337bc46f345838b1c0d420dbd3655c94f5f360fb5b8Ted Kremenek                                         GCEnabled,
338bc46f345838b1c0d420dbd3655c94f5f360fb5b8Ted Kremenek                                         mgr.getLangOptions());
3391eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
340d2592a34a059e7cbb2b11dc53649ac4912422909Argyrios Kyrtzidis  ActionExprEngine(C, mgr, D, TF);
341b35a74a40c1d2656a25e560e773ed48bdf49f9c0Ted Kremenek}
342b35a74a40c1d2656a25e560e773ed48bdf49f9c0Ted Kremenek
343565e465c6d0093f1bf8414b2cabdc842022385a9Ted Kremenekstatic void ActionObjCMemChecker(AnalysisConsumer &C, AnalysisManager& mgr,
3441d9cbeb76cf4c36acf5545028e2b2ac207086442Ted Kremenek                               Decl *D) {
3451eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
346b35a74a40c1d2656a25e560e773ed48bdf49f9c0Ted Kremenek switch (mgr.getLangOptions().getGCMode()) {
347b7166334d897e1e4e6a5b428fe2d0ec752ef187fMike Stump default:
348b7166334d897e1e4e6a5b428fe2d0ec752ef187fMike Stump   assert (false && "Invalid GC mode.");
349b7166334d897e1e4e6a5b428fe2d0ec752ef187fMike Stump case LangOptions::NonGC:
350565e465c6d0093f1bf8414b2cabdc842022385a9Ted Kremenek   ActionObjCMemCheckerAux(C, mgr, D, false);
351b7166334d897e1e4e6a5b428fe2d0ec752ef187fMike Stump   break;
352b7166334d897e1e4e6a5b428fe2d0ec752ef187fMike Stump
353b7166334d897e1e4e6a5b428fe2d0ec752ef187fMike Stump case LangOptions::GCOnly:
354565e465c6d0093f1bf8414b2cabdc842022385a9Ted Kremenek   ActionObjCMemCheckerAux(C, mgr, D, true);
355b7166334d897e1e4e6a5b428fe2d0ec752ef187fMike Stump   break;
356b7166334d897e1e4e6a5b428fe2d0ec752ef187fMike Stump
357b7166334d897e1e4e6a5b428fe2d0ec752ef187fMike Stump case LangOptions::HybridGC:
358565e465c6d0093f1bf8414b2cabdc842022385a9Ted Kremenek   ActionObjCMemCheckerAux(C, mgr, D, false);
359565e465c6d0093f1bf8414b2cabdc842022385a9Ted Kremenek   ActionObjCMemCheckerAux(C, mgr, D, true);
360b7166334d897e1e4e6a5b428fe2d0ec752ef187fMike Stump   break;
361b35a74a40c1d2656a25e560e773ed48bdf49f9c0Ted Kremenek }
362b35a74a40c1d2656a25e560e773ed48bdf49f9c0Ted Kremenek}
363b35a74a40c1d2656a25e560e773ed48bdf49f9c0Ted Kremenek
364f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek//===----------------------------------------------------------------------===//
365f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek// AnalysisConsumer creation.
366f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek//===----------------------------------------------------------------------===//
367f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek
3689ef6537a894c33003359b1f9b9676e9178e028b7Ted KremenekASTConsumer* ento::CreateAnalysisConsumer(const Preprocessor& pp,
369e71b85feb0a2df9273b1b488f5b40279369a6255Eli Friedman                                           const std::string& OutDir,
370e71b85feb0a2df9273b1b488f5b40279369a6255Eli Friedman                                           const AnalyzerOptions& Opts) {
371efceabd2380f49306bc0229583458e93b062094bDaniel Dunbar  llvm::OwningPtr<AnalysisConsumer> C(new AnalysisConsumer(pp, OutDir, Opts));
372be1fe1eb12a1cb91c8e3a9fcc2db4dfe989def6cTed Kremenek
3732c4036eda90fad6d219d9f3fadbd9288fa197e89Ted Kremenek  // Last, disable the effects of '-Werror' when using the AnalysisConsumer.
374efceabd2380f49306bc0229583458e93b062094bDaniel Dunbar  pp.getDiagnostics().setWarningsAsErrors(false);
375be1fe1eb12a1cb91c8e3a9fcc2db4dfe989def6cTed Kremenek
376f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek  return C.take();
377f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek}
378f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek
379f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek//===----------------------------------------------------------------------===//
380f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek// Ubigraph Visualization.  FIXME: Move to separate file.
381f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek//===----------------------------------------------------------------------===//
382f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek
383f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremeneknamespace {
3841eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
385c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xuclass UbigraphViz : public ExplodedNode::Auditor {
3865f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner  llvm::OwningPtr<raw_ostream> Out;
387710ad9343f32b33b336369b20edad1a21a0b3299Ted Kremenek  llvm::sys::Path Dir, Filename;
388f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek  unsigned Cntr;
389f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek
390f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek  typedef llvm::DenseMap<void*,unsigned> VMap;
391f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek  VMap M;
3921eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
393f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenekpublic:
3949c378f705405d37f49795d5e915989de774fe11fTed Kremenek  UbigraphViz(raw_ostream *out, llvm::sys::Path& dir,
39556b98719b0dbebb33cb228afa888c47156be2381Ted Kremenek              llvm::sys::Path& filename);
3961eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
397710ad9343f32b33b336369b20edad1a21a0b3299Ted Kremenek  ~UbigraphViz();
3981eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
3999c378f705405d37f49795d5e915989de774fe11fTed Kremenek  virtual void AddEdge(ExplodedNode *Src, ExplodedNode *Dst);
400f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek};
4011eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
402f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek} // end anonymous namespace
403f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek
404c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xustatic ExplodedNode::Auditor* CreateUbiViz() {
405f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek  std::string ErrMsg;
4061eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
407710ad9343f32b33b336369b20edad1a21a0b3299Ted Kremenek  llvm::sys::Path Dir = llvm::sys::Path::GetTemporaryDirectory(&ErrMsg);
408f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek  if (!ErrMsg.empty())
409f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek    return 0;
410f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek
411710ad9343f32b33b336369b20edad1a21a0b3299Ted Kremenek  llvm::sys::Path Filename = Dir;
412f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek  Filename.appendComponent("llvm_ubi");
413f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek  Filename.makeUnique(true,&ErrMsg);
414f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek
415f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek  if (!ErrMsg.empty())
416f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek    return 0;
417f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek
418d57a7ef9252964bc6c8471451d7bd395b0520cb8Chris Lattner  llvm::errs() << "Writing '" << Filename.str() << "'.\n";
4191eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
420f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek  llvm::OwningPtr<llvm::raw_fd_ostream> Stream;
421b044c473a155b7e827680635c1699cb2b5b6c0eeDan Gohman  Stream.reset(new llvm::raw_fd_ostream(Filename.c_str(), ErrMsg));
422f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek
423f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek  if (!ErrMsg.empty())
424f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek    return 0;
4251eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
426710ad9343f32b33b336369b20edad1a21a0b3299Ted Kremenek  return new UbigraphViz(Stream.take(), Dir, Filename);
427f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek}
428f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek
4299c378f705405d37f49795d5e915989de774fe11fTed Kremenekvoid UbigraphViz::AddEdge(ExplodedNode *Src, ExplodedNode *Dst) {
4301eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
43145479c88c8a44c55d27c3bd855273bb318082f37Ted Kremenek  assert (Src != Dst && "Self-edges are not allowed.");
4321eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
433f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek  // Lookup the Src.  If it is a new node, it's a root.
434f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek  VMap::iterator SrcI= M.find(Src);
435f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek  unsigned SrcID;
4361eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
437f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek  if (SrcI == M.end()) {
438f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek    M[Src] = SrcID = Cntr++;
439f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek    *Out << "('vertex', " << SrcID << ", ('color','#00ff00'))\n";
440f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek  }
441f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek  else
442f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek    SrcID = SrcI->second;
4431eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
444f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek  // Lookup the Dst.
445f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek  VMap::iterator DstI= M.find(Dst);
446f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek  unsigned DstID;
447f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek
448f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek  if (DstI == M.end()) {
449f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek    M[Dst] = DstID = Cntr++;
450f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek    *Out << "('vertex', " << DstID << ")\n";
451f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek  }
45256b98719b0dbebb33cb228afa888c47156be2381Ted Kremenek  else {
45356b98719b0dbebb33cb228afa888c47156be2381Ted Kremenek    // We have hit DstID before.  Change its style to reflect a cache hit.
454f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek    DstID = DstI->second;
45556b98719b0dbebb33cb228afa888c47156be2381Ted Kremenek    *Out << "('change_vertex_style', " << DstID << ", 1)\n";
45656b98719b0dbebb33cb228afa888c47156be2381Ted Kremenek  }
457f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek
458f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek  // Add the edge.
4591eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  *Out << "('edge', " << SrcID << ", " << DstID
460d1289327f7d2126d732e23cc189ecd0aa5d07cbbTed Kremenek       << ", ('arrow','true'), ('oriented', 'true'))\n";
461f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek}
462f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek
4639c378f705405d37f49795d5e915989de774fe11fTed KremenekUbigraphViz::UbigraphViz(raw_ostream *out, llvm::sys::Path& dir,
46456b98719b0dbebb33cb228afa888c47156be2381Ted Kremenek                         llvm::sys::Path& filename)
46556b98719b0dbebb33cb228afa888c47156be2381Ted Kremenek  : Out(out), Dir(dir), Filename(filename), Cntr(0) {
46656b98719b0dbebb33cb228afa888c47156be2381Ted Kremenek
46756b98719b0dbebb33cb228afa888c47156be2381Ted Kremenek  *Out << "('vertex_style_attribute', 0, ('shape', 'icosahedron'))\n";
46856b98719b0dbebb33cb228afa888c47156be2381Ted Kremenek  *Out << "('vertex_style', 1, 0, ('shape', 'sphere'), ('color', '#ffcc66'),"
46956b98719b0dbebb33cb228afa888c47156be2381Ted Kremenek          " ('size', '1.5'))\n";
47056b98719b0dbebb33cb228afa888c47156be2381Ted Kremenek}
47156b98719b0dbebb33cb228afa888c47156be2381Ted Kremenek
472710ad9343f32b33b336369b20edad1a21a0b3299Ted KremenekUbigraphViz::~UbigraphViz() {
473710ad9343f32b33b336369b20edad1a21a0b3299Ted Kremenek  Out.reset(0);
4746cb7c1a43b0c8f739d1f54b7fdae5ede86033496Benjamin Kramer  llvm::errs() << "Running 'ubiviz' program... ";
475710ad9343f32b33b336369b20edad1a21a0b3299Ted Kremenek  std::string ErrMsg;
476710ad9343f32b33b336369b20edad1a21a0b3299Ted Kremenek  llvm::sys::Path Ubiviz = llvm::sys::Program::FindProgramByName("ubiviz");
477710ad9343f32b33b336369b20edad1a21a0b3299Ted Kremenek  std::vector<const char*> args;
478710ad9343f32b33b336369b20edad1a21a0b3299Ted Kremenek  args.push_back(Ubiviz.c_str());
479710ad9343f32b33b336369b20edad1a21a0b3299Ted Kremenek  args.push_back(Filename.c_str());
480710ad9343f32b33b336369b20edad1a21a0b3299Ted Kremenek  args.push_back(0);
4811eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
482710ad9343f32b33b336369b20edad1a21a0b3299Ted Kremenek  if (llvm::sys::Program::ExecuteAndWait(Ubiviz, &args[0],0,0,0,0,&ErrMsg)) {
4836cb7c1a43b0c8f739d1f54b7fdae5ede86033496Benjamin Kramer    llvm::errs() << "Error viewing graph: " << ErrMsg << "\n";
484710ad9343f32b33b336369b20edad1a21a0b3299Ted Kremenek  }
4851eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
486710ad9343f32b33b336369b20edad1a21a0b3299Ted Kremenek  // Delete the directory.
4871eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  Dir.eraseFromDisk(true);
488932680ecdeab4c216ce7c0736093d3dcd2f60f6dDaniel Dunbar}
489