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