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