brintos

brintos / llvm-project-archived public Read only

0
0
Text · 4.8 KiB · b5778e0 Raw
139 lines · cpp
1//==--AnalyzerStatsChecker.cpp - Analyzer visitation statistics --*- C++ -*-==//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8// This file reports various statistics about analyzer visitation.9//===----------------------------------------------------------------------===//10#include "clang/AST/DeclObjC.h"11#include "clang/Basic/SourceManager.h"12#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"13#include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h"14#include "clang/StaticAnalyzer/Core/Checker.h"15#include "clang/StaticAnalyzer/Core/CheckerManager.h"16#include "clang/StaticAnalyzer/Core/PathSensitive/EntryPointStats.h"17#include "clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h"18#include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"19#include "llvm/ADT/STLExtras.h"20#include "llvm/ADT/SmallPtrSet.h"21#include "llvm/Support/raw_ostream.h"22#include <optional>23 24using namespace clang;25using namespace ento;26 27#define DEBUG_TYPE "StatsChecker"28 29STAT_COUNTER(NumBlocks, "The # of blocks in top level functions");30STAT_COUNTER(NumBlocksUnreachable,31             "The # of unreachable blocks in analyzing top level functions");32 33namespace {34class AnalyzerStatsChecker : public Checker<check::EndAnalysis> {35public:36  void checkEndAnalysis(ExplodedGraph &G, BugReporter &B,ExprEngine &Eng) const;37};38}39 40void AnalyzerStatsChecker::checkEndAnalysis(ExplodedGraph &G,41                                            BugReporter &B,42                                            ExprEngine &Eng) const {43  const CFG *C = nullptr;44  const SourceManager &SM = B.getSourceManager();45  llvm::SmallPtrSet<const CFGBlock*, 32> reachable;46 47  const LocationContext *LC = Eng.getRootLocationContext();48 49  const Decl *D = LC->getDecl();50 51  // Iterate over the exploded graph.52  for (const ExplodedNode &N : G.nodes()) {53    const ProgramPoint &P = N.getLocation();54 55    // Only check the coverage in the top level function (optimization).56    if (D != P.getLocationContext()->getDecl())57      continue;58 59    if (std::optional<BlockEntrance> BE = P.getAs<BlockEntrance>()) {60      const CFGBlock *CB = BE->getBlock();61      reachable.insert(CB);62    }63  }64 65  // Get the CFG and the Decl of this block.66  C = LC->getCFG();67 68  unsigned total = 0, unreachable = 0;69 70  // Find CFGBlocks that were not covered by any node71  for (CFG::const_iterator I = C->begin(); I != C->end(); ++I) {72    const CFGBlock *CB = *I;73    ++total;74    // Check if the block is unreachable75    if (!reachable.count(CB)) {76      ++unreachable;77    }78  }79 80  // We never 'reach' the entry block, so correct the unreachable count81  unreachable--;82  // There is no BlockEntrance corresponding to the exit block as well, so83  // assume it is reached as well.84  unreachable--;85 86  // Generate the warning string87  SmallString<128> buf;88  llvm::raw_svector_ostream output(buf);89  PresumedLoc Loc = SM.getPresumedLoc(D->getLocation());90  if (!Loc.isValid())91    return;92 93  if (isa<FunctionDecl, ObjCMethodDecl>(D)) {94    const NamedDecl *ND = cast<NamedDecl>(D);95    output << *ND;96  } else if (isa<BlockDecl>(D)) {97    output << "block(line:" << Loc.getLine() << ":col:" << Loc.getColumn();98  }99 100  NumBlocksUnreachable += unreachable;101  NumBlocks += total;102  std::string NameOfRootFunction = std::string(output.str());103 104  output << " -> Total CFGBlocks: " << total << " | Unreachable CFGBlocks: "105      << unreachable << " | Exhausted Block: "106      << (Eng.wasBlocksExhausted() ? "yes" : "no")107      << " | Empty WorkList: "108      << (Eng.hasEmptyWorkList() ? "yes" : "no");109 110  B.EmitBasicReport(D, this, "Analyzer Statistics", "Internal Statistics",111                    output.str(), PathDiagnosticLocation(D, SM));112 113  // Emit warning for each block we bailed out on.114  const CoreEngine &CE = Eng.getCoreEngine();115  for (const BlockEdge &BE : make_first_range(CE.exhausted_blocks())) {116    const CFGBlock *Exit = BE.getDst();117    if (Exit->empty())118      continue;119    const CFGElement &CE = Exit->front();120    if (std::optional<CFGStmt> CS = CE.getAs<CFGStmt>()) {121      SmallString<128> bufI;122      llvm::raw_svector_ostream outputI(bufI);123      outputI << "(" << NameOfRootFunction << ")" <<124                 ": The analyzer generated a sink at this point";125      B.EmitBasicReport(126          D, this, "Sink Point", "Internal Statistics", outputI.str(),127          PathDiagnosticLocation::createBegin(CS->getStmt(), SM, LC));128    }129  }130}131 132void ento::registerAnalyzerStatsChecker(CheckerManager &mgr) {133  mgr.registerChecker<AnalyzerStatsChecker>();134}135 136bool ento::shouldRegisterAnalyzerStatsChecker(const CheckerManager &mgr) {137  return true;138}139