108 lines · cpp
1//== TraversalChecker.cpp -------------------------------------- -*- 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// These checkers print various aspects of the ExprEngine's traversal of the CFG10// as it builds the ExplodedGraph.11//12//===----------------------------------------------------------------------===//13#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"14#include "clang/AST/ParentMap.h"15#include "clang/AST/StmtObjC.h"16#include "clang/StaticAnalyzer/Core/Checker.h"17#include "clang/StaticAnalyzer/Core/CheckerManager.h"18#include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"19#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"20#include "llvm/Support/raw_ostream.h"21 22using namespace clang;23using namespace ento;24 25namespace {26// TODO: This checker is only referenced from two small test files and it27// doesn't seem to be useful for manual debugging, so consider reimplementing28// those tests with more modern tools and removing this checker.29class TraversalDumper30 : public Checker<check::BeginFunction, check::EndFunction> {31public:32 void checkBeginFunction(CheckerContext &C) const;33 void checkEndFunction(const ReturnStmt *RS, CheckerContext &C) const;34};35}36 37void TraversalDumper::checkBeginFunction(CheckerContext &C) const {38 llvm::outs() << "--BEGIN FUNCTION--\n";39}40 41void TraversalDumper::checkEndFunction(const ReturnStmt *RS,42 CheckerContext &C) const {43 llvm::outs() << "--END FUNCTION--\n";44}45 46void ento::registerTraversalDumper(CheckerManager &mgr) {47 mgr.registerChecker<TraversalDumper>();48}49 50bool ento::shouldRegisterTraversalDumper(const CheckerManager &mgr) {51 return true;52}53 54//------------------------------------------------------------------------------55 56namespace {57// TODO: This checker appears to be a utility for creating `FileCheck` tests58// verifying its stdout output, but there are no tests that rely on it, so59// perhaps it should be removed.60class CallDumper : public Checker< check::PreCall,61 check::PostCall > {62public:63 void checkPreCall(const CallEvent &Call, CheckerContext &C) const;64 void checkPostCall(const CallEvent &Call, CheckerContext &C) const;65};66}67 68void CallDumper::checkPreCall(const CallEvent &Call, CheckerContext &C) const {69 unsigned Indentation = 0;70 for (const LocationContext *LC = C.getLocationContext()->getParent();71 LC != nullptr; LC = LC->getParent())72 ++Indentation;73 74 // It is mildly evil to print directly to llvm::outs() rather than emitting75 // warnings, but this ensures things do not get filtered out by the rest of76 // the static analyzer machinery.77 llvm::outs().indent(Indentation);78 Call.dump(llvm::outs());79}80 81void CallDumper::checkPostCall(const CallEvent &Call, CheckerContext &C) const {82 const Expr *CallE = Call.getOriginExpr();83 if (!CallE)84 return;85 86 unsigned Indentation = 0;87 for (const LocationContext *LC = C.getLocationContext()->getParent();88 LC != nullptr; LC = LC->getParent())89 ++Indentation;90 91 // It is mildly evil to print directly to llvm::outs() rather than emitting92 // warnings, but this ensures things do not get filtered out by the rest of93 // the static analyzer machinery.94 llvm::outs().indent(Indentation);95 if (Call.getResultType()->isVoidType())96 llvm::outs() << "Returning void\n";97 else98 llvm::outs() << "Returning " << C.getSVal(CallE) << "\n";99}100 101void ento::registerCallDumper(CheckerManager &mgr) {102 mgr.registerChecker<CallDumper>();103}104 105bool ento::shouldRegisterCallDumper(const CheckerManager &mgr) {106 return true;107}108