clang API Documentation
00001 //===--- CheckerManager.h - Static Analyzer Checker Manager -----*- C++ -*-===// 00002 // 00003 // The LLVM Compiler Infrastructure 00004 // 00005 // This file is distributed under the University of Illinois Open Source 00006 // License. See LICENSE.TXT for details. 00007 // 00008 //===----------------------------------------------------------------------===// 00009 // 00010 // Defines the Static Analyzer Checker Manager. 00011 // 00012 //===----------------------------------------------------------------------===// 00013 00014 #ifndef LLVM_CLANG_SA_CORE_CHECKERMANAGER_H 00015 #define LLVM_CLANG_SA_CORE_CHECKERMANAGER_H 00016 00017 #include "clang/Basic/LangOptions.h" 00018 #include "llvm/ADT/SmallVector.h" 00019 #include "llvm/ADT/DenseMap.h" 00020 #include "llvm/ADT/FoldingSet.h" 00021 #include "clang/StaticAnalyzer/Core/PathSensitive/Store.h" 00022 #include "clang/Analysis/ProgramPoint.h" 00023 #include <vector> 00024 00025 namespace clang { 00026 class Decl; 00027 class Stmt; 00028 class CallExpr; 00029 00030 namespace ento { 00031 class CheckerBase; 00032 class ExprEngine; 00033 class AnalysisManager; 00034 class BugReporter; 00035 class CheckerContext; 00036 class ObjCMessage; 00037 class SVal; 00038 class ExplodedNode; 00039 class ExplodedNodeSet; 00040 class ExplodedGraph; 00041 class ProgramState; 00042 class NodeBuilder; 00043 struct NodeBuilderContext; 00044 class MemRegion; 00045 class SymbolReaper; 00046 00047 class GraphExpander { 00048 public: 00049 virtual ~GraphExpander(); 00050 virtual void expandGraph(ExplodedNodeSet &Dst, ExplodedNode *Pred) = 0; 00051 }; 00052 00053 template <typename T> class CheckerFn; 00054 00055 template <typename RET, typename P1, typename P2, typename P3, typename P4, 00056 typename P5> 00057 class CheckerFn<RET(P1, P2, P3, P4, P5)> { 00058 typedef RET (*Func)(void *, P1, P2, P3, P4, P5); 00059 Func Fn; 00060 public: 00061 CheckerBase *Checker; 00062 CheckerFn(CheckerBase *checker, Func fn) : Fn(fn), Checker(checker) { } 00063 RET operator()(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5) const { 00064 return Fn(Checker, p1, p2, p3, p4, p5); 00065 } 00066 }; 00067 00068 template <typename RET, typename P1, typename P2, typename P3, typename P4> 00069 class CheckerFn<RET(P1, P2, P3, P4)> { 00070 typedef RET (*Func)(void *, P1, P2, P3, P4); 00071 Func Fn; 00072 public: 00073 CheckerBase *Checker; 00074 CheckerFn(CheckerBase *checker, Func fn) : Fn(fn), Checker(checker) { } 00075 RET operator()(P1 p1, P2 p2, P3 p3, P4 p4) const { 00076 return Fn(Checker, p1, p2, p3, p4); 00077 } 00078 }; 00079 00080 template <typename RET, typename P1, typename P2, typename P3> 00081 class CheckerFn<RET(P1, P2, P3)> { 00082 typedef RET (*Func)(void *, P1, P2, P3); 00083 Func Fn; 00084 public: 00085 CheckerBase *Checker; 00086 CheckerFn(CheckerBase *checker, Func fn) : Fn(fn), Checker(checker) { } 00087 RET operator()(P1 p1, P2 p2, P3 p3) const { return Fn(Checker, p1, p2, p3); } 00088 }; 00089 00090 template <typename RET, typename P1, typename P2> 00091 class CheckerFn<RET(P1, P2)> { 00092 typedef RET (*Func)(void *, P1, P2); 00093 Func Fn; 00094 public: 00095 CheckerBase *Checker; 00096 CheckerFn(CheckerBase *checker, Func fn) : Fn(fn), Checker(checker) { } 00097 RET operator()(P1 p1, P2 p2) const { return Fn(Checker, p1, p2); } 00098 }; 00099 00100 template <typename RET, typename P1> 00101 class CheckerFn<RET(P1)> { 00102 typedef RET (*Func)(void *, P1); 00103 Func Fn; 00104 public: 00105 CheckerBase *Checker; 00106 CheckerFn(CheckerBase *checker, Func fn) : Fn(fn), Checker(checker) { } 00107 RET operator()(P1 p1) const { return Fn(Checker, p1); } 00108 }; 00109 00110 template <typename RET> 00111 class CheckerFn<RET()> { 00112 typedef RET (*Func)(void *); 00113 Func Fn; 00114 public: 00115 CheckerBase *Checker; 00116 CheckerFn(CheckerBase *checker, Func fn) : Fn(fn), Checker(checker) { } 00117 RET operator()() const { return Fn(Checker); } 00118 }; 00119 00120 class CheckerManager { 00121 const LangOptions LangOpts; 00122 00123 public: 00124 CheckerManager(const LangOptions &langOpts) : LangOpts(langOpts) { } 00125 ~CheckerManager(); 00126 00127 bool hasPathSensitiveCheckers() const; 00128 00129 void finishedCheckerRegistration(); 00130 00131 const LangOptions &getLangOpts() const { return LangOpts; } 00132 00133 typedef CheckerBase *CheckerRef; 00134 typedef const void *CheckerTag; 00135 typedef CheckerFn<void ()> CheckerDtor; 00136 00137 //===----------------------------------------------------------------------===// 00138 // registerChecker 00139 //===----------------------------------------------------------------------===// 00140 00141 /// \brief Used to register checkers. 00142 /// 00143 /// \returns a pointer to the checker object. 00144 template <typename CHECKER> 00145 CHECKER *registerChecker() { 00146 CheckerTag tag = getTag<CHECKER>(); 00147 CheckerRef &ref = CheckerTags[tag]; 00148 if (ref) 00149 return static_cast<CHECKER *>(ref); // already registered. 00150 00151 CHECKER *checker = new CHECKER(); 00152 CheckerDtors.push_back(CheckerDtor(checker, destruct<CHECKER>)); 00153 CHECKER::_register(checker, *this); 00154 ref = checker; 00155 return checker; 00156 } 00157 00158 //===----------------------------------------------------------------------===// 00159 // Functions for running checkers for AST traversing.. 00160 //===----------------------------------------------------------------------===// 00161 00162 /// \brief Run checkers handling Decls. 00163 void runCheckersOnASTDecl(const Decl *D, AnalysisManager& mgr, 00164 BugReporter &BR); 00165 00166 /// \brief Run checkers handling Decls containing a Stmt body. 00167 void runCheckersOnASTBody(const Decl *D, AnalysisManager& mgr, 00168 BugReporter &BR); 00169 00170 //===----------------------------------------------------------------------===// 00171 // Functions for running checkers for path-sensitive checking. 00172 //===----------------------------------------------------------------------===// 00173 00174 /// \brief Run checkers for pre-visiting Stmts. 00175 /// 00176 /// The notification is performed for every explored CFGElement, which does 00177 /// not include the control flow statements such as IfStmt. 00178 /// 00179 /// \sa runCheckersForBranchCondition, runCheckersForPostStmt 00180 void runCheckersForPreStmt(ExplodedNodeSet &Dst, 00181 const ExplodedNodeSet &Src, 00182 const Stmt *S, 00183 ExprEngine &Eng) { 00184 runCheckersForStmt(/*isPreVisit=*/true, Dst, Src, S, Eng); 00185 } 00186 00187 /// \brief Run checkers for post-visiting Stmts. 00188 /// 00189 /// The notification is performed for every explored CFGElement, which does 00190 /// not include the control flow statements such as IfStmt. 00191 /// 00192 /// \sa runCheckersForBranchCondition, runCheckersForPreStmt 00193 void runCheckersForPostStmt(ExplodedNodeSet &Dst, 00194 const ExplodedNodeSet &Src, 00195 const Stmt *S, 00196 ExprEngine &Eng, 00197 bool wasInlined = false) { 00198 runCheckersForStmt(/*isPreVisit=*/false, Dst, Src, S, Eng, wasInlined); 00199 } 00200 00201 /// \brief Run checkers for visiting Stmts. 00202 void runCheckersForStmt(bool isPreVisit, 00203 ExplodedNodeSet &Dst, const ExplodedNodeSet &Src, 00204 const Stmt *S, ExprEngine &Eng, 00205 bool wasInlined = false); 00206 00207 /// \brief Run checkers for pre-visiting obj-c messages. 00208 void runCheckersForPreObjCMessage(ExplodedNodeSet &Dst, 00209 const ExplodedNodeSet &Src, 00210 const ObjCMessage &msg, 00211 ExprEngine &Eng) { 00212 runCheckersForObjCMessage(/*isPreVisit=*/true, Dst, Src, msg, Eng); 00213 } 00214 00215 /// \brief Run checkers for post-visiting obj-c messages. 00216 void runCheckersForPostObjCMessage(ExplodedNodeSet &Dst, 00217 const ExplodedNodeSet &Src, 00218 const ObjCMessage &msg, 00219 ExprEngine &Eng) { 00220 runCheckersForObjCMessage(/*isPreVisit=*/false, Dst, Src, msg, Eng); 00221 } 00222 00223 /// \brief Run checkers for visiting obj-c messages. 00224 void runCheckersForObjCMessage(bool isPreVisit, 00225 ExplodedNodeSet &Dst, 00226 const ExplodedNodeSet &Src, 00227 const ObjCMessage &msg, ExprEngine &Eng); 00228 00229 /// \brief Run checkers for load/store of a location. 00230 void runCheckersForLocation(ExplodedNodeSet &Dst, 00231 const ExplodedNodeSet &Src, 00232 SVal location, 00233 bool isLoad, 00234 const Stmt *NodeEx, 00235 const Stmt *BoundEx, 00236 ExprEngine &Eng); 00237 00238 /// \brief Run checkers for binding of a value to a location. 00239 void runCheckersForBind(ExplodedNodeSet &Dst, 00240 const ExplodedNodeSet &Src, 00241 SVal location, SVal val, 00242 const Stmt *S, ExprEngine &Eng, 00243 ProgramPoint::Kind PointKind); 00244 00245 /// \brief Run checkers for end of analysis. 00246 void runCheckersForEndAnalysis(ExplodedGraph &G, BugReporter &BR, 00247 ExprEngine &Eng); 00248 00249 /// \brief Run checkers for end of path. 00250 void runCheckersForEndPath(NodeBuilderContext &BC, 00251 ExplodedNodeSet &Dst, 00252 ExprEngine &Eng); 00253 00254 /// \brief Run checkers for branch condition. 00255 void runCheckersForBranchCondition(const Stmt *condition, 00256 ExplodedNodeSet &Dst, ExplodedNode *Pred, 00257 ExprEngine &Eng); 00258 00259 /// \brief Run checkers for live symbols. 00260 /// 00261 /// Allows modifying SymbolReaper object. For example, checkers can explicitly 00262 /// register symbols of interest as live. These symbols will not be marked 00263 /// dead and removed. 00264 void runCheckersForLiveSymbols(ProgramStateRef state, 00265 SymbolReaper &SymReaper); 00266 00267 /// \brief Run checkers for dead symbols. 00268 /// 00269 /// Notifies checkers when symbols become dead. For example, this allows 00270 /// checkers to aggressively clean up/reduce the checker state and produce 00271 /// precise diagnostics. 00272 void runCheckersForDeadSymbols(ExplodedNodeSet &Dst, 00273 const ExplodedNodeSet &Src, 00274 SymbolReaper &SymReaper, const Stmt *S, 00275 ExprEngine &Eng, 00276 ProgramPoint::Kind K); 00277 00278 /// \brief True if at least one checker wants to check region changes. 00279 bool wantsRegionChangeUpdate(ProgramStateRef state); 00280 00281 /// \brief Run checkers for region changes. 00282 /// 00283 /// This corresponds to the check::RegionChanges callback. 00284 /// \param state The current program state. 00285 /// \param invalidated A set of all symbols potentially touched by the change. 00286 /// \param ExplicitRegions The regions explicitly requested for invalidation. 00287 /// For example, in the case of a function call, these would be arguments. 00288 /// \param Regions The transitive closure of accessible regions, 00289 /// i.e. all regions that may have been touched by this change. 00290 /// \param The call expression wrapper if the regions are invalidated by a 00291 /// call. 00292 ProgramStateRef 00293 runCheckersForRegionChanges(ProgramStateRef state, 00294 const StoreManager::InvalidatedSymbols *invalidated, 00295 ArrayRef<const MemRegion *> ExplicitRegions, 00296 ArrayRef<const MemRegion *> Regions, 00297 const CallOrObjCMessage *Call); 00298 00299 /// \brief Run checkers for handling assumptions on symbolic values. 00300 ProgramStateRef runCheckersForEvalAssume(ProgramStateRef state, 00301 SVal Cond, bool Assumption); 00302 00303 /// \brief Run checkers for evaluating a call. 00304 void runCheckersForEvalCall(ExplodedNodeSet &Dst, 00305 const ExplodedNodeSet &Src, 00306 const CallExpr *CE, ExprEngine &Eng, 00307 GraphExpander *defaultEval = 0); 00308 00309 /// \brief Run checkers for the entire Translation Unit. 00310 void runCheckersOnEndOfTranslationUnit(const TranslationUnitDecl *TU, 00311 AnalysisManager &mgr, 00312 BugReporter &BR); 00313 00314 /// \brief Run checkers for debug-printing a ProgramState. 00315 /// 00316 /// Unlike most other callbacks, any checker can simply implement the virtual 00317 /// method CheckerBase::printState if it has custom data to print. 00318 /// \param Out The output stream 00319 /// \param State The state being printed 00320 /// \param NL The preferred representation of a newline. 00321 /// \param Sep The preferred separator between different kinds of data. 00322 void runCheckersForPrintState(raw_ostream &Out, ProgramStateRef State, 00323 const char *NL, const char *Sep); 00324 00325 //===----------------------------------------------------------------------===// 00326 // Internal registration functions for AST traversing. 00327 //===----------------------------------------------------------------------===// 00328 00329 // Functions used by the registration mechanism, checkers should not touch 00330 // these directly. 00331 00332 typedef CheckerFn<void (const Decl *, AnalysisManager&, BugReporter &)> 00333 CheckDeclFunc; 00334 00335 typedef bool (*HandlesDeclFunc)(const Decl *D); 00336 void _registerForDecl(CheckDeclFunc checkfn, HandlesDeclFunc isForDeclFn); 00337 00338 void _registerForBody(CheckDeclFunc checkfn); 00339 00340 //===----------------------------------------------------------------------===// 00341 // Internal registration functions for path-sensitive checking. 00342 //===----------------------------------------------------------------------===// 00343 00344 typedef CheckerFn<void (const Stmt *, CheckerContext &)> CheckStmtFunc; 00345 00346 typedef CheckerFn<void (const ObjCMessage &, CheckerContext &)> 00347 CheckObjCMessageFunc; 00348 00349 typedef CheckerFn<void (const SVal &location, bool isLoad, 00350 const Stmt *S, 00351 CheckerContext &)> 00352 CheckLocationFunc; 00353 00354 typedef CheckerFn<void (const SVal &location, const SVal &val, 00355 const Stmt *S, CheckerContext &)> 00356 CheckBindFunc; 00357 00358 typedef CheckerFn<void (ExplodedGraph &, BugReporter &, ExprEngine &)> 00359 CheckEndAnalysisFunc; 00360 00361 typedef CheckerFn<void (CheckerContext &)> 00362 CheckEndPathFunc; 00363 00364 typedef CheckerFn<void (const Stmt *, CheckerContext &)> 00365 CheckBranchConditionFunc; 00366 00367 typedef CheckerFn<void (SymbolReaper &, CheckerContext &)> 00368 CheckDeadSymbolsFunc; 00369 00370 typedef CheckerFn<void (ProgramStateRef,SymbolReaper &)> CheckLiveSymbolsFunc; 00371 00372 typedef CheckerFn<ProgramStateRef (ProgramStateRef, 00373 const StoreManager::InvalidatedSymbols *symbols, 00374 ArrayRef<const MemRegion *> ExplicitRegions, 00375 ArrayRef<const MemRegion *> Regions, 00376 const CallOrObjCMessage *Call)> 00377 CheckRegionChangesFunc; 00378 00379 typedef CheckerFn<bool (ProgramStateRef)> WantsRegionChangeUpdateFunc; 00380 00381 typedef CheckerFn<ProgramStateRef (ProgramStateRef, 00382 const SVal &cond, bool assumption)> 00383 EvalAssumeFunc; 00384 00385 typedef CheckerFn<bool (const CallExpr *, CheckerContext &)> 00386 EvalCallFunc; 00387 00388 typedef CheckerFn<bool (const CallExpr *, ExprEngine &Eng, 00389 ExplodedNode *Pred, 00390 ExplodedNodeSet &Dst)> 00391 InlineCallFunc; 00392 00393 typedef CheckerFn<void (const TranslationUnitDecl *, 00394 AnalysisManager&, BugReporter &)> 00395 CheckEndOfTranslationUnit; 00396 00397 typedef bool (*HandlesStmtFunc)(const Stmt *D); 00398 void _registerForPreStmt(CheckStmtFunc checkfn, 00399 HandlesStmtFunc isForStmtFn); 00400 void _registerForPostStmt(CheckStmtFunc checkfn, 00401 HandlesStmtFunc isForStmtFn); 00402 00403 void _registerForPreObjCMessage(CheckObjCMessageFunc checkfn); 00404 void _registerForPostObjCMessage(CheckObjCMessageFunc checkfn); 00405 00406 void _registerForLocation(CheckLocationFunc checkfn); 00407 00408 void _registerForBind(CheckBindFunc checkfn); 00409 00410 void _registerForEndAnalysis(CheckEndAnalysisFunc checkfn); 00411 00412 void _registerForEndPath(CheckEndPathFunc checkfn); 00413 00414 void _registerForBranchCondition(CheckBranchConditionFunc checkfn); 00415 00416 void _registerForLiveSymbols(CheckLiveSymbolsFunc checkfn); 00417 00418 void _registerForDeadSymbols(CheckDeadSymbolsFunc checkfn); 00419 00420 void _registerForRegionChanges(CheckRegionChangesFunc checkfn, 00421 WantsRegionChangeUpdateFunc wantUpdateFn); 00422 00423 void _registerForEvalAssume(EvalAssumeFunc checkfn); 00424 00425 void _registerForEvalCall(EvalCallFunc checkfn); 00426 00427 void _registerForInlineCall(InlineCallFunc checkfn); 00428 00429 void _registerForEndOfTranslationUnit(CheckEndOfTranslationUnit checkfn); 00430 00431 //===----------------------------------------------------------------------===// 00432 // Internal registration functions for events. 00433 //===----------------------------------------------------------------------===// 00434 00435 typedef void *EventTag; 00436 typedef CheckerFn<void (const void *event)> CheckEventFunc; 00437 00438 template <typename EVENT> 00439 void _registerListenerForEvent(CheckEventFunc checkfn) { 00440 EventInfo &info = Events[getTag<EVENT>()]; 00441 info.Checkers.push_back(checkfn); 00442 } 00443 00444 template <typename EVENT> 00445 void _registerDispatcherForEvent() { 00446 EventInfo &info = Events[getTag<EVENT>()]; 00447 info.HasDispatcher = true; 00448 } 00449 00450 template <typename EVENT> 00451 void _dispatchEvent(const EVENT &event) const { 00452 EventsTy::const_iterator I = Events.find(getTag<EVENT>()); 00453 if (I == Events.end()) 00454 return; 00455 const EventInfo &info = I->second; 00456 for (unsigned i = 0, e = info.Checkers.size(); i != e; ++i) 00457 info.Checkers[i](&event); 00458 } 00459 00460 //===----------------------------------------------------------------------===// 00461 // Implementation details. 00462 //===----------------------------------------------------------------------===// 00463 00464 private: 00465 template <typename CHECKER> 00466 static void destruct(void *obj) { delete static_cast<CHECKER *>(obj); } 00467 00468 template <typename T> 00469 static void *getTag() { static int tag; return &tag; } 00470 00471 llvm::DenseMap<CheckerTag, CheckerRef> CheckerTags; 00472 00473 std::vector<CheckerDtor> CheckerDtors; 00474 00475 struct DeclCheckerInfo { 00476 CheckDeclFunc CheckFn; 00477 HandlesDeclFunc IsForDeclFn; 00478 }; 00479 std::vector<DeclCheckerInfo> DeclCheckers; 00480 00481 std::vector<CheckDeclFunc> BodyCheckers; 00482 00483 typedef SmallVector<CheckDeclFunc, 4> CachedDeclCheckers; 00484 typedef llvm::DenseMap<unsigned, CachedDeclCheckers> CachedDeclCheckersMapTy; 00485 CachedDeclCheckersMapTy CachedDeclCheckersMap; 00486 00487 struct StmtCheckerInfo { 00488 CheckStmtFunc CheckFn; 00489 HandlesStmtFunc IsForStmtFn; 00490 bool IsPreVisit; 00491 }; 00492 std::vector<StmtCheckerInfo> StmtCheckers; 00493 00494 struct CachedStmtCheckersKey { 00495 unsigned StmtKind; 00496 bool IsPreVisit; 00497 00498 CachedStmtCheckersKey() : StmtKind(0), IsPreVisit(0) { } 00499 CachedStmtCheckersKey(unsigned stmtKind, bool isPreVisit) 00500 : StmtKind(stmtKind), IsPreVisit(isPreVisit) { } 00501 00502 static CachedStmtCheckersKey getSentinel() { 00503 return CachedStmtCheckersKey(~0U, 0); 00504 } 00505 unsigned getHashValue() const { 00506 llvm::FoldingSetNodeID ID; 00507 ID.AddInteger(StmtKind); 00508 ID.AddBoolean(IsPreVisit); 00509 return ID.ComputeHash(); 00510 } 00511 bool operator==(const CachedStmtCheckersKey &RHS) const { 00512 return StmtKind == RHS.StmtKind && IsPreVisit == RHS.IsPreVisit; 00513 } 00514 }; 00515 friend struct llvm::DenseMapInfo<CachedStmtCheckersKey>; 00516 00517 typedef SmallVector<CheckStmtFunc, 4> CachedStmtCheckers; 00518 typedef llvm::DenseMap<CachedStmtCheckersKey, CachedStmtCheckers> 00519 CachedStmtCheckersMapTy; 00520 CachedStmtCheckersMapTy CachedStmtCheckersMap; 00521 00522 CachedStmtCheckers *getCachedStmtCheckersFor(const Stmt *S, bool isPreVisit); 00523 00524 std::vector<CheckObjCMessageFunc> PreObjCMessageCheckers; 00525 std::vector<CheckObjCMessageFunc> PostObjCMessageCheckers; 00526 00527 std::vector<CheckLocationFunc> LocationCheckers; 00528 00529 std::vector<CheckBindFunc> BindCheckers; 00530 00531 std::vector<CheckEndAnalysisFunc> EndAnalysisCheckers; 00532 00533 std::vector<CheckEndPathFunc> EndPathCheckers; 00534 00535 std::vector<CheckBranchConditionFunc> BranchConditionCheckers; 00536 00537 std::vector<CheckLiveSymbolsFunc> LiveSymbolsCheckers; 00538 00539 std::vector<CheckDeadSymbolsFunc> DeadSymbolsCheckers; 00540 00541 struct RegionChangesCheckerInfo { 00542 CheckRegionChangesFunc CheckFn; 00543 WantsRegionChangeUpdateFunc WantUpdateFn; 00544 }; 00545 std::vector<RegionChangesCheckerInfo> RegionChangesCheckers; 00546 00547 std::vector<EvalAssumeFunc> EvalAssumeCheckers; 00548 00549 std::vector<EvalCallFunc> EvalCallCheckers; 00550 00551 std::vector<InlineCallFunc> InlineCallCheckers; 00552 00553 std::vector<CheckEndOfTranslationUnit> EndOfTranslationUnitCheckers; 00554 00555 struct EventInfo { 00556 SmallVector<CheckEventFunc, 4> Checkers; 00557 bool HasDispatcher; 00558 EventInfo() : HasDispatcher(false) { } 00559 }; 00560 00561 typedef llvm::DenseMap<EventTag, EventInfo> EventsTy; 00562 EventsTy Events; 00563 }; 00564 00565 } // end ento namespace 00566 00567 } // end clang namespace 00568 00569 namespace llvm { 00570 /// Define DenseMapInfo so that CachedStmtCheckersKey can be used as key 00571 /// in DenseMap and DenseSets. 00572 template <> 00573 struct DenseMapInfo<clang::ento::CheckerManager::CachedStmtCheckersKey> { 00574 static inline clang::ento::CheckerManager::CachedStmtCheckersKey 00575 getEmptyKey() { 00576 return clang::ento::CheckerManager::CachedStmtCheckersKey(); 00577 } 00578 static inline clang::ento::CheckerManager::CachedStmtCheckersKey 00579 getTombstoneKey() { 00580 return clang::ento::CheckerManager::CachedStmtCheckersKey::getSentinel(); 00581 } 00582 00583 static unsigned 00584 getHashValue(clang::ento::CheckerManager::CachedStmtCheckersKey S) { 00585 return S.getHashValue(); 00586 } 00587 00588 static bool isEqual(clang::ento::CheckerManager::CachedStmtCheckersKey LHS, 00589 clang::ento::CheckerManager::CachedStmtCheckersKey RHS) { 00590 return LHS == RHS; 00591 } 00592 }; 00593 } // end namespace llvm 00594 00595 #endif