AnalyzerStatsChecker.cpp 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118
  1. //==--AnalyzerStatsChecker.cpp - Analyzer visitation statistics --*- C++ -*-==//
  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. // This file reports various statistics about analyzer visitation.
  10. //===----------------------------------------------------------------------===//
  11. #include "ClangSACheckers.h"
  12. #include "clang/StaticAnalyzer/Core/Checker.h"
  13. #include "clang/StaticAnalyzer/Core/CheckerManager.h"
  14. #include "clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h"
  15. #include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
  16. #include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h"
  17. #include "clang/AST/DeclObjC.h"
  18. #include "clang/Basic/SourceManager.h"
  19. #include "llvm/ADT/SmallPtrSet.h"
  20. #include "llvm/ADT/SmallString.h"
  21. using namespace clang;
  22. using namespace ento;
  23. namespace {
  24. class AnalyzerStatsChecker : public Checker<check::EndAnalysis> {
  25. public:
  26. void checkEndAnalysis(ExplodedGraph &G, BugReporter &B,ExprEngine &Eng) const;
  27. };
  28. }
  29. void AnalyzerStatsChecker::checkEndAnalysis(ExplodedGraph &G,
  30. BugReporter &B,
  31. ExprEngine &Eng) const {
  32. const CFG *C = 0;
  33. const Decl *D = 0;
  34. const LocationContext *LC = 0;
  35. const SourceManager &SM = B.getSourceManager();
  36. llvm::SmallPtrSet<const CFGBlock*, 256> reachable;
  37. // Iterate over explodedgraph
  38. for (ExplodedGraph::node_iterator I = G.nodes_begin();
  39. I != G.nodes_end(); ++I) {
  40. const ProgramPoint &P = I->getLocation();
  41. // Save the LocationContext if we don't have it already
  42. if (!LC)
  43. LC = P.getLocationContext();
  44. if (const BlockEntrance *BE = dyn_cast<BlockEntrance>(&P)) {
  45. const CFGBlock *CB = BE->getBlock();
  46. reachable.insert(CB);
  47. }
  48. }
  49. // Get the CFG and the Decl of this block
  50. C = LC->getCFG();
  51. D = LC->getAnalysisDeclContext()->getDecl();
  52. unsigned total = 0, unreachable = 0;
  53. // Find CFGBlocks that were not covered by any node
  54. for (CFG::const_iterator I = C->begin(); I != C->end(); ++I) {
  55. const CFGBlock *CB = *I;
  56. ++total;
  57. // Check if the block is unreachable
  58. if (!reachable.count(CB)) {
  59. ++unreachable;
  60. }
  61. }
  62. // We never 'reach' the entry block, so correct the unreachable count
  63. unreachable--;
  64. // Generate the warning string
  65. SmallString<128> buf;
  66. llvm::raw_svector_ostream output(buf);
  67. PresumedLoc Loc = SM.getPresumedLoc(D->getLocation());
  68. if (Loc.isValid()) {
  69. output << Loc.getFilename() << " : ";
  70. if (isa<FunctionDecl>(D) || isa<ObjCMethodDecl>(D)) {
  71. const NamedDecl *ND = cast<NamedDecl>(D);
  72. output << *ND;
  73. }
  74. else if (isa<BlockDecl>(D)) {
  75. output << "block(line:" << Loc.getLine() << ":col:" << Loc.getColumn();
  76. }
  77. }
  78. output << " -> Total CFGBlocks: " << total << " | Unreachable CFGBlocks: "
  79. << unreachable << " | Exhausted Block: "
  80. << (Eng.wasBlocksExhausted() ? "yes" : "no")
  81. << " | Empty WorkList: "
  82. << (Eng.hasEmptyWorkList() ? "yes" : "no");
  83. B.EmitBasicReport("Analyzer Statistics", "Internal Statistics", output.str(),
  84. PathDiagnosticLocation(D, SM));
  85. // Emit warning for each block we bailed out on
  86. typedef CoreEngine::BlocksExhausted::const_iterator ExhaustedIterator;
  87. const CoreEngine &CE = Eng.getCoreEngine();
  88. for (ExhaustedIterator I = CE.blocks_exhausted_begin(),
  89. E = CE.blocks_exhausted_end(); I != E; ++I) {
  90. const BlockEdge &BE = I->first;
  91. const CFGBlock *Exit = BE.getDst();
  92. const CFGElement &CE = Exit->front();
  93. if (const CFGStmt *CS = dyn_cast<CFGStmt>(&CE))
  94. B.EmitBasicReport("Bailout Point", "Internal Statistics", "The analyzer "
  95. "stopped analyzing at this point",
  96. PathDiagnosticLocation::createBegin(CS->getStmt(), SM, LC));
  97. }
  98. }
  99. void ento::registerAnalyzerStatsChecker(CheckerManager &mgr) {
  100. mgr.registerChecker<AnalyzerStatsChecker>();
  101. }