AnalysisConsumer.cpp revision b219cfc4d75f0a03630b7c4509ef791b7e97b2c8
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/PathDiagnosticClients.h" 29a7af5ea88a6c5bdf87497cca6c20831e8c546751Argyrios Kyrtzidis 30efceabd2380f49306bc0229583458e93b062094bDaniel Dunbar#include "clang/Basic/FileManager.h" 31efceabd2380f49306bc0229583458e93b062094bDaniel Dunbar#include "clang/Basic/SourceManager.h" 329b414d3e2d0cb84512b55a3275a98490b090162aDaniel Dunbar#include "clang/Frontend/AnalyzerOptions.h" 33efceabd2380f49306bc0229583458e93b062094bDaniel Dunbar#include "clang/Lex/Preprocessor.h" 34f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek#include "llvm/Support/raw_ostream.h" 3503013fa9a0bf1ef4b907f5fec006c8f4000fdd21Michael J. Spencer#include "llvm/Support/Path.h" 3603013fa9a0bf1ef4b907f5fec006c8f4000fdd21Michael J. Spencer#include "llvm/Support/Program.h" 376cb7c1a43b0c8f739d1f54b7fdae5ede86033496Benjamin Kramer#include "llvm/ADT/OwningPtr.h" 38db09a4dee28a4515438af60f2d2b4a83e4965c31Ted Kremenek 39f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenekusing namespace clang; 409ef6537a894c33003359b1f9b9676e9178e028b7Ted Kremenekusing namespace ento; 41f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek 42c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xustatic ExplodedNode::Auditor* CreateUbiViz(); 43ff944a8c481d6c0f1ad2633e4be9bf8b1dd2a09fZhongxing Xu 44be1fe1eb12a1cb91c8e3a9fcc2db4dfe989def6cTed Kremenek//===----------------------------------------------------------------------===// 45f75560670bcdd59b051149bdece3eac14e313853Ted Kremenek// Special PathDiagnosticClients. 46f75560670bcdd59b051149bdece3eac14e313853Ted Kremenek//===----------------------------------------------------------------------===// 47f75560670bcdd59b051149bdece3eac14e313853Ted Kremenek 48f75560670bcdd59b051149bdece3eac14e313853Ted Kremenekstatic PathDiagnosticClient* 49f928dca56542cf8f981a684f090d2c79bdcb2a10Argyrios KyrtzidiscreatePlistHTMLDiagnosticClient(const std::string& prefix, 50efceabd2380f49306bc0229583458e93b062094bDaniel Dunbar const Preprocessor &PP) { 51d5b08bee799d4f77f1a25fa5977ca77b983ab031Michael J. Spencer PathDiagnosticClient *PD = 52d5b08bee799d4f77f1a25fa5977ca77b983ab031Michael J. Spencer createHTMLDiagnosticClient(llvm::sys::path::parent_path(prefix), PP); 53f928dca56542cf8f981a684f090d2c79bdcb2a10Argyrios Kyrtzidis return createPlistDiagnosticClient(prefix, PP, PD); 54f75560670bcdd59b051149bdece3eac14e313853Ted Kremenek} 55f75560670bcdd59b051149bdece3eac14e313853Ted Kremenek 56f75560670bcdd59b051149bdece3eac14e313853Ted Kremenek//===----------------------------------------------------------------------===// 57f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek// AnalysisConsumer declaration. 58f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek//===----------------------------------------------------------------------===// 59f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek 60f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremeneknamespace { 61f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek 62ed8afacb8118b71bcfa8017059e51da325e7691bZhongxing Xuclass AnalysisConsumer : public ASTConsumer { 63ed8afacb8118b71bcfa8017059e51da325e7691bZhongxing Xupublic: 649c378f705405d37f49795d5e915989de774fe11fTed Kremenek ASTContext *Ctx; 651d9cbeb76cf4c36acf5545028e2b2ac207086442Ted Kremenek const Preprocessor &PP; 661d9cbeb76cf4c36acf5545028e2b2ac207086442Ted Kremenek const std::string OutDir; 671d9cbeb76cf4c36acf5545028e2b2ac207086442Ted Kremenek AnalyzerOptions Opts; 6808b86531ade68727c56918f162816075b87c864aJordy Rose ArrayRef<std::string> Plugins; 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, 8108b86531ade68727c56918f162816075b87c864aJordy Rose const AnalyzerOptions& opts, 8208b86531ade68727c56918f162816075b87c864aJordy Rose ArrayRef<std::string> plugins) 8308b86531ade68727c56918f162816075b87c864aJordy Rose : Ctx(0), PP(pp), OutDir(outdir), Opts(opts), Plugins(plugins), 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: 105b219cfc4d75f0a03630b7c4509ef791b7e97b2c8David Blaikie llvm_unreachable("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: 113b219cfc4d75f0a03630b7c4509ef791b7e97b2c8David Blaikie llvm_unreachable("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; 14608b86531ade68727c56918f162816075b87c864aJordy Rose checkerMgr.reset(createCheckerManager(Opts, PP.getLangOptions(), Plugins, 14708b86531ade68727c56918f162816075b87c864aJordy Rose 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); 164fee618af5dd7dee2caaa7347b372eb3dc5fdeffcTed Kremenek void HandleDeclContextDecl(ASTContext &C, Decl *D); 16514cc9451de4a9539bf79e4e5d63248c2377426dbTed Kremenek 166c367a876d0abcf32cb443712ce2709a0491be00bArgyrios Kyrtzidis void HandleCode(Decl *D); 1671d9cbeb76cf4c36acf5545028e2b2ac207086442Ted Kremenek}; 168f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek} // end anonymous namespace 169f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek 170f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek//===----------------------------------------------------------------------===// 171f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek// AnalysisConsumer implementation. 172f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek//===----------------------------------------------------------------------===// 173f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek 17414cc9451de4a9539bf79e4e5d63248c2377426dbTed Kremenekvoid AnalysisConsumer::HandleDeclContext(ASTContext &C, DeclContext *dc) { 17514cc9451de4a9539bf79e4e5d63248c2377426dbTed Kremenek for (DeclContext::decl_iterator I = dc->decls_begin(), E = dc->decls_end(); 176ed8afacb8118b71bcfa8017059e51da325e7691bZhongxing Xu I != E; ++I) { 177fee618af5dd7dee2caaa7347b372eb3dc5fdeffcTed Kremenek HandleDeclContextDecl(C, *I); 178fee618af5dd7dee2caaa7347b372eb3dc5fdeffcTed Kremenek } 179fee618af5dd7dee2caaa7347b372eb3dc5fdeffcTed Kremenek} 180fee618af5dd7dee2caaa7347b372eb3dc5fdeffcTed Kremenek 181fee618af5dd7dee2caaa7347b372eb3dc5fdeffcTed Kremenekvoid AnalysisConsumer::HandleDeclContextDecl(ASTContext &C, Decl *D) { 182fee618af5dd7dee2caaa7347b372eb3dc5fdeffcTed Kremenek { // Handle callbacks for arbitrary decls. 183fee618af5dd7dee2caaa7347b372eb3dc5fdeffcTed Kremenek BugReporter BR(*Mgr); 1849fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis checkerMgr->runCheckersOnASTDecl(D, *Mgr, BR); 185fee618af5dd7dee2caaa7347b372eb3dc5fdeffcTed Kremenek } 1869fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis 187fee618af5dd7dee2caaa7347b372eb3dc5fdeffcTed Kremenek switch (D->getKind()) { 188fee618af5dd7dee2caaa7347b372eb3dc5fdeffcTed Kremenek case Decl::Namespace: { 189fee618af5dd7dee2caaa7347b372eb3dc5fdeffcTed Kremenek HandleDeclContext(C, cast<NamespaceDecl>(D)); 190fee618af5dd7dee2caaa7347b372eb3dc5fdeffcTed Kremenek break; 191fee618af5dd7dee2caaa7347b372eb3dc5fdeffcTed Kremenek } 192fee618af5dd7dee2caaa7347b372eb3dc5fdeffcTed Kremenek case Decl::CXXConstructor: 193fee618af5dd7dee2caaa7347b372eb3dc5fdeffcTed Kremenek case Decl::CXXDestructor: 194fee618af5dd7dee2caaa7347b372eb3dc5fdeffcTed Kremenek case Decl::CXXConversion: 195fee618af5dd7dee2caaa7347b372eb3dc5fdeffcTed Kremenek case Decl::CXXMethod: 196fee618af5dd7dee2caaa7347b372eb3dc5fdeffcTed Kremenek case Decl::Function: { 197fee618af5dd7dee2caaa7347b372eb3dc5fdeffcTed Kremenek FunctionDecl *FD = cast<FunctionDecl>(D); 198fee618af5dd7dee2caaa7347b372eb3dc5fdeffcTed Kremenek // We skip function template definitions, as their semantics is 199fee618af5dd7dee2caaa7347b372eb3dc5fdeffcTed Kremenek // only determined when they are instantiated. 200fee618af5dd7dee2caaa7347b372eb3dc5fdeffcTed Kremenek if (FD->isThisDeclarationADefinition() && 201fee618af5dd7dee2caaa7347b372eb3dc5fdeffcTed Kremenek !FD->isDependentContext()) { 202fee618af5dd7dee2caaa7347b372eb3dc5fdeffcTed Kremenek if (!Opts.AnalyzeSpecificFunction.empty() && 203fee618af5dd7dee2caaa7347b372eb3dc5fdeffcTed Kremenek FD->getDeclName().getAsString() != Opts.AnalyzeSpecificFunction) 204fee618af5dd7dee2caaa7347b372eb3dc5fdeffcTed Kremenek break; 205fee618af5dd7dee2caaa7347b372eb3dc5fdeffcTed Kremenek DisplayFunction(FD); 206fee618af5dd7dee2caaa7347b372eb3dc5fdeffcTed Kremenek HandleCode(FD); 207ed8afacb8118b71bcfa8017059e51da325e7691bZhongxing Xu } 208fee618af5dd7dee2caaa7347b372eb3dc5fdeffcTed Kremenek break; 209fee618af5dd7dee2caaa7347b372eb3dc5fdeffcTed Kremenek } 210fee618af5dd7dee2caaa7347b372eb3dc5fdeffcTed Kremenek 211fee618af5dd7dee2caaa7347b372eb3dc5fdeffcTed Kremenek case Decl::ObjCCategoryImpl: 212fee618af5dd7dee2caaa7347b372eb3dc5fdeffcTed Kremenek case Decl::ObjCImplementation: { 213fee618af5dd7dee2caaa7347b372eb3dc5fdeffcTed Kremenek ObjCImplDecl *ID = cast<ObjCImplDecl>(D); 214fee618af5dd7dee2caaa7347b372eb3dc5fdeffcTed Kremenek HandleCode(ID); 215fee618af5dd7dee2caaa7347b372eb3dc5fdeffcTed Kremenek 216fee618af5dd7dee2caaa7347b372eb3dc5fdeffcTed Kremenek for (ObjCContainerDecl::method_iterator MI = ID->meth_begin(), 217fee618af5dd7dee2caaa7347b372eb3dc5fdeffcTed Kremenek ME = ID->meth_end(); MI != ME; ++MI) { 218fee618af5dd7dee2caaa7347b372eb3dc5fdeffcTed Kremenek BugReporter BR(*Mgr); 219fee618af5dd7dee2caaa7347b372eb3dc5fdeffcTed Kremenek checkerMgr->runCheckersOnASTDecl(*MI, *Mgr, BR); 220fee618af5dd7dee2caaa7347b372eb3dc5fdeffcTed Kremenek 221fee618af5dd7dee2caaa7347b372eb3dc5fdeffcTed Kremenek if ((*MI)->isThisDeclarationADefinition()) { 222ed8afacb8118b71bcfa8017059e51da325e7691bZhongxing Xu if (!Opts.AnalyzeSpecificFunction.empty() && 223fee618af5dd7dee2caaa7347b372eb3dc5fdeffcTed Kremenek Opts.AnalyzeSpecificFunction != 224fee618af5dd7dee2caaa7347b372eb3dc5fdeffcTed Kremenek (*MI)->getSelector().getAsString()) 225d1fe529b1a17a2422f28f1b938ee70453dc7199dAnna Zaks continue; 226fee618af5dd7dee2caaa7347b372eb3dc5fdeffcTed Kremenek DisplayFunction(*MI); 227fee618af5dd7dee2caaa7347b372eb3dc5fdeffcTed Kremenek HandleCode(*MI); 22814cc9451de4a9539bf79e4e5d63248c2377426dbTed Kremenek } 22914cc9451de4a9539bf79e4e5d63248c2377426dbTed Kremenek } 230fee618af5dd7dee2caaa7347b372eb3dc5fdeffcTed Kremenek break; 231ed8afacb8118b71bcfa8017059e51da325e7691bZhongxing Xu } 232fee618af5dd7dee2caaa7347b372eb3dc5fdeffcTed Kremenek 233fee618af5dd7dee2caaa7347b372eb3dc5fdeffcTed Kremenek default: 234fee618af5dd7dee2caaa7347b372eb3dc5fdeffcTed Kremenek break; 235fee618af5dd7dee2caaa7347b372eb3dc5fdeffcTed Kremenek } 23614cc9451de4a9539bf79e4e5d63248c2377426dbTed Kremenek} 237f6eafcca7734274d277afa121f2c4fb025a54218Ted Kremenek 23814cc9451de4a9539bf79e4e5d63248c2377426dbTed Kremenekvoid AnalysisConsumer::HandleTranslationUnit(ASTContext &C) { 2399fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis BugReporter BR(*Mgr); 24014cc9451de4a9539bf79e4e5d63248c2377426dbTed Kremenek TranslationUnitDecl *TU = C.getTranslationUnitDecl(); 2419fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis checkerMgr->runCheckersOnASTDecl(TU, *Mgr, BR); 24214cc9451de4a9539bf79e4e5d63248c2377426dbTed Kremenek HandleDeclContext(C, TU); 243b317f8f5ca8737a5bbad97a3f7566a2dbd2ed61bZhongxing Xu 2449be6e7ce5788e50c62d40c59b0bbc2ea423683f7Ted Kremenek // After all decls handled, run checkers on the entire TranslationUnit. 2459be6e7ce5788e50c62d40c59b0bbc2ea423683f7Ted Kremenek checkerMgr->runCheckersOnEndOfTranslationUnit(TU, *Mgr, BR); 2469be6e7ce5788e50c62d40c59b0bbc2ea423683f7Ted Kremenek 247690a7f431d6863a101711e67636d51ddd13f35c5Ted Kremenek // Explicitly destroy the PathDiagnosticClient. This will flush its output. 248690a7f431d6863a101711e67636d51ddd13f35c5Ted Kremenek // FIXME: This should be replaced with something that doesn't rely on 249da17fd50ad485fd2a1fc5c2f055caacf532992daZhongxing Xu // side-effects in PathDiagnosticClient's destructor. This is required when 250da17fd50ad485fd2a1fc5c2f055caacf532992daZhongxing Xu // used with option -disable-free. 251d07a0d0279c09d1017f8450fce575a94dc9703c0Zhongxing Xu Mgr.reset(NULL); 252db09a4dee28a4515438af60f2d2b4a83e4965c31Ted Kremenek} 253db09a4dee28a4515438af60f2d2b4a83e4965c31Ted Kremenek 2545f9e272e632e951b1efe824cd16acb4d96077930Chris Lattnerstatic void FindBlocks(DeclContext *D, SmallVectorImpl<Decl*> &WL) { 255fc576514d06c46a7cac49500169411d82f38d04bTed Kremenek if (BlockDecl *BD = dyn_cast<BlockDecl>(D)) 256fc576514d06c46a7cac49500169411d82f38d04bTed Kremenek WL.push_back(BD); 257f6eafcca7734274d277afa121f2c4fb025a54218Ted Kremenek 258fc576514d06c46a7cac49500169411d82f38d04bTed Kremenek for (DeclContext::decl_iterator I = D->decls_begin(), E = D->decls_end(); 259fc576514d06c46a7cac49500169411d82f38d04bTed Kremenek I!=E; ++I) 260fc576514d06c46a7cac49500169411d82f38d04bTed Kremenek if (DeclContext *DC = dyn_cast<DeclContext>(*I)) 261fc576514d06c46a7cac49500169411d82f38d04bTed Kremenek FindBlocks(DC, WL); 262fc576514d06c46a7cac49500169411d82f38d04bTed Kremenek} 263fc576514d06c46a7cac49500169411d82f38d04bTed Kremenek 26417a38e2636a8b1ce473fc6504c4b16cb09db29f4Jordy Rosestatic void RunPathSensitiveChecks(AnalysisConsumer &C, AnalysisManager &mgr, 26517a38e2636a8b1ce473fc6504c4b16cb09db29f4Jordy Rose Decl *D); 266d655ab28fdf7c940d3f79f8f287954d7f76e0977Argyrios Kyrtzidis 267c367a876d0abcf32cb443712ce2709a0491be00bArgyrios Kyrtzidisvoid AnalysisConsumer::HandleCode(Decl *D) { 2681eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 269fc8f0e14ad142ed811e90fbd9a30e419e301c717Chris Lattner // Don't run the actions if an error has occurred with parsing the file. 27099e8192c4c8f1f596f9969e5f2cdafcee64ddaacTed Kremenek Diagnostic &Diags = PP.getDiagnostics(); 27199e8192c4c8f1f596f9969e5f2cdafcee64ddaacTed Kremenek if (Diags.hasErrorOccurred() || Diags.hasFatalErrorOccurred()) 272f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek return; 27381922f01352aceeb923c0c3cc8c96b6527322384Ted Kremenek 274f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek // Don't run the actions on declarations in header files unless 275f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek // otherwise specified. 276fcd783d583d270b7ec1ec3e0fcf83cd93d30e381Ted Kremenek SourceManager &SM = Ctx->getSourceManager(); 277402785357ab053dd53f4fdd858b9630a5e0f8badChandler Carruth SourceLocation SL = SM.getExpansionLoc(D->getLocation()); 278fcd783d583d270b7ec1ec3e0fcf83cd93d30e381Ted Kremenek if (!Opts.AnalyzeAll && !SM.isFromMainFile(SL)) 2791eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump return; 280f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek 28158f5ec7d56b1ebf5f90ee11226ebe7663f2821eaTed Kremenek // Clear the AnalysisManager of old AnalysisContexts. 28258f5ec7d56b1ebf5f90ee11226ebe7663f2821eaTed Kremenek Mgr->ClearContexts(); 283f6eafcca7734274d277afa121f2c4fb025a54218Ted Kremenek 2841eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump // Dispatch on the actions. 2855f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner SmallVector<Decl*, 10> WL; 286fc576514d06c46a7cac49500169411d82f38d04bTed Kremenek WL.push_back(D); 287f6eafcca7734274d277afa121f2c4fb025a54218Ted Kremenek 28806a54a38be5054c910ffc92db60edab23f9ea105Argyrios Kyrtzidis if (D->hasBody() && Opts.AnalyzeNestedBlocks) 289fc576514d06c46a7cac49500169411d82f38d04bTed Kremenek FindBlocks(cast<DeclContext>(D), WL); 290f6eafcca7734274d277afa121f2c4fb025a54218Ted Kremenek 2919fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis BugReporter BR(*Mgr); 2925f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner for (SmallVectorImpl<Decl*>::iterator WI=WL.begin(), WE=WL.end(); 2939fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis WI != WE; ++WI) 294d655ab28fdf7c940d3f79f8f287954d7f76e0977Argyrios Kyrtzidis if ((*WI)->hasBody()) { 2959fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis checkerMgr->runCheckersOnASTBody(*WI, *Mgr, BR); 296d655ab28fdf7c940d3f79f8f287954d7f76e0977Argyrios Kyrtzidis if (checkerMgr->hasPathSensitiveCheckers()) 29717a38e2636a8b1ce473fc6504c4b16cb09db29f4Jordy Rose RunPathSensitiveChecks(*this, *Mgr, *WI); 298d655ab28fdf7c940d3f79f8f287954d7f76e0977Argyrios Kyrtzidis } 299f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek} 300f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek 301f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek//===----------------------------------------------------------------------===// 302d655ab28fdf7c940d3f79f8f287954d7f76e0977Argyrios Kyrtzidis// Path-sensitive checking. 303f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek//===----------------------------------------------------------------------===// 304f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek 30517a38e2636a8b1ce473fc6504c4b16cb09db29f4Jordy Rosestatic void ActionExprEngine(AnalysisConsumer &C, AnalysisManager &mgr, 30617a38e2636a8b1ce473fc6504c4b16cb09db29f4Jordy Rose Decl *D, bool ObjCGCEnabled) { 30775d03cffe20b5c945ef04eba208efb0437339997Ted Kremenek // Construct the analysis engine. We first query for the LiveVariables 30875d03cffe20b5c945ef04eba208efb0437339997Ted Kremenek // information to see if the CFG is valid. 30975d03cffe20b5c945ef04eba208efb0437339997Ted Kremenek // FIXME: Inter-procedural analysis will need to handle invalid CFGs. 31075d03cffe20b5c945ef04eba208efb0437339997Ted Kremenek if (!mgr.getLiveVariables(D)) 311f6eafcca7734274d277afa121f2c4fb025a54218Ted Kremenek return; 31217a38e2636a8b1ce473fc6504c4b16cb09db29f4Jordy Rose ExprEngine Eng(mgr, ObjCGCEnabled); 313f6eafcca7734274d277afa121f2c4fb025a54218Ted Kremenek 314f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek // Set the graph auditor. 315c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu llvm::OwningPtr<ExplodedNode::Auditor> Auditor; 316f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek if (mgr.shouldVisualizeUbigraph()) { 317f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek Auditor.reset(CreateUbiViz()); 318c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu ExplodedNode::SetAuditor(Auditor.get()); 319f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek } 3201eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 321b35a74a40c1d2656a25e560e773ed48bdf49f9c0Ted Kremenek // Execute the worklist algorithm. 322c6238d2786cfd961b94580b3d3675a1b3ff0721cZhongxing Xu Eng.ExecuteWorkList(mgr.getStackFrame(D, 0), mgr.getMaxNodes()); 3231eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 324f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek // Release the auditor (if any) so that it doesn't monitor the graph 325f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek // created BugReporter. 326c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu ExplodedNode::SetAuditor(0); 3273df6421150271266b5a90fd4c6bfa6566c38c036Ted Kremenek 32834d7734b6ed1d9c0f647405e065251eb67f42badTed Kremenek // Visualize the exploded graph. 329f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek if (mgr.shouldVisualizeGraphviz()) 33034d7734b6ed1d9c0f647405e065251eb67f42badTed Kremenek Eng.ViewGraph(mgr.shouldTrimGraph()); 3311eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 3323df6421150271266b5a90fd4c6bfa6566c38c036Ted Kremenek // Display warnings. 3333df6421150271266b5a90fd4c6bfa6566c38c036Ted Kremenek Eng.getBugReporter().FlushReports(); 334bc46f345838b1c0d420dbd3655c94f5f360fb5b8Ted Kremenek} 335bc46f345838b1c0d420dbd3655c94f5f360fb5b8Ted Kremenek 33617a38e2636a8b1ce473fc6504c4b16cb09db29f4Jordy Rosestatic void RunPathSensitiveChecks(AnalysisConsumer &C, AnalysisManager &mgr, 33717a38e2636a8b1ce473fc6504c4b16cb09db29f4Jordy Rose Decl *D) { 33817a38e2636a8b1ce473fc6504c4b16cb09db29f4Jordy Rose 339e289d81369914678db386f6aa86faf8f178e245dDouglas Gregor switch (mgr.getLangOptions().getGC()) { 34017a38e2636a8b1ce473fc6504c4b16cb09db29f4Jordy Rose default: 34117a38e2636a8b1ce473fc6504c4b16cb09db29f4Jordy Rose llvm_unreachable("Invalid GC mode."); 34217a38e2636a8b1ce473fc6504c4b16cb09db29f4Jordy Rose case LangOptions::NonGC: 34317a38e2636a8b1ce473fc6504c4b16cb09db29f4Jordy Rose ActionExprEngine(C, mgr, D, false); 34417a38e2636a8b1ce473fc6504c4b16cb09db29f4Jordy Rose break; 34517a38e2636a8b1ce473fc6504c4b16cb09db29f4Jordy Rose 34617a38e2636a8b1ce473fc6504c4b16cb09db29f4Jordy Rose case LangOptions::GCOnly: 34717a38e2636a8b1ce473fc6504c4b16cb09db29f4Jordy Rose ActionExprEngine(C, mgr, D, true); 34817a38e2636a8b1ce473fc6504c4b16cb09db29f4Jordy Rose break; 34917a38e2636a8b1ce473fc6504c4b16cb09db29f4Jordy Rose 35017a38e2636a8b1ce473fc6504c4b16cb09db29f4Jordy Rose case LangOptions::HybridGC: 35117a38e2636a8b1ce473fc6504c4b16cb09db29f4Jordy Rose ActionExprEngine(C, mgr, D, false); 35217a38e2636a8b1ce473fc6504c4b16cb09db29f4Jordy Rose ActionExprEngine(C, mgr, D, true); 35317a38e2636a8b1ce473fc6504c4b16cb09db29f4Jordy Rose break; 35417a38e2636a8b1ce473fc6504c4b16cb09db29f4Jordy Rose } 355b35a74a40c1d2656a25e560e773ed48bdf49f9c0Ted Kremenek} 356b35a74a40c1d2656a25e560e773ed48bdf49f9c0Ted Kremenek 357f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek//===----------------------------------------------------------------------===// 358f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek// AnalysisConsumer creation. 359f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek//===----------------------------------------------------------------------===// 360f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek 3619ef6537a894c33003359b1f9b9676e9178e028b7Ted KremenekASTConsumer* ento::CreateAnalysisConsumer(const Preprocessor& pp, 36208b86531ade68727c56918f162816075b87c864aJordy Rose const std::string& outDir, 36308b86531ade68727c56918f162816075b87c864aJordy Rose const AnalyzerOptions& opts, 36408b86531ade68727c56918f162816075b87c864aJordy Rose ArrayRef<std::string> plugins) { 36508b86531ade68727c56918f162816075b87c864aJordy Rose // Disable the effects of '-Werror' when using the AnalysisConsumer. 366efceabd2380f49306bc0229583458e93b062094bDaniel Dunbar pp.getDiagnostics().setWarningsAsErrors(false); 367be1fe1eb12a1cb91c8e3a9fcc2db4dfe989def6cTed Kremenek 36808b86531ade68727c56918f162816075b87c864aJordy Rose return new AnalysisConsumer(pp, outDir, opts, plugins); 369f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek} 370f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek 371f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek//===----------------------------------------------------------------------===// 372f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek// Ubigraph Visualization. FIXME: Move to separate file. 373f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek//===----------------------------------------------------------------------===// 374f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek 375f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremeneknamespace { 3761eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 377c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xuclass UbigraphViz : public ExplodedNode::Auditor { 3785f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner llvm::OwningPtr<raw_ostream> Out; 379710ad9343f32b33b336369b20edad1a21a0b3299Ted Kremenek llvm::sys::Path Dir, Filename; 380f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek unsigned Cntr; 381f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek 382f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek typedef llvm::DenseMap<void*,unsigned> VMap; 383f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek VMap M; 3841eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 385f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenekpublic: 3869c378f705405d37f49795d5e915989de774fe11fTed Kremenek UbigraphViz(raw_ostream *out, llvm::sys::Path& dir, 38756b98719b0dbebb33cb228afa888c47156be2381Ted Kremenek llvm::sys::Path& filename); 3881eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 389710ad9343f32b33b336369b20edad1a21a0b3299Ted Kremenek ~UbigraphViz(); 3901eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 3919c378f705405d37f49795d5e915989de774fe11fTed Kremenek virtual void AddEdge(ExplodedNode *Src, ExplodedNode *Dst); 392f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek}; 3931eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 394f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek} // end anonymous namespace 395f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek 396c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xustatic ExplodedNode::Auditor* CreateUbiViz() { 397f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek std::string ErrMsg; 3981eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 399710ad9343f32b33b336369b20edad1a21a0b3299Ted Kremenek llvm::sys::Path Dir = llvm::sys::Path::GetTemporaryDirectory(&ErrMsg); 400f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek if (!ErrMsg.empty()) 401f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek return 0; 402f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek 403710ad9343f32b33b336369b20edad1a21a0b3299Ted Kremenek llvm::sys::Path Filename = Dir; 404f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek Filename.appendComponent("llvm_ubi"); 405f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek Filename.makeUnique(true,&ErrMsg); 406f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek 407f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek if (!ErrMsg.empty()) 408f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek return 0; 409f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek 410d57a7ef9252964bc6c8471451d7bd395b0520cb8Chris Lattner llvm::errs() << "Writing '" << Filename.str() << "'.\n"; 4111eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 412f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek llvm::OwningPtr<llvm::raw_fd_ostream> Stream; 413b044c473a155b7e827680635c1699cb2b5b6c0eeDan Gohman Stream.reset(new llvm::raw_fd_ostream(Filename.c_str(), ErrMsg)); 414f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek 415f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek if (!ErrMsg.empty()) 416f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek return 0; 4171eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 418710ad9343f32b33b336369b20edad1a21a0b3299Ted Kremenek return new UbigraphViz(Stream.take(), Dir, Filename); 419f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek} 420f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek 4219c378f705405d37f49795d5e915989de774fe11fTed Kremenekvoid UbigraphViz::AddEdge(ExplodedNode *Src, ExplodedNode *Dst) { 4221eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 42345479c88c8a44c55d27c3bd855273bb318082f37Ted Kremenek assert (Src != Dst && "Self-edges are not allowed."); 4241eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 425f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek // Lookup the Src. If it is a new node, it's a root. 426f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek VMap::iterator SrcI= M.find(Src); 427f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek unsigned SrcID; 4281eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 429f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek if (SrcI == M.end()) { 430f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek M[Src] = SrcID = Cntr++; 431f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek *Out << "('vertex', " << SrcID << ", ('color','#00ff00'))\n"; 432f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek } 433f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek else 434f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek SrcID = SrcI->second; 4351eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 436f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek // Lookup the Dst. 437f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek VMap::iterator DstI= M.find(Dst); 438f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek unsigned DstID; 439f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek 440f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek if (DstI == M.end()) { 441f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek M[Dst] = DstID = Cntr++; 442f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek *Out << "('vertex', " << DstID << ")\n"; 443f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek } 44456b98719b0dbebb33cb228afa888c47156be2381Ted Kremenek else { 44556b98719b0dbebb33cb228afa888c47156be2381Ted Kremenek // We have hit DstID before. Change its style to reflect a cache hit. 446f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek DstID = DstI->second; 44756b98719b0dbebb33cb228afa888c47156be2381Ted Kremenek *Out << "('change_vertex_style', " << DstID << ", 1)\n"; 44856b98719b0dbebb33cb228afa888c47156be2381Ted Kremenek } 449f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek 450f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek // Add the edge. 4511eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump *Out << "('edge', " << SrcID << ", " << DstID 452d1289327f7d2126d732e23cc189ecd0aa5d07cbbTed Kremenek << ", ('arrow','true'), ('oriented', 'true'))\n"; 453f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek} 454f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek 4559c378f705405d37f49795d5e915989de774fe11fTed KremenekUbigraphViz::UbigraphViz(raw_ostream *out, llvm::sys::Path& dir, 45656b98719b0dbebb33cb228afa888c47156be2381Ted Kremenek llvm::sys::Path& filename) 45756b98719b0dbebb33cb228afa888c47156be2381Ted Kremenek : Out(out), Dir(dir), Filename(filename), Cntr(0) { 45856b98719b0dbebb33cb228afa888c47156be2381Ted Kremenek 45956b98719b0dbebb33cb228afa888c47156be2381Ted Kremenek *Out << "('vertex_style_attribute', 0, ('shape', 'icosahedron'))\n"; 46056b98719b0dbebb33cb228afa888c47156be2381Ted Kremenek *Out << "('vertex_style', 1, 0, ('shape', 'sphere'), ('color', '#ffcc66')," 46156b98719b0dbebb33cb228afa888c47156be2381Ted Kremenek " ('size', '1.5'))\n"; 46256b98719b0dbebb33cb228afa888c47156be2381Ted Kremenek} 46356b98719b0dbebb33cb228afa888c47156be2381Ted Kremenek 464710ad9343f32b33b336369b20edad1a21a0b3299Ted KremenekUbigraphViz::~UbigraphViz() { 465710ad9343f32b33b336369b20edad1a21a0b3299Ted Kremenek Out.reset(0); 4666cb7c1a43b0c8f739d1f54b7fdae5ede86033496Benjamin Kramer llvm::errs() << "Running 'ubiviz' program... "; 467710ad9343f32b33b336369b20edad1a21a0b3299Ted Kremenek std::string ErrMsg; 468710ad9343f32b33b336369b20edad1a21a0b3299Ted Kremenek llvm::sys::Path Ubiviz = llvm::sys::Program::FindProgramByName("ubiviz"); 469710ad9343f32b33b336369b20edad1a21a0b3299Ted Kremenek std::vector<const char*> args; 470710ad9343f32b33b336369b20edad1a21a0b3299Ted Kremenek args.push_back(Ubiviz.c_str()); 471710ad9343f32b33b336369b20edad1a21a0b3299Ted Kremenek args.push_back(Filename.c_str()); 472710ad9343f32b33b336369b20edad1a21a0b3299Ted Kremenek args.push_back(0); 4731eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 474710ad9343f32b33b336369b20edad1a21a0b3299Ted Kremenek if (llvm::sys::Program::ExecuteAndWait(Ubiviz, &args[0],0,0,0,0,&ErrMsg)) { 4756cb7c1a43b0c8f739d1f54b7fdae5ede86033496Benjamin Kramer llvm::errs() << "Error viewing graph: " << ErrMsg << "\n"; 476710ad9343f32b33b336369b20edad1a21a0b3299Ted Kremenek } 4771eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 478710ad9343f32b33b336369b20edad1a21a0b3299Ted Kremenek // Delete the directory. 4791eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump Dir.eraseFromDisk(true); 480932680ecdeab4c216ce7c0736093d3dcd2f60f6dDaniel Dunbar} 481