CheckerManager.h revision 1655bcd052a67a3050fc55df8ecce57342352e68
1//===--- CheckerManager.h - Static Analyzer Checker Manager -----*- C++ -*-===//
2//
3//                     The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// Defines the Static Analyzer Checker Manager.
11//
12//===----------------------------------------------------------------------===//
13
14#ifndef LLVM_CLANG_SA_CORE_CHECKERMANAGER_H
15#define LLVM_CLANG_SA_CORE_CHECKERMANAGER_H
16
17#include "clang/Analysis/ProgramPoint.h"
18#include "clang/Basic/LangOptions.h"
19#include "clang/StaticAnalyzer/Core/PathSensitive/Store.h"
20#include "llvm/ADT/DenseMap.h"
21#include "llvm/ADT/FoldingSet.h"
22#include "llvm/ADT/SmallVector.h"
23#include <vector>
24
25namespace clang {
26  class Decl;
27  class Stmt;
28  class CallExpr;
29
30namespace 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
48template <typename T> class CheckerFn;
49
50template <typename RET, typename P1, typename P2, typename P3, typename P4,
51          typename P5>
52class CheckerFn<RET(P1, P2, P3, P4, P5)> {
53  typedef RET (*Func)(void *, P1, P2, P3, P4, P5);
54  Func Fn;
55public:
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
63template <typename RET, typename P1, typename P2, typename P3, typename P4>
64class CheckerFn<RET(P1, P2, P3, P4)> {
65  typedef RET (*Func)(void *, P1, P2, P3, P4);
66  Func Fn;
67public:
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
75template <typename RET, typename P1, typename P2, typename P3>
76class CheckerFn<RET(P1, P2, P3)> {
77  typedef RET (*Func)(void *, P1, P2, P3);
78  Func Fn;
79public:
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
85template <typename RET, typename P1, typename P2>
86class CheckerFn<RET(P1, P2)> {
87  typedef RET (*Func)(void *, P1, P2);
88  Func Fn;
89public:
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
95template <typename RET, typename P1>
96class CheckerFn<RET(P1)> {
97  typedef RET (*Func)(void *, P1);
98  Func Fn;
99public:
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
105template <typename RET>
106class CheckerFn<RET()> {
107  typedef RET (*Func)(void *);
108  Func Fn;
109public:
110  CheckerBase *Checker;
111  CheckerFn(CheckerBase *checker, Func fn) : Fn(fn), Checker(checker) { }
112  RET operator()() const { return Fn(Checker); }
113};
114
115class CheckerManager {
116  const LangOptions LangOpts;
117
118public:
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                          const ProgramPoint &PP);
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                             ExplodedNode *Pred,
271                             ExprEngine &Eng);
272
273  /// \brief Run checkers for branch condition.
274  void runCheckersForBranchCondition(const Stmt *condition,
275                                     ExplodedNodeSet &Dst, ExplodedNode *Pred,
276                                     ExprEngine &Eng);
277
278  /// \brief Run checkers for live symbols.
279  ///
280  /// Allows modifying SymbolReaper object. For example, checkers can explicitly
281  /// register symbols of interest as live. These symbols will not be marked
282  /// dead and removed.
283  void runCheckersForLiveSymbols(ProgramStateRef state,
284                                 SymbolReaper &SymReaper);
285
286  /// \brief Run checkers for dead symbols.
287  ///
288  /// Notifies checkers when symbols become dead. For example, this allows
289  /// checkers to aggressively clean up/reduce the checker state and produce
290  /// precise diagnostics.
291  void runCheckersForDeadSymbols(ExplodedNodeSet &Dst,
292                                 const ExplodedNodeSet &Src,
293                                 SymbolReaper &SymReaper, const Stmt *S,
294                                 ExprEngine &Eng,
295                                 ProgramPoint::Kind K);
296
297  /// \brief True if at least one checker wants to check region changes.
298  bool wantsRegionChangeUpdate(ProgramStateRef state);
299
300  /// \brief Run checkers for region changes.
301  ///
302  /// This corresponds to the check::RegionChanges callback.
303  /// \param state The current program state.
304  /// \param invalidated A set of all symbols potentially touched by the change.
305  /// \param ExplicitRegions The regions explicitly requested for invalidation.
306  ///   For example, in the case of a function call, these would be arguments.
307  /// \param Regions The transitive closure of accessible regions,
308  ///   i.e. all regions that may have been touched by this change.
309  /// \param Call The call expression wrapper if the regions are invalidated
310  ///   by a call.
311  ProgramStateRef
312  runCheckersForRegionChanges(ProgramStateRef state,
313                              const InvalidatedSymbols *invalidated,
314                              ArrayRef<const MemRegion *> ExplicitRegions,
315                              ArrayRef<const MemRegion *> Regions,
316                              const CallEvent *Call);
317
318  /// \brief Run checkers when pointers escape.
319  ///
320  /// This notifies the checkers about pointer escape, which occurs whenever
321  /// the analyzer cannot track the symbol any more. For example, as a
322  /// result of assigning a pointer into a global or when it's passed to a
323  /// function call the analyzer cannot model.
324  ///
325  /// \param State The state at the point of escape.
326  /// \param Escaped The list of escaped symbols.
327  /// \param Call The corresponding CallEvent, if the symbols escape as
328  ///        parameters to the given call.
329  /// \returns Checkers can modify the state by returning a new one.
330  ProgramStateRef
331  runCheckersForPointerEscape(ProgramStateRef State,
332                              const InvalidatedSymbols &Escaped,
333                              const CallEvent *Call);
334
335  /// \brief Run checkers for handling assumptions on symbolic values.
336  ProgramStateRef runCheckersForEvalAssume(ProgramStateRef state,
337                                           SVal Cond, bool Assumption);
338
339  /// \brief Run checkers for evaluating a call.
340  ///
341  /// Warning: Currently, the CallEvent MUST come from a CallExpr!
342  void runCheckersForEvalCall(ExplodedNodeSet &Dst,
343                              const ExplodedNodeSet &Src,
344                              const CallEvent &CE, ExprEngine &Eng);
345
346  /// \brief Run checkers for the entire Translation Unit.
347  void runCheckersOnEndOfTranslationUnit(const TranslationUnitDecl *TU,
348                                         AnalysisManager &mgr,
349                                         BugReporter &BR);
350
351  /// \brief Run checkers for debug-printing a ProgramState.
352  ///
353  /// Unlike most other callbacks, any checker can simply implement the virtual
354  /// method CheckerBase::printState if it has custom data to print.
355  /// \param Out The output stream
356  /// \param State The state being printed
357  /// \param NL The preferred representation of a newline.
358  /// \param Sep The preferred separator between different kinds of data.
359  void runCheckersForPrintState(raw_ostream &Out, ProgramStateRef State,
360                                const char *NL, const char *Sep);
361
362//===----------------------------------------------------------------------===//
363// Internal registration functions for AST traversing.
364//===----------------------------------------------------------------------===//
365
366  // Functions used by the registration mechanism, checkers should not touch
367  // these directly.
368
369  typedef CheckerFn<void (const Decl *, AnalysisManager&, BugReporter &)>
370      CheckDeclFunc;
371
372  typedef bool (*HandlesDeclFunc)(const Decl *D);
373  void _registerForDecl(CheckDeclFunc checkfn, HandlesDeclFunc isForDeclFn);
374
375  void _registerForBody(CheckDeclFunc checkfn);
376
377//===----------------------------------------------------------------------===//
378// Internal registration functions for path-sensitive checking.
379//===----------------------------------------------------------------------===//
380
381  typedef CheckerFn<void (const Stmt *, CheckerContext &)> CheckStmtFunc;
382
383  typedef CheckerFn<void (const ObjCMethodCall &, CheckerContext &)>
384      CheckObjCMessageFunc;
385
386  typedef CheckerFn<void (const CallEvent &, CheckerContext &)>
387      CheckCallFunc;
388
389  typedef CheckerFn<void (const SVal &location, bool isLoad,
390                          const Stmt *S,
391                          CheckerContext &)>
392      CheckLocationFunc;
393
394  typedef CheckerFn<void (const SVal &location, const SVal &val,
395                          const Stmt *S, CheckerContext &)>
396      CheckBindFunc;
397
398  typedef CheckerFn<void (ExplodedGraph &, BugReporter &, ExprEngine &)>
399      CheckEndAnalysisFunc;
400
401  typedef CheckerFn<void (CheckerContext &)>
402      CheckEndPathFunc;
403
404  typedef CheckerFn<void (const Stmt *, CheckerContext &)>
405      CheckBranchConditionFunc;
406
407  typedef CheckerFn<void (SymbolReaper &, CheckerContext &)>
408      CheckDeadSymbolsFunc;
409
410  typedef CheckerFn<void (ProgramStateRef,SymbolReaper &)> CheckLiveSymbolsFunc;
411
412  typedef CheckerFn<ProgramStateRef (ProgramStateRef,
413                                const InvalidatedSymbols *symbols,
414                                ArrayRef<const MemRegion *> ExplicitRegions,
415                                ArrayRef<const MemRegion *> Regions,
416                                const CallEvent *Call)>
417      CheckRegionChangesFunc;
418
419  typedef CheckerFn<bool (ProgramStateRef)> WantsRegionChangeUpdateFunc;
420
421  typedef CheckerFn<ProgramStateRef (ProgramStateRef,
422                                     const InvalidatedSymbols &Escaped,
423                                     const CallEvent *Call)>
424      CheckPointerEscapeFunc;
425
426  typedef CheckerFn<ProgramStateRef (ProgramStateRef,
427                                          const SVal &cond, bool assumption)>
428      EvalAssumeFunc;
429
430  typedef CheckerFn<bool (const CallExpr *, CheckerContext &)>
431      EvalCallFunc;
432
433  typedef CheckerFn<void (const TranslationUnitDecl *,
434                          AnalysisManager&, BugReporter &)>
435      CheckEndOfTranslationUnit;
436
437  typedef bool (*HandlesStmtFunc)(const Stmt *D);
438  void _registerForPreStmt(CheckStmtFunc checkfn,
439                           HandlesStmtFunc isForStmtFn);
440  void _registerForPostStmt(CheckStmtFunc checkfn,
441                            HandlesStmtFunc isForStmtFn);
442
443  void _registerForPreObjCMessage(CheckObjCMessageFunc checkfn);
444  void _registerForPostObjCMessage(CheckObjCMessageFunc checkfn);
445
446  void _registerForPreCall(CheckCallFunc checkfn);
447  void _registerForPostCall(CheckCallFunc checkfn);
448
449  void _registerForLocation(CheckLocationFunc checkfn);
450
451  void _registerForBind(CheckBindFunc checkfn);
452
453  void _registerForEndAnalysis(CheckEndAnalysisFunc checkfn);
454
455  void _registerForEndPath(CheckEndPathFunc checkfn);
456
457  void _registerForBranchCondition(CheckBranchConditionFunc checkfn);
458
459  void _registerForLiveSymbols(CheckLiveSymbolsFunc checkfn);
460
461  void _registerForDeadSymbols(CheckDeadSymbolsFunc checkfn);
462
463  void _registerForRegionChanges(CheckRegionChangesFunc checkfn,
464                                 WantsRegionChangeUpdateFunc wantUpdateFn);
465
466  void _registerForPointerEscape(CheckPointerEscapeFunc checkfn);
467
468  void _registerForEvalAssume(EvalAssumeFunc checkfn);
469
470  void _registerForEvalCall(EvalCallFunc checkfn);
471
472  void _registerForEndOfTranslationUnit(CheckEndOfTranslationUnit checkfn);
473
474//===----------------------------------------------------------------------===//
475// Internal registration functions for events.
476//===----------------------------------------------------------------------===//
477
478  typedef void *EventTag;
479  typedef CheckerFn<void (const void *event)> CheckEventFunc;
480
481  template <typename EVENT>
482  void _registerListenerForEvent(CheckEventFunc checkfn) {
483    EventInfo &info = Events[getTag<EVENT>()];
484    info.Checkers.push_back(checkfn);
485  }
486
487  template <typename EVENT>
488  void _registerDispatcherForEvent() {
489    EventInfo &info = Events[getTag<EVENT>()];
490    info.HasDispatcher = true;
491  }
492
493  template <typename EVENT>
494  void _dispatchEvent(const EVENT &event) const {
495    EventsTy::const_iterator I = Events.find(getTag<EVENT>());
496    if (I == Events.end())
497      return;
498    const EventInfo &info = I->second;
499    for (unsigned i = 0, e = info.Checkers.size(); i != e; ++i)
500      info.Checkers[i](&event);
501  }
502
503//===----------------------------------------------------------------------===//
504// Implementation details.
505//===----------------------------------------------------------------------===//
506
507private:
508  template <typename CHECKER>
509  static void destruct(void *obj) { delete static_cast<CHECKER *>(obj); }
510
511  template <typename T>
512  static void *getTag() { static int tag; return &tag; }
513
514  llvm::DenseMap<CheckerTag, CheckerRef> CheckerTags;
515
516  std::vector<CheckerDtor> CheckerDtors;
517
518  struct DeclCheckerInfo {
519    CheckDeclFunc CheckFn;
520    HandlesDeclFunc IsForDeclFn;
521  };
522  std::vector<DeclCheckerInfo> DeclCheckers;
523
524  std::vector<CheckDeclFunc> BodyCheckers;
525
526  typedef SmallVector<CheckDeclFunc, 4> CachedDeclCheckers;
527  typedef llvm::DenseMap<unsigned, CachedDeclCheckers> CachedDeclCheckersMapTy;
528  CachedDeclCheckersMapTy CachedDeclCheckersMap;
529
530  struct StmtCheckerInfo {
531    CheckStmtFunc CheckFn;
532    HandlesStmtFunc IsForStmtFn;
533    bool IsPreVisit;
534  };
535  std::vector<StmtCheckerInfo> StmtCheckers;
536
537  struct CachedStmtCheckersKey {
538    unsigned StmtKind;
539    bool IsPreVisit;
540
541    CachedStmtCheckersKey() : StmtKind(0), IsPreVisit(0) { }
542    CachedStmtCheckersKey(unsigned stmtKind, bool isPreVisit)
543      : StmtKind(stmtKind), IsPreVisit(isPreVisit) { }
544
545    static CachedStmtCheckersKey getSentinel() {
546      return CachedStmtCheckersKey(~0U, 0);
547    }
548    unsigned getHashValue() const {
549      llvm::FoldingSetNodeID ID;
550      ID.AddInteger(StmtKind);
551      ID.AddBoolean(IsPreVisit);
552      return ID.ComputeHash();
553    }
554    bool operator==(const CachedStmtCheckersKey &RHS) const {
555      return StmtKind == RHS.StmtKind && IsPreVisit == RHS.IsPreVisit;
556    }
557  };
558  friend struct llvm::DenseMapInfo<CachedStmtCheckersKey>;
559
560  typedef SmallVector<CheckStmtFunc, 4> CachedStmtCheckers;
561  typedef llvm::DenseMap<CachedStmtCheckersKey, CachedStmtCheckers>
562      CachedStmtCheckersMapTy;
563  CachedStmtCheckersMapTy CachedStmtCheckersMap;
564
565  CachedStmtCheckers *getCachedStmtCheckersFor(const Stmt *S, bool isPreVisit);
566
567  std::vector<CheckObjCMessageFunc> PreObjCMessageCheckers;
568  std::vector<CheckObjCMessageFunc> PostObjCMessageCheckers;
569
570  std::vector<CheckCallFunc> PreCallCheckers;
571  std::vector<CheckCallFunc> PostCallCheckers;
572
573  std::vector<CheckLocationFunc> LocationCheckers;
574
575  std::vector<CheckBindFunc> BindCheckers;
576
577  std::vector<CheckEndAnalysisFunc> EndAnalysisCheckers;
578
579  std::vector<CheckEndPathFunc> EndPathCheckers;
580
581  std::vector<CheckBranchConditionFunc> BranchConditionCheckers;
582
583  std::vector<CheckLiveSymbolsFunc> LiveSymbolsCheckers;
584
585  std::vector<CheckDeadSymbolsFunc> DeadSymbolsCheckers;
586
587  struct RegionChangesCheckerInfo {
588    CheckRegionChangesFunc CheckFn;
589    WantsRegionChangeUpdateFunc WantUpdateFn;
590  };
591  std::vector<RegionChangesCheckerInfo> RegionChangesCheckers;
592
593  std::vector<CheckPointerEscapeFunc> PointerEscapeCheckers;
594
595  std::vector<EvalAssumeFunc> EvalAssumeCheckers;
596
597  std::vector<EvalCallFunc> EvalCallCheckers;
598
599  std::vector<CheckEndOfTranslationUnit> EndOfTranslationUnitCheckers;
600
601  struct EventInfo {
602    SmallVector<CheckEventFunc, 4> Checkers;
603    bool HasDispatcher;
604    EventInfo() : HasDispatcher(false) { }
605  };
606
607  typedef llvm::DenseMap<EventTag, EventInfo> EventsTy;
608  EventsTy Events;
609};
610
611} // end ento namespace
612
613} // end clang namespace
614
615namespace llvm {
616  /// Define DenseMapInfo so that CachedStmtCheckersKey can be used as key
617  /// in DenseMap and DenseSets.
618  template <>
619  struct DenseMapInfo<clang::ento::CheckerManager::CachedStmtCheckersKey> {
620    static inline clang::ento::CheckerManager::CachedStmtCheckersKey
621        getEmptyKey() {
622      return clang::ento::CheckerManager::CachedStmtCheckersKey();
623    }
624    static inline clang::ento::CheckerManager::CachedStmtCheckersKey
625        getTombstoneKey() {
626      return clang::ento::CheckerManager::CachedStmtCheckersKey::getSentinel();
627    }
628
629    static unsigned
630        getHashValue(clang::ento::CheckerManager::CachedStmtCheckersKey S) {
631      return S.getHashValue();
632    }
633
634    static bool isEqual(clang::ento::CheckerManager::CachedStmtCheckersKey LHS,
635                       clang::ento::CheckerManager::CachedStmtCheckersKey RHS) {
636      return LHS == RHS;
637    }
638  };
639} // end namespace llvm
640
641#endif
642