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