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