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/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