1 //===- CheckerManager.h - Static Analyzer Checker Manager -------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // Defines the Static Analyzer Checker Manager.
10 //
11 //===----------------------------------------------------------------------===//
12 
13 #ifndef LLVM_CLANG_STATICANALYZER_CORE_CHECKERMANAGER_H
14 #define LLVM_CLANG_STATICANALYZER_CORE_CHECKERMANAGER_H
15 
16 #include "clang/Analysis/ProgramPoint.h"
17 #include "clang/Basic/Diagnostic.h"
18 #include "clang/Basic/LangOptions.h"
19 #include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState_Fwd.h"
20 #include "clang/StaticAnalyzer/Core/PathSensitive/Store.h"
21 #include "llvm/ADT/ArrayRef.h"
22 #include "llvm/ADT/DenseMap.h"
23 #include "llvm/ADT/SmallVector.h"
24 #include "llvm/ADT/StringRef.h"
25 #include <vector>
26 
27 namespace clang {
28 
29 class AnalyzerOptions;
30 class CallExpr;
31 class CXXNewExpr;
32 class Decl;
33 class LocationContext;
34 class Stmt;
35 class TranslationUnitDecl;
36 
37 namespace ento {
38 
39 class AnalysisManager;
40 class CXXAllocatorCall;
41 class BugReporter;
42 class CallEvent;
43 class CheckerBase;
44 class CheckerContext;
45 class CheckerRegistry;
46 struct CheckerRegistryData;
47 class ExplodedGraph;
48 class ExplodedNode;
49 class ExplodedNodeSet;
50 class ExprEngine;
51 struct EvalCallOptions;
52 class MemRegion;
53 struct NodeBuilderContext;
54 class ObjCMethodCall;
55 class RegionAndSymbolInvalidationTraits;
56 class SVal;
57 class SymbolReaper;
58 
59 template <typename T> class CheckerFn;
60 
61 template <typename RET, typename... Ps>
62 class CheckerFn<RET(Ps...)> {
63   using Func = RET (*)(void *, Ps...);
64 
65   Func Fn;
66 
67 public:
68   CheckerBase *Checker;
69 
70   CheckerFn(CheckerBase *checker, Func fn) : Fn(fn), Checker(checker) {}
71 
72   RET operator()(Ps... ps) const {
73     return Fn(Checker, ps...);
74   }
75 };
76 
77 /// Describes the different reasons a pointer escapes
78 /// during analysis.
79 enum PointerEscapeKind {
80   /// A pointer escapes due to binding its value to a location
81   /// that the analyzer cannot track.
82   PSK_EscapeOnBind,
83 
84   /// The pointer has been passed to a function call directly.
85   PSK_DirectEscapeOnCall,
86 
87   /// The pointer has been passed to a function indirectly.
88   /// For example, the pointer is accessible through an
89   /// argument to a function.
90   PSK_IndirectEscapeOnCall,
91 
92 
93   /// Escape for a new symbol that was generated into a region
94   /// that the analyzer cannot follow during a conservative call.
95   PSK_EscapeOutParameters,
96 
97   /// The reason for pointer escape is unknown. For example,
98   /// a region containing this pointer is invalidated.
99   PSK_EscapeOther
100 };
101 
102 /// This wrapper is used to ensure that only StringRefs originating from the
103 /// CheckerRegistry are used as check names. We want to make sure all checker
104 /// name strings have a lifetime that keeps them alive at least until the path
105 /// diagnostics have been processed, since they are expected to be constexpr
106 /// string literals (most likely generated by TblGen).
107 class CheckerNameRef {
108   friend class ::clang::ento::CheckerRegistry;
109 
110   StringRef Name;
111 
112   explicit CheckerNameRef(StringRef Name) : Name(Name) {}
113 
114 public:
115   CheckerNameRef() = default;
116 
117   StringRef getName() const { return Name; }
118   operator StringRef() const { return Name; }
119 };
120 
121 enum class ObjCMessageVisitKind {
122   Pre,
123   Post,
124   MessageNil
125 };
126 
127 class CheckerManager {
128   ASTContext *Context = nullptr;
129   const LangOptions LangOpts;
130   const AnalyzerOptions &AOptions;
131   const Preprocessor *PP = nullptr;
132   CheckerNameRef CurrentCheckerName;
133   DiagnosticsEngine &Diags;
134   std::unique_ptr<CheckerRegistryData> RegistryData;
135 
136 public:
137   // These constructors are defined in the Frontend library, because
138   // CheckerRegistry, a crucial component of the initialization is in there.
139   // CheckerRegistry cannot be moved to the Core library, because the checker
140   // registration functions are defined in the Checkers library, and the library
141   // dependencies look like this: Core -> Checkers -> Frontend.
142 
143   CheckerManager(
144       ASTContext &Context, AnalyzerOptions &AOptions, const Preprocessor &PP,
145       ArrayRef<std::string> plugins,
146       ArrayRef<std::function<void(CheckerRegistry &)>> checkerRegistrationFns);
147 
148   /// Constructs a CheckerManager that ignores all non TblGen-generated
149   /// checkers. Useful for unit testing, unless the checker infrastructure
150   /// itself is tested.
151   CheckerManager(ASTContext &Context, AnalyzerOptions &AOptions,
152                  const Preprocessor &PP)
153       : CheckerManager(Context, AOptions, PP, {}, {}) {}
154 
155   /// Constructs a CheckerManager without requiring an AST. No checker
156   /// registration will take place. Only useful when one needs to print the
157   /// help flags through CheckerRegistryData, and the AST is unavalaible.
158   CheckerManager(AnalyzerOptions &AOptions, const LangOptions &LangOpts,
159                  DiagnosticsEngine &Diags, ArrayRef<std::string> plugins);
160 
161   ~CheckerManager();
162 
163   void setCurrentCheckerName(CheckerNameRef name) { CurrentCheckerName = name; }
164   CheckerNameRef getCurrentCheckerName() const { return CurrentCheckerName; }
165 
166   bool hasPathSensitiveCheckers() const;
167 
168   void finishedCheckerRegistration();
169 
170   const LangOptions &getLangOpts() const { return LangOpts; }
171   const AnalyzerOptions &getAnalyzerOptions() const { return AOptions; }
172   const Preprocessor &getPreprocessor() const {
173     assert(PP);
174     return *PP;
175   }
176   const CheckerRegistryData &getCheckerRegistryData() const {
177     return *RegistryData;
178   }
179   DiagnosticsEngine &getDiagnostics() const { return Diags; }
180   ASTContext &getASTContext() const {
181     assert(Context);
182     return *Context;
183   }
184 
185   /// Emits an error through a DiagnosticsEngine about an invalid user supplied
186   /// checker option value.
187   void reportInvalidCheckerOptionValue(const CheckerBase *C,
188                                        StringRef OptionName,
189                                        StringRef ExpectedValueDesc) const;
190 
191   using CheckerRef = CheckerBase *;
192   using CheckerTag = const void *;
193   using CheckerDtor = CheckerFn<void ()>;
194 
195 //===----------------------------------------------------------------------===//
196 // Checker registration.
197 //===----------------------------------------------------------------------===//
198 
199   /// Used to register checkers.
200   /// All arguments are automatically passed through to the checker
201   /// constructor.
202   ///
203   /// \returns a pointer to the checker object.
204   template <typename CHECKER, typename... AT>
205   CHECKER *registerChecker(AT &&... Args) {
206     CheckerTag tag = getTag<CHECKER>();
207     CheckerRef &ref = CheckerTags[tag];
208     assert(!ref && "Checker already registered, use getChecker!");
209 
210     CHECKER *checker = new CHECKER(std::forward<AT>(Args)...);
211     checker->Name = CurrentCheckerName;
212     CheckerDtors.push_back(CheckerDtor(checker, destruct<CHECKER>));
213     CHECKER::_register(checker, *this);
214     ref = checker;
215     return checker;
216   }
217 
218   template <typename CHECKER>
219   CHECKER *getChecker() {
220     CheckerTag tag = getTag<CHECKER>();
221     assert(CheckerTags.count(tag) != 0 &&
222            "Requested checker is not registered! Maybe you should add it as a "
223            "dependency in Checkers.td?");
224     return static_cast<CHECKER *>(CheckerTags[tag]);
225   }
226 
227 //===----------------------------------------------------------------------===//
228 // Functions for running checkers for AST traversing.
229 //===----------------------------------------------------------------------===//
230 
231   /// Run checkers handling Decls.
232   void runCheckersOnASTDecl(const Decl *D, AnalysisManager& mgr,
233                             BugReporter &BR);
234 
235   /// Run checkers handling Decls containing a Stmt body.
236   void runCheckersOnASTBody(const Decl *D, AnalysisManager& mgr,
237                             BugReporter &BR);
238 
239 //===----------------------------------------------------------------------===//
240 // Functions for running checkers for path-sensitive checking.
241 //===----------------------------------------------------------------------===//
242 
243   /// Run checkers for pre-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, runCheckersForPostStmt
249   void runCheckersForPreStmt(ExplodedNodeSet &Dst,
250                              const ExplodedNodeSet &Src,
251                              const Stmt *S,
252                              ExprEngine &Eng) {
253     runCheckersForStmt(/*isPreVisit=*/true, Dst, Src, S, Eng);
254   }
255 
256   /// Run checkers for post-visiting Stmts.
257   ///
258   /// The notification is performed for every explored CFGElement, which does
259   /// not include the control flow statements such as IfStmt.
260   ///
261   /// \sa runCheckersForBranchCondition, runCheckersForPreStmt
262   void runCheckersForPostStmt(ExplodedNodeSet &Dst,
263                               const ExplodedNodeSet &Src,
264                               const Stmt *S,
265                               ExprEngine &Eng,
266                               bool wasInlined = false) {
267     runCheckersForStmt(/*isPreVisit=*/false, Dst, Src, S, Eng, wasInlined);
268   }
269 
270   /// Run checkers for visiting Stmts.
271   void runCheckersForStmt(bool isPreVisit,
272                           ExplodedNodeSet &Dst, const ExplodedNodeSet &Src,
273                           const Stmt *S, ExprEngine &Eng,
274                           bool wasInlined = false);
275 
276   /// Run checkers for pre-visiting obj-c messages.
277   void runCheckersForPreObjCMessage(ExplodedNodeSet &Dst,
278                                     const ExplodedNodeSet &Src,
279                                     const ObjCMethodCall &msg,
280                                     ExprEngine &Eng) {
281     runCheckersForObjCMessage(ObjCMessageVisitKind::Pre, Dst, Src, msg, Eng);
282   }
283 
284   /// Run checkers for post-visiting obj-c messages.
285   void runCheckersForPostObjCMessage(ExplodedNodeSet &Dst,
286                                      const ExplodedNodeSet &Src,
287                                      const ObjCMethodCall &msg,
288                                      ExprEngine &Eng,
289                                      bool wasInlined = false) {
290     runCheckersForObjCMessage(ObjCMessageVisitKind::Post, Dst, Src, msg, Eng,
291                               wasInlined);
292   }
293 
294   /// Run checkers for visiting an obj-c message to nil.
295   void runCheckersForObjCMessageNil(ExplodedNodeSet &Dst,
296                                     const ExplodedNodeSet &Src,
297                                     const ObjCMethodCall &msg,
298                                     ExprEngine &Eng) {
299     runCheckersForObjCMessage(ObjCMessageVisitKind::MessageNil, Dst, Src, msg,
300                               Eng);
301   }
302 
303   /// Run checkers for visiting obj-c messages.
304   void runCheckersForObjCMessage(ObjCMessageVisitKind visitKind,
305                                  ExplodedNodeSet &Dst,
306                                  const ExplodedNodeSet &Src,
307                                  const ObjCMethodCall &msg, ExprEngine &Eng,
308                                  bool wasInlined = false);
309 
310   /// Run checkers for pre-visiting obj-c messages.
311   void runCheckersForPreCall(ExplodedNodeSet &Dst, const ExplodedNodeSet &Src,
312                              const CallEvent &Call, ExprEngine &Eng) {
313     runCheckersForCallEvent(/*isPreVisit=*/true, Dst, Src, Call, Eng);
314   }
315 
316   /// Run checkers for post-visiting obj-c messages.
317   void runCheckersForPostCall(ExplodedNodeSet &Dst, const ExplodedNodeSet &Src,
318                               const CallEvent &Call, ExprEngine &Eng,
319                               bool wasInlined = false) {
320     runCheckersForCallEvent(/*isPreVisit=*/false, Dst, Src, Call, Eng,
321                             wasInlined);
322   }
323 
324   /// Run checkers for visiting obj-c messages.
325   void runCheckersForCallEvent(bool isPreVisit, ExplodedNodeSet &Dst,
326                                const ExplodedNodeSet &Src,
327                                const CallEvent &Call, ExprEngine &Eng,
328                                bool wasInlined = false);
329 
330   /// Run checkers for load/store of a location.
331   void runCheckersForLocation(ExplodedNodeSet &Dst,
332                               const ExplodedNodeSet &Src,
333                               SVal location,
334                               bool isLoad,
335                               const Stmt *NodeEx,
336                               const Stmt *BoundEx,
337                               ExprEngine &Eng);
338 
339   /// Run checkers for binding of a value to a location.
340   void runCheckersForBind(ExplodedNodeSet &Dst,
341                           const ExplodedNodeSet &Src,
342                           SVal location, SVal val,
343                           const Stmt *S, ExprEngine &Eng,
344                           const ProgramPoint &PP);
345 
346   /// Run checkers for end of analysis.
347   void runCheckersForEndAnalysis(ExplodedGraph &G, BugReporter &BR,
348                                  ExprEngine &Eng);
349 
350   /// Run checkers on beginning of function.
351   void runCheckersForBeginFunction(ExplodedNodeSet &Dst,
352                                    const BlockEdge &L,
353                                    ExplodedNode *Pred,
354                                    ExprEngine &Eng);
355 
356   /// Run checkers on end of function.
357   void runCheckersForEndFunction(NodeBuilderContext &BC,
358                                  ExplodedNodeSet &Dst,
359                                  ExplodedNode *Pred,
360                                  ExprEngine &Eng,
361                                  const ReturnStmt *RS);
362 
363   /// Run checkers for branch condition.
364   void runCheckersForBranchCondition(const Stmt *condition,
365                                      ExplodedNodeSet &Dst, ExplodedNode *Pred,
366                                      ExprEngine &Eng);
367 
368   /// Run checkers between C++ operator new and constructor calls.
369   void runCheckersForNewAllocator(const CXXAllocatorCall &Call,
370                                   ExplodedNodeSet &Dst, ExplodedNode *Pred,
371                                   ExprEngine &Eng, bool wasInlined = false);
372 
373   /// Run checkers for live symbols.
374   ///
375   /// Allows modifying SymbolReaper object. For example, checkers can explicitly
376   /// register symbols of interest as live. These symbols will not be marked
377   /// dead and removed.
378   void runCheckersForLiveSymbols(ProgramStateRef state,
379                                  SymbolReaper &SymReaper);
380 
381   /// Run checkers for dead symbols.
382   ///
383   /// Notifies checkers when symbols become dead. For example, this allows
384   /// checkers to aggressively clean up/reduce the checker state and produce
385   /// precise diagnostics.
386   void runCheckersForDeadSymbols(ExplodedNodeSet &Dst,
387                                  const ExplodedNodeSet &Src,
388                                  SymbolReaper &SymReaper, const Stmt *S,
389                                  ExprEngine &Eng,
390                                  ProgramPoint::Kind K);
391 
392   /// Run checkers for region changes.
393   ///
394   /// This corresponds to the check::RegionChanges callback.
395   /// \param state The current program state.
396   /// \param invalidated A set of all symbols potentially touched by the change.
397   /// \param ExplicitRegions The regions explicitly requested for invalidation.
398   ///   For example, in the case of a function call, these would be arguments.
399   /// \param Regions The transitive closure of accessible regions,
400   ///   i.e. all regions that may have been touched by this change.
401   /// \param Call The call expression wrapper if the regions are invalidated
402   ///   by a call.
403   ProgramStateRef
404   runCheckersForRegionChanges(ProgramStateRef state,
405                               const InvalidatedSymbols *invalidated,
406                               ArrayRef<const MemRegion *> ExplicitRegions,
407                               ArrayRef<const MemRegion *> Regions,
408                               const LocationContext *LCtx,
409                               const CallEvent *Call);
410 
411   /// Run checkers when pointers escape.
412   ///
413   /// This notifies the checkers about pointer escape, which occurs whenever
414   /// the analyzer cannot track the symbol any more. For example, as a
415   /// result of assigning a pointer into a global or when it's passed to a
416   /// function call the analyzer cannot model.
417   ///
418   /// \param State The state at the point of escape.
419   /// \param Escaped The list of escaped symbols.
420   /// \param Call The corresponding CallEvent, if the symbols escape as
421   ///        parameters to the given call.
422   /// \param Kind The reason of pointer escape.
423   /// \param ITraits Information about invalidation for a particular
424   ///        region/symbol.
425   /// \returns Checkers can modify the state by returning a new one.
426   ProgramStateRef
427   runCheckersForPointerEscape(ProgramStateRef State,
428                               const InvalidatedSymbols &Escaped,
429                               const CallEvent *Call,
430                               PointerEscapeKind Kind,
431                               RegionAndSymbolInvalidationTraits *ITraits);
432 
433   /// Run checkers for handling assumptions on symbolic values.
434   ProgramStateRef runCheckersForEvalAssume(ProgramStateRef state,
435                                            SVal Cond, bool Assumption);
436 
437   /// Run checkers for evaluating a call.
438   ///
439   /// Warning: Currently, the CallEvent MUST come from a CallExpr!
440   void runCheckersForEvalCall(ExplodedNodeSet &Dst, const ExplodedNodeSet &Src,
441                               const CallEvent &CE, ExprEngine &Eng,
442                               const EvalCallOptions &CallOpts);
443 
444   /// Run checkers for the entire Translation Unit.
445   void runCheckersOnEndOfTranslationUnit(const TranslationUnitDecl *TU,
446                                          AnalysisManager &mgr,
447                                          BugReporter &BR);
448 
449   /// Run checkers for debug-printing a ProgramState.
450   ///
451   /// Unlike most other callbacks, any checker can simply implement the virtual
452   /// method CheckerBase::printState if it has custom data to print.
453   ///
454   /// \param Out   The output stream
455   /// \param State The state being printed
456   /// \param NL    The preferred representation of a newline.
457   /// \param Space The preferred space between the left side and the message.
458   /// \param IsDot Whether the message will be printed in 'dot' format.
459   void runCheckersForPrintStateJson(raw_ostream &Out, ProgramStateRef State,
460                                     const char *NL = "\n",
461                                     unsigned int Space = 0,
462                                     bool IsDot = false) const;
463 
464   //===----------------------------------------------------------------------===//
465   // Internal registration functions for AST traversing.
466   //===----------------------------------------------------------------------===//
467 
468   // Functions used by the registration mechanism, checkers should not touch
469   // these directly.
470 
471   using CheckDeclFunc =
472       CheckerFn<void (const Decl *, AnalysisManager&, BugReporter &)>;
473 
474   using HandlesDeclFunc = bool (*)(const Decl *D);
475 
476   void _registerForDecl(CheckDeclFunc checkfn, HandlesDeclFunc isForDeclFn);
477 
478   void _registerForBody(CheckDeclFunc checkfn);
479 
480 //===----------------------------------------------------------------------===//
481 // Internal registration functions for path-sensitive checking.
482 //===----------------------------------------------------------------------===//
483 
484   using CheckStmtFunc = CheckerFn<void (const Stmt *, CheckerContext &)>;
485 
486   using CheckObjCMessageFunc =
487       CheckerFn<void (const ObjCMethodCall &, CheckerContext &)>;
488 
489   using CheckCallFunc =
490       CheckerFn<void (const CallEvent &, CheckerContext &)>;
491 
492   using CheckLocationFunc =
493       CheckerFn<void (const SVal &location, bool isLoad, const Stmt *S,
494                       CheckerContext &)>;
495 
496   using CheckBindFunc =
497       CheckerFn<void (const SVal &location, const SVal &val, const Stmt *S,
498                       CheckerContext &)>;
499 
500   using CheckEndAnalysisFunc =
501       CheckerFn<void (ExplodedGraph &, BugReporter &, ExprEngine &)>;
502 
503   using CheckBeginFunctionFunc = CheckerFn<void (CheckerContext &)>;
504 
505   using CheckEndFunctionFunc =
506       CheckerFn<void (const ReturnStmt *, CheckerContext &)>;
507 
508   using CheckBranchConditionFunc =
509       CheckerFn<void (const Stmt *, CheckerContext &)>;
510 
511   using CheckNewAllocatorFunc =
512       CheckerFn<void(const CXXAllocatorCall &Call, CheckerContext &)>;
513 
514   using CheckDeadSymbolsFunc =
515       CheckerFn<void (SymbolReaper &, CheckerContext &)>;
516 
517   using CheckLiveSymbolsFunc = CheckerFn<void (ProgramStateRef,SymbolReaper &)>;
518 
519   using CheckRegionChangesFunc =
520       CheckerFn<ProgramStateRef (ProgramStateRef,
521                                  const InvalidatedSymbols *symbols,
522                                  ArrayRef<const MemRegion *> ExplicitRegions,
523                                  ArrayRef<const MemRegion *> Regions,
524                                  const LocationContext *LCtx,
525                                  const CallEvent *Call)>;
526 
527   using CheckPointerEscapeFunc =
528       CheckerFn<ProgramStateRef (ProgramStateRef,
529                                  const InvalidatedSymbols &Escaped,
530                                  const CallEvent *Call, PointerEscapeKind Kind,
531                                  RegionAndSymbolInvalidationTraits *ITraits)>;
532 
533   using EvalAssumeFunc =
534       CheckerFn<ProgramStateRef (ProgramStateRef, const SVal &cond,
535                                  bool assumption)>;
536 
537   using EvalCallFunc = CheckerFn<bool (const CallEvent &, CheckerContext &)>;
538 
539   using CheckEndOfTranslationUnit =
540       CheckerFn<void (const TranslationUnitDecl *, AnalysisManager &,
541                       BugReporter &)>;
542 
543   using HandlesStmtFunc = bool (*)(const Stmt *D);
544 
545   void _registerForPreStmt(CheckStmtFunc checkfn,
546                            HandlesStmtFunc isForStmtFn);
547   void _registerForPostStmt(CheckStmtFunc checkfn,
548                             HandlesStmtFunc isForStmtFn);
549 
550   void _registerForPreObjCMessage(CheckObjCMessageFunc checkfn);
551   void _registerForPostObjCMessage(CheckObjCMessageFunc checkfn);
552 
553   void _registerForObjCMessageNil(CheckObjCMessageFunc checkfn);
554 
555   void _registerForPreCall(CheckCallFunc checkfn);
556   void _registerForPostCall(CheckCallFunc checkfn);
557 
558   void _registerForLocation(CheckLocationFunc checkfn);
559 
560   void _registerForBind(CheckBindFunc checkfn);
561 
562   void _registerForEndAnalysis(CheckEndAnalysisFunc checkfn);
563 
564   void _registerForBeginFunction(CheckBeginFunctionFunc checkfn);
565   void _registerForEndFunction(CheckEndFunctionFunc checkfn);
566 
567   void _registerForBranchCondition(CheckBranchConditionFunc checkfn);
568 
569   void _registerForNewAllocator(CheckNewAllocatorFunc checkfn);
570 
571   void _registerForLiveSymbols(CheckLiveSymbolsFunc checkfn);
572 
573   void _registerForDeadSymbols(CheckDeadSymbolsFunc checkfn);
574 
575   void _registerForRegionChanges(CheckRegionChangesFunc checkfn);
576 
577   void _registerForPointerEscape(CheckPointerEscapeFunc checkfn);
578 
579   void _registerForConstPointerEscape(CheckPointerEscapeFunc checkfn);
580 
581   void _registerForEvalAssume(EvalAssumeFunc checkfn);
582 
583   void _registerForEvalCall(EvalCallFunc checkfn);
584 
585   void _registerForEndOfTranslationUnit(CheckEndOfTranslationUnit checkfn);
586 
587 //===----------------------------------------------------------------------===//
588 // Internal registration functions for events.
589 //===----------------------------------------------------------------------===//
590 
591   using EventTag = void *;
592   using CheckEventFunc = CheckerFn<void (const void *event)>;
593 
594   template <typename EVENT>
595   void _registerListenerForEvent(CheckEventFunc checkfn) {
596     EventInfo &info = Events[&EVENT::Tag];
597     info.Checkers.push_back(checkfn);
598   }
599 
600   template <typename EVENT>
601   void _registerDispatcherForEvent() {
602     EventInfo &info = Events[&EVENT::Tag];
603     info.HasDispatcher = true;
604   }
605 
606   template <typename EVENT>
607   void _dispatchEvent(const EVENT &event) const {
608     EventsTy::const_iterator I = Events.find(&EVENT::Tag);
609     if (I == Events.end())
610       return;
611     const EventInfo &info = I->second;
612     for (const auto &Checker : info.Checkers)
613       Checker(&event);
614   }
615 
616 //===----------------------------------------------------------------------===//
617 // Implementation details.
618 //===----------------------------------------------------------------------===//
619 
620 private:
621   template <typename CHECKER>
622   static void destruct(void *obj) { delete static_cast<CHECKER *>(obj); }
623 
624   template <typename T>
625   static void *getTag() { static int tag; return &tag; }
626 
627   llvm::DenseMap<CheckerTag, CheckerRef> CheckerTags;
628 
629   std::vector<CheckerDtor> CheckerDtors;
630 
631   struct DeclCheckerInfo {
632     CheckDeclFunc CheckFn;
633     HandlesDeclFunc IsForDeclFn;
634   };
635   std::vector<DeclCheckerInfo> DeclCheckers;
636 
637   std::vector<CheckDeclFunc> BodyCheckers;
638 
639   using CachedDeclCheckers = SmallVector<CheckDeclFunc, 4>;
640   using CachedDeclCheckersMapTy = llvm::DenseMap<unsigned, CachedDeclCheckers>;
641   CachedDeclCheckersMapTy CachedDeclCheckersMap;
642 
643   struct StmtCheckerInfo {
644     CheckStmtFunc CheckFn;
645     HandlesStmtFunc IsForStmtFn;
646     bool IsPreVisit;
647   };
648   std::vector<StmtCheckerInfo> StmtCheckers;
649 
650   using CachedStmtCheckers = SmallVector<CheckStmtFunc, 4>;
651   using CachedStmtCheckersMapTy = llvm::DenseMap<unsigned, CachedStmtCheckers>;
652   CachedStmtCheckersMapTy CachedStmtCheckersMap;
653 
654   const CachedStmtCheckers &getCachedStmtCheckersFor(const Stmt *S,
655                                                      bool isPreVisit);
656 
657   /// Returns the checkers that have registered for callbacks of the
658   /// given \p Kind.
659   const std::vector<CheckObjCMessageFunc> &
660   getObjCMessageCheckers(ObjCMessageVisitKind Kind) const;
661 
662   std::vector<CheckObjCMessageFunc> PreObjCMessageCheckers;
663   std::vector<CheckObjCMessageFunc> PostObjCMessageCheckers;
664   std::vector<CheckObjCMessageFunc> ObjCMessageNilCheckers;
665 
666   std::vector<CheckCallFunc> PreCallCheckers;
667   std::vector<CheckCallFunc> PostCallCheckers;
668 
669   std::vector<CheckLocationFunc> LocationCheckers;
670 
671   std::vector<CheckBindFunc> BindCheckers;
672 
673   std::vector<CheckEndAnalysisFunc> EndAnalysisCheckers;
674 
675   std::vector<CheckBeginFunctionFunc> BeginFunctionCheckers;
676   std::vector<CheckEndFunctionFunc> EndFunctionCheckers;
677 
678   std::vector<CheckBranchConditionFunc> BranchConditionCheckers;
679 
680   std::vector<CheckNewAllocatorFunc> NewAllocatorCheckers;
681 
682   std::vector<CheckLiveSymbolsFunc> LiveSymbolsCheckers;
683 
684   std::vector<CheckDeadSymbolsFunc> DeadSymbolsCheckers;
685 
686   std::vector<CheckRegionChangesFunc> RegionChangesCheckers;
687 
688   std::vector<CheckPointerEscapeFunc> PointerEscapeCheckers;
689 
690   std::vector<EvalAssumeFunc> EvalAssumeCheckers;
691 
692   std::vector<EvalCallFunc> EvalCallCheckers;
693 
694   std::vector<CheckEndOfTranslationUnit> EndOfTranslationUnitCheckers;
695 
696   struct EventInfo {
697     SmallVector<CheckEventFunc, 4> Checkers;
698     bool HasDispatcher = false;
699 
700     EventInfo() = default;
701   };
702 
703   using EventsTy = llvm::DenseMap<EventTag, EventInfo>;
704   EventsTy Events;
705 };
706 
707 } // namespace ento
708 
709 } // namespace clang
710 
711 #endif // LLVM_CLANG_STATICANALYZER_CORE_CHECKERMANAGER_H
712