xref: /freebsd/contrib/llvm-project/clang/include/clang/StaticAnalyzer/Core/CheckerManager.h (revision 700637cbb5e582861067a11aaca4d053546871d2)
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 CheckerFrontend;
43 class CheckerBackend;
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 class 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   CheckerBackend *Checker;
69 
CheckerFn(CheckerBackend * checker,Func fn)70   CheckerFn(CheckerBackend *checker, Func fn) : Fn(fn), Checker(checker) {}
71 
operator()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 
CheckerNameRef(StringRef Name)112   explicit CheckerNameRef(StringRef Name) : Name(Name) {}
113 
114 public:
115   CheckerNameRef() = default;
116 
StringRef()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.
CheckerManager(ASTContext & Context,AnalyzerOptions & AOptions,const Preprocessor & PP)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 
setCurrentCheckerName(CheckerNameRef name)162   void setCurrentCheckerName(CheckerNameRef name) { CurrentCheckerName = name; }
getCurrentCheckerName()163   CheckerNameRef getCurrentCheckerName() const { return CurrentCheckerName; }
164 
165   bool hasPathSensitiveCheckers() const;
166 
getLangOpts()167   const LangOptions &getLangOpts() const { return LangOpts; }
getAnalyzerOptions()168   const AnalyzerOptions &getAnalyzerOptions() const { return AOptions; }
getPreprocessor()169   const Preprocessor &getPreprocessor() const {
170     assert(PP);
171     return *PP;
172   }
getCheckerRegistryData()173   const CheckerRegistryData &getCheckerRegistryData() const {
174     return *RegistryData;
175   }
getDiagnostics()176   DiagnosticsEngine &getDiagnostics() const { return Diags; }
getASTContext()177   ASTContext &getASTContext() const {
178     assert(Context);
179     return *Context;
180   }
181 
182   /// Emits an error through a DiagnosticsEngine about an invalid user supplied
183   /// checker option value.
184   void reportInvalidCheckerOptionValue(const CheckerFrontend *Checker,
185                                        StringRef OptionName,
186                                        StringRef ExpectedValueDesc) const;
187 
188   using CheckerTag = const void *;
189 
190   //===--------------------------------------------------------------------===//
191   // Checker registration.
192   //===--------------------------------------------------------------------===//
193 
194   /// If the the singleton instance of a checker class is not yet constructed,
195   /// then construct it (with the supplied arguments), register it for the
196   /// callbacks that are supported by it, and return it. Otherwise, just return
197   /// a pointer to the existing instance.
198   template <typename CHECKER, typename... AT>
getChecker(AT &&...Args)199   CHECKER *getChecker(AT &&...Args) {
200     CheckerTag Tag = getTag<CHECKER>();
201 
202     std::unique_ptr<CheckerBackend> &Ref = CheckerTags[Tag];
203     if (!Ref) {
204       std::unique_ptr<CHECKER> Checker =
205           std::make_unique<CHECKER>(std::forward<AT>(Args)...);
206       CHECKER::_register(Checker.get(), *this);
207       Ref = std::move(Checker);
208     }
209 
210     return static_cast<CHECKER *>(Ref.get());
211   }
212 
213   /// Register a single-part checker (derived from `Checker`): construct its
214   /// singleton instance, register it for the supported callbacks and record
215   /// its name (with `CheckerFrontend::enable`). Calling this multiple times
216   /// triggers an assertion failure.
217   template <typename CHECKER, typename... AT>
registerChecker(AT &&...Args)218   CHECKER *registerChecker(AT &&...Args) {
219     CHECKER *Chk = getChecker<CHECKER>(std::forward<AT>(Args)...);
220     Chk->enable(*this);
221     return Chk;
222   }
223 
isRegisteredChecker()224   template <typename CHECKER> bool isRegisteredChecker() {
225     return CheckerTags.contains(getTag<CHECKER>());
226   }
227 
228 //===----------------------------------------------------------------------===//
229 // Functions for running checkers for AST traversing.
230 //===----------------------------------------------------------------------===//
231 
232   /// Run checkers handling Decls.
233   void runCheckersOnASTDecl(const Decl *D, AnalysisManager& mgr,
234                             BugReporter &BR);
235 
236   /// Run checkers handling Decls containing a Stmt body.
237   void runCheckersOnASTBody(const Decl *D, AnalysisManager& mgr,
238                             BugReporter &BR);
239 
240 //===----------------------------------------------------------------------===//
241 // Functions for running checkers for path-sensitive checking.
242 //===----------------------------------------------------------------------===//
243 
244   /// Run checkers for pre-visiting Stmts.
245   ///
246   /// The notification is performed for every explored CFGElement, which does
247   /// not include the control flow statements such as IfStmt.
248   ///
249   /// \sa runCheckersForBranchCondition, runCheckersForPostStmt
runCheckersForPreStmt(ExplodedNodeSet & Dst,const ExplodedNodeSet & Src,const Stmt * S,ExprEngine & Eng)250   void runCheckersForPreStmt(ExplodedNodeSet &Dst,
251                              const ExplodedNodeSet &Src,
252                              const Stmt *S,
253                              ExprEngine &Eng) {
254     runCheckersForStmt(/*isPreVisit=*/true, Dst, Src, S, Eng);
255   }
256 
257   /// Run checkers for post-visiting Stmts.
258   ///
259   /// The notification is performed for every explored CFGElement, which does
260   /// not include the control flow statements such as IfStmt.
261   ///
262   /// \sa runCheckersForBranchCondition, runCheckersForPreStmt
263   void runCheckersForPostStmt(ExplodedNodeSet &Dst,
264                               const ExplodedNodeSet &Src,
265                               const Stmt *S,
266                               ExprEngine &Eng,
267                               bool wasInlined = false) {
268     runCheckersForStmt(/*isPreVisit=*/false, Dst, Src, S, Eng, wasInlined);
269   }
270 
271   /// Run checkers for visiting Stmts.
272   void runCheckersForStmt(bool isPreVisit,
273                           ExplodedNodeSet &Dst, const ExplodedNodeSet &Src,
274                           const Stmt *S, ExprEngine &Eng,
275                           bool wasInlined = false);
276 
277   /// Run checkers for pre-visiting obj-c messages.
runCheckersForPreObjCMessage(ExplodedNodeSet & Dst,const ExplodedNodeSet & Src,const ObjCMethodCall & msg,ExprEngine & Eng)278   void runCheckersForPreObjCMessage(ExplodedNodeSet &Dst,
279                                     const ExplodedNodeSet &Src,
280                                     const ObjCMethodCall &msg,
281                                     ExprEngine &Eng) {
282     runCheckersForObjCMessage(ObjCMessageVisitKind::Pre, Dst, Src, msg, Eng);
283   }
284 
285   /// Run checkers for post-visiting obj-c messages.
286   void runCheckersForPostObjCMessage(ExplodedNodeSet &Dst,
287                                      const ExplodedNodeSet &Src,
288                                      const ObjCMethodCall &msg,
289                                      ExprEngine &Eng,
290                                      bool wasInlined = false) {
291     runCheckersForObjCMessage(ObjCMessageVisitKind::Post, Dst, Src, msg, Eng,
292                               wasInlined);
293   }
294 
295   /// Run checkers for visiting an obj-c message to nil.
runCheckersForObjCMessageNil(ExplodedNodeSet & Dst,const ExplodedNodeSet & Src,const ObjCMethodCall & msg,ExprEngine & Eng)296   void runCheckersForObjCMessageNil(ExplodedNodeSet &Dst,
297                                     const ExplodedNodeSet &Src,
298                                     const ObjCMethodCall &msg,
299                                     ExprEngine &Eng) {
300     runCheckersForObjCMessage(ObjCMessageVisitKind::MessageNil, Dst, Src, msg,
301                               Eng);
302   }
303 
304   /// Run checkers for visiting obj-c messages.
305   void runCheckersForObjCMessage(ObjCMessageVisitKind visitKind,
306                                  ExplodedNodeSet &Dst,
307                                  const ExplodedNodeSet &Src,
308                                  const ObjCMethodCall &msg, ExprEngine &Eng,
309                                  bool wasInlined = false);
310 
311   /// Run checkers for pre-visiting obj-c messages.
runCheckersForPreCall(ExplodedNodeSet & Dst,const ExplodedNodeSet & Src,const CallEvent & Call,ExprEngine & Eng)312   void runCheckersForPreCall(ExplodedNodeSet &Dst, const ExplodedNodeSet &Src,
313                              const CallEvent &Call, ExprEngine &Eng) {
314     runCheckersForCallEvent(/*isPreVisit=*/true, Dst, Src, Call, Eng);
315   }
316 
317   /// Run checkers for post-visiting obj-c messages.
318   void runCheckersForPostCall(ExplodedNodeSet &Dst, const ExplodedNodeSet &Src,
319                               const CallEvent &Call, ExprEngine &Eng,
320                               bool wasInlined = false) {
321     runCheckersForCallEvent(/*isPreVisit=*/false, Dst, Src, Call, Eng,
322                             wasInlined);
323   }
324 
325   /// Run checkers for visiting obj-c messages.
326   void runCheckersForCallEvent(bool isPreVisit, ExplodedNodeSet &Dst,
327                                const ExplodedNodeSet &Src,
328                                const CallEvent &Call, ExprEngine &Eng,
329                                bool wasInlined = false);
330 
331   /// Run checkers for load/store of a location.
332   void runCheckersForLocation(ExplodedNodeSet &Dst,
333                               const ExplodedNodeSet &Src,
334                               SVal location,
335                               bool isLoad,
336                               const Stmt *NodeEx,
337                               const Stmt *BoundEx,
338                               ExprEngine &Eng);
339 
340   /// Run checkers for binding of a value to a location.
341   void runCheckersForBind(ExplodedNodeSet &Dst,
342                           const ExplodedNodeSet &Src,
343                           SVal location, SVal val,
344                           const Stmt *S, ExprEngine &Eng,
345                           const ProgramPoint &PP);
346 
347   /// Run checkers after taking a control flow edge.
348   void runCheckersForBlockEntrance(ExplodedNodeSet &Dst,
349                                    const ExplodedNodeSet &Src,
350                                    const BlockEntrance &Entrance,
351                                    ExprEngine &Eng) const;
352 
353   /// Run checkers for end of analysis.
354   void runCheckersForEndAnalysis(ExplodedGraph &G, BugReporter &BR,
355                                  ExprEngine &Eng);
356 
357   /// Run checkers on beginning of function.
358   void runCheckersForBeginFunction(ExplodedNodeSet &Dst,
359                                    const BlockEdge &L,
360                                    ExplodedNode *Pred,
361                                    ExprEngine &Eng);
362 
363   /// Run checkers on end of function.
364   void runCheckersForEndFunction(NodeBuilderContext &BC,
365                                  ExplodedNodeSet &Dst,
366                                  ExplodedNode *Pred,
367                                  ExprEngine &Eng,
368                                  const ReturnStmt *RS);
369 
370   /// Run checkers for branch condition.
371   void runCheckersForBranchCondition(const Stmt *condition,
372                                      ExplodedNodeSet &Dst, ExplodedNode *Pred,
373                                      ExprEngine &Eng);
374 
375   /// Run checkers between C++ operator new and constructor calls.
376   void runCheckersForNewAllocator(const CXXAllocatorCall &Call,
377                                   ExplodedNodeSet &Dst, ExplodedNode *Pred,
378                                   ExprEngine &Eng, bool wasInlined = false);
379 
380   /// Run checkers for live symbols.
381   ///
382   /// Allows modifying SymbolReaper object. For example, checkers can explicitly
383   /// register symbols of interest as live. These symbols will not be marked
384   /// dead and removed.
385   void runCheckersForLiveSymbols(ProgramStateRef state,
386                                  SymbolReaper &SymReaper);
387 
388   /// Run checkers for dead symbols.
389   ///
390   /// Notifies checkers when symbols become dead. For example, this allows
391   /// checkers to aggressively clean up/reduce the checker state and produce
392   /// precise diagnostics.
393   void runCheckersForDeadSymbols(ExplodedNodeSet &Dst,
394                                  const ExplodedNodeSet &Src,
395                                  SymbolReaper &SymReaper, const Stmt *S,
396                                  ExprEngine &Eng,
397                                  ProgramPoint::Kind K);
398 
399   /// Run checkers for region changes.
400   ///
401   /// This corresponds to the check::RegionChanges callback.
402   /// \param state The current program state.
403   /// \param invalidated A set of all symbols potentially touched by the change.
404   /// \param ExplicitRegions The regions explicitly requested for invalidation.
405   ///   For example, in the case of a function call, these would be arguments.
406   /// \param Regions The transitive closure of accessible regions,
407   ///   i.e. all regions that may have been touched by this change.
408   /// \param Call The call expression wrapper if the regions are invalidated
409   ///   by a call.
410   ProgramStateRef
411   runCheckersForRegionChanges(ProgramStateRef state,
412                               const InvalidatedSymbols *invalidated,
413                               ArrayRef<const MemRegion *> ExplicitRegions,
414                               ArrayRef<const MemRegion *> Regions,
415                               const LocationContext *LCtx,
416                               const CallEvent *Call);
417 
418   /// Run checkers when pointers escape.
419   ///
420   /// This notifies the checkers about pointer escape, which occurs whenever
421   /// the analyzer cannot track the symbol any more. For example, as a
422   /// result of assigning a pointer into a global or when it's passed to a
423   /// function call the analyzer cannot model.
424   ///
425   /// \param State The state at the point of escape.
426   /// \param Escaped The list of escaped symbols.
427   /// \param Call The corresponding CallEvent, if the symbols escape as
428   ///        parameters to the given call.
429   /// \param Kind The reason of pointer escape.
430   /// \param ITraits Information about invalidation for a particular
431   ///        region/symbol.
432   /// \returns Checkers can modify the state by returning a new one.
433   ProgramStateRef
434   runCheckersForPointerEscape(ProgramStateRef State,
435                               const InvalidatedSymbols &Escaped,
436                               const CallEvent *Call,
437                               PointerEscapeKind Kind,
438                               RegionAndSymbolInvalidationTraits *ITraits);
439 
440   /// Run checkers for handling assumptions on symbolic values.
441   ProgramStateRef runCheckersForEvalAssume(ProgramStateRef state,
442                                            SVal Cond, bool Assumption);
443 
444   /// Run checkers for evaluating a call.
445   ///
446   /// Warning: Currently, the CallEvent MUST come from a CallExpr!
447   void runCheckersForEvalCall(ExplodedNodeSet &Dst, const ExplodedNodeSet &Src,
448                               const CallEvent &CE, ExprEngine &Eng,
449                               const EvalCallOptions &CallOpts);
450 
451   /// Run checkers for the entire Translation Unit.
452   void runCheckersOnEndOfTranslationUnit(const TranslationUnitDecl *TU,
453                                          AnalysisManager &mgr,
454                                          BugReporter &BR);
455 
456   /// Run checkers for debug-printing a ProgramState.
457   ///
458   /// Unlike most other callbacks, any checker can simply implement the virtual
459   /// method CheckerBackend::printState if it has custom data to print.
460   ///
461   /// \param Out   The output stream
462   /// \param State The state being printed
463   /// \param NL    The preferred representation of a newline.
464   /// \param Space The preferred space between the left side and the message.
465   /// \param IsDot Whether the message will be printed in 'dot' format.
466   void runCheckersForPrintStateJson(raw_ostream &Out, ProgramStateRef State,
467                                     const char *NL = "\n",
468                                     unsigned int Space = 0,
469                                     bool IsDot = false) const;
470 
471   //===--------------------------------------------------------------------===//
472   // Internal registration functions for AST traversing.
473   //===--------------------------------------------------------------------===//
474 
475   // Functions used by the registration mechanism, checkers should not touch
476   // these directly.
477 
478   using CheckDeclFunc =
479       CheckerFn<void (const Decl *, AnalysisManager&, BugReporter &)>;
480 
481   using HandlesDeclFunc = bool (*)(const Decl *D);
482 
483   void _registerForDecl(CheckDeclFunc checkfn, HandlesDeclFunc isForDeclFn);
484 
485   void _registerForBody(CheckDeclFunc checkfn);
486 
487   //===--------------------------------------------------------------------===//
488   // Internal registration functions for path-sensitive checking.
489   //===--------------------------------------------------------------------===//
490 
491   using CheckStmtFunc = CheckerFn<void (const Stmt *, CheckerContext &)>;
492 
493   using CheckObjCMessageFunc =
494       CheckerFn<void (const ObjCMethodCall &, CheckerContext &)>;
495 
496   using CheckCallFunc =
497       CheckerFn<void (const CallEvent &, CheckerContext &)>;
498 
499   using CheckLocationFunc = CheckerFn<void(SVal location, bool isLoad,
500                                            const Stmt *S, CheckerContext &)>;
501 
502   using CheckBindFunc =
503       CheckerFn<void(SVal location, SVal val, const Stmt *S, CheckerContext &)>;
504 
505   using CheckBlockEntranceFunc =
506       CheckerFn<void(const BlockEntrance &, CheckerContext &)>;
507 
508   using CheckEndAnalysisFunc =
509       CheckerFn<void (ExplodedGraph &, BugReporter &, ExprEngine &)>;
510 
511   using CheckBeginFunctionFunc = CheckerFn<void (CheckerContext &)>;
512 
513   using CheckEndFunctionFunc =
514       CheckerFn<void (const ReturnStmt *, CheckerContext &)>;
515 
516   using CheckBranchConditionFunc =
517       CheckerFn<void (const Stmt *, CheckerContext &)>;
518 
519   using CheckNewAllocatorFunc =
520       CheckerFn<void(const CXXAllocatorCall &Call, CheckerContext &)>;
521 
522   using CheckDeadSymbolsFunc =
523       CheckerFn<void (SymbolReaper &, CheckerContext &)>;
524 
525   using CheckLiveSymbolsFunc = CheckerFn<void (ProgramStateRef,SymbolReaper &)>;
526 
527   using CheckRegionChangesFunc =
528       CheckerFn<ProgramStateRef (ProgramStateRef,
529                                  const InvalidatedSymbols *symbols,
530                                  ArrayRef<const MemRegion *> ExplicitRegions,
531                                  ArrayRef<const MemRegion *> Regions,
532                                  const LocationContext *LCtx,
533                                  const CallEvent *Call)>;
534 
535   using CheckPointerEscapeFunc =
536       CheckerFn<ProgramStateRef (ProgramStateRef,
537                                  const InvalidatedSymbols &Escaped,
538                                  const CallEvent *Call, PointerEscapeKind Kind,
539                                  RegionAndSymbolInvalidationTraits *ITraits)>;
540 
541   using EvalAssumeFunc =
542       CheckerFn<ProgramStateRef(ProgramStateRef, SVal cond, bool assumption)>;
543 
544   using EvalCallFunc = CheckerFn<bool (const CallEvent &, CheckerContext &)>;
545 
546   using CheckEndOfTranslationUnit =
547       CheckerFn<void (const TranslationUnitDecl *, AnalysisManager &,
548                       BugReporter &)>;
549 
550   using HandlesStmtFunc = bool (*)(const Stmt *D);
551 
552   void _registerForPreStmt(CheckStmtFunc checkfn,
553                            HandlesStmtFunc isForStmtFn);
554   void _registerForPostStmt(CheckStmtFunc checkfn,
555                             HandlesStmtFunc isForStmtFn);
556 
557   void _registerForPreObjCMessage(CheckObjCMessageFunc checkfn);
558   void _registerForPostObjCMessage(CheckObjCMessageFunc checkfn);
559 
560   void _registerForObjCMessageNil(CheckObjCMessageFunc checkfn);
561 
562   void _registerForPreCall(CheckCallFunc checkfn);
563   void _registerForPostCall(CheckCallFunc checkfn);
564 
565   void _registerForLocation(CheckLocationFunc checkfn);
566 
567   void _registerForBind(CheckBindFunc checkfn);
568 
569   void _registerForBlockEntrance(CheckBlockEntranceFunc checkfn);
570 
571   void _registerForEndAnalysis(CheckEndAnalysisFunc checkfn);
572 
573   void _registerForBeginFunction(CheckBeginFunctionFunc checkfn);
574   void _registerForEndFunction(CheckEndFunctionFunc checkfn);
575 
576   void _registerForBranchCondition(CheckBranchConditionFunc checkfn);
577 
578   void _registerForNewAllocator(CheckNewAllocatorFunc checkfn);
579 
580   void _registerForLiveSymbols(CheckLiveSymbolsFunc checkfn);
581 
582   void _registerForDeadSymbols(CheckDeadSymbolsFunc checkfn);
583 
584   void _registerForRegionChanges(CheckRegionChangesFunc checkfn);
585 
586   void _registerForPointerEscape(CheckPointerEscapeFunc checkfn);
587 
588   void _registerForConstPointerEscape(CheckPointerEscapeFunc checkfn);
589 
590   void _registerForEvalAssume(EvalAssumeFunc checkfn);
591 
592   void _registerForEvalCall(EvalCallFunc checkfn);
593 
594   void _registerForEndOfTranslationUnit(CheckEndOfTranslationUnit checkfn);
595 
596   //===--------------------------------------------------------------------===//
597   // Internal registration functions for events.
598   //===--------------------------------------------------------------------===//
599 
600   using EventTag = void *;
601   using CheckEventFunc = CheckerFn<void (const void *event)>;
602 
603   template <typename EVENT>
_registerListenerForEvent(CheckEventFunc checkfn)604   void _registerListenerForEvent(CheckEventFunc checkfn) {
605     EventInfo &info = Events[&EVENT::Tag];
606     info.Checkers.push_back(checkfn);
607   }
608 
609   template <typename EVENT>
_registerDispatcherForEvent()610   void _registerDispatcherForEvent() {
611     EventInfo &info = Events[&EVENT::Tag];
612     info.HasDispatcher = true;
613   }
614 
615   template <typename EVENT>
_dispatchEvent(const EVENT & event)616   void _dispatchEvent(const EVENT &event) const {
617     EventsTy::const_iterator I = Events.find(&EVENT::Tag);
618     if (I == Events.end())
619       return;
620     const EventInfo &info = I->second;
621     for (const auto &Checker : info.Checkers)
622       Checker(&event);
623   }
624 
625   //===--------------------------------------------------------------------===//
626   // Implementation details.
627   //===--------------------------------------------------------------------===//
628 
629 private:
630   template <typename T>
getTag()631   static void *getTag() { static int tag; return &tag; }
632 
633   llvm::DenseMap<CheckerTag, std::unique_ptr<CheckerBackend>> CheckerTags;
634 
635   struct DeclCheckerInfo {
636     CheckDeclFunc CheckFn;
637     HandlesDeclFunc IsForDeclFn;
638   };
639   std::vector<DeclCheckerInfo> DeclCheckers;
640 
641   std::vector<CheckDeclFunc> BodyCheckers;
642 
643   using CachedDeclCheckers = SmallVector<CheckDeclFunc, 4>;
644   using CachedDeclCheckersMapTy = llvm::DenseMap<unsigned, CachedDeclCheckers>;
645   CachedDeclCheckersMapTy CachedDeclCheckersMap;
646 
647   struct StmtCheckerInfo {
648     CheckStmtFunc CheckFn;
649     HandlesStmtFunc IsForStmtFn;
650     bool IsPreVisit;
651   };
652   std::vector<StmtCheckerInfo> StmtCheckers;
653 
654   using CachedStmtCheckers = SmallVector<CheckStmtFunc, 4>;
655   using CachedStmtCheckersMapTy = llvm::DenseMap<unsigned, CachedStmtCheckers>;
656   CachedStmtCheckersMapTy CachedStmtCheckersMap;
657 
658   const CachedStmtCheckers &getCachedStmtCheckersFor(const Stmt *S,
659                                                      bool isPreVisit);
660 
661   /// Returns the checkers that have registered for callbacks of the
662   /// given \p Kind.
663   const std::vector<CheckObjCMessageFunc> &
664   getObjCMessageCheckers(ObjCMessageVisitKind Kind) const;
665 
666   std::vector<CheckObjCMessageFunc> PreObjCMessageCheckers;
667   std::vector<CheckObjCMessageFunc> PostObjCMessageCheckers;
668   std::vector<CheckObjCMessageFunc> ObjCMessageNilCheckers;
669 
670   std::vector<CheckCallFunc> PreCallCheckers;
671   std::vector<CheckCallFunc> PostCallCheckers;
672 
673   std::vector<CheckLocationFunc> LocationCheckers;
674 
675   std::vector<CheckBindFunc> BindCheckers;
676 
677   std::vector<CheckBlockEntranceFunc> BlockEntranceCheckers;
678 
679   std::vector<CheckEndAnalysisFunc> EndAnalysisCheckers;
680 
681   std::vector<CheckBeginFunctionFunc> BeginFunctionCheckers;
682   std::vector<CheckEndFunctionFunc> EndFunctionCheckers;
683 
684   std::vector<CheckBranchConditionFunc> BranchConditionCheckers;
685 
686   std::vector<CheckNewAllocatorFunc> NewAllocatorCheckers;
687 
688   std::vector<CheckLiveSymbolsFunc> LiveSymbolsCheckers;
689 
690   std::vector<CheckDeadSymbolsFunc> DeadSymbolsCheckers;
691 
692   std::vector<CheckRegionChangesFunc> RegionChangesCheckers;
693 
694   std::vector<CheckPointerEscapeFunc> PointerEscapeCheckers;
695 
696   std::vector<EvalAssumeFunc> EvalAssumeCheckers;
697 
698   std::vector<EvalCallFunc> EvalCallCheckers;
699 
700   std::vector<CheckEndOfTranslationUnit> EndOfTranslationUnitCheckers;
701 
702   struct EventInfo {
703     SmallVector<CheckEventFunc, 4> Checkers;
704     bool HasDispatcher = false;
705 
706     EventInfo() = default;
707   };
708 
709   using EventsTy = llvm::DenseMap<EventTag, EventInfo>;
710   EventsTy Events;
711 };
712 
713 } // namespace ento
714 
715 } // namespace clang
716 
717 #endif // LLVM_CLANG_STATICANALYZER_CORE_CHECKERMANAGER_H
718