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