CheckerManager.h revision 769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5
1//===--- CheckerManager.h - Static Analyzer Checker Manager -----*- 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// Defines the Static Analyzer Checker Manager. 11// 12//===----------------------------------------------------------------------===// 13 14#ifndef LLVM_CLANG_SA_CORE_CHECKERMANAGER_H 15#define LLVM_CLANG_SA_CORE_CHECKERMANAGER_H 16 17#include "llvm/ADT/SmallVector.h" 18#include "llvm/ADT/DenseMap.h" 19#include "llvm/ADT/FoldingSet.h" 20#include <vector> 21 22namespace clang { 23 class Decl; 24 class Stmt; 25 26namespace ento { 27 class ExprEngine; 28 class AnalysisManager; 29 class BugReporter; 30 class CheckerContext; 31 class ObjCMessage; 32 class SVal; 33 class ExplodedNodeSet; 34 class GRState; 35 36struct VoidCheckerFnParm {}; 37template <typename P1=VoidCheckerFnParm, typename P2=VoidCheckerFnParm, 38 typename P3=VoidCheckerFnParm, typename P4=VoidCheckerFnParm> 39class CheckerFn { 40 typedef void (*Func)(void *, P1, P2, P3, P4); 41 Func Fn; 42public: 43 void *Checker; 44 CheckerFn(void *checker, Func fn) : Fn(fn), Checker(checker) { } 45 void operator()(P1 p1, P2 p2, P3 p3, P4 p4) { Fn(Checker, p1, p2, p3, p4); } 46}; 47 48template <typename P1, typename P2, typename P3> 49class CheckerFn<P1, P2, P3, VoidCheckerFnParm> { 50 typedef void (*Func)(void *, P1, P2, P3); 51 Func Fn; 52public: 53 void *Checker; 54 CheckerFn(void *checker, Func fn) : Fn(fn), Checker(checker) { } 55 void operator()(P1 p1, P2 p2, P3 p3) { Fn(Checker, p1, p2, p3); } 56}; 57 58template <typename P1, typename P2> 59class CheckerFn<P1, P2, VoidCheckerFnParm, VoidCheckerFnParm> { 60 typedef void (*Func)(void *, P1, P2); 61 Func Fn; 62public: 63 void *Checker; 64 CheckerFn(void *checker, Func fn) : Fn(fn), Checker(checker) { } 65 void operator()(P1 p1, P2 p2) { Fn(Checker, p1, p2); } 66}; 67 68template <> 69class CheckerFn<VoidCheckerFnParm, VoidCheckerFnParm, VoidCheckerFnParm, 70 VoidCheckerFnParm> { 71 typedef void (*Func)(void *); 72 Func Fn; 73public: 74 void *Checker; 75 CheckerFn(void *checker, Func fn) : Fn(fn), Checker(checker) { } 76 void operator()() { Fn(Checker); } 77}; 78 79class CheckerManager { 80public: 81 ~CheckerManager(); 82 83 typedef void *CheckerRef; 84 typedef CheckerFn<> CheckerDtor; 85 86//===----------------------------------------------------------------------===// 87// registerChecker 88//===----------------------------------------------------------------------===// 89 90 /// \brief Used to register checkers. 91 template <typename CHECKER> 92 void registerChecker() { 93 CHECKER *checker = new CHECKER(); 94 CheckerDtors.push_back(CheckerDtor(checker, destruct<CHECKER>)); 95 CHECKER::_register(checker, *this); 96 } 97 98 typedef void (*RegisterToEngFunc)(ExprEngine &Eng); 99 void addCheckerRegisterFunction(RegisterToEngFunc fn) { 100 Funcs.push_back(fn); 101 } 102 103//===----------------------------------------------------------------------===// 104// Functions for running checkers for AST traversing.. 105//===----------------------------------------------------------------------===// 106 107 /// \brief Run checkers handling Decls. 108 void runCheckersOnASTDecl(const Decl *D, AnalysisManager& mgr, 109 BugReporter &BR); 110 111 /// \brief Run checkers handling Decls containing a Stmt body. 112 void runCheckersOnASTBody(const Decl *D, AnalysisManager& mgr, 113 BugReporter &BR); 114 115//===----------------------------------------------------------------------===// 116// Functions for running checkers for path-sensitive checking. 117//===----------------------------------------------------------------------===// 118 119 /// \brief Run checkers for pre-visiting Stmts. 120 void runCheckersForPreStmt(ExplodedNodeSet &Dst, 121 ExplodedNodeSet &Src, 122 const Stmt *S, 123 ExprEngine &Eng) { 124 runCheckersForStmt(/*isPreVisit=*/true, Dst, Src, S, Eng); 125 } 126 127 /// \brief Run checkers for post-visiting Stmts. 128 void runCheckersForPostStmt(ExplodedNodeSet &Dst, 129 ExplodedNodeSet &Src, 130 const Stmt *S, 131 ExprEngine &Eng) { 132 runCheckersForStmt(/*isPreVisit=*/false, Dst, Src, S, Eng); 133 } 134 135 /// \brief Run checkers for visiting Stmts. 136 void runCheckersForStmt(bool isPreVisit, 137 ExplodedNodeSet &Dst, ExplodedNodeSet &Src, 138 const Stmt *S, ExprEngine &Eng); 139 140 /// \brief Run checkers for pre-visiting obj-c messages. 141 void runCheckersForPreObjCMessage(ExplodedNodeSet &Dst, 142 ExplodedNodeSet &Src, 143 const ObjCMessage &msg, 144 ExprEngine &Eng) { 145 runCheckersForObjCMessage(/*isPreVisit=*/true, Dst, Src, msg, Eng); 146 } 147 148 /// \brief Run checkers for post-visiting obj-c messages. 149 void runCheckersForPostObjCMessage(ExplodedNodeSet &Dst, 150 ExplodedNodeSet &Src, 151 const ObjCMessage &msg, 152 ExprEngine &Eng) { 153 runCheckersForObjCMessage(/*isPreVisit=*/false, Dst, Src, msg, Eng); 154 } 155 156 /// \brief Run checkers for visiting obj-c messages. 157 void runCheckersForObjCMessage(bool isPreVisit, 158 ExplodedNodeSet &Dst, ExplodedNodeSet &Src, 159 const ObjCMessage &msg, ExprEngine &Eng); 160 161 /// \brief Run checkers for load/store of a location. 162 void runCheckersForLocation(ExplodedNodeSet &Dst, 163 ExplodedNodeSet &Src, 164 SVal location, bool isLoad, 165 const Stmt *S, 166 const GRState *state, 167 ExprEngine &Eng); 168 169 // FIXME: Temporary until checker running is moved completely into 170 // CheckerManager. 171 void registerCheckersToEngine(ExprEngine &eng); 172 173//===----------------------------------------------------------------------===// 174// Internal registration functions for AST traversing. 175//===----------------------------------------------------------------------===// 176 177 // Functions used by the registration mechanism, checkers should not touch 178 // these directly. 179 180 typedef CheckerFn<const Decl *, AnalysisManager&, BugReporter &> 181 CheckDeclFunc; 182 typedef CheckerFn<const Stmt *, CheckerContext &> CheckStmtFunc; 183 184 typedef bool (*HandlesDeclFunc)(const Decl *D); 185 void _registerForDecl(CheckDeclFunc checkfn, HandlesDeclFunc isForDeclFn); 186 187 void _registerForBody(CheckDeclFunc checkfn); 188 189//===----------------------------------------------------------------------===// 190// Internal registration functions for path-sensitive checking. 191//===----------------------------------------------------------------------===// 192 193 typedef CheckerFn<const ObjCMessage &, CheckerContext &> CheckObjCMessageFunc; 194 typedef CheckerFn<const SVal &/*location*/, bool/*isLoad*/, CheckerContext &> 195 CheckLocationFunc; 196 197 typedef bool (*HandlesStmtFunc)(const Stmt *D); 198 void _registerForPreStmt(CheckStmtFunc checkfn, 199 HandlesStmtFunc isForStmtFn); 200 void _registerForPostStmt(CheckStmtFunc checkfn, 201 HandlesStmtFunc isForStmtFn); 202 203 void _registerForPreObjCMessage(CheckObjCMessageFunc checkfn); 204 void _registerForPostObjCMessage(CheckObjCMessageFunc checkfn); 205 206 void _registerForLocation(CheckLocationFunc checkfn); 207 208//===----------------------------------------------------------------------===// 209// Implementation details. 210//===----------------------------------------------------------------------===// 211 212private: 213 template <typename CHECKER> 214 static void destruct(void *obj) { delete static_cast<CHECKER *>(obj); } 215 216 std::vector<CheckerDtor> CheckerDtors; 217 218 std::vector<RegisterToEngFunc> Funcs; 219 220 struct DeclCheckerInfo { 221 CheckDeclFunc CheckFn; 222 HandlesDeclFunc IsForDeclFn; 223 }; 224 std::vector<DeclCheckerInfo> DeclCheckers; 225 226 std::vector<CheckDeclFunc> BodyCheckers; 227 228 typedef llvm::SmallVector<CheckDeclFunc, 4> CachedDeclCheckers; 229 typedef llvm::DenseMap<unsigned, CachedDeclCheckers> CachedDeclCheckersMapTy; 230 CachedDeclCheckersMapTy CachedDeclCheckersMap; 231 232 struct StmtCheckerInfo { 233 CheckStmtFunc CheckFn; 234 HandlesStmtFunc IsForStmtFn; 235 bool IsPreVisit; 236 }; 237 std::vector<StmtCheckerInfo> StmtCheckers; 238 239 struct CachedStmtCheckersKey { 240 unsigned StmtKind; 241 bool IsPreVisit; 242 243 CachedStmtCheckersKey() : StmtKind(0), IsPreVisit(0) { } 244 CachedStmtCheckersKey(unsigned stmtKind, bool isPreVisit) 245 : StmtKind(stmtKind), IsPreVisit(isPreVisit) { } 246 247 static CachedStmtCheckersKey getSentinel() { 248 return CachedStmtCheckersKey(~0U, ~0U); 249 } 250 unsigned getHashValue() const { 251 llvm::FoldingSetNodeID ID; 252 ID.AddInteger(StmtKind); 253 ID.AddBoolean(IsPreVisit); 254 return ID.ComputeHash(); 255 } 256 bool operator==(const CachedStmtCheckersKey &RHS) const { 257 return StmtKind == RHS.StmtKind && IsPreVisit == RHS.IsPreVisit; 258 } 259 }; 260 friend struct llvm::DenseMapInfo<CachedStmtCheckersKey>; 261 262 typedef llvm::SmallVector<CheckStmtFunc, 4> CachedStmtCheckers; 263 typedef llvm::DenseMap<CachedStmtCheckersKey, CachedStmtCheckers> 264 CachedStmtCheckersMapTy; 265 CachedStmtCheckersMapTy CachedStmtCheckersMap; 266 267 CachedStmtCheckers *getCachedStmtCheckersFor(const Stmt *S, bool isPreVisit); 268 269 std::vector<CheckObjCMessageFunc> PreObjCMessageCheckers; 270 std::vector<CheckObjCMessageFunc> PostObjCMessageCheckers; 271 272 std::vector<CheckLocationFunc> LocationCheckers; 273}; 274 275} // end ento namespace 276 277} // end clang namespace 278 279namespace llvm { 280 /// Define DenseMapInfo so that CachedStmtCheckersKey can be used as key 281 /// in DenseMap and DenseSets. 282 template <> 283 struct DenseMapInfo<clang::ento::CheckerManager::CachedStmtCheckersKey> { 284 static inline clang::ento::CheckerManager::CachedStmtCheckersKey 285 getEmptyKey() { 286 return clang::ento::CheckerManager::CachedStmtCheckersKey(); 287 } 288 static inline clang::ento::CheckerManager::CachedStmtCheckersKey 289 getTombstoneKey() { 290 return clang::ento::CheckerManager::CachedStmtCheckersKey::getSentinel(); 291 } 292 293 static unsigned 294 getHashValue(clang::ento::CheckerManager::CachedStmtCheckersKey S) { 295 return S.getHashValue(); 296 } 297 298 static bool isEqual(clang::ento::CheckerManager::CachedStmtCheckersKey LHS, 299 clang::ento::CheckerManager::CachedStmtCheckersKey RHS) { 300 return LHS == RHS; 301 } 302 }; 303} // end namespace llvm 304 305#endif 306