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