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