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