AnalysisConsumer.cpp revision 45796b10d11869e86c6b85e24df165410536b313
1d2592a34a059e7cbb2b11dc53649ac4912422909Argyrios Kyrtzidis//===--- AnalysisConsumer.cpp - ASTConsumer for running Analyses ----------===// 21eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump// 3f24af5bc2e01ca8e7396ed997378a77fddfa521eTed Kremenek// The LLVM Compiler Infrastructure 4f24af5bc2e01ca8e7396ed997378a77fddfa521eTed Kremenek// 5f24af5bc2e01ca8e7396ed997378a77fddfa521eTed Kremenek// This file is distributed under the University of Illinois Open Source 6f24af5bc2e01ca8e7396ed997378a77fddfa521eTed Kremenek// License. See LICENSE.TXT for details. 7f24af5bc2e01ca8e7396ed997378a77fddfa521eTed Kremenek// 8f24af5bc2e01ca8e7396ed997378a77fddfa521eTed Kremenek//===----------------------------------------------------------------------===// 9f24af5bc2e01ca8e7396ed997378a77fddfa521eTed Kremenek// 10f24af5bc2e01ca8e7396ed997378a77fddfa521eTed Kremenek// "Meta" ASTConsumer for running different source analyses. 118e49dd6e7e73b275a74338a5127a524f0765303cTed Kremenek// 12f24af5bc2e01ca8e7396ed997378a77fddfa521eTed Kremenek//===----------------------------------------------------------------------===// 13f24af5bc2e01ca8e7396ed997378a77fddfa521eTed Kremenek 14f24af5bc2e01ca8e7396ed997378a77fddfa521eTed Kremenek#define DEBUG_TYPE "AnalysisConsumer" 15d2592a34a059e7cbb2b11dc53649ac4912422909Argyrios Kyrtzidis 16d2592a34a059e7cbb2b11dc53649ac4912422909Argyrios Kyrtzidis#include "AnalysisConsumer.h" 17f24af5bc2e01ca8e7396ed997378a77fddfa521eTed Kremenek#include "clang/AST/ASTConsumer.h" 1899c6ad3f22b865d0f4cce52bc36904403c9ed4c4Ted Kremenek#include "clang/AST/Decl.h" 195eca482fe895ea57bc82410222e6426c09e63284Ted Kremenek#include "clang/AST/DeclCXX.h" 2030a2e16f6c27f888dd11eba6bbbae1e980078fcbChandler Carruth#include "clang/AST/DeclObjC.h" 219b663716449b618ba0390b1dbebc54fa8e971124Ted Kremenek#include "clang/AST/ParentMap.h" 22e62f048960645b79363408fdead53fec2a063c52Anna Zaks#include "clang/AST/RecursiveASTVisitor.h" 239b663716449b618ba0390b1dbebc54fa8e971124Ted Kremenek#include "clang/Analysis/CFG.h" 24651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines#include "clang/Analysis/CallGraph.h" 25f24af5bc2e01ca8e7396ed997378a77fddfa521eTed Kremenek#include "clang/Analysis/Analyses/LiveVariables.h" 26f24af5bc2e01ca8e7396ed997378a77fddfa521eTed Kremenek#include "clang/StaticAnalyzer/Frontend/CheckerRegistration.h" 270111f575b968e423dccae439e501225b8314b257Zhongxing Xu#include "clang/StaticAnalyzer/Core/CheckerManager.h" 28ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenek#include "clang/StaticAnalyzer/Checkers/LocalCheckers.h" 29ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenek#include "clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h" 309ef6537a894c33003359b1f9b9676e9178e028b7Ted Kremenek#include "clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h" 315a4f98ff943e6a501b0fe47ade007c9bbf96cb88Argyrios Kyrtzidis#include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h" 32a19f4af7a94835ce4693bfe12d6270754e79eb56Anna Zaks#include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h" 33a19f4af7a94835ce4693bfe12d6270754e79eb56Anna Zaks#include "clang/StaticAnalyzer/Core/PathDiagnosticConsumers.h" 3424f1a967741ff9f8025ee23be12ba6feacc31f77Ted Kremenek 35d2592a34a059e7cbb2b11dc53649ac4912422909Argyrios Kyrtzidis#include "clang/Basic/FileManager.h" 36922059dec59c7bed235da01aff75ae522a369811Ted Kremenek#include "clang/Basic/SourceManager.h" 37922059dec59c7bed235da01aff75ae522a369811Ted Kremenek#include "clang/StaticAnalyzer/Core/AnalyzerOptions.h" 38d2592a34a059e7cbb2b11dc53649ac4912422909Argyrios Kyrtzidis#include "clang/Lex/Preprocessor.h" 39922059dec59c7bed235da01aff75ae522a369811Ted Kremenek#include "llvm/Support/raw_ostream.h" 40922059dec59c7bed235da01aff75ae522a369811Ted Kremenek#include "llvm/Support/Path.h" 41922059dec59c7bed235da01aff75ae522a369811Ted Kremenek#include "llvm/Support/Program.h" 42922059dec59c7bed235da01aff75ae522a369811Ted Kremenek#include "llvm/Support/Timer.h" 43d2592a34a059e7cbb2b11dc53649ac4912422909Argyrios Kyrtzidis#include "llvm/ADT/DepthFirstIterator.h" 44ebae6d0209e1ec3d5ea14f9e63bd0d740218ed14Anna Zaks#include "llvm/ADT/OwningPtr.h" 45f05aac8472d8ed081a361a218fd14d59ddc91b85Anna Zaks#include "llvm/ADT/SmallPtrSet.h" 46253955ca25c7e7049963b5db613c0cd15d66e4f8Anna Zaks#include "llvm/ADT/Statistic.h" 47ebae6d0209e1ec3d5ea14f9e63bd0d740218ed14Anna Zaks 48d2592a34a059e7cbb2b11dc53649ac4912422909Argyrios Kyrtzidis#include <queue> 49d2592a34a059e7cbb2b11dc53649ac4912422909Argyrios Kyrtzidis 50e36de1fe51c39d9161915dd3dbef880954af6476Ted Kremenekusing namespace clang; 51a7a8a450d908b34fa5f569f2e694ebd4b61aae2fTom Careusing namespace ento; 52a7a8a450d908b34fa5f569f2e694ebd4b61aae2fTom Careusing llvm::SmallPtrSet; 5366750fa464ace9f8c41666c8585ec71a248c1ccaTed Kremenek 54422ab7a49a9a4252dbc6350e49d7a5708337b9c7Ted Kremenekstatic ExplodedNode::Auditor* CreateUbiViz(); 55422ab7a49a9a4252dbc6350e49d7a5708337b9c7Ted Kremenek 56422ab7a49a9a4252dbc6350e49d7a5708337b9c7Ted KremenekSTATISTIC(NumFunctionTopLevel, "The # of functions at top level."); 57422ab7a49a9a4252dbc6350e49d7a5708337b9c7Ted KremenekSTATISTIC(NumFunctionsAnalyzed, "The # of functions analysed (as top level)."); 58a7a8a450d908b34fa5f569f2e694ebd4b61aae2fTom CareSTATISTIC(NumBlocksInAnalyzedFunctions, 59a7a8a450d908b34fa5f569f2e694ebd4b61aae2fTom Care "The # of basic blocks in the analyzed functions."); 60d2592a34a059e7cbb2b11dc53649ac4912422909Argyrios KyrtzidisSTATISTIC(PercentReachableBlocks, "The % of reachable basic blocks."); 610111f575b968e423dccae439e501225b8314b257Zhongxing XuSTATISTIC(MaxCFGSize, "The maximum number of basic blocks in a function."); 62f24af5bc2e01ca8e7396ed997378a77fddfa521eTed Kremenek 63651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines//===----------------------------------------------------------------------===// 641eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump// Special PathDiagnosticConsumers. 65f24af5bc2e01ca8e7396ed997378a77fddfa521eTed Kremenek//===----------------------------------------------------------------------===// 66f24af5bc2e01ca8e7396ed997378a77fddfa521eTed Kremenek 67f24af5bc2e01ca8e7396ed997378a77fddfa521eTed Kremenekstatic void createPlistHTMLDiagnosticConsumer(PathDiagnosticConsumers &C, 68651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines const std::string &prefix, 691eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump const Preprocessor &PP) { 70d2592a34a059e7cbb2b11dc53649ac4912422909Argyrios Kyrtzidis createHTMLDiagnosticConsumer(C, llvm::sys::path::parent_path(prefix), PP); 718e49dd6e7e73b275a74338a5127a524f0765303cTed Kremenek createPlistDiagnosticConsumer(C, prefix, PP); 728e49dd6e7e73b275a74338a5127a524f0765303cTed Kremenek} 73d2592a34a059e7cbb2b11dc53649ac4912422909Argyrios Kyrtzidis 74f598087b4adfea164acdd5b53ea2951bde740a2dTed Kremeneknamespace { 75f598087b4adfea164acdd5b53ea2951bde740a2dTed Kremenekclass ClangDiagPathDiagConsumer : public PathDiagnosticConsumer { 76f598087b4adfea164acdd5b53ea2951bde740a2dTed Kremenek DiagnosticsEngine &Diag; 7766750fa464ace9f8c41666c8585ec71a248c1ccaTed Kremenekpublic: 78422ab7a49a9a4252dbc6350e49d7a5708337b9c7Ted Kremenek ClangDiagPathDiagConsumer(DiagnosticsEngine &Diag) : Diag(Diag) {} 79422ab7a49a9a4252dbc6350e49d7a5708337b9c7Ted Kremenek virtual ~ClangDiagPathDiagConsumer() {} 80422ab7a49a9a4252dbc6350e49d7a5708337b9c7Ted Kremenek virtual StringRef getName() const { return "ClangDiags"; } 81422ab7a49a9a4252dbc6350e49d7a5708337b9c7Ted Kremenek virtual PathGenerationScheme getGenerationScheme() const { return None; } 821eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 83e62f048960645b79363408fdead53fec2a063c52Anna Zaks void FlushDiagnosticsImpl(std::vector<const PathDiagnostic *> &Diags, 84e62f048960645b79363408fdead53fec2a063c52Anna Zaks FilesMade *filesMade) { 85e62f048960645b79363408fdead53fec2a063c52Anna Zaks for (std::vector<const PathDiagnostic*>::iterator I = Diags.begin(), 86e62f048960645b79363408fdead53fec2a063c52Anna Zaks E = Diags.end(); I != E; ++I) { 8718c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek const PathDiagnostic *PD = *I; 888bef8238181a30e52dea380789a7e2d760eac532Ted Kremenek StringRef desc = PD->getShortDescription(); 899c378f705405d37f49795d5e915989de774fe11fTed Kremenek SmallString<512> TmpStr; 901eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump llvm::raw_svector_ostream Out(TmpStr); 919c378f705405d37f49795d5e915989de774fe11fTed Kremenek for (StringRef::iterator I=desc.begin(), E=desc.end(); I!=E; ++I) { 929c378f705405d37f49795d5e915989de774fe11fTed Kremenek if (*I == '%') 939c378f705405d37f49795d5e915989de774fe11fTed Kremenek Out << "%%"; 949c378f705405d37f49795d5e915989de774fe11fTed Kremenek else 951eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump Out << *I; 969c378f705405d37f49795d5e915989de774fe11fTed Kremenek } 979c378f705405d37f49795d5e915989de774fe11fTed Kremenek Out.flush(); 980111f575b968e423dccae439e501225b8314b257Zhongxing Xu unsigned ErrorDiag = Diag.getCustomDiagID(DiagnosticsEngine::Warning, 990f5c5c60e9806d13f0907cd99d7204ffab0e08f7Ted Kremenek TmpStr); 1000f5c5c60e9806d13f0907cd99d7204ffab0e08f7Ted Kremenek SourceLocation L = PD->getLocation().asLocation(); 1010f5c5c60e9806d13f0907cd99d7204ffab0e08f7Ted Kremenek DiagnosticBuilder diagBuilder = Diag.Report(L, ErrorDiag); 1020f5c5c60e9806d13f0907cd99d7204ffab0e08f7Ted Kremenek 103f24af5bc2e01ca8e7396ed997378a77fddfa521eTed Kremenek // Get the ranges from the last point in the path. 104f56faa01936b9cf909623d7f06e3c2569ca4a78eDmitri Gribenko ArrayRef<SourceRange> Ranges = PD->path.back()->getRanges(); 105f56faa01936b9cf909623d7f06e3c2569ca4a78eDmitri Gribenko 1061eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump for (ArrayRef<SourceRange>::iterator I = Ranges.begin(), 1070b3ade86a1c60cf0c7b56aa238aff458eb7f5974Anna Zaks E = Ranges.end(); I != E; ++I) { 1084d2ae4a70336dc2aa11389b34946be152bb454c9Anna Zaks diagBuilder << *I; 109f24af5bc2e01ca8e7396ed997378a77fddfa521eTed Kremenek } 1108d0f528afd9fcb9ebb8ccb4b8a529a05375b628eJordan Rose } 111fbcb3f11fc90e9f00e6074e9b118b8dc11ca604cAnna Zaks } 112e62f048960645b79363408fdead53fec2a063c52Anna Zaks}; 113d2592a34a059e7cbb2b11dc53649ac4912422909Argyrios Kyrtzidis} // end anonymous namespace 1148d0f528afd9fcb9ebb8ccb4b8a529a05375b628eJordan Rose 1153fd5f370a28552976c52e76c3035d79012d78ddaAnna Zaks//===----------------------------------------------------------------------===// 116e62f048960645b79363408fdead53fec2a063c52Anna Zaks// AnalysisConsumer declaration. 1170111f575b968e423dccae439e501225b8314b257Zhongxing Xu//===----------------------------------------------------------------------===// 1180111f575b968e423dccae439e501225b8314b257Zhongxing Xu 119031ccc0555a82afc2e8afe29e19dd57ff204e2deZhongxing Xunamespace { 1201eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1210111f575b968e423dccae439e501225b8314b257Zhongxing Xuclass AnalysisConsumer : public ASTConsumer, 122fc8f0e14ad142ed811e90fbd9a30e419e301c717Chris Lattner public RecursiveASTVisitor<AnalysisConsumer> { 123651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines enum AnalysisMode { 1240111f575b968e423dccae439e501225b8314b257Zhongxing Xu ANALYSIS_SYNTAX, 125f24af5bc2e01ca8e7396ed997378a77fddfa521eTed Kremenek ANALYSIS_PATH, 126f24af5bc2e01ca8e7396ed997378a77fddfa521eTed Kremenek ANALYSIS_ALL 1272ce43c8f43254a9edea53a20dc0e69195bc82ae0Zhongxing Xu }; 1288bef8238181a30e52dea380789a7e2d760eac532Ted Kremenek 129253955ca25c7e7049963b5db613c0cd15d66e4f8Anna Zaks /// Mode of the analyzes while recursively visiting Decls. 130253955ca25c7e7049963b5db613c0cd15d66e4f8Anna Zaks AnalysisMode RecVisitorMode; 13118c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek /// Bug Reporter to use while recursively visiting Decls. 1328bef8238181a30e52dea380789a7e2d760eac532Ted Kremenek BugReporter *RecVisitorBR; 1332ce43c8f43254a9edea53a20dc0e69195bc82ae0Zhongxing Xu 134bc42c533e7d3d946704a49e242939dd232f33072Tom Carepublic: 1355903a373db3d27794c90b25687e0dd6adb0e497dAnna Zaks ASTContext *Ctx; 1365903a373db3d27794c90b25687e0dd6adb0e497dAnna Zaks const Preprocessor &PP; 1375903a373db3d27794c90b25687e0dd6adb0e497dAnna Zaks const std::string OutDir; 1385903a373db3d27794c90b25687e0dd6adb0e497dAnna Zaks AnalyzerOptionsRef Opts; 1395903a373db3d27794c90b25687e0dd6adb0e497dAnna Zaks ArrayRef<std::string> Plugins; 140bc42c533e7d3d946704a49e242939dd232f33072Tom Care 141422ab7a49a9a4252dbc6350e49d7a5708337b9c7Ted Kremenek /// \brief Stores the declarations from the local translation unit. 142422ab7a49a9a4252dbc6350e49d7a5708337b9c7Ted Kremenek /// Note, we pre-compute the local declarations at parse time as an 143422ab7a49a9a4252dbc6350e49d7a5708337b9c7Ted Kremenek /// optimization to make sure we do not deserialize everything from disk. 144422ab7a49a9a4252dbc6350e49d7a5708337b9c7Ted Kremenek /// The local declaration to all declarations ratio might be very small when 145422ab7a49a9a4252dbc6350e49d7a5708337b9c7Ted Kremenek /// working with a PCH file. 146422ab7a49a9a4252dbc6350e49d7a5708337b9c7Ted Kremenek SetOfDecls LocalTUDecls; 147422ab7a49a9a4252dbc6350e49d7a5708337b9c7Ted Kremenek 148422ab7a49a9a4252dbc6350e49d7a5708337b9c7Ted Kremenek // Set of PathDiagnosticConsumers. Owned by AnalysisManager. 149422ab7a49a9a4252dbc6350e49d7a5708337b9c7Ted Kremenek PathDiagnosticConsumers PathConsumers; 150422ab7a49a9a4252dbc6350e49d7a5708337b9c7Ted Kremenek 151422ab7a49a9a4252dbc6350e49d7a5708337b9c7Ted Kremenek StoreManagerCreator CreateStoreMgr; 152422ab7a49a9a4252dbc6350e49d7a5708337b9c7Ted Kremenek ConstraintManagerCreator CreateConstraintMgr; 1538d0f528afd9fcb9ebb8ccb4b8a529a05375b628eJordan Rose 154f598087b4adfea164acdd5b53ea2951bde740a2dTed Kremenek OwningPtr<CheckerManager> checkerMgr; 155422ab7a49a9a4252dbc6350e49d7a5708337b9c7Ted Kremenek OwningPtr<AnalysisManager> Mgr; 15666750fa464ace9f8c41666c8585ec71a248c1ccaTed Kremenek 157f598087b4adfea164acdd5b53ea2951bde740a2dTed Kremenek /// Time the analyzes time of each translation unit. 158422ab7a49a9a4252dbc6350e49d7a5708337b9c7Ted Kremenek static llvm::Timer* TUTotalTimer; 15966750fa464ace9f8c41666c8585ec71a248c1ccaTed Kremenek 160f598087b4adfea164acdd5b53ea2951bde740a2dTed Kremenek /// The information about analyzed functions shared throughout the 161422ab7a49a9a4252dbc6350e49d7a5708337b9c7Ted Kremenek /// translation unit. 162422ab7a49a9a4252dbc6350e49d7a5708337b9c7Ted Kremenek FunctionSummariesTy FunctionSummaries; 163422ab7a49a9a4252dbc6350e49d7a5708337b9c7Ted Kremenek 164422ab7a49a9a4252dbc6350e49d7a5708337b9c7Ted Kremenek AnalysisConsumer(const Preprocessor& pp, 165422ab7a49a9a4252dbc6350e49d7a5708337b9c7Ted Kremenek const std::string& outdir, 166422ab7a49a9a4252dbc6350e49d7a5708337b9c7Ted Kremenek AnalyzerOptionsRef opts, 167a19f4af7a94835ce4693bfe12d6270754e79eb56Anna Zaks ArrayRef<std::string> plugins) 168dd7ddf2b2296f95e7591ca3f9791f0eb9a15ee42Anna Zaks : RecVisitorMode(ANALYSIS_ALL), RecVisitorBR(0), 1694d2ae4a70336dc2aa11389b34946be152bb454c9Anna Zaks Ctx(0), PP(pp), OutDir(outdir), Opts(opts), Plugins(plugins) { 170dd7ddf2b2296f95e7591ca3f9791f0eb9a15ee42Anna Zaks DigestAnalyzerOptions(); 171dd7ddf2b2296f95e7591ca3f9791f0eb9a15ee42Anna Zaks if (Opts->PrintStats) { 172dd7ddf2b2296f95e7591ca3f9791f0eb9a15ee42Anna Zaks llvm::EnableStatistics(); 173dd7ddf2b2296f95e7591ca3f9791f0eb9a15ee42Anna Zaks TUTotalTimer = new llvm::Timer("Analyzer Total Time"); 1744d2ae4a70336dc2aa11389b34946be152bb454c9Anna Zaks } 1754d2ae4a70336dc2aa11389b34946be152bb454c9Anna Zaks } 1764d2ae4a70336dc2aa11389b34946be152bb454c9Anna Zaks 1774d2ae4a70336dc2aa11389b34946be152bb454c9Anna Zaks ~AnalysisConsumer() { 1785903a373db3d27794c90b25687e0dd6adb0e497dAnna Zaks if (Opts->PrintStats) 1795903a373db3d27794c90b25687e0dd6adb0e497dAnna Zaks delete TUTotalTimer; 1805903a373db3d27794c90b25687e0dd6adb0e497dAnna Zaks } 181a19f4af7a94835ce4693bfe12d6270754e79eb56Anna Zaks 182a19f4af7a94835ce4693bfe12d6270754e79eb56Anna Zaks void DigestAnalyzerOptions() { 183c03a39e16762627b421247b12a2658be630a3300Anna Zaks // Create the PathDiagnosticConsumer. 184a19f4af7a94835ce4693bfe12d6270754e79eb56Anna Zaks PathConsumers.push_back(new ClangDiagPathDiagConsumer(PP.getDiagnostics())); 1855a878b2cabb940bf3c1ac420a52cac305765e3e2Anna Zaks 186a19f4af7a94835ce4693bfe12d6270754e79eb56Anna Zaks if (!OutDir.empty()) { 187b355be838a22a511d078504b2277f70aea52ca85Anna Zaks switch (Opts->AnalysisDiagOpt) { 1885a878b2cabb940bf3c1ac420a52cac305765e3e2Anna Zaks default: 189b355be838a22a511d078504b2277f70aea52ca85Anna Zaks#define ANALYSIS_DIAGNOSTICS(NAME, CMDFLAG, DESC, CREATEFN, AUTOCREATE) \ 190c03a39e16762627b421247b12a2658be630a3300Anna Zaks case PD_##NAME: CREATEFN(PathConsumers, OutDir, PP); break; 191ebae6d0209e1ec3d5ea14f9e63bd0d740218ed14Anna Zaks#include "clang/StaticAnalyzer/Core/Analyses.def" 192ebae6d0209e1ec3d5ea14f9e63bd0d740218ed14Anna Zaks } 193ebae6d0209e1ec3d5ea14f9e63bd0d740218ed14Anna Zaks } else if (Opts->AnalysisDiagOpt == PD_TEXT) { 194ebae6d0209e1ec3d5ea14f9e63bd0d740218ed14Anna Zaks // Create the text client even without a specified output file since 195ebae6d0209e1ec3d5ea14f9e63bd0d740218ed14Anna Zaks // it just uses diagnostic notes. 19666c486f275531df6362b3511fc3af6563561801bTed Kremenek createTextPathDiagnosticConsumer(PathConsumers, "", PP); 197ebae6d0209e1ec3d5ea14f9e63bd0d740218ed14Anna Zaks } 198b355be838a22a511d078504b2277f70aea52ca85Anna Zaks 199ebae6d0209e1ec3d5ea14f9e63bd0d740218ed14Anna Zaks // Create the analyzer component creators. 200ebae6d0209e1ec3d5ea14f9e63bd0d740218ed14Anna Zaks switch (Opts->AnalysisStoreOpt) { 201f24af5bc2e01ca8e7396ed997378a77fddfa521eTed Kremenek default: 2021eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump llvm_unreachable("Unknown store manager."); 203aa0aeb1cbe117db68d35700cb3a34aace0f99b99Anna Zaks#define ANALYSIS_STORE(NAME, CMDFLAG, DESC, CREATEFN) \ 204aa0aeb1cbe117db68d35700cb3a34aace0f99b99Anna Zaks case NAME##Model: CreateStoreMgr = CREATEFN; break; 205aa0aeb1cbe117db68d35700cb3a34aace0f99b99Anna Zaks#include "clang/StaticAnalyzer/Core/Analyses.def" 206aa0aeb1cbe117db68d35700cb3a34aace0f99b99Anna Zaks } 207aa0aeb1cbe117db68d35700cb3a34aace0f99b99Anna Zaks 208aa0aeb1cbe117db68d35700cb3a34aace0f99b99Anna Zaks switch (Opts->AnalysisConstraintsOpt) { 209aa0aeb1cbe117db68d35700cb3a34aace0f99b99Anna Zaks default: 210aa0aeb1cbe117db68d35700cb3a34aace0f99b99Anna Zaks llvm_unreachable("Unknown store manager."); 211aa0aeb1cbe117db68d35700cb3a34aace0f99b99Anna Zaks#define ANALYSIS_CONSTRAINTS(NAME, CMDFLAG, DESC, CREATEFN) \ 212f05aac8472d8ed081a361a218fd14d59ddc91b85Anna Zaks case NAME##Model: CreateConstraintMgr = CREATEFN; break; 21399ba9e3bd70671f3441fb974895f226a83ce0e66David Blaikie#include "clang/StaticAnalyzer/Core/Analyses.def" 214a19f4af7a94835ce4693bfe12d6270754e79eb56Anna Zaks } 215cd656cab3fa3dd4b0c974c6ae1c0e60880b18c22Anna Zaks } 216319a9184d5ca9f77622b45ae15c08f6b9ce01621Anna Zaks 2173152b3cb5b6a2f797d0972c81a5eb3fd69c0d620Anna Zaks void DisplayFunction(const Decl *D, AnalysisMode Mode) { 2183152b3cb5b6a2f797d0972c81a5eb3fd69c0d620Anna Zaks if (!Opts->AnalyzerDisplayProgress) 219f05aac8472d8ed081a361a218fd14d59ddc91b85Anna Zaks return; 2204e82d3cf6fd4c907265e3fa3aac0a835c35dc759Anna Zaks 221f05aac8472d8ed081a361a218fd14d59ddc91b85Anna Zaks SourceManager &SM = Mgr->getASTContext().getSourceManager(); 222f05aac8472d8ed081a361a218fd14d59ddc91b85Anna Zaks PresumedLoc Loc = SM.getPresumedLoc(D->getLocation()); 2231aae01a8308d2f8e31adab3f4d7ac35543aac680Anna Zaks if (Loc.isValid()) { 22471fdf469a3b6d7d557b0bfba36e8659f4966c565Anna Zaks llvm::errs() << "ANALYZE"; 2253152b3cb5b6a2f797d0972c81a5eb3fd69c0d620Anna Zaks switch (Mode) { 2263152b3cb5b6a2f797d0972c81a5eb3fd69c0d620Anna Zaks case ANALYSIS_SYNTAX: llvm::errs() << "(Syntax)"; break; 227a19f4af7a94835ce4693bfe12d6270754e79eb56Anna Zaks case ANALYSIS_PATH: llvm::errs() << "(Path Sensitive)"; break; 228a19f4af7a94835ce4693bfe12d6270754e79eb56Anna Zaks case ANALYSIS_ALL: break; 229a19f4af7a94835ce4693bfe12d6270754e79eb56Anna Zaks }; 230a19f4af7a94835ce4693bfe12d6270754e79eb56Anna Zaks llvm::errs() << ": " << Loc.getFilename(); 231f05aac8472d8ed081a361a218fd14d59ddc91b85Anna Zaks if (isa<FunctionDecl>(D) || isa<ObjCMethodDecl>(D)) { 232aa0aeb1cbe117db68d35700cb3a34aace0f99b99Anna Zaks const NamedDecl *ND = cast<NamedDecl>(D); 2338ff5c41f2bde7ebbe568b4c15e59f14b8befae66Anna Zaks llvm::errs() << ' ' << *ND << '\n'; 2348ff5c41f2bde7ebbe568b4c15e59f14b8befae66Anna Zaks } 2358ff5c41f2bde7ebbe568b4c15e59f14b8befae66Anna Zaks else if (isa<BlockDecl>(D)) { 2368ff5c41f2bde7ebbe568b4c15e59f14b8befae66Anna Zaks llvm::errs() << ' ' << "block(line:" << Loc.getLine() << ",col:" 2378ff5c41f2bde7ebbe568b4c15e59f14b8befae66Anna Zaks << Loc.getColumn() << '\n'; 2388ff5c41f2bde7ebbe568b4c15e59f14b8befae66Anna Zaks } 2398ff5c41f2bde7ebbe568b4c15e59f14b8befae66Anna Zaks else if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D)) { 2403152b3cb5b6a2f797d0972c81a5eb3fd69c0d620Anna Zaks Selector S = MD->getSelector(); 2413152b3cb5b6a2f797d0972c81a5eb3fd69c0d620Anna Zaks llvm::errs() << ' ' << S.getAsString(); 242f05aac8472d8ed081a361a218fd14d59ddc91b85Anna Zaks } 243f05aac8472d8ed081a361a218fd14d59ddc91b85Anna Zaks } 2448bef8238181a30e52dea380789a7e2d760eac532Ted Kremenek } 245f05aac8472d8ed081a361a218fd14d59ddc91b85Anna Zaks 246f05aac8472d8ed081a361a218fd14d59ddc91b85Anna Zaks virtual void Initialize(ASTContext &Context) { 247f05aac8472d8ed081a361a218fd14d59ddc91b85Anna Zaks Ctx = &Context; 248f05aac8472d8ed081a361a218fd14d59ddc91b85Anna Zaks checkerMgr.reset(createCheckerManager(*Opts, PP.getLangOpts(), Plugins, 2491aae01a8308d2f8e31adab3f4d7ac35543aac680Anna Zaks PP.getDiagnostics())); 2501aae01a8308d2f8e31adab3f4d7ac35543aac680Anna Zaks Mgr.reset(new AnalysisManager(*Ctx, 2511aae01a8308d2f8e31adab3f4d7ac35543aac680Anna Zaks PP.getDiagnostics(), 2528ff5c41f2bde7ebbe568b4c15e59f14b8befae66Anna Zaks PP.getLangOpts(), 253ad62deeb70e97da6bd514dd390ea1ce6af6ad81dAnna Zaks PathConsumers, 254a19f4af7a94835ce4693bfe12d6270754e79eb56Anna Zaks CreateStoreMgr, 2551aae01a8308d2f8e31adab3f4d7ac35543aac680Anna Zaks CreateConstraintMgr, 2561aae01a8308d2f8e31adab3f4d7ac35543aac680Anna Zaks checkerMgr.get(), 2571aae01a8308d2f8e31adab3f4d7ac35543aac680Anna Zaks *Opts)); 2581aae01a8308d2f8e31adab3f4d7ac35543aac680Anna Zaks } 259aa0aeb1cbe117db68d35700cb3a34aace0f99b99Anna Zaks 260cd656cab3fa3dd4b0c974c6ae1c0e60880b18c22Anna Zaks /// \brief Store the top level decls in the set to be processed later on. 261cd656cab3fa3dd4b0c974c6ae1c0e60880b18c22Anna Zaks /// (Doing this pre-processing avoids deserialization of data from PCH.) 262a19f4af7a94835ce4693bfe12d6270754e79eb56Anna Zaks virtual bool HandleTopLevelDecl(DeclGroupRef D); 263f05aac8472d8ed081a361a218fd14d59ddc91b85Anna Zaks virtual void HandleTopLevelDeclInObjCContainer(DeclGroupRef D); 264f05aac8472d8ed081a361a218fd14d59ddc91b85Anna Zaks 265fa06f0464a04bb7fce1fcfb3780d151bb029e00cJordan Rose virtual void HandleTranslationUnit(ASTContext &C); 266fa06f0464a04bb7fce1fcfb3780d151bb029e00cJordan Rose 267fa06f0464a04bb7fce1fcfb3780d151bb029e00cJordan Rose /// \brief Build the call graph for all the top level decls of this TU and 268fa06f0464a04bb7fce1fcfb3780d151bb029e00cJordan Rose /// use it to define the order in which the functions should be visited. 269fa06f0464a04bb7fce1fcfb3780d151bb029e00cJordan Rose void HandleDeclsGallGraph(const unsigned LocalTUDeclsSize); 270fa06f0464a04bb7fce1fcfb3780d151bb029e00cJordan Rose 271fa06f0464a04bb7fce1fcfb3780d151bb029e00cJordan Rose /// \brief Run analyzes(syntax or path sensitive) on the given function. 272f05aac8472d8ed081a361a218fd14d59ddc91b85Anna Zaks /// \param Mode - determines if we are requesting syntax only or path 273f05aac8472d8ed081a361a218fd14d59ddc91b85Anna Zaks /// sensitive only analysis. 274fa06f0464a04bb7fce1fcfb3780d151bb029e00cJordan Rose /// \param VisitedCallees - The output parameter, which is populated with the 275fa06f0464a04bb7fce1fcfb3780d151bb029e00cJordan Rose /// set of functions which should be considered analyzed after analyzing the 276fa06f0464a04bb7fce1fcfb3780d151bb029e00cJordan Rose /// given root function. 2778bef8238181a30e52dea380789a7e2d760eac532Ted Kremenek void HandleCode(Decl *D, AnalysisMode Mode, 278fa06f0464a04bb7fce1fcfb3780d151bb029e00cJordan Rose SetOfConstDecls *VisitedCallees = 0); 279fa06f0464a04bb7fce1fcfb3780d151bb029e00cJordan Rose 280f05aac8472d8ed081a361a218fd14d59ddc91b85Anna Zaks void RunPathSensitiveChecks(Decl *D, SetOfConstDecls *VisitedCallees); 281f05aac8472d8ed081a361a218fd14d59ddc91b85Anna Zaks void ActionExprEngine(Decl *D, bool ObjCGCEnabled, 2821aae01a8308d2f8e31adab3f4d7ac35543aac680Anna Zaks SetOfConstDecls *VisitedCallees); 2831aae01a8308d2f8e31adab3f4d7ac35543aac680Anna Zaks 2841aae01a8308d2f8e31adab3f4d7ac35543aac680Anna Zaks /// Visitors for the RecursiveASTVisitor. 2851aae01a8308d2f8e31adab3f4d7ac35543aac680Anna Zaks bool shouldWalkTypesOfTypeLocs() const { return false; } 2861aae01a8308d2f8e31adab3f4d7ac35543aac680Anna Zaks 2871aae01a8308d2f8e31adab3f4d7ac35543aac680Anna Zaks /// Handle callbacks for arbitrary Decls. 2881aae01a8308d2f8e31adab3f4d7ac35543aac680Anna Zaks bool VisitDecl(Decl *D) { 289f05aac8472d8ed081a361a218fd14d59ddc91b85Anna Zaks checkerMgr->runCheckersOnASTDecl(D, *Mgr, *RecVisitorBR); 2901aae01a8308d2f8e31adab3f4d7ac35543aac680Anna Zaks return true; 291a19f4af7a94835ce4693bfe12d6270754e79eb56Anna Zaks } 292a19f4af7a94835ce4693bfe12d6270754e79eb56Anna Zaks 2931aae01a8308d2f8e31adab3f4d7ac35543aac680Anna Zaks bool VisitFunctionDecl(FunctionDecl *FD) { 294a19f4af7a94835ce4693bfe12d6270754e79eb56Anna Zaks IdentifierInfo *II = FD->getIdentifier(); 2951aae01a8308d2f8e31adab3f4d7ac35543aac680Anna Zaks if (II && II->getName().startswith("__inline")) 296a19f4af7a94835ce4693bfe12d6270754e79eb56Anna Zaks return true; 2971aae01a8308d2f8e31adab3f4d7ac35543aac680Anna Zaks 298a19f4af7a94835ce4693bfe12d6270754e79eb56Anna Zaks // We skip function template definitions, as their semantics is 299f05aac8472d8ed081a361a218fd14d59ddc91b85Anna Zaks // only determined when they are instantiated. 3001aae01a8308d2f8e31adab3f4d7ac35543aac680Anna Zaks if (FD->isThisDeclarationADefinition() && 301aa0aeb1cbe117db68d35700cb3a34aace0f99b99Anna Zaks !FD->isDependentContext()) { 3021aae01a8308d2f8e31adab3f4d7ac35543aac680Anna Zaks HandleCode(FD, RecVisitorMode); 303d231d0130a95336610ab9a42eaeb2cdac19992f3Anna Zaks } 304d231d0130a95336610ab9a42eaeb2cdac19992f3Anna Zaks return true; 305d231d0130a95336610ab9a42eaeb2cdac19992f3Anna Zaks } 306d231d0130a95336610ab9a42eaeb2cdac19992f3Anna Zaks 307aa0aeb1cbe117db68d35700cb3a34aace0f99b99Anna Zaks bool VisitObjCMethodDecl(ObjCMethodDecl *MD) { 308aa0aeb1cbe117db68d35700cb3a34aace0f99b99Anna Zaks checkerMgr->runCheckersOnASTDecl(MD, *Mgr, *RecVisitorBR); 309aa0aeb1cbe117db68d35700cb3a34aace0f99b99Anna Zaks if (MD->isThisDeclarationADefinition()) 310f05aac8472d8ed081a361a218fd14d59ddc91b85Anna Zaks HandleCode(MD, RecVisitorMode); 311f05aac8472d8ed081a361a218fd14d59ddc91b85Anna Zaks return true; 312c03a39e16762627b421247b12a2658be630a3300Anna Zaks } 313c03a39e16762627b421247b12a2658be630a3300Anna Zaks 314c03a39e16762627b421247b12a2658be630a3300Anna Zaksprivate: 315651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines void storeTopLevelDecls(DeclGroupRef DG); 316c03a39e16762627b421247b12a2658be630a3300Anna Zaks 317c03a39e16762627b421247b12a2658be630a3300Anna Zaks /// \brief Check if we should skip (not analyze) the given function. 318c03a39e16762627b421247b12a2658be630a3300Anna Zaks bool skipFunction(Decl *D); 319c03a39e16762627b421247b12a2658be630a3300Anna Zaks 320c03a39e16762627b421247b12a2658be630a3300Anna Zaks}; 321c03a39e16762627b421247b12a2658be630a3300Anna Zaks} // end anonymous namespace 322c03a39e16762627b421247b12a2658be630a3300Anna Zaks 323c03a39e16762627b421247b12a2658be630a3300Anna Zaks 324fa06f0464a04bb7fce1fcfb3780d151bb029e00cJordan Rose//===----------------------------------------------------------------------===// 3258bef8238181a30e52dea380789a7e2d760eac532Ted Kremenek// AnalysisConsumer implementation. 326c03a39e16762627b421247b12a2658be630a3300Anna Zaks//===----------------------------------------------------------------------===// 3276bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hinesllvm::Timer* AnalysisConsumer::TUTotalTimer = 0; 328fa06f0464a04bb7fce1fcfb3780d151bb029e00cJordan Rose 329fa06f0464a04bb7fce1fcfb3780d151bb029e00cJordan Rosebool AnalysisConsumer::HandleTopLevelDecl(DeclGroupRef DG) { 330fa06f0464a04bb7fce1fcfb3780d151bb029e00cJordan Rose storeTopLevelDecls(DG); 331c03a39e16762627b421247b12a2658be630a3300Anna Zaks return true; 332fa06f0464a04bb7fce1fcfb3780d151bb029e00cJordan Rose} 3336bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines 334fa06f0464a04bb7fce1fcfb3780d151bb029e00cJordan Rosevoid AnalysisConsumer::HandleTopLevelDeclInObjCContainer(DeclGroupRef DG) { 335fa06f0464a04bb7fce1fcfb3780d151bb029e00cJordan Rose storeTopLevelDecls(DG); 336c03a39e16762627b421247b12a2658be630a3300Anna Zaks} 337c03a39e16762627b421247b12a2658be630a3300Anna Zaks 338c03a39e16762627b421247b12a2658be630a3300Anna Zaksvoid AnalysisConsumer::storeTopLevelDecls(DeclGroupRef DG) { 339c03a39e16762627b421247b12a2658be630a3300Anna Zaks for (DeclGroupRef::iterator I = DG.begin(), E = DG.end(); I != E; ++I) { 340c03a39e16762627b421247b12a2658be630a3300Anna Zaks 341c03a39e16762627b421247b12a2658be630a3300Anna Zaks // Skip ObjCMethodDecl, wait for the objc container to avoid 342c03a39e16762627b421247b12a2658be630a3300Anna Zaks // analyzing twice. 343c03a39e16762627b421247b12a2658be630a3300Anna Zaks if (isa<ObjCMethodDecl>(*I)) 344c03a39e16762627b421247b12a2658be630a3300Anna Zaks continue; 345c03a39e16762627b421247b12a2658be630a3300Anna Zaks 346aa0aeb1cbe117db68d35700cb3a34aace0f99b99Anna Zaks LocalTUDecls.push_back(*I); 347aa0aeb1cbe117db68d35700cb3a34aace0f99b99Anna Zaks } 348fa06f0464a04bb7fce1fcfb3780d151bb029e00cJordan Rose} 349aa0aeb1cbe117db68d35700cb3a34aace0f99b99Anna Zaks 350aa0aeb1cbe117db68d35700cb3a34aace0f99b99Anna Zaksstatic bool shouldSkipFunction(CallGraphNode *N, 351ebae6d0209e1ec3d5ea14f9e63bd0d740218ed14Anna Zaks SmallPtrSet<CallGraphNode*,24> Visited) { 3528ad8c546372fe602708cb7ceeaf0ebbb866735c6Anna Zaks // We want to re-analyse the functions as top level in several cases: 353aa0aeb1cbe117db68d35700cb3a34aace0f99b99Anna Zaks // - The 'init' methods should be reanalyzed because 354aa0aeb1cbe117db68d35700cb3a34aace0f99b99Anna Zaks // ObjCNonNilReturnValueChecker assumes that '[super init]' never returns 355aa0aeb1cbe117db68d35700cb3a34aace0f99b99Anna Zaks // 'nil' and unless we analyze the 'init' functions as top level, we will not 356aa0aeb1cbe117db68d35700cb3a34aace0f99b99Anna Zaks // catch errors within defensive code. 357aa0aeb1cbe117db68d35700cb3a34aace0f99b99Anna Zaks // - We want to reanalyze all ObjC methods as top level to report Retain 3586bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines // Count naming convention errors more aggressively. 3596bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines if (isa<ObjCMethodDecl>(N->getDecl())) 360ebae6d0209e1ec3d5ea14f9e63bd0d740218ed14Anna Zaks return false; 361ebae6d0209e1ec3d5ea14f9e63bd0d740218ed14Anna Zaks 362ebae6d0209e1ec3d5ea14f9e63bd0d740218ed14Anna Zaks // Otherwise, if we visited the function before, do not reanalyze it. 363ebae6d0209e1ec3d5ea14f9e63bd0d740218ed14Anna Zaks return Visited.count(N); 3648ad8c546372fe602708cb7ceeaf0ebbb866735c6Anna Zaks} 365aa0aeb1cbe117db68d35700cb3a34aace0f99b99Anna Zaks 3666bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hinesvoid AnalysisConsumer::HandleDeclsGallGraph(const unsigned LocalTUDeclsSize) { 3676bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines // Otherwise, use the Callgraph to derive the order. 368ebae6d0209e1ec3d5ea14f9e63bd0d740218ed14Anna Zaks // Build the Call Graph. 369ebae6d0209e1ec3d5ea14f9e63bd0d740218ed14Anna Zaks CallGraph CG; 370ebae6d0209e1ec3d5ea14f9e63bd0d740218ed14Anna Zaks 371ebae6d0209e1ec3d5ea14f9e63bd0d740218ed14Anna Zaks // Add all the top level declarations to the graph. 372ebae6d0209e1ec3d5ea14f9e63bd0d740218ed14Anna Zaks // Note: CallGraph can trigger deserialization of more items from a pch 373ebae6d0209e1ec3d5ea14f9e63bd0d740218ed14Anna Zaks // (though HandleInterestingDecl); triggering additions to LocalTUDecls. 374ebae6d0209e1ec3d5ea14f9e63bd0d740218ed14Anna Zaks // We rely on random access to add the initially processed Decls to CG. 375aa0aeb1cbe117db68d35700cb3a34aace0f99b99Anna Zaks for (unsigned i = 0 ; i < LocalTUDeclsSize ; ++i) { 3766b6152ba96c164a292cc0b8d8b1d4cecbec27a60Anna Zaks CG.addToCallGraph(LocalTUDecls[i]); 377fa06f0464a04bb7fce1fcfb3780d151bb029e00cJordan Rose } 378fa06f0464a04bb7fce1fcfb3780d151bb029e00cJordan Rose 379fa06f0464a04bb7fce1fcfb3780d151bb029e00cJordan Rose // Find the top level nodes - children of root + the unreachable (parentless) 3808ad8c546372fe602708cb7ceeaf0ebbb866735c6Anna Zaks // nodes. 3818ad8c546372fe602708cb7ceeaf0ebbb866735c6Anna Zaks llvm::SmallVector<CallGraphNode*, 24> TopLevelFunctions; 3828bef8238181a30e52dea380789a7e2d760eac532Ted Kremenek for (CallGraph::nodes_iterator TI = CG.parentless_begin(), 3836bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines TE = CG.parentless_end(); TI != TE; ++TI) { 384aa0aeb1cbe117db68d35700cb3a34aace0f99b99Anna Zaks TopLevelFunctions.push_back(*TI); 3858ad8c546372fe602708cb7ceeaf0ebbb866735c6Anna Zaks NumFunctionTopLevel++; 3868ad8c546372fe602708cb7ceeaf0ebbb866735c6Anna Zaks } 387fa06f0464a04bb7fce1fcfb3780d151bb029e00cJordan Rose CallGraphNode *Entry = CG.getRoot(); 3888ad8c546372fe602708cb7ceeaf0ebbb866735c6Anna Zaks for (CallGraphNode::iterator I = Entry->begin(), 389ebae6d0209e1ec3d5ea14f9e63bd0d740218ed14Anna Zaks E = Entry->end(); I != E; ++I) { 390fa06f0464a04bb7fce1fcfb3780d151bb029e00cJordan Rose TopLevelFunctions.push_back(*I); 391ebae6d0209e1ec3d5ea14f9e63bd0d740218ed14Anna Zaks NumFunctionTopLevel++; 392fa06f0464a04bb7fce1fcfb3780d151bb029e00cJordan Rose } 3936bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines 394fa06f0464a04bb7fce1fcfb3780d151bb029e00cJordan Rose // Make sure the nodes are sorted in order reverse of their definition in the 395fa06f0464a04bb7fce1fcfb3780d151bb029e00cJordan Rose // translation unit. This step is very important for performance. It ensures 396fa06f0464a04bb7fce1fcfb3780d151bb029e00cJordan Rose // that we analyze the root functions before the externally available 397fa06f0464a04bb7fce1fcfb3780d151bb029e00cJordan Rose // subroutines. 398ebae6d0209e1ec3d5ea14f9e63bd0d740218ed14Anna Zaks std::deque<CallGraphNode*> BFSQueue; 3998ad8c546372fe602708cb7ceeaf0ebbb866735c6Anna Zaks for (llvm::SmallVector<CallGraphNode*, 24>::reverse_iterator 4008ad8c546372fe602708cb7ceeaf0ebbb866735c6Anna Zaks TI = TopLevelFunctions.rbegin(), TE = TopLevelFunctions.rend(); 401cdcc653642d4ac9255c574fabe74a48149e06733Anna Zaks TI != TE; ++TI) 402cdcc653642d4ac9255c574fabe74a48149e06733Anna Zaks BFSQueue.push_back(*TI); 403a19f4af7a94835ce4693bfe12d6270754e79eb56Anna Zaks 404651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // BFS over all of the functions, while skipping the ones inlined into 4059c378f705405d37f49795d5e915989de774fe11fTed Kremenek // the previously processed functions. Use external Visited set, which is 4069c378f705405d37f49795d5e915989de774fe11fTed Kremenek // also modified when we inline a function. 40752a16499df87730c0252b431abdf2b2e32d756a6Ted Kremenek SmallPtrSet<CallGraphNode*,24> Visited; 408520035439d7133064325c4df6378c5a8f2f05539Ted Kremenek while(!BFSQueue.empty()) { 409520035439d7133064325c4df6378c5a8f2f05539Ted Kremenek CallGraphNode *N = BFSQueue.front(); 4101eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump BFSQueue.pop_front(); 4117d7fe6d539b3bdb1701835223cca306c325614a7Ted Kremenek 4121aae01a8308d2f8e31adab3f4d7ac35543aac680Anna Zaks // Push the children into the queue. 4131aae01a8308d2f8e31adab3f4d7ac35543aac680Anna Zaks for (CallGraphNode::const_iterator CI = N->begin(), 414ad62deeb70e97da6bd514dd390ea1ce6af6ad81dAnna Zaks CE = N->end(); CI != CE; ++CI) { 4151aae01a8308d2f8e31adab3f4d7ac35543aac680Anna Zaks if (!shouldSkipFunction(*CI, Visited)) 416cdcc653642d4ac9255c574fabe74a48149e06733Anna Zaks BFSQueue.push_back(*CI); 4172d950b15b2b2b650b102ecf0c6b50b45e0cb6a8aAnna Zaks } 418cdcc653642d4ac9255c574fabe74a48149e06733Anna Zaks 419cdcc653642d4ac9255c574fabe74a48149e06733Anna Zaks // Skip the functions which have been processed already or previously 420cdcc653642d4ac9255c574fabe74a48149e06733Anna Zaks // inlined. 421031ccc0555a82afc2e8afe29e19dd57ff204e2deZhongxing Xu if (shouldSkipFunction(N, Visited)) 4221aae01a8308d2f8e31adab3f4d7ac35543aac680Anna Zaks continue; 4231aae01a8308d2f8e31adab3f4d7ac35543aac680Anna Zaks 4241aae01a8308d2f8e31adab3f4d7ac35543aac680Anna Zaks // Analyze the function. 4251aae01a8308d2f8e31adab3f4d7ac35543aac680Anna Zaks SetOfConstDecls VisitedCallees; 426cdcc653642d4ac9255c574fabe74a48149e06733Anna Zaks Decl *D = N->getDecl(); 427cdcc653642d4ac9255c574fabe74a48149e06733Anna Zaks assert(D); 428cdcc653642d4ac9255c574fabe74a48149e06733Anna Zaks HandleCode(D, ANALYSIS_PATH, 4298083414ee7cc8f5c807ed6a4e120fb4e0ab50ff8Ted Kremenek (Mgr->options.InliningMode == All ? 0 : &VisitedCallees)); 4308bef8238181a30e52dea380789a7e2d760eac532Ted Kremenek 431c9003c89c7aead1686aba89c8e3ddcea1f2bec54Anna Zaks // Add the visited callees to the global visited set. 4321eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump for (SetOfConstDecls::iterator I = VisitedCallees.begin(), 4339c378f705405d37f49795d5e915989de774fe11fTed Kremenek E = VisitedCallees.end(); I != E; ++I) { 4348e49dd6e7e73b275a74338a5127a524f0765303cTed Kremenek CallGraphNode *VN = CG.getNode(*I); 4351eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump if (VN) 4361eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump Visited.insert(VN); 43752a16499df87730c0252b431abdf2b2e32d756a6Ted Kremenek } 438520035439d7133064325c4df6378c5a8f2f05539Ted Kremenek Visited.insert(N); 4394e82d3cf6fd4c907265e3fa3aac0a835c35dc759Anna Zaks } 440520035439d7133064325c4df6378c5a8f2f05539Ted Kremenek} 4414e82d3cf6fd4c907265e3fa3aac0a835c35dc759Anna Zaks 442520035439d7133064325c4df6378c5a8f2f05539Ted Kremenekvoid AnalysisConsumer::HandleTranslationUnit(ASTContext &C) { 4431eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump // Don't run the actions if an error has occurred with parsing the file. 444520035439d7133064325c4df6378c5a8f2f05539Ted Kremenek DiagnosticsEngine &Diags = PP.getDiagnostics(); 445520035439d7133064325c4df6378c5a8f2f05539Ted Kremenek if (Diags.hasErrorOccurred() || Diags.hasFatalErrorOccurred()) 44652a16499df87730c0252b431abdf2b2e32d756a6Ted Kremenek return; 4477d7fe6d539b3bdb1701835223cca306c325614a7Ted Kremenek 448031ccc0555a82afc2e8afe29e19dd57ff204e2deZhongxing Xu { 449d2592a34a059e7cbb2b11dc53649ac4912422909Argyrios Kyrtzidis if (TUTotalTimer) TUTotalTimer->startTimer(); 450d2592a34a059e7cbb2b11dc53649ac4912422909Argyrios Kyrtzidis 4519c378f705405d37f49795d5e915989de774fe11fTed Kremenek // Introduce a scope to destroy BR before Mgr. 4529c378f705405d37f49795d5e915989de774fe11fTed Kremenek BugReporter BR(*Mgr); 4539c378f705405d37f49795d5e915989de774fe11fTed Kremenek TranslationUnitDecl *TU = C.getTranslationUnitDecl(); 4549c378f705405d37f49795d5e915989de774fe11fTed Kremenek checkerMgr->runCheckersOnASTDecl(TU, *Mgr, BR); 455031ccc0555a82afc2e8afe29e19dd57ff204e2deZhongxing Xu 456754607e7cff2d902d9af8b771409449fb2f8d2bfTed Kremenek // Run the AST-only checks using the order in which functions are defined. 4579c378f705405d37f49795d5e915989de774fe11fTed Kremenek // If inlining is not turned on, use the simplest function order for path 4589c378f705405d37f49795d5e915989de774fe11fTed Kremenek // sensitive analyzes as well. 45903509aea098772644bf4662dc1c88634818ceeccZhongxing Xu RecVisitorMode = (Mgr->shouldInlineCall() ? ANALYSIS_SYNTAX : ANALYSIS_ALL); 460754607e7cff2d902d9af8b771409449fb2f8d2bfTed Kremenek RecVisitorBR = &BR; 461031ccc0555a82afc2e8afe29e19dd57ff204e2deZhongxing Xu 46203509aea098772644bf4662dc1c88634818ceeccZhongxing Xu // Process all the top level declarations. 4631eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump // 464d2592a34a059e7cbb2b11dc53649ac4912422909Argyrios Kyrtzidis // Note: TraverseDecl may modify LocalTUDecls, but only by appending more 46503509aea098772644bf4662dc1c88634818ceeccZhongxing Xu // entries. Thus we don't use an iterator, but rely on LocalTUDecls 466754607e7cff2d902d9af8b771409449fb2f8d2bfTed Kremenek // random access. By doing so, we automatically compensate for iterators 4671eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump // possibly being invalidated, although this is a bit slower. 4689c378f705405d37f49795d5e915989de774fe11fTed Kremenek const unsigned LocalTUDeclsSize = LocalTUDecls.size(); 4699c378f705405d37f49795d5e915989de774fe11fTed Kremenek for (unsigned i = 0 ; i < LocalTUDeclsSize ; ++i) { 4701eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump TraverseDecl(LocalTUDecls[i]); 471ad8dcf4a9df0e24051dc31bf9e6f3cd138a34298Chris Lattner } 472cfa88f893915ceb8ae4ce2f17c46c24a4d67502fDmitri Gribenko 47324f1a967741ff9f8025ee23be12ba6feacc31f77Ted Kremenek if (Mgr->shouldInlineCall()) 4741eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump HandleDeclsGallGraph(LocalTUDeclsSize); 475ad8dcf4a9df0e24051dc31bf9e6f3cd138a34298Chris Lattner 47624f1a967741ff9f8025ee23be12ba6feacc31f77Ted Kremenek // After all decls handled, run checkers on the entire TranslationUnit. 47724f1a967741ff9f8025ee23be12ba6feacc31f77Ted Kremenek checkerMgr->runCheckersOnEndOfTranslationUnit(TU, *Mgr, BR); 478754607e7cff2d902d9af8b771409449fb2f8d2bfTed Kremenek 4791eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump RecVisitorBR = 0; 480031ccc0555a82afc2e8afe29e19dd57ff204e2deZhongxing Xu } 481031ccc0555a82afc2e8afe29e19dd57ff204e2deZhongxing Xu 4821eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump // Explicitly destroy the PathDiagnosticConsumer. This will flush its output. 48318c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek // FIXME: This should be replaced with something that doesn't rely on 4848bef8238181a30e52dea380789a7e2d760eac532Ted Kremenek // side-effects in PathDiagnosticConsumer's destructor. This is required when 485031ccc0555a82afc2e8afe29e19dd57ff204e2deZhongxing Xu // used with option -disable-free. 4861eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump Mgr.reset(NULL); 4879c378f705405d37f49795d5e915989de774fe11fTed Kremenek 488754607e7cff2d902d9af8b771409449fb2f8d2bfTed Kremenek if (TUTotalTimer) TUTotalTimer->stopTimer(); 4898bef8238181a30e52dea380789a7e2d760eac532Ted Kremenek 4905eca482fe895ea57bc82410222e6426c09e63284Ted Kremenek // Count how many basic blocks we have not covered. 4915eca482fe895ea57bc82410222e6426c09e63284Ted Kremenek NumBlocksInAnalyzedFunctions = FunctionSummaries.getTotalNumBasicBlocks(); 4925eca482fe895ea57bc82410222e6426c09e63284Ted Kremenek if (NumBlocksInAnalyzedFunctions > 0) 4935eca482fe895ea57bc82410222e6426c09e63284Ted Kremenek PercentReachableBlocks = 494754607e7cff2d902d9af8b771409449fb2f8d2bfTed Kremenek (FunctionSummaries.getTotalNumVisitedBasicBlocks() * 100) / 4951eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump NumBlocksInAnalyzedFunctions; 496d2592a34a059e7cbb2b11dc53649ac4912422909Argyrios Kyrtzidis 497d2592a34a059e7cbb2b11dc53649ac4912422909Argyrios Kyrtzidis} 4989c378f705405d37f49795d5e915989de774fe11fTed Kremenek 4999c378f705405d37f49795d5e915989de774fe11fTed Kremenekstatic void FindBlocks(DeclContext *D, SmallVectorImpl<Decl*> &WL) { 5009c378f705405d37f49795d5e915989de774fe11fTed Kremenek if (BlockDecl *BD = dyn_cast<BlockDecl>(D)) 501031ccc0555a82afc2e8afe29e19dd57ff204e2deZhongxing Xu WL.push_back(BD); 502daeb9a7376830d637e02b5bc51faf4750a7bce70Ted Kremenek 5039c378f705405d37f49795d5e915989de774fe11fTed Kremenek for (DeclContext::decl_iterator I = D->decls_begin(), E = D->decls_end(); 5049c378f705405d37f49795d5e915989de774fe11fTed Kremenek I!=E; ++I) 505daeb9a7376830d637e02b5bc51faf4750a7bce70Ted Kremenek if (DeclContext *DC = dyn_cast<DeclContext>(*I)) 5061eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump FindBlocks(DC, WL); 507031ccc0555a82afc2e8afe29e19dd57ff204e2deZhongxing Xu} 50803509aea098772644bf4662dc1c88634818ceeccZhongxing Xu 5091eb4433ac451dc16f4133a88af2d002ac26c58efMike Stumpstatic std::string getFunctionName(const Decl *D) { 510d2592a34a059e7cbb2b11dc53649ac4912422909Argyrios Kyrtzidis if (const ObjCMethodDecl *ID = dyn_cast<ObjCMethodDecl>(D)) { 51103509aea098772644bf4662dc1c88634818ceeccZhongxing Xu return ID->getSelector().getAsString(); 512031ccc0555a82afc2e8afe29e19dd57ff204e2deZhongxing Xu } 513daeb9a7376830d637e02b5bc51faf4750a7bce70Ted Kremenek if (const FunctionDecl *ND = dyn_cast<FunctionDecl>(D)) { 5149c378f705405d37f49795d5e915989de774fe11fTed Kremenek IdentifierInfo *II = ND->getIdentifier(); 51534feff654c6304e0a59ceb1376989d28dbc956ffTed Kremenek if (II) 51634feff654c6304e0a59ceb1376989d28dbc956ffTed Kremenek return II->getName(); 5171eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump } 5189c378f705405d37f49795d5e915989de774fe11fTed Kremenek return ""; 519cfa88f893915ceb8ae4ce2f17c46c24a4d67502fDmitri Gribenko} 520daeb9a7376830d637e02b5bc51faf4750a7bce70Ted Kremenek 5211eb4433ac451dc16f4133a88af2d002ac26c58efMike Stumpbool AnalysisConsumer::skipFunction(Decl *D) { 5229c378f705405d37f49795d5e915989de774fe11fTed Kremenek if (!Opts->AnalyzeSpecificFunction.empty() && 523daeb9a7376830d637e02b5bc51faf4750a7bce70Ted Kremenek getFunctionName(D) != Opts->AnalyzeSpecificFunction) 524daeb9a7376830d637e02b5bc51faf4750a7bce70Ted Kremenek return true; 525daeb9a7376830d637e02b5bc51faf4750a7bce70Ted Kremenek 5261eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump // Don't run the actions on declarations in header files unless 527031ccc0555a82afc2e8afe29e19dd57ff204e2deZhongxing Xu // otherwise specified. 528031ccc0555a82afc2e8afe29e19dd57ff204e2deZhongxing Xu SourceManager &SM = Ctx->getSourceManager(); 5291eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump SourceLocation SL = SM.getExpansionLoc(D->getLocation()); 5304d3175c1e5a44251ea97b0c81e80f060629d9c08Ted Kremenek if (!Opts->AnalyzeAll && !SM.isFromMainFile(SL)) 531cfa88f893915ceb8ae4ce2f17c46c24a4d67502fDmitri Gribenko return true; 5324d3175c1e5a44251ea97b0c81e80f060629d9c08Ted Kremenek 5334d3175c1e5a44251ea97b0c81e80f060629d9c08Ted Kremenek return false; 53418c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek} 5358bef8238181a30e52dea380789a7e2d760eac532Ted Kremenek 5361eb4433ac451dc16f4133a88af2d002ac26c58efMike Stumpvoid AnalysisConsumer::HandleCode(Decl *D, AnalysisMode Mode, 5378bef8238181a30e52dea380789a7e2d760eac532Ted Kremenek SetOfConstDecls *VisitedCallees) { 538031ccc0555a82afc2e8afe29e19dd57ff204e2deZhongxing Xu if (skipFunction(D)) 5391eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump return; 5409c378f705405d37f49795d5e915989de774fe11fTed Kremenek 541daeb9a7376830d637e02b5bc51faf4750a7bce70Ted Kremenek DisplayFunction(D, Mode); 5428bef8238181a30e52dea380789a7e2d760eac532Ted Kremenek CFG *DeclCFG = Mgr->getCFG(D); 5435eca482fe895ea57bc82410222e6426c09e63284Ted Kremenek if (DeclCFG) { 5445eca482fe895ea57bc82410222e6426c09e63284Ted Kremenek unsigned CFGSize = DeclCFG->size(); 5455eca482fe895ea57bc82410222e6426c09e63284Ted Kremenek MaxCFGSize = MaxCFGSize < CFGSize ? CFGSize : MaxCFGSize; 5465eca482fe895ea57bc82410222e6426c09e63284Ted Kremenek } 547daeb9a7376830d637e02b5bc51faf4750a7bce70Ted Kremenek 54811062b118476368fa5b294954713e5df97d8599fTed Kremenek 5493070e13dca5bbefa32acb80ce4a7b217a6220983Ted Kremenek // Clear the AnalysisManager of old AnalysisDeclContexts. 550f24af5bc2e01ca8e7396ed997378a77fddfa521eTed Kremenek Mgr->ClearContexts(); 551f24af5bc2e01ca8e7396ed997378a77fddfa521eTed Kremenek 552f24af5bc2e01ca8e7396ed997378a77fddfa521eTed Kremenek // Dispatch on the actions. 553 SmallVector<Decl*, 10> WL; 554 WL.push_back(D); 555 556 if (D->hasBody() && Opts->AnalyzeNestedBlocks) 557 FindBlocks(cast<DeclContext>(D), WL); 558 559 BugReporter BR(*Mgr); 560 for (SmallVectorImpl<Decl*>::iterator WI=WL.begin(), WE=WL.end(); 561 WI != WE; ++WI) 562 if ((*WI)->hasBody()) { 563 if (Mode != ANALYSIS_PATH) 564 checkerMgr->runCheckersOnASTBody(*WI, *Mgr, BR); 565 if (Mode != ANALYSIS_SYNTAX && checkerMgr->hasPathSensitiveCheckers()) { 566 RunPathSensitiveChecks(*WI, VisitedCallees); 567 NumFunctionsAnalyzed++; 568 } 569 } 570} 571 572//===----------------------------------------------------------------------===// 573// Path-sensitive checking. 574//===----------------------------------------------------------------------===// 575 576void AnalysisConsumer::ActionExprEngine(Decl *D, bool ObjCGCEnabled, 577 SetOfConstDecls *VisitedCallees) { 578 // Construct the analysis engine. First check if the CFG is valid. 579 // FIXME: Inter-procedural analysis will need to handle invalid CFGs. 580 if (!Mgr->getCFG(D)) 581 return; 582 583 // See if the LiveVariables analysis scales. 584 if (!Mgr->getAnalysisDeclContext(D)->getAnalysis<RelaxedLiveVariables>()) 585 return; 586 587 ExprEngine Eng(*Mgr, ObjCGCEnabled, VisitedCallees, &FunctionSummaries); 588 589 // Set the graph auditor. 590 OwningPtr<ExplodedNode::Auditor> Auditor; 591 if (Mgr->options.visualizeExplodedGraphWithUbiGraph) { 592 Auditor.reset(CreateUbiViz()); 593 ExplodedNode::SetAuditor(Auditor.get()); 594 } 595 596 // Execute the worklist algorithm. 597 Eng.ExecuteWorkList(Mgr->getAnalysisDeclContextManager().getStackFrame(D), 598 Mgr->options.MaxNodes); 599 600 // Release the auditor (if any) so that it doesn't monitor the graph 601 // created BugReporter. 602 ExplodedNode::SetAuditor(0); 603 604 // Visualize the exploded graph. 605 if (Mgr->options.visualizeExplodedGraphWithGraphViz) 606 Eng.ViewGraph(Mgr->options.TrimGraph); 607 608 // Display warnings. 609 Eng.getBugReporter().FlushReports(); 610} 611 612void AnalysisConsumer::RunPathSensitiveChecks(Decl *D, 613 SetOfConstDecls *Visited) { 614 615 switch (Mgr->getLangOpts().getGC()) { 616 case LangOptions::NonGC: 617 ActionExprEngine(D, false, Visited); 618 break; 619 620 case LangOptions::GCOnly: 621 ActionExprEngine(D, true, Visited); 622 break; 623 624 case LangOptions::HybridGC: 625 ActionExprEngine(D, false, Visited); 626 ActionExprEngine(D, true, Visited); 627 break; 628 } 629} 630 631//===----------------------------------------------------------------------===// 632// AnalysisConsumer creation. 633//===----------------------------------------------------------------------===// 634 635ASTConsumer* ento::CreateAnalysisConsumer(const Preprocessor& pp, 636 const std::string& outDir, 637 AnalyzerOptionsRef opts, 638 ArrayRef<std::string> plugins) { 639 // Disable the effects of '-Werror' when using the AnalysisConsumer. 640 pp.getDiagnostics().setWarningsAsErrors(false); 641 642 return new AnalysisConsumer(pp, outDir, opts, plugins); 643} 644 645//===----------------------------------------------------------------------===// 646// Ubigraph Visualization. FIXME: Move to separate file. 647//===----------------------------------------------------------------------===// 648 649namespace { 650 651class UbigraphViz : public ExplodedNode::Auditor { 652 OwningPtr<raw_ostream> Out; 653 llvm::sys::Path Dir, Filename; 654 unsigned Cntr; 655 656 typedef llvm::DenseMap<void*,unsigned> VMap; 657 VMap M; 658 659public: 660 UbigraphViz(raw_ostream *out, llvm::sys::Path& dir, 661 llvm::sys::Path& filename); 662 663 ~UbigraphViz(); 664 665 virtual void AddEdge(ExplodedNode *Src, ExplodedNode *Dst); 666}; 667 668} // end anonymous namespace 669 670static ExplodedNode::Auditor* CreateUbiViz() { 671 std::string ErrMsg; 672 673 llvm::sys::Path Dir = llvm::sys::Path::GetTemporaryDirectory(&ErrMsg); 674 if (!ErrMsg.empty()) 675 return 0; 676 677 llvm::sys::Path Filename = Dir; 678 Filename.appendComponent("llvm_ubi"); 679 Filename.makeUnique(true,&ErrMsg); 680 681 if (!ErrMsg.empty()) 682 return 0; 683 684 llvm::errs() << "Writing '" << Filename.str() << "'.\n"; 685 686 OwningPtr<llvm::raw_fd_ostream> Stream; 687 Stream.reset(new llvm::raw_fd_ostream(Filename.c_str(), ErrMsg)); 688 689 if (!ErrMsg.empty()) 690 return 0; 691 692 return new UbigraphViz(Stream.take(), Dir, Filename); 693} 694 695void UbigraphViz::AddEdge(ExplodedNode *Src, ExplodedNode *Dst) { 696 697 assert (Src != Dst && "Self-edges are not allowed."); 698 699 // Lookup the Src. If it is a new node, it's a root. 700 VMap::iterator SrcI= M.find(Src); 701 unsigned SrcID; 702 703 if (SrcI == M.end()) { 704 M[Src] = SrcID = Cntr++; 705 *Out << "('vertex', " << SrcID << ", ('color','#00ff00'))\n"; 706 } 707 else 708 SrcID = SrcI->second; 709 710 // Lookup the Dst. 711 VMap::iterator DstI= M.find(Dst); 712 unsigned DstID; 713 714 if (DstI == M.end()) { 715 M[Dst] = DstID = Cntr++; 716 *Out << "('vertex', " << DstID << ")\n"; 717 } 718 else { 719 // We have hit DstID before. Change its style to reflect a cache hit. 720 DstID = DstI->second; 721 *Out << "('change_vertex_style', " << DstID << ", 1)\n"; 722 } 723 724 // Add the edge. 725 *Out << "('edge', " << SrcID << ", " << DstID 726 << ", ('arrow','true'), ('oriented', 'true'))\n"; 727} 728 729UbigraphViz::UbigraphViz(raw_ostream *out, llvm::sys::Path& dir, 730 llvm::sys::Path& filename) 731 : Out(out), Dir(dir), Filename(filename), Cntr(0) { 732 733 *Out << "('vertex_style_attribute', 0, ('shape', 'icosahedron'))\n"; 734 *Out << "('vertex_style', 1, 0, ('shape', 'sphere'), ('color', '#ffcc66')," 735 " ('size', '1.5'))\n"; 736} 737 738UbigraphViz::~UbigraphViz() { 739 Out.reset(0); 740 llvm::errs() << "Running 'ubiviz' program... "; 741 std::string ErrMsg; 742 llvm::sys::Path Ubiviz = llvm::sys::Program::FindProgramByName("ubiviz"); 743 std::vector<const char*> args; 744 args.push_back(Ubiviz.c_str()); 745 args.push_back(Filename.c_str()); 746 args.push_back(0); 747 748 if (llvm::sys::Program::ExecuteAndWait(Ubiviz, &args[0],0,0,0,0,&ErrMsg)) { 749 llvm::errs() << "Error viewing graph: " << ErrMsg << "\n"; 750 } 751 752 // Delete the directory. 753 Dir.eraseFromDisk(true); 754} 755