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 "clang/StaticAnalyzer/Core/PathSensitive/Store.h" 22 #include "clang/Analysis/ProgramPoint.h" 23 #include <vector> 24 25 namespace clang { 26 class Decl; 27 class Stmt; 28 class CallExpr; 29 30 namespace ento { 31 class CheckerBase; 32 class ExprEngine; 33 class AnalysisManager; 34 class BugReporter; 35 class CheckerContext; 36 class SimpleCall; 37 class ObjCMethodCall; 38 class SVal; 39 class ExplodedNode; 40 class ExplodedNodeSet; 41 class ExplodedGraph; 42 class ProgramState; 43 class NodeBuilder; 44 struct NodeBuilderContext; 45 class MemRegion; 46 class SymbolReaper; 47 48 template <typename T> class CheckerFn; 49 50 template <typename RET, typename P1, typename P2, typename P3, typename P4, 51 typename P5> 52 class CheckerFn<RET(P1, P2, P3, P4, P5)> { 53 typedef RET (*Func)(void *, P1, P2, P3, P4, P5); 54 Func Fn; 55 public: 56 CheckerBase *Checker; 57 CheckerFn(CheckerBase *checker, Func fn) : Fn(fn), Checker(checker) { } 58 RET operator()(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5) const { 59 return Fn(Checker, p1, p2, p3, p4, p5); 60 } 61 }; 62 63 template <typename RET, typename P1, typename P2, typename P3, typename P4> 64 class CheckerFn<RET(P1, P2, P3, P4)> { 65 typedef RET (*Func)(void *, P1, P2, P3, P4); 66 Func Fn; 67 public: 68 CheckerBase *Checker; 69 CheckerFn(CheckerBase *checker, Func fn) : Fn(fn), Checker(checker) { } 70 RET operator()(P1 p1, P2 p2, P3 p3, P4 p4) const { 71 return Fn(Checker, p1, p2, p3, p4); 72 } 73 }; 74 75 template <typename RET, typename P1, typename P2, typename P3> 76 class CheckerFn<RET(P1, P2, P3)> { 77 typedef RET (*Func)(void *, P1, P2, P3); 78 Func Fn; 79 public: 80 CheckerBase *Checker; 81 CheckerFn(CheckerBase *checker, Func fn) : Fn(fn), Checker(checker) { } 82 RET operator()(P1 p1, P2 p2, P3 p3) const { return Fn(Checker, p1, p2, p3); } 83 }; 84 85 template <typename RET, typename P1, typename P2> 86 class CheckerFn<RET(P1, P2)> { 87 typedef RET (*Func)(void *, P1, P2); 88 Func Fn; 89 public: 90 CheckerBase *Checker; 91 CheckerFn(CheckerBase *checker, Func fn) : Fn(fn), Checker(checker) { } 92 RET operator()(P1 p1, P2 p2) const { return Fn(Checker, p1, p2); } 93 }; 94 95 template <typename RET, typename P1> 96 class CheckerFn<RET(P1)> { 97 typedef RET (*Func)(void *, P1); 98 Func Fn; 99 public: 100 CheckerBase *Checker; 101 CheckerFn(CheckerBase *checker, Func fn) : Fn(fn), Checker(checker) { } 102 RET operator()(P1 p1) const { return Fn(Checker, p1); } 103 }; 104 105 template <typename RET> 106 class CheckerFn<RET()> { 107 typedef RET (*Func)(void *); 108 Func Fn; 109 public: 110 CheckerBase *Checker; 111 CheckerFn(CheckerBase *checker, Func fn) : Fn(fn), Checker(checker) { } 112 RET operator()() const { return Fn(Checker); } 113 }; 114 115 class CheckerManager { 116 const LangOptions LangOpts; 117 118 public: 119 CheckerManager(const LangOptions &langOpts) : LangOpts(langOpts) { } 120 ~CheckerManager(); 121 122 bool hasPathSensitiveCheckers() const; 123 124 void finishedCheckerRegistration(); 125 126 const LangOptions &getLangOpts() const { return LangOpts; } 127 128 typedef CheckerBase *CheckerRef; 129 typedef const void *CheckerTag; 130 typedef CheckerFn<void ()> CheckerDtor; 131 132 //===----------------------------------------------------------------------===// 133 // registerChecker 134 //===----------------------------------------------------------------------===// 135 136 /// \brief Used to register checkers. 137 /// 138 /// \returns a pointer to the checker object. 139 template <typename CHECKER> 140 CHECKER *registerChecker() { 141 CheckerTag tag = getTag<CHECKER>(); 142 CheckerRef &ref = CheckerTags[tag]; 143 if (ref) 144 return static_cast<CHECKER *>(ref); // already registered. 145 146 CHECKER *checker = new CHECKER(); 147 CheckerDtors.push_back(CheckerDtor(checker, destruct<CHECKER>)); 148 CHECKER::_register(checker, *this); 149 ref = checker; 150 return checker; 151 } 152 153 //===----------------------------------------------------------------------===// 154 // Functions for running checkers for AST traversing.. 155 //===----------------------------------------------------------------------===// 156 157 /// \brief Run checkers handling Decls. 158 void runCheckersOnASTDecl(const Decl *D, AnalysisManager& mgr, 159 BugReporter &BR); 160 161 /// \brief Run checkers handling Decls containing a Stmt body. 162 void runCheckersOnASTBody(const Decl *D, AnalysisManager& mgr, 163 BugReporter &BR); 164 165 //===----------------------------------------------------------------------===// 166 // Functions for running checkers for path-sensitive checking. 167 //===----------------------------------------------------------------------===// 168 169 /// \brief Run checkers for pre-visiting Stmts. 170 /// 171 /// The notification is performed for every explored CFGElement, which does 172 /// not include the control flow statements such as IfStmt. 173 /// 174 /// \sa runCheckersForBranchCondition, runCheckersForPostStmt 175 void runCheckersForPreStmt(ExplodedNodeSet &Dst, 176 const ExplodedNodeSet &Src, 177 const Stmt *S, 178 ExprEngine &Eng) { 179 runCheckersForStmt(/*isPreVisit=*/true, Dst, Src, S, Eng); 180 } 181 182 /// \brief Run checkers for post-visiting Stmts. 183 /// 184 /// The notification is performed for every explored CFGElement, which does 185 /// not include the control flow statements such as IfStmt. 186 /// 187 /// \sa runCheckersForBranchCondition, runCheckersForPreStmt 188 void runCheckersForPostStmt(ExplodedNodeSet &Dst, 189 const ExplodedNodeSet &Src, 190 const Stmt *S, 191 ExprEngine &Eng, 192 bool wasInlined = false) { 193 runCheckersForStmt(/*isPreVisit=*/false, Dst, Src, S, Eng, wasInlined); 194 } 195 196 /// \brief Run checkers for visiting Stmts. 197 void runCheckersForStmt(bool isPreVisit, 198 ExplodedNodeSet &Dst, const ExplodedNodeSet &Src, 199 const Stmt *S, ExprEngine &Eng, 200 bool wasInlined = false); 201 202 /// \brief Run checkers for pre-visiting obj-c messages. 203 void runCheckersForPreObjCMessage(ExplodedNodeSet &Dst, 204 const ExplodedNodeSet &Src, 205 const ObjCMethodCall &msg, 206 ExprEngine &Eng) { 207 runCheckersForObjCMessage(/*isPreVisit=*/true, Dst, Src, msg, Eng); 208 } 209 210 /// \brief Run checkers for post-visiting obj-c messages. 211 void runCheckersForPostObjCMessage(ExplodedNodeSet &Dst, 212 const ExplodedNodeSet &Src, 213 const ObjCMethodCall &msg, 214 ExprEngine &Eng, 215 bool wasInlined = false) { 216 runCheckersForObjCMessage(/*isPreVisit=*/false, Dst, Src, msg, Eng, 217 wasInlined); 218 } 219 220 /// \brief Run checkers for visiting obj-c messages. 221 void runCheckersForObjCMessage(bool isPreVisit, 222 ExplodedNodeSet &Dst, 223 const ExplodedNodeSet &Src, 224 const ObjCMethodCall &msg, ExprEngine &Eng, 225 bool wasInlined = false); 226 227 /// \brief Run checkers for pre-visiting obj-c messages. 228 void runCheckersForPreCall(ExplodedNodeSet &Dst, const ExplodedNodeSet &Src, 229 const CallEvent &Call, ExprEngine &Eng) { 230 runCheckersForCallEvent(/*isPreVisit=*/true, Dst, Src, Call, Eng); 231 } 232 233 /// \brief Run checkers for post-visiting obj-c messages. 234 void runCheckersForPostCall(ExplodedNodeSet &Dst, const ExplodedNodeSet &Src, 235 const CallEvent &Call, ExprEngine &Eng, 236 bool wasInlined = false) { 237 runCheckersForCallEvent(/*isPreVisit=*/false, Dst, Src, Call, Eng, 238 wasInlined); 239 } 240 241 /// \brief Run checkers for visiting obj-c messages. 242 void runCheckersForCallEvent(bool isPreVisit, ExplodedNodeSet &Dst, 243 const ExplodedNodeSet &Src, 244 const CallEvent &Call, ExprEngine &Eng, 245 bool wasInlined = false); 246 247 /// \brief Run checkers for load/store of a location. 248 void runCheckersForLocation(ExplodedNodeSet &Dst, 249 const ExplodedNodeSet &Src, 250 SVal location, 251 bool isLoad, 252 const Stmt *NodeEx, 253 const Stmt *BoundEx, 254 ExprEngine &Eng); 255 256 /// \brief Run checkers for binding of a value to a location. 257 void runCheckersForBind(ExplodedNodeSet &Dst, 258 const ExplodedNodeSet &Src, 259 SVal location, SVal val, 260 const Stmt *S, ExprEngine &Eng, 261 const ProgramPoint &PP); 262 263 /// \brief Run checkers for end of analysis. 264 void runCheckersForEndAnalysis(ExplodedGraph &G, BugReporter &BR, 265 ExprEngine &Eng); 266 267 /// \brief Run checkers for end of path. 268 void runCheckersForEndPath(NodeBuilderContext &BC, 269 ExplodedNodeSet &Dst, 270 ExprEngine &Eng); 271 272 /// \brief Run checkers for branch condition. 273 void runCheckersForBranchCondition(const Stmt *condition, 274 ExplodedNodeSet &Dst, ExplodedNode *Pred, 275 ExprEngine &Eng); 276 277 /// \brief Run checkers for live symbols. 278 /// 279 /// Allows modifying SymbolReaper object. For example, checkers can explicitly 280 /// register symbols of interest as live. These symbols will not be marked 281 /// dead and removed. 282 void runCheckersForLiveSymbols(ProgramStateRef state, 283 SymbolReaper &SymReaper); 284 285 /// \brief Run checkers for dead symbols. 286 /// 287 /// Notifies checkers when symbols become dead. For example, this allows 288 /// checkers to aggressively clean up/reduce the checker state and produce 289 /// precise diagnostics. 290 void runCheckersForDeadSymbols(ExplodedNodeSet &Dst, 291 const ExplodedNodeSet &Src, 292 SymbolReaper &SymReaper, const Stmt *S, 293 ExprEngine &Eng, 294 ProgramPoint::Kind K); 295 296 /// \brief True if at least one checker wants to check region changes. 297 bool wantsRegionChangeUpdate(ProgramStateRef state); 298 299 /// \brief Run checkers for region changes. 300 /// 301 /// This corresponds to the check::RegionChanges callback. 302 /// \param state The current program state. 303 /// \param invalidated A set of all symbols potentially touched by the change. 304 /// \param ExplicitRegions The regions explicitly requested for invalidation. 305 /// For example, in the case of a function call, these would be arguments. 306 /// \param Regions The transitive closure of accessible regions, 307 /// i.e. all regions that may have been touched by this change. 308 /// \param Call The call expression wrapper if the regions are invalidated 309 /// by a call. 310 ProgramStateRef 311 runCheckersForRegionChanges(ProgramStateRef state, 312 const StoreManager::InvalidatedSymbols *invalidated, 313 ArrayRef<const MemRegion *> ExplicitRegions, 314 ArrayRef<const MemRegion *> Regions, 315 const CallEvent *Call); 316 317 /// \brief Run checkers for handling assumptions on symbolic values. 318 ProgramStateRef runCheckersForEvalAssume(ProgramStateRef state, 319 SVal Cond, bool Assumption); 320 321 /// \brief Run checkers for evaluating a call. 322 /// 323 /// Warning: Currently, the CallEvent MUST come from a CallExpr! 324 void runCheckersForEvalCall(ExplodedNodeSet &Dst, 325 const ExplodedNodeSet &Src, 326 const CallEvent &CE, ExprEngine &Eng); 327 328 /// \brief Run checkers for the entire Translation Unit. 329 void runCheckersOnEndOfTranslationUnit(const TranslationUnitDecl *TU, 330 AnalysisManager &mgr, 331 BugReporter &BR); 332 333 /// \brief Run checkers for debug-printing a ProgramState. 334 /// 335 /// Unlike most other callbacks, any checker can simply implement the virtual 336 /// method CheckerBase::printState if it has custom data to print. 337 /// \param Out The output stream 338 /// \param State The state being printed 339 /// \param NL The preferred representation of a newline. 340 /// \param Sep The preferred separator between different kinds of data. 341 void runCheckersForPrintState(raw_ostream &Out, ProgramStateRef State, 342 const char *NL, const char *Sep); 343 344 //===----------------------------------------------------------------------===// 345 // Internal registration functions for AST traversing. 346 //===----------------------------------------------------------------------===// 347 348 // Functions used by the registration mechanism, checkers should not touch 349 // these directly. 350 351 typedef CheckerFn<void (const Decl *, AnalysisManager&, BugReporter &)> 352 CheckDeclFunc; 353 354 typedef bool (*HandlesDeclFunc)(const Decl *D); 355 void _registerForDecl(CheckDeclFunc checkfn, HandlesDeclFunc isForDeclFn); 356 357 void _registerForBody(CheckDeclFunc checkfn); 358 359 //===----------------------------------------------------------------------===// 360 // Internal registration functions for path-sensitive checking. 361 //===----------------------------------------------------------------------===// 362 363 typedef CheckerFn<void (const Stmt *, CheckerContext &)> CheckStmtFunc; 364 365 typedef CheckerFn<void (const ObjCMethodCall &, CheckerContext &)> 366 CheckObjCMessageFunc; 367 368 typedef CheckerFn<void (const CallEvent &, CheckerContext &)> 369 CheckCallFunc; 370 371 typedef CheckerFn<void (const SVal &location, bool isLoad, 372 const Stmt *S, 373 CheckerContext &)> 374 CheckLocationFunc; 375 376 typedef CheckerFn<void (const SVal &location, const SVal &val, 377 const Stmt *S, CheckerContext &)> 378 CheckBindFunc; 379 380 typedef CheckerFn<void (ExplodedGraph &, BugReporter &, ExprEngine &)> 381 CheckEndAnalysisFunc; 382 383 typedef CheckerFn<void (CheckerContext &)> 384 CheckEndPathFunc; 385 386 typedef CheckerFn<void (const Stmt *, CheckerContext &)> 387 CheckBranchConditionFunc; 388 389 typedef CheckerFn<void (SymbolReaper &, CheckerContext &)> 390 CheckDeadSymbolsFunc; 391 392 typedef CheckerFn<void (ProgramStateRef,SymbolReaper &)> CheckLiveSymbolsFunc; 393 394 typedef CheckerFn<ProgramStateRef (ProgramStateRef, 395 const StoreManager::InvalidatedSymbols *symbols, 396 ArrayRef<const MemRegion *> ExplicitRegions, 397 ArrayRef<const MemRegion *> Regions, 398 const CallEvent *Call)> 399 CheckRegionChangesFunc; 400 401 typedef CheckerFn<bool (ProgramStateRef)> WantsRegionChangeUpdateFunc; 402 403 typedef CheckerFn<ProgramStateRef (ProgramStateRef, 404 const SVal &cond, bool assumption)> 405 EvalAssumeFunc; 406 407 typedef CheckerFn<bool (const CallExpr *, CheckerContext &)> 408 EvalCallFunc; 409 410 typedef CheckerFn<bool (const CallExpr *, ExprEngine &Eng, 411 ExplodedNode *Pred, 412 ExplodedNodeSet &Dst)> 413 InlineCallFunc; 414 415 typedef CheckerFn<void (const TranslationUnitDecl *, 416 AnalysisManager&, BugReporter &)> 417 CheckEndOfTranslationUnit; 418 419 typedef bool (*HandlesStmtFunc)(const Stmt *D); 420 void _registerForPreStmt(CheckStmtFunc checkfn, 421 HandlesStmtFunc isForStmtFn); 422 void _registerForPostStmt(CheckStmtFunc checkfn, 423 HandlesStmtFunc isForStmtFn); 424 425 void _registerForPreObjCMessage(CheckObjCMessageFunc checkfn); 426 void _registerForPostObjCMessage(CheckObjCMessageFunc checkfn); 427 428 void _registerForPreCall(CheckCallFunc checkfn); 429 void _registerForPostCall(CheckCallFunc checkfn); 430 431 void _registerForLocation(CheckLocationFunc checkfn); 432 433 void _registerForBind(CheckBindFunc checkfn); 434 435 void _registerForEndAnalysis(CheckEndAnalysisFunc checkfn); 436 437 void _registerForEndPath(CheckEndPathFunc checkfn); 438 439 void _registerForBranchCondition(CheckBranchConditionFunc checkfn); 440 441 void _registerForLiveSymbols(CheckLiveSymbolsFunc checkfn); 442 443 void _registerForDeadSymbols(CheckDeadSymbolsFunc checkfn); 444 445 void _registerForRegionChanges(CheckRegionChangesFunc checkfn, 446 WantsRegionChangeUpdateFunc wantUpdateFn); 447 448 void _registerForEvalAssume(EvalAssumeFunc checkfn); 449 450 void _registerForEvalCall(EvalCallFunc checkfn); 451 452 void _registerForInlineCall(InlineCallFunc checkfn); 453 454 void _registerForEndOfTranslationUnit(CheckEndOfTranslationUnit checkfn); 455 456 //===----------------------------------------------------------------------===// 457 // Internal registration functions for events. 458 //===----------------------------------------------------------------------===// 459 460 typedef void *EventTag; 461 typedef CheckerFn<void (const void *event)> CheckEventFunc; 462 463 template <typename EVENT> 464 void _registerListenerForEvent(CheckEventFunc checkfn) { 465 EventInfo &info = Events[getTag<EVENT>()]; 466 info.Checkers.push_back(checkfn); 467 } 468 469 template <typename EVENT> 470 void _registerDispatcherForEvent() { 471 EventInfo &info = Events[getTag<EVENT>()]; 472 info.HasDispatcher = true; 473 } 474 475 template <typename EVENT> 476 void _dispatchEvent(const EVENT &event) const { 477 EventsTy::const_iterator I = Events.find(getTag<EVENT>()); 478 if (I == Events.end()) 479 return; 480 const EventInfo &info = I->second; 481 for (unsigned i = 0, e = info.Checkers.size(); i != e; ++i) 482 info.Checkers[i](&event); 483 } 484 485 //===----------------------------------------------------------------------===// 486 // Implementation details. 487 //===----------------------------------------------------------------------===// 488 489 private: 490 template <typename CHECKER> 491 static void destruct(void *obj) { delete static_cast<CHECKER *>(obj); } 492 493 template <typename T> 494 static void *getTag() { static int tag; return &tag; } 495 496 llvm::DenseMap<CheckerTag, CheckerRef> CheckerTags; 497 498 std::vector<CheckerDtor> CheckerDtors; 499 500 struct DeclCheckerInfo { 501 CheckDeclFunc CheckFn; 502 HandlesDeclFunc IsForDeclFn; 503 }; 504 std::vector<DeclCheckerInfo> DeclCheckers; 505 506 std::vector<CheckDeclFunc> BodyCheckers; 507 508 typedef SmallVector<CheckDeclFunc, 4> CachedDeclCheckers; 509 typedef llvm::DenseMap<unsigned, CachedDeclCheckers> CachedDeclCheckersMapTy; 510 CachedDeclCheckersMapTy CachedDeclCheckersMap; 511 512 struct StmtCheckerInfo { 513 CheckStmtFunc CheckFn; 514 HandlesStmtFunc IsForStmtFn; 515 bool IsPreVisit; 516 }; 517 std::vector<StmtCheckerInfo> StmtCheckers; 518 519 struct CachedStmtCheckersKey { 520 unsigned StmtKind; 521 bool IsPreVisit; 522 523 CachedStmtCheckersKey() : StmtKind(0), IsPreVisit(0) { } 524 CachedStmtCheckersKey(unsigned stmtKind, bool isPreVisit) 525 : StmtKind(stmtKind), IsPreVisit(isPreVisit) { } 526 527 static CachedStmtCheckersKey getSentinel() { 528 return CachedStmtCheckersKey(~0U, 0); 529 } 530 unsigned getHashValue() const { 531 llvm::FoldingSetNodeID ID; 532 ID.AddInteger(StmtKind); 533 ID.AddBoolean(IsPreVisit); 534 return ID.ComputeHash(); 535 } 536 bool operator==(const CachedStmtCheckersKey &RHS) const { 537 return StmtKind == RHS.StmtKind && IsPreVisit == RHS.IsPreVisit; 538 } 539 }; 540 friend struct llvm::DenseMapInfo<CachedStmtCheckersKey>; 541 542 typedef SmallVector<CheckStmtFunc, 4> CachedStmtCheckers; 543 typedef llvm::DenseMap<CachedStmtCheckersKey, CachedStmtCheckers> 544 CachedStmtCheckersMapTy; 545 CachedStmtCheckersMapTy CachedStmtCheckersMap; 546 547 CachedStmtCheckers *getCachedStmtCheckersFor(const Stmt *S, bool isPreVisit); 548 549 std::vector<CheckObjCMessageFunc> PreObjCMessageCheckers; 550 std::vector<CheckObjCMessageFunc> PostObjCMessageCheckers; 551 552 std::vector<CheckCallFunc> PreCallCheckers; 553 std::vector<CheckCallFunc> PostCallCheckers; 554 555 std::vector<CheckLocationFunc> LocationCheckers; 556 557 std::vector<CheckBindFunc> BindCheckers; 558 559 std::vector<CheckEndAnalysisFunc> EndAnalysisCheckers; 560 561 std::vector<CheckEndPathFunc> EndPathCheckers; 562 563 std::vector<CheckBranchConditionFunc> BranchConditionCheckers; 564 565 std::vector<CheckLiveSymbolsFunc> LiveSymbolsCheckers; 566 567 std::vector<CheckDeadSymbolsFunc> DeadSymbolsCheckers; 568 569 struct RegionChangesCheckerInfo { 570 CheckRegionChangesFunc CheckFn; 571 WantsRegionChangeUpdateFunc WantUpdateFn; 572 }; 573 std::vector<RegionChangesCheckerInfo> RegionChangesCheckers; 574 575 std::vector<EvalAssumeFunc> EvalAssumeCheckers; 576 577 std::vector<EvalCallFunc> EvalCallCheckers; 578 579 std::vector<InlineCallFunc> InlineCallCheckers; 580 581 std::vector<CheckEndOfTranslationUnit> EndOfTranslationUnitCheckers; 582 583 struct EventInfo { 584 SmallVector<CheckEventFunc, 4> Checkers; 585 bool HasDispatcher; 586 EventInfo() : HasDispatcher(false) { } 587 }; 588 589 typedef llvm::DenseMap<EventTag, EventInfo> EventsTy; 590 EventsTy Events; 591 }; 592 593 } // end ento namespace 594 595 } // end clang namespace 596 597 namespace llvm { 598 /// Define DenseMapInfo so that CachedStmtCheckersKey can be used as key 599 /// in DenseMap and DenseSets. 600 template <> 601 struct DenseMapInfo<clang::ento::CheckerManager::CachedStmtCheckersKey> { 602 static inline clang::ento::CheckerManager::CachedStmtCheckersKey 603 getEmptyKey() { 604 return clang::ento::CheckerManager::CachedStmtCheckersKey(); 605 } 606 static inline clang::ento::CheckerManager::CachedStmtCheckersKey 607 getTombstoneKey() { 608 return clang::ento::CheckerManager::CachedStmtCheckersKey::getSentinel(); 609 } 610 611 static unsigned 612 getHashValue(clang::ento::CheckerManager::CachedStmtCheckersKey S) { 613 return S.getHashValue(); 614 } 615 616 static bool isEqual(clang::ento::CheckerManager::CachedStmtCheckersKey LHS, 617 clang::ento::CheckerManager::CachedStmtCheckersKey RHS) { 618 return LHS == RHS; 619 } 620 }; 621 } // end namespace llvm 622 623 #endif 624