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