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