AnalysisConsumer.cpp revision 6a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3
1f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek//===--- AnalysisConsumer.cpp - ASTConsumer for running Analyses ----------===// 2f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek// 3f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek// The LLVM Compiler Infrastructure 4f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek// 5f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek// This file is distributed under the University of Illinois Open Source 6f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek// License. See LICENSE.TXT for details. 7f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek// 8f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek//===----------------------------------------------------------------------===// 9f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek// 10f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek// "Meta" ASTConsumer for running different source analyses. 11f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek// 12f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek//===----------------------------------------------------------------------===// 13f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek 14d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks#define DEBUG_TYPE "AnalysisConsumer" 15d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks 16e6348c336fecc8da9288ea367375a1b1cd2358d2Argyrios Kyrtzidis#include "AnalysisConsumer.h" 17f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek#include "clang/AST/ASTConsumer.h" 18f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek#include "clang/AST/Decl.h" 19802be99a6817aba6edb166b93c133da4358aa783Zhongxing Xu#include "clang/AST/DeclCXX.h" 20f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek#include "clang/AST/DeclObjC.h" 21efceabd2380f49306bc0229583458e93b062094bDaniel Dunbar#include "clang/AST/ParentMap.h" 22aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks#include "clang/AST/RecursiveASTVisitor.h" 23efceabd2380f49306bc0229583458e93b062094bDaniel Dunbar#include "clang/Analysis/CFG.h" 24d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks#include "clang/Analysis/CallGraph.h" 2527af04bcca46f8a3374586be1301477f9123f5e1Argyrios Kyrtzidis#include "clang/StaticAnalyzer/Frontend/CheckerRegistration.h" 2643dee220252ef0b42c5f8a3bb1eca97f84f2565fArgyrios Kyrtzidis#include "clang/StaticAnalyzer/Core/CheckerManager.h" 2721142581d55918beed544a757e4af3bb865b1812Ted Kremenek#include "clang/StaticAnalyzer/Checkers/LocalCheckers.h" 289b663716449b618ba0390b1dbebc54fa8e971124Ted Kremenek#include "clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h" 299b663716449b618ba0390b1dbebc54fa8e971124Ted Kremenek#include "clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h" 309b663716449b618ba0390b1dbebc54fa8e971124Ted Kremenek#include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h" 319b663716449b618ba0390b1dbebc54fa8e971124Ted Kremenek#include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h" 32f39d962cf84f46d2c0512157259ae1d41a1a5173David Blaikie#include "clang/StaticAnalyzer/Core/PathDiagnosticConsumers.h" 33a7af5ea88a6c5bdf87497cca6c20831e8c546751Argyrios Kyrtzidis 34efceabd2380f49306bc0229583458e93b062094bDaniel Dunbar#include "clang/Basic/FileManager.h" 35efceabd2380f49306bc0229583458e93b062094bDaniel Dunbar#include "clang/Basic/SourceManager.h" 369b414d3e2d0cb84512b55a3275a98490b090162aDaniel Dunbar#include "clang/Frontend/AnalyzerOptions.h" 37efceabd2380f49306bc0229583458e93b062094bDaniel Dunbar#include "clang/Lex/Preprocessor.h" 38f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek#include "llvm/Support/raw_ostream.h" 3903013fa9a0bf1ef4b907f5fec006c8f4000fdd21Michael J. Spencer#include "llvm/Support/Path.h" 4003013fa9a0bf1ef4b907f5fec006c8f4000fdd21Michael J. Spencer#include "llvm/Support/Program.h" 41d38f79543136ba68cd14b1dab0856474df1fbfd5Anna Zaks#include "llvm/Support/Timer.h" 42d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks#include "llvm/ADT/DepthFirstIterator.h" 436cb7c1a43b0c8f739d1f54b7fdae5ede86033496Benjamin Kramer#include "llvm/ADT/OwningPtr.h" 446a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks#include "llvm/ADT/SmallPtrSet.h" 4581fb169f42769e02c7425b23885a261c025fd5e6Anna Zaks#include "llvm/ADT/Statistic.h" 46db09a4dee28a4515438af60f2d2b4a83e4965c31Ted Kremenek 477fe8dcef71ae56e43fd7df345db2895f84f2d0caAnna Zaks#include <queue> 487fe8dcef71ae56e43fd7df345db2895f84f2d0caAnna Zaks 49f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenekusing namespace clang; 509ef6537a894c33003359b1f9b9676e9178e028b7Ted Kremenekusing namespace ento; 51d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaksusing llvm::SmallPtrSet; 52f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek 53c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xustatic ExplodedNode::Auditor* CreateUbiViz(); 54ff944a8c481d6c0f1ad2633e4be9bf8b1dd2a09fZhongxing Xu 553fd5f370a28552976c52e76c3035d79012d78ddaAnna ZaksSTATISTIC(NumFunctionTopLevel, "The # of functions at top level."); 56d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna ZaksSTATISTIC(NumFunctionsAnalyzed, "The # of functions analysed (as top level)."); 57e62f048960645b79363408fdead53fec2a063c52Anna ZaksSTATISTIC(NumBlocksInAnalyzedFunctions, 58e62f048960645b79363408fdead53fec2a063c52Anna Zaks "The # of basic blocks in the analyzed functions."); 59e62f048960645b79363408fdead53fec2a063c52Anna ZaksSTATISTIC(PercentReachableBlocks, "The % of reachable basic blocks."); 60d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks 61be1fe1eb12a1cb91c8e3a9fcc2db4dfe989def6cTed Kremenek//===----------------------------------------------------------------------===// 62f39d962cf84f46d2c0512157259ae1d41a1a5173David Blaikie// Special PathDiagnosticConsumers. 63f75560670bcdd59b051149bdece3eac14e313853Ted Kremenek//===----------------------------------------------------------------------===// 64f75560670bcdd59b051149bdece3eac14e313853Ted Kremenek 65ef3643fbbbf66247c5e205497fae0f46e240c143David Blaikiestatic PathDiagnosticConsumer* 66ef3643fbbbf66247c5e205497fae0f46e240c143David BlaikiecreatePlistHTMLDiagnosticConsumer(const std::string& prefix, 67efceabd2380f49306bc0229583458e93b062094bDaniel Dunbar const Preprocessor &PP) { 68ef3643fbbbf66247c5e205497fae0f46e240c143David Blaikie PathDiagnosticConsumer *PD = 69ef3643fbbbf66247c5e205497fae0f46e240c143David Blaikie createHTMLDiagnosticConsumer(llvm::sys::path::parent_path(prefix), PP); 70ef3643fbbbf66247c5e205497fae0f46e240c143David Blaikie return createPlistDiagnosticConsumer(prefix, PP, PD); 71f75560670bcdd59b051149bdece3eac14e313853Ted Kremenek} 72f75560670bcdd59b051149bdece3eac14e313853Ted Kremenek 73f75560670bcdd59b051149bdece3eac14e313853Ted Kremenek//===----------------------------------------------------------------------===// 74f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek// AnalysisConsumer declaration. 75f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek//===----------------------------------------------------------------------===// 76f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek 77f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremeneknamespace { 78f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek 79aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaksclass AnalysisConsumer : public ASTConsumer, 80aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks public RecursiveASTVisitor<AnalysisConsumer> { 81aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks enum AnalysisMode { 82aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks ANALYSIS_SYNTAX, 83aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks ANALYSIS_PATH, 84aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks ANALYSIS_ALL 85aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks }; 86aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks 87aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks /// Mode of the analyzes while recursively visiting Decls. 88aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks AnalysisMode RecVisitorMode; 89aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks /// Bug Reporter to use while recursively visiting Decls. 90aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks BugReporter *RecVisitorBR; 91aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks 92ed8afacb8118b71bcfa8017059e51da325e7691bZhongxing Xupublic: 939c378f705405d37f49795d5e915989de774fe11fTed Kremenek ASTContext *Ctx; 941d9cbeb76cf4c36acf5545028e2b2ac207086442Ted Kremenek const Preprocessor &PP; 951d9cbeb76cf4c36acf5545028e2b2ac207086442Ted Kremenek const std::string OutDir; 961d9cbeb76cf4c36acf5545028e2b2ac207086442Ted Kremenek AnalyzerOptions Opts; 9708b86531ade68727c56918f162816075b87c864aJordy Rose ArrayRef<std::string> Plugins; 98d07a0d0279c09d1017f8450fce575a94dc9703c0Zhongxing Xu 996a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks /// \brief Stores the declarations from the local translation unit. 1006a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks /// Note, we pre-compute the local declarations at parse time as an 1016a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks /// optimization to make sure we do not deserialize everything from disk. 1026a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks /// The local declaration to all declarations ratio might be very small when 1036a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks /// working with a PCH file. 1046a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks SetOfDecls LocalTUDecls; 1056a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks 1061d9cbeb76cf4c36acf5545028e2b2ac207086442Ted Kremenek // PD is owned by AnalysisManager. 107ef3643fbbbf66247c5e205497fae0f46e240c143David Blaikie PathDiagnosticConsumer *PD; 108d07a0d0279c09d1017f8450fce575a94dc9703c0Zhongxing Xu 1091d9cbeb76cf4c36acf5545028e2b2ac207086442Ted Kremenek StoreManagerCreator CreateStoreMgr; 1101d9cbeb76cf4c36acf5545028e2b2ac207086442Ted Kremenek ConstraintManagerCreator CreateConstraintMgr; 111f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek 1126f42b62b6194f53bcbc349f5d17388e1936535d7Dylan Noblesmith OwningPtr<CheckerManager> checkerMgr; 1136f42b62b6194f53bcbc349f5d17388e1936535d7Dylan Noblesmith OwningPtr<AnalysisManager> Mgr; 114c471e7b44e63ff1b46b480e723c4130aeaef5a8aZhongxing Xu 115d38f79543136ba68cd14b1dab0856474df1fbfd5Anna Zaks /// Time the analyzes time of each translation unit. 116d38f79543136ba68cd14b1dab0856474df1fbfd5Anna Zaks static llvm::Timer* TUTotalTimer; 117d38f79543136ba68cd14b1dab0856474df1fbfd5Anna Zaks 1183bbd8cd831788c506f2980293eb3c7e1b3ca2501Anna Zaks /// The information about analyzed functions shared throughout the 1193bbd8cd831788c506f2980293eb3c7e1b3ca2501Anna Zaks /// translation unit. 1203bbd8cd831788c506f2980293eb3c7e1b3ca2501Anna Zaks FunctionSummariesTy FunctionSummaries; 1213bbd8cd831788c506f2980293eb3c7e1b3ca2501Anna Zaks 1221d9cbeb76cf4c36acf5545028e2b2ac207086442Ted Kremenek AnalysisConsumer(const Preprocessor& pp, 1231d9cbeb76cf4c36acf5545028e2b2ac207086442Ted Kremenek const std::string& outdir, 12408b86531ade68727c56918f162816075b87c864aJordy Rose const AnalyzerOptions& opts, 12508b86531ade68727c56918f162816075b87c864aJordy Rose ArrayRef<std::string> plugins) 126aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks : RecVisitorMode(ANALYSIS_ALL), RecVisitorBR(0), 127aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks Ctx(0), PP(pp), OutDir(outdir), Opts(opts), Plugins(plugins), PD(0) { 1281d9cbeb76cf4c36acf5545028e2b2ac207086442Ted Kremenek DigestAnalyzerOptions(); 129d38f79543136ba68cd14b1dab0856474df1fbfd5Anna Zaks if (Opts.PrintStats) { 130d38f79543136ba68cd14b1dab0856474df1fbfd5Anna Zaks llvm::EnableStatistics(); 131d38f79543136ba68cd14b1dab0856474df1fbfd5Anna Zaks TUTotalTimer = new llvm::Timer("Analyzer Total Time"); 132d38f79543136ba68cd14b1dab0856474df1fbfd5Anna Zaks } 133d38f79543136ba68cd14b1dab0856474df1fbfd5Anna Zaks } 134d38f79543136ba68cd14b1dab0856474df1fbfd5Anna Zaks 135d38f79543136ba68cd14b1dab0856474df1fbfd5Anna Zaks ~AnalysisConsumer() { 136d38f79543136ba68cd14b1dab0856474df1fbfd5Anna Zaks if (Opts.PrintStats) 137d38f79543136ba68cd14b1dab0856474df1fbfd5Anna Zaks delete TUTotalTimer; 1381d9cbeb76cf4c36acf5545028e2b2ac207086442Ted Kremenek } 139fda7832b000ff8927386f093b52c067641679469Zhongxing Xu 1401d9cbeb76cf4c36acf5545028e2b2ac207086442Ted Kremenek void DigestAnalyzerOptions() { 141ef3643fbbbf66247c5e205497fae0f46e240c143David Blaikie // Create the PathDiagnosticConsumer. 1421d9cbeb76cf4c36acf5545028e2b2ac207086442Ted Kremenek if (!OutDir.empty()) { 1431d9cbeb76cf4c36acf5545028e2b2ac207086442Ted Kremenek switch (Opts.AnalysisDiagOpt) { 1441d9cbeb76cf4c36acf5545028e2b2ac207086442Ted Kremenek default: 145fda7832b000ff8927386f093b52c067641679469Zhongxing Xu#define ANALYSIS_DIAGNOSTICS(NAME, CMDFLAG, DESC, CREATEFN, AUTOCREATE) \ 1461d9cbeb76cf4c36acf5545028e2b2ac207086442Ted Kremenek case PD_##NAME: PD = CREATEFN(OutDir, PP); break; 147fda7832b000ff8927386f093b52c067641679469Zhongxing Xu#include "clang/Frontend/Analyses.def" 148fda7832b000ff8927386f093b52c067641679469Zhongxing Xu } 149a599ae8826b01c0160a519b0fc5a4871f599bf04Argyrios Kyrtzidis } else if (Opts.AnalysisDiagOpt == PD_TEXT) { 150a599ae8826b01c0160a519b0fc5a4871f599bf04Argyrios Kyrtzidis // Create the text client even without a specified output file since 151a599ae8826b01c0160a519b0fc5a4871f599bf04Argyrios Kyrtzidis // it just uses diagnostic notes. 152ef3643fbbbf66247c5e205497fae0f46e240c143David Blaikie PD = createTextPathDiagnosticConsumer("", PP); 1531d9cbeb76cf4c36acf5545028e2b2ac207086442Ted Kremenek } 154fda7832b000ff8927386f093b52c067641679469Zhongxing Xu 1551d9cbeb76cf4c36acf5545028e2b2ac207086442Ted Kremenek // Create the analyzer component creators. 1565f83d6f36a7308eef21d87104fd70c421e854448Argyrios Kyrtzidis switch (Opts.AnalysisStoreOpt) { 1575f83d6f36a7308eef21d87104fd70c421e854448Argyrios Kyrtzidis default: 158b219cfc4d75f0a03630b7c4509ef791b7e97b2c8David Blaikie llvm_unreachable("Unknown store manager."); 159fda7832b000ff8927386f093b52c067641679469Zhongxing Xu#define ANALYSIS_STORE(NAME, CMDFLAG, DESC, CREATEFN) \ 1605f83d6f36a7308eef21d87104fd70c421e854448Argyrios Kyrtzidis case NAME##Model: CreateStoreMgr = CREATEFN; break; 161fda7832b000ff8927386f093b52c067641679469Zhongxing Xu#include "clang/Frontend/Analyses.def" 1621d9cbeb76cf4c36acf5545028e2b2ac207086442Ted Kremenek } 1631eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1645f83d6f36a7308eef21d87104fd70c421e854448Argyrios Kyrtzidis switch (Opts.AnalysisConstraintsOpt) { 1655f83d6f36a7308eef21d87104fd70c421e854448Argyrios Kyrtzidis default: 166b219cfc4d75f0a03630b7c4509ef791b7e97b2c8David Blaikie llvm_unreachable("Unknown store manager."); 167fda7832b000ff8927386f093b52c067641679469Zhongxing Xu#define ANALYSIS_CONSTRAINTS(NAME, CMDFLAG, DESC, CREATEFN) \ 1685f83d6f36a7308eef21d87104fd70c421e854448Argyrios Kyrtzidis case NAME##Model: CreateConstraintMgr = CREATEFN; break; 169fda7832b000ff8927386f093b52c067641679469Zhongxing Xu#include "clang/Frontend/Analyses.def" 170fda7832b000ff8927386f093b52c067641679469Zhongxing Xu } 1711d9cbeb76cf4c36acf5545028e2b2ac207086442Ted Kremenek } 172f6eafcca7734274d277afa121f2c4fb025a54218Ted Kremenek 173aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks void DisplayFunction(const Decl *D, AnalysisMode Mode) { 174c4a1437c15da43eb8d2601cdce13161ef41a4389Ted Kremenek if (!Opts.AnalyzerDisplayProgress) 1751d9cbeb76cf4c36acf5545028e2b2ac207086442Ted Kremenek return; 176f6eafcca7734274d277afa121f2c4fb025a54218Ted Kremenek 177fc576514d06c46a7cac49500169411d82f38d04bTed Kremenek SourceManager &SM = Mgr->getASTContext().getSourceManager(); 178fc576514d06c46a7cac49500169411d82f38d04bTed Kremenek PresumedLoc Loc = SM.getPresumedLoc(D->getLocation()); 179cb7b1e17b63967317ab5cc55682168cf0380519aDouglas Gregor if (Loc.isValid()) { 180aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks llvm::errs() << "ANALYZE"; 181aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks switch (Mode) { 182aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks case ANALYSIS_SYNTAX: llvm::errs() << "(Syntax)"; break; 183aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks case ANALYSIS_PATH: llvm::errs() << "(Path Sensitive)"; break; 184aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks case ANALYSIS_ALL: break; 185aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks }; 186aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks llvm::errs() << ": " << Loc.getFilename(); 187cb7b1e17b63967317ab5cc55682168cf0380519aDouglas Gregor if (isa<FunctionDecl>(D) || isa<ObjCMethodDecl>(D)) { 188cb7b1e17b63967317ab5cc55682168cf0380519aDouglas Gregor const NamedDecl *ND = cast<NamedDecl>(D); 189b8989f27f116ff2400e92a52c067a69846119eb5Benjamin Kramer llvm::errs() << ' ' << *ND << '\n'; 190cb7b1e17b63967317ab5cc55682168cf0380519aDouglas Gregor } 191cb7b1e17b63967317ab5cc55682168cf0380519aDouglas Gregor else if (isa<BlockDecl>(D)) { 192cb7b1e17b63967317ab5cc55682168cf0380519aDouglas Gregor llvm::errs() << ' ' << "block(line:" << Loc.getLine() << ",col:" 193cb7b1e17b63967317ab5cc55682168cf0380519aDouglas Gregor << Loc.getColumn() << '\n'; 194cb7b1e17b63967317ab5cc55682168cf0380519aDouglas Gregor } 195cb7b1e17b63967317ab5cc55682168cf0380519aDouglas Gregor else if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D)) { 196cb7b1e17b63967317ab5cc55682168cf0380519aDouglas Gregor Selector S = MD->getSelector(); 197cb7b1e17b63967317ab5cc55682168cf0380519aDouglas Gregor llvm::errs() << ' ' << S.getAsString(); 198cb7b1e17b63967317ab5cc55682168cf0380519aDouglas Gregor } 19935fa76d0bb6fb8c86159a7506efd094a4fe376d2Ted Kremenek } 2001d9cbeb76cf4c36acf5545028e2b2ac207086442Ted Kremenek } 2011eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 2021d9cbeb76cf4c36acf5545028e2b2ac207086442Ted Kremenek virtual void Initialize(ASTContext &Context) { 2031d9cbeb76cf4c36acf5545028e2b2ac207086442Ted Kremenek Ctx = &Context; 2044e4d08403ca5cfd4d558fa2936215d3a4e5a528dDavid Blaikie checkerMgr.reset(createCheckerManager(Opts, PP.getLangOpts(), Plugins, 20508b86531ade68727c56918f162816075b87c864aJordy Rose PP.getDiagnostics())); 2061d9cbeb76cf4c36acf5545028e2b2ac207086442Ted Kremenek Mgr.reset(new AnalysisManager(*Ctx, PP.getDiagnostics(), 2074e4d08403ca5cfd4d558fa2936215d3a4e5a528dDavid Blaikie PP.getLangOpts(), PD, 2081d9cbeb76cf4c36acf5545028e2b2ac207086442Ted Kremenek CreateStoreMgr, CreateConstraintMgr, 20943dee220252ef0b42c5f8a3bb1eca97f84f2565fArgyrios Kyrtzidis checkerMgr.get(), 210c6238d2786cfd961b94580b3d3675a1b3ff0721cZhongxing Xu /* Indexer */ 0, 2116362b893731ccf4480a96527db9e55e04b801503Zhongxing Xu Opts.MaxNodes, Opts.MaxLoop, 2121d9cbeb76cf4c36acf5545028e2b2ac207086442Ted Kremenek Opts.VisualizeEGDot, Opts.VisualizeEGUbi, 213d30952838421ddfb9f7e346b2ba8213889a5f789Anna Zaks Opts.AnalysisPurgeOpt, Opts.EagerlyAssume, 21466253352131e3e7a22b3bfd0e180607aa2bfb988Anna Zaks Opts.TrimGraph, 2159121ba232903ebe61e7bbe14ca294cf0f07dfa96Marcin Swiderski Opts.UnoptimizedCFG, Opts.CFGAddImplicitDtors, 216d767d81290288c030f3be0be1d3e62b9c8df51dcTed Kremenek Opts.CFGAddInitializers, 2178235f9c9c8b3d1737d1c6bd57f7ba3f616b92392Anna Zaks Opts.EagerlyTrimEGraph, 21866253352131e3e7a22b3bfd0e180607aa2bfb988Anna Zaks Opts.IPAMode, 2198235f9c9c8b3d1737d1c6bd57f7ba3f616b92392Anna Zaks Opts.InlineMaxStackDepth, 22066253352131e3e7a22b3bfd0e180607aa2bfb988Anna Zaks Opts.InlineMaxFunctionSize, 2215903a373db3d27794c90b25687e0dd6adb0e497dAnna Zaks Opts.InliningMode, 222b47dbcbc12430fdf3e5a5b9f59cdec5480e89e75Anna Zaks Opts.NoRetryExhausted)); 2231d9cbeb76cf4c36acf5545028e2b2ac207086442Ted Kremenek } 2241eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 2256a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks /// \brief Store the top level decls in the set to be processed later on. 2266a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks /// (Doing this pre-processing avoids deserialization of data from PCH.) 2276a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks virtual bool HandleTopLevelDecl(DeclGroupRef D); 2286a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks virtual void HandleTopLevelDeclInObjCContainer(DeclGroupRef D); 2296a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks 2301d9cbeb76cf4c36acf5545028e2b2ac207086442Ted Kremenek virtual void HandleTranslationUnit(ASTContext &C); 23114cc9451de4a9539bf79e4e5d63248c2377426dbTed Kremenek 2326a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks /// \brief Build the call graph for all the top level decls of this TU and 2336a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks /// use it to define the order in which the functions should be visited. 2346a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks void HandleDeclsGallGraph(); 235aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks 236aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks /// \brief Run analyzes(syntax or path sensitive) on the given function. 237aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks /// \param Mode - determines if we are requesting syntax only or path 238aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks /// sensitive only analysis. 239aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks /// \param VisitedCallees - The output parameter, which is populated with the 240aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks /// set of functions which should be considered analyzed after analyzing the 241aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks /// given root function. 2426a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks void HandleCode(Decl *D, AnalysisMode Mode, 2436a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks SetOfConstDecls *VisitedCallees = 0); 244aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks 2456a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks void RunPathSensitiveChecks(Decl *D, SetOfConstDecls *VisitedCallees); 2466a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks void ActionExprEngine(Decl *D, bool ObjCGCEnabled, 2476a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks SetOfConstDecls *VisitedCallees); 248aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks 249aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks /// Visitors for the RecursiveASTVisitor. 250aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks 251aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks /// Handle callbacks for arbitrary Decls. 252aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks bool VisitDecl(Decl *D) { 253aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks checkerMgr->runCheckersOnASTDecl(D, *Mgr, *RecVisitorBR); 254aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks return true; 255aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks } 256aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks 257aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks bool VisitFunctionDecl(FunctionDecl *FD) { 258aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks IdentifierInfo *II = FD->getIdentifier(); 259aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks if (II && II->getName().startswith("__inline")) 260aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks return true; 261aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks 262aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks // We skip function template definitions, as their semantics is 263aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks // only determined when they are instantiated. 264aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks if (FD->isThisDeclarationADefinition() && 265aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks !FD->isDependentContext()) { 266aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks HandleCode(FD, RecVisitorMode); 267aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks } 268aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks return true; 269aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks } 270aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks 271aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks bool VisitObjCMethodDecl(ObjCMethodDecl *MD) { 272aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks checkerMgr->runCheckersOnASTDecl(MD, *Mgr, *RecVisitorBR); 273aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks if (MD->isThisDeclarationADefinition()) 274aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks HandleCode(MD, RecVisitorMode); 275aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks return true; 276aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks } 2776a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks 2786a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaksprivate: 2796a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks void storeTopLevelDecls(DeclGroupRef DG); 2806a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks 2816a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks /// \brief Check if we should skip (not analyze) the given function. 2826a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks bool skipFunction(Decl *D); 2836a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks 2841d9cbeb76cf4c36acf5545028e2b2ac207086442Ted Kremenek}; 285f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek} // end anonymous namespace 286f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek 287aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks 288f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek//===----------------------------------------------------------------------===// 289f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek// AnalysisConsumer implementation. 290f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek//===----------------------------------------------------------------------===// 291d38f79543136ba68cd14b1dab0856474df1fbfd5Anna Zaksllvm::Timer* AnalysisConsumer::TUTotalTimer = 0; 292f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek 2936a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaksbool AnalysisConsumer::HandleTopLevelDecl(DeclGroupRef DG) { 2946a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks storeTopLevelDecls(DG); 2956a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks return true; 2966a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks} 2976a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks 2986a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaksvoid AnalysisConsumer::HandleTopLevelDeclInObjCContainer(DeclGroupRef DG) { 2996a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks storeTopLevelDecls(DG); 3006a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks} 3016a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks 3026a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaksvoid AnalysisConsumer::storeTopLevelDecls(DeclGroupRef DG) { 3036a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks for (DeclGroupRef::iterator I = DG.begin(), E = DG.end(); I != E; ++I) { 3046a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks 3056a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks // Skip ObjCMethodDecl, wait for the objc container to avoid 3066a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks // analyzing twice. 3076a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks if (isa<ObjCMethodDecl>(*I)) 3086a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks continue; 3096a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks 3106a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks LocalTUDecls.insert(*I); 3116a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks } 3126a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks} 3136a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks 3146a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaksvoid AnalysisConsumer::HandleDeclsGallGraph() { 315d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks // Otherwise, use the Callgraph to derive the order. 316d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks // Build the Call Graph. 317d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks CallGraph CG; 3186a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks // Add all the top level declarations to the graph. 3196a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks for (SetOfDecls::iterator I = LocalTUDecls.begin(), 3206a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks E = LocalTUDecls.end(); I != E; ++I) 3216a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks CG.addToCallGraph(*I); 322d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks 323d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks // Find the top level nodes - children of root + the unreachable (parentless) 324d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks // nodes. 3253fd5f370a28552976c52e76c3035d79012d78ddaAnna Zaks llvm::SmallVector<CallGraphNode*, 24> TopLevelFunctions; 326b990d039c7e01ad0055dcbd1e13a691813397b96Anna Zaks for (CallGraph::nodes_iterator TI = CG.parentless_begin(), 327b990d039c7e01ad0055dcbd1e13a691813397b96Anna Zaks TE = CG.parentless_end(); TI != TE; ++TI) { 328b990d039c7e01ad0055dcbd1e13a691813397b96Anna Zaks TopLevelFunctions.push_back(*TI); 329b990d039c7e01ad0055dcbd1e13a691813397b96Anna Zaks NumFunctionTopLevel++; 330b990d039c7e01ad0055dcbd1e13a691813397b96Anna Zaks } 331d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks CallGraphNode *Entry = CG.getRoot(); 332d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks for (CallGraphNode::iterator I = Entry->begin(), 3333fd5f370a28552976c52e76c3035d79012d78ddaAnna Zaks E = Entry->end(); I != E; ++I) { 334d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks TopLevelFunctions.push_back(*I); 3353fd5f370a28552976c52e76c3035d79012d78ddaAnna Zaks NumFunctionTopLevel++; 3363fd5f370a28552976c52e76c3035d79012d78ddaAnna Zaks } 337d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks 338b990d039c7e01ad0055dcbd1e13a691813397b96Anna Zaks // Make sure the nodes are sorted in order reverse of their definition in the 339b990d039c7e01ad0055dcbd1e13a691813397b96Anna Zaks // translation unit. This step is very important for performance. It ensures 340b990d039c7e01ad0055dcbd1e13a691813397b96Anna Zaks // that we analyze the root functions before the externally available 341b990d039c7e01ad0055dcbd1e13a691813397b96Anna Zaks // subroutines. 3427fe8dcef71ae56e43fd7df345db2895f84f2d0caAnna Zaks std::queue<CallGraphNode*> BFSQueue; 343b990d039c7e01ad0055dcbd1e13a691813397b96Anna Zaks for (llvm::SmallVector<CallGraphNode*, 24>::reverse_iterator 344b990d039c7e01ad0055dcbd1e13a691813397b96Anna Zaks TI = TopLevelFunctions.rbegin(), TE = TopLevelFunctions.rend(); 3457fe8dcef71ae56e43fd7df345db2895f84f2d0caAnna Zaks TI != TE; ++TI) 3467fe8dcef71ae56e43fd7df345db2895f84f2d0caAnna Zaks BFSQueue.push(*TI); 347d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks 3487fe8dcef71ae56e43fd7df345db2895f84f2d0caAnna Zaks // BFS over all of the functions, while skipping the ones inlined into 3497fe8dcef71ae56e43fd7df345db2895f84f2d0caAnna Zaks // the previously processed functions. Use external Visited set, which is 350d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks // also modified when we inline a function. 351d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks SmallPtrSet<CallGraphNode*,24> Visited; 3527fe8dcef71ae56e43fd7df345db2895f84f2d0caAnna Zaks while(!BFSQueue.empty()) { 3537fe8dcef71ae56e43fd7df345db2895f84f2d0caAnna Zaks CallGraphNode *N = BFSQueue.front(); 3547fe8dcef71ae56e43fd7df345db2895f84f2d0caAnna Zaks BFSQueue.pop(); 3557fe8dcef71ae56e43fd7df345db2895f84f2d0caAnna Zaks 3567fe8dcef71ae56e43fd7df345db2895f84f2d0caAnna Zaks // Skip the functions which have been processed already or previously 3577fe8dcef71ae56e43fd7df345db2895f84f2d0caAnna Zaks // inlined. 3587fe8dcef71ae56e43fd7df345db2895f84f2d0caAnna Zaks if (Visited.count(N)) 3597fe8dcef71ae56e43fd7df345db2895f84f2d0caAnna Zaks continue; 3607fe8dcef71ae56e43fd7df345db2895f84f2d0caAnna Zaks 3617fe8dcef71ae56e43fd7df345db2895f84f2d0caAnna Zaks // Analyze the function. 3626a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks SetOfConstDecls VisitedCallees; 3637fe8dcef71ae56e43fd7df345db2895f84f2d0caAnna Zaks Decl *D = N->getDecl(); 3647fe8dcef71ae56e43fd7df345db2895f84f2d0caAnna Zaks assert(D); 3657fe8dcef71ae56e43fd7df345db2895f84f2d0caAnna Zaks HandleCode(D, ANALYSIS_PATH, 3667fe8dcef71ae56e43fd7df345db2895f84f2d0caAnna Zaks (Mgr->InliningMode == All ? 0 : &VisitedCallees)); 3677fe8dcef71ae56e43fd7df345db2895f84f2d0caAnna Zaks 3687fe8dcef71ae56e43fd7df345db2895f84f2d0caAnna Zaks // Add the visited callees to the global visited set. 3696a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks for (SetOfConstDecls::const_iterator I = VisitedCallees.begin(), 3706a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks E = VisitedCallees.end(); I != E; ++I){ 3717fe8dcef71ae56e43fd7df345db2895f84f2d0caAnna Zaks CallGraphNode *VN = CG.getNode(*I); 3727fe8dcef71ae56e43fd7df345db2895f84f2d0caAnna Zaks if (VN) 3737fe8dcef71ae56e43fd7df345db2895f84f2d0caAnna Zaks Visited.insert(VN); 3747fe8dcef71ae56e43fd7df345db2895f84f2d0caAnna Zaks } 3757fe8dcef71ae56e43fd7df345db2895f84f2d0caAnna Zaks Visited.insert(N); 3767fe8dcef71ae56e43fd7df345db2895f84f2d0caAnna Zaks 3777fe8dcef71ae56e43fd7df345db2895f84f2d0caAnna Zaks // Push the children into the queue. 3787fe8dcef71ae56e43fd7df345db2895f84f2d0caAnna Zaks for (CallGraphNode::const_iterator CI = N->begin(), 3797fe8dcef71ae56e43fd7df345db2895f84f2d0caAnna Zaks CE = N->end(); CI != CE; ++CI) { 3807fe8dcef71ae56e43fd7df345db2895f84f2d0caAnna Zaks BFSQueue.push(*CI); 381d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks } 382d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks } 383fee618af5dd7dee2caaa7347b372eb3dc5fdeffcTed Kremenek} 384fee618af5dd7dee2caaa7347b372eb3dc5fdeffcTed Kremenek 38514cc9451de4a9539bf79e4e5d63248c2377426dbTed Kremenekvoid AnalysisConsumer::HandleTranslationUnit(ASTContext &C) { 386aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks // Don't run the actions if an error has occurred with parsing the file. 387aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks DiagnosticsEngine &Diags = PP.getDiagnostics(); 388aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks if (Diags.hasErrorOccurred() || Diags.hasFatalErrorOccurred()) 389aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks return; 390aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks 391c5bdc556f6a65c677e0ed73f918c3000ecad33afAnna Zaks { 392d38f79543136ba68cd14b1dab0856474df1fbfd5Anna Zaks if (TUTotalTimer) TUTotalTimer->startTimer(); 393d38f79543136ba68cd14b1dab0856474df1fbfd5Anna Zaks 394c5bdc556f6a65c677e0ed73f918c3000ecad33afAnna Zaks // Introduce a scope to destroy BR before Mgr. 395c5bdc556f6a65c677e0ed73f918c3000ecad33afAnna Zaks BugReporter BR(*Mgr); 396c5bdc556f6a65c677e0ed73f918c3000ecad33afAnna Zaks TranslationUnitDecl *TU = C.getTranslationUnitDecl(); 397c5bdc556f6a65c677e0ed73f918c3000ecad33afAnna Zaks checkerMgr->runCheckersOnASTDecl(TU, *Mgr, BR); 398aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks 399aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks // Run the AST-only checks using the order in which functions are defined. 400aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks // If inlining is not turned on, use the simplest function order for path 401aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks // sensitive analyzes as well. 402aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks RecVisitorMode = (Mgr->shouldInlineCall() ? ANALYSIS_SYNTAX : ANALYSIS_ALL); 403aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks RecVisitorBR = &BR; 4046a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks 4056a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks // Process all the top level declarations. 4066a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks for (SetOfDecls::iterator I = LocalTUDecls.begin(), 4076a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks E = LocalTUDecls.end(); I != E; ++I) 4086a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks TraverseDecl(*I); 409aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks 410aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks if (Mgr->shouldInlineCall()) 4116a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks HandleDeclsGallGraph(); 412b317f8f5ca8737a5bbad97a3f7566a2dbd2ed61bZhongxing Xu 413c5bdc556f6a65c677e0ed73f918c3000ecad33afAnna Zaks // After all decls handled, run checkers on the entire TranslationUnit. 414c5bdc556f6a65c677e0ed73f918c3000ecad33afAnna Zaks checkerMgr->runCheckersOnEndOfTranslationUnit(TU, *Mgr, BR); 415aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks 416aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks RecVisitorBR = 0; 417c5bdc556f6a65c677e0ed73f918c3000ecad33afAnna Zaks } 4189be6e7ce5788e50c62d40c59b0bbc2ea423683f7Ted Kremenek 419ef3643fbbbf66247c5e205497fae0f46e240c143David Blaikie // Explicitly destroy the PathDiagnosticConsumer. This will flush its output. 420690a7f431d6863a101711e67636d51ddd13f35c5Ted Kremenek // FIXME: This should be replaced with something that doesn't rely on 421ef3643fbbbf66247c5e205497fae0f46e240c143David Blaikie // side-effects in PathDiagnosticConsumer's destructor. This is required when 422da17fd50ad485fd2a1fc5c2f055caacf532992daZhongxing Xu // used with option -disable-free. 423d07a0d0279c09d1017f8450fce575a94dc9703c0Zhongxing Xu Mgr.reset(NULL); 424d38f79543136ba68cd14b1dab0856474df1fbfd5Anna Zaks 425d38f79543136ba68cd14b1dab0856474df1fbfd5Anna Zaks if (TUTotalTimer) TUTotalTimer->stopTimer(); 4266b77ce8824cf62c2cfb61cf2d801eb3fcfbecffeAnna Zaks 4276b77ce8824cf62c2cfb61cf2d801eb3fcfbecffeAnna Zaks // Count how many basic blocks we have not covered. 4286b77ce8824cf62c2cfb61cf2d801eb3fcfbecffeAnna Zaks NumBlocksInAnalyzedFunctions = FunctionSummaries.getTotalNumBasicBlocks(); 4296b77ce8824cf62c2cfb61cf2d801eb3fcfbecffeAnna Zaks if (NumBlocksInAnalyzedFunctions > 0) 4306b77ce8824cf62c2cfb61cf2d801eb3fcfbecffeAnna Zaks PercentReachableBlocks = 4316b77ce8824cf62c2cfb61cf2d801eb3fcfbecffeAnna Zaks (FunctionSummaries.getTotalNumVisitedBasicBlocks() * 100) / 4326b77ce8824cf62c2cfb61cf2d801eb3fcfbecffeAnna Zaks NumBlocksInAnalyzedFunctions; 4336b77ce8824cf62c2cfb61cf2d801eb3fcfbecffeAnna Zaks 434db09a4dee28a4515438af60f2d2b4a83e4965c31Ted Kremenek} 435db09a4dee28a4515438af60f2d2b4a83e4965c31Ted Kremenek 4365f9e272e632e951b1efe824cd16acb4d96077930Chris Lattnerstatic void FindBlocks(DeclContext *D, SmallVectorImpl<Decl*> &WL) { 437fc576514d06c46a7cac49500169411d82f38d04bTed Kremenek if (BlockDecl *BD = dyn_cast<BlockDecl>(D)) 438fc576514d06c46a7cac49500169411d82f38d04bTed Kremenek WL.push_back(BD); 439f6eafcca7734274d277afa121f2c4fb025a54218Ted Kremenek 440fc576514d06c46a7cac49500169411d82f38d04bTed Kremenek for (DeclContext::decl_iterator I = D->decls_begin(), E = D->decls_end(); 441fc576514d06c46a7cac49500169411d82f38d04bTed Kremenek I!=E; ++I) 442fc576514d06c46a7cac49500169411d82f38d04bTed Kremenek if (DeclContext *DC = dyn_cast<DeclContext>(*I)) 443fc576514d06c46a7cac49500169411d82f38d04bTed Kremenek FindBlocks(DC, WL); 444fc576514d06c46a7cac49500169411d82f38d04bTed Kremenek} 445fc576514d06c46a7cac49500169411d82f38d04bTed Kremenek 446d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaksstatic std::string getFunctionName(const Decl *D) { 447d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks if (const ObjCMethodDecl *ID = dyn_cast<ObjCMethodDecl>(D)) { 448d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks return ID->getSelector().getAsString(); 449d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks } 450d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks if (const FunctionDecl *ND = dyn_cast<FunctionDecl>(D)) { 451d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks IdentifierInfo *II = ND->getIdentifier(); 452d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks if (II) 453d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks return II->getName(); 454d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks } 455d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks return ""; 456d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks} 457d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks 45898520835eb1aa091429afa06e9f4f7ebe3864d34Anna Zaksbool AnalysisConsumer::skipFunction(Decl *D) { 459d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks if (!Opts.AnalyzeSpecificFunction.empty() && 460d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks getFunctionName(D) != Opts.AnalyzeSpecificFunction) 46198520835eb1aa091429afa06e9f4f7ebe3864d34Anna Zaks return true; 4621eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 463f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek // Don't run the actions on declarations in header files unless 464f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek // otherwise specified. 465fcd783d583d270b7ec1ec3e0fcf83cd93d30e381Ted Kremenek SourceManager &SM = Ctx->getSourceManager(); 466402785357ab053dd53f4fdd858b9630a5e0f8badChandler Carruth SourceLocation SL = SM.getExpansionLoc(D->getLocation()); 467fcd783d583d270b7ec1ec3e0fcf83cd93d30e381Ted Kremenek if (!Opts.AnalyzeAll && !SM.isFromMainFile(SL)) 46898520835eb1aa091429afa06e9f4f7ebe3864d34Anna Zaks return true; 46998520835eb1aa091429afa06e9f4f7ebe3864d34Anna Zaks 47098520835eb1aa091429afa06e9f4f7ebe3864d34Anna Zaks return false; 47198520835eb1aa091429afa06e9f4f7ebe3864d34Anna Zaks} 47298520835eb1aa091429afa06e9f4f7ebe3864d34Anna Zaks 473aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaksvoid AnalysisConsumer::HandleCode(Decl *D, AnalysisMode Mode, 4746a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks SetOfConstDecls *VisitedCallees) { 47598520835eb1aa091429afa06e9f4f7ebe3864d34Anna Zaks if (skipFunction(D)) 4761eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump return; 477f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek 478aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks DisplayFunction(D, Mode); 47998520835eb1aa091429afa06e9f4f7ebe3864d34Anna Zaks 4801d26f48dc2eea1c07431ca1519d7034a21b9bcffTed Kremenek // Clear the AnalysisManager of old AnalysisDeclContexts. 48158f5ec7d56b1ebf5f90ee11226ebe7663f2821eaTed Kremenek Mgr->ClearContexts(); 482f6eafcca7734274d277afa121f2c4fb025a54218Ted Kremenek 4831eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump // Dispatch on the actions. 4845f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner SmallVector<Decl*, 10> WL; 485fc576514d06c46a7cac49500169411d82f38d04bTed Kremenek WL.push_back(D); 486f6eafcca7734274d277afa121f2c4fb025a54218Ted Kremenek 48706a54a38be5054c910ffc92db60edab23f9ea105Argyrios Kyrtzidis if (D->hasBody() && Opts.AnalyzeNestedBlocks) 488fc576514d06c46a7cac49500169411d82f38d04bTed Kremenek FindBlocks(cast<DeclContext>(D), WL); 489f6eafcca7734274d277afa121f2c4fb025a54218Ted Kremenek 4909fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis BugReporter BR(*Mgr); 4915f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner for (SmallVectorImpl<Decl*>::iterator WI=WL.begin(), WE=WL.end(); 4929fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis WI != WE; ++WI) 493d655ab28fdf7c940d3f79f8f287954d7f76e0977Argyrios Kyrtzidis if ((*WI)->hasBody()) { 494aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks if (Mode != ANALYSIS_PATH) 495aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks checkerMgr->runCheckersOnASTBody(*WI, *Mgr, BR); 4961f5171edc9fb9b0698a75fa981c29a750b0a6082Anna Zaks if (Mode != ANALYSIS_SYNTAX && checkerMgr->hasPathSensitiveCheckers()) { 4973fd5f370a28552976c52e76c3035d79012d78ddaAnna Zaks RunPathSensitiveChecks(*WI, VisitedCallees); 4981f5171edc9fb9b0698a75fa981c29a750b0a6082Anna Zaks NumFunctionsAnalyzed++; 4991f5171edc9fb9b0698a75fa981c29a750b0a6082Anna Zaks } 500d655ab28fdf7c940d3f79f8f287954d7f76e0977Argyrios Kyrtzidis } 501f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek} 502f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek 503f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek//===----------------------------------------------------------------------===// 504d655ab28fdf7c940d3f79f8f287954d7f76e0977Argyrios Kyrtzidis// Path-sensitive checking. 505f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek//===----------------------------------------------------------------------===// 506f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek 5073fd5f370a28552976c52e76c3035d79012d78ddaAnna Zaksvoid AnalysisConsumer::ActionExprEngine(Decl *D, bool ObjCGCEnabled, 5086a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks SetOfConstDecls *VisitedCallees) { 509a5937bbfd19e61d651a58b0f0ffeef68457902a5Ted Kremenek // Construct the analysis engine. First check if the CFG is valid. 51075d03cffe20b5c945ef04eba208efb0437339997Ted Kremenek // FIXME: Inter-procedural analysis will need to handle invalid CFGs. 5113fd5f370a28552976c52e76c3035d79012d78ddaAnna Zaks if (!Mgr->getCFG(D)) 512f6eafcca7734274d277afa121f2c4fb025a54218Ted Kremenek return; 5133fd5f370a28552976c52e76c3035d79012d78ddaAnna Zaks 5143bbd8cd831788c506f2980293eb3c7e1b3ca2501Anna Zaks ExprEngine Eng(*Mgr, ObjCGCEnabled, VisitedCallees, &FunctionSummaries); 515f6eafcca7734274d277afa121f2c4fb025a54218Ted Kremenek 516f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek // Set the graph auditor. 5176f42b62b6194f53bcbc349f5d17388e1936535d7Dylan Noblesmith OwningPtr<ExplodedNode::Auditor> Auditor; 5183fd5f370a28552976c52e76c3035d79012d78ddaAnna Zaks if (Mgr->shouldVisualizeUbigraph()) { 519f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek Auditor.reset(CreateUbiViz()); 520c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu ExplodedNode::SetAuditor(Auditor.get()); 521f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek } 5221eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 523b35a74a40c1d2656a25e560e773ed48bdf49f9c0Ted Kremenek // Execute the worklist algorithm. 5243fd5f370a28552976c52e76c3035d79012d78ddaAnna Zaks Eng.ExecuteWorkList(Mgr->getAnalysisDeclContextManager().getStackFrame(D, 0), 5253fd5f370a28552976c52e76c3035d79012d78ddaAnna Zaks Mgr->getMaxNodes()); 5261eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 527f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek // Release the auditor (if any) so that it doesn't monitor the graph 528f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek // created BugReporter. 529c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu ExplodedNode::SetAuditor(0); 5303df6421150271266b5a90fd4c6bfa6566c38c036Ted Kremenek 53134d7734b6ed1d9c0f647405e065251eb67f42badTed Kremenek // Visualize the exploded graph. 5323fd5f370a28552976c52e76c3035d79012d78ddaAnna Zaks if (Mgr->shouldVisualizeGraphviz()) 5333fd5f370a28552976c52e76c3035d79012d78ddaAnna Zaks Eng.ViewGraph(Mgr->shouldTrimGraph()); 5341eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 5353df6421150271266b5a90fd4c6bfa6566c38c036Ted Kremenek // Display warnings. 5363df6421150271266b5a90fd4c6bfa6566c38c036Ted Kremenek Eng.getBugReporter().FlushReports(); 537bc46f345838b1c0d420dbd3655c94f5f360fb5b8Ted Kremenek} 538bc46f345838b1c0d420dbd3655c94f5f360fb5b8Ted Kremenek 5396a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaksvoid AnalysisConsumer::RunPathSensitiveChecks(Decl *D, 5406a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks SetOfConstDecls *Visited) { 54117a38e2636a8b1ce473fc6504c4b16cb09db29f4Jordy Rose 5424e4d08403ca5cfd4d558fa2936215d3a4e5a528dDavid Blaikie switch (Mgr->getLangOpts().getGC()) { 54317a38e2636a8b1ce473fc6504c4b16cb09db29f4Jordy Rose case LangOptions::NonGC: 5443fd5f370a28552976c52e76c3035d79012d78ddaAnna Zaks ActionExprEngine(D, false, Visited); 54517a38e2636a8b1ce473fc6504c4b16cb09db29f4Jordy Rose break; 54617a38e2636a8b1ce473fc6504c4b16cb09db29f4Jordy Rose 54717a38e2636a8b1ce473fc6504c4b16cb09db29f4Jordy Rose case LangOptions::GCOnly: 5483fd5f370a28552976c52e76c3035d79012d78ddaAnna Zaks ActionExprEngine(D, true, Visited); 54917a38e2636a8b1ce473fc6504c4b16cb09db29f4Jordy Rose break; 55017a38e2636a8b1ce473fc6504c4b16cb09db29f4Jordy Rose 55117a38e2636a8b1ce473fc6504c4b16cb09db29f4Jordy Rose case LangOptions::HybridGC: 5523fd5f370a28552976c52e76c3035d79012d78ddaAnna Zaks ActionExprEngine(D, false, Visited); 5533fd5f370a28552976c52e76c3035d79012d78ddaAnna Zaks ActionExprEngine(D, true, Visited); 55417a38e2636a8b1ce473fc6504c4b16cb09db29f4Jordy Rose break; 55517a38e2636a8b1ce473fc6504c4b16cb09db29f4Jordy Rose } 556b35a74a40c1d2656a25e560e773ed48bdf49f9c0Ted Kremenek} 557b35a74a40c1d2656a25e560e773ed48bdf49f9c0Ted Kremenek 558f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek//===----------------------------------------------------------------------===// 559f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek// AnalysisConsumer creation. 560f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek//===----------------------------------------------------------------------===// 561f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek 5629ef6537a894c33003359b1f9b9676e9178e028b7Ted KremenekASTConsumer* ento::CreateAnalysisConsumer(const Preprocessor& pp, 56308b86531ade68727c56918f162816075b87c864aJordy Rose const std::string& outDir, 56408b86531ade68727c56918f162816075b87c864aJordy Rose const AnalyzerOptions& opts, 56508b86531ade68727c56918f162816075b87c864aJordy Rose ArrayRef<std::string> plugins) { 56608b86531ade68727c56918f162816075b87c864aJordy Rose // Disable the effects of '-Werror' when using the AnalysisConsumer. 567efceabd2380f49306bc0229583458e93b062094bDaniel Dunbar pp.getDiagnostics().setWarningsAsErrors(false); 568be1fe1eb12a1cb91c8e3a9fcc2db4dfe989def6cTed Kremenek 56908b86531ade68727c56918f162816075b87c864aJordy Rose return new AnalysisConsumer(pp, outDir, opts, plugins); 570f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek} 571f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek 572f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek//===----------------------------------------------------------------------===// 573f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek// Ubigraph Visualization. FIXME: Move to separate file. 574f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek//===----------------------------------------------------------------------===// 575f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek 576f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremeneknamespace { 5771eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 578c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xuclass UbigraphViz : public ExplodedNode::Auditor { 5796f42b62b6194f53bcbc349f5d17388e1936535d7Dylan Noblesmith OwningPtr<raw_ostream> Out; 580710ad9343f32b33b336369b20edad1a21a0b3299Ted Kremenek llvm::sys::Path Dir, Filename; 581f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek unsigned Cntr; 582f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek 583f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek typedef llvm::DenseMap<void*,unsigned> VMap; 584f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek VMap M; 5851eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 586f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenekpublic: 5879c378f705405d37f49795d5e915989de774fe11fTed Kremenek UbigraphViz(raw_ostream *out, llvm::sys::Path& dir, 58856b98719b0dbebb33cb228afa888c47156be2381Ted Kremenek llvm::sys::Path& filename); 5891eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 590710ad9343f32b33b336369b20edad1a21a0b3299Ted Kremenek ~UbigraphViz(); 5911eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 5929c378f705405d37f49795d5e915989de774fe11fTed Kremenek virtual void AddEdge(ExplodedNode *Src, ExplodedNode *Dst); 593f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek}; 5941eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 595f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek} // end anonymous namespace 596f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek 597c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xustatic ExplodedNode::Auditor* CreateUbiViz() { 598f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek std::string ErrMsg; 5991eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 600710ad9343f32b33b336369b20edad1a21a0b3299Ted Kremenek llvm::sys::Path Dir = llvm::sys::Path::GetTemporaryDirectory(&ErrMsg); 601f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek if (!ErrMsg.empty()) 602f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek return 0; 603f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek 604710ad9343f32b33b336369b20edad1a21a0b3299Ted Kremenek llvm::sys::Path Filename = Dir; 605f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek Filename.appendComponent("llvm_ubi"); 606f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek Filename.makeUnique(true,&ErrMsg); 607f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek 608f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek if (!ErrMsg.empty()) 609f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek return 0; 610f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek 611d57a7ef9252964bc6c8471451d7bd395b0520cb8Chris Lattner llvm::errs() << "Writing '" << Filename.str() << "'.\n"; 6121eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 6136f42b62b6194f53bcbc349f5d17388e1936535d7Dylan Noblesmith OwningPtr<llvm::raw_fd_ostream> Stream; 614b044c473a155b7e827680635c1699cb2b5b6c0eeDan Gohman Stream.reset(new llvm::raw_fd_ostream(Filename.c_str(), ErrMsg)); 615f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek 616f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek if (!ErrMsg.empty()) 617f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek return 0; 6181eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 619710ad9343f32b33b336369b20edad1a21a0b3299Ted Kremenek return new UbigraphViz(Stream.take(), Dir, Filename); 620f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek} 621f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek 6229c378f705405d37f49795d5e915989de774fe11fTed Kremenekvoid UbigraphViz::AddEdge(ExplodedNode *Src, ExplodedNode *Dst) { 6231eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 62445479c88c8a44c55d27c3bd855273bb318082f37Ted Kremenek assert (Src != Dst && "Self-edges are not allowed."); 6251eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 626f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek // Lookup the Src. If it is a new node, it's a root. 627f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek VMap::iterator SrcI= M.find(Src); 628f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek unsigned SrcID; 6291eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 630f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek if (SrcI == M.end()) { 631f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek M[Src] = SrcID = Cntr++; 632f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek *Out << "('vertex', " << SrcID << ", ('color','#00ff00'))\n"; 633f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek } 634f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek else 635f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek SrcID = SrcI->second; 6361eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 637f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek // Lookup the Dst. 638f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek VMap::iterator DstI= M.find(Dst); 639f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek unsigned DstID; 640f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek 641f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek if (DstI == M.end()) { 642f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek M[Dst] = DstID = Cntr++; 643f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek *Out << "('vertex', " << DstID << ")\n"; 644f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek } 64556b98719b0dbebb33cb228afa888c47156be2381Ted Kremenek else { 64656b98719b0dbebb33cb228afa888c47156be2381Ted Kremenek // We have hit DstID before. Change its style to reflect a cache hit. 647f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek DstID = DstI->second; 64856b98719b0dbebb33cb228afa888c47156be2381Ted Kremenek *Out << "('change_vertex_style', " << DstID << ", 1)\n"; 64956b98719b0dbebb33cb228afa888c47156be2381Ted Kremenek } 650f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek 651f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek // Add the edge. 6521eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump *Out << "('edge', " << SrcID << ", " << DstID 653d1289327f7d2126d732e23cc189ecd0aa5d07cbbTed Kremenek << ", ('arrow','true'), ('oriented', 'true'))\n"; 654f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek} 655f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek 6569c378f705405d37f49795d5e915989de774fe11fTed KremenekUbigraphViz::UbigraphViz(raw_ostream *out, llvm::sys::Path& dir, 65756b98719b0dbebb33cb228afa888c47156be2381Ted Kremenek llvm::sys::Path& filename) 65856b98719b0dbebb33cb228afa888c47156be2381Ted Kremenek : Out(out), Dir(dir), Filename(filename), Cntr(0) { 65956b98719b0dbebb33cb228afa888c47156be2381Ted Kremenek 66056b98719b0dbebb33cb228afa888c47156be2381Ted Kremenek *Out << "('vertex_style_attribute', 0, ('shape', 'icosahedron'))\n"; 66156b98719b0dbebb33cb228afa888c47156be2381Ted Kremenek *Out << "('vertex_style', 1, 0, ('shape', 'sphere'), ('color', '#ffcc66')," 66256b98719b0dbebb33cb228afa888c47156be2381Ted Kremenek " ('size', '1.5'))\n"; 66356b98719b0dbebb33cb228afa888c47156be2381Ted Kremenek} 66456b98719b0dbebb33cb228afa888c47156be2381Ted Kremenek 665710ad9343f32b33b336369b20edad1a21a0b3299Ted KremenekUbigraphViz::~UbigraphViz() { 666710ad9343f32b33b336369b20edad1a21a0b3299Ted Kremenek Out.reset(0); 6676cb7c1a43b0c8f739d1f54b7fdae5ede86033496Benjamin Kramer llvm::errs() << "Running 'ubiviz' program... "; 668710ad9343f32b33b336369b20edad1a21a0b3299Ted Kremenek std::string ErrMsg; 669710ad9343f32b33b336369b20edad1a21a0b3299Ted Kremenek llvm::sys::Path Ubiviz = llvm::sys::Program::FindProgramByName("ubiviz"); 670710ad9343f32b33b336369b20edad1a21a0b3299Ted Kremenek std::vector<const char*> args; 671710ad9343f32b33b336369b20edad1a21a0b3299Ted Kremenek args.push_back(Ubiviz.c_str()); 672710ad9343f32b33b336369b20edad1a21a0b3299Ted Kremenek args.push_back(Filename.c_str()); 673710ad9343f32b33b336369b20edad1a21a0b3299Ted Kremenek args.push_back(0); 6741eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 675710ad9343f32b33b336369b20edad1a21a0b3299Ted Kremenek if (llvm::sys::Program::ExecuteAndWait(Ubiviz, &args[0],0,0,0,0,&ErrMsg)) { 6766cb7c1a43b0c8f739d1f54b7fdae5ede86033496Benjamin Kramer llvm::errs() << "Error viewing graph: " << ErrMsg << "\n"; 677710ad9343f32b33b336369b20edad1a21a0b3299Ted Kremenek } 6781eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 679710ad9343f32b33b336369b20edad1a21a0b3299Ted Kremenek // Delete the directory. 6801eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump Dir.eraseFromDisk(true); 681932680ecdeab4c216ce7c0736093d3dcd2f60f6dDaniel Dunbar} 682