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_SA_CORE_CHECKERMANAGER_H
00015 #define LLVM_CLANG_SA_CORE_CHECKERMANAGER_H
00016 
00017 #include "clang/Basic/LangOptions.h"
00018 #include "llvm/ADT/SmallVector.h"
00019 #include "llvm/ADT/DenseMap.h"
00020 #include "llvm/ADT/FoldingSet.h"
00021 #include "clang/StaticAnalyzer/Core/PathSensitive/Store.h"
00022 #include "clang/Analysis/ProgramPoint.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 ExprEngine;
00033   class AnalysisManager;
00034   class BugReporter;
00035   class CheckerContext;
00036   class ObjCMessage;
00037   class SVal;
00038   class ExplodedNode;
00039   class ExplodedNodeSet;
00040   class ExplodedGraph;
00041   class ProgramState;
00042   class NodeBuilder;
00043   struct NodeBuilderContext;
00044   class MemRegion;
00045   class SymbolReaper;
00046 
00047 class GraphExpander {
00048 public:
00049   virtual ~GraphExpander();
00050   virtual void expandGraph(ExplodedNodeSet &Dst, ExplodedNode *Pred) = 0;
00051 };
00052 
00053 template <typename T> class CheckerFn;
00054 
00055 template <typename RET, typename P1, typename P2, typename P3, typename P4,
00056           typename P5>
00057 class CheckerFn<RET(P1, P2, P3, P4, P5)> {
00058   typedef RET (*Func)(void *, P1, P2, P3, P4, P5);
00059   Func Fn;
00060 public:
00061   CheckerBase *Checker;
00062   CheckerFn(CheckerBase *checker, Func fn) : Fn(fn), Checker(checker) { }
00063   RET operator()(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5) const {
00064     return Fn(Checker, p1, p2, p3, p4, p5);
00065   }
00066 };
00067 
00068 template <typename RET, typename P1, typename P2, typename P3, typename P4>
00069 class CheckerFn<RET(P1, P2, P3, P4)> {
00070   typedef RET (*Func)(void *, P1, P2, P3, P4);
00071   Func Fn;
00072 public:
00073   CheckerBase *Checker;
00074   CheckerFn(CheckerBase *checker, Func fn) : Fn(fn), Checker(checker) { }
00075   RET operator()(P1 p1, P2 p2, P3 p3, P4 p4) const { 
00076     return Fn(Checker, p1, p2, p3, p4);
00077   } 
00078 };
00079 
00080 template <typename RET, typename P1, typename P2, typename P3>
00081 class CheckerFn<RET(P1, P2, P3)> {
00082   typedef RET (*Func)(void *, P1, P2, P3);
00083   Func Fn;
00084 public:
00085   CheckerBase *Checker;
00086   CheckerFn(CheckerBase *checker, Func fn) : Fn(fn), Checker(checker) { }
00087   RET operator()(P1 p1, P2 p2, P3 p3) const { return Fn(Checker, p1, p2, p3); } 
00088 };
00089 
00090 template <typename RET, typename P1, typename P2>
00091 class CheckerFn<RET(P1, P2)> {
00092   typedef RET (*Func)(void *, P1, P2);
00093   Func Fn;
00094 public:
00095   CheckerBase *Checker;
00096   CheckerFn(CheckerBase *checker, Func fn) : Fn(fn), Checker(checker) { }
00097   RET operator()(P1 p1, P2 p2) const { return Fn(Checker, p1, p2); } 
00098 };
00099 
00100 template <typename RET, typename P1>
00101 class CheckerFn<RET(P1)> {
00102   typedef RET (*Func)(void *, P1);
00103   Func Fn;
00104 public:
00105   CheckerBase *Checker;
00106   CheckerFn(CheckerBase *checker, Func fn) : Fn(fn), Checker(checker) { }
00107   RET operator()(P1 p1) const { return Fn(Checker, p1); } 
00108 };
00109 
00110 template <typename RET>
00111 class CheckerFn<RET()> {
00112   typedef RET (*Func)(void *);
00113   Func Fn;
00114 public:
00115   CheckerBase *Checker;
00116   CheckerFn(CheckerBase *checker, Func fn) : Fn(fn), Checker(checker) { }
00117   RET operator()() const { return Fn(Checker); } 
00118 };
00119 
00120 class CheckerManager {
00121   const LangOptions LangOpts;
00122 
00123 public:
00124   CheckerManager(const LangOptions &langOpts) : LangOpts(langOpts) { }
00125   ~CheckerManager();
00126 
00127   bool hasPathSensitiveCheckers() const;
00128 
00129   void finishedCheckerRegistration();
00130 
00131   const LangOptions &getLangOpts() const { return LangOpts; }
00132 
00133   typedef CheckerBase *CheckerRef;
00134   typedef const void *CheckerTag;
00135   typedef CheckerFn<void ()> CheckerDtor;
00136 
00137 //===----------------------------------------------------------------------===//
00138 // registerChecker
00139 //===----------------------------------------------------------------------===//
00140 
00141   /// \brief Used to register checkers.
00142   ///
00143   /// \returns a pointer to the checker object.
00144   template <typename CHECKER>
00145   CHECKER *registerChecker() {
00146     CheckerTag tag = getTag<CHECKER>();
00147     CheckerRef &ref = CheckerTags[tag];
00148     if (ref)
00149       return static_cast<CHECKER *>(ref); // already registered.
00150 
00151     CHECKER *checker = new CHECKER();
00152     CheckerDtors.push_back(CheckerDtor(checker, destruct<CHECKER>));
00153     CHECKER::_register(checker, *this);
00154     ref = checker;
00155     return checker;
00156   }
00157 
00158 //===----------------------------------------------------------------------===//
00159 // Functions for running checkers for AST traversing..
00160 //===----------------------------------------------------------------------===//
00161 
00162   /// \brief Run checkers handling Decls.
00163   void runCheckersOnASTDecl(const Decl *D, AnalysisManager& mgr,
00164                             BugReporter &BR);
00165 
00166   /// \brief Run checkers handling Decls containing a Stmt body.
00167   void runCheckersOnASTBody(const Decl *D, AnalysisManager& mgr,
00168                             BugReporter &BR);
00169 
00170 //===----------------------------------------------------------------------===//
00171 // Functions for running checkers for path-sensitive checking.
00172 //===----------------------------------------------------------------------===//
00173 
00174   /// \brief Run checkers for pre-visiting Stmts.
00175   ///
00176   /// The notification is performed for every explored CFGElement, which does
00177   /// not include the control flow statements such as IfStmt.
00178   ///
00179   /// \sa runCheckersForBranchCondition, runCheckersForPostStmt
00180   void runCheckersForPreStmt(ExplodedNodeSet &Dst,
00181                              const ExplodedNodeSet &Src,
00182                              const Stmt *S,
00183                              ExprEngine &Eng) {
00184     runCheckersForStmt(/*isPreVisit=*/true, Dst, Src, S, Eng);
00185   }
00186 
00187   /// \brief Run checkers for post-visiting Stmts.
00188   ///
00189   /// The notification is performed for every explored CFGElement, which does
00190   /// not include the control flow statements such as IfStmt.
00191   ///
00192   /// \sa runCheckersForBranchCondition, runCheckersForPreStmt
00193   void runCheckersForPostStmt(ExplodedNodeSet &Dst,
00194                               const ExplodedNodeSet &Src,
00195                               const Stmt *S,
00196                               ExprEngine &Eng,
00197                               bool wasInlined = false) {
00198     runCheckersForStmt(/*isPreVisit=*/false, Dst, Src, S, Eng, wasInlined);
00199   }
00200 
00201   /// \brief Run checkers for visiting Stmts.
00202   void runCheckersForStmt(bool isPreVisit,
00203                           ExplodedNodeSet &Dst, const ExplodedNodeSet &Src,
00204                           const Stmt *S, ExprEngine &Eng,
00205                           bool wasInlined = false);
00206 
00207   /// \brief Run checkers for pre-visiting obj-c messages.
00208   void runCheckersForPreObjCMessage(ExplodedNodeSet &Dst,
00209                                     const ExplodedNodeSet &Src,
00210                                     const ObjCMessage &msg,
00211                                     ExprEngine &Eng) {
00212     runCheckersForObjCMessage(/*isPreVisit=*/true, Dst, Src, msg, Eng);
00213   }
00214 
00215   /// \brief Run checkers for post-visiting obj-c messages.
00216   void runCheckersForPostObjCMessage(ExplodedNodeSet &Dst,
00217                                      const ExplodedNodeSet &Src,
00218                                      const ObjCMessage &msg,
00219                                      ExprEngine &Eng) {
00220     runCheckersForObjCMessage(/*isPreVisit=*/false, Dst, Src, msg, Eng);
00221   }
00222 
00223   /// \brief Run checkers for visiting obj-c messages.
00224   void runCheckersForObjCMessage(bool isPreVisit,
00225                                  ExplodedNodeSet &Dst,
00226                                  const ExplodedNodeSet &Src,
00227                                  const ObjCMessage &msg, ExprEngine &Eng);
00228 
00229   /// \brief Run checkers for load/store of a location.
00230   void runCheckersForLocation(ExplodedNodeSet &Dst,
00231                               const ExplodedNodeSet &Src,
00232                               SVal location,
00233                               bool isLoad,
00234                               const Stmt *NodeEx,
00235                               const Stmt *BoundEx,
00236                               ExprEngine &Eng);
00237 
00238   /// \brief Run checkers for binding of a value to a location.
00239   void runCheckersForBind(ExplodedNodeSet &Dst,
00240                           const ExplodedNodeSet &Src,
00241                           SVal location, SVal val,
00242                           const Stmt *S, ExprEngine &Eng,
00243                           ProgramPoint::Kind PointKind);
00244 
00245   /// \brief Run checkers for end of analysis.
00246   void runCheckersForEndAnalysis(ExplodedGraph &G, BugReporter &BR,
00247                                  ExprEngine &Eng);
00248 
00249   /// \brief Run checkers for end of path.
00250   void runCheckersForEndPath(NodeBuilderContext &BC,
00251                              ExplodedNodeSet &Dst,
00252                              ExprEngine &Eng);
00253 
00254   /// \brief Run checkers for branch condition.
00255   void runCheckersForBranchCondition(const Stmt *condition,
00256                                      ExplodedNodeSet &Dst, ExplodedNode *Pred,
00257                                      ExprEngine &Eng);
00258 
00259   /// \brief Run checkers for live symbols.
00260   ///
00261   /// Allows modifying SymbolReaper object. For example, checkers can explicitly
00262   /// register symbols of interest as live. These symbols will not be marked
00263   /// dead and removed.
00264   void runCheckersForLiveSymbols(ProgramStateRef state,
00265                                  SymbolReaper &SymReaper);
00266 
00267   /// \brief Run checkers for dead symbols.
00268   ///
00269   /// Notifies checkers when symbols become dead. For example, this allows
00270   /// checkers to aggressively clean up/reduce the checker state and produce
00271   /// precise diagnostics.
00272   void runCheckersForDeadSymbols(ExplodedNodeSet &Dst,
00273                                  const ExplodedNodeSet &Src,
00274                                  SymbolReaper &SymReaper, const Stmt *S,
00275                                  ExprEngine &Eng,
00276                                  ProgramPoint::Kind K);
00277 
00278   /// \brief True if at least one checker wants to check region changes.
00279   bool wantsRegionChangeUpdate(ProgramStateRef state);
00280 
00281   /// \brief Run checkers for region changes.
00282   ///
00283   /// This corresponds to the check::RegionChanges callback.
00284   /// \param state The current program state.
00285   /// \param invalidated A set of all symbols potentially touched by the change.
00286   /// \param ExplicitRegions The regions explicitly requested for invalidation.
00287   ///   For example, in the case of a function call, these would be arguments.
00288   /// \param Regions The transitive closure of accessible regions,
00289   ///   i.e. all regions that may have been touched by this change.
00290   /// \param The call expression wrapper if the regions are invalidated by a
00291   ///   call.
00292   ProgramStateRef 
00293   runCheckersForRegionChanges(ProgramStateRef state,
00294                             const StoreManager::InvalidatedSymbols *invalidated,
00295                               ArrayRef<const MemRegion *> ExplicitRegions,
00296                               ArrayRef<const MemRegion *> Regions,
00297                               const CallOrObjCMessage *Call);
00298 
00299   /// \brief Run checkers for handling assumptions on symbolic values.
00300   ProgramStateRef runCheckersForEvalAssume(ProgramStateRef state,
00301                                                SVal Cond, bool Assumption);
00302 
00303   /// \brief Run checkers for evaluating a call.
00304   void runCheckersForEvalCall(ExplodedNodeSet &Dst,
00305                               const ExplodedNodeSet &Src,
00306                               const CallExpr *CE, ExprEngine &Eng,
00307                               GraphExpander *defaultEval = 0);
00308   
00309   /// \brief Run checkers for the entire Translation Unit.
00310   void runCheckersOnEndOfTranslationUnit(const TranslationUnitDecl *TU,
00311                                          AnalysisManager &mgr,
00312                                          BugReporter &BR);
00313 
00314   /// \brief Run checkers for debug-printing a ProgramState.
00315   ///
00316   /// Unlike most other callbacks, any checker can simply implement the virtual
00317   /// method CheckerBase::printState if it has custom data to print.
00318   /// \param Out The output stream
00319   /// \param State The state being printed
00320   /// \param NL The preferred representation of a newline.
00321   /// \param Sep The preferred separator between different kinds of data.
00322   void runCheckersForPrintState(raw_ostream &Out, ProgramStateRef State,
00323                                 const char *NL, const char *Sep);
00324 
00325 //===----------------------------------------------------------------------===//
00326 // Internal registration functions for AST traversing.
00327 //===----------------------------------------------------------------------===//
00328 
00329   // Functions used by the registration mechanism, checkers should not touch
00330   // these directly.
00331 
00332   typedef CheckerFn<void (const Decl *, AnalysisManager&, BugReporter &)>
00333       CheckDeclFunc;
00334 
00335   typedef bool (*HandlesDeclFunc)(const Decl *D);
00336   void _registerForDecl(CheckDeclFunc checkfn, HandlesDeclFunc isForDeclFn);
00337 
00338   void _registerForBody(CheckDeclFunc checkfn);
00339 
00340 //===----------------------------------------------------------------------===//
00341 // Internal registration functions for path-sensitive checking.
00342 //===----------------------------------------------------------------------===//
00343 
00344   typedef CheckerFn<void (const Stmt *, CheckerContext &)> CheckStmtFunc;
00345   
00346   typedef CheckerFn<void (const ObjCMessage &, CheckerContext &)>
00347       CheckObjCMessageFunc;
00348   
00349   typedef CheckerFn<void (const SVal &location, bool isLoad,
00350                           const Stmt *S,
00351                           CheckerContext &)>
00352       CheckLocationFunc;
00353   
00354   typedef CheckerFn<void (const SVal &location, const SVal &val, 
00355                           const Stmt *S, CheckerContext &)> 
00356       CheckBindFunc;
00357   
00358   typedef CheckerFn<void (ExplodedGraph &, BugReporter &, ExprEngine &)>
00359       CheckEndAnalysisFunc;
00360   
00361   typedef CheckerFn<void (CheckerContext &)>
00362       CheckEndPathFunc;
00363   
00364   typedef CheckerFn<void (const Stmt *, CheckerContext &)>
00365       CheckBranchConditionFunc;
00366   
00367   typedef CheckerFn<void (SymbolReaper &, CheckerContext &)>
00368       CheckDeadSymbolsFunc;
00369   
00370   typedef CheckerFn<void (ProgramStateRef,SymbolReaper &)> CheckLiveSymbolsFunc;
00371   
00372   typedef CheckerFn<ProgramStateRef (ProgramStateRef,
00373                                 const StoreManager::InvalidatedSymbols *symbols,
00374                                 ArrayRef<const MemRegion *> ExplicitRegions,
00375                                 ArrayRef<const MemRegion *> Regions,
00376                                 const CallOrObjCMessage *Call)>
00377       CheckRegionChangesFunc;
00378   
00379   typedef CheckerFn<bool (ProgramStateRef)> WantsRegionChangeUpdateFunc;
00380   
00381   typedef CheckerFn<ProgramStateRef (ProgramStateRef,
00382                                           const SVal &cond, bool assumption)>
00383       EvalAssumeFunc;
00384   
00385   typedef CheckerFn<bool (const CallExpr *, CheckerContext &)>
00386       EvalCallFunc;
00387 
00388   typedef CheckerFn<bool (const CallExpr *, ExprEngine &Eng,
00389                                             ExplodedNode *Pred,
00390                                             ExplodedNodeSet &Dst)>
00391       InlineCallFunc;
00392 
00393   typedef CheckerFn<void (const TranslationUnitDecl *,
00394                           AnalysisManager&, BugReporter &)>
00395       CheckEndOfTranslationUnit;
00396 
00397   typedef bool (*HandlesStmtFunc)(const Stmt *D);
00398   void _registerForPreStmt(CheckStmtFunc checkfn,
00399                            HandlesStmtFunc isForStmtFn);
00400   void _registerForPostStmt(CheckStmtFunc checkfn,
00401                             HandlesStmtFunc isForStmtFn);
00402 
00403   void _registerForPreObjCMessage(CheckObjCMessageFunc checkfn);
00404   void _registerForPostObjCMessage(CheckObjCMessageFunc checkfn);
00405 
00406   void _registerForLocation(CheckLocationFunc checkfn);
00407 
00408   void _registerForBind(CheckBindFunc checkfn);
00409 
00410   void _registerForEndAnalysis(CheckEndAnalysisFunc checkfn);
00411 
00412   void _registerForEndPath(CheckEndPathFunc checkfn);
00413 
00414   void _registerForBranchCondition(CheckBranchConditionFunc checkfn);
00415 
00416   void _registerForLiveSymbols(CheckLiveSymbolsFunc checkfn);
00417 
00418   void _registerForDeadSymbols(CheckDeadSymbolsFunc checkfn);
00419 
00420   void _registerForRegionChanges(CheckRegionChangesFunc checkfn,
00421                                  WantsRegionChangeUpdateFunc wantUpdateFn);
00422 
00423   void _registerForEvalAssume(EvalAssumeFunc checkfn);
00424 
00425   void _registerForEvalCall(EvalCallFunc checkfn);
00426 
00427   void _registerForInlineCall(InlineCallFunc checkfn);
00428 
00429   void _registerForEndOfTranslationUnit(CheckEndOfTranslationUnit checkfn);
00430 
00431 //===----------------------------------------------------------------------===//
00432 // Internal registration functions for events.
00433 //===----------------------------------------------------------------------===//
00434 
00435   typedef void *EventTag;
00436   typedef CheckerFn<void (const void *event)> CheckEventFunc;
00437 
00438   template <typename EVENT>
00439   void _registerListenerForEvent(CheckEventFunc checkfn) {
00440     EventInfo &info = Events[getTag<EVENT>()];
00441     info.Checkers.push_back(checkfn);    
00442   }
00443 
00444   template <typename EVENT>
00445   void _registerDispatcherForEvent() {
00446     EventInfo &info = Events[getTag<EVENT>()];
00447     info.HasDispatcher = true;
00448   }
00449 
00450   template <typename EVENT>
00451   void _dispatchEvent(const EVENT &event) const {
00452     EventsTy::const_iterator I = Events.find(getTag<EVENT>());
00453     if (I == Events.end())
00454       return;
00455     const EventInfo &info = I->second;
00456     for (unsigned i = 0, e = info.Checkers.size(); i != e; ++i)
00457       info.Checkers[i](&event);
00458   }
00459 
00460 //===----------------------------------------------------------------------===//
00461 // Implementation details.
00462 //===----------------------------------------------------------------------===//
00463 
00464 private:
00465   template <typename CHECKER>
00466   static void destruct(void *obj) { delete static_cast<CHECKER *>(obj); }
00467 
00468   template <typename T>
00469   static void *getTag() { static int tag; return &tag; }
00470 
00471   llvm::DenseMap<CheckerTag, CheckerRef> CheckerTags;
00472 
00473   std::vector<CheckerDtor> CheckerDtors;
00474 
00475   struct DeclCheckerInfo {
00476     CheckDeclFunc CheckFn;
00477     HandlesDeclFunc IsForDeclFn;
00478   };
00479   std::vector<DeclCheckerInfo> DeclCheckers;
00480 
00481   std::vector<CheckDeclFunc> BodyCheckers;
00482 
00483   typedef SmallVector<CheckDeclFunc, 4> CachedDeclCheckers;
00484   typedef llvm::DenseMap<unsigned, CachedDeclCheckers> CachedDeclCheckersMapTy;
00485   CachedDeclCheckersMapTy CachedDeclCheckersMap;
00486 
00487   struct StmtCheckerInfo {
00488     CheckStmtFunc CheckFn;
00489     HandlesStmtFunc IsForStmtFn;
00490     bool IsPreVisit;
00491   };
00492   std::vector<StmtCheckerInfo> StmtCheckers;
00493 
00494   struct CachedStmtCheckersKey {
00495     unsigned StmtKind;
00496     bool IsPreVisit;
00497 
00498     CachedStmtCheckersKey() : StmtKind(0), IsPreVisit(0) { }
00499     CachedStmtCheckersKey(unsigned stmtKind, bool isPreVisit)
00500       : StmtKind(stmtKind), IsPreVisit(isPreVisit) { }
00501 
00502     static CachedStmtCheckersKey getSentinel() {
00503       return CachedStmtCheckersKey(~0U, 0);
00504     }
00505     unsigned getHashValue() const {
00506       llvm::FoldingSetNodeID ID;
00507       ID.AddInteger(StmtKind);
00508       ID.AddBoolean(IsPreVisit);
00509       return ID.ComputeHash();
00510     }
00511     bool operator==(const CachedStmtCheckersKey &RHS) const {
00512       return StmtKind == RHS.StmtKind && IsPreVisit == RHS.IsPreVisit;
00513     }
00514   };
00515   friend struct llvm::DenseMapInfo<CachedStmtCheckersKey>;
00516 
00517   typedef SmallVector<CheckStmtFunc, 4> CachedStmtCheckers;
00518   typedef llvm::DenseMap<CachedStmtCheckersKey, CachedStmtCheckers>
00519       CachedStmtCheckersMapTy;
00520   CachedStmtCheckersMapTy CachedStmtCheckersMap;
00521 
00522   CachedStmtCheckers *getCachedStmtCheckersFor(const Stmt *S, bool isPreVisit);
00523 
00524   std::vector<CheckObjCMessageFunc> PreObjCMessageCheckers;
00525   std::vector<CheckObjCMessageFunc> PostObjCMessageCheckers;
00526 
00527   std::vector<CheckLocationFunc> LocationCheckers;
00528 
00529   std::vector<CheckBindFunc> BindCheckers;
00530 
00531   std::vector<CheckEndAnalysisFunc> EndAnalysisCheckers;
00532 
00533   std::vector<CheckEndPathFunc> EndPathCheckers;
00534 
00535   std::vector<CheckBranchConditionFunc> BranchConditionCheckers;
00536 
00537   std::vector<CheckLiveSymbolsFunc> LiveSymbolsCheckers;
00538 
00539   std::vector<CheckDeadSymbolsFunc> DeadSymbolsCheckers;
00540 
00541   struct RegionChangesCheckerInfo {
00542     CheckRegionChangesFunc CheckFn;
00543     WantsRegionChangeUpdateFunc WantUpdateFn;
00544   };
00545   std::vector<RegionChangesCheckerInfo> RegionChangesCheckers;
00546 
00547   std::vector<EvalAssumeFunc> EvalAssumeCheckers;
00548 
00549   std::vector<EvalCallFunc> EvalCallCheckers;
00550 
00551   std::vector<InlineCallFunc> InlineCallCheckers;
00552 
00553   std::vector<CheckEndOfTranslationUnit> EndOfTranslationUnitCheckers;
00554 
00555   struct EventInfo {
00556     SmallVector<CheckEventFunc, 4> Checkers;
00557     bool HasDispatcher;
00558     EventInfo() : HasDispatcher(false) { }
00559   };
00560   
00561   typedef llvm::DenseMap<EventTag, EventInfo> EventsTy;
00562   EventsTy Events;
00563 };
00564 
00565 } // end ento namespace
00566 
00567 } // end clang namespace
00568 
00569 namespace llvm {
00570   /// Define DenseMapInfo so that CachedStmtCheckersKey can be used as key
00571   /// in DenseMap and DenseSets.
00572   template <>
00573   struct DenseMapInfo<clang::ento::CheckerManager::CachedStmtCheckersKey> {
00574     static inline clang::ento::CheckerManager::CachedStmtCheckersKey
00575         getEmptyKey() {
00576       return clang::ento::CheckerManager::CachedStmtCheckersKey();
00577     }
00578     static inline clang::ento::CheckerManager::CachedStmtCheckersKey
00579         getTombstoneKey() {
00580       return clang::ento::CheckerManager::CachedStmtCheckersKey::getSentinel();
00581     }
00582 
00583     static unsigned
00584         getHashValue(clang::ento::CheckerManager::CachedStmtCheckersKey S) {
00585       return S.getHashValue();
00586     }
00587 
00588     static bool isEqual(clang::ento::CheckerManager::CachedStmtCheckersKey LHS,
00589                        clang::ento::CheckerManager::CachedStmtCheckersKey RHS) {
00590       return LHS == RHS;
00591     }
00592   };
00593 } // end namespace llvm
00594 
00595 #endif