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