clang API Documentation

CheckerManager.h
Go to the documentation of this file.
00001 //===--- CheckerManager.h - Static Analyzer Checker Manager -----*- C++ -*-===//
00002 //
00003 //                     The LLVM Compiler Infrastructure
00004 //
00005 // This file is distributed under the University of Illinois Open Source
00006 // License. See LICENSE.TXT for details.
00007 //
00008 //===----------------------------------------------------------------------===//
00009 //
00010 // Defines the Static Analyzer Checker Manager.
00011 //
00012 //===----------------------------------------------------------------------===//
00013 
00014 #ifndef LLVM_CLANG_STATICANALYZER_CORE_CHECKERMANAGER_H
00015 #define LLVM_CLANG_STATICANALYZER_CORE_CHECKERMANAGER_H
00016 
00017 #include "clang/Analysis/ProgramPoint.h"
00018 #include "clang/Basic/LangOptions.h"
00019 #include "clang/StaticAnalyzer/Core/AnalyzerOptions.h"
00020 #include "clang/StaticAnalyzer/Core/PathSensitive/Store.h"
00021 #include "llvm/ADT/DenseMap.h"
00022 #include "llvm/ADT/SmallVector.h"
00023 #include <vector>
00024 
00025 namespace clang {
00026   class Decl;
00027   class Stmt;
00028   class CallExpr;
00029 
00030 namespace ento {
00031   class CheckerBase;
00032   class CheckerRegistry;
00033   class ExprEngine;
00034   class AnalysisManager;
00035   class BugReporter;
00036   class CheckerContext;
00037   class ObjCMethodCall;
00038   class SVal;
00039   class ExplodedNode;
00040   class ExplodedNodeSet;
00041   class ExplodedGraph;
00042   class ProgramState;
00043   class NodeBuilder;
00044   struct NodeBuilderContext;
00045   class MemRegion;
00046   class SymbolReaper;
00047 
00048 template <typename T> class CheckerFn;
00049 
00050 template <typename RET, typename P1, typename P2, typename P3, typename P4,
00051           typename P5>
00052 class CheckerFn<RET(P1, P2, P3, P4, P5)> {
00053   typedef RET (*Func)(void *, P1, P2, P3, P4, P5);
00054   Func Fn;
00055 public:
00056   CheckerBase *Checker;
00057   CheckerFn(CheckerBase *checker, Func fn) : Fn(fn), Checker(checker) { }
00058   RET operator()(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5) const {
00059     return Fn(Checker, p1, p2, p3, p4, p5);
00060   }
00061 };
00062 
00063 template <typename RET, typename P1, typename P2, typename P3, typename P4>
00064 class CheckerFn<RET(P1, P2, P3, P4)> {
00065   typedef RET (*Func)(void *, P1, P2, P3, P4);
00066   Func Fn;
00067 public:
00068   CheckerBase *Checker;
00069   CheckerFn(CheckerBase *checker, Func fn) : Fn(fn), Checker(checker) { }
00070   RET operator()(P1 p1, P2 p2, P3 p3, P4 p4) const { 
00071     return Fn(Checker, p1, p2, p3, p4);
00072   } 
00073 };
00074 
00075 template <typename RET, typename P1, typename P2, typename P3>
00076 class CheckerFn<RET(P1, P2, P3)> {
00077   typedef RET (*Func)(void *, P1, P2, P3);
00078   Func Fn;
00079 public:
00080   CheckerBase *Checker;
00081   CheckerFn(CheckerBase *checker, Func fn) : Fn(fn), Checker(checker) { }
00082   RET operator()(P1 p1, P2 p2, P3 p3) const { return Fn(Checker, p1, p2, p3); } 
00083 };
00084 
00085 template <typename RET, typename P1, typename P2>
00086 class CheckerFn<RET(P1, P2)> {
00087   typedef RET (*Func)(void *, P1, P2);
00088   Func Fn;
00089 public:
00090   CheckerBase *Checker;
00091   CheckerFn(CheckerBase *checker, Func fn) : Fn(fn), Checker(checker) { }
00092   RET operator()(P1 p1, P2 p2) const { return Fn(Checker, p1, p2); } 
00093 };
00094 
00095 template <typename RET, typename P1>
00096 class CheckerFn<RET(P1)> {
00097   typedef RET (*Func)(void *, P1);
00098   Func Fn;
00099 public:
00100   CheckerBase *Checker;
00101   CheckerFn(CheckerBase *checker, Func fn) : Fn(fn), Checker(checker) { }
00102   RET operator()(P1 p1) const { return Fn(Checker, p1); } 
00103 };
00104 
00105 template <typename RET>
00106 class CheckerFn<RET()> {
00107   typedef RET (*Func)(void *);
00108   Func Fn;
00109 public:
00110   CheckerBase *Checker;
00111   CheckerFn(CheckerBase *checker, Func fn) : Fn(fn), Checker(checker) { }
00112   RET operator()() const { return Fn(Checker); } 
00113 };
00114 
00115 /// \brief Describes the different reasons a pointer escapes
00116 /// during analysis.
00117 enum PointerEscapeKind {
00118   /// A pointer escapes due to binding its value to a location
00119   /// that the analyzer cannot track.
00120   PSK_EscapeOnBind,
00121 
00122   /// The pointer has been passed to a function call directly.
00123   PSK_DirectEscapeOnCall,
00124 
00125   /// The pointer has been passed to a function indirectly.
00126   /// For example, the pointer is accessible through an
00127   /// argument to a function.
00128   PSK_IndirectEscapeOnCall,
00129 
00130   /// The reason for pointer escape is unknown. For example, 
00131   /// a region containing this pointer is invalidated.
00132   PSK_EscapeOther
00133 };
00134 
00135 // This wrapper is used to ensure that only StringRefs originating from the
00136 // CheckerRegistry are used as check names. We want to make sure all check
00137 // name strings have a lifetime that keeps them alive at least until the path
00138 // diagnostics have been processed.
00139 class CheckName {
00140   StringRef Name;
00141   friend class ::clang::ento::CheckerRegistry;
00142   explicit CheckName(StringRef Name) : Name(Name) {}
00143 
00144 public:
00145   CheckName() {}
00146   CheckName(const CheckName &Other) : Name(Other.Name) {}
00147   StringRef getName() const { return Name; }
00148 };
00149 
00150 class CheckerManager {
00151   const LangOptions LangOpts;
00152   AnalyzerOptionsRef AOptions;
00153   CheckName CurrentCheckName;
00154 
00155 public:
00156   CheckerManager(const LangOptions &langOpts,
00157                  AnalyzerOptionsRef AOptions)
00158     : LangOpts(langOpts),
00159       AOptions(AOptions) {}
00160 
00161   ~CheckerManager();
00162 
00163   void setCurrentCheckName(CheckName name) { CurrentCheckName = name; }
00164   CheckName getCurrentCheckName() const { return CurrentCheckName; }
00165 
00166   bool hasPathSensitiveCheckers() const;
00167 
00168   void finishedCheckerRegistration();
00169 
00170   const LangOptions &getLangOpts() const { return LangOpts; }
00171   AnalyzerOptions &getAnalyzerOptions() { return *AOptions; }
00172 
00173   typedef CheckerBase *CheckerRef;
00174   typedef const void *CheckerTag;
00175   typedef CheckerFn<void ()> CheckerDtor;
00176 
00177 //===----------------------------------------------------------------------===//
00178 // registerChecker
00179 //===----------------------------------------------------------------------===//
00180 
00181   /// \brief Used to register checkers.
00182   ///
00183   /// \returns a pointer to the checker object.
00184   template <typename CHECKER>
00185   CHECKER *registerChecker() {
00186     CheckerTag tag = getTag<CHECKER>();
00187     CheckerRef &ref = CheckerTags[tag];
00188     if (ref)
00189       return static_cast<CHECKER *>(ref); // already registered.
00190 
00191     CHECKER *checker = new CHECKER();
00192     checker->Name = CurrentCheckName;
00193     CheckerDtors.push_back(CheckerDtor(checker, destruct<CHECKER>));
00194     CHECKER::_register(checker, *this);
00195     ref = checker;
00196     return checker;
00197   }
00198 
00199   template <typename CHECKER>
00200   CHECKER *registerChecker(AnalyzerOptions &AOpts) {
00201     CheckerTag tag = getTag<CHECKER>();
00202     CheckerRef &ref = CheckerTags[tag];
00203     if (ref)
00204       return static_cast<CHECKER *>(ref); // already registered.
00205 
00206     CHECKER *checker = new CHECKER(AOpts);
00207     checker->Name = CurrentCheckName;
00208     CheckerDtors.push_back(CheckerDtor(checker, destruct<CHECKER>));
00209     CHECKER::_register(checker, *this);
00210     ref = checker;
00211     return checker;
00212   }
00213 
00214 //===----------------------------------------------------------------------===//
00215 // Functions for running checkers for AST traversing..
00216 //===----------------------------------------------------------------------===//
00217 
00218   /// \brief Run checkers handling Decls.
00219   void runCheckersOnASTDecl(const Decl *D, AnalysisManager& mgr,
00220                             BugReporter &BR);
00221 
00222   /// \brief Run checkers handling Decls containing a Stmt body.
00223   void runCheckersOnASTBody(const Decl *D, AnalysisManager& mgr,
00224                             BugReporter &BR);
00225 
00226 //===----------------------------------------------------------------------===//
00227 // Functions for running checkers for path-sensitive checking.
00228 //===----------------------------------------------------------------------===//
00229 
00230   /// \brief Run checkers for pre-visiting Stmts.
00231   ///
00232   /// The notification is performed for every explored CFGElement, which does
00233   /// not include the control flow statements such as IfStmt.
00234   ///
00235   /// \sa runCheckersForBranchCondition, runCheckersForPostStmt
00236   void runCheckersForPreStmt(ExplodedNodeSet &Dst,
00237                              const ExplodedNodeSet &Src,
00238                              const Stmt *S,
00239                              ExprEngine &Eng) {
00240     runCheckersForStmt(/*isPreVisit=*/true, Dst, Src, S, Eng);
00241   }
00242 
00243   /// \brief Run checkers for post-visiting Stmts.
00244   ///
00245   /// The notification is performed for every explored CFGElement, which does
00246   /// not include the control flow statements such as IfStmt.
00247   ///
00248   /// \sa runCheckersForBranchCondition, runCheckersForPreStmt
00249   void runCheckersForPostStmt(ExplodedNodeSet &Dst,
00250                               const ExplodedNodeSet &Src,
00251                               const Stmt *S,
00252                               ExprEngine &Eng,
00253                               bool wasInlined = false) {
00254     runCheckersForStmt(/*isPreVisit=*/false, Dst, Src, S, Eng, wasInlined);
00255   }
00256 
00257   /// \brief Run checkers for visiting Stmts.
00258   void runCheckersForStmt(bool isPreVisit,
00259                           ExplodedNodeSet &Dst, const ExplodedNodeSet &Src,
00260                           const Stmt *S, ExprEngine &Eng,
00261                           bool wasInlined = false);
00262 
00263   /// \brief Run checkers for pre-visiting obj-c messages.
00264   void runCheckersForPreObjCMessage(ExplodedNodeSet &Dst,
00265                                     const ExplodedNodeSet &Src,
00266                                     const ObjCMethodCall &msg,
00267                                     ExprEngine &Eng) {
00268     runCheckersForObjCMessage(/*isPreVisit=*/true, Dst, Src, msg, Eng);
00269   }
00270 
00271   /// \brief Run checkers for post-visiting obj-c messages.
00272   void runCheckersForPostObjCMessage(ExplodedNodeSet &Dst,
00273                                      const ExplodedNodeSet &Src,
00274                                      const ObjCMethodCall &msg,
00275                                      ExprEngine &Eng,
00276                                      bool wasInlined = false) {
00277     runCheckersForObjCMessage(/*isPreVisit=*/false, Dst, Src, msg, Eng,
00278                               wasInlined);
00279   }
00280 
00281   /// \brief Run checkers for visiting obj-c messages.
00282   void runCheckersForObjCMessage(bool isPreVisit,
00283                                  ExplodedNodeSet &Dst,
00284                                  const ExplodedNodeSet &Src,
00285                                  const ObjCMethodCall &msg, ExprEngine &Eng,
00286                                  bool wasInlined = false);
00287 
00288   /// \brief Run checkers for pre-visiting obj-c messages.
00289   void runCheckersForPreCall(ExplodedNodeSet &Dst, const ExplodedNodeSet &Src,
00290                              const CallEvent &Call, ExprEngine &Eng) {
00291     runCheckersForCallEvent(/*isPreVisit=*/true, Dst, Src, Call, Eng);
00292   }
00293 
00294   /// \brief Run checkers for post-visiting obj-c messages.
00295   void runCheckersForPostCall(ExplodedNodeSet &Dst, const ExplodedNodeSet &Src,
00296                               const CallEvent &Call, ExprEngine &Eng,
00297                               bool wasInlined = false) {
00298     runCheckersForCallEvent(/*isPreVisit=*/false, Dst, Src, Call, Eng,
00299                             wasInlined);
00300   }
00301 
00302   /// \brief Run checkers for visiting obj-c messages.
00303   void runCheckersForCallEvent(bool isPreVisit, ExplodedNodeSet &Dst,
00304                                const ExplodedNodeSet &Src,
00305                                const CallEvent &Call, ExprEngine &Eng,
00306                                bool wasInlined = false);
00307 
00308   /// \brief Run checkers for load/store of a location.
00309   void runCheckersForLocation(ExplodedNodeSet &Dst,
00310                               const ExplodedNodeSet &Src,
00311                               SVal location,
00312                               bool isLoad,
00313                               const Stmt *NodeEx,
00314                               const Stmt *BoundEx,
00315                               ExprEngine &Eng);
00316 
00317   /// \brief Run checkers for binding of a value to a location.
00318   void runCheckersForBind(ExplodedNodeSet &Dst,
00319                           const ExplodedNodeSet &Src,
00320                           SVal location, SVal val,
00321                           const Stmt *S, ExprEngine &Eng,
00322                           const ProgramPoint &PP);
00323 
00324   /// \brief Run checkers for end of analysis.
00325   void runCheckersForEndAnalysis(ExplodedGraph &G, BugReporter &BR,
00326                                  ExprEngine &Eng);
00327 
00328   /// \brief Run checkers on end of function.
00329   void runCheckersForEndFunction(NodeBuilderContext &BC,
00330                                  ExplodedNodeSet &Dst,
00331                                  ExplodedNode *Pred,
00332                                  ExprEngine &Eng);
00333 
00334   /// \brief Run checkers for branch condition.
00335   void runCheckersForBranchCondition(const Stmt *condition,
00336                                      ExplodedNodeSet &Dst, ExplodedNode *Pred,
00337                                      ExprEngine &Eng);
00338 
00339   /// \brief Run checkers for live symbols.
00340   ///
00341   /// Allows modifying SymbolReaper object. For example, checkers can explicitly
00342   /// register symbols of interest as live. These symbols will not be marked
00343   /// dead and removed.
00344   void runCheckersForLiveSymbols(ProgramStateRef state,
00345                                  SymbolReaper &SymReaper);
00346 
00347   /// \brief Run checkers for dead symbols.
00348   ///
00349   /// Notifies checkers when symbols become dead. For example, this allows
00350   /// checkers to aggressively clean up/reduce the checker state and produce
00351   /// precise diagnostics.
00352   void runCheckersForDeadSymbols(ExplodedNodeSet &Dst,
00353                                  const ExplodedNodeSet &Src,
00354                                  SymbolReaper &SymReaper, const Stmt *S,
00355                                  ExprEngine &Eng,
00356                                  ProgramPoint::Kind K);
00357 
00358   /// \brief True if at least one checker wants to check region changes.
00359   bool wantsRegionChangeUpdate(ProgramStateRef state);
00360 
00361   /// \brief Run checkers for region changes.
00362   ///
00363   /// This corresponds to the check::RegionChanges callback.
00364   /// \param state The current program state.
00365   /// \param invalidated A set of all symbols potentially touched by the change.
00366   /// \param ExplicitRegions The regions explicitly requested for invalidation.
00367   ///   For example, in the case of a function call, these would be arguments.
00368   /// \param Regions The transitive closure of accessible regions,
00369   ///   i.e. all regions that may have been touched by this change.
00370   /// \param Call The call expression wrapper if the regions are invalidated
00371   ///   by a call.
00372   ProgramStateRef
00373   runCheckersForRegionChanges(ProgramStateRef state,
00374                               const InvalidatedSymbols *invalidated,
00375                               ArrayRef<const MemRegion *> ExplicitRegions,
00376                               ArrayRef<const MemRegion *> Regions,
00377                               const CallEvent *Call);
00378 
00379   /// \brief Run checkers when pointers escape.
00380   ///
00381   /// This notifies the checkers about pointer escape, which occurs whenever
00382   /// the analyzer cannot track the symbol any more. For example, as a
00383   /// result of assigning a pointer into a global or when it's passed to a 
00384   /// function call the analyzer cannot model.
00385   /// 
00386   /// \param State The state at the point of escape.
00387   /// \param Escaped The list of escaped symbols.
00388   /// \param Call The corresponding CallEvent, if the symbols escape as 
00389   ///        parameters to the given call.
00390   /// \param Kind The reason of pointer escape.
00391   /// \param ITraits Information about invalidation for a particular 
00392   ///        region/symbol.
00393   /// \returns Checkers can modify the state by returning a new one.
00394   ProgramStateRef 
00395   runCheckersForPointerEscape(ProgramStateRef State,
00396                               const InvalidatedSymbols &Escaped,
00397                               const CallEvent *Call,
00398                               PointerEscapeKind Kind,
00399                              RegionAndSymbolInvalidationTraits *ITraits);
00400 
00401   /// \brief Run checkers for handling assumptions on symbolic values.
00402   ProgramStateRef runCheckersForEvalAssume(ProgramStateRef state,
00403                                            SVal Cond, bool Assumption);
00404 
00405   /// \brief Run checkers for evaluating a call.
00406   ///
00407   /// Warning: Currently, the CallEvent MUST come from a CallExpr!
00408   void runCheckersForEvalCall(ExplodedNodeSet &Dst,
00409                               const ExplodedNodeSet &Src,
00410                               const CallEvent &CE, ExprEngine &Eng);
00411   
00412   /// \brief Run checkers for the entire Translation Unit.
00413   void runCheckersOnEndOfTranslationUnit(const TranslationUnitDecl *TU,
00414                                          AnalysisManager &mgr,
00415                                          BugReporter &BR);
00416 
00417   /// \brief Run checkers for debug-printing a ProgramState.
00418   ///
00419   /// Unlike most other callbacks, any checker can simply implement the virtual
00420   /// method CheckerBase::printState if it has custom data to print.
00421   /// \param Out The output stream
00422   /// \param State The state being printed
00423   /// \param NL The preferred representation of a newline.
00424   /// \param Sep The preferred separator between different kinds of data.
00425   void runCheckersForPrintState(raw_ostream &Out, ProgramStateRef State,
00426                                 const char *NL, const char *Sep);
00427 
00428 //===----------------------------------------------------------------------===//
00429 // Internal registration functions for AST traversing.
00430 //===----------------------------------------------------------------------===//
00431 
00432   // Functions used by the registration mechanism, checkers should not touch
00433   // these directly.
00434 
00435   typedef CheckerFn<void (const Decl *, AnalysisManager&, BugReporter &)>
00436       CheckDeclFunc;
00437 
00438   typedef bool (*HandlesDeclFunc)(const Decl *D);
00439   void _registerForDecl(CheckDeclFunc checkfn, HandlesDeclFunc isForDeclFn);
00440 
00441   void _registerForBody(CheckDeclFunc checkfn);
00442 
00443 //===----------------------------------------------------------------------===//
00444 // Internal registration functions for path-sensitive checking.
00445 //===----------------------------------------------------------------------===//
00446 
00447   typedef CheckerFn<void (const Stmt *, CheckerContext &)> CheckStmtFunc;
00448   
00449   typedef CheckerFn<void (const ObjCMethodCall &, CheckerContext &)>
00450       CheckObjCMessageFunc;
00451 
00452   typedef CheckerFn<void (const CallEvent &, CheckerContext &)>
00453       CheckCallFunc;
00454   
00455   typedef CheckerFn<void (const SVal &location, bool isLoad,
00456                           const Stmt *S,
00457                           CheckerContext &)>
00458       CheckLocationFunc;
00459   
00460   typedef CheckerFn<void (const SVal &location, const SVal &val, 
00461                           const Stmt *S, CheckerContext &)> 
00462       CheckBindFunc;
00463   
00464   typedef CheckerFn<void (ExplodedGraph &, BugReporter &, ExprEngine &)>
00465       CheckEndAnalysisFunc;
00466   
00467   typedef CheckerFn<void (CheckerContext &)>
00468       CheckEndFunctionFunc;
00469   
00470   typedef CheckerFn<void (const Stmt *, CheckerContext &)>
00471       CheckBranchConditionFunc;
00472   
00473   typedef CheckerFn<void (SymbolReaper &, CheckerContext &)>
00474       CheckDeadSymbolsFunc;
00475   
00476   typedef CheckerFn<void (ProgramStateRef,SymbolReaper &)> CheckLiveSymbolsFunc;
00477   
00478   typedef CheckerFn<ProgramStateRef (ProgramStateRef,
00479                                 const InvalidatedSymbols *symbols,
00480                                 ArrayRef<const MemRegion *> ExplicitRegions,
00481                                 ArrayRef<const MemRegion *> Regions,
00482                                 const CallEvent *Call)>
00483       CheckRegionChangesFunc;
00484   
00485   typedef CheckerFn<bool (ProgramStateRef)> WantsRegionChangeUpdateFunc;
00486 
00487   typedef CheckerFn<ProgramStateRef (ProgramStateRef,
00488                                      const InvalidatedSymbols &Escaped,
00489                                      const CallEvent *Call,
00490                                      PointerEscapeKind Kind,
00491                                      RegionAndSymbolInvalidationTraits *ITraits)>
00492       CheckPointerEscapeFunc;
00493   
00494   typedef CheckerFn<ProgramStateRef (ProgramStateRef,
00495                                           const SVal &cond, bool assumption)>
00496       EvalAssumeFunc;
00497   
00498   typedef CheckerFn<bool (const CallExpr *, CheckerContext &)>
00499       EvalCallFunc;
00500 
00501   typedef CheckerFn<void (const TranslationUnitDecl *,
00502                           AnalysisManager&, BugReporter &)>
00503       CheckEndOfTranslationUnit;
00504 
00505   typedef bool (*HandlesStmtFunc)(const Stmt *D);
00506   void _registerForPreStmt(CheckStmtFunc checkfn,
00507                            HandlesStmtFunc isForStmtFn);
00508   void _registerForPostStmt(CheckStmtFunc checkfn,
00509                             HandlesStmtFunc isForStmtFn);
00510 
00511   void _registerForPreObjCMessage(CheckObjCMessageFunc checkfn);
00512   void _registerForPostObjCMessage(CheckObjCMessageFunc checkfn);
00513 
00514   void _registerForPreCall(CheckCallFunc checkfn);
00515   void _registerForPostCall(CheckCallFunc checkfn);
00516 
00517   void _registerForLocation(CheckLocationFunc checkfn);
00518 
00519   void _registerForBind(CheckBindFunc checkfn);
00520 
00521   void _registerForEndAnalysis(CheckEndAnalysisFunc checkfn);
00522 
00523   void _registerForEndFunction(CheckEndFunctionFunc checkfn);
00524 
00525   void _registerForBranchCondition(CheckBranchConditionFunc checkfn);
00526 
00527   void _registerForLiveSymbols(CheckLiveSymbolsFunc checkfn);
00528 
00529   void _registerForDeadSymbols(CheckDeadSymbolsFunc checkfn);
00530 
00531   void _registerForRegionChanges(CheckRegionChangesFunc checkfn,
00532                                  WantsRegionChangeUpdateFunc wantUpdateFn);
00533 
00534   void _registerForPointerEscape(CheckPointerEscapeFunc checkfn);
00535 
00536   void _registerForConstPointerEscape(CheckPointerEscapeFunc checkfn);
00537 
00538   void _registerForEvalAssume(EvalAssumeFunc checkfn);
00539 
00540   void _registerForEvalCall(EvalCallFunc checkfn);
00541 
00542   void _registerForEndOfTranslationUnit(CheckEndOfTranslationUnit checkfn);
00543 
00544 //===----------------------------------------------------------------------===//
00545 // Internal registration functions for events.
00546 //===----------------------------------------------------------------------===//
00547 
00548   typedef void *EventTag;
00549   typedef CheckerFn<void (const void *event)> CheckEventFunc;
00550 
00551   template <typename EVENT>
00552   void _registerListenerForEvent(CheckEventFunc checkfn) {
00553     EventInfo &info = Events[getTag<EVENT>()];
00554     info.Checkers.push_back(checkfn);    
00555   }
00556 
00557   template <typename EVENT>
00558   void _registerDispatcherForEvent() {
00559     EventInfo &info = Events[getTag<EVENT>()];
00560     info.HasDispatcher = true;
00561   }
00562 
00563   template <typename EVENT>
00564   void _dispatchEvent(const EVENT &event) const {
00565     EventsTy::const_iterator I = Events.find(getTag<EVENT>());
00566     if (I == Events.end())
00567       return;
00568     const EventInfo &info = I->second;
00569     for (unsigned i = 0, e = info.Checkers.size(); i != e; ++i)
00570       info.Checkers[i](&event);
00571   }
00572 
00573 //===----------------------------------------------------------------------===//
00574 // Implementation details.
00575 //===----------------------------------------------------------------------===//
00576 
00577 private:
00578   template <typename CHECKER>
00579   static void destruct(void *obj) { delete static_cast<CHECKER *>(obj); }
00580 
00581   template <typename T>
00582   static void *getTag() { static int tag; return &tag; }
00583 
00584   llvm::DenseMap<CheckerTag, CheckerRef> CheckerTags;
00585 
00586   std::vector<CheckerDtor> CheckerDtors;
00587 
00588   struct DeclCheckerInfo {
00589     CheckDeclFunc CheckFn;
00590     HandlesDeclFunc IsForDeclFn;
00591   };
00592   std::vector<DeclCheckerInfo> DeclCheckers;
00593 
00594   std::vector<CheckDeclFunc> BodyCheckers;
00595 
00596   typedef SmallVector<CheckDeclFunc, 4> CachedDeclCheckers;
00597   typedef llvm::DenseMap<unsigned, CachedDeclCheckers> CachedDeclCheckersMapTy;
00598   CachedDeclCheckersMapTy CachedDeclCheckersMap;
00599 
00600   struct StmtCheckerInfo {
00601     CheckStmtFunc CheckFn;
00602     HandlesStmtFunc IsForStmtFn;
00603     bool IsPreVisit;
00604   };
00605   std::vector<StmtCheckerInfo> StmtCheckers;
00606 
00607   typedef SmallVector<CheckStmtFunc, 4> CachedStmtCheckers;
00608   typedef llvm::DenseMap<unsigned, CachedStmtCheckers> CachedStmtCheckersMapTy;
00609   CachedStmtCheckersMapTy CachedStmtCheckersMap;
00610 
00611   const CachedStmtCheckers &getCachedStmtCheckersFor(const Stmt *S,
00612                                                      bool isPreVisit);
00613 
00614   std::vector<CheckObjCMessageFunc> PreObjCMessageCheckers;
00615   std::vector<CheckObjCMessageFunc> PostObjCMessageCheckers;
00616 
00617   std::vector<CheckCallFunc> PreCallCheckers;
00618   std::vector<CheckCallFunc> PostCallCheckers;
00619 
00620   std::vector<CheckLocationFunc> LocationCheckers;
00621 
00622   std::vector<CheckBindFunc> BindCheckers;
00623 
00624   std::vector<CheckEndAnalysisFunc> EndAnalysisCheckers;
00625 
00626   std::vector<CheckEndFunctionFunc> EndFunctionCheckers;
00627 
00628   std::vector<CheckBranchConditionFunc> BranchConditionCheckers;
00629 
00630   std::vector<CheckLiveSymbolsFunc> LiveSymbolsCheckers;
00631 
00632   std::vector<CheckDeadSymbolsFunc> DeadSymbolsCheckers;
00633 
00634   struct RegionChangesCheckerInfo {
00635     CheckRegionChangesFunc CheckFn;
00636     WantsRegionChangeUpdateFunc WantUpdateFn;
00637   };
00638   std::vector<RegionChangesCheckerInfo> RegionChangesCheckers;
00639 
00640   std::vector<CheckPointerEscapeFunc> PointerEscapeCheckers;
00641 
00642   std::vector<EvalAssumeFunc> EvalAssumeCheckers;
00643 
00644   std::vector<EvalCallFunc> EvalCallCheckers;
00645 
00646   std::vector<CheckEndOfTranslationUnit> EndOfTranslationUnitCheckers;
00647 
00648   struct EventInfo {
00649     SmallVector<CheckEventFunc, 4> Checkers;
00650     bool HasDispatcher;
00651     EventInfo() : HasDispatcher(false) { }
00652   };
00653   
00654   typedef llvm::DenseMap<EventTag, EventInfo> EventsTy;
00655   EventsTy Events;
00656 };
00657 
00658 } // end ento namespace
00659 
00660 } // end clang namespace
00661 
00662 #endif