Path: blob/main/contrib/llvm-project/clang/lib/StaticAnalyzer/Checkers/DebugCheckers.cpp
35266 views
//==- DebugCheckers.cpp - Debugging Checkers ---------------------*- C++ -*-==//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7//8// This file defines checkers that display debugging information.9//10//===----------------------------------------------------------------------===//1112#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"13#include "clang/Analysis/Analyses/Dominators.h"14#include "clang/Analysis/Analyses/LiveVariables.h"15#include "clang/Analysis/CallGraph.h"16#include "clang/StaticAnalyzer/Core/Checker.h"17#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"18#include "clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h"19#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"20#include "clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h"21#include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"22#include "llvm/Support/Process.h"2324using namespace clang;25using namespace ento;2627//===----------------------------------------------------------------------===//28// DominatorsTreeDumper29//===----------------------------------------------------------------------===//3031namespace {32class DominatorsTreeDumper : public Checker<check::ASTCodeBody> {33public:34void checkASTCodeBody(const Decl *D, AnalysisManager& mgr,35BugReporter &BR) const {36if (AnalysisDeclContext *AC = mgr.getAnalysisDeclContext(D)) {37CFGDomTree Dom;38Dom.buildDominatorTree(AC->getCFG());39Dom.dump();40}41}42};43}4445void ento::registerDominatorsTreeDumper(CheckerManager &mgr) {46mgr.registerChecker<DominatorsTreeDumper>();47}4849bool ento::shouldRegisterDominatorsTreeDumper(const CheckerManager &mgr) {50return true;51}5253//===----------------------------------------------------------------------===//54// PostDominatorsTreeDumper55//===----------------------------------------------------------------------===//5657namespace {58class PostDominatorsTreeDumper : public Checker<check::ASTCodeBody> {59public:60void checkASTCodeBody(const Decl *D, AnalysisManager& mgr,61BugReporter &BR) const {62if (AnalysisDeclContext *AC = mgr.getAnalysisDeclContext(D)) {63CFGPostDomTree Dom;64Dom.buildDominatorTree(AC->getCFG());65Dom.dump();66}67}68};69}7071void ento::registerPostDominatorsTreeDumper(CheckerManager &mgr) {72mgr.registerChecker<PostDominatorsTreeDumper>();73}7475bool ento::shouldRegisterPostDominatorsTreeDumper(const CheckerManager &mgr) {76return true;77}7879//===----------------------------------------------------------------------===//80// ControlDependencyTreeDumper81//===----------------------------------------------------------------------===//8283namespace {84class ControlDependencyTreeDumper : public Checker<check::ASTCodeBody> {85public:86void checkASTCodeBody(const Decl *D, AnalysisManager& mgr,87BugReporter &BR) const {88if (AnalysisDeclContext *AC = mgr.getAnalysisDeclContext(D)) {89ControlDependencyCalculator Dom(AC->getCFG());90Dom.dump();91}92}93};94}9596void ento::registerControlDependencyTreeDumper(CheckerManager &mgr) {97mgr.registerChecker<ControlDependencyTreeDumper>();98}99100bool ento::shouldRegisterControlDependencyTreeDumper(const CheckerManager &mgr) {101return true;102}103104//===----------------------------------------------------------------------===//105// LiveVariablesDumper106//===----------------------------------------------------------------------===//107108namespace {109class LiveVariablesDumper : public Checker<check::ASTCodeBody> {110public:111void checkASTCodeBody(const Decl *D, AnalysisManager& mgr,112BugReporter &BR) const {113if (LiveVariables* L = mgr.getAnalysis<LiveVariables>(D)) {114L->dumpBlockLiveness(mgr.getSourceManager());115}116}117};118}119120void ento::registerLiveVariablesDumper(CheckerManager &mgr) {121mgr.registerChecker<LiveVariablesDumper>();122}123124bool ento::shouldRegisterLiveVariablesDumper(const CheckerManager &mgr) {125return true;126}127128//===----------------------------------------------------------------------===//129// LiveStatementsDumper130//===----------------------------------------------------------------------===//131132namespace {133class LiveExpressionsDumper : public Checker<check::ASTCodeBody> {134public:135void checkASTCodeBody(const Decl *D, AnalysisManager& Mgr,136BugReporter &BR) const {137if (LiveVariables *L = Mgr.getAnalysis<RelaxedLiveVariables>(D))138L->dumpExprLiveness(Mgr.getSourceManager());139}140};141}142143void ento::registerLiveExpressionsDumper(CheckerManager &mgr) {144mgr.registerChecker<LiveExpressionsDumper>();145}146147bool ento::shouldRegisterLiveExpressionsDumper(const CheckerManager &mgr) {148return true;149}150151//===----------------------------------------------------------------------===//152// CFGViewer153//===----------------------------------------------------------------------===//154155namespace {156class CFGViewer : public Checker<check::ASTCodeBody> {157public:158void checkASTCodeBody(const Decl *D, AnalysisManager& mgr,159BugReporter &BR) const {160if (CFG *cfg = mgr.getCFG(D)) {161cfg->viewCFG(mgr.getLangOpts());162}163}164};165}166167void ento::registerCFGViewer(CheckerManager &mgr) {168mgr.registerChecker<CFGViewer>();169}170171bool ento::shouldRegisterCFGViewer(const CheckerManager &mgr) {172return true;173}174175//===----------------------------------------------------------------------===//176// CFGDumper177//===----------------------------------------------------------------------===//178179namespace {180class CFGDumper : public Checker<check::ASTCodeBody> {181public:182void checkASTCodeBody(const Decl *D, AnalysisManager& mgr,183BugReporter &BR) const {184PrintingPolicy Policy(mgr.getLangOpts());185Policy.TerseOutput = true;186Policy.PolishForDeclaration = true;187D->print(llvm::errs(), Policy);188189if (CFG *cfg = mgr.getCFG(D)) {190cfg->dump(mgr.getLangOpts(),191llvm::sys::Process::StandardErrHasColors());192}193}194};195}196197void ento::registerCFGDumper(CheckerManager &mgr) {198mgr.registerChecker<CFGDumper>();199}200201bool ento::shouldRegisterCFGDumper(const CheckerManager &mgr) {202return true;203}204205//===----------------------------------------------------------------------===//206// CallGraphViewer207//===----------------------------------------------------------------------===//208209namespace {210class CallGraphViewer : public Checker< check::ASTDecl<TranslationUnitDecl> > {211public:212void checkASTDecl(const TranslationUnitDecl *TU, AnalysisManager& mgr,213BugReporter &BR) const {214CallGraph CG;215CG.addToCallGraph(const_cast<TranslationUnitDecl*>(TU));216CG.viewGraph();217}218};219}220221void ento::registerCallGraphViewer(CheckerManager &mgr) {222mgr.registerChecker<CallGraphViewer>();223}224225bool ento::shouldRegisterCallGraphViewer(const CheckerManager &mgr) {226return true;227}228229//===----------------------------------------------------------------------===//230// CallGraphDumper231//===----------------------------------------------------------------------===//232233namespace {234class CallGraphDumper : public Checker< check::ASTDecl<TranslationUnitDecl> > {235public:236void checkASTDecl(const TranslationUnitDecl *TU, AnalysisManager& mgr,237BugReporter &BR) const {238CallGraph CG;239CG.addToCallGraph(const_cast<TranslationUnitDecl*>(TU));240CG.dump();241}242};243}244245void ento::registerCallGraphDumper(CheckerManager &mgr) {246mgr.registerChecker<CallGraphDumper>();247}248249bool ento::shouldRegisterCallGraphDumper(const CheckerManager &mgr) {250return true;251}252253//===----------------------------------------------------------------------===//254// ConfigDumper255//===----------------------------------------------------------------------===//256257namespace {258class ConfigDumper : public Checker< check::EndOfTranslationUnit > {259typedef AnalyzerOptions::ConfigTable Table;260261static int compareEntry(const Table::MapEntryTy *const *LHS,262const Table::MapEntryTy *const *RHS) {263return (*LHS)->getKey().compare((*RHS)->getKey());264}265266public:267void checkEndOfTranslationUnit(const TranslationUnitDecl *TU,268AnalysisManager& mgr,269BugReporter &BR) const {270const Table &Config = mgr.options.Config;271272SmallVector<const Table::MapEntryTy *, 32> Keys;273for (const auto &Entry : Config)274Keys.push_back(&Entry);275llvm::array_pod_sort(Keys.begin(), Keys.end(), compareEntry);276277llvm::errs() << "[config]\n";278for (unsigned I = 0, E = Keys.size(); I != E; ++I)279llvm::errs() << Keys[I]->getKey() << " = "280<< (Keys[I]->second.empty() ? "\"\"" : Keys[I]->second)281<< '\n';282}283};284}285286void ento::registerConfigDumper(CheckerManager &mgr) {287mgr.registerChecker<ConfigDumper>();288}289290bool ento::shouldRegisterConfigDumper(const CheckerManager &mgr) {291return true;292}293294//===----------------------------------------------------------------------===//295// ExplodedGraph Viewer296//===----------------------------------------------------------------------===//297298namespace {299class ExplodedGraphViewer : public Checker< check::EndAnalysis > {300public:301ExplodedGraphViewer() {}302void checkEndAnalysis(ExplodedGraph &G, BugReporter &B,ExprEngine &Eng) const {303Eng.ViewGraph(false);304}305};306307}308309void ento::registerExplodedGraphViewer(CheckerManager &mgr) {310mgr.registerChecker<ExplodedGraphViewer>();311}312313bool ento::shouldRegisterExplodedGraphViewer(const CheckerManager &mgr) {314return true;315}316317//===----------------------------------------------------------------------===//318// Emits a report for every Stmt that the analyzer visits.319//===----------------------------------------------------------------------===//320321namespace {322323class ReportStmts : public Checker<check::PreStmt<Stmt>> {324BugType BT_stmtLoc{this, "Statement"};325326public:327void checkPreStmt(const Stmt *S, CheckerContext &C) const {328ExplodedNode *Node = C.generateNonFatalErrorNode();329if (!Node)330return;331332auto Report =333std::make_unique<PathSensitiveBugReport>(BT_stmtLoc, "Statement", Node);334335C.emitReport(std::move(Report));336}337};338339} // end of anonymous namespace340341void ento::registerReportStmts(CheckerManager &mgr) {342mgr.registerChecker<ReportStmts>();343}344345bool ento::shouldRegisterReportStmts(const CheckerManager &mgr) {346return true;347}348349350