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