blob: 443916bd67d712b3567bb9f98117a8b194de9242 [file] [log] [blame]
Tom Care52d861c2010-09-10 00:44:44 +00001//==--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
Argyrios Kyrtzidis58f2e7c2011-02-28 01:26:50 +000012#include "ClangSACheckers.h"
Argyrios Kyrtzidisec8605f2011-03-01 01:16:21 +000013#include "clang/StaticAnalyzer/Core/Checker.h"
Argyrios Kyrtzidis58f2e7c2011-02-28 01:26:50 +000014#include "clang/StaticAnalyzer/Core/CheckerManager.h"
Ted Kremenek9b663712011-02-10 01:03:03 +000015#include "clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h"
Argyrios Kyrtzidis58f2e7c2011-02-28 01:26:50 +000016#include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
Ted Kremenek9b663712011-02-10 01:03:03 +000017#include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h"
Argyrios Kyrtzidisa7af5ea2010-12-22 18:52:56 +000018
Tom Care52d861c2010-09-10 00:44:44 +000019#include "clang/Basic/SourceManager.h"
20#include "llvm/ADT/SmallPtrSet.h"
21
22using namespace clang;
Ted Kremenek9ef65372010-12-23 07:20:52 +000023using namespace ento;
Tom Care52d861c2010-09-10 00:44:44 +000024
25namespace {
Argyrios Kyrtzidisec8605f2011-03-01 01:16:21 +000026class AnalyzerStatsChecker : public Checker<check::EndAnalysis> {
Tom Care52d861c2010-09-10 00:44:44 +000027public:
Argyrios Kyrtzidis58f2e7c2011-02-28 01:26:50 +000028 void checkEndAnalysis(ExplodedGraph &G, BugReporter &B,ExprEngine &Eng) const;
Tom Care52d861c2010-09-10 00:44:44 +000029};
30}
31
Argyrios Kyrtzidis58f2e7c2011-02-28 01:26:50 +000032void AnalyzerStatsChecker::checkEndAnalysis(ExplodedGraph &G,
Tom Care52d861c2010-09-10 00:44:44 +000033 BugReporter &B,
Argyrios Kyrtzidis58f2e7c2011-02-28 01:26:50 +000034 ExprEngine &Eng) const {
Tom Care52d861c2010-09-10 00:44:44 +000035 const CFG *C = 0;
36 const Decl *D = 0;
37 const LocationContext *LC = 0;
38 const SourceManager &SM = B.getSourceManager();
Argyrios Kyrtzidis58f2e7c2011-02-28 01:26:50 +000039 llvm::SmallPtrSet<const CFGBlock*, 256> reachable;
Tom Care52d861c2010-09-10 00:44:44 +000040
41 // Iterate over explodedgraph
42 for (ExplodedGraph::node_iterator I = G.nodes_begin();
43 I != G.nodes_end(); ++I) {
44 const ProgramPoint &P = I->getLocation();
45 // Save the LocationContext if we don't have it already
46 if (!LC)
47 LC = P.getLocationContext();
48
Tom Care2cb55202010-09-29 23:48:34 +000049 if (const BlockEntrance *BE = dyn_cast<BlockEntrance>(&P)) {
50 const CFGBlock *CB = BE->getBlock();
Tom Care52d861c2010-09-10 00:44:44 +000051 reachable.insert(CB);
52 }
53 }
54
55 // Get the CFG and the Decl of this block
56 C = LC->getCFG();
57 D = LC->getAnalysisContext()->getDecl();
58
59 unsigned total = 0, unreachable = 0;
60
61 // Find CFGBlocks that were not covered by any node
62 for (CFG::const_iterator I = C->begin(); I != C->end(); ++I) {
63 const CFGBlock *CB = *I;
64 ++total;
65 // Check if the block is unreachable
66 if (!reachable.count(CB)) {
67 ++unreachable;
68 }
69 }
70
71 // We never 'reach' the entry block, so correct the unreachable count
72 unreachable--;
73
74 // Generate the warning string
75 llvm::SmallString<128> buf;
76 llvm::raw_svector_ostream output(buf);
77 PresumedLoc Loc = SM.getPresumedLoc(D->getLocation());
Douglas Gregorcb7b1e12010-11-12 07:15:47 +000078 if (Loc.isValid()) {
79 output << Loc.getFilename() << " : ";
Tom Care52d861c2010-09-10 00:44:44 +000080
Douglas Gregorcb7b1e12010-11-12 07:15:47 +000081 if (isa<FunctionDecl>(D) || isa<ObjCMethodDecl>(D)) {
82 const NamedDecl *ND = cast<NamedDecl>(D);
83 output << ND;
84 }
85 else if (isa<BlockDecl>(D)) {
86 output << "block(line:" << Loc.getLine() << ":col:" << Loc.getColumn();
87 }
Tom Care52d861c2010-09-10 00:44:44 +000088 }
Douglas Gregorcb7b1e12010-11-12 07:15:47 +000089
Tom Care52d861c2010-09-10 00:44:44 +000090 output << " -> Total CFGBlocks: " << total << " | Unreachable CFGBlocks: "
Ted Kremenek422ab7a2011-04-02 02:56:23 +000091 << unreachable << " | Exhausted Block: "
92 << (Eng.wasBlocksExhausted() ? "yes" : "no")
Tom Care52d861c2010-09-10 00:44:44 +000093 << " | Empty WorkList: "
Tom Care0e1cd942010-09-22 21:07:51 +000094 << (Eng.hasEmptyWorkList() ? "yes" : "no");
Tom Care52d861c2010-09-10 00:44:44 +000095
96 B.EmitBasicReport("Analyzer Statistics", "Internal Statistics", output.str(),
Anna Zaks590dd8e2011-09-20 21:38:35 +000097 PathDiagnosticLocation(D, SM));
Tom Care2cb55202010-09-29 23:48:34 +000098
99 // Emit warning for each block we bailed out on
Ted Kremenek422ab7a2011-04-02 02:56:23 +0000100 typedef CoreEngine::BlocksExhausted::const_iterator ExhaustedIterator;
Argyrios Kyrtzidisd2592a32010-12-22 18:53:44 +0000101 const CoreEngine &CE = Eng.getCoreEngine();
Ted Kremenek422ab7a2011-04-02 02:56:23 +0000102 for (ExhaustedIterator I = CE.blocks_exhausted_begin(),
103 E = CE.blocks_exhausted_end(); I != E; ++I) {
Tom Care2cb55202010-09-29 23:48:34 +0000104 const BlockEdge &BE = I->first;
105 const CFGBlock *Exit = BE.getDst();
106 const CFGElement &CE = Exit->front();
107 if (const CFGStmt *CS = dyn_cast<CFGStmt>(&CE))
108 B.EmitBasicReport("Bailout Point", "Internal Statistics", "The analyzer "
Anna Zaks590dd8e2011-09-20 21:38:35 +0000109 "stopped analyzing at this point",
110 PathDiagnosticLocation::createBegin(CS->getStmt(), SM, LC));
Tom Care2cb55202010-09-29 23:48:34 +0000111 }
Tom Care52d861c2010-09-10 00:44:44 +0000112}
Argyrios Kyrtzidis58f2e7c2011-02-28 01:26:50 +0000113
114void ento::registerAnalyzerStatsChecker(CheckerManager &mgr) {
115 mgr.registerChecker<AnalyzerStatsChecker>();
116}