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