AnalyzerStatsChecker.cpp revision f7ccbad5d9949e7ddd1cbef43d482553b811e026
152d861ce41ce84d8389495ea78d97bcc962ac5baTom Care//==--AnalyzerStatsChecker.cpp - Analyzer visitation statistics --*- C++ -*-==//
252d861ce41ce84d8389495ea78d97bcc962ac5baTom Care//
352d861ce41ce84d8389495ea78d97bcc962ac5baTom Care//                     The LLVM Compiler Infrastructure
452d861ce41ce84d8389495ea78d97bcc962ac5baTom Care//
552d861ce41ce84d8389495ea78d97bcc962ac5baTom Care// This file is distributed under the University of Illinois Open Source
652d861ce41ce84d8389495ea78d97bcc962ac5baTom Care// License. See LICENSE.TXT for details.
752d861ce41ce84d8389495ea78d97bcc962ac5baTom Care//
852d861ce41ce84d8389495ea78d97bcc962ac5baTom Care//===----------------------------------------------------------------------===//
952d861ce41ce84d8389495ea78d97bcc962ac5baTom Care// This file reports various statistics about analyzer visitation.
1052d861ce41ce84d8389495ea78d97bcc962ac5baTom Care//===----------------------------------------------------------------------===//
1152d861ce41ce84d8389495ea78d97bcc962ac5baTom Care
1258f2e7c3c3860e410fa3d8252862ef10be7cdc70Argyrios Kyrtzidis#include "ClangSACheckers.h"
13ec8605f1d7ec846dbf51047bfd5c56d32d1ff91cArgyrios Kyrtzidis#include "clang/StaticAnalyzer/Core/Checker.h"
1458f2e7c3c3860e410fa3d8252862ef10be7cdc70Argyrios Kyrtzidis#include "clang/StaticAnalyzer/Core/CheckerManager.h"
159b663716449b618ba0390b1dbebc54fa8e971124Ted Kremenek#include "clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h"
1658f2e7c3c3860e410fa3d8252862ef10be7cdc70Argyrios Kyrtzidis#include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
179b663716449b618ba0390b1dbebc54fa8e971124Ted Kremenek#include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h"
18a7af5ea88a6c5bdf87497cca6c20831e8c546751Argyrios Kyrtzidis
19c35fb7d67d515659ad2325b4f6ec97c9fe64fb63Benjamin Kramer#include "clang/AST/DeclObjC.h"
2052d861ce41ce84d8389495ea78d97bcc962ac5baTom Care#include "clang/Basic/SourceManager.h"
2152d861ce41ce84d8389495ea78d97bcc962ac5baTom Care#include "llvm/ADT/SmallPtrSet.h"
228fe83e1df954d72c0f4ffc15d20a5222ec151c21Benjamin Kramer#include "llvm/ADT/SmallString.h"
2352d861ce41ce84d8389495ea78d97bcc962ac5baTom Care
2452d861ce41ce84d8389495ea78d97bcc962ac5baTom Careusing namespace clang;
259ef6537a894c33003359b1f9b9676e9178e028b7Ted Kremenekusing namespace ento;
2652d861ce41ce84d8389495ea78d97bcc962ac5baTom Care
2752d861ce41ce84d8389495ea78d97bcc962ac5baTom Carenamespace {
28ec8605f1d7ec846dbf51047bfd5c56d32d1ff91cArgyrios Kyrtzidisclass AnalyzerStatsChecker : public Checker<check::EndAnalysis> {
2952d861ce41ce84d8389495ea78d97bcc962ac5baTom Carepublic:
3058f2e7c3c3860e410fa3d8252862ef10be7cdc70Argyrios Kyrtzidis  void checkEndAnalysis(ExplodedGraph &G, BugReporter &B,ExprEngine &Eng) const;
3152d861ce41ce84d8389495ea78d97bcc962ac5baTom Care};
3252d861ce41ce84d8389495ea78d97bcc962ac5baTom Care}
3352d861ce41ce84d8389495ea78d97bcc962ac5baTom Care
3458f2e7c3c3860e410fa3d8252862ef10be7cdc70Argyrios Kyrtzidisvoid AnalyzerStatsChecker::checkEndAnalysis(ExplodedGraph &G,
3552d861ce41ce84d8389495ea78d97bcc962ac5baTom Care                                            BugReporter &B,
3658f2e7c3c3860e410fa3d8252862ef10be7cdc70Argyrios Kyrtzidis                                            ExprEngine &Eng) const {
3752d861ce41ce84d8389495ea78d97bcc962ac5baTom Care  const CFG *C  = 0;
3852d861ce41ce84d8389495ea78d97bcc962ac5baTom Care  const Decl *D = 0;
3952d861ce41ce84d8389495ea78d97bcc962ac5baTom Care  const LocationContext *LC = 0;
4052d861ce41ce84d8389495ea78d97bcc962ac5baTom Care  const SourceManager &SM = B.getSourceManager();
4158f2e7c3c3860e410fa3d8252862ef10be7cdc70Argyrios Kyrtzidis  llvm::SmallPtrSet<const CFGBlock*, 256> reachable;
4252d861ce41ce84d8389495ea78d97bcc962ac5baTom Care
4352d861ce41ce84d8389495ea78d97bcc962ac5baTom Care  // Iterate over explodedgraph
4452d861ce41ce84d8389495ea78d97bcc962ac5baTom Care  for (ExplodedGraph::node_iterator I = G.nodes_begin();
4552d861ce41ce84d8389495ea78d97bcc962ac5baTom Care      I != G.nodes_end(); ++I) {
4652d861ce41ce84d8389495ea78d97bcc962ac5baTom Care    const ProgramPoint &P = I->getLocation();
4752d861ce41ce84d8389495ea78d97bcc962ac5baTom Care    // Save the LocationContext if we don't have it already
4852d861ce41ce84d8389495ea78d97bcc962ac5baTom Care    if (!LC)
4952d861ce41ce84d8389495ea78d97bcc962ac5baTom Care      LC = P.getLocationContext();
5052d861ce41ce84d8389495ea78d97bcc962ac5baTom Care
512cb5520f62e52f09175f546af12b8b8fb05b81adTom Care    if (const BlockEntrance *BE = dyn_cast<BlockEntrance>(&P)) {
522cb5520f62e52f09175f546af12b8b8fb05b81adTom Care      const CFGBlock *CB = BE->getBlock();
5352d861ce41ce84d8389495ea78d97bcc962ac5baTom Care      reachable.insert(CB);
5452d861ce41ce84d8389495ea78d97bcc962ac5baTom Care    }
5552d861ce41ce84d8389495ea78d97bcc962ac5baTom Care  }
5652d861ce41ce84d8389495ea78d97bcc962ac5baTom Care
5752d861ce41ce84d8389495ea78d97bcc962ac5baTom Care  // Get the CFG and the Decl of this block
5852d861ce41ce84d8389495ea78d97bcc962ac5baTom Care  C = LC->getCFG();
591d26f48dc2eea1c07431ca1519d7034a21b9bcffTed Kremenek  D = LC->getAnalysisDeclContext()->getDecl();
6052d861ce41ce84d8389495ea78d97bcc962ac5baTom Care
6152d861ce41ce84d8389495ea78d97bcc962ac5baTom Care  unsigned total = 0, unreachable = 0;
6252d861ce41ce84d8389495ea78d97bcc962ac5baTom Care
6352d861ce41ce84d8389495ea78d97bcc962ac5baTom Care  // Find CFGBlocks that were not covered by any node
6452d861ce41ce84d8389495ea78d97bcc962ac5baTom Care  for (CFG::const_iterator I = C->begin(); I != C->end(); ++I) {
6552d861ce41ce84d8389495ea78d97bcc962ac5baTom Care    const CFGBlock *CB = *I;
6652d861ce41ce84d8389495ea78d97bcc962ac5baTom Care    ++total;
6752d861ce41ce84d8389495ea78d97bcc962ac5baTom Care    // Check if the block is unreachable
6852d861ce41ce84d8389495ea78d97bcc962ac5baTom Care    if (!reachable.count(CB)) {
6952d861ce41ce84d8389495ea78d97bcc962ac5baTom Care      ++unreachable;
7052d861ce41ce84d8389495ea78d97bcc962ac5baTom Care    }
7152d861ce41ce84d8389495ea78d97bcc962ac5baTom Care  }
7252d861ce41ce84d8389495ea78d97bcc962ac5baTom Care
7352d861ce41ce84d8389495ea78d97bcc962ac5baTom Care  // We never 'reach' the entry block, so correct the unreachable count
7452d861ce41ce84d8389495ea78d97bcc962ac5baTom Care  unreachable--;
7552d861ce41ce84d8389495ea78d97bcc962ac5baTom Care
7652d861ce41ce84d8389495ea78d97bcc962ac5baTom Care  // Generate the warning string
77f7ccbad5d9949e7ddd1cbef43d482553b811e026Dylan Noblesmith  SmallString<128> buf;
7852d861ce41ce84d8389495ea78d97bcc962ac5baTom Care  llvm::raw_svector_ostream output(buf);
7952d861ce41ce84d8389495ea78d97bcc962ac5baTom Care  PresumedLoc Loc = SM.getPresumedLoc(D->getLocation());
80cb7b1e17b63967317ab5cc55682168cf0380519aDouglas Gregor  if (Loc.isValid()) {
81cb7b1e17b63967317ab5cc55682168cf0380519aDouglas Gregor    output << Loc.getFilename() << " : ";
8252d861ce41ce84d8389495ea78d97bcc962ac5baTom Care
83cb7b1e17b63967317ab5cc55682168cf0380519aDouglas Gregor    if (isa<FunctionDecl>(D) || isa<ObjCMethodDecl>(D)) {
84cb7b1e17b63967317ab5cc55682168cf0380519aDouglas Gregor      const NamedDecl *ND = cast<NamedDecl>(D);
85b8989f27f116ff2400e92a52c067a69846119eb5Benjamin Kramer      output << *ND;
86cb7b1e17b63967317ab5cc55682168cf0380519aDouglas Gregor    }
87cb7b1e17b63967317ab5cc55682168cf0380519aDouglas Gregor    else if (isa<BlockDecl>(D)) {
88cb7b1e17b63967317ab5cc55682168cf0380519aDouglas Gregor      output << "block(line:" << Loc.getLine() << ":col:" << Loc.getColumn();
89cb7b1e17b63967317ab5cc55682168cf0380519aDouglas Gregor    }
9052d861ce41ce84d8389495ea78d97bcc962ac5baTom Care  }
91cb7b1e17b63967317ab5cc55682168cf0380519aDouglas Gregor
9252d861ce41ce84d8389495ea78d97bcc962ac5baTom Care  output << " -> Total CFGBlocks: " << total << " | Unreachable CFGBlocks: "
93422ab7a49a9a4252dbc6350e49d7a5708337b9c7Ted Kremenek      << unreachable << " | Exhausted Block: "
94422ab7a49a9a4252dbc6350e49d7a5708337b9c7Ted Kremenek      << (Eng.wasBlocksExhausted() ? "yes" : "no")
9552d861ce41ce84d8389495ea78d97bcc962ac5baTom Care      << " | Empty WorkList: "
960e1cd944398c9e9a3d4c0cf5273a126be91830e8Tom Care      << (Eng.hasEmptyWorkList() ? "yes" : "no");
9752d861ce41ce84d8389495ea78d97bcc962ac5baTom Care
9852d861ce41ce84d8389495ea78d97bcc962ac5baTom Care  B.EmitBasicReport("Analyzer Statistics", "Internal Statistics", output.str(),
99590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks      PathDiagnosticLocation(D, SM));
1002cb5520f62e52f09175f546af12b8b8fb05b81adTom Care
1012cb5520f62e52f09175f546af12b8b8fb05b81adTom Care  // Emit warning for each block we bailed out on
102422ab7a49a9a4252dbc6350e49d7a5708337b9c7Ted Kremenek  typedef CoreEngine::BlocksExhausted::const_iterator ExhaustedIterator;
103d2592a34a059e7cbb2b11dc53649ac4912422909Argyrios Kyrtzidis  const CoreEngine &CE = Eng.getCoreEngine();
104422ab7a49a9a4252dbc6350e49d7a5708337b9c7Ted Kremenek  for (ExhaustedIterator I = CE.blocks_exhausted_begin(),
105422ab7a49a9a4252dbc6350e49d7a5708337b9c7Ted Kremenek      E = CE.blocks_exhausted_end(); I != E; ++I) {
1062cb5520f62e52f09175f546af12b8b8fb05b81adTom Care    const BlockEdge &BE =  I->first;
1072cb5520f62e52f09175f546af12b8b8fb05b81adTom Care    const CFGBlock *Exit = BE.getDst();
1082cb5520f62e52f09175f546af12b8b8fb05b81adTom Care    const CFGElement &CE = Exit->front();
1092cb5520f62e52f09175f546af12b8b8fb05b81adTom Care    if (const CFGStmt *CS = dyn_cast<CFGStmt>(&CE))
1102cb5520f62e52f09175f546af12b8b8fb05b81adTom Care      B.EmitBasicReport("Bailout Point", "Internal Statistics", "The analyzer "
111590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks          "stopped analyzing at this point",
112590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks          PathDiagnosticLocation::createBegin(CS->getStmt(), SM, LC));
1132cb5520f62e52f09175f546af12b8b8fb05b81adTom Care  }
11452d861ce41ce84d8389495ea78d97bcc962ac5baTom Care}
11558f2e7c3c3860e410fa3d8252862ef10be7cdc70Argyrios Kyrtzidis
11658f2e7c3c3860e410fa3d8252862ef10be7cdc70Argyrios Kyrtzidisvoid ento::registerAnalyzerStatsChecker(CheckerManager &mgr) {
11758f2e7c3c3860e410fa3d8252862ef10be7cdc70Argyrios Kyrtzidis  mgr.registerChecker<AnalyzerStatsChecker>();
11858f2e7c3c3860e410fa3d8252862ef10be7cdc70Argyrios Kyrtzidis}
119