Subversion Repositories QNX 8.QNX8 LLVM/Clang compiler suite

Rev

Blame | Last modification | View Log | Download | RSS feed

  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 Decl;
  32. class LocationContext;
  33. class Stmt;
  34. class TranslationUnitDecl;
  35.  
  36. namespace ento {
  37.  
  38. class AnalysisManager;
  39. class CXXAllocatorCall;
  40. class BugReporter;
  41. class CallEvent;
  42. class CheckerBase;
  43. class CheckerContext;
  44. class CheckerRegistry;
  45. struct CheckerRegistryData;
  46. class ExplodedGraph;
  47. class ExplodedNode;
  48. class ExplodedNodeSet;
  49. class ExprEngine;
  50. struct EvalCallOptions;
  51. class MemRegion;
  52. struct NodeBuilderContext;
  53. class ObjCMethodCall;
  54. class RegionAndSymbolInvalidationTraits;
  55. class SVal;
  56. class SymbolReaper;
  57.  
  58. template <typename T> class CheckerFn;
  59.  
  60. template <typename RET, typename... Ps>
  61. class CheckerFn<RET(Ps...)> {
  62.   using Func = RET (*)(void *, Ps...);
  63.  
  64.   Func Fn;
  65.  
  66. public:
  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.
  78. enum 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).
  106. class CheckerNameRef {
  107.   friend class ::clang::ento::CheckerRegistry;
  108.  
  109.   StringRef Name;
  110.  
  111.   explicit CheckerNameRef(StringRef Name) : Name(Name) {}
  112.  
  113. public:
  114.   CheckerNameRef() = default;
  115.  
  116.   StringRef getName() const { return Name; }
  117.   operator StringRef() const { return Name; }
  118. };
  119.  
  120. enum class ObjCMessageVisitKind {
  121.   Pre,
  122.   Post,
  123.   MessageNil
  124. };
  125.  
  126. class 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.  
  135. public:
  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.  
  619. private:
  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.