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