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