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