DebugCheckers.cpp 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349
  1. //==- DebugCheckers.cpp - Debugging Checkers ---------------------*- C++ -*-==//
  2. //
  3. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  4. // See https://llvm.org/LICENSE.txt for license information.
  5. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  6. //
  7. //===----------------------------------------------------------------------===//
  8. //
  9. // This file defines checkers that display debugging information.
  10. //
  11. //===----------------------------------------------------------------------===//
  12. #include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
  13. #include "clang/Analysis/Analyses/Dominators.h"
  14. #include "clang/Analysis/Analyses/LiveVariables.h"
  15. #include "clang/Analysis/CallGraph.h"
  16. #include "clang/StaticAnalyzer/Core/Checker.h"
  17. #include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
  18. #include "clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h"
  19. #include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
  20. #include "clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h"
  21. #include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
  22. #include "llvm/Support/Process.h"
  23. using namespace clang;
  24. using namespace ento;
  25. //===----------------------------------------------------------------------===//
  26. // DominatorsTreeDumper
  27. //===----------------------------------------------------------------------===//
  28. namespace {
  29. class DominatorsTreeDumper : public Checker<check::ASTCodeBody> {
  30. public:
  31. void checkASTCodeBody(const Decl *D, AnalysisManager& mgr,
  32. BugReporter &BR) const {
  33. if (AnalysisDeclContext *AC = mgr.getAnalysisDeclContext(D)) {
  34. CFGDomTree Dom;
  35. Dom.buildDominatorTree(AC->getCFG());
  36. Dom.dump();
  37. }
  38. }
  39. };
  40. }
  41. void ento::registerDominatorsTreeDumper(CheckerManager &mgr) {
  42. mgr.registerChecker<DominatorsTreeDumper>();
  43. }
  44. bool ento::shouldRegisterDominatorsTreeDumper(const CheckerManager &mgr) {
  45. return true;
  46. }
  47. //===----------------------------------------------------------------------===//
  48. // PostDominatorsTreeDumper
  49. //===----------------------------------------------------------------------===//
  50. namespace {
  51. class PostDominatorsTreeDumper : public Checker<check::ASTCodeBody> {
  52. public:
  53. void checkASTCodeBody(const Decl *D, AnalysisManager& mgr,
  54. BugReporter &BR) const {
  55. if (AnalysisDeclContext *AC = mgr.getAnalysisDeclContext(D)) {
  56. CFGPostDomTree Dom;
  57. Dom.buildDominatorTree(AC->getCFG());
  58. Dom.dump();
  59. }
  60. }
  61. };
  62. }
  63. void ento::registerPostDominatorsTreeDumper(CheckerManager &mgr) {
  64. mgr.registerChecker<PostDominatorsTreeDumper>();
  65. }
  66. bool ento::shouldRegisterPostDominatorsTreeDumper(const CheckerManager &mgr) {
  67. return true;
  68. }
  69. //===----------------------------------------------------------------------===//
  70. // ControlDependencyTreeDumper
  71. //===----------------------------------------------------------------------===//
  72. namespace {
  73. class ControlDependencyTreeDumper : public Checker<check::ASTCodeBody> {
  74. public:
  75. void checkASTCodeBody(const Decl *D, AnalysisManager& mgr,
  76. BugReporter &BR) const {
  77. if (AnalysisDeclContext *AC = mgr.getAnalysisDeclContext(D)) {
  78. ControlDependencyCalculator Dom(AC->getCFG());
  79. Dom.dump();
  80. }
  81. }
  82. };
  83. }
  84. void ento::registerControlDependencyTreeDumper(CheckerManager &mgr) {
  85. mgr.registerChecker<ControlDependencyTreeDumper>();
  86. }
  87. bool ento::shouldRegisterControlDependencyTreeDumper(const CheckerManager &mgr) {
  88. return true;
  89. }
  90. //===----------------------------------------------------------------------===//
  91. // LiveVariablesDumper
  92. //===----------------------------------------------------------------------===//
  93. namespace {
  94. class LiveVariablesDumper : public Checker<check::ASTCodeBody> {
  95. public:
  96. void checkASTCodeBody(const Decl *D, AnalysisManager& mgr,
  97. BugReporter &BR) const {
  98. if (LiveVariables* L = mgr.getAnalysis<LiveVariables>(D)) {
  99. L->dumpBlockLiveness(mgr.getSourceManager());
  100. }
  101. }
  102. };
  103. }
  104. void ento::registerLiveVariablesDumper(CheckerManager &mgr) {
  105. mgr.registerChecker<LiveVariablesDumper>();
  106. }
  107. bool ento::shouldRegisterLiveVariablesDumper(const CheckerManager &mgr) {
  108. return true;
  109. }
  110. //===----------------------------------------------------------------------===//
  111. // LiveStatementsDumper
  112. //===----------------------------------------------------------------------===//
  113. namespace {
  114. class LiveExpressionsDumper : public Checker<check::ASTCodeBody> {
  115. public:
  116. void checkASTCodeBody(const Decl *D, AnalysisManager& Mgr,
  117. BugReporter &BR) const {
  118. if (LiveVariables *L = Mgr.getAnalysis<RelaxedLiveVariables>(D))
  119. L->dumpExprLiveness(Mgr.getSourceManager());
  120. }
  121. };
  122. }
  123. void ento::registerLiveExpressionsDumper(CheckerManager &mgr) {
  124. mgr.registerChecker<LiveExpressionsDumper>();
  125. }
  126. bool ento::shouldRegisterLiveExpressionsDumper(const CheckerManager &mgr) {
  127. return true;
  128. }
  129. //===----------------------------------------------------------------------===//
  130. // CFGViewer
  131. //===----------------------------------------------------------------------===//
  132. namespace {
  133. class CFGViewer : public Checker<check::ASTCodeBody> {
  134. public:
  135. void checkASTCodeBody(const Decl *D, AnalysisManager& mgr,
  136. BugReporter &BR) const {
  137. if (CFG *cfg = mgr.getCFG(D)) {
  138. cfg->viewCFG(mgr.getLangOpts());
  139. }
  140. }
  141. };
  142. }
  143. void ento::registerCFGViewer(CheckerManager &mgr) {
  144. mgr.registerChecker<CFGViewer>();
  145. }
  146. bool ento::shouldRegisterCFGViewer(const CheckerManager &mgr) {
  147. return true;
  148. }
  149. //===----------------------------------------------------------------------===//
  150. // CFGDumper
  151. //===----------------------------------------------------------------------===//
  152. namespace {
  153. class CFGDumper : public Checker<check::ASTCodeBody> {
  154. public:
  155. void checkASTCodeBody(const Decl *D, AnalysisManager& mgr,
  156. BugReporter &BR) const {
  157. PrintingPolicy Policy(mgr.getLangOpts());
  158. Policy.TerseOutput = true;
  159. Policy.PolishForDeclaration = true;
  160. D->print(llvm::errs(), Policy);
  161. if (CFG *cfg = mgr.getCFG(D)) {
  162. cfg->dump(mgr.getLangOpts(),
  163. llvm::sys::Process::StandardErrHasColors());
  164. }
  165. }
  166. };
  167. }
  168. void ento::registerCFGDumper(CheckerManager &mgr) {
  169. mgr.registerChecker<CFGDumper>();
  170. }
  171. bool ento::shouldRegisterCFGDumper(const CheckerManager &mgr) {
  172. return true;
  173. }
  174. //===----------------------------------------------------------------------===//
  175. // CallGraphViewer
  176. //===----------------------------------------------------------------------===//
  177. namespace {
  178. class CallGraphViewer : public Checker< check::ASTDecl<TranslationUnitDecl> > {
  179. public:
  180. void checkASTDecl(const TranslationUnitDecl *TU, AnalysisManager& mgr,
  181. BugReporter &BR) const {
  182. CallGraph CG;
  183. CG.addToCallGraph(const_cast<TranslationUnitDecl*>(TU));
  184. CG.viewGraph();
  185. }
  186. };
  187. }
  188. void ento::registerCallGraphViewer(CheckerManager &mgr) {
  189. mgr.registerChecker<CallGraphViewer>();
  190. }
  191. bool ento::shouldRegisterCallGraphViewer(const CheckerManager &mgr) {
  192. return true;
  193. }
  194. //===----------------------------------------------------------------------===//
  195. // CallGraphDumper
  196. //===----------------------------------------------------------------------===//
  197. namespace {
  198. class CallGraphDumper : public Checker< check::ASTDecl<TranslationUnitDecl> > {
  199. public:
  200. void checkASTDecl(const TranslationUnitDecl *TU, AnalysisManager& mgr,
  201. BugReporter &BR) const {
  202. CallGraph CG;
  203. CG.addToCallGraph(const_cast<TranslationUnitDecl*>(TU));
  204. CG.dump();
  205. }
  206. };
  207. }
  208. void ento::registerCallGraphDumper(CheckerManager &mgr) {
  209. mgr.registerChecker<CallGraphDumper>();
  210. }
  211. bool ento::shouldRegisterCallGraphDumper(const CheckerManager &mgr) {
  212. return true;
  213. }
  214. //===----------------------------------------------------------------------===//
  215. // ConfigDumper
  216. //===----------------------------------------------------------------------===//
  217. namespace {
  218. class ConfigDumper : public Checker< check::EndOfTranslationUnit > {
  219. typedef AnalyzerOptions::ConfigTable Table;
  220. static int compareEntry(const Table::MapEntryTy *const *LHS,
  221. const Table::MapEntryTy *const *RHS) {
  222. return (*LHS)->getKey().compare((*RHS)->getKey());
  223. }
  224. public:
  225. void checkEndOfTranslationUnit(const TranslationUnitDecl *TU,
  226. AnalysisManager& mgr,
  227. BugReporter &BR) const {
  228. const Table &Config = mgr.options.Config;
  229. SmallVector<const Table::MapEntryTy *, 32> Keys;
  230. for (Table::const_iterator I = Config.begin(), E = Config.end(); I != E;
  231. ++I)
  232. Keys.push_back(&*I);
  233. llvm::array_pod_sort(Keys.begin(), Keys.end(), compareEntry);
  234. llvm::errs() << "[config]\n";
  235. for (unsigned I = 0, E = Keys.size(); I != E; ++I)
  236. llvm::errs() << Keys[I]->getKey() << " = "
  237. << (Keys[I]->second.empty() ? "\"\"" : Keys[I]->second)
  238. << '\n';
  239. }
  240. };
  241. }
  242. void ento::registerConfigDumper(CheckerManager &mgr) {
  243. mgr.registerChecker<ConfigDumper>();
  244. }
  245. bool ento::shouldRegisterConfigDumper(const CheckerManager &mgr) {
  246. return true;
  247. }
  248. //===----------------------------------------------------------------------===//
  249. // ExplodedGraph Viewer
  250. //===----------------------------------------------------------------------===//
  251. namespace {
  252. class ExplodedGraphViewer : public Checker< check::EndAnalysis > {
  253. public:
  254. ExplodedGraphViewer() {}
  255. void checkEndAnalysis(ExplodedGraph &G, BugReporter &B,ExprEngine &Eng) const {
  256. Eng.ViewGraph(false);
  257. }
  258. };
  259. }
  260. void ento::registerExplodedGraphViewer(CheckerManager &mgr) {
  261. mgr.registerChecker<ExplodedGraphViewer>();
  262. }
  263. bool ento::shouldRegisterExplodedGraphViewer(const CheckerManager &mgr) {
  264. return true;
  265. }
  266. //===----------------------------------------------------------------------===//
  267. // Emits a report for every Stmt that the analyzer visits.
  268. //===----------------------------------------------------------------------===//
  269. namespace {
  270. class ReportStmts : public Checker<check::PreStmt<Stmt>> {
  271. BuiltinBug BT_stmtLoc{this, "Statement"};
  272. public:
  273. void checkPreStmt(const Stmt *S, CheckerContext &C) const {
  274. ExplodedNode *Node = C.generateNonFatalErrorNode();
  275. if (!Node)
  276. return;
  277. auto Report =
  278. std::make_unique<PathSensitiveBugReport>(BT_stmtLoc, "Statement", Node);
  279. C.emitReport(std::move(Report));
  280. }
  281. };
  282. } // end of anonymous namespace
  283. void ento::registerReportStmts(CheckerManager &mgr) {
  284. mgr.registerChecker<ReportStmts>();
  285. }
  286. bool ento::shouldRegisterReportStmts(const CheckerManager &mgr) {
  287. return true;
  288. }