AnalysisConsumer.cpp revision 84c1f4b1edddf74f8080cfc470796c2c498b5d43
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" 25371b477836f289f2e9caaab58530f187b51bc86dTed Kremenek#include "clang/Analysis/Analyses/LiveVariables.h" 2627af04bcca46f8a3374586be1301477f9123f5e1Argyrios Kyrtzidis#include "clang/StaticAnalyzer/Frontend/CheckerRegistration.h" 2743dee220252ef0b42c5f8a3bb1eca97f84f2565fArgyrios Kyrtzidis#include "clang/StaticAnalyzer/Core/CheckerManager.h" 2821142581d55918beed544a757e4af3bb865b1812Ted Kremenek#include "clang/StaticAnalyzer/Checkers/LocalCheckers.h" 299b663716449b618ba0390b1dbebc54fa8e971124Ted Kremenek#include "clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h" 309b663716449b618ba0390b1dbebc54fa8e971124Ted Kremenek#include "clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h" 319b663716449b618ba0390b1dbebc54fa8e971124Ted Kremenek#include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h" 329b663716449b618ba0390b1dbebc54fa8e971124Ted Kremenek#include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h" 33f39d962cf84f46d2c0512157259ae1d41a1a5173David Blaikie#include "clang/StaticAnalyzer/Core/PathDiagnosticConsumers.h" 34a7af5ea88a6c5bdf87497cca6c20831e8c546751Argyrios Kyrtzidis 35efceabd2380f49306bc0229583458e93b062094bDaniel Dunbar#include "clang/Basic/FileManager.h" 36efceabd2380f49306bc0229583458e93b062094bDaniel Dunbar#include "clang/Basic/SourceManager.h" 379b414d3e2d0cb84512b55a3275a98490b090162aDaniel Dunbar#include "clang/Frontend/AnalyzerOptions.h" 38efceabd2380f49306bc0229583458e93b062094bDaniel Dunbar#include "clang/Lex/Preprocessor.h" 39f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek#include "llvm/Support/raw_ostream.h" 4003013fa9a0bf1ef4b907f5fec006c8f4000fdd21Michael J. Spencer#include "llvm/Support/Path.h" 4103013fa9a0bf1ef4b907f5fec006c8f4000fdd21Michael J. Spencer#include "llvm/Support/Program.h" 42d38f79543136ba68cd14b1dab0856474df1fbfd5Anna Zaks#include "llvm/Support/Timer.h" 43d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks#include "llvm/ADT/DepthFirstIterator.h" 446cb7c1a43b0c8f739d1f54b7fdae5ede86033496Benjamin Kramer#include "llvm/ADT/OwningPtr.h" 456a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks#include "llvm/ADT/SmallPtrSet.h" 4681fb169f42769e02c7425b23885a261c025fd5e6Anna Zaks#include "llvm/ADT/Statistic.h" 47db09a4dee28a4515438af60f2d2b4a83e4965c31Ted Kremenek 487fe8dcef71ae56e43fd7df345db2895f84f2d0caAnna Zaks#include <queue> 497fe8dcef71ae56e43fd7df345db2895f84f2d0caAnna Zaks 50f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenekusing namespace clang; 519ef6537a894c33003359b1f9b9676e9178e028b7Ted Kremenekusing namespace ento; 52d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaksusing llvm::SmallPtrSet; 53f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek 54c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xustatic ExplodedNode::Auditor* CreateUbiViz(); 55ff944a8c481d6c0f1ad2633e4be9bf8b1dd2a09fZhongxing Xu 563fd5f370a28552976c52e76c3035d79012d78ddaAnna ZaksSTATISTIC(NumFunctionTopLevel, "The # of functions at top level."); 57d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna ZaksSTATISTIC(NumFunctionsAnalyzed, "The # of functions analysed (as top level)."); 58e62f048960645b79363408fdead53fec2a063c52Anna ZaksSTATISTIC(NumBlocksInAnalyzedFunctions, 59e62f048960645b79363408fdead53fec2a063c52Anna Zaks "The # of basic blocks in the analyzed functions."); 60e62f048960645b79363408fdead53fec2a063c52Anna ZaksSTATISTIC(PercentReachableBlocks, "The % of reachable basic blocks."); 6184c1f4b1edddf74f8080cfc470796c2c498b5d43Anna ZaksSTATISTIC(MaxCFGSize, "The maximum number of basic blocks in a function."); 62d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks 63be1fe1eb12a1cb91c8e3a9fcc2db4dfe989def6cTed Kremenek//===----------------------------------------------------------------------===// 64f39d962cf84f46d2c0512157259ae1d41a1a5173David Blaikie// Special PathDiagnosticConsumers. 65f75560670bcdd59b051149bdece3eac14e313853Ted Kremenek//===----------------------------------------------------------------------===// 66f75560670bcdd59b051149bdece3eac14e313853Ted Kremenek 67ef3643fbbbf66247c5e205497fae0f46e240c143David Blaikiestatic PathDiagnosticConsumer* 68ef3643fbbbf66247c5e205497fae0f46e240c143David BlaikiecreatePlistHTMLDiagnosticConsumer(const std::string& prefix, 69efceabd2380f49306bc0229583458e93b062094bDaniel Dunbar const Preprocessor &PP) { 70ef3643fbbbf66247c5e205497fae0f46e240c143David Blaikie PathDiagnosticConsumer *PD = 71ef3643fbbbf66247c5e205497fae0f46e240c143David Blaikie createHTMLDiagnosticConsumer(llvm::sys::path::parent_path(prefix), PP); 72ef3643fbbbf66247c5e205497fae0f46e240c143David Blaikie return createPlistDiagnosticConsumer(prefix, PP, PD); 73f75560670bcdd59b051149bdece3eac14e313853Ted Kremenek} 74f75560670bcdd59b051149bdece3eac14e313853Ted Kremenek 75f75560670bcdd59b051149bdece3eac14e313853Ted Kremenek//===----------------------------------------------------------------------===// 76f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek// AnalysisConsumer declaration. 77f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek//===----------------------------------------------------------------------===// 78f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek 79f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremeneknamespace { 80f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek 81aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaksclass AnalysisConsumer : public ASTConsumer, 82aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks public RecursiveASTVisitor<AnalysisConsumer> { 83aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks enum AnalysisMode { 84aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks ANALYSIS_SYNTAX, 85aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks ANALYSIS_PATH, 86aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks ANALYSIS_ALL 87aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks }; 88aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks 89aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks /// Mode of the analyzes while recursively visiting Decls. 90aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks AnalysisMode RecVisitorMode; 91aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks /// Bug Reporter to use while recursively visiting Decls. 92aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks BugReporter *RecVisitorBR; 93aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks 94ed8afacb8118b71bcfa8017059e51da325e7691bZhongxing Xupublic: 959c378f705405d37f49795d5e915989de774fe11fTed Kremenek ASTContext *Ctx; 961d9cbeb76cf4c36acf5545028e2b2ac207086442Ted Kremenek const Preprocessor &PP; 971d9cbeb76cf4c36acf5545028e2b2ac207086442Ted Kremenek const std::string OutDir; 981d9cbeb76cf4c36acf5545028e2b2ac207086442Ted Kremenek AnalyzerOptions Opts; 9908b86531ade68727c56918f162816075b87c864aJordy Rose ArrayRef<std::string> Plugins; 100d07a0d0279c09d1017f8450fce575a94dc9703c0Zhongxing Xu 1016a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks /// \brief Stores the declarations from the local translation unit. 1026a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks /// Note, we pre-compute the local declarations at parse time as an 1036a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks /// optimization to make sure we do not deserialize everything from disk. 1046a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks /// The local declaration to all declarations ratio might be very small when 1056a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks /// working with a PCH file. 1066a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks SetOfDecls LocalTUDecls; 107cb0a5039c243f5b0c178e70f424adac334e5789bTed Kremenek 1081d9cbeb76cf4c36acf5545028e2b2ac207086442Ted Kremenek // PD is owned by AnalysisManager. 109ef3643fbbbf66247c5e205497fae0f46e240c143David Blaikie PathDiagnosticConsumer *PD; 110d07a0d0279c09d1017f8450fce575a94dc9703c0Zhongxing Xu 1111d9cbeb76cf4c36acf5545028e2b2ac207086442Ted Kremenek StoreManagerCreator CreateStoreMgr; 1121d9cbeb76cf4c36acf5545028e2b2ac207086442Ted Kremenek ConstraintManagerCreator CreateConstraintMgr; 113f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek 1146f42b62b6194f53bcbc349f5d17388e1936535d7Dylan Noblesmith OwningPtr<CheckerManager> checkerMgr; 1156f42b62b6194f53bcbc349f5d17388e1936535d7Dylan Noblesmith OwningPtr<AnalysisManager> Mgr; 116c471e7b44e63ff1b46b480e723c4130aeaef5a8aZhongxing Xu 117d38f79543136ba68cd14b1dab0856474df1fbfd5Anna Zaks /// Time the analyzes time of each translation unit. 118d38f79543136ba68cd14b1dab0856474df1fbfd5Anna Zaks static llvm::Timer* TUTotalTimer; 119d38f79543136ba68cd14b1dab0856474df1fbfd5Anna Zaks 1203bbd8cd831788c506f2980293eb3c7e1b3ca2501Anna Zaks /// The information about analyzed functions shared throughout the 1213bbd8cd831788c506f2980293eb3c7e1b3ca2501Anna Zaks /// translation unit. 1223bbd8cd831788c506f2980293eb3c7e1b3ca2501Anna Zaks FunctionSummariesTy FunctionSummaries; 1233bbd8cd831788c506f2980293eb3c7e1b3ca2501Anna Zaks 1241d9cbeb76cf4c36acf5545028e2b2ac207086442Ted Kremenek AnalysisConsumer(const Preprocessor& pp, 1251d9cbeb76cf4c36acf5545028e2b2ac207086442Ted Kremenek const std::string& outdir, 12608b86531ade68727c56918f162816075b87c864aJordy Rose const AnalyzerOptions& opts, 12708b86531ade68727c56918f162816075b87c864aJordy Rose ArrayRef<std::string> plugins) 128aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks : RecVisitorMode(ANALYSIS_ALL), RecVisitorBR(0), 129aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks Ctx(0), PP(pp), OutDir(outdir), Opts(opts), Plugins(plugins), PD(0) { 1301d9cbeb76cf4c36acf5545028e2b2ac207086442Ted Kremenek DigestAnalyzerOptions(); 131d38f79543136ba68cd14b1dab0856474df1fbfd5Anna Zaks if (Opts.PrintStats) { 132d38f79543136ba68cd14b1dab0856474df1fbfd5Anna Zaks llvm::EnableStatistics(); 133d38f79543136ba68cd14b1dab0856474df1fbfd5Anna Zaks TUTotalTimer = new llvm::Timer("Analyzer Total Time"); 134d38f79543136ba68cd14b1dab0856474df1fbfd5Anna Zaks } 135d38f79543136ba68cd14b1dab0856474df1fbfd5Anna Zaks } 136d38f79543136ba68cd14b1dab0856474df1fbfd5Anna Zaks 137d38f79543136ba68cd14b1dab0856474df1fbfd5Anna Zaks ~AnalysisConsumer() { 138d38f79543136ba68cd14b1dab0856474df1fbfd5Anna Zaks if (Opts.PrintStats) 139d38f79543136ba68cd14b1dab0856474df1fbfd5Anna Zaks delete TUTotalTimer; 1401d9cbeb76cf4c36acf5545028e2b2ac207086442Ted Kremenek } 141fda7832b000ff8927386f093b52c067641679469Zhongxing Xu 1421d9cbeb76cf4c36acf5545028e2b2ac207086442Ted Kremenek void DigestAnalyzerOptions() { 143ef3643fbbbf66247c5e205497fae0f46e240c143David Blaikie // Create the PathDiagnosticConsumer. 1441d9cbeb76cf4c36acf5545028e2b2ac207086442Ted Kremenek if (!OutDir.empty()) { 1451d9cbeb76cf4c36acf5545028e2b2ac207086442Ted Kremenek switch (Opts.AnalysisDiagOpt) { 1461d9cbeb76cf4c36acf5545028e2b2ac207086442Ted Kremenek default: 147fda7832b000ff8927386f093b52c067641679469Zhongxing Xu#define ANALYSIS_DIAGNOSTICS(NAME, CMDFLAG, DESC, CREATEFN, AUTOCREATE) \ 1481d9cbeb76cf4c36acf5545028e2b2ac207086442Ted Kremenek case PD_##NAME: PD = CREATEFN(OutDir, PP); break; 149fda7832b000ff8927386f093b52c067641679469Zhongxing Xu#include "clang/Frontend/Analyses.def" 150fda7832b000ff8927386f093b52c067641679469Zhongxing Xu } 151a599ae8826b01c0160a519b0fc5a4871f599bf04Argyrios Kyrtzidis } else if (Opts.AnalysisDiagOpt == PD_TEXT) { 152a599ae8826b01c0160a519b0fc5a4871f599bf04Argyrios Kyrtzidis // Create the text client even without a specified output file since 153a599ae8826b01c0160a519b0fc5a4871f599bf04Argyrios Kyrtzidis // it just uses diagnostic notes. 154ef3643fbbbf66247c5e205497fae0f46e240c143David Blaikie PD = createTextPathDiagnosticConsumer("", PP); 1551d9cbeb76cf4c36acf5545028e2b2ac207086442Ted Kremenek } 156fda7832b000ff8927386f093b52c067641679469Zhongxing Xu 1571d9cbeb76cf4c36acf5545028e2b2ac207086442Ted Kremenek // Create the analyzer component creators. 1585f83d6f36a7308eef21d87104fd70c421e854448Argyrios Kyrtzidis switch (Opts.AnalysisStoreOpt) { 1595f83d6f36a7308eef21d87104fd70c421e854448Argyrios Kyrtzidis default: 160b219cfc4d75f0a03630b7c4509ef791b7e97b2c8David Blaikie llvm_unreachable("Unknown store manager."); 161fda7832b000ff8927386f093b52c067641679469Zhongxing Xu#define ANALYSIS_STORE(NAME, CMDFLAG, DESC, CREATEFN) \ 1625f83d6f36a7308eef21d87104fd70c421e854448Argyrios Kyrtzidis case NAME##Model: CreateStoreMgr = CREATEFN; break; 163fda7832b000ff8927386f093b52c067641679469Zhongxing Xu#include "clang/Frontend/Analyses.def" 1641d9cbeb76cf4c36acf5545028e2b2ac207086442Ted Kremenek } 1651eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1665f83d6f36a7308eef21d87104fd70c421e854448Argyrios Kyrtzidis switch (Opts.AnalysisConstraintsOpt) { 1675f83d6f36a7308eef21d87104fd70c421e854448Argyrios Kyrtzidis default: 168b219cfc4d75f0a03630b7c4509ef791b7e97b2c8David Blaikie llvm_unreachable("Unknown store manager."); 169fda7832b000ff8927386f093b52c067641679469Zhongxing Xu#define ANALYSIS_CONSTRAINTS(NAME, CMDFLAG, DESC, CREATEFN) \ 1705f83d6f36a7308eef21d87104fd70c421e854448Argyrios Kyrtzidis case NAME##Model: CreateConstraintMgr = CREATEFN; break; 171fda7832b000ff8927386f093b52c067641679469Zhongxing Xu#include "clang/Frontend/Analyses.def" 172fda7832b000ff8927386f093b52c067641679469Zhongxing Xu } 1731d9cbeb76cf4c36acf5545028e2b2ac207086442Ted Kremenek } 174f6eafcca7734274d277afa121f2c4fb025a54218Ted Kremenek 175aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks void DisplayFunction(const Decl *D, AnalysisMode Mode) { 176c4a1437c15da43eb8d2601cdce13161ef41a4389Ted Kremenek if (!Opts.AnalyzerDisplayProgress) 1771d9cbeb76cf4c36acf5545028e2b2ac207086442Ted Kremenek return; 178f6eafcca7734274d277afa121f2c4fb025a54218Ted Kremenek 179fc576514d06c46a7cac49500169411d82f38d04bTed Kremenek SourceManager &SM = Mgr->getASTContext().getSourceManager(); 180fc576514d06c46a7cac49500169411d82f38d04bTed Kremenek PresumedLoc Loc = SM.getPresumedLoc(D->getLocation()); 181cb7b1e17b63967317ab5cc55682168cf0380519aDouglas Gregor if (Loc.isValid()) { 182aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks llvm::errs() << "ANALYZE"; 183aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks switch (Mode) { 184aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks case ANALYSIS_SYNTAX: llvm::errs() << "(Syntax)"; break; 185aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks case ANALYSIS_PATH: llvm::errs() << "(Path Sensitive)"; break; 186aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks case ANALYSIS_ALL: break; 187aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks }; 188aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks llvm::errs() << ": " << Loc.getFilename(); 189cb7b1e17b63967317ab5cc55682168cf0380519aDouglas Gregor if (isa<FunctionDecl>(D) || isa<ObjCMethodDecl>(D)) { 190cb7b1e17b63967317ab5cc55682168cf0380519aDouglas Gregor const NamedDecl *ND = cast<NamedDecl>(D); 191b8989f27f116ff2400e92a52c067a69846119eb5Benjamin Kramer llvm::errs() << ' ' << *ND << '\n'; 192cb7b1e17b63967317ab5cc55682168cf0380519aDouglas Gregor } 193cb7b1e17b63967317ab5cc55682168cf0380519aDouglas Gregor else if (isa<BlockDecl>(D)) { 194cb7b1e17b63967317ab5cc55682168cf0380519aDouglas Gregor llvm::errs() << ' ' << "block(line:" << Loc.getLine() << ",col:" 195cb7b1e17b63967317ab5cc55682168cf0380519aDouglas Gregor << Loc.getColumn() << '\n'; 196cb7b1e17b63967317ab5cc55682168cf0380519aDouglas Gregor } 197cb7b1e17b63967317ab5cc55682168cf0380519aDouglas Gregor else if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D)) { 198cb7b1e17b63967317ab5cc55682168cf0380519aDouglas Gregor Selector S = MD->getSelector(); 199cb7b1e17b63967317ab5cc55682168cf0380519aDouglas Gregor llvm::errs() << ' ' << S.getAsString(); 200cb7b1e17b63967317ab5cc55682168cf0380519aDouglas Gregor } 20135fa76d0bb6fb8c86159a7506efd094a4fe376d2Ted Kremenek } 2021d9cbeb76cf4c36acf5545028e2b2ac207086442Ted Kremenek } 2031eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 2041d9cbeb76cf4c36acf5545028e2b2ac207086442Ted Kremenek virtual void Initialize(ASTContext &Context) { 2051d9cbeb76cf4c36acf5545028e2b2ac207086442Ted Kremenek Ctx = &Context; 2064e4d08403ca5cfd4d558fa2936215d3a4e5a528dDavid Blaikie checkerMgr.reset(createCheckerManager(Opts, PP.getLangOpts(), Plugins, 20708b86531ade68727c56918f162816075b87c864aJordy Rose PP.getDiagnostics())); 2081d9cbeb76cf4c36acf5545028e2b2ac207086442Ted Kremenek Mgr.reset(new AnalysisManager(*Ctx, PP.getDiagnostics(), 2094e4d08403ca5cfd4d558fa2936215d3a4e5a528dDavid Blaikie PP.getLangOpts(), PD, 2101d9cbeb76cf4c36acf5545028e2b2ac207086442Ted Kremenek CreateStoreMgr, CreateConstraintMgr, 21143dee220252ef0b42c5f8a3bb1eca97f84f2565fArgyrios Kyrtzidis checkerMgr.get(), 2126362b893731ccf4480a96527db9e55e04b801503Zhongxing Xu Opts.MaxNodes, Opts.MaxLoop, 2131d9cbeb76cf4c36acf5545028e2b2ac207086442Ted Kremenek Opts.VisualizeEGDot, Opts.VisualizeEGUbi, 214d30952838421ddfb9f7e346b2ba8213889a5f789Anna Zaks Opts.AnalysisPurgeOpt, Opts.EagerlyAssume, 21566253352131e3e7a22b3bfd0e180607aa2bfb988Anna Zaks Opts.TrimGraph, 2169121ba232903ebe61e7bbe14ca294cf0f07dfa96Marcin Swiderski Opts.UnoptimizedCFG, Opts.CFGAddImplicitDtors, 217d767d81290288c030f3be0be1d3e62b9c8df51dcTed Kremenek Opts.CFGAddInitializers, 2188235f9c9c8b3d1737d1c6bd57f7ba3f616b92392Anna Zaks Opts.EagerlyTrimEGraph, 21966253352131e3e7a22b3bfd0e180607aa2bfb988Anna Zaks Opts.IPAMode, 2208235f9c9c8b3d1737d1c6bd57f7ba3f616b92392Anna Zaks Opts.InlineMaxStackDepth, 22166253352131e3e7a22b3bfd0e180607aa2bfb988Anna Zaks Opts.InlineMaxFunctionSize, 2225903a373db3d27794c90b25687e0dd6adb0e497dAnna Zaks Opts.InliningMode, 223b47dbcbc12430fdf3e5a5b9f59cdec5480e89e75Anna Zaks Opts.NoRetryExhausted)); 2241d9cbeb76cf4c36acf5545028e2b2ac207086442Ted Kremenek } 2251eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 2266a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks /// \brief Store the top level decls in the set to be processed later on. 2276a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks /// (Doing this pre-processing avoids deserialization of data from PCH.) 2286a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks virtual bool HandleTopLevelDecl(DeclGroupRef D); 2296a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks virtual void HandleTopLevelDeclInObjCContainer(DeclGroupRef D); 2306a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks 2311d9cbeb76cf4c36acf5545028e2b2ac207086442Ted Kremenek virtual void HandleTranslationUnit(ASTContext &C); 23214cc9451de4a9539bf79e4e5d63248c2377426dbTed Kremenek 2336a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks /// \brief Build the call graph for all the top level decls of this TU and 2346a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks /// use it to define the order in which the functions should be visited. 235694a942b0a14e02757a695142c45437eec6e3684Anna Zaks void HandleDeclsGallGraph(const unsigned LocalTUDeclsSize); 236aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks 237aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks /// \brief Run analyzes(syntax or path sensitive) on the given function. 238aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks /// \param Mode - determines if we are requesting syntax only or path 239aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks /// sensitive only analysis. 240aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks /// \param VisitedCallees - The output parameter, which is populated with the 241aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks /// set of functions which should be considered analyzed after analyzing the 242aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks /// given root function. 2436a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks void HandleCode(Decl *D, AnalysisMode Mode, 2446a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks SetOfConstDecls *VisitedCallees = 0); 245aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks 2466a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks void RunPathSensitiveChecks(Decl *D, SetOfConstDecls *VisitedCallees); 2476a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks void ActionExprEngine(Decl *D, bool ObjCGCEnabled, 2486a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks SetOfConstDecls *VisitedCallees); 249aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks 250aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks /// Visitors for the RecursiveASTVisitor. 251c8848f34bbde083b8d89f445eb605eaabf30d6a8Anna Zaks bool shouldWalkTypesOfTypeLocs() const { return false; } 252aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks 253aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks /// Handle callbacks for arbitrary Decls. 254aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks bool VisitDecl(Decl *D) { 255aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks checkerMgr->runCheckersOnASTDecl(D, *Mgr, *RecVisitorBR); 256aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks return true; 257aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks } 258aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks 259aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks bool VisitFunctionDecl(FunctionDecl *FD) { 260aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks IdentifierInfo *II = FD->getIdentifier(); 261aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks if (II && II->getName().startswith("__inline")) 262aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks return true; 263aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks 264aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks // We skip function template definitions, as their semantics is 265aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks // only determined when they are instantiated. 266aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks if (FD->isThisDeclarationADefinition() && 267aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks !FD->isDependentContext()) { 268aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks HandleCode(FD, RecVisitorMode); 269aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks } 270aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks return true; 271aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks } 272aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks 273aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks bool VisitObjCMethodDecl(ObjCMethodDecl *MD) { 274aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks checkerMgr->runCheckersOnASTDecl(MD, *Mgr, *RecVisitorBR); 275aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks if (MD->isThisDeclarationADefinition()) 276aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks HandleCode(MD, RecVisitorMode); 277aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks return true; 278aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks } 2796a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks 2806a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaksprivate: 2816a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks void storeTopLevelDecls(DeclGroupRef DG); 2826a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks 2836a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks /// \brief Check if we should skip (not analyze) the given function. 2846a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks bool skipFunction(Decl *D); 2856a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks 2861d9cbeb76cf4c36acf5545028e2b2ac207086442Ted Kremenek}; 287f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek} // end anonymous namespace 288f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek 289aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks 290f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek//===----------------------------------------------------------------------===// 291f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek// AnalysisConsumer implementation. 292f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek//===----------------------------------------------------------------------===// 293d38f79543136ba68cd14b1dab0856474df1fbfd5Anna Zaksllvm::Timer* AnalysisConsumer::TUTotalTimer = 0; 294f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek 2956a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaksbool AnalysisConsumer::HandleTopLevelDecl(DeclGroupRef DG) { 2966a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks storeTopLevelDecls(DG); 2976a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks return true; 2986a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks} 2996a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks 3006a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaksvoid AnalysisConsumer::HandleTopLevelDeclInObjCContainer(DeclGroupRef DG) { 3016a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks storeTopLevelDecls(DG); 3026a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks} 3036a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks 3046a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaksvoid AnalysisConsumer::storeTopLevelDecls(DeclGroupRef DG) { 3056a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks for (DeclGroupRef::iterator I = DG.begin(), E = DG.end(); I != E; ++I) { 3066a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks 3076a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks // Skip ObjCMethodDecl, wait for the objc container to avoid 3086a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks // analyzing twice. 3096a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks if (isa<ObjCMethodDecl>(*I)) 3106a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks continue; 3116a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks 312577f14a34457032523e59dbbbacb88ca2cd4db57Ted Kremenek LocalTUDecls.push_back(*I); 3136a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks } 3146a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks} 3156a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks 316694a942b0a14e02757a695142c45437eec6e3684Anna Zaksvoid AnalysisConsumer::HandleDeclsGallGraph(const unsigned LocalTUDeclsSize) { 317d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks // Otherwise, use the Callgraph to derive the order. 318d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks // Build the Call Graph. 319d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks CallGraph CG; 320eaa069075f060f58840af03e0bd5bd75bb27e809Anna Zaks 3216a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks // Add all the top level declarations to the graph. 322694a942b0a14e02757a695142c45437eec6e3684Anna Zaks // Note: CallGraph can trigger deserialization of more items from a pch 323694a942b0a14e02757a695142c45437eec6e3684Anna Zaks // (though HandleInterestingDecl); triggering additions to LocalTUDecls. 324694a942b0a14e02757a695142c45437eec6e3684Anna Zaks // We rely on random access to add the initially processed Decls to CG. 325694a942b0a14e02757a695142c45437eec6e3684Anna Zaks for (unsigned i = 0 ; i < LocalTUDeclsSize ; ++i) { 326eaa069075f060f58840af03e0bd5bd75bb27e809Anna Zaks CG.addToCallGraph(LocalTUDecls[i]); 327eaa069075f060f58840af03e0bd5bd75bb27e809Anna Zaks } 328d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks 329d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks // Find the top level nodes - children of root + the unreachable (parentless) 330d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks // nodes. 3313fd5f370a28552976c52e76c3035d79012d78ddaAnna Zaks llvm::SmallVector<CallGraphNode*, 24> TopLevelFunctions; 332b990d039c7e01ad0055dcbd1e13a691813397b96Anna Zaks for (CallGraph::nodes_iterator TI = CG.parentless_begin(), 333b990d039c7e01ad0055dcbd1e13a691813397b96Anna Zaks TE = CG.parentless_end(); TI != TE; ++TI) { 334b990d039c7e01ad0055dcbd1e13a691813397b96Anna Zaks TopLevelFunctions.push_back(*TI); 335b990d039c7e01ad0055dcbd1e13a691813397b96Anna Zaks NumFunctionTopLevel++; 336b990d039c7e01ad0055dcbd1e13a691813397b96Anna Zaks } 337d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks CallGraphNode *Entry = CG.getRoot(); 338d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks for (CallGraphNode::iterator I = Entry->begin(), 3393fd5f370a28552976c52e76c3035d79012d78ddaAnna Zaks E = Entry->end(); I != E; ++I) { 340d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks TopLevelFunctions.push_back(*I); 3413fd5f370a28552976c52e76c3035d79012d78ddaAnna Zaks NumFunctionTopLevel++; 3423fd5f370a28552976c52e76c3035d79012d78ddaAnna Zaks } 343d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks 344b990d039c7e01ad0055dcbd1e13a691813397b96Anna Zaks // Make sure the nodes are sorted in order reverse of their definition in the 345b990d039c7e01ad0055dcbd1e13a691813397b96Anna Zaks // translation unit. This step is very important for performance. It ensures 346b990d039c7e01ad0055dcbd1e13a691813397b96Anna Zaks // that we analyze the root functions before the externally available 347b990d039c7e01ad0055dcbd1e13a691813397b96Anna Zaks // subroutines. 348cb0a5039c243f5b0c178e70f424adac334e5789bTed Kremenek std::deque<CallGraphNode*> BFSQueue; 349b990d039c7e01ad0055dcbd1e13a691813397b96Anna Zaks for (llvm::SmallVector<CallGraphNode*, 24>::reverse_iterator 350b990d039c7e01ad0055dcbd1e13a691813397b96Anna Zaks TI = TopLevelFunctions.rbegin(), TE = TopLevelFunctions.rend(); 3517fe8dcef71ae56e43fd7df345db2895f84f2d0caAnna Zaks TI != TE; ++TI) 352371b477836f289f2e9caaab58530f187b51bc86dTed Kremenek BFSQueue.push_back(*TI); 353d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks 3547fe8dcef71ae56e43fd7df345db2895f84f2d0caAnna Zaks // BFS over all of the functions, while skipping the ones inlined into 3557fe8dcef71ae56e43fd7df345db2895f84f2d0caAnna Zaks // the previously processed functions. Use external Visited set, which is 356d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks // also modified when we inline a function. 357d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks SmallPtrSet<CallGraphNode*,24> Visited; 3587fe8dcef71ae56e43fd7df345db2895f84f2d0caAnna Zaks while(!BFSQueue.empty()) { 3597fe8dcef71ae56e43fd7df345db2895f84f2d0caAnna Zaks CallGraphNode *N = BFSQueue.front(); 360cb0a5039c243f5b0c178e70f424adac334e5789bTed Kremenek BFSQueue.pop_front(); 3617fe8dcef71ae56e43fd7df345db2895f84f2d0caAnna Zaks 362371b477836f289f2e9caaab58530f187b51bc86dTed Kremenek // Push the children into the queue. 363371b477836f289f2e9caaab58530f187b51bc86dTed Kremenek for (CallGraphNode::const_iterator CI = N->begin(), 364371b477836f289f2e9caaab58530f187b51bc86dTed Kremenek CE = N->end(); CI != CE; ++CI) { 365371b477836f289f2e9caaab58530f187b51bc86dTed Kremenek if (!Visited.count(*CI)) 366371b477836f289f2e9caaab58530f187b51bc86dTed Kremenek BFSQueue.push_back(*CI); 367371b477836f289f2e9caaab58530f187b51bc86dTed Kremenek } 368371b477836f289f2e9caaab58530f187b51bc86dTed Kremenek 3697fe8dcef71ae56e43fd7df345db2895f84f2d0caAnna Zaks // Skip the functions which have been processed already or previously 3707fe8dcef71ae56e43fd7df345db2895f84f2d0caAnna Zaks // inlined. 3717fe8dcef71ae56e43fd7df345db2895f84f2d0caAnna Zaks if (Visited.count(N)) 3727fe8dcef71ae56e43fd7df345db2895f84f2d0caAnna Zaks continue; 3737fe8dcef71ae56e43fd7df345db2895f84f2d0caAnna Zaks 3747fe8dcef71ae56e43fd7df345db2895f84f2d0caAnna Zaks // Analyze the function. 3756a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks SetOfConstDecls VisitedCallees; 3767fe8dcef71ae56e43fd7df345db2895f84f2d0caAnna Zaks Decl *D = N->getDecl(); 3777fe8dcef71ae56e43fd7df345db2895f84f2d0caAnna Zaks assert(D); 3787fe8dcef71ae56e43fd7df345db2895f84f2d0caAnna Zaks HandleCode(D, ANALYSIS_PATH, 3797fe8dcef71ae56e43fd7df345db2895f84f2d0caAnna Zaks (Mgr->InliningMode == All ? 0 : &VisitedCallees)); 3807fe8dcef71ae56e43fd7df345db2895f84f2d0caAnna Zaks 3817fe8dcef71ae56e43fd7df345db2895f84f2d0caAnna Zaks // Add the visited callees to the global visited set. 382cb0a5039c243f5b0c178e70f424adac334e5789bTed Kremenek for (SetOfConstDecls::iterator I = VisitedCallees.begin(), 383cb0a5039c243f5b0c178e70f424adac334e5789bTed Kremenek E = VisitedCallees.end(); I != E; ++I) { 3847fe8dcef71ae56e43fd7df345db2895f84f2d0caAnna Zaks CallGraphNode *VN = CG.getNode(*I); 3857fe8dcef71ae56e43fd7df345db2895f84f2d0caAnna Zaks if (VN) 3867fe8dcef71ae56e43fd7df345db2895f84f2d0caAnna Zaks Visited.insert(VN); 3877fe8dcef71ae56e43fd7df345db2895f84f2d0caAnna Zaks } 3887fe8dcef71ae56e43fd7df345db2895f84f2d0caAnna Zaks Visited.insert(N); 389d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks } 390fee618af5dd7dee2caaa7347b372eb3dc5fdeffcTed Kremenek} 391fee618af5dd7dee2caaa7347b372eb3dc5fdeffcTed Kremenek 39214cc9451de4a9539bf79e4e5d63248c2377426dbTed Kremenekvoid AnalysisConsumer::HandleTranslationUnit(ASTContext &C) { 393aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks // Don't run the actions if an error has occurred with parsing the file. 394aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks DiagnosticsEngine &Diags = PP.getDiagnostics(); 395aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks if (Diags.hasErrorOccurred() || Diags.hasFatalErrorOccurred()) 396aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks return; 397aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks 398c5bdc556f6a65c677e0ed73f918c3000ecad33afAnna Zaks { 399d38f79543136ba68cd14b1dab0856474df1fbfd5Anna Zaks if (TUTotalTimer) TUTotalTimer->startTimer(); 400d38f79543136ba68cd14b1dab0856474df1fbfd5Anna Zaks 401c5bdc556f6a65c677e0ed73f918c3000ecad33afAnna Zaks // Introduce a scope to destroy BR before Mgr. 402c5bdc556f6a65c677e0ed73f918c3000ecad33afAnna Zaks BugReporter BR(*Mgr); 403c5bdc556f6a65c677e0ed73f918c3000ecad33afAnna Zaks TranslationUnitDecl *TU = C.getTranslationUnitDecl(); 404c5bdc556f6a65c677e0ed73f918c3000ecad33afAnna Zaks checkerMgr->runCheckersOnASTDecl(TU, *Mgr, BR); 405aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks 406aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks // Run the AST-only checks using the order in which functions are defined. 407aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks // If inlining is not turned on, use the simplest function order for path 408aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks // sensitive analyzes as well. 409aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks RecVisitorMode = (Mgr->shouldInlineCall() ? ANALYSIS_SYNTAX : ANALYSIS_ALL); 410aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks RecVisitorBR = &BR; 4116a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks 4126a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks // Process all the top level declarations. 413cb0a5039c243f5b0c178e70f424adac334e5789bTed Kremenek // 414577f14a34457032523e59dbbbacb88ca2cd4db57Ted Kremenek // Note: TraverseDecl may modify LocalTUDecls, but only by appending more 415577f14a34457032523e59dbbbacb88ca2cd4db57Ted Kremenek // entries. Thus we don't use an iterator, but rely on LocalTUDecls 416577f14a34457032523e59dbbbacb88ca2cd4db57Ted Kremenek // random access. By doing so, we automatically compensate for iterators 417577f14a34457032523e59dbbbacb88ca2cd4db57Ted Kremenek // possibly being invalidated, although this is a bit slower. 418694a942b0a14e02757a695142c45437eec6e3684Anna Zaks const unsigned LocalTUDeclsSize = LocalTUDecls.size(); 419694a942b0a14e02757a695142c45437eec6e3684Anna Zaks for (unsigned i = 0 ; i < LocalTUDeclsSize ; ++i) { 420577f14a34457032523e59dbbbacb88ca2cd4db57Ted Kremenek TraverseDecl(LocalTUDecls[i]); 421cb0a5039c243f5b0c178e70f424adac334e5789bTed Kremenek } 422aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks 423aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks if (Mgr->shouldInlineCall()) 424694a942b0a14e02757a695142c45437eec6e3684Anna Zaks HandleDeclsGallGraph(LocalTUDeclsSize); 425b317f8f5ca8737a5bbad97a3f7566a2dbd2ed61bZhongxing Xu 426c5bdc556f6a65c677e0ed73f918c3000ecad33afAnna Zaks // After all decls handled, run checkers on the entire TranslationUnit. 427c5bdc556f6a65c677e0ed73f918c3000ecad33afAnna Zaks checkerMgr->runCheckersOnEndOfTranslationUnit(TU, *Mgr, BR); 428aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks 429aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks RecVisitorBR = 0; 430c5bdc556f6a65c677e0ed73f918c3000ecad33afAnna Zaks } 4319be6e7ce5788e50c62d40c59b0bbc2ea423683f7Ted Kremenek 432ef3643fbbbf66247c5e205497fae0f46e240c143David Blaikie // Explicitly destroy the PathDiagnosticConsumer. This will flush its output. 433690a7f431d6863a101711e67636d51ddd13f35c5Ted Kremenek // FIXME: This should be replaced with something that doesn't rely on 434ef3643fbbbf66247c5e205497fae0f46e240c143David Blaikie // side-effects in PathDiagnosticConsumer's destructor. This is required when 435da17fd50ad485fd2a1fc5c2f055caacf532992daZhongxing Xu // used with option -disable-free. 436d07a0d0279c09d1017f8450fce575a94dc9703c0Zhongxing Xu Mgr.reset(NULL); 437d38f79543136ba68cd14b1dab0856474df1fbfd5Anna Zaks 438d38f79543136ba68cd14b1dab0856474df1fbfd5Anna Zaks if (TUTotalTimer) TUTotalTimer->stopTimer(); 4396b77ce8824cf62c2cfb61cf2d801eb3fcfbecffeAnna Zaks 4406b77ce8824cf62c2cfb61cf2d801eb3fcfbecffeAnna Zaks // Count how many basic blocks we have not covered. 4416b77ce8824cf62c2cfb61cf2d801eb3fcfbecffeAnna Zaks NumBlocksInAnalyzedFunctions = FunctionSummaries.getTotalNumBasicBlocks(); 4426b77ce8824cf62c2cfb61cf2d801eb3fcfbecffeAnna Zaks if (NumBlocksInAnalyzedFunctions > 0) 4436b77ce8824cf62c2cfb61cf2d801eb3fcfbecffeAnna Zaks PercentReachableBlocks = 4446b77ce8824cf62c2cfb61cf2d801eb3fcfbecffeAnna Zaks (FunctionSummaries.getTotalNumVisitedBasicBlocks() * 100) / 4456b77ce8824cf62c2cfb61cf2d801eb3fcfbecffeAnna Zaks NumBlocksInAnalyzedFunctions; 4466b77ce8824cf62c2cfb61cf2d801eb3fcfbecffeAnna Zaks 447db09a4dee28a4515438af60f2d2b4a83e4965c31Ted Kremenek} 448db09a4dee28a4515438af60f2d2b4a83e4965c31Ted Kremenek 4495f9e272e632e951b1efe824cd16acb4d96077930Chris Lattnerstatic void FindBlocks(DeclContext *D, SmallVectorImpl<Decl*> &WL) { 450fc576514d06c46a7cac49500169411d82f38d04bTed Kremenek if (BlockDecl *BD = dyn_cast<BlockDecl>(D)) 451fc576514d06c46a7cac49500169411d82f38d04bTed Kremenek WL.push_back(BD); 452f6eafcca7734274d277afa121f2c4fb025a54218Ted Kremenek 453fc576514d06c46a7cac49500169411d82f38d04bTed Kremenek for (DeclContext::decl_iterator I = D->decls_begin(), E = D->decls_end(); 454fc576514d06c46a7cac49500169411d82f38d04bTed Kremenek I!=E; ++I) 455fc576514d06c46a7cac49500169411d82f38d04bTed Kremenek if (DeclContext *DC = dyn_cast<DeclContext>(*I)) 456fc576514d06c46a7cac49500169411d82f38d04bTed Kremenek FindBlocks(DC, WL); 457fc576514d06c46a7cac49500169411d82f38d04bTed Kremenek} 458fc576514d06c46a7cac49500169411d82f38d04bTed Kremenek 459d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaksstatic std::string getFunctionName(const Decl *D) { 460d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks if (const ObjCMethodDecl *ID = dyn_cast<ObjCMethodDecl>(D)) { 461d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks return ID->getSelector().getAsString(); 462d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks } 463d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks if (const FunctionDecl *ND = dyn_cast<FunctionDecl>(D)) { 464d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks IdentifierInfo *II = ND->getIdentifier(); 465d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks if (II) 466d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks return II->getName(); 467d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks } 468d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks return ""; 469d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks} 470d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks 47198520835eb1aa091429afa06e9f4f7ebe3864d34Anna Zaksbool AnalysisConsumer::skipFunction(Decl *D) { 472d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks if (!Opts.AnalyzeSpecificFunction.empty() && 473d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks getFunctionName(D) != Opts.AnalyzeSpecificFunction) 47498520835eb1aa091429afa06e9f4f7ebe3864d34Anna Zaks return true; 4751eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 476f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek // Don't run the actions on declarations in header files unless 477f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek // otherwise specified. 478fcd783d583d270b7ec1ec3e0fcf83cd93d30e381Ted Kremenek SourceManager &SM = Ctx->getSourceManager(); 479402785357ab053dd53f4fdd858b9630a5e0f8badChandler Carruth SourceLocation SL = SM.getExpansionLoc(D->getLocation()); 480fcd783d583d270b7ec1ec3e0fcf83cd93d30e381Ted Kremenek if (!Opts.AnalyzeAll && !SM.isFromMainFile(SL)) 48198520835eb1aa091429afa06e9f4f7ebe3864d34Anna Zaks return true; 48298520835eb1aa091429afa06e9f4f7ebe3864d34Anna Zaks 48398520835eb1aa091429afa06e9f4f7ebe3864d34Anna Zaks return false; 48498520835eb1aa091429afa06e9f4f7ebe3864d34Anna Zaks} 48598520835eb1aa091429afa06e9f4f7ebe3864d34Anna Zaks 486aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaksvoid AnalysisConsumer::HandleCode(Decl *D, AnalysisMode Mode, 4876a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks SetOfConstDecls *VisitedCallees) { 48898520835eb1aa091429afa06e9f4f7ebe3864d34Anna Zaks if (skipFunction(D)) 4891eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump return; 490f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek 491aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks DisplayFunction(D, Mode); 49284c1f4b1edddf74f8080cfc470796c2c498b5d43Anna Zaks CFG *DeclCFG = Mgr->getCFG(D); 49384c1f4b1edddf74f8080cfc470796c2c498b5d43Anna Zaks if (DeclCFG) { 49484c1f4b1edddf74f8080cfc470796c2c498b5d43Anna Zaks unsigned CFGSize = DeclCFG->size(); 49584c1f4b1edddf74f8080cfc470796c2c498b5d43Anna Zaks MaxCFGSize = MaxCFGSize < CFGSize ? CFGSize : MaxCFGSize; 49684c1f4b1edddf74f8080cfc470796c2c498b5d43Anna Zaks } 49784c1f4b1edddf74f8080cfc470796c2c498b5d43Anna Zaks 49898520835eb1aa091429afa06e9f4f7ebe3864d34Anna Zaks 4991d26f48dc2eea1c07431ca1519d7034a21b9bcffTed Kremenek // Clear the AnalysisManager of old AnalysisDeclContexts. 50058f5ec7d56b1ebf5f90ee11226ebe7663f2821eaTed Kremenek Mgr->ClearContexts(); 501f6eafcca7734274d277afa121f2c4fb025a54218Ted Kremenek 5021eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump // Dispatch on the actions. 5035f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner SmallVector<Decl*, 10> WL; 504fc576514d06c46a7cac49500169411d82f38d04bTed Kremenek WL.push_back(D); 505f6eafcca7734274d277afa121f2c4fb025a54218Ted Kremenek 50606a54a38be5054c910ffc92db60edab23f9ea105Argyrios Kyrtzidis if (D->hasBody() && Opts.AnalyzeNestedBlocks) 507fc576514d06c46a7cac49500169411d82f38d04bTed Kremenek FindBlocks(cast<DeclContext>(D), WL); 508f6eafcca7734274d277afa121f2c4fb025a54218Ted Kremenek 5099fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis BugReporter BR(*Mgr); 5105f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner for (SmallVectorImpl<Decl*>::iterator WI=WL.begin(), WE=WL.end(); 5119fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis WI != WE; ++WI) 512d655ab28fdf7c940d3f79f8f287954d7f76e0977Argyrios Kyrtzidis if ((*WI)->hasBody()) { 513aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks if (Mode != ANALYSIS_PATH) 514aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks checkerMgr->runCheckersOnASTBody(*WI, *Mgr, BR); 5151f5171edc9fb9b0698a75fa981c29a750b0a6082Anna Zaks if (Mode != ANALYSIS_SYNTAX && checkerMgr->hasPathSensitiveCheckers()) { 5163fd5f370a28552976c52e76c3035d79012d78ddaAnna Zaks RunPathSensitiveChecks(*WI, VisitedCallees); 5171f5171edc9fb9b0698a75fa981c29a750b0a6082Anna Zaks NumFunctionsAnalyzed++; 5181f5171edc9fb9b0698a75fa981c29a750b0a6082Anna Zaks } 519d655ab28fdf7c940d3f79f8f287954d7f76e0977Argyrios Kyrtzidis } 520f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek} 521f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek 522f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek//===----------------------------------------------------------------------===// 523d655ab28fdf7c940d3f79f8f287954d7f76e0977Argyrios Kyrtzidis// Path-sensitive checking. 524f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek//===----------------------------------------------------------------------===// 525f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek 5263fd5f370a28552976c52e76c3035d79012d78ddaAnna Zaksvoid AnalysisConsumer::ActionExprEngine(Decl *D, bool ObjCGCEnabled, 5276a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks SetOfConstDecls *VisitedCallees) { 528a5937bbfd19e61d651a58b0f0ffeef68457902a5Ted Kremenek // Construct the analysis engine. First check if the CFG is valid. 52975d03cffe20b5c945ef04eba208efb0437339997Ted Kremenek // FIXME: Inter-procedural analysis will need to handle invalid CFGs. 5303fd5f370a28552976c52e76c3035d79012d78ddaAnna Zaks if (!Mgr->getCFG(D)) 531f6eafcca7734274d277afa121f2c4fb025a54218Ted Kremenek return; 5323fd5f370a28552976c52e76c3035d79012d78ddaAnna Zaks 533d4aeb8050a1d0fe47c53a73361c8b0b8ac310f46Ted Kremenek // See if the LiveVariables analysis scales. 534d4aeb8050a1d0fe47c53a73361c8b0b8ac310f46Ted Kremenek if (!Mgr->getAnalysisDeclContext(D)->getAnalysis<RelaxedLiveVariables>()) 535d4aeb8050a1d0fe47c53a73361c8b0b8ac310f46Ted Kremenek return; 536d4aeb8050a1d0fe47c53a73361c8b0b8ac310f46Ted Kremenek 5373bbd8cd831788c506f2980293eb3c7e1b3ca2501Anna Zaks ExprEngine Eng(*Mgr, ObjCGCEnabled, VisitedCallees, &FunctionSummaries); 538f6eafcca7734274d277afa121f2c4fb025a54218Ted Kremenek 539f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek // Set the graph auditor. 5406f42b62b6194f53bcbc349f5d17388e1936535d7Dylan Noblesmith OwningPtr<ExplodedNode::Auditor> Auditor; 5413fd5f370a28552976c52e76c3035d79012d78ddaAnna Zaks if (Mgr->shouldVisualizeUbigraph()) { 542f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek Auditor.reset(CreateUbiViz()); 543c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu ExplodedNode::SetAuditor(Auditor.get()); 544f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek } 5451eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 546b35a74a40c1d2656a25e560e773ed48bdf49f9c0Ted Kremenek // Execute the worklist algorithm. 547d200187bd27f9ad68699693a6e57f9ee3ff260faJordy Rose Eng.ExecuteWorkList(Mgr->getAnalysisDeclContextManager().getStackFrame(D), 5483fd5f370a28552976c52e76c3035d79012d78ddaAnna Zaks Mgr->getMaxNodes()); 5491eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 550f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek // Release the auditor (if any) so that it doesn't monitor the graph 551f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek // created BugReporter. 552c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu ExplodedNode::SetAuditor(0); 5533df6421150271266b5a90fd4c6bfa6566c38c036Ted Kremenek 55434d7734b6ed1d9c0f647405e065251eb67f42badTed Kremenek // Visualize the exploded graph. 5553fd5f370a28552976c52e76c3035d79012d78ddaAnna Zaks if (Mgr->shouldVisualizeGraphviz()) 5563fd5f370a28552976c52e76c3035d79012d78ddaAnna Zaks Eng.ViewGraph(Mgr->shouldTrimGraph()); 5571eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 5583df6421150271266b5a90fd4c6bfa6566c38c036Ted Kremenek // Display warnings. 5593df6421150271266b5a90fd4c6bfa6566c38c036Ted Kremenek Eng.getBugReporter().FlushReports(); 560bc46f345838b1c0d420dbd3655c94f5f360fb5b8Ted Kremenek} 561bc46f345838b1c0d420dbd3655c94f5f360fb5b8Ted Kremenek 5626a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaksvoid AnalysisConsumer::RunPathSensitiveChecks(Decl *D, 5636a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks SetOfConstDecls *Visited) { 56417a38e2636a8b1ce473fc6504c4b16cb09db29f4Jordy Rose 5654e4d08403ca5cfd4d558fa2936215d3a4e5a528dDavid Blaikie switch (Mgr->getLangOpts().getGC()) { 56617a38e2636a8b1ce473fc6504c4b16cb09db29f4Jordy Rose case LangOptions::NonGC: 5673fd5f370a28552976c52e76c3035d79012d78ddaAnna Zaks ActionExprEngine(D, false, Visited); 56817a38e2636a8b1ce473fc6504c4b16cb09db29f4Jordy Rose break; 56917a38e2636a8b1ce473fc6504c4b16cb09db29f4Jordy Rose 57017a38e2636a8b1ce473fc6504c4b16cb09db29f4Jordy Rose case LangOptions::GCOnly: 5713fd5f370a28552976c52e76c3035d79012d78ddaAnna Zaks ActionExprEngine(D, true, Visited); 57217a38e2636a8b1ce473fc6504c4b16cb09db29f4Jordy Rose break; 57317a38e2636a8b1ce473fc6504c4b16cb09db29f4Jordy Rose 57417a38e2636a8b1ce473fc6504c4b16cb09db29f4Jordy Rose case LangOptions::HybridGC: 5753fd5f370a28552976c52e76c3035d79012d78ddaAnna Zaks ActionExprEngine(D, false, Visited); 5763fd5f370a28552976c52e76c3035d79012d78ddaAnna Zaks ActionExprEngine(D, true, Visited); 57717a38e2636a8b1ce473fc6504c4b16cb09db29f4Jordy Rose break; 57817a38e2636a8b1ce473fc6504c4b16cb09db29f4Jordy Rose } 579b35a74a40c1d2656a25e560e773ed48bdf49f9c0Ted Kremenek} 580b35a74a40c1d2656a25e560e773ed48bdf49f9c0Ted Kremenek 581f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek//===----------------------------------------------------------------------===// 582f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek// AnalysisConsumer creation. 583f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek//===----------------------------------------------------------------------===// 584f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek 5859ef6537a894c33003359b1f9b9676e9178e028b7Ted KremenekASTConsumer* ento::CreateAnalysisConsumer(const Preprocessor& pp, 58608b86531ade68727c56918f162816075b87c864aJordy Rose const std::string& outDir, 58708b86531ade68727c56918f162816075b87c864aJordy Rose const AnalyzerOptions& opts, 58808b86531ade68727c56918f162816075b87c864aJordy Rose ArrayRef<std::string> plugins) { 58908b86531ade68727c56918f162816075b87c864aJordy Rose // Disable the effects of '-Werror' when using the AnalysisConsumer. 590efceabd2380f49306bc0229583458e93b062094bDaniel Dunbar pp.getDiagnostics().setWarningsAsErrors(false); 591be1fe1eb12a1cb91c8e3a9fcc2db4dfe989def6cTed Kremenek 59208b86531ade68727c56918f162816075b87c864aJordy Rose return new AnalysisConsumer(pp, outDir, opts, plugins); 593f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek} 594f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek 595f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek//===----------------------------------------------------------------------===// 596f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek// Ubigraph Visualization. FIXME: Move to separate file. 597f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek//===----------------------------------------------------------------------===// 598f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek 599f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremeneknamespace { 6001eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 601c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xuclass UbigraphViz : public ExplodedNode::Auditor { 6026f42b62b6194f53bcbc349f5d17388e1936535d7Dylan Noblesmith OwningPtr<raw_ostream> Out; 603710ad9343f32b33b336369b20edad1a21a0b3299Ted Kremenek llvm::sys::Path Dir, Filename; 604f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek unsigned Cntr; 605f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek 606f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek typedef llvm::DenseMap<void*,unsigned> VMap; 607f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek VMap M; 6081eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 609f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenekpublic: 6109c378f705405d37f49795d5e915989de774fe11fTed Kremenek UbigraphViz(raw_ostream *out, llvm::sys::Path& dir, 61156b98719b0dbebb33cb228afa888c47156be2381Ted Kremenek llvm::sys::Path& filename); 6121eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 613710ad9343f32b33b336369b20edad1a21a0b3299Ted Kremenek ~UbigraphViz(); 6141eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 6159c378f705405d37f49795d5e915989de774fe11fTed Kremenek virtual void AddEdge(ExplodedNode *Src, ExplodedNode *Dst); 616f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek}; 6171eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 618f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek} // end anonymous namespace 619f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek 620c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xustatic ExplodedNode::Auditor* CreateUbiViz() { 621f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek std::string ErrMsg; 6221eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 623710ad9343f32b33b336369b20edad1a21a0b3299Ted Kremenek llvm::sys::Path Dir = llvm::sys::Path::GetTemporaryDirectory(&ErrMsg); 624f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek if (!ErrMsg.empty()) 625f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek return 0; 626f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek 627710ad9343f32b33b336369b20edad1a21a0b3299Ted Kremenek llvm::sys::Path Filename = Dir; 628f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek Filename.appendComponent("llvm_ubi"); 629f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek Filename.makeUnique(true,&ErrMsg); 630f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek 631f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek if (!ErrMsg.empty()) 632f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek return 0; 633f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek 634d57a7ef9252964bc6c8471451d7bd395b0520cb8Chris Lattner llvm::errs() << "Writing '" << Filename.str() << "'.\n"; 6351eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 6366f42b62b6194f53bcbc349f5d17388e1936535d7Dylan Noblesmith OwningPtr<llvm::raw_fd_ostream> Stream; 637b044c473a155b7e827680635c1699cb2b5b6c0eeDan Gohman Stream.reset(new llvm::raw_fd_ostream(Filename.c_str(), ErrMsg)); 638f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek 639f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek if (!ErrMsg.empty()) 640f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek return 0; 6411eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 642710ad9343f32b33b336369b20edad1a21a0b3299Ted Kremenek return new UbigraphViz(Stream.take(), Dir, Filename); 643f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek} 644f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek 6459c378f705405d37f49795d5e915989de774fe11fTed Kremenekvoid UbigraphViz::AddEdge(ExplodedNode *Src, ExplodedNode *Dst) { 6461eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 64745479c88c8a44c55d27c3bd855273bb318082f37Ted Kremenek assert (Src != Dst && "Self-edges are not allowed."); 6481eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 649f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek // Lookup the Src. If it is a new node, it's a root. 650f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek VMap::iterator SrcI= M.find(Src); 651f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek unsigned SrcID; 6521eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 653f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek if (SrcI == M.end()) { 654f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek M[Src] = SrcID = Cntr++; 655f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek *Out << "('vertex', " << SrcID << ", ('color','#00ff00'))\n"; 656f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek } 657f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek else 658f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek SrcID = SrcI->second; 6591eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 660f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek // Lookup the Dst. 661f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek VMap::iterator DstI= M.find(Dst); 662f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek unsigned DstID; 663f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek 664f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek if (DstI == M.end()) { 665f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek M[Dst] = DstID = Cntr++; 666f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek *Out << "('vertex', " << DstID << ")\n"; 667f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek } 66856b98719b0dbebb33cb228afa888c47156be2381Ted Kremenek else { 66956b98719b0dbebb33cb228afa888c47156be2381Ted Kremenek // We have hit DstID before. Change its style to reflect a cache hit. 670f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek DstID = DstI->second; 67156b98719b0dbebb33cb228afa888c47156be2381Ted Kremenek *Out << "('change_vertex_style', " << DstID << ", 1)\n"; 67256b98719b0dbebb33cb228afa888c47156be2381Ted Kremenek } 673f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek 674f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek // Add the edge. 6751eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump *Out << "('edge', " << SrcID << ", " << DstID 676d1289327f7d2126d732e23cc189ecd0aa5d07cbbTed Kremenek << ", ('arrow','true'), ('oriented', 'true'))\n"; 677f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek} 678f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek 6799c378f705405d37f49795d5e915989de774fe11fTed KremenekUbigraphViz::UbigraphViz(raw_ostream *out, llvm::sys::Path& dir, 68056b98719b0dbebb33cb228afa888c47156be2381Ted Kremenek llvm::sys::Path& filename) 68156b98719b0dbebb33cb228afa888c47156be2381Ted Kremenek : Out(out), Dir(dir), Filename(filename), Cntr(0) { 68256b98719b0dbebb33cb228afa888c47156be2381Ted Kremenek 68356b98719b0dbebb33cb228afa888c47156be2381Ted Kremenek *Out << "('vertex_style_attribute', 0, ('shape', 'icosahedron'))\n"; 68456b98719b0dbebb33cb228afa888c47156be2381Ted Kremenek *Out << "('vertex_style', 1, 0, ('shape', 'sphere'), ('color', '#ffcc66')," 68556b98719b0dbebb33cb228afa888c47156be2381Ted Kremenek " ('size', '1.5'))\n"; 68656b98719b0dbebb33cb228afa888c47156be2381Ted Kremenek} 68756b98719b0dbebb33cb228afa888c47156be2381Ted Kremenek 688710ad9343f32b33b336369b20edad1a21a0b3299Ted KremenekUbigraphViz::~UbigraphViz() { 689710ad9343f32b33b336369b20edad1a21a0b3299Ted Kremenek Out.reset(0); 6906cb7c1a43b0c8f739d1f54b7fdae5ede86033496Benjamin Kramer llvm::errs() << "Running 'ubiviz' program... "; 691710ad9343f32b33b336369b20edad1a21a0b3299Ted Kremenek std::string ErrMsg; 692710ad9343f32b33b336369b20edad1a21a0b3299Ted Kremenek llvm::sys::Path Ubiviz = llvm::sys::Program::FindProgramByName("ubiviz"); 693710ad9343f32b33b336369b20edad1a21a0b3299Ted Kremenek std::vector<const char*> args; 694710ad9343f32b33b336369b20edad1a21a0b3299Ted Kremenek args.push_back(Ubiviz.c_str()); 695710ad9343f32b33b336369b20edad1a21a0b3299Ted Kremenek args.push_back(Filename.c_str()); 696710ad9343f32b33b336369b20edad1a21a0b3299Ted Kremenek args.push_back(0); 6971eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 698710ad9343f32b33b336369b20edad1a21a0b3299Ted Kremenek if (llvm::sys::Program::ExecuteAndWait(Ubiviz, &args[0],0,0,0,0,&ErrMsg)) { 6996cb7c1a43b0c8f739d1f54b7fdae5ede86033496Benjamin Kramer llvm::errs() << "Error viewing graph: " << ErrMsg << "\n"; 700710ad9343f32b33b336369b20edad1a21a0b3299Ted Kremenek } 7011eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 702710ad9343f32b33b336369b20edad1a21a0b3299Ted Kremenek // Delete the directory. 7031eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump Dir.eraseFromDisk(true); 704932680ecdeab4c216ce7c0736093d3dcd2f60f6dDaniel Dunbar} 705