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