Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-05-10 08:37:10

0001 //===- CheckerManager.h - Static Analyzer Checker Manager -------*- C++ -*-===//
0002 //
0003 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
0004 // See https://llvm.org/LICENSE.txt for license information.
0005 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
0006 //
0007 //===----------------------------------------------------------------------===//
0008 //
0009 // Defines the Static Analyzer Checker Manager.
0010 //
0011 //===----------------------------------------------------------------------===//
0012 
0013 #ifndef LLVM_CLANG_STATICANALYZER_CORE_CHECKERMANAGER_H
0014 #define LLVM_CLANG_STATICANALYZER_CORE_CHECKERMANAGER_H
0015 
0016 #include "clang/Analysis/ProgramPoint.h"
0017 #include "clang/Basic/Diagnostic.h"
0018 #include "clang/Basic/LangOptions.h"
0019 #include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState_Fwd.h"
0020 #include "clang/StaticAnalyzer/Core/PathSensitive/Store.h"
0021 #include "llvm/ADT/ArrayRef.h"
0022 #include "llvm/ADT/DenseMap.h"
0023 #include "llvm/ADT/SmallVector.h"
0024 #include "llvm/ADT/StringRef.h"
0025 #include <vector>
0026 
0027 namespace clang {
0028 
0029 class AnalyzerOptions;
0030 class CallExpr;
0031 class Decl;
0032 class LocationContext;
0033 class Stmt;
0034 class TranslationUnitDecl;
0035 
0036 namespace ento {
0037 
0038 class AnalysisManager;
0039 class CXXAllocatorCall;
0040 class BugReporter;
0041 class CallEvent;
0042 class CheckerBase;
0043 class CheckerContext;
0044 class CheckerRegistry;
0045 struct CheckerRegistryData;
0046 class ExplodedGraph;
0047 class ExplodedNode;
0048 class ExplodedNodeSet;
0049 class ExprEngine;
0050 struct EvalCallOptions;
0051 class MemRegion;
0052 class NodeBuilderContext;
0053 class ObjCMethodCall;
0054 class RegionAndSymbolInvalidationTraits;
0055 class SVal;
0056 class SymbolReaper;
0057 
0058 template <typename T> class CheckerFn;
0059 
0060 template <typename RET, typename... Ps>
0061 class CheckerFn<RET(Ps...)> {
0062   using Func = RET (*)(void *, Ps...);
0063 
0064   Func Fn;
0065 
0066 public:
0067   CheckerBase *Checker;
0068 
0069   CheckerFn(CheckerBase *checker, Func fn) : Fn(fn), Checker(checker) {}
0070 
0071   RET operator()(Ps... ps) const {
0072     return Fn(Checker, ps...);
0073   }
0074 };
0075 
0076 /// Describes the different reasons a pointer escapes
0077 /// during analysis.
0078 enum PointerEscapeKind {
0079   /// A pointer escapes due to binding its value to a location
0080   /// that the analyzer cannot track.
0081   PSK_EscapeOnBind,
0082 
0083   /// The pointer has been passed to a function call directly.
0084   PSK_DirectEscapeOnCall,
0085 
0086   /// The pointer has been passed to a function indirectly.
0087   /// For example, the pointer is accessible through an
0088   /// argument to a function.
0089   PSK_IndirectEscapeOnCall,
0090 
0091 
0092   /// Escape for a new symbol that was generated into a region
0093   /// that the analyzer cannot follow during a conservative call.
0094   PSK_EscapeOutParameters,
0095 
0096   /// The reason for pointer escape is unknown. For example,
0097   /// a region containing this pointer is invalidated.
0098   PSK_EscapeOther
0099 };
0100 
0101 /// This wrapper is used to ensure that only StringRefs originating from the
0102 /// CheckerRegistry are used as check names. We want to make sure all checker
0103 /// name strings have a lifetime that keeps them alive at least until the path
0104 /// diagnostics have been processed, since they are expected to be constexpr
0105 /// string literals (most likely generated by TblGen).
0106 class CheckerNameRef {
0107   friend class ::clang::ento::CheckerRegistry;
0108 
0109   StringRef Name;
0110 
0111   explicit CheckerNameRef(StringRef Name) : Name(Name) {}
0112 
0113 public:
0114   CheckerNameRef() = default;
0115 
0116   StringRef getName() const { return Name; }
0117   operator StringRef() const { return Name; }
0118 };
0119 
0120 enum class ObjCMessageVisitKind {
0121   Pre,
0122   Post,
0123   MessageNil
0124 };
0125 
0126 class CheckerManager {
0127   ASTContext *Context = nullptr;
0128   const LangOptions LangOpts;
0129   const AnalyzerOptions &AOptions;
0130   const Preprocessor *PP = nullptr;
0131   CheckerNameRef CurrentCheckerName;
0132   DiagnosticsEngine &Diags;
0133   std::unique_ptr<CheckerRegistryData> RegistryData;
0134 
0135 public:
0136   // These constructors are defined in the Frontend library, because
0137   // CheckerRegistry, a crucial component of the initialization is in there.
0138   // CheckerRegistry cannot be moved to the Core library, because the checker
0139   // registration functions are defined in the Checkers library, and the library
0140   // dependencies look like this: Core -> Checkers -> Frontend.
0141 
0142   CheckerManager(
0143       ASTContext &Context, AnalyzerOptions &AOptions, const Preprocessor &PP,
0144       ArrayRef<std::string> plugins,
0145       ArrayRef<std::function<void(CheckerRegistry &)>> checkerRegistrationFns);
0146 
0147   /// Constructs a CheckerManager that ignores all non TblGen-generated
0148   /// checkers. Useful for unit testing, unless the checker infrastructure
0149   /// itself is tested.
0150   CheckerManager(ASTContext &Context, AnalyzerOptions &AOptions,
0151                  const Preprocessor &PP)
0152       : CheckerManager(Context, AOptions, PP, {}, {}) {}
0153 
0154   /// Constructs a CheckerManager without requiring an AST. No checker
0155   /// registration will take place. Only useful when one needs to print the
0156   /// help flags through CheckerRegistryData, and the AST is unavailable.
0157   CheckerManager(AnalyzerOptions &AOptions, const LangOptions &LangOpts,
0158                  DiagnosticsEngine &Diags, ArrayRef<std::string> plugins);
0159 
0160   ~CheckerManager();
0161 
0162   void setCurrentCheckerName(CheckerNameRef name) { CurrentCheckerName = name; }
0163   CheckerNameRef getCurrentCheckerName() const { return CurrentCheckerName; }
0164 
0165   bool hasPathSensitiveCheckers() const;
0166 
0167   const LangOptions &getLangOpts() const { return LangOpts; }
0168   const AnalyzerOptions &getAnalyzerOptions() const { return AOptions; }
0169   const Preprocessor &getPreprocessor() const {
0170     assert(PP);
0171     return *PP;
0172   }
0173   const CheckerRegistryData &getCheckerRegistryData() const {
0174     return *RegistryData;
0175   }
0176   DiagnosticsEngine &getDiagnostics() const { return Diags; }
0177   ASTContext &getASTContext() const {
0178     assert(Context);
0179     return *Context;
0180   }
0181 
0182   /// Emits an error through a DiagnosticsEngine about an invalid user supplied
0183   /// checker option value.
0184   void reportInvalidCheckerOptionValue(const CheckerBase *C,
0185                                        StringRef OptionName,
0186                                        StringRef ExpectedValueDesc) const;
0187 
0188   using CheckerRef = CheckerBase *;
0189   using CheckerTag = const void *;
0190   using CheckerDtor = CheckerFn<void ()>;
0191 
0192 //===----------------------------------------------------------------------===//
0193 // Checker registration.
0194 //===----------------------------------------------------------------------===//
0195 
0196   /// Used to register checkers.
0197   /// All arguments are automatically passed through to the checker
0198   /// constructor.
0199   ///
0200   /// \returns a pointer to the checker object.
0201   template <typename CHECKER, typename... AT>
0202   CHECKER *registerChecker(AT &&... Args) {
0203     CheckerTag tag = getTag<CHECKER>();
0204     CheckerRef &ref = CheckerTags[tag];
0205     assert(!ref && "Checker already registered, use getChecker!");
0206 
0207     CHECKER *checker = new CHECKER(std::forward<AT>(Args)...);
0208     checker->Name = CurrentCheckerName;
0209     CheckerDtors.push_back(CheckerDtor(checker, destruct<CHECKER>));
0210     CHECKER::_register(checker, *this);
0211     ref = checker;
0212     return checker;
0213   }
0214 
0215   template <typename CHECKER>
0216   CHECKER *getChecker() {
0217     CheckerTag tag = getTag<CHECKER>();
0218     assert(CheckerTags.count(tag) != 0 &&
0219            "Requested checker is not registered! Maybe you should add it as a "
0220            "dependency in Checkers.td?");
0221     return static_cast<CHECKER *>(CheckerTags[tag]);
0222   }
0223 
0224   template <typename CHECKER> bool isRegisteredChecker() {
0225     return CheckerTags.contains(getTag<CHECKER>());
0226   }
0227 
0228 //===----------------------------------------------------------------------===//
0229 // Functions for running checkers for AST traversing.
0230 //===----------------------------------------------------------------------===//
0231 
0232   /// Run checkers handling Decls.
0233   void runCheckersOnASTDecl(const Decl *D, AnalysisManager& mgr,
0234                             BugReporter &BR);
0235 
0236   /// Run checkers handling Decls containing a Stmt body.
0237   void runCheckersOnASTBody(const Decl *D, AnalysisManager& mgr,
0238                             BugReporter &BR);
0239 
0240 //===----------------------------------------------------------------------===//
0241 // Functions for running checkers for path-sensitive checking.
0242 //===----------------------------------------------------------------------===//
0243 
0244   /// Run checkers for pre-visiting Stmts.
0245   ///
0246   /// The notification is performed for every explored CFGElement, which does
0247   /// not include the control flow statements such as IfStmt.
0248   ///
0249   /// \sa runCheckersForBranchCondition, runCheckersForPostStmt
0250   void runCheckersForPreStmt(ExplodedNodeSet &Dst,
0251                              const ExplodedNodeSet &Src,
0252                              const Stmt *S,
0253                              ExprEngine &Eng) {
0254     runCheckersForStmt(/*isPreVisit=*/true, Dst, Src, S, Eng);
0255   }
0256 
0257   /// Run checkers for post-visiting Stmts.
0258   ///
0259   /// The notification is performed for every explored CFGElement, which does
0260   /// not include the control flow statements such as IfStmt.
0261   ///
0262   /// \sa runCheckersForBranchCondition, runCheckersForPreStmt
0263   void runCheckersForPostStmt(ExplodedNodeSet &Dst,
0264                               const ExplodedNodeSet &Src,
0265                               const Stmt *S,
0266                               ExprEngine &Eng,
0267                               bool wasInlined = false) {
0268     runCheckersForStmt(/*isPreVisit=*/false, Dst, Src, S, Eng, wasInlined);
0269   }
0270 
0271   /// Run checkers for visiting Stmts.
0272   void runCheckersForStmt(bool isPreVisit,
0273                           ExplodedNodeSet &Dst, const ExplodedNodeSet &Src,
0274                           const Stmt *S, ExprEngine &Eng,
0275                           bool wasInlined = false);
0276 
0277   /// Run checkers for pre-visiting obj-c messages.
0278   void runCheckersForPreObjCMessage(ExplodedNodeSet &Dst,
0279                                     const ExplodedNodeSet &Src,
0280                                     const ObjCMethodCall &msg,
0281                                     ExprEngine &Eng) {
0282     runCheckersForObjCMessage(ObjCMessageVisitKind::Pre, Dst, Src, msg, Eng);
0283   }
0284 
0285   /// Run checkers for post-visiting obj-c messages.
0286   void runCheckersForPostObjCMessage(ExplodedNodeSet &Dst,
0287                                      const ExplodedNodeSet &Src,
0288                                      const ObjCMethodCall &msg,
0289                                      ExprEngine &Eng,
0290                                      bool wasInlined = false) {
0291     runCheckersForObjCMessage(ObjCMessageVisitKind::Post, Dst, Src, msg, Eng,
0292                               wasInlined);
0293   }
0294 
0295   /// Run checkers for visiting an obj-c message to nil.
0296   void runCheckersForObjCMessageNil(ExplodedNodeSet &Dst,
0297                                     const ExplodedNodeSet &Src,
0298                                     const ObjCMethodCall &msg,
0299                                     ExprEngine &Eng) {
0300     runCheckersForObjCMessage(ObjCMessageVisitKind::MessageNil, Dst, Src, msg,
0301                               Eng);
0302   }
0303 
0304   /// Run checkers for visiting obj-c messages.
0305   void runCheckersForObjCMessage(ObjCMessageVisitKind visitKind,
0306                                  ExplodedNodeSet &Dst,
0307                                  const ExplodedNodeSet &Src,
0308                                  const ObjCMethodCall &msg, ExprEngine &Eng,
0309                                  bool wasInlined = false);
0310 
0311   /// Run checkers for pre-visiting obj-c messages.
0312   void runCheckersForPreCall(ExplodedNodeSet &Dst, const ExplodedNodeSet &Src,
0313                              const CallEvent &Call, ExprEngine &Eng) {
0314     runCheckersForCallEvent(/*isPreVisit=*/true, Dst, Src, Call, Eng);
0315   }
0316 
0317   /// Run checkers for post-visiting obj-c messages.
0318   void runCheckersForPostCall(ExplodedNodeSet &Dst, const ExplodedNodeSet &Src,
0319                               const CallEvent &Call, ExprEngine &Eng,
0320                               bool wasInlined = false) {
0321     runCheckersForCallEvent(/*isPreVisit=*/false, Dst, Src, Call, Eng,
0322                             wasInlined);
0323   }
0324 
0325   /// Run checkers for visiting obj-c messages.
0326   void runCheckersForCallEvent(bool isPreVisit, ExplodedNodeSet &Dst,
0327                                const ExplodedNodeSet &Src,
0328                                const CallEvent &Call, ExprEngine &Eng,
0329                                bool wasInlined = false);
0330 
0331   /// Run checkers for load/store of a location.
0332   void runCheckersForLocation(ExplodedNodeSet &Dst,
0333                               const ExplodedNodeSet &Src,
0334                               SVal location,
0335                               bool isLoad,
0336                               const Stmt *NodeEx,
0337                               const Stmt *BoundEx,
0338                               ExprEngine &Eng);
0339 
0340   /// Run checkers for binding of a value to a location.
0341   void runCheckersForBind(ExplodedNodeSet &Dst,
0342                           const ExplodedNodeSet &Src,
0343                           SVal location, SVal val,
0344                           const Stmt *S, ExprEngine &Eng,
0345                           const ProgramPoint &PP);
0346 
0347   /// Run checkers for end of analysis.
0348   void runCheckersForEndAnalysis(ExplodedGraph &G, BugReporter &BR,
0349                                  ExprEngine &Eng);
0350 
0351   /// Run checkers on beginning of function.
0352   void runCheckersForBeginFunction(ExplodedNodeSet &Dst,
0353                                    const BlockEdge &L,
0354                                    ExplodedNode *Pred,
0355                                    ExprEngine &Eng);
0356 
0357   /// Run checkers on end of function.
0358   void runCheckersForEndFunction(NodeBuilderContext &BC,
0359                                  ExplodedNodeSet &Dst,
0360                                  ExplodedNode *Pred,
0361                                  ExprEngine &Eng,
0362                                  const ReturnStmt *RS);
0363 
0364   /// Run checkers for branch condition.
0365   void runCheckersForBranchCondition(const Stmt *condition,
0366                                      ExplodedNodeSet &Dst, ExplodedNode *Pred,
0367                                      ExprEngine &Eng);
0368 
0369   /// Run checkers between C++ operator new and constructor calls.
0370   void runCheckersForNewAllocator(const CXXAllocatorCall &Call,
0371                                   ExplodedNodeSet &Dst, ExplodedNode *Pred,
0372                                   ExprEngine &Eng, bool wasInlined = false);
0373 
0374   /// Run checkers for live symbols.
0375   ///
0376   /// Allows modifying SymbolReaper object. For example, checkers can explicitly
0377   /// register symbols of interest as live. These symbols will not be marked
0378   /// dead and removed.
0379   void runCheckersForLiveSymbols(ProgramStateRef state,
0380                                  SymbolReaper &SymReaper);
0381 
0382   /// Run checkers for dead symbols.
0383   ///
0384   /// Notifies checkers when symbols become dead. For example, this allows
0385   /// checkers to aggressively clean up/reduce the checker state and produce
0386   /// precise diagnostics.
0387   void runCheckersForDeadSymbols(ExplodedNodeSet &Dst,
0388                                  const ExplodedNodeSet &Src,
0389                                  SymbolReaper &SymReaper, const Stmt *S,
0390                                  ExprEngine &Eng,
0391                                  ProgramPoint::Kind K);
0392 
0393   /// Run checkers for region changes.
0394   ///
0395   /// This corresponds to the check::RegionChanges callback.
0396   /// \param state The current program state.
0397   /// \param invalidated A set of all symbols potentially touched by the change.
0398   /// \param ExplicitRegions The regions explicitly requested for invalidation.
0399   ///   For example, in the case of a function call, these would be arguments.
0400   /// \param Regions The transitive closure of accessible regions,
0401   ///   i.e. all regions that may have been touched by this change.
0402   /// \param Call The call expression wrapper if the regions are invalidated
0403   ///   by a call.
0404   ProgramStateRef
0405   runCheckersForRegionChanges(ProgramStateRef state,
0406                               const InvalidatedSymbols *invalidated,
0407                               ArrayRef<const MemRegion *> ExplicitRegions,
0408                               ArrayRef<const MemRegion *> Regions,
0409                               const LocationContext *LCtx,
0410                               const CallEvent *Call);
0411 
0412   /// Run checkers when pointers escape.
0413   ///
0414   /// This notifies the checkers about pointer escape, which occurs whenever
0415   /// the analyzer cannot track the symbol any more. For example, as a
0416   /// result of assigning a pointer into a global or when it's passed to a
0417   /// function call the analyzer cannot model.
0418   ///
0419   /// \param State The state at the point of escape.
0420   /// \param Escaped The list of escaped symbols.
0421   /// \param Call The corresponding CallEvent, if the symbols escape as
0422   ///        parameters to the given call.
0423   /// \param Kind The reason of pointer escape.
0424   /// \param ITraits Information about invalidation for a particular
0425   ///        region/symbol.
0426   /// \returns Checkers can modify the state by returning a new one.
0427   ProgramStateRef
0428   runCheckersForPointerEscape(ProgramStateRef State,
0429                               const InvalidatedSymbols &Escaped,
0430                               const CallEvent *Call,
0431                               PointerEscapeKind Kind,
0432                               RegionAndSymbolInvalidationTraits *ITraits);
0433 
0434   /// Run checkers for handling assumptions on symbolic values.
0435   ProgramStateRef runCheckersForEvalAssume(ProgramStateRef state,
0436                                            SVal Cond, bool Assumption);
0437 
0438   /// Run checkers for evaluating a call.
0439   ///
0440   /// Warning: Currently, the CallEvent MUST come from a CallExpr!
0441   void runCheckersForEvalCall(ExplodedNodeSet &Dst, const ExplodedNodeSet &Src,
0442                               const CallEvent &CE, ExprEngine &Eng,
0443                               const EvalCallOptions &CallOpts);
0444 
0445   /// Run checkers for the entire Translation Unit.
0446   void runCheckersOnEndOfTranslationUnit(const TranslationUnitDecl *TU,
0447                                          AnalysisManager &mgr,
0448                                          BugReporter &BR);
0449 
0450   /// Run checkers for debug-printing a ProgramState.
0451   ///
0452   /// Unlike most other callbacks, any checker can simply implement the virtual
0453   /// method CheckerBase::printState if it has custom data to print.
0454   ///
0455   /// \param Out   The output stream
0456   /// \param State The state being printed
0457   /// \param NL    The preferred representation of a newline.
0458   /// \param Space The preferred space between the left side and the message.
0459   /// \param IsDot Whether the message will be printed in 'dot' format.
0460   void runCheckersForPrintStateJson(raw_ostream &Out, ProgramStateRef State,
0461                                     const char *NL = "\n",
0462                                     unsigned int Space = 0,
0463                                     bool IsDot = false) const;
0464 
0465   //===----------------------------------------------------------------------===//
0466   // Internal registration functions for AST traversing.
0467   //===----------------------------------------------------------------------===//
0468 
0469   // Functions used by the registration mechanism, checkers should not touch
0470   // these directly.
0471 
0472   using CheckDeclFunc =
0473       CheckerFn<void (const Decl *, AnalysisManager&, BugReporter &)>;
0474 
0475   using HandlesDeclFunc = bool (*)(const Decl *D);
0476 
0477   void _registerForDecl(CheckDeclFunc checkfn, HandlesDeclFunc isForDeclFn);
0478 
0479   void _registerForBody(CheckDeclFunc checkfn);
0480 
0481 //===----------------------------------------------------------------------===//
0482 // Internal registration functions for path-sensitive checking.
0483 //===----------------------------------------------------------------------===//
0484 
0485   using CheckStmtFunc = CheckerFn<void (const Stmt *, CheckerContext &)>;
0486 
0487   using CheckObjCMessageFunc =
0488       CheckerFn<void (const ObjCMethodCall &, CheckerContext &)>;
0489 
0490   using CheckCallFunc =
0491       CheckerFn<void (const CallEvent &, CheckerContext &)>;
0492 
0493   using CheckLocationFunc = CheckerFn<void(SVal location, bool isLoad,
0494                                            const Stmt *S, CheckerContext &)>;
0495 
0496   using CheckBindFunc =
0497       CheckerFn<void(SVal location, SVal val, const Stmt *S, CheckerContext &)>;
0498 
0499   using CheckEndAnalysisFunc =
0500       CheckerFn<void (ExplodedGraph &, BugReporter &, ExprEngine &)>;
0501 
0502   using CheckBeginFunctionFunc = CheckerFn<void (CheckerContext &)>;
0503 
0504   using CheckEndFunctionFunc =
0505       CheckerFn<void (const ReturnStmt *, CheckerContext &)>;
0506 
0507   using CheckBranchConditionFunc =
0508       CheckerFn<void (const Stmt *, CheckerContext &)>;
0509 
0510   using CheckNewAllocatorFunc =
0511       CheckerFn<void(const CXXAllocatorCall &Call, CheckerContext &)>;
0512 
0513   using CheckDeadSymbolsFunc =
0514       CheckerFn<void (SymbolReaper &, CheckerContext &)>;
0515 
0516   using CheckLiveSymbolsFunc = CheckerFn<void (ProgramStateRef,SymbolReaper &)>;
0517 
0518   using CheckRegionChangesFunc =
0519       CheckerFn<ProgramStateRef (ProgramStateRef,
0520                                  const InvalidatedSymbols *symbols,
0521                                  ArrayRef<const MemRegion *> ExplicitRegions,
0522                                  ArrayRef<const MemRegion *> Regions,
0523                                  const LocationContext *LCtx,
0524                                  const CallEvent *Call)>;
0525 
0526   using CheckPointerEscapeFunc =
0527       CheckerFn<ProgramStateRef (ProgramStateRef,
0528                                  const InvalidatedSymbols &Escaped,
0529                                  const CallEvent *Call, PointerEscapeKind Kind,
0530                                  RegionAndSymbolInvalidationTraits *ITraits)>;
0531 
0532   using EvalAssumeFunc =
0533       CheckerFn<ProgramStateRef(ProgramStateRef, SVal cond, bool assumption)>;
0534 
0535   using EvalCallFunc = CheckerFn<bool (const CallEvent &, CheckerContext &)>;
0536 
0537   using CheckEndOfTranslationUnit =
0538       CheckerFn<void (const TranslationUnitDecl *, AnalysisManager &,
0539                       BugReporter &)>;
0540 
0541   using HandlesStmtFunc = bool (*)(const Stmt *D);
0542 
0543   void _registerForPreStmt(CheckStmtFunc checkfn,
0544                            HandlesStmtFunc isForStmtFn);
0545   void _registerForPostStmt(CheckStmtFunc checkfn,
0546                             HandlesStmtFunc isForStmtFn);
0547 
0548   void _registerForPreObjCMessage(CheckObjCMessageFunc checkfn);
0549   void _registerForPostObjCMessage(CheckObjCMessageFunc checkfn);
0550 
0551   void _registerForObjCMessageNil(CheckObjCMessageFunc checkfn);
0552 
0553   void _registerForPreCall(CheckCallFunc checkfn);
0554   void _registerForPostCall(CheckCallFunc checkfn);
0555 
0556   void _registerForLocation(CheckLocationFunc checkfn);
0557 
0558   void _registerForBind(CheckBindFunc checkfn);
0559 
0560   void _registerForEndAnalysis(CheckEndAnalysisFunc checkfn);
0561 
0562   void _registerForBeginFunction(CheckBeginFunctionFunc checkfn);
0563   void _registerForEndFunction(CheckEndFunctionFunc checkfn);
0564 
0565   void _registerForBranchCondition(CheckBranchConditionFunc checkfn);
0566 
0567   void _registerForNewAllocator(CheckNewAllocatorFunc checkfn);
0568 
0569   void _registerForLiveSymbols(CheckLiveSymbolsFunc checkfn);
0570 
0571   void _registerForDeadSymbols(CheckDeadSymbolsFunc checkfn);
0572 
0573   void _registerForRegionChanges(CheckRegionChangesFunc checkfn);
0574 
0575   void _registerForPointerEscape(CheckPointerEscapeFunc checkfn);
0576 
0577   void _registerForConstPointerEscape(CheckPointerEscapeFunc checkfn);
0578 
0579   void _registerForEvalAssume(EvalAssumeFunc checkfn);
0580 
0581   void _registerForEvalCall(EvalCallFunc checkfn);
0582 
0583   void _registerForEndOfTranslationUnit(CheckEndOfTranslationUnit checkfn);
0584 
0585 //===----------------------------------------------------------------------===//
0586 // Internal registration functions for events.
0587 //===----------------------------------------------------------------------===//
0588 
0589   using EventTag = void *;
0590   using CheckEventFunc = CheckerFn<void (const void *event)>;
0591 
0592   template <typename EVENT>
0593   void _registerListenerForEvent(CheckEventFunc checkfn) {
0594     EventInfo &info = Events[&EVENT::Tag];
0595     info.Checkers.push_back(checkfn);
0596   }
0597 
0598   template <typename EVENT>
0599   void _registerDispatcherForEvent() {
0600     EventInfo &info = Events[&EVENT::Tag];
0601     info.HasDispatcher = true;
0602   }
0603 
0604   template <typename EVENT>
0605   void _dispatchEvent(const EVENT &event) const {
0606     EventsTy::const_iterator I = Events.find(&EVENT::Tag);
0607     if (I == Events.end())
0608       return;
0609     const EventInfo &info = I->second;
0610     for (const auto &Checker : info.Checkers)
0611       Checker(&event);
0612   }
0613 
0614 //===----------------------------------------------------------------------===//
0615 // Implementation details.
0616 //===----------------------------------------------------------------------===//
0617 
0618 private:
0619   template <typename CHECKER>
0620   static void destruct(void *obj) { delete static_cast<CHECKER *>(obj); }
0621 
0622   template <typename T>
0623   static void *getTag() { static int tag; return &tag; }
0624 
0625   llvm::DenseMap<CheckerTag, CheckerRef> CheckerTags;
0626 
0627   std::vector<CheckerDtor> CheckerDtors;
0628 
0629   struct DeclCheckerInfo {
0630     CheckDeclFunc CheckFn;
0631     HandlesDeclFunc IsForDeclFn;
0632   };
0633   std::vector<DeclCheckerInfo> DeclCheckers;
0634 
0635   std::vector<CheckDeclFunc> BodyCheckers;
0636 
0637   using CachedDeclCheckers = SmallVector<CheckDeclFunc, 4>;
0638   using CachedDeclCheckersMapTy = llvm::DenseMap<unsigned, CachedDeclCheckers>;
0639   CachedDeclCheckersMapTy CachedDeclCheckersMap;
0640 
0641   struct StmtCheckerInfo {
0642     CheckStmtFunc CheckFn;
0643     HandlesStmtFunc IsForStmtFn;
0644     bool IsPreVisit;
0645   };
0646   std::vector<StmtCheckerInfo> StmtCheckers;
0647 
0648   using CachedStmtCheckers = SmallVector<CheckStmtFunc, 4>;
0649   using CachedStmtCheckersMapTy = llvm::DenseMap<unsigned, CachedStmtCheckers>;
0650   CachedStmtCheckersMapTy CachedStmtCheckersMap;
0651 
0652   const CachedStmtCheckers &getCachedStmtCheckersFor(const Stmt *S,
0653                                                      bool isPreVisit);
0654 
0655   /// Returns the checkers that have registered for callbacks of the
0656   /// given \p Kind.
0657   const std::vector<CheckObjCMessageFunc> &
0658   getObjCMessageCheckers(ObjCMessageVisitKind Kind) const;
0659 
0660   std::vector<CheckObjCMessageFunc> PreObjCMessageCheckers;
0661   std::vector<CheckObjCMessageFunc> PostObjCMessageCheckers;
0662   std::vector<CheckObjCMessageFunc> ObjCMessageNilCheckers;
0663 
0664   std::vector<CheckCallFunc> PreCallCheckers;
0665   std::vector<CheckCallFunc> PostCallCheckers;
0666 
0667   std::vector<CheckLocationFunc> LocationCheckers;
0668 
0669   std::vector<CheckBindFunc> BindCheckers;
0670 
0671   std::vector<CheckEndAnalysisFunc> EndAnalysisCheckers;
0672 
0673   std::vector<CheckBeginFunctionFunc> BeginFunctionCheckers;
0674   std::vector<CheckEndFunctionFunc> EndFunctionCheckers;
0675 
0676   std::vector<CheckBranchConditionFunc> BranchConditionCheckers;
0677 
0678   std::vector<CheckNewAllocatorFunc> NewAllocatorCheckers;
0679 
0680   std::vector<CheckLiveSymbolsFunc> LiveSymbolsCheckers;
0681 
0682   std::vector<CheckDeadSymbolsFunc> DeadSymbolsCheckers;
0683 
0684   std::vector<CheckRegionChangesFunc> RegionChangesCheckers;
0685 
0686   std::vector<CheckPointerEscapeFunc> PointerEscapeCheckers;
0687 
0688   std::vector<EvalAssumeFunc> EvalAssumeCheckers;
0689 
0690   std::vector<EvalCallFunc> EvalCallCheckers;
0691 
0692   std::vector<CheckEndOfTranslationUnit> EndOfTranslationUnitCheckers;
0693 
0694   struct EventInfo {
0695     SmallVector<CheckEventFunc, 4> Checkers;
0696     bool HasDispatcher = false;
0697 
0698     EventInfo() = default;
0699   };
0700 
0701   using EventsTy = llvm::DenseMap<EventTag, EventInfo>;
0702   EventsTy Events;
0703 };
0704 
0705 } // namespace ento
0706 
0707 } // namespace clang
0708 
0709 #endif // LLVM_CLANG_STATICANALYZER_CORE_CHECKERMANAGER_H