AnalysisConsumer.cpp revision 3fd5f370a28552976c52e76c3035d79012d78dda
1f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek//===--- AnalysisConsumer.cpp - ASTConsumer for running Analyses ----------===//
2f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek//
3f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek//                     The LLVM Compiler Infrastructure
4f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek//
5f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek// This file is distributed under the University of Illinois Open Source
6f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek// License. See LICENSE.TXT for details.
7f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek//
8f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek//===----------------------------------------------------------------------===//
9f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek//
10f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek// "Meta" ASTConsumer for running different source analyses.
11f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek//
12f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek//===----------------------------------------------------------------------===//
13f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek
14d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks#define DEBUG_TYPE "AnalysisConsumer"
15d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks
16e6348c336fecc8da9288ea367375a1b1cd2358d2Argyrios Kyrtzidis#include "AnalysisConsumer.h"
17f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek#include "clang/AST/ASTConsumer.h"
18f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek#include "clang/AST/Decl.h"
19802be99a6817aba6edb166b93c133da4358aa783Zhongxing Xu#include "clang/AST/DeclCXX.h"
20f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek#include "clang/AST/DeclObjC.h"
21efceabd2380f49306bc0229583458e93b062094bDaniel Dunbar#include "clang/AST/ParentMap.h"
22efceabd2380f49306bc0229583458e93b062094bDaniel Dunbar#include "clang/Analysis/CFG.h"
23d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks#include "clang/Analysis/CallGraph.h"
2427af04bcca46f8a3374586be1301477f9123f5e1Argyrios Kyrtzidis#include "clang/StaticAnalyzer/Frontend/CheckerRegistration.h"
2543dee220252ef0b42c5f8a3bb1eca97f84f2565fArgyrios Kyrtzidis#include "clang/StaticAnalyzer/Core/CheckerManager.h"
2621142581d55918beed544a757e4af3bb865b1812Ted Kremenek#include "clang/StaticAnalyzer/Checkers/LocalCheckers.h"
279b663716449b618ba0390b1dbebc54fa8e971124Ted Kremenek#include "clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h"
289b663716449b618ba0390b1dbebc54fa8e971124Ted Kremenek#include "clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h"
299b663716449b618ba0390b1dbebc54fa8e971124Ted Kremenek#include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h"
309b663716449b618ba0390b1dbebc54fa8e971124Ted Kremenek#include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
31f39d962cf84f46d2c0512157259ae1d41a1a5173David Blaikie#include "clang/StaticAnalyzer/Core/PathDiagnosticConsumers.h"
32a7af5ea88a6c5bdf87497cca6c20831e8c546751Argyrios Kyrtzidis
33efceabd2380f49306bc0229583458e93b062094bDaniel Dunbar#include "clang/Basic/FileManager.h"
34efceabd2380f49306bc0229583458e93b062094bDaniel Dunbar#include "clang/Basic/SourceManager.h"
359b414d3e2d0cb84512b55a3275a98490b090162aDaniel Dunbar#include "clang/Frontend/AnalyzerOptions.h"
36efceabd2380f49306bc0229583458e93b062094bDaniel Dunbar#include "clang/Lex/Preprocessor.h"
37f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek#include "llvm/Support/raw_ostream.h"
3803013fa9a0bf1ef4b907f5fec006c8f4000fdd21Michael J. Spencer#include "llvm/Support/Path.h"
3903013fa9a0bf1ef4b907f5fec006c8f4000fdd21Michael J. Spencer#include "llvm/Support/Program.h"
40d38f79543136ba68cd14b1dab0856474df1fbfd5Anna Zaks#include "llvm/Support/Timer.h"
41d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks#include "llvm/ADT/DepthFirstIterator.h"
426cb7c1a43b0c8f739d1f54b7fdae5ede86033496Benjamin Kramer#include "llvm/ADT/OwningPtr.h"
4381fb169f42769e02c7425b23885a261c025fd5e6Anna Zaks#include "llvm/ADT/Statistic.h"
44db09a4dee28a4515438af60f2d2b4a83e4965c31Ted Kremenek
45f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenekusing namespace clang;
469ef6537a894c33003359b1f9b9676e9178e028b7Ted Kremenekusing namespace ento;
47d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaksusing llvm::SmallPtrSet;
48f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek
49c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xustatic ExplodedNode::Auditor* CreateUbiViz();
50ff944a8c481d6c0f1ad2633e4be9bf8b1dd2a09fZhongxing Xu
513fd5f370a28552976c52e76c3035d79012d78ddaAnna ZaksSTATISTIC(NumFunctionTopLevel, "The # of functions at top level.");
52d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna ZaksSTATISTIC(NumFunctionsAnalyzed, "The # of functions analysed (as top level).");
53d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks
54be1fe1eb12a1cb91c8e3a9fcc2db4dfe989def6cTed Kremenek//===----------------------------------------------------------------------===//
55f39d962cf84f46d2c0512157259ae1d41a1a5173David Blaikie// Special PathDiagnosticConsumers.
56f75560670bcdd59b051149bdece3eac14e313853Ted Kremenek//===----------------------------------------------------------------------===//
57f75560670bcdd59b051149bdece3eac14e313853Ted Kremenek
58ef3643fbbbf66247c5e205497fae0f46e240c143David Blaikiestatic PathDiagnosticConsumer*
59ef3643fbbbf66247c5e205497fae0f46e240c143David BlaikiecreatePlistHTMLDiagnosticConsumer(const std::string& prefix,
60efceabd2380f49306bc0229583458e93b062094bDaniel Dunbar                                const Preprocessor &PP) {
61ef3643fbbbf66247c5e205497fae0f46e240c143David Blaikie  PathDiagnosticConsumer *PD =
62ef3643fbbbf66247c5e205497fae0f46e240c143David Blaikie    createHTMLDiagnosticConsumer(llvm::sys::path::parent_path(prefix), PP);
63ef3643fbbbf66247c5e205497fae0f46e240c143David Blaikie  return createPlistDiagnosticConsumer(prefix, PP, PD);
64f75560670bcdd59b051149bdece3eac14e313853Ted Kremenek}
65f75560670bcdd59b051149bdece3eac14e313853Ted Kremenek
66f75560670bcdd59b051149bdece3eac14e313853Ted Kremenek//===----------------------------------------------------------------------===//
67f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek// AnalysisConsumer declaration.
68f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek//===----------------------------------------------------------------------===//
69f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek
70f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremeneknamespace {
71f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek
72ed8afacb8118b71bcfa8017059e51da325e7691bZhongxing Xuclass AnalysisConsumer : public ASTConsumer {
73ed8afacb8118b71bcfa8017059e51da325e7691bZhongxing Xupublic:
749c378f705405d37f49795d5e915989de774fe11fTed Kremenek  ASTContext *Ctx;
751d9cbeb76cf4c36acf5545028e2b2ac207086442Ted Kremenek  const Preprocessor &PP;
761d9cbeb76cf4c36acf5545028e2b2ac207086442Ted Kremenek  const std::string OutDir;
771d9cbeb76cf4c36acf5545028e2b2ac207086442Ted Kremenek  AnalyzerOptions Opts;
7808b86531ade68727c56918f162816075b87c864aJordy Rose  ArrayRef<std::string> Plugins;
79d07a0d0279c09d1017f8450fce575a94dc9703c0Zhongxing Xu
801d9cbeb76cf4c36acf5545028e2b2ac207086442Ted Kremenek  // PD is owned by AnalysisManager.
81ef3643fbbbf66247c5e205497fae0f46e240c143David Blaikie  PathDiagnosticConsumer *PD;
82d07a0d0279c09d1017f8450fce575a94dc9703c0Zhongxing Xu
831d9cbeb76cf4c36acf5545028e2b2ac207086442Ted Kremenek  StoreManagerCreator CreateStoreMgr;
841d9cbeb76cf4c36acf5545028e2b2ac207086442Ted Kremenek  ConstraintManagerCreator CreateConstraintMgr;
85f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek
866f42b62b6194f53bcbc349f5d17388e1936535d7Dylan Noblesmith  OwningPtr<CheckerManager> checkerMgr;
876f42b62b6194f53bcbc349f5d17388e1936535d7Dylan Noblesmith  OwningPtr<AnalysisManager> Mgr;
88c471e7b44e63ff1b46b480e723c4130aeaef5a8aZhongxing Xu
89d38f79543136ba68cd14b1dab0856474df1fbfd5Anna Zaks  /// Time the analyzes time of each translation unit.
90d38f79543136ba68cd14b1dab0856474df1fbfd5Anna Zaks  static llvm::Timer* TUTotalTimer;
91d38f79543136ba68cd14b1dab0856474df1fbfd5Anna Zaks
921d9cbeb76cf4c36acf5545028e2b2ac207086442Ted Kremenek  AnalysisConsumer(const Preprocessor& pp,
931d9cbeb76cf4c36acf5545028e2b2ac207086442Ted Kremenek                   const std::string& outdir,
9408b86531ade68727c56918f162816075b87c864aJordy Rose                   const AnalyzerOptions& opts,
9508b86531ade68727c56918f162816075b87c864aJordy Rose                   ArrayRef<std::string> plugins)
9608b86531ade68727c56918f162816075b87c864aJordy Rose    : Ctx(0), PP(pp), OutDir(outdir), Opts(opts), Plugins(plugins), PD(0) {
971d9cbeb76cf4c36acf5545028e2b2ac207086442Ted Kremenek    DigestAnalyzerOptions();
98d38f79543136ba68cd14b1dab0856474df1fbfd5Anna Zaks    if (Opts.PrintStats) {
99d38f79543136ba68cd14b1dab0856474df1fbfd5Anna Zaks      llvm::EnableStatistics();
100d38f79543136ba68cd14b1dab0856474df1fbfd5Anna Zaks      TUTotalTimer = new llvm::Timer("Analyzer Total Time");
101d38f79543136ba68cd14b1dab0856474df1fbfd5Anna Zaks    }
102d38f79543136ba68cd14b1dab0856474df1fbfd5Anna Zaks  }
103d38f79543136ba68cd14b1dab0856474df1fbfd5Anna Zaks
104d38f79543136ba68cd14b1dab0856474df1fbfd5Anna Zaks  ~AnalysisConsumer() {
105d38f79543136ba68cd14b1dab0856474df1fbfd5Anna Zaks    if (Opts.PrintStats)
106d38f79543136ba68cd14b1dab0856474df1fbfd5Anna Zaks      delete TUTotalTimer;
1071d9cbeb76cf4c36acf5545028e2b2ac207086442Ted Kremenek  }
108fda7832b000ff8927386f093b52c067641679469Zhongxing Xu
1091d9cbeb76cf4c36acf5545028e2b2ac207086442Ted Kremenek  void DigestAnalyzerOptions() {
110ef3643fbbbf66247c5e205497fae0f46e240c143David Blaikie    // Create the PathDiagnosticConsumer.
1111d9cbeb76cf4c36acf5545028e2b2ac207086442Ted Kremenek    if (!OutDir.empty()) {
1121d9cbeb76cf4c36acf5545028e2b2ac207086442Ted Kremenek      switch (Opts.AnalysisDiagOpt) {
1131d9cbeb76cf4c36acf5545028e2b2ac207086442Ted Kremenek      default:
114fda7832b000ff8927386f093b52c067641679469Zhongxing Xu#define ANALYSIS_DIAGNOSTICS(NAME, CMDFLAG, DESC, CREATEFN, AUTOCREATE) \
1151d9cbeb76cf4c36acf5545028e2b2ac207086442Ted Kremenek        case PD_##NAME: PD = CREATEFN(OutDir, PP); break;
116fda7832b000ff8927386f093b52c067641679469Zhongxing Xu#include "clang/Frontend/Analyses.def"
117fda7832b000ff8927386f093b52c067641679469Zhongxing Xu      }
118a599ae8826b01c0160a519b0fc5a4871f599bf04Argyrios Kyrtzidis    } else if (Opts.AnalysisDiagOpt == PD_TEXT) {
119a599ae8826b01c0160a519b0fc5a4871f599bf04Argyrios Kyrtzidis      // Create the text client even without a specified output file since
120a599ae8826b01c0160a519b0fc5a4871f599bf04Argyrios Kyrtzidis      // it just uses diagnostic notes.
121ef3643fbbbf66247c5e205497fae0f46e240c143David Blaikie      PD = createTextPathDiagnosticConsumer("", PP);
1221d9cbeb76cf4c36acf5545028e2b2ac207086442Ted Kremenek    }
123fda7832b000ff8927386f093b52c067641679469Zhongxing Xu
1241d9cbeb76cf4c36acf5545028e2b2ac207086442Ted Kremenek    // Create the analyzer component creators.
1255f83d6f36a7308eef21d87104fd70c421e854448Argyrios Kyrtzidis    switch (Opts.AnalysisStoreOpt) {
1265f83d6f36a7308eef21d87104fd70c421e854448Argyrios Kyrtzidis    default:
127b219cfc4d75f0a03630b7c4509ef791b7e97b2c8David Blaikie      llvm_unreachable("Unknown store manager.");
128fda7832b000ff8927386f093b52c067641679469Zhongxing Xu#define ANALYSIS_STORE(NAME, CMDFLAG, DESC, CREATEFN)           \
1295f83d6f36a7308eef21d87104fd70c421e854448Argyrios Kyrtzidis      case NAME##Model: CreateStoreMgr = CREATEFN; break;
130fda7832b000ff8927386f093b52c067641679469Zhongxing Xu#include "clang/Frontend/Analyses.def"
1311d9cbeb76cf4c36acf5545028e2b2ac207086442Ted Kremenek    }
1321eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
1335f83d6f36a7308eef21d87104fd70c421e854448Argyrios Kyrtzidis    switch (Opts.AnalysisConstraintsOpt) {
1345f83d6f36a7308eef21d87104fd70c421e854448Argyrios Kyrtzidis    default:
135b219cfc4d75f0a03630b7c4509ef791b7e97b2c8David Blaikie      llvm_unreachable("Unknown store manager.");
136fda7832b000ff8927386f093b52c067641679469Zhongxing Xu#define ANALYSIS_CONSTRAINTS(NAME, CMDFLAG, DESC, CREATEFN)     \
1375f83d6f36a7308eef21d87104fd70c421e854448Argyrios Kyrtzidis      case NAME##Model: CreateConstraintMgr = CREATEFN; break;
138fda7832b000ff8927386f093b52c067641679469Zhongxing Xu#include "clang/Frontend/Analyses.def"
139fda7832b000ff8927386f093b52c067641679469Zhongxing Xu    }
1401d9cbeb76cf4c36acf5545028e2b2ac207086442Ted Kremenek  }
141f6eafcca7734274d277afa121f2c4fb025a54218Ted Kremenek
1421d9cbeb76cf4c36acf5545028e2b2ac207086442Ted Kremenek  void DisplayFunction(const Decl *D) {
143c4a1437c15da43eb8d2601cdce13161ef41a4389Ted Kremenek    if (!Opts.AnalyzerDisplayProgress)
1441d9cbeb76cf4c36acf5545028e2b2ac207086442Ted Kremenek      return;
145f6eafcca7734274d277afa121f2c4fb025a54218Ted Kremenek
146fc576514d06c46a7cac49500169411d82f38d04bTed Kremenek    SourceManager &SM = Mgr->getASTContext().getSourceManager();
147fc576514d06c46a7cac49500169411d82f38d04bTed Kremenek    PresumedLoc Loc = SM.getPresumedLoc(D->getLocation());
148cb7b1e17b63967317ab5cc55682168cf0380519aDouglas Gregor    if (Loc.isValid()) {
149cb7b1e17b63967317ab5cc55682168cf0380519aDouglas Gregor      llvm::errs() << "ANALYZE: " << Loc.getFilename();
150fc576514d06c46a7cac49500169411d82f38d04bTed Kremenek
151cb7b1e17b63967317ab5cc55682168cf0380519aDouglas Gregor      if (isa<FunctionDecl>(D) || isa<ObjCMethodDecl>(D)) {
152cb7b1e17b63967317ab5cc55682168cf0380519aDouglas Gregor        const NamedDecl *ND = cast<NamedDecl>(D);
153b8989f27f116ff2400e92a52c067a69846119eb5Benjamin Kramer        llvm::errs() << ' ' << *ND << '\n';
154cb7b1e17b63967317ab5cc55682168cf0380519aDouglas Gregor      }
155cb7b1e17b63967317ab5cc55682168cf0380519aDouglas Gregor      else if (isa<BlockDecl>(D)) {
156cb7b1e17b63967317ab5cc55682168cf0380519aDouglas Gregor        llvm::errs() << ' ' << "block(line:" << Loc.getLine() << ",col:"
157cb7b1e17b63967317ab5cc55682168cf0380519aDouglas Gregor                     << Loc.getColumn() << '\n';
158cb7b1e17b63967317ab5cc55682168cf0380519aDouglas Gregor      }
159cb7b1e17b63967317ab5cc55682168cf0380519aDouglas Gregor      else if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D)) {
160cb7b1e17b63967317ab5cc55682168cf0380519aDouglas Gregor        Selector S = MD->getSelector();
161cb7b1e17b63967317ab5cc55682168cf0380519aDouglas Gregor        llvm::errs() << ' ' << S.getAsString();
162cb7b1e17b63967317ab5cc55682168cf0380519aDouglas Gregor      }
16335fa76d0bb6fb8c86159a7506efd094a4fe376d2Ted Kremenek    }
1641d9cbeb76cf4c36acf5545028e2b2ac207086442Ted Kremenek  }
1651eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
1661d9cbeb76cf4c36acf5545028e2b2ac207086442Ted Kremenek  virtual void Initialize(ASTContext &Context) {
1671d9cbeb76cf4c36acf5545028e2b2ac207086442Ted Kremenek    Ctx = &Context;
16808b86531ade68727c56918f162816075b87c864aJordy Rose    checkerMgr.reset(createCheckerManager(Opts, PP.getLangOptions(), Plugins,
16908b86531ade68727c56918f162816075b87c864aJordy Rose                                          PP.getDiagnostics()));
1701d9cbeb76cf4c36acf5545028e2b2ac207086442Ted Kremenek    Mgr.reset(new AnalysisManager(*Ctx, PP.getDiagnostics(),
1711d9cbeb76cf4c36acf5545028e2b2ac207086442Ted Kremenek                                  PP.getLangOptions(), PD,
1721d9cbeb76cf4c36acf5545028e2b2ac207086442Ted Kremenek                                  CreateStoreMgr, CreateConstraintMgr,
17343dee220252ef0b42c5f8a3bb1eca97f84f2565fArgyrios Kyrtzidis                                  checkerMgr.get(),
174c6238d2786cfd961b94580b3d3675a1b3ff0721cZhongxing Xu                                  /* Indexer */ 0,
1756362b893731ccf4480a96527db9e55e04b801503Zhongxing Xu                                  Opts.MaxNodes, Opts.MaxLoop,
1761d9cbeb76cf4c36acf5545028e2b2ac207086442Ted Kremenek                                  Opts.VisualizeEGDot, Opts.VisualizeEGUbi,
177d30952838421ddfb9f7e346b2ba8213889a5f789Anna Zaks                                  Opts.AnalysisPurgeOpt, Opts.EagerlyAssume,
17866253352131e3e7a22b3bfd0e180607aa2bfb988Anna Zaks                                  Opts.TrimGraph,
1799121ba232903ebe61e7bbe14ca294cf0f07dfa96Marcin Swiderski                                  Opts.UnoptimizedCFG, Opts.CFGAddImplicitDtors,
180d767d81290288c030f3be0be1d3e62b9c8df51dcTed Kremenek                                  Opts.CFGAddInitializers,
1818235f9c9c8b3d1737d1c6bd57f7ba3f616b92392Anna Zaks                                  Opts.EagerlyTrimEGraph,
18266253352131e3e7a22b3bfd0e180607aa2bfb988Anna Zaks                                  Opts.IPAMode,
1838235f9c9c8b3d1737d1c6bd57f7ba3f616b92392Anna Zaks                                  Opts.InlineMaxStackDepth,
18466253352131e3e7a22b3bfd0e180607aa2bfb988Anna Zaks                                  Opts.InlineMaxFunctionSize,
18566253352131e3e7a22b3bfd0e180607aa2bfb988Anna Zaks                                  Opts.InliningMode));
1861d9cbeb76cf4c36acf5545028e2b2ac207086442Ted Kremenek  }
1871eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
1881d9cbeb76cf4c36acf5545028e2b2ac207086442Ted Kremenek  virtual void HandleTranslationUnit(ASTContext &C);
18914cc9451de4a9539bf79e4e5d63248c2377426dbTed Kremenek  void HandleDeclContext(ASTContext &C, DeclContext *dc);
190fee618af5dd7dee2caaa7347b372eb3dc5fdeffcTed Kremenek  void HandleDeclContextDecl(ASTContext &C, Decl *D);
191d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks  void HandleDeclContextDeclFunction(ASTContext &C, Decl *D);
19214cc9451de4a9539bf79e4e5d63248c2377426dbTed Kremenek
1933fd5f370a28552976c52e76c3035d79012d78ddaAnna Zaks  void HandleCode(Decl *D, SetOfDecls *VisitedCallees = 0);
1943fd5f370a28552976c52e76c3035d79012d78ddaAnna Zaks  void RunPathSensitiveChecks(Decl *D, SetOfDecls *VisitedCallees);
1953fd5f370a28552976c52e76c3035d79012d78ddaAnna Zaks  void ActionExprEngine(Decl *D, bool ObjCGCEnabled, SetOfDecls *VisitedCallees);
1961d9cbeb76cf4c36acf5545028e2b2ac207086442Ted Kremenek};
197f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek} // end anonymous namespace
198f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek
199f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek//===----------------------------------------------------------------------===//
200f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek// AnalysisConsumer implementation.
201f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek//===----------------------------------------------------------------------===//
202d38f79543136ba68cd14b1dab0856474df1fbfd5Anna Zaksllvm::Timer* AnalysisConsumer::TUTotalTimer = 0;
203f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek
20414cc9451de4a9539bf79e4e5d63248c2377426dbTed Kremenekvoid AnalysisConsumer::HandleDeclContext(ASTContext &C, DeclContext *dc) {
20514cc9451de4a9539bf79e4e5d63248c2377426dbTed Kremenek  for (DeclContext::decl_iterator I = dc->decls_begin(), E = dc->decls_end();
206ed8afacb8118b71bcfa8017059e51da325e7691bZhongxing Xu       I != E; ++I) {
207fee618af5dd7dee2caaa7347b372eb3dc5fdeffcTed Kremenek    HandleDeclContextDecl(C, *I);
208fee618af5dd7dee2caaa7347b372eb3dc5fdeffcTed Kremenek  }
209d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks
210d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks  // If inlining is not turned on, use the simplest function order.
211d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks  if (!Mgr->shouldInlineCall()) {
212d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks    for (DeclContext::decl_iterator I = dc->decls_begin(), E = dc->decls_end();
213d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks         I != E; ++I)
214d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks      HandleDeclContextDeclFunction(C, *I);
215d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks    return;
216d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks  }
217d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks
218d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks  // Otherwise, use the Callgraph to derive the order.
219d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks  // Build the Call Graph.
220d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks  CallGraph CG;
221d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks  CG.addToCallGraph(dc);
222d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks
223d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks  // Find the top level nodes - children of root + the unreachable (parentless)
224d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks  // nodes.
2253fd5f370a28552976c52e76c3035d79012d78ddaAnna Zaks  llvm::SmallVector<CallGraphNode*, 24> TopLevelFunctions;
226d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks  CallGraphNode *Entry = CG.getRoot();
227d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks  for (CallGraphNode::iterator I = Entry->begin(),
2283fd5f370a28552976c52e76c3035d79012d78ddaAnna Zaks                               E = Entry->end(); I != E; ++I) {
229d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks    TopLevelFunctions.push_back(*I);
2303fd5f370a28552976c52e76c3035d79012d78ddaAnna Zaks    NumFunctionTopLevel++;
2313fd5f370a28552976c52e76c3035d79012d78ddaAnna Zaks  }
232d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks  for (CallGraph::nodes_iterator TI = CG.parentless_begin(),
2333fd5f370a28552976c52e76c3035d79012d78ddaAnna Zaks                                 TE = CG.parentless_end(); TI != TE; ++TI) {
234d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks    TopLevelFunctions.push_back(*TI);
2353fd5f370a28552976c52e76c3035d79012d78ddaAnna Zaks    NumFunctionTopLevel++;
2363fd5f370a28552976c52e76c3035d79012d78ddaAnna Zaks  }
237d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks
238d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks  // TODO: Sort TopLevelFunctions.
239d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks
240d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks  // DFS over all of the top level nodes. Use external Visited set, which is
241d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks  // also modified when we inline a function.
242d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks  SmallPtrSet<CallGraphNode*,24> Visited;
243d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks  for (llvm::SmallVector<CallGraphNode*, 24>::iterator
244d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks         TI = TopLevelFunctions.begin(), TE = TopLevelFunctions.end();
245d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks         TI != TE; ++TI) {
246d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks    for (llvm::df_ext_iterator<CallGraphNode*, SmallPtrSet<CallGraphNode*,24> >
247d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks        DFI = llvm::df_ext_begin(*TI, Visited),
248d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks        E = llvm::df_ext_end(*TI, Visited);
249d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks        DFI != E; ++DFI) {
2503fd5f370a28552976c52e76c3035d79012d78ddaAnna Zaks      SetOfDecls VisitedCallees;
251d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks      Decl *D = (*DFI)->getDecl();
252d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks      assert(D);
2533fd5f370a28552976c52e76c3035d79012d78ddaAnna Zaks      HandleCode(D, (Mgr->InliningMode == All ? 0 : &VisitedCallees));
2543fd5f370a28552976c52e76c3035d79012d78ddaAnna Zaks
2553fd5f370a28552976c52e76c3035d79012d78ddaAnna Zaks      // Add the visited callees to the global visited set.
2563fd5f370a28552976c52e76c3035d79012d78ddaAnna Zaks      for (SetOfDecls::const_iterator I = VisitedCallees.begin(),
2573fd5f370a28552976c52e76c3035d79012d78ddaAnna Zaks                                      E = VisitedCallees.end(); I != E; ++I) {
2583fd5f370a28552976c52e76c3035d79012d78ddaAnna Zaks        CallGraphNode *VN = CG.getNode(*I);
2593fd5f370a28552976c52e76c3035d79012d78ddaAnna Zaks        if (VN)
2603fd5f370a28552976c52e76c3035d79012d78ddaAnna Zaks          Visited.insert(VN);
2613fd5f370a28552976c52e76c3035d79012d78ddaAnna Zaks      }
262d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks    }
263d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks  }
264fee618af5dd7dee2caaa7347b372eb3dc5fdeffcTed Kremenek}
265fee618af5dd7dee2caaa7347b372eb3dc5fdeffcTed Kremenek
266fee618af5dd7dee2caaa7347b372eb3dc5fdeffcTed Kremenekvoid AnalysisConsumer::HandleDeclContextDecl(ASTContext &C, Decl *D) {
267fee618af5dd7dee2caaa7347b372eb3dc5fdeffcTed Kremenek  { // Handle callbacks for arbitrary decls.
268fee618af5dd7dee2caaa7347b372eb3dc5fdeffcTed Kremenek    BugReporter BR(*Mgr);
2699fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis    checkerMgr->runCheckersOnASTDecl(D, *Mgr, BR);
270fee618af5dd7dee2caaa7347b372eb3dc5fdeffcTed Kremenek  }
2719fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis
272fee618af5dd7dee2caaa7347b372eb3dc5fdeffcTed Kremenek  switch (D->getKind()) {
273fee618af5dd7dee2caaa7347b372eb3dc5fdeffcTed Kremenek    case Decl::Namespace: {
274fee618af5dd7dee2caaa7347b372eb3dc5fdeffcTed Kremenek      HandleDeclContext(C, cast<NamespaceDecl>(D));
275fee618af5dd7dee2caaa7347b372eb3dc5fdeffcTed Kremenek      break;
276fee618af5dd7dee2caaa7347b372eb3dc5fdeffcTed Kremenek    }
277d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks    case Decl::ObjCCategoryImpl:
278d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks    case Decl::ObjCImplementation: {
279d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks      ObjCImplDecl *ID = cast<ObjCImplDecl>(D);
280d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks      for (ObjCContainerDecl::method_iterator MI = ID->meth_begin(),
281d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks           ME = ID->meth_end(); MI != ME; ++MI) {
282d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks        BugReporter BR(*Mgr);
283d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks        checkerMgr->runCheckersOnASTDecl(*MI, *Mgr, BR);
284d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks      }
285d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks      break;
286d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks    }
287d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks
288d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks    default:
289d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks      break;
290d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks  }
291d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks}
292d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks
293d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaksvoid AnalysisConsumer::HandleDeclContextDeclFunction(ASTContext &C, Decl *D) {
294d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks  switch (D->getKind()) {
295fee618af5dd7dee2caaa7347b372eb3dc5fdeffcTed Kremenek    case Decl::CXXConstructor:
296fee618af5dd7dee2caaa7347b372eb3dc5fdeffcTed Kremenek    case Decl::CXXDestructor:
297fee618af5dd7dee2caaa7347b372eb3dc5fdeffcTed Kremenek    case Decl::CXXConversion:
298fee618af5dd7dee2caaa7347b372eb3dc5fdeffcTed Kremenek    case Decl::CXXMethod:
299fee618af5dd7dee2caaa7347b372eb3dc5fdeffcTed Kremenek    case Decl::Function: {
300fee618af5dd7dee2caaa7347b372eb3dc5fdeffcTed Kremenek      FunctionDecl *FD = cast<FunctionDecl>(D);
3013fd5f370a28552976c52e76c3035d79012d78ddaAnna Zaks      IdentifierInfo *II = FD->getIdentifier();
3023fd5f370a28552976c52e76c3035d79012d78ddaAnna Zaks      if (II && II->getName().startswith("__inline"))
3033fd5f370a28552976c52e76c3035d79012d78ddaAnna Zaks        break;
304fee618af5dd7dee2caaa7347b372eb3dc5fdeffcTed Kremenek      // We skip function template definitions, as their semantics is
305fee618af5dd7dee2caaa7347b372eb3dc5fdeffcTed Kremenek      // only determined when they are instantiated.
306fee618af5dd7dee2caaa7347b372eb3dc5fdeffcTed Kremenek      if (FD->isThisDeclarationADefinition() &&
307fee618af5dd7dee2caaa7347b372eb3dc5fdeffcTed Kremenek          !FD->isDependentContext()) {
308fee618af5dd7dee2caaa7347b372eb3dc5fdeffcTed Kremenek        if (!Opts.AnalyzeSpecificFunction.empty() &&
309fee618af5dd7dee2caaa7347b372eb3dc5fdeffcTed Kremenek            FD->getDeclName().getAsString() != Opts.AnalyzeSpecificFunction)
310fee618af5dd7dee2caaa7347b372eb3dc5fdeffcTed Kremenek          break;
311fee618af5dd7dee2caaa7347b372eb3dc5fdeffcTed Kremenek        HandleCode(FD);
312ed8afacb8118b71bcfa8017059e51da325e7691bZhongxing Xu      }
313fee618af5dd7dee2caaa7347b372eb3dc5fdeffcTed Kremenek      break;
314fee618af5dd7dee2caaa7347b372eb3dc5fdeffcTed Kremenek    }
315fee618af5dd7dee2caaa7347b372eb3dc5fdeffcTed Kremenek
316fee618af5dd7dee2caaa7347b372eb3dc5fdeffcTed Kremenek    case Decl::ObjCCategoryImpl:
317fee618af5dd7dee2caaa7347b372eb3dc5fdeffcTed Kremenek    case Decl::ObjCImplementation: {
318fee618af5dd7dee2caaa7347b372eb3dc5fdeffcTed Kremenek      ObjCImplDecl *ID = cast<ObjCImplDecl>(D);
319fee618af5dd7dee2caaa7347b372eb3dc5fdeffcTed Kremenek      for (ObjCContainerDecl::method_iterator MI = ID->meth_begin(),
320fee618af5dd7dee2caaa7347b372eb3dc5fdeffcTed Kremenek           ME = ID->meth_end(); MI != ME; ++MI) {
321fee618af5dd7dee2caaa7347b372eb3dc5fdeffcTed Kremenek        if ((*MI)->isThisDeclarationADefinition()) {
322ed8afacb8118b71bcfa8017059e51da325e7691bZhongxing Xu          if (!Opts.AnalyzeSpecificFunction.empty() &&
323fee618af5dd7dee2caaa7347b372eb3dc5fdeffcTed Kremenek              Opts.AnalyzeSpecificFunction !=
324fee618af5dd7dee2caaa7347b372eb3dc5fdeffcTed Kremenek                (*MI)->getSelector().getAsString())
325d1fe529b1a17a2422f28f1b938ee70453dc7199dAnna Zaks            continue;
326fee618af5dd7dee2caaa7347b372eb3dc5fdeffcTed Kremenek          HandleCode(*MI);
32714cc9451de4a9539bf79e4e5d63248c2377426dbTed Kremenek        }
32814cc9451de4a9539bf79e4e5d63248c2377426dbTed Kremenek      }
329fee618af5dd7dee2caaa7347b372eb3dc5fdeffcTed Kremenek      break;
330ed8afacb8118b71bcfa8017059e51da325e7691bZhongxing Xu    }
331fee618af5dd7dee2caaa7347b372eb3dc5fdeffcTed Kremenek
332fee618af5dd7dee2caaa7347b372eb3dc5fdeffcTed Kremenek    default:
333fee618af5dd7dee2caaa7347b372eb3dc5fdeffcTed Kremenek      break;
334fee618af5dd7dee2caaa7347b372eb3dc5fdeffcTed Kremenek  }
33514cc9451de4a9539bf79e4e5d63248c2377426dbTed Kremenek}
336f6eafcca7734274d277afa121f2c4fb025a54218Ted Kremenek
33714cc9451de4a9539bf79e4e5d63248c2377426dbTed Kremenekvoid AnalysisConsumer::HandleTranslationUnit(ASTContext &C) {
338c5bdc556f6a65c677e0ed73f918c3000ecad33afAnna Zaks  {
339d38f79543136ba68cd14b1dab0856474df1fbfd5Anna Zaks    if (TUTotalTimer) TUTotalTimer->startTimer();
340d38f79543136ba68cd14b1dab0856474df1fbfd5Anna Zaks
341c5bdc556f6a65c677e0ed73f918c3000ecad33afAnna Zaks    // Introduce a scope to destroy BR before Mgr.
342c5bdc556f6a65c677e0ed73f918c3000ecad33afAnna Zaks    BugReporter BR(*Mgr);
343c5bdc556f6a65c677e0ed73f918c3000ecad33afAnna Zaks    TranslationUnitDecl *TU = C.getTranslationUnitDecl();
344c5bdc556f6a65c677e0ed73f918c3000ecad33afAnna Zaks    checkerMgr->runCheckersOnASTDecl(TU, *Mgr, BR);
345c5bdc556f6a65c677e0ed73f918c3000ecad33afAnna Zaks    HandleDeclContext(C, TU);
346b317f8f5ca8737a5bbad97a3f7566a2dbd2ed61bZhongxing Xu
347c5bdc556f6a65c677e0ed73f918c3000ecad33afAnna Zaks    // After all decls handled, run checkers on the entire TranslationUnit.
348c5bdc556f6a65c677e0ed73f918c3000ecad33afAnna Zaks    checkerMgr->runCheckersOnEndOfTranslationUnit(TU, *Mgr, BR);
349c5bdc556f6a65c677e0ed73f918c3000ecad33afAnna Zaks  }
3509be6e7ce5788e50c62d40c59b0bbc2ea423683f7Ted Kremenek
351ef3643fbbbf66247c5e205497fae0f46e240c143David Blaikie  // Explicitly destroy the PathDiagnosticConsumer.  This will flush its output.
352690a7f431d6863a101711e67636d51ddd13f35c5Ted Kremenek  // FIXME: This should be replaced with something that doesn't rely on
353ef3643fbbbf66247c5e205497fae0f46e240c143David Blaikie  // side-effects in PathDiagnosticConsumer's destructor. This is required when
354da17fd50ad485fd2a1fc5c2f055caacf532992daZhongxing Xu  // used with option -disable-free.
355d07a0d0279c09d1017f8450fce575a94dc9703c0Zhongxing Xu  Mgr.reset(NULL);
356d38f79543136ba68cd14b1dab0856474df1fbfd5Anna Zaks
357d38f79543136ba68cd14b1dab0856474df1fbfd5Anna Zaks  if (TUTotalTimer) TUTotalTimer->stopTimer();
358db09a4dee28a4515438af60f2d2b4a83e4965c31Ted Kremenek}
359db09a4dee28a4515438af60f2d2b4a83e4965c31Ted Kremenek
3605f9e272e632e951b1efe824cd16acb4d96077930Chris Lattnerstatic void FindBlocks(DeclContext *D, SmallVectorImpl<Decl*> &WL) {
361fc576514d06c46a7cac49500169411d82f38d04bTed Kremenek  if (BlockDecl *BD = dyn_cast<BlockDecl>(D))
362fc576514d06c46a7cac49500169411d82f38d04bTed Kremenek    WL.push_back(BD);
363f6eafcca7734274d277afa121f2c4fb025a54218Ted Kremenek
364fc576514d06c46a7cac49500169411d82f38d04bTed Kremenek  for (DeclContext::decl_iterator I = D->decls_begin(), E = D->decls_end();
365fc576514d06c46a7cac49500169411d82f38d04bTed Kremenek       I!=E; ++I)
366fc576514d06c46a7cac49500169411d82f38d04bTed Kremenek    if (DeclContext *DC = dyn_cast<DeclContext>(*I))
367fc576514d06c46a7cac49500169411d82f38d04bTed Kremenek      FindBlocks(DC, WL);
368fc576514d06c46a7cac49500169411d82f38d04bTed Kremenek}
369fc576514d06c46a7cac49500169411d82f38d04bTed Kremenek
370d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaksstatic std::string getFunctionName(const Decl *D) {
371d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks  if (const ObjCMethodDecl *ID = dyn_cast<ObjCMethodDecl>(D)) {
372d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks    return ID->getSelector().getAsString();
373d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks  }
374d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks  if (const FunctionDecl *ND = dyn_cast<FunctionDecl>(D)) {
375d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks    IdentifierInfo *II = ND->getIdentifier();
376d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks    if (II)
377d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks      return II->getName();
378d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks  }
379d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks  return "";
380d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks}
381d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks
3823fd5f370a28552976c52e76c3035d79012d78ddaAnna Zaksvoid AnalysisConsumer::HandleCode(Decl *D, SetOfDecls *VisitedCallees) {
383d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks  if (!Opts.AnalyzeSpecificFunction.empty() &&
384d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks      getFunctionName(D) != Opts.AnalyzeSpecificFunction)
385d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks    return;
386d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks
387d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks  DisplayFunction(D);
3881eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
389fc8f0e14ad142ed811e90fbd9a30e419e301c717Chris Lattner  // Don't run the actions if an error has occurred with parsing the file.
390d6471f7c1921c7802804ce3ff6fe9768310f72b9David Blaikie  DiagnosticsEngine &Diags = PP.getDiagnostics();
39199e8192c4c8f1f596f9969e5f2cdafcee64ddaacTed Kremenek  if (Diags.hasErrorOccurred() || Diags.hasFatalErrorOccurred())
392f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek    return;
39381922f01352aceeb923c0c3cc8c96b6527322384Ted Kremenek
394f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek  // Don't run the actions on declarations in header files unless
395f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek  // otherwise specified.
396fcd783d583d270b7ec1ec3e0fcf83cd93d30e381Ted Kremenek  SourceManager &SM = Ctx->getSourceManager();
397402785357ab053dd53f4fdd858b9630a5e0f8badChandler Carruth  SourceLocation SL = SM.getExpansionLoc(D->getLocation());
398fcd783d583d270b7ec1ec3e0fcf83cd93d30e381Ted Kremenek  if (!Opts.AnalyzeAll && !SM.isFromMainFile(SL))
3991eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump    return;
400f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek
4011d26f48dc2eea1c07431ca1519d7034a21b9bcffTed Kremenek  // Clear the AnalysisManager of old AnalysisDeclContexts.
40258f5ec7d56b1ebf5f90ee11226ebe7663f2821eaTed Kremenek  Mgr->ClearContexts();
403f6eafcca7734274d277afa121f2c4fb025a54218Ted Kremenek
4041eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  // Dispatch on the actions.
4055f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner  SmallVector<Decl*, 10> WL;
406fc576514d06c46a7cac49500169411d82f38d04bTed Kremenek  WL.push_back(D);
407f6eafcca7734274d277afa121f2c4fb025a54218Ted Kremenek
40806a54a38be5054c910ffc92db60edab23f9ea105Argyrios Kyrtzidis  if (D->hasBody() && Opts.AnalyzeNestedBlocks)
409fc576514d06c46a7cac49500169411d82f38d04bTed Kremenek    FindBlocks(cast<DeclContext>(D), WL);
410f6eafcca7734274d277afa121f2c4fb025a54218Ted Kremenek
4119fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis  BugReporter BR(*Mgr);
4125f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner  for (SmallVectorImpl<Decl*>::iterator WI=WL.begin(), WE=WL.end();
4139fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis       WI != WE; ++WI)
414d655ab28fdf7c940d3f79f8f287954d7f76e0977Argyrios Kyrtzidis    if ((*WI)->hasBody()) {
4159fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis      checkerMgr->runCheckersOnASTBody(*WI, *Mgr, BR);
416d655ab28fdf7c940d3f79f8f287954d7f76e0977Argyrios Kyrtzidis      if (checkerMgr->hasPathSensitiveCheckers())
4173fd5f370a28552976c52e76c3035d79012d78ddaAnna Zaks        RunPathSensitiveChecks(*WI, VisitedCallees);
418d655ab28fdf7c940d3f79f8f287954d7f76e0977Argyrios Kyrtzidis    }
419d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks  NumFunctionsAnalyzed++;
420f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek}
421f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek
422f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek//===----------------------------------------------------------------------===//
423d655ab28fdf7c940d3f79f8f287954d7f76e0977Argyrios Kyrtzidis// Path-sensitive checking.
424f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek//===----------------------------------------------------------------------===//
425f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek
4263fd5f370a28552976c52e76c3035d79012d78ddaAnna Zaksvoid AnalysisConsumer::ActionExprEngine(Decl *D, bool ObjCGCEnabled,
4273fd5f370a28552976c52e76c3035d79012d78ddaAnna Zaks                                        SetOfDecls *VisitedCallees) {
428a5937bbfd19e61d651a58b0f0ffeef68457902a5Ted Kremenek  // Construct the analysis engine.  First check if the CFG is valid.
42975d03cffe20b5c945ef04eba208efb0437339997Ted Kremenek  // FIXME: Inter-procedural analysis will need to handle invalid CFGs.
4303fd5f370a28552976c52e76c3035d79012d78ddaAnna Zaks  if (!Mgr->getCFG(D))
431f6eafcca7734274d277afa121f2c4fb025a54218Ted Kremenek    return;
4323fd5f370a28552976c52e76c3035d79012d78ddaAnna Zaks
4333fd5f370a28552976c52e76c3035d79012d78ddaAnna Zaks  ExprEngine Eng(*Mgr, ObjCGCEnabled, VisitedCallees);
434f6eafcca7734274d277afa121f2c4fb025a54218Ted Kremenek
435f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek  // Set the graph auditor.
4366f42b62b6194f53bcbc349f5d17388e1936535d7Dylan Noblesmith  OwningPtr<ExplodedNode::Auditor> Auditor;
4373fd5f370a28552976c52e76c3035d79012d78ddaAnna Zaks  if (Mgr->shouldVisualizeUbigraph()) {
438f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek    Auditor.reset(CreateUbiViz());
439c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu    ExplodedNode::SetAuditor(Auditor.get());
440f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek  }
4411eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
442b35a74a40c1d2656a25e560e773ed48bdf49f9c0Ted Kremenek  // Execute the worklist algorithm.
4433fd5f370a28552976c52e76c3035d79012d78ddaAnna Zaks  Eng.ExecuteWorkList(Mgr->getAnalysisDeclContextManager().getStackFrame(D, 0),
4443fd5f370a28552976c52e76c3035d79012d78ddaAnna Zaks                      Mgr->getMaxNodes());
4451eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
446f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek  // Release the auditor (if any) so that it doesn't monitor the graph
447f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek  // created BugReporter.
448c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu  ExplodedNode::SetAuditor(0);
4493df6421150271266b5a90fd4c6bfa6566c38c036Ted Kremenek
45034d7734b6ed1d9c0f647405e065251eb67f42badTed Kremenek  // Visualize the exploded graph.
4513fd5f370a28552976c52e76c3035d79012d78ddaAnna Zaks  if (Mgr->shouldVisualizeGraphviz())
4523fd5f370a28552976c52e76c3035d79012d78ddaAnna Zaks    Eng.ViewGraph(Mgr->shouldTrimGraph());
4531eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
4543df6421150271266b5a90fd4c6bfa6566c38c036Ted Kremenek  // Display warnings.
4553df6421150271266b5a90fd4c6bfa6566c38c036Ted Kremenek  Eng.getBugReporter().FlushReports();
456bc46f345838b1c0d420dbd3655c94f5f360fb5b8Ted Kremenek}
457bc46f345838b1c0d420dbd3655c94f5f360fb5b8Ted Kremenek
4583fd5f370a28552976c52e76c3035d79012d78ddaAnna Zaksvoid AnalysisConsumer::RunPathSensitiveChecks(Decl *D, SetOfDecls *Visited) {
45917a38e2636a8b1ce473fc6504c4b16cb09db29f4Jordy Rose
4603fd5f370a28552976c52e76c3035d79012d78ddaAnna Zaks  switch (Mgr->getLangOptions().getGC()) {
46117a38e2636a8b1ce473fc6504c4b16cb09db29f4Jordy Rose  case LangOptions::NonGC:
4623fd5f370a28552976c52e76c3035d79012d78ddaAnna Zaks    ActionExprEngine(D, false, Visited);
46317a38e2636a8b1ce473fc6504c4b16cb09db29f4Jordy Rose    break;
46417a38e2636a8b1ce473fc6504c4b16cb09db29f4Jordy Rose
46517a38e2636a8b1ce473fc6504c4b16cb09db29f4Jordy Rose  case LangOptions::GCOnly:
4663fd5f370a28552976c52e76c3035d79012d78ddaAnna Zaks    ActionExprEngine(D, true, Visited);
46717a38e2636a8b1ce473fc6504c4b16cb09db29f4Jordy Rose    break;
46817a38e2636a8b1ce473fc6504c4b16cb09db29f4Jordy Rose
46917a38e2636a8b1ce473fc6504c4b16cb09db29f4Jordy Rose  case LangOptions::HybridGC:
4703fd5f370a28552976c52e76c3035d79012d78ddaAnna Zaks    ActionExprEngine(D, false, Visited);
4713fd5f370a28552976c52e76c3035d79012d78ddaAnna Zaks    ActionExprEngine(D, true, Visited);
47217a38e2636a8b1ce473fc6504c4b16cb09db29f4Jordy Rose    break;
47317a38e2636a8b1ce473fc6504c4b16cb09db29f4Jordy Rose  }
474b35a74a40c1d2656a25e560e773ed48bdf49f9c0Ted Kremenek}
475b35a74a40c1d2656a25e560e773ed48bdf49f9c0Ted Kremenek
476f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek//===----------------------------------------------------------------------===//
477f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek// AnalysisConsumer creation.
478f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek//===----------------------------------------------------------------------===//
479f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek
4809ef6537a894c33003359b1f9b9676e9178e028b7Ted KremenekASTConsumer* ento::CreateAnalysisConsumer(const Preprocessor& pp,
48108b86531ade68727c56918f162816075b87c864aJordy Rose                                          const std::string& outDir,
48208b86531ade68727c56918f162816075b87c864aJordy Rose                                          const AnalyzerOptions& opts,
48308b86531ade68727c56918f162816075b87c864aJordy Rose                                          ArrayRef<std::string> plugins) {
48408b86531ade68727c56918f162816075b87c864aJordy Rose  // Disable the effects of '-Werror' when using the AnalysisConsumer.
485efceabd2380f49306bc0229583458e93b062094bDaniel Dunbar  pp.getDiagnostics().setWarningsAsErrors(false);
486be1fe1eb12a1cb91c8e3a9fcc2db4dfe989def6cTed Kremenek
48708b86531ade68727c56918f162816075b87c864aJordy Rose  return new AnalysisConsumer(pp, outDir, opts, plugins);
488f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek}
489f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek
490f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek//===----------------------------------------------------------------------===//
491f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek// Ubigraph Visualization.  FIXME: Move to separate file.
492f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek//===----------------------------------------------------------------------===//
493f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek
494f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremeneknamespace {
4951eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
496c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xuclass UbigraphViz : public ExplodedNode::Auditor {
4976f42b62b6194f53bcbc349f5d17388e1936535d7Dylan Noblesmith  OwningPtr<raw_ostream> Out;
498710ad9343f32b33b336369b20edad1a21a0b3299Ted Kremenek  llvm::sys::Path Dir, Filename;
499f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek  unsigned Cntr;
500f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek
501f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek  typedef llvm::DenseMap<void*,unsigned> VMap;
502f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek  VMap M;
5031eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
504f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenekpublic:
5059c378f705405d37f49795d5e915989de774fe11fTed Kremenek  UbigraphViz(raw_ostream *out, llvm::sys::Path& dir,
50656b98719b0dbebb33cb228afa888c47156be2381Ted Kremenek              llvm::sys::Path& filename);
5071eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
508710ad9343f32b33b336369b20edad1a21a0b3299Ted Kremenek  ~UbigraphViz();
5091eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
5109c378f705405d37f49795d5e915989de774fe11fTed Kremenek  virtual void AddEdge(ExplodedNode *Src, ExplodedNode *Dst);
511f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek};
5121eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
513f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek} // end anonymous namespace
514f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek
515c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xustatic ExplodedNode::Auditor* CreateUbiViz() {
516f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek  std::string ErrMsg;
5171eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
518710ad9343f32b33b336369b20edad1a21a0b3299Ted Kremenek  llvm::sys::Path Dir = llvm::sys::Path::GetTemporaryDirectory(&ErrMsg);
519f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek  if (!ErrMsg.empty())
520f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek    return 0;
521f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek
522710ad9343f32b33b336369b20edad1a21a0b3299Ted Kremenek  llvm::sys::Path Filename = Dir;
523f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek  Filename.appendComponent("llvm_ubi");
524f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek  Filename.makeUnique(true,&ErrMsg);
525f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek
526f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek  if (!ErrMsg.empty())
527f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek    return 0;
528f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek
529d57a7ef9252964bc6c8471451d7bd395b0520cb8Chris Lattner  llvm::errs() << "Writing '" << Filename.str() << "'.\n";
5301eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
5316f42b62b6194f53bcbc349f5d17388e1936535d7Dylan Noblesmith  OwningPtr<llvm::raw_fd_ostream> Stream;
532b044c473a155b7e827680635c1699cb2b5b6c0eeDan Gohman  Stream.reset(new llvm::raw_fd_ostream(Filename.c_str(), ErrMsg));
533f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek
534f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek  if (!ErrMsg.empty())
535f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek    return 0;
5361eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
537710ad9343f32b33b336369b20edad1a21a0b3299Ted Kremenek  return new UbigraphViz(Stream.take(), Dir, Filename);
538f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek}
539f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek
5409c378f705405d37f49795d5e915989de774fe11fTed Kremenekvoid UbigraphViz::AddEdge(ExplodedNode *Src, ExplodedNode *Dst) {
5411eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
54245479c88c8a44c55d27c3bd855273bb318082f37Ted Kremenek  assert (Src != Dst && "Self-edges are not allowed.");
5431eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
544f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek  // Lookup the Src.  If it is a new node, it's a root.
545f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek  VMap::iterator SrcI= M.find(Src);
546f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek  unsigned SrcID;
5471eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
548f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek  if (SrcI == M.end()) {
549f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek    M[Src] = SrcID = Cntr++;
550f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek    *Out << "('vertex', " << SrcID << ", ('color','#00ff00'))\n";
551f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek  }
552f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek  else
553f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek    SrcID = SrcI->second;
5541eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
555f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek  // Lookup the Dst.
556f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek  VMap::iterator DstI= M.find(Dst);
557f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek  unsigned DstID;
558f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek
559f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek  if (DstI == M.end()) {
560f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek    M[Dst] = DstID = Cntr++;
561f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek    *Out << "('vertex', " << DstID << ")\n";
562f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek  }
56356b98719b0dbebb33cb228afa888c47156be2381Ted Kremenek  else {
56456b98719b0dbebb33cb228afa888c47156be2381Ted Kremenek    // We have hit DstID before.  Change its style to reflect a cache hit.
565f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek    DstID = DstI->second;
56656b98719b0dbebb33cb228afa888c47156be2381Ted Kremenek    *Out << "('change_vertex_style', " << DstID << ", 1)\n";
56756b98719b0dbebb33cb228afa888c47156be2381Ted Kremenek  }
568f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek
569f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek  // Add the edge.
5701eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  *Out << "('edge', " << SrcID << ", " << DstID
571d1289327f7d2126d732e23cc189ecd0aa5d07cbbTed Kremenek       << ", ('arrow','true'), ('oriented', 'true'))\n";
572f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek}
573f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek
5749c378f705405d37f49795d5e915989de774fe11fTed KremenekUbigraphViz::UbigraphViz(raw_ostream *out, llvm::sys::Path& dir,
57556b98719b0dbebb33cb228afa888c47156be2381Ted Kremenek                         llvm::sys::Path& filename)
57656b98719b0dbebb33cb228afa888c47156be2381Ted Kremenek  : Out(out), Dir(dir), Filename(filename), Cntr(0) {
57756b98719b0dbebb33cb228afa888c47156be2381Ted Kremenek
57856b98719b0dbebb33cb228afa888c47156be2381Ted Kremenek  *Out << "('vertex_style_attribute', 0, ('shape', 'icosahedron'))\n";
57956b98719b0dbebb33cb228afa888c47156be2381Ted Kremenek  *Out << "('vertex_style', 1, 0, ('shape', 'sphere'), ('color', '#ffcc66'),"
58056b98719b0dbebb33cb228afa888c47156be2381Ted Kremenek          " ('size', '1.5'))\n";
58156b98719b0dbebb33cb228afa888c47156be2381Ted Kremenek}
58256b98719b0dbebb33cb228afa888c47156be2381Ted Kremenek
583710ad9343f32b33b336369b20edad1a21a0b3299Ted KremenekUbigraphViz::~UbigraphViz() {
584710ad9343f32b33b336369b20edad1a21a0b3299Ted Kremenek  Out.reset(0);
5856cb7c1a43b0c8f739d1f54b7fdae5ede86033496Benjamin Kramer  llvm::errs() << "Running 'ubiviz' program... ";
586710ad9343f32b33b336369b20edad1a21a0b3299Ted Kremenek  std::string ErrMsg;
587710ad9343f32b33b336369b20edad1a21a0b3299Ted Kremenek  llvm::sys::Path Ubiviz = llvm::sys::Program::FindProgramByName("ubiviz");
588710ad9343f32b33b336369b20edad1a21a0b3299Ted Kremenek  std::vector<const char*> args;
589710ad9343f32b33b336369b20edad1a21a0b3299Ted Kremenek  args.push_back(Ubiviz.c_str());
590710ad9343f32b33b336369b20edad1a21a0b3299Ted Kremenek  args.push_back(Filename.c_str());
591710ad9343f32b33b336369b20edad1a21a0b3299Ted Kremenek  args.push_back(0);
5921eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
593710ad9343f32b33b336369b20edad1a21a0b3299Ted Kremenek  if (llvm::sys::Program::ExecuteAndWait(Ubiviz, &args[0],0,0,0,0,&ErrMsg)) {
5946cb7c1a43b0c8f739d1f54b7fdae5ede86033496Benjamin Kramer    llvm::errs() << "Error viewing graph: " << ErrMsg << "\n";
595710ad9343f32b33b336369b20edad1a21a0b3299Ted Kremenek  }
5961eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
597710ad9343f32b33b336369b20edad1a21a0b3299Ted Kremenek  // Delete the directory.
5981eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  Dir.eraseFromDisk(true);
599932680ecdeab4c216ce7c0736093d3dcd2f60f6dDaniel Dunbar}
600