AnalysisOrderChecker.cpp revision 353358
1311118Sdim//===- AnalysisOrderChecker - Print callbacks called ------------*- C++ -*-===// 2311118Sdim// 3353358Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4353358Sdim// See https://llvm.org/LICENSE.txt for license information. 5353358Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6311118Sdim// 7311118Sdim//===----------------------------------------------------------------------===// 8311118Sdim// 9311118Sdim// This checker prints callbacks that are called during analysis. 10311118Sdim// This is required to ensure that callbacks are fired in order 11311118Sdim// and do not duplicate or get lost. 12311118Sdim// Feel free to extend this checker with any callback you need to check. 13311118Sdim// 14311118Sdim//===----------------------------------------------------------------------===// 15311118Sdim 16344779Sdim#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h" 17341825Sdim#include "clang/AST/ExprCXX.h" 18344779Sdim#include "clang/Analysis/CFGStmtMap.h" 19311118Sdim#include "clang/StaticAnalyzer/Core/Checker.h" 20311118Sdim#include "clang/StaticAnalyzer/Core/CheckerManager.h" 21341825Sdim#include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h" 22311118Sdim#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" 23311118Sdim 24311118Sdimusing namespace clang; 25311118Sdimusing namespace ento; 26311118Sdim 27311118Sdimnamespace { 28311118Sdim 29321369Sdimclass AnalysisOrderChecker 30321369Sdim : public Checker<check::PreStmt<CastExpr>, 31321369Sdim check::PostStmt<CastExpr>, 32321369Sdim check::PreStmt<ArraySubscriptExpr>, 33321369Sdim check::PostStmt<ArraySubscriptExpr>, 34341825Sdim check::PreStmt<CXXNewExpr>, 35341825Sdim check::PostStmt<CXXNewExpr>, 36341825Sdim check::PreStmt<OffsetOfExpr>, 37341825Sdim check::PostStmt<OffsetOfExpr>, 38341825Sdim check::PreCall, 39341825Sdim check::PostCall, 40344779Sdim check::EndFunction, 41341825Sdim check::NewAllocator, 42321369Sdim check::Bind, 43341825Sdim check::RegionChanges, 44341825Sdim check::LiveSymbols> { 45341825Sdim 46321369Sdim bool isCallbackEnabled(AnalyzerOptions &Opts, StringRef CallbackName) const { 47353358Sdim return Opts.getCheckerBooleanOption(this, "*") || 48353358Sdim Opts.getCheckerBooleanOption(this, CallbackName); 49311118Sdim } 50311118Sdim 51321369Sdim bool isCallbackEnabled(CheckerContext &C, StringRef CallbackName) const { 52321369Sdim AnalyzerOptions &Opts = C.getAnalysisManager().getAnalyzerOptions(); 53321369Sdim return isCallbackEnabled(Opts, CallbackName); 54321369Sdim } 55321369Sdim 56321369Sdim bool isCallbackEnabled(ProgramStateRef State, StringRef CallbackName) const { 57321369Sdim AnalyzerOptions &Opts = State->getStateManager().getOwningEngine() 58344779Sdim .getAnalysisManager().getAnalyzerOptions(); 59321369Sdim return isCallbackEnabled(Opts, CallbackName); 60321369Sdim } 61321369Sdim 62311118Sdimpublic: 63311118Sdim void checkPreStmt(const CastExpr *CE, CheckerContext &C) const { 64311118Sdim if (isCallbackEnabled(C, "PreStmtCastExpr")) 65311118Sdim llvm::errs() << "PreStmt<CastExpr> (Kind : " << CE->getCastKindName() 66311118Sdim << ")\n"; 67311118Sdim } 68311118Sdim 69311118Sdim void checkPostStmt(const CastExpr *CE, CheckerContext &C) const { 70311118Sdim if (isCallbackEnabled(C, "PostStmtCastExpr")) 71311118Sdim llvm::errs() << "PostStmt<CastExpr> (Kind : " << CE->getCastKindName() 72311118Sdim << ")\n"; 73311118Sdim } 74311118Sdim 75321369Sdim void checkPreStmt(const ArraySubscriptExpr *SubExpr, 76321369Sdim CheckerContext &C) const { 77311118Sdim if (isCallbackEnabled(C, "PreStmtArraySubscriptExpr")) 78311118Sdim llvm::errs() << "PreStmt<ArraySubscriptExpr>\n"; 79311118Sdim } 80311118Sdim 81321369Sdim void checkPostStmt(const ArraySubscriptExpr *SubExpr, 82321369Sdim CheckerContext &C) const { 83311118Sdim if (isCallbackEnabled(C, "PostStmtArraySubscriptExpr")) 84311118Sdim llvm::errs() << "PostStmt<ArraySubscriptExpr>\n"; 85311118Sdim } 86321369Sdim 87341825Sdim void checkPreStmt(const CXXNewExpr *NE, CheckerContext &C) const { 88341825Sdim if (isCallbackEnabled(C, "PreStmtCXXNewExpr")) 89341825Sdim llvm::errs() << "PreStmt<CXXNewExpr>\n"; 90341825Sdim } 91341825Sdim 92341825Sdim void checkPostStmt(const CXXNewExpr *NE, CheckerContext &C) const { 93341825Sdim if (isCallbackEnabled(C, "PostStmtCXXNewExpr")) 94341825Sdim llvm::errs() << "PostStmt<CXXNewExpr>\n"; 95341825Sdim } 96341825Sdim 97341825Sdim void checkPreStmt(const OffsetOfExpr *OOE, CheckerContext &C) const { 98341825Sdim if (isCallbackEnabled(C, "PreStmtOffsetOfExpr")) 99341825Sdim llvm::errs() << "PreStmt<OffsetOfExpr>\n"; 100341825Sdim } 101341825Sdim 102341825Sdim void checkPostStmt(const OffsetOfExpr *OOE, CheckerContext &C) const { 103341825Sdim if (isCallbackEnabled(C, "PostStmtOffsetOfExpr")) 104341825Sdim llvm::errs() << "PostStmt<OffsetOfExpr>\n"; 105341825Sdim } 106341825Sdim 107341825Sdim void checkPreCall(const CallEvent &Call, CheckerContext &C) const { 108341825Sdim if (isCallbackEnabled(C, "PreCall")) { 109341825Sdim llvm::errs() << "PreCall"; 110341825Sdim if (const NamedDecl *ND = dyn_cast_or_null<NamedDecl>(Call.getDecl())) 111341825Sdim llvm::errs() << " (" << ND->getQualifiedNameAsString() << ')'; 112341825Sdim llvm::errs() << '\n'; 113341825Sdim } 114341825Sdim } 115341825Sdim 116341825Sdim void checkPostCall(const CallEvent &Call, CheckerContext &C) const { 117341825Sdim if (isCallbackEnabled(C, "PostCall")) { 118341825Sdim llvm::errs() << "PostCall"; 119341825Sdim if (const NamedDecl *ND = dyn_cast_or_null<NamedDecl>(Call.getDecl())) 120341825Sdim llvm::errs() << " (" << ND->getQualifiedNameAsString() << ')'; 121341825Sdim llvm::errs() << '\n'; 122341825Sdim } 123341825Sdim } 124341825Sdim 125344779Sdim void checkEndFunction(const ReturnStmt *S, CheckerContext &C) const { 126344779Sdim if (isCallbackEnabled(C, "EndFunction")) { 127344779Sdim llvm::errs() << "EndFunction\nReturnStmt: " << (S ? "yes" : "no") << "\n"; 128344779Sdim if (!S) 129344779Sdim return; 130344779Sdim 131344779Sdim llvm::errs() << "CFGElement: "; 132344779Sdim CFGStmtMap *Map = C.getCurrentAnalysisDeclContext()->getCFGStmtMap(); 133344779Sdim CFGElement LastElement = Map->getBlock(S)->back(); 134344779Sdim 135344779Sdim if (LastElement.getAs<CFGStmt>()) 136344779Sdim llvm::errs() << "CFGStmt\n"; 137344779Sdim else if (LastElement.getAs<CFGAutomaticObjDtor>()) 138344779Sdim llvm::errs() << "CFGAutomaticObjDtor\n"; 139344779Sdim } 140344779Sdim } 141344779Sdim 142341825Sdim void checkNewAllocator(const CXXNewExpr *CNE, SVal Target, 143341825Sdim CheckerContext &C) const { 144341825Sdim if (isCallbackEnabled(C, "NewAllocator")) 145341825Sdim llvm::errs() << "NewAllocator\n"; 146341825Sdim } 147341825Sdim 148321369Sdim void checkBind(SVal Loc, SVal Val, const Stmt *S, CheckerContext &C) const { 149321369Sdim if (isCallbackEnabled(C, "Bind")) 150321369Sdim llvm::errs() << "Bind\n"; 151321369Sdim } 152321369Sdim 153341825Sdim void checkLiveSymbols(ProgramStateRef State, SymbolReaper &SymReaper) const { 154341825Sdim if (isCallbackEnabled(State, "LiveSymbols")) 155341825Sdim llvm::errs() << "LiveSymbols\n"; 156341825Sdim } 157341825Sdim 158321369Sdim ProgramStateRef 159321369Sdim checkRegionChanges(ProgramStateRef State, 160321369Sdim const InvalidatedSymbols *Invalidated, 161321369Sdim ArrayRef<const MemRegion *> ExplicitRegions, 162321369Sdim ArrayRef<const MemRegion *> Regions, 163321369Sdim const LocationContext *LCtx, const CallEvent *Call) const { 164321369Sdim if (isCallbackEnabled(State, "RegionChanges")) 165321369Sdim llvm::errs() << "RegionChanges\n"; 166321369Sdim return State; 167321369Sdim } 168311118Sdim}; 169321369Sdim} // end anonymous namespace 170311118Sdim 171311118Sdim//===----------------------------------------------------------------------===// 172311118Sdim// Registration. 173311118Sdim//===----------------------------------------------------------------------===// 174311118Sdim 175311118Sdimvoid ento::registerAnalysisOrderChecker(CheckerManager &mgr) { 176311118Sdim mgr.registerChecker<AnalysisOrderChecker>(); 177311118Sdim} 178353358Sdim 179353358Sdimbool ento::shouldRegisterAnalysisOrderChecker(const LangOptions &LO) { 180353358Sdim return true; 181353358Sdim} 182