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