brintos

brintos / llvm-project-archived public Read only

0
0
Text · 10.4 KiB · 04bbe85 Raw
349 lines · cpp
1//==- DebugCheckers.cpp - Debugging Checkers ---------------------*- 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//9//  This file defines checkers that display debugging information.10//11//===----------------------------------------------------------------------===//12 13#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"14#include "clang/Analysis/Analyses/Dominators.h"15#include "clang/Analysis/Analyses/LiveVariables.h"16#include "clang/Analysis/CallGraph.h"17#include "clang/StaticAnalyzer/Core/Checker.h"18#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"19#include "clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h"20#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"21#include "clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h"22#include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"23#include "llvm/Support/Process.h"24 25using namespace clang;26using namespace ento;27 28//===----------------------------------------------------------------------===//29// DominatorsTreeDumper30//===----------------------------------------------------------------------===//31 32namespace {33class DominatorsTreeDumper : public Checker<check::ASTCodeBody> {34public:35  void checkASTCodeBody(const Decl *D, AnalysisManager& mgr,36                        BugReporter &BR) const {37    if (AnalysisDeclContext *AC = mgr.getAnalysisDeclContext(D)) {38      CFGDomTree Dom;39      Dom.buildDominatorTree(AC->getCFG());40      Dom.dump();41    }42  }43};44}45 46void ento::registerDominatorsTreeDumper(CheckerManager &mgr) {47  mgr.registerChecker<DominatorsTreeDumper>();48}49 50bool ento::shouldRegisterDominatorsTreeDumper(const CheckerManager &mgr) {51  return true;52}53 54//===----------------------------------------------------------------------===//55// PostDominatorsTreeDumper56//===----------------------------------------------------------------------===//57 58namespace {59class PostDominatorsTreeDumper : public Checker<check::ASTCodeBody> {60public:61  void checkASTCodeBody(const Decl *D, AnalysisManager& mgr,62                        BugReporter &BR) const {63    if (AnalysisDeclContext *AC = mgr.getAnalysisDeclContext(D)) {64      CFGPostDomTree Dom;65      Dom.buildDominatorTree(AC->getCFG());66      Dom.dump();67    }68  }69};70}71 72void ento::registerPostDominatorsTreeDumper(CheckerManager &mgr) {73  mgr.registerChecker<PostDominatorsTreeDumper>();74}75 76bool ento::shouldRegisterPostDominatorsTreeDumper(const CheckerManager &mgr) {77  return true;78}79 80//===----------------------------------------------------------------------===//81// ControlDependencyTreeDumper82//===----------------------------------------------------------------------===//83 84namespace {85class ControlDependencyTreeDumper : public Checker<check::ASTCodeBody> {86public:87  void checkASTCodeBody(const Decl *D, AnalysisManager& mgr,88                        BugReporter &BR) const {89    if (AnalysisDeclContext *AC = mgr.getAnalysisDeclContext(D)) {90      ControlDependencyCalculator Dom(AC->getCFG());91      Dom.dump();92    }93  }94};95}96 97void ento::registerControlDependencyTreeDumper(CheckerManager &mgr) {98  mgr.registerChecker<ControlDependencyTreeDumper>();99}100 101bool ento::shouldRegisterControlDependencyTreeDumper(const CheckerManager &mgr) {102  return true;103}104 105//===----------------------------------------------------------------------===//106// LiveVariablesDumper107//===----------------------------------------------------------------------===//108 109namespace {110class LiveVariablesDumper : public Checker<check::ASTCodeBody> {111public:112  void checkASTCodeBody(const Decl *D, AnalysisManager& mgr,113                        BugReporter &BR) const {114    if (LiveVariables* L = mgr.getAnalysis<LiveVariables>(D)) {115      L->dumpBlockLiveness(mgr.getSourceManager());116    }117  }118};119}120 121void ento::registerLiveVariablesDumper(CheckerManager &mgr) {122  mgr.registerChecker<LiveVariablesDumper>();123}124 125bool ento::shouldRegisterLiveVariablesDumper(const CheckerManager &mgr) {126  return true;127}128 129//===----------------------------------------------------------------------===//130// LiveStatementsDumper131//===----------------------------------------------------------------------===//132 133namespace {134class LiveExpressionsDumper : public Checker<check::ASTCodeBody> {135public:136  void checkASTCodeBody(const Decl *D, AnalysisManager& Mgr,137                        BugReporter &BR) const {138    if (LiveVariables *L = Mgr.getAnalysis<RelaxedLiveVariables>(D))139      L->dumpExprLiveness(Mgr.getSourceManager());140  }141};142}143 144void ento::registerLiveExpressionsDumper(CheckerManager &mgr) {145  mgr.registerChecker<LiveExpressionsDumper>();146}147 148bool ento::shouldRegisterLiveExpressionsDumper(const CheckerManager &mgr) {149  return true;150}151 152//===----------------------------------------------------------------------===//153// CFGViewer154//===----------------------------------------------------------------------===//155 156namespace {157class CFGViewer : public Checker<check::ASTCodeBody> {158public:159  void checkASTCodeBody(const Decl *D, AnalysisManager& mgr,160                        BugReporter &BR) const {161    if (CFG *cfg = mgr.getCFG(D)) {162      cfg->viewCFG(mgr.getLangOpts());163    }164  }165};166}167 168void ento::registerCFGViewer(CheckerManager &mgr) {169  mgr.registerChecker<CFGViewer>();170}171 172bool ento::shouldRegisterCFGViewer(const CheckerManager &mgr) {173  return true;174}175 176//===----------------------------------------------------------------------===//177// CFGDumper178//===----------------------------------------------------------------------===//179 180namespace {181class CFGDumper : public Checker<check::ASTCodeBody> {182public:183  void checkASTCodeBody(const Decl *D, AnalysisManager& mgr,184                        BugReporter &BR) const {185    PrintingPolicy Policy(mgr.getLangOpts());186    Policy.TerseOutput = true;187    Policy.PolishForDeclaration = true;188    D->print(llvm::errs(), Policy);189 190    if (CFG *cfg = mgr.getCFG(D)) {191      cfg->dump(mgr.getLangOpts(),192                llvm::sys::Process::StandardErrHasColors());193    }194  }195};196}197 198void ento::registerCFGDumper(CheckerManager &mgr) {199  mgr.registerChecker<CFGDumper>();200}201 202bool ento::shouldRegisterCFGDumper(const CheckerManager &mgr) {203  return true;204}205 206//===----------------------------------------------------------------------===//207// CallGraphViewer208//===----------------------------------------------------------------------===//209 210namespace {211class CallGraphViewer : public Checker< check::ASTDecl<TranslationUnitDecl> > {212public:213  void checkASTDecl(const TranslationUnitDecl *TU, AnalysisManager& mgr,214                    BugReporter &BR) const {215    CallGraph CG;216    CG.addToCallGraph(const_cast<TranslationUnitDecl*>(TU));217    CG.viewGraph();218  }219};220}221 222void ento::registerCallGraphViewer(CheckerManager &mgr) {223  mgr.registerChecker<CallGraphViewer>();224}225 226bool ento::shouldRegisterCallGraphViewer(const CheckerManager &mgr) {227  return true;228}229 230//===----------------------------------------------------------------------===//231// CallGraphDumper232//===----------------------------------------------------------------------===//233 234namespace {235class CallGraphDumper : public Checker< check::ASTDecl<TranslationUnitDecl> > {236public:237  void checkASTDecl(const TranslationUnitDecl *TU, AnalysisManager& mgr,238                    BugReporter &BR) const {239    CallGraph CG;240    CG.addToCallGraph(const_cast<TranslationUnitDecl*>(TU));241    CG.dump();242  }243};244}245 246void ento::registerCallGraphDumper(CheckerManager &mgr) {247  mgr.registerChecker<CallGraphDumper>();248}249 250bool ento::shouldRegisterCallGraphDumper(const CheckerManager &mgr) {251  return true;252}253 254//===----------------------------------------------------------------------===//255// ConfigDumper256//===----------------------------------------------------------------------===//257 258namespace {259class ConfigDumper : public Checker< check::EndOfTranslationUnit > {260  typedef AnalyzerOptions::ConfigTable Table;261 262  static int compareEntry(const Table::MapEntryTy *const *LHS,263                          const Table::MapEntryTy *const *RHS) {264    return (*LHS)->getKey().compare((*RHS)->getKey());265  }266 267public:268  void checkEndOfTranslationUnit(const TranslationUnitDecl *TU,269                                 AnalysisManager& mgr,270                                 BugReporter &BR) const {271    const Table &Config = mgr.options.Config;272 273    SmallVector<const Table::MapEntryTy *, 32> Keys;274    for (const auto &Entry : Config)275      Keys.push_back(&Entry);276    llvm::array_pod_sort(Keys.begin(), Keys.end(), compareEntry);277 278    llvm::errs() << "[config]\n";279    for (unsigned I = 0, E = Keys.size(); I != E; ++I)280      llvm::errs() << Keys[I]->getKey() << " = "281                   << (Keys[I]->second.empty() ? "\"\"" : Keys[I]->second)282                   << '\n';283  }284};285}286 287void ento::registerConfigDumper(CheckerManager &mgr) {288  mgr.registerChecker<ConfigDumper>();289}290 291bool ento::shouldRegisterConfigDumper(const CheckerManager &mgr) {292  return true;293}294 295//===----------------------------------------------------------------------===//296// ExplodedGraph Viewer297//===----------------------------------------------------------------------===//298 299namespace {300class ExplodedGraphViewer : public Checker< check::EndAnalysis > {301public:302  ExplodedGraphViewer() {}303  void checkEndAnalysis(ExplodedGraph &G, BugReporter &B,ExprEngine &Eng) const {304    Eng.ViewGraph(false);305  }306};307 308}309 310void ento::registerExplodedGraphViewer(CheckerManager &mgr) {311  mgr.registerChecker<ExplodedGraphViewer>();312}313 314bool ento::shouldRegisterExplodedGraphViewer(const CheckerManager &mgr) {315  return true;316}317 318//===----------------------------------------------------------------------===//319// Emits a report for every Stmt that the analyzer visits.320//===----------------------------------------------------------------------===//321 322namespace {323 324class ReportStmts : public Checker<check::PreStmt<Stmt>> {325  BugType BT_stmtLoc{this, "Statement"};326 327public:328  void checkPreStmt(const Stmt *S, CheckerContext &C) const {329    ExplodedNode *Node = C.generateNonFatalErrorNode();330    if (!Node)331      return;332 333    auto Report =334        std::make_unique<PathSensitiveBugReport>(BT_stmtLoc, "Statement", Node);335 336    C.emitReport(std::move(Report));337  }338};339 340} // end of anonymous namespace341 342void ento::registerReportStmts(CheckerManager &mgr) {343  mgr.registerChecker<ReportStmts>();344}345 346bool ento::shouldRegisterReportStmts(const CheckerManager &mgr) {347  return true;348}349