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