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/AST/ExprCXX.h" 19 #include "clang/StaticAnalyzer/Core/Checker.h" 20 #include "clang/StaticAnalyzer/Core/CheckerManager.h" 21 #include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h" 22 #include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" 23 24 using namespace clang; 25 using namespace ento; 26 27 namespace { 28 29 class AnalysisOrderChecker 30 : public Checker<check::PreStmt<CastExpr>, 31 check::PostStmt<CastExpr>, 32 check::PreStmt<ArraySubscriptExpr>, 33 check::PostStmt<ArraySubscriptExpr>, 34 check::PreStmt<CXXNewExpr>, 35 check::PostStmt<CXXNewExpr>, 36 check::PreCall, 37 check::PostCall, 38 check::NewAllocator, 39 check::Bind, 40 check::RegionChanges, 41 check::LiveSymbols> { 42 43 bool isCallbackEnabled(AnalyzerOptions &Opts, StringRef CallbackName) const { 44 return Opts.getBooleanOption("*", false, this) || 45 Opts.getBooleanOption(CallbackName, false, this); 46 } 47 48 bool isCallbackEnabled(CheckerContext &C, StringRef CallbackName) const { 49 AnalyzerOptions &Opts = C.getAnalysisManager().getAnalyzerOptions(); 50 return isCallbackEnabled(Opts, CallbackName); 51 } 52 53 bool isCallbackEnabled(ProgramStateRef State, StringRef CallbackName) const { 54 AnalyzerOptions &Opts = State->getStateManager().getOwningEngine() 55 ->getAnalysisManager().getAnalyzerOptions(); 56 return isCallbackEnabled(Opts, CallbackName); 57 } 58 59 public: 60 void checkPreStmt(const CastExpr *CE, CheckerContext &C) const { 61 if (isCallbackEnabled(C, "PreStmtCastExpr")) 62 llvm::errs() << "PreStmt<CastExpr> (Kind : " << CE->getCastKindName() 63 << ")\n"; 64 } 65 66 void checkPostStmt(const CastExpr *CE, CheckerContext &C) const { 67 if (isCallbackEnabled(C, "PostStmtCastExpr")) 68 llvm::errs() << "PostStmt<CastExpr> (Kind : " << CE->getCastKindName() 69 << ")\n"; 70 } 71 72 void checkPreStmt(const ArraySubscriptExpr *SubExpr, 73 CheckerContext &C) const { 74 if (isCallbackEnabled(C, "PreStmtArraySubscriptExpr")) 75 llvm::errs() << "PreStmt<ArraySubscriptExpr>\n"; 76 } 77 78 void checkPostStmt(const ArraySubscriptExpr *SubExpr, 79 CheckerContext &C) const { 80 if (isCallbackEnabled(C, "PostStmtArraySubscriptExpr")) 81 llvm::errs() << "PostStmt<ArraySubscriptExpr>\n"; 82 } 83 84 void checkPreStmt(const CXXNewExpr *NE, CheckerContext &C) const { 85 if (isCallbackEnabled(C, "PreStmtCXXNewExpr")) 86 llvm::errs() << "PreStmt<CXXNewExpr>\n"; 87 } 88 89 void checkPostStmt(const CXXNewExpr *NE, CheckerContext &C) const { 90 if (isCallbackEnabled(C, "PostStmtCXXNewExpr")) 91 llvm::errs() << "PostStmt<CXXNewExpr>\n"; 92 } 93 94 void checkPreCall(const CallEvent &Call, CheckerContext &C) const { 95 if (isCallbackEnabled(C, "PreCall")) { 96 llvm::errs() << "PreCall"; 97 if (const NamedDecl *ND = dyn_cast_or_null<NamedDecl>(Call.getDecl())) 98 llvm::errs() << " (" << ND->getQualifiedNameAsString() << ')'; 99 llvm::errs() << '\n'; 100 } 101 } 102 103 void checkPostCall(const CallEvent &Call, CheckerContext &C) const { 104 if (isCallbackEnabled(C, "PostCall")) { 105 llvm::errs() << "PostCall"; 106 if (const NamedDecl *ND = dyn_cast_or_null<NamedDecl>(Call.getDecl())) 107 llvm::errs() << " (" << ND->getQualifiedNameAsString() << ')'; 108 llvm::errs() << '\n'; 109 } 110 } 111 112 void checkNewAllocator(const CXXNewExpr *CNE, SVal Target, 113 CheckerContext &C) const { 114 if (isCallbackEnabled(C, "NewAllocator")) 115 llvm::errs() << "NewAllocator\n"; 116 } 117 118 void checkBind(SVal Loc, SVal Val, const Stmt *S, CheckerContext &C) const { 119 if (isCallbackEnabled(C, "Bind")) 120 llvm::errs() << "Bind\n"; 121 } 122 123 void checkLiveSymbols(ProgramStateRef State, SymbolReaper &SymReaper) const { 124 if (isCallbackEnabled(State, "LiveSymbols")) 125 llvm::errs() << "LiveSymbols\n"; 126 } 127 128 ProgramStateRef 129 checkRegionChanges(ProgramStateRef State, 130 const InvalidatedSymbols *Invalidated, 131 ArrayRef<const MemRegion *> ExplicitRegions, 132 ArrayRef<const MemRegion *> Regions, 133 const LocationContext *LCtx, const CallEvent *Call) const { 134 if (isCallbackEnabled(State, "RegionChanges")) 135 llvm::errs() << "RegionChanges\n"; 136 return State; 137 } 138 }; 139 } // end anonymous namespace 140 141 //===----------------------------------------------------------------------===// 142 // Registration. 143 //===----------------------------------------------------------------------===// 144 145 void ento::registerAnalysisOrderChecker(CheckerManager &mgr) { 146 mgr.registerChecker<AnalysisOrderChecker>(); 147 } 148