AnalysisConsumer.cpp 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481
  1. //===--- AnalysisConsumer.cpp - ASTConsumer for running Analyses ----------===//
  2. //
  3. // The LLVM Compiler Infrastructure
  4. //
  5. // This file is distributed under the University of Illinois Open Source
  6. // License. See LICENSE.TXT for details.
  7. //
  8. //===----------------------------------------------------------------------===//
  9. //
  10. // "Meta" ASTConsumer for running different source analyses.
  11. //
  12. //===----------------------------------------------------------------------===//
  13. #include "AnalysisConsumer.h"
  14. #include "clang/AST/ASTConsumer.h"
  15. #include "clang/AST/Decl.h"
  16. #include "clang/AST/DeclCXX.h"
  17. #include "clang/AST/DeclObjC.h"
  18. #include "clang/AST/ParentMap.h"
  19. #include "clang/Analysis/CFG.h"
  20. #include "clang/StaticAnalyzer/Frontend/CheckerRegistration.h"
  21. #include "clang/StaticAnalyzer/Core/CheckerManager.h"
  22. #include "clang/StaticAnalyzer/Checkers/LocalCheckers.h"
  23. #include "clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h"
  24. #include "clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h"
  25. #include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h"
  26. #include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
  27. #include "clang/StaticAnalyzer/Core/PathDiagnosticConsumers.h"
  28. #include "clang/Basic/FileManager.h"
  29. #include "clang/Basic/SourceManager.h"
  30. #include "clang/Frontend/AnalyzerOptions.h"
  31. #include "clang/Lex/Preprocessor.h"
  32. #include "llvm/Support/raw_ostream.h"
  33. #include "llvm/Support/Path.h"
  34. #include "llvm/Support/Program.h"
  35. #include "llvm/ADT/OwningPtr.h"
  36. using namespace clang;
  37. using namespace ento;
  38. static ExplodedNode::Auditor* CreateUbiViz();
  39. //===----------------------------------------------------------------------===//
  40. // Special PathDiagnosticConsumers.
  41. //===----------------------------------------------------------------------===//
  42. static PathDiagnosticConsumer*
  43. createPlistHTMLDiagnosticConsumer(const std::string& prefix,
  44. const Preprocessor &PP) {
  45. PathDiagnosticConsumer *PD =
  46. createHTMLDiagnosticConsumer(llvm::sys::path::parent_path(prefix), PP);
  47. return createPlistDiagnosticConsumer(prefix, PP, PD);
  48. }
  49. //===----------------------------------------------------------------------===//
  50. // AnalysisConsumer declaration.
  51. //===----------------------------------------------------------------------===//
  52. namespace {
  53. class AnalysisConsumer : public ASTConsumer {
  54. public:
  55. ASTContext *Ctx;
  56. const Preprocessor &PP;
  57. const std::string OutDir;
  58. AnalyzerOptions Opts;
  59. ArrayRef<std::string> Plugins;
  60. // PD is owned by AnalysisManager.
  61. PathDiagnosticConsumer *PD;
  62. StoreManagerCreator CreateStoreMgr;
  63. ConstraintManagerCreator CreateConstraintMgr;
  64. OwningPtr<CheckerManager> checkerMgr;
  65. OwningPtr<AnalysisManager> Mgr;
  66. AnalysisConsumer(const Preprocessor& pp,
  67. const std::string& outdir,
  68. const AnalyzerOptions& opts,
  69. ArrayRef<std::string> plugins)
  70. : Ctx(0), PP(pp), OutDir(outdir), Opts(opts), Plugins(plugins), PD(0) {
  71. DigestAnalyzerOptions();
  72. }
  73. void DigestAnalyzerOptions() {
  74. // Create the PathDiagnosticConsumer.
  75. if (!OutDir.empty()) {
  76. switch (Opts.AnalysisDiagOpt) {
  77. default:
  78. #define ANALYSIS_DIAGNOSTICS(NAME, CMDFLAG, DESC, CREATEFN, AUTOCREATE) \
  79. case PD_##NAME: PD = CREATEFN(OutDir, PP); break;
  80. #include "clang/Frontend/Analyses.def"
  81. }
  82. } else if (Opts.AnalysisDiagOpt == PD_TEXT) {
  83. // Create the text client even without a specified output file since
  84. // it just uses diagnostic notes.
  85. PD = createTextPathDiagnosticConsumer("", PP);
  86. }
  87. // Create the analyzer component creators.
  88. switch (Opts.AnalysisStoreOpt) {
  89. default:
  90. llvm_unreachable("Unknown store manager.");
  91. #define ANALYSIS_STORE(NAME, CMDFLAG, DESC, CREATEFN) \
  92. case NAME##Model: CreateStoreMgr = CREATEFN; break;
  93. #include "clang/Frontend/Analyses.def"
  94. }
  95. switch (Opts.AnalysisConstraintsOpt) {
  96. default:
  97. llvm_unreachable("Unknown store manager.");
  98. #define ANALYSIS_CONSTRAINTS(NAME, CMDFLAG, DESC, CREATEFN) \
  99. case NAME##Model: CreateConstraintMgr = CREATEFN; break;
  100. #include "clang/Frontend/Analyses.def"
  101. }
  102. }
  103. void DisplayFunction(const Decl *D) {
  104. if (!Opts.AnalyzerDisplayProgress)
  105. return;
  106. SourceManager &SM = Mgr->getASTContext().getSourceManager();
  107. PresumedLoc Loc = SM.getPresumedLoc(D->getLocation());
  108. if (Loc.isValid()) {
  109. llvm::errs() << "ANALYZE: " << Loc.getFilename();
  110. if (isa<FunctionDecl>(D) || isa<ObjCMethodDecl>(D)) {
  111. const NamedDecl *ND = cast<NamedDecl>(D);
  112. llvm::errs() << ' ' << *ND << '\n';
  113. }
  114. else if (isa<BlockDecl>(D)) {
  115. llvm::errs() << ' ' << "block(line:" << Loc.getLine() << ",col:"
  116. << Loc.getColumn() << '\n';
  117. }
  118. else if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D)) {
  119. Selector S = MD->getSelector();
  120. llvm::errs() << ' ' << S.getAsString();
  121. }
  122. }
  123. }
  124. virtual void Initialize(ASTContext &Context) {
  125. Ctx = &Context;
  126. checkerMgr.reset(createCheckerManager(Opts, PP.getLangOptions(), Plugins,
  127. PP.getDiagnostics()));
  128. Mgr.reset(new AnalysisManager(*Ctx, PP.getDiagnostics(),
  129. PP.getLangOptions(), PD,
  130. CreateStoreMgr, CreateConstraintMgr,
  131. checkerMgr.get(),
  132. /* Indexer */ 0,
  133. Opts.MaxNodes, Opts.MaxLoop,
  134. Opts.VisualizeEGDot, Opts.VisualizeEGUbi,
  135. Opts.AnalysisPurgeOpt, Opts.EagerlyAssume,
  136. Opts.TrimGraph, Opts.InlineCall,
  137. Opts.UnoptimizedCFG, Opts.CFGAddImplicitDtors,
  138. Opts.CFGAddInitializers,
  139. Opts.EagerlyTrimEGraph));
  140. }
  141. virtual void HandleTranslationUnit(ASTContext &C);
  142. void HandleDeclContext(ASTContext &C, DeclContext *dc);
  143. void HandleDeclContextDecl(ASTContext &C, Decl *D);
  144. void HandleCode(Decl *D);
  145. };
  146. } // end anonymous namespace
  147. //===----------------------------------------------------------------------===//
  148. // AnalysisConsumer implementation.
  149. //===----------------------------------------------------------------------===//
  150. void AnalysisConsumer::HandleDeclContext(ASTContext &C, DeclContext *dc) {
  151. for (DeclContext::decl_iterator I = dc->decls_begin(), E = dc->decls_end();
  152. I != E; ++I) {
  153. HandleDeclContextDecl(C, *I);
  154. }
  155. }
  156. void AnalysisConsumer::HandleDeclContextDecl(ASTContext &C, Decl *D) {
  157. { // Handle callbacks for arbitrary decls.
  158. BugReporter BR(*Mgr);
  159. checkerMgr->runCheckersOnASTDecl(D, *Mgr, BR);
  160. }
  161. switch (D->getKind()) {
  162. case Decl::Namespace: {
  163. HandleDeclContext(C, cast<NamespaceDecl>(D));
  164. break;
  165. }
  166. case Decl::CXXConstructor:
  167. case Decl::CXXDestructor:
  168. case Decl::CXXConversion:
  169. case Decl::CXXMethod:
  170. case Decl::Function: {
  171. FunctionDecl *FD = cast<FunctionDecl>(D);
  172. // We skip function template definitions, as their semantics is
  173. // only determined when they are instantiated.
  174. if (FD->isThisDeclarationADefinition() &&
  175. !FD->isDependentContext()) {
  176. if (!Opts.AnalyzeSpecificFunction.empty() &&
  177. FD->getDeclName().getAsString() != Opts.AnalyzeSpecificFunction)
  178. break;
  179. DisplayFunction(FD);
  180. HandleCode(FD);
  181. }
  182. break;
  183. }
  184. case Decl::ObjCCategoryImpl:
  185. case Decl::ObjCImplementation: {
  186. ObjCImplDecl *ID = cast<ObjCImplDecl>(D);
  187. HandleCode(ID);
  188. for (ObjCContainerDecl::method_iterator MI = ID->meth_begin(),
  189. ME = ID->meth_end(); MI != ME; ++MI) {
  190. BugReporter BR(*Mgr);
  191. checkerMgr->runCheckersOnASTDecl(*MI, *Mgr, BR);
  192. if ((*MI)->isThisDeclarationADefinition()) {
  193. if (!Opts.AnalyzeSpecificFunction.empty() &&
  194. Opts.AnalyzeSpecificFunction !=
  195. (*MI)->getSelector().getAsString())
  196. continue;
  197. DisplayFunction(*MI);
  198. HandleCode(*MI);
  199. }
  200. }
  201. break;
  202. }
  203. default:
  204. break;
  205. }
  206. }
  207. void AnalysisConsumer::HandleTranslationUnit(ASTContext &C) {
  208. {
  209. // Introduce a scope to destroy BR before Mgr.
  210. BugReporter BR(*Mgr);
  211. TranslationUnitDecl *TU = C.getTranslationUnitDecl();
  212. checkerMgr->runCheckersOnASTDecl(TU, *Mgr, BR);
  213. HandleDeclContext(C, TU);
  214. // After all decls handled, run checkers on the entire TranslationUnit.
  215. checkerMgr->runCheckersOnEndOfTranslationUnit(TU, *Mgr, BR);
  216. }
  217. // Explicitly destroy the PathDiagnosticConsumer. This will flush its output.
  218. // FIXME: This should be replaced with something that doesn't rely on
  219. // side-effects in PathDiagnosticConsumer's destructor. This is required when
  220. // used with option -disable-free.
  221. Mgr.reset(NULL);
  222. }
  223. static void FindBlocks(DeclContext *D, SmallVectorImpl<Decl*> &WL) {
  224. if (BlockDecl *BD = dyn_cast<BlockDecl>(D))
  225. WL.push_back(BD);
  226. for (DeclContext::decl_iterator I = D->decls_begin(), E = D->decls_end();
  227. I!=E; ++I)
  228. if (DeclContext *DC = dyn_cast<DeclContext>(*I))
  229. FindBlocks(DC, WL);
  230. }
  231. static void RunPathSensitiveChecks(AnalysisConsumer &C, AnalysisManager &mgr,
  232. Decl *D);
  233. void AnalysisConsumer::HandleCode(Decl *D) {
  234. // Don't run the actions if an error has occurred with parsing the file.
  235. DiagnosticsEngine &Diags = PP.getDiagnostics();
  236. if (Diags.hasErrorOccurred() || Diags.hasFatalErrorOccurred())
  237. return;
  238. // Don't run the actions on declarations in header files unless
  239. // otherwise specified.
  240. SourceManager &SM = Ctx->getSourceManager();
  241. SourceLocation SL = SM.getExpansionLoc(D->getLocation());
  242. if (!Opts.AnalyzeAll && !SM.isFromMainFile(SL))
  243. return;
  244. // Clear the AnalysisManager of old AnalysisDeclContexts.
  245. Mgr->ClearContexts();
  246. // Dispatch on the actions.
  247. SmallVector<Decl*, 10> WL;
  248. WL.push_back(D);
  249. if (D->hasBody() && Opts.AnalyzeNestedBlocks)
  250. FindBlocks(cast<DeclContext>(D), WL);
  251. BugReporter BR(*Mgr);
  252. for (SmallVectorImpl<Decl*>::iterator WI=WL.begin(), WE=WL.end();
  253. WI != WE; ++WI)
  254. if ((*WI)->hasBody()) {
  255. checkerMgr->runCheckersOnASTBody(*WI, *Mgr, BR);
  256. if (checkerMgr->hasPathSensitiveCheckers())
  257. RunPathSensitiveChecks(*this, *Mgr, *WI);
  258. }
  259. }
  260. //===----------------------------------------------------------------------===//
  261. // Path-sensitive checking.
  262. //===----------------------------------------------------------------------===//
  263. static void ActionExprEngine(AnalysisConsumer &C, AnalysisManager &mgr,
  264. Decl *D, bool ObjCGCEnabled) {
  265. // Construct the analysis engine. First check if the CFG is valid.
  266. // FIXME: Inter-procedural analysis will need to handle invalid CFGs.
  267. if (!mgr.getCFG(D))
  268. return;
  269. ExprEngine Eng(mgr, ObjCGCEnabled);
  270. // Set the graph auditor.
  271. OwningPtr<ExplodedNode::Auditor> Auditor;
  272. if (mgr.shouldVisualizeUbigraph()) {
  273. Auditor.reset(CreateUbiViz());
  274. ExplodedNode::SetAuditor(Auditor.get());
  275. }
  276. // Execute the worklist algorithm.
  277. Eng.ExecuteWorkList(mgr.getAnalysisDeclContextManager().getStackFrame(D, 0),
  278. mgr.getMaxNodes());
  279. // Release the auditor (if any) so that it doesn't monitor the graph
  280. // created BugReporter.
  281. ExplodedNode::SetAuditor(0);
  282. // Visualize the exploded graph.
  283. if (mgr.shouldVisualizeGraphviz())
  284. Eng.ViewGraph(mgr.shouldTrimGraph());
  285. // Display warnings.
  286. Eng.getBugReporter().FlushReports();
  287. }
  288. static void RunPathSensitiveChecks(AnalysisConsumer &C, AnalysisManager &mgr,
  289. Decl *D) {
  290. switch (mgr.getLangOptions().getGC()) {
  291. case LangOptions::NonGC:
  292. ActionExprEngine(C, mgr, D, false);
  293. break;
  294. case LangOptions::GCOnly:
  295. ActionExprEngine(C, mgr, D, true);
  296. break;
  297. case LangOptions::HybridGC:
  298. ActionExprEngine(C, mgr, D, false);
  299. ActionExprEngine(C, mgr, D, true);
  300. break;
  301. }
  302. }
  303. //===----------------------------------------------------------------------===//
  304. // AnalysisConsumer creation.
  305. //===----------------------------------------------------------------------===//
  306. ASTConsumer* ento::CreateAnalysisConsumer(const Preprocessor& pp,
  307. const std::string& outDir,
  308. const AnalyzerOptions& opts,
  309. ArrayRef<std::string> plugins) {
  310. // Disable the effects of '-Werror' when using the AnalysisConsumer.
  311. pp.getDiagnostics().setWarningsAsErrors(false);
  312. return new AnalysisConsumer(pp, outDir, opts, plugins);
  313. }
  314. //===----------------------------------------------------------------------===//
  315. // Ubigraph Visualization. FIXME: Move to separate file.
  316. //===----------------------------------------------------------------------===//
  317. namespace {
  318. class UbigraphViz : public ExplodedNode::Auditor {
  319. OwningPtr<raw_ostream> Out;
  320. llvm::sys::Path Dir, Filename;
  321. unsigned Cntr;
  322. typedef llvm::DenseMap<void*,unsigned> VMap;
  323. VMap M;
  324. public:
  325. UbigraphViz(raw_ostream *out, llvm::sys::Path& dir,
  326. llvm::sys::Path& filename);
  327. ~UbigraphViz();
  328. virtual void AddEdge(ExplodedNode *Src, ExplodedNode *Dst);
  329. };
  330. } // end anonymous namespace
  331. static ExplodedNode::Auditor* CreateUbiViz() {
  332. std::string ErrMsg;
  333. llvm::sys::Path Dir = llvm::sys::Path::GetTemporaryDirectory(&ErrMsg);
  334. if (!ErrMsg.empty())
  335. return 0;
  336. llvm::sys::Path Filename = Dir;
  337. Filename.appendComponent("llvm_ubi");
  338. Filename.makeUnique(true,&ErrMsg);
  339. if (!ErrMsg.empty())
  340. return 0;
  341. llvm::errs() << "Writing '" << Filename.str() << "'.\n";
  342. OwningPtr<llvm::raw_fd_ostream> Stream;
  343. Stream.reset(new llvm::raw_fd_ostream(Filename.c_str(), ErrMsg));
  344. if (!ErrMsg.empty())
  345. return 0;
  346. return new UbigraphViz(Stream.take(), Dir, Filename);
  347. }
  348. void UbigraphViz::AddEdge(ExplodedNode *Src, ExplodedNode *Dst) {
  349. assert (Src != Dst && "Self-edges are not allowed.");
  350. // Lookup the Src. If it is a new node, it's a root.
  351. VMap::iterator SrcI= M.find(Src);
  352. unsigned SrcID;
  353. if (SrcI == M.end()) {
  354. M[Src] = SrcID = Cntr++;
  355. *Out << "('vertex', " << SrcID << ", ('color','#00ff00'))\n";
  356. }
  357. else
  358. SrcID = SrcI->second;
  359. // Lookup the Dst.
  360. VMap::iterator DstI= M.find(Dst);
  361. unsigned DstID;
  362. if (DstI == M.end()) {
  363. M[Dst] = DstID = Cntr++;
  364. *Out << "('vertex', " << DstID << ")\n";
  365. }
  366. else {
  367. // We have hit DstID before. Change its style to reflect a cache hit.
  368. DstID = DstI->second;
  369. *Out << "('change_vertex_style', " << DstID << ", 1)\n";
  370. }
  371. // Add the edge.
  372. *Out << "('edge', " << SrcID << ", " << DstID
  373. << ", ('arrow','true'), ('oriented', 'true'))\n";
  374. }
  375. UbigraphViz::UbigraphViz(raw_ostream *out, llvm::sys::Path& dir,
  376. llvm::sys::Path& filename)
  377. : Out(out), Dir(dir), Filename(filename), Cntr(0) {
  378. *Out << "('vertex_style_attribute', 0, ('shape', 'icosahedron'))\n";
  379. *Out << "('vertex_style', 1, 0, ('shape', 'sphere'), ('color', '#ffcc66'),"
  380. " ('size', '1.5'))\n";
  381. }
  382. UbigraphViz::~UbigraphViz() {
  383. Out.reset(0);
  384. llvm::errs() << "Running 'ubiviz' program... ";
  385. std::string ErrMsg;
  386. llvm::sys::Path Ubiviz = llvm::sys::Program::FindProgramByName("ubiviz");
  387. std::vector<const char*> args;
  388. args.push_back(Ubiviz.c_str());
  389. args.push_back(Filename.c_str());
  390. args.push_back(0);
  391. if (llvm::sys::Program::ExecuteAndWait(Ubiviz, &args[0],0,0,0,0,&ErrMsg)) {
  392. llvm::errs() << "Error viewing graph: " << ErrMsg << "\n";
  393. }
  394. // Delete the directory.
  395. Dir.eraseFromDisk(true);
  396. }