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