1 //===- AnalysisOrderChecker - Print callbacks called ------------*- C++ -*-===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 // 10 // This checker prints callbacks that are called during analysis. 11 // This is required to ensure that callbacks are fired in order 12 // and do not duplicate or get lost. 13 // Feel free to extend this checker with any callback you need to check. 14 // 15 //===----------------------------------------------------------------------===// 16 17 #include "ClangSACheckers.h" 18 #include "clang/StaticAnalyzer/Core/Checker.h" 19 #include "clang/StaticAnalyzer/Core/CheckerManager.h" 20 #include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" 21 22 using namespace clang; 23 using namespace ento; 24 25 namespace { 26 27 class AnalysisOrderChecker 28 : public Checker<check::PreStmt<CastExpr>, 29 check::PostStmt<CastExpr>, 30 check::PreStmt<ArraySubscriptExpr>, 31 check::PostStmt<ArraySubscriptExpr>, 32 check::Bind, 33 check::RegionChanges> { 34 bool isCallbackEnabled(AnalyzerOptions &Opts, StringRef CallbackName) const { 35 return Opts.getBooleanOption("*", false, this) || 36 Opts.getBooleanOption(CallbackName, false, this); 37 } 38 39 bool isCallbackEnabled(CheckerContext &C, StringRef CallbackName) const { 40 AnalyzerOptions &Opts = C.getAnalysisManager().getAnalyzerOptions(); 41 return isCallbackEnabled(Opts, CallbackName); 42 } 43 44 bool isCallbackEnabled(ProgramStateRef State, StringRef CallbackName) const { 45 AnalyzerOptions &Opts = State->getStateManager().getOwningEngine() 46 ->getAnalysisManager().getAnalyzerOptions(); 47 return isCallbackEnabled(Opts, CallbackName); 48 } 49 50 public: 51 void checkPreStmt(const CastExpr *CE, CheckerContext &C) const { 52 if (isCallbackEnabled(C, "PreStmtCastExpr")) 53 llvm::errs() << "PreStmt<CastExpr> (Kind : " << CE->getCastKindName() 54 << ")\n"; 55 } 56 57 void checkPostStmt(const CastExpr *CE, CheckerContext &C) const { 58 if (isCallbackEnabled(C, "PostStmtCastExpr")) 59 llvm::errs() << "PostStmt<CastExpr> (Kind : " << CE->getCastKindName() 60 << ")\n"; 61 } 62 63 void checkPreStmt(const ArraySubscriptExpr *SubExpr, 64 CheckerContext &C) const { 65 if (isCallbackEnabled(C, "PreStmtArraySubscriptExpr")) 66 llvm::errs() << "PreStmt<ArraySubscriptExpr>\n"; 67 } 68 69 void checkPostStmt(const ArraySubscriptExpr *SubExpr, 70 CheckerContext &C) const { 71 if (isCallbackEnabled(C, "PostStmtArraySubscriptExpr")) 72 llvm::errs() << "PostStmt<ArraySubscriptExpr>\n"; 73 } 74 75 void checkBind(SVal Loc, SVal Val, const Stmt *S, CheckerContext &C) const { 76 if (isCallbackEnabled(C, "Bind")) 77 llvm::errs() << "Bind\n"; 78 } 79 80 ProgramStateRef 81 checkRegionChanges(ProgramStateRef State, 82 const InvalidatedSymbols *Invalidated, 83 ArrayRef<const MemRegion *> ExplicitRegions, 84 ArrayRef<const MemRegion *> Regions, 85 const LocationContext *LCtx, const CallEvent *Call) const { 86 if (isCallbackEnabled(State, "RegionChanges")) 87 llvm::errs() << "RegionChanges\n"; 88 return State; 89 } 90 }; 91 } // end anonymous namespace 92 93 //===----------------------------------------------------------------------===// 94 // Registration. 95 //===----------------------------------------------------------------------===// 96 97 void ento::registerAnalysisOrderChecker(CheckerManager &mgr) { 98 mgr.registerChecker<AnalysisOrderChecker>(); 99 } 100