diff options
Diffstat (limited to 'lib/StaticAnalyzer/Checkers/AnalyzerStatsChecker.cpp')
-rw-r--r-- | lib/StaticAnalyzer/Checkers/AnalyzerStatsChecker.cpp | 74 |
1 files changed, 49 insertions, 25 deletions
diff --git a/lib/StaticAnalyzer/Checkers/AnalyzerStatsChecker.cpp b/lib/StaticAnalyzer/Checkers/AnalyzerStatsChecker.cpp index cd977bf..aa6f97b 100644 --- a/lib/StaticAnalyzer/Checkers/AnalyzerStatsChecker.cpp +++ b/lib/StaticAnalyzer/Checkers/AnalyzerStatsChecker.cpp @@ -8,6 +8,7 @@ //===----------------------------------------------------------------------===// // This file reports various statistics about analyzer visitation. //===----------------------------------------------------------------------===// +#define DEBUG_TYPE "StatsChecker" #include "ClangSACheckers.h" #include "clang/StaticAnalyzer/Core/Checker.h" @@ -16,12 +17,20 @@ #include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h" #include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h" +#include "clang/AST/DeclObjC.h" #include "clang/Basic/SourceManager.h" #include "llvm/ADT/SmallPtrSet.h" +#include "llvm/ADT/SmallString.h" +#include "llvm/ADT/Statistic.h" using namespace clang; using namespace ento; +STATISTIC(NumBlocks, + "The # of blocks in top level functions"); +STATISTIC(NumBlocksUnreachable, + "The # of unreachable blocks in analyzing top level functions"); + namespace { class AnalyzerStatsChecker : public Checker<check::EndAnalysis> { public: @@ -33,18 +42,23 @@ void AnalyzerStatsChecker::checkEndAnalysis(ExplodedGraph &G, BugReporter &B, ExprEngine &Eng) const { const CFG *C = 0; - const Decl *D = 0; - const LocationContext *LC = 0; const SourceManager &SM = B.getSourceManager(); llvm::SmallPtrSet<const CFGBlock*, 256> reachable; - // Iterate over explodedgraph + // Root node should have the location context of the top most function. + const ExplodedNode *GraphRoot = *G.roots_begin(); + const LocationContext *LC = GraphRoot->getLocation().getLocationContext(); + + const Decl *D = LC->getDecl(); + + // Iterate over the exploded graph. for (ExplodedGraph::node_iterator I = G.nodes_begin(); I != G.nodes_end(); ++I) { const ProgramPoint &P = I->getLocation(); - // Save the LocationContext if we don't have it already - if (!LC) - LC = P.getLocationContext(); + + // Only check the coverage in the top level function (optimization). + if (D != P.getLocationContext()->getDecl()) + continue; if (const BlockEntrance *BE = dyn_cast<BlockEntrance>(&P)) { const CFGBlock *CB = BE->getBlock(); @@ -52,9 +66,8 @@ void AnalyzerStatsChecker::checkEndAnalysis(ExplodedGraph &G, } } - // Get the CFG and the Decl of this block + // Get the CFG and the Decl of this block. C = LC->getCFG(); - D = LC->getAnalysisContext()->getDecl(); unsigned total = 0, unreachable = 0; @@ -70,33 +83,39 @@ void AnalyzerStatsChecker::checkEndAnalysis(ExplodedGraph &G, // We never 'reach' the entry block, so correct the unreachable count unreachable--; + // There is no BlockEntrance corresponding to the exit block as well, so + // assume it is reached as well. + unreachable--; // Generate the warning string - llvm::SmallString<128> buf; + SmallString<128> buf; llvm::raw_svector_ostream output(buf); PresumedLoc Loc = SM.getPresumedLoc(D->getLocation()); - if (Loc.isValid()) { - output << Loc.getFilename() << " : "; + if (!Loc.isValid()) + return; - if (isa<FunctionDecl>(D) || isa<ObjCMethodDecl>(D)) { - const NamedDecl *ND = cast<NamedDecl>(D); - output << *ND; - } - else if (isa<BlockDecl>(D)) { - output << "block(line:" << Loc.getLine() << ":col:" << Loc.getColumn(); - } + if (isa<FunctionDecl>(D) || isa<ObjCMethodDecl>(D)) { + const NamedDecl *ND = cast<NamedDecl>(D); + output << *ND; + } + else if (isa<BlockDecl>(D)) { + output << "block(line:" << Loc.getLine() << ":col:" << Loc.getColumn(); } + NumBlocksUnreachable += unreachable; + NumBlocks += total; + std::string NameOfRootFunction = output.str(); + output << " -> Total CFGBlocks: " << total << " | Unreachable CFGBlocks: " << unreachable << " | Exhausted Block: " << (Eng.wasBlocksExhausted() ? "yes" : "no") << " | Empty WorkList: " << (Eng.hasEmptyWorkList() ? "yes" : "no"); - B.EmitBasicReport("Analyzer Statistics", "Internal Statistics", output.str(), - PathDiagnosticLocation(D, SM)); + B.EmitBasicReport(D, "Analyzer Statistics", "Internal Statistics", + output.str(), PathDiagnosticLocation(D, SM)); - // Emit warning for each block we bailed out on + // Emit warning for each block we bailed out on. typedef CoreEngine::BlocksExhausted::const_iterator ExhaustedIterator; const CoreEngine &CE = Eng.getCoreEngine(); for (ExhaustedIterator I = CE.blocks_exhausted_begin(), @@ -104,10 +123,15 @@ void AnalyzerStatsChecker::checkEndAnalysis(ExplodedGraph &G, const BlockEdge &BE = I->first; const CFGBlock *Exit = BE.getDst(); const CFGElement &CE = Exit->front(); - if (const CFGStmt *CS = dyn_cast<CFGStmt>(&CE)) - B.EmitBasicReport("Bailout Point", "Internal Statistics", "The analyzer " - "stopped analyzing at this point", - PathDiagnosticLocation::createBegin(CS->getStmt(), SM, LC)); + if (const CFGStmt *CS = dyn_cast<CFGStmt>(&CE)) { + SmallString<128> bufI; + llvm::raw_svector_ostream outputI(bufI); + outputI << "(" << NameOfRootFunction << ")" << + ": The analyzer generated a sink at this point"; + B.EmitBasicReport(D, "Sink Point", "Internal Statistics", outputI.str(), + PathDiagnosticLocation::createBegin(CS->getStmt(), + SM, LC)); + } } } |