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