xref: /freebsd/contrib/llvm-project/clang/include/clang/StaticAnalyzer/Core/CheckerManager.h (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
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 class 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 
CheckerFn(CheckerBase * checker,Func fn)69   CheckerFn(CheckerBase *checker, Func fn) : Fn(fn), Checker(checker) {}
70 
operator()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 
CheckerNameRef(StringRef Name)111   explicit CheckerNameRef(StringRef Name) : Name(Name) {}
112 
113 public:
114   CheckerNameRef() = default;
115 
getName()116   StringRef getName() const { return Name; }
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 
167   void finishedCheckerRegistration();
168 
getLangOpts()169   const LangOptions &getLangOpts() const { return LangOpts; }
getAnalyzerOptions()170   const AnalyzerOptions &getAnalyzerOptions() const { return AOptions; }
getPreprocessor()171   const Preprocessor &getPreprocessor() const {
172     assert(PP);
173     return *PP;
174   }
getCheckerRegistryData()175   const CheckerRegistryData &getCheckerRegistryData() const {
176     return *RegistryData;
177   }
getDiagnostics()178   DiagnosticsEngine &getDiagnostics() const { return Diags; }
getASTContext()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>
registerChecker(AT &&...Args)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>
getChecker()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
runCheckersForPreStmt(ExplodedNodeSet & Dst,const ExplodedNodeSet & Src,const Stmt * S,ExprEngine & Eng)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.
runCheckersForPreObjCMessage(ExplodedNodeSet & Dst,const ExplodedNodeSet & Src,const ObjCMethodCall & msg,ExprEngine & Eng)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.
runCheckersForObjCMessageNil(ExplodedNodeSet & Dst,const ExplodedNodeSet & Src,const ObjCMethodCall & msg,ExprEngine & Eng)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.
runCheckersForPreCall(ExplodedNodeSet & Dst,const ExplodedNodeSet & Src,const CallEvent & Call,ExprEngine & Eng)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 = CheckerFn<void(SVal location, bool isLoad,
492                                            const Stmt *S, CheckerContext &)>;
493 
494   using CheckBindFunc =
495       CheckerFn<void(SVal location, SVal val, const Stmt *S, CheckerContext &)>;
496 
497   using CheckEndAnalysisFunc =
498       CheckerFn<void (ExplodedGraph &, BugReporter &, ExprEngine &)>;
499 
500   using CheckBeginFunctionFunc = CheckerFn<void (CheckerContext &)>;
501 
502   using CheckEndFunctionFunc =
503       CheckerFn<void (const ReturnStmt *, CheckerContext &)>;
504 
505   using CheckBranchConditionFunc =
506       CheckerFn<void (const Stmt *, CheckerContext &)>;
507 
508   using CheckNewAllocatorFunc =
509       CheckerFn<void(const CXXAllocatorCall &Call, CheckerContext &)>;
510 
511   using CheckDeadSymbolsFunc =
512       CheckerFn<void (SymbolReaper &, CheckerContext &)>;
513 
514   using CheckLiveSymbolsFunc = CheckerFn<void (ProgramStateRef,SymbolReaper &)>;
515 
516   using CheckRegionChangesFunc =
517       CheckerFn<ProgramStateRef (ProgramStateRef,
518                                  const InvalidatedSymbols *symbols,
519                                  ArrayRef<const MemRegion *> ExplicitRegions,
520                                  ArrayRef<const MemRegion *> Regions,
521                                  const LocationContext *LCtx,
522                                  const CallEvent *Call)>;
523 
524   using CheckPointerEscapeFunc =
525       CheckerFn<ProgramStateRef (ProgramStateRef,
526                                  const InvalidatedSymbols &Escaped,
527                                  const CallEvent *Call, PointerEscapeKind Kind,
528                                  RegionAndSymbolInvalidationTraits *ITraits)>;
529 
530   using EvalAssumeFunc =
531       CheckerFn<ProgramStateRef(ProgramStateRef, SVal cond, bool assumption)>;
532 
533   using EvalCallFunc = CheckerFn<bool (const CallEvent &, CheckerContext &)>;
534 
535   using CheckEndOfTranslationUnit =
536       CheckerFn<void (const TranslationUnitDecl *, AnalysisManager &,
537                       BugReporter &)>;
538 
539   using HandlesStmtFunc = bool (*)(const Stmt *D);
540 
541   void _registerForPreStmt(CheckStmtFunc checkfn,
542                            HandlesStmtFunc isForStmtFn);
543   void _registerForPostStmt(CheckStmtFunc checkfn,
544                             HandlesStmtFunc isForStmtFn);
545 
546   void _registerForPreObjCMessage(CheckObjCMessageFunc checkfn);
547   void _registerForPostObjCMessage(CheckObjCMessageFunc checkfn);
548 
549   void _registerForObjCMessageNil(CheckObjCMessageFunc checkfn);
550 
551   void _registerForPreCall(CheckCallFunc checkfn);
552   void _registerForPostCall(CheckCallFunc checkfn);
553 
554   void _registerForLocation(CheckLocationFunc checkfn);
555 
556   void _registerForBind(CheckBindFunc checkfn);
557 
558   void _registerForEndAnalysis(CheckEndAnalysisFunc checkfn);
559 
560   void _registerForBeginFunction(CheckBeginFunctionFunc checkfn);
561   void _registerForEndFunction(CheckEndFunctionFunc checkfn);
562 
563   void _registerForBranchCondition(CheckBranchConditionFunc checkfn);
564 
565   void _registerForNewAllocator(CheckNewAllocatorFunc checkfn);
566 
567   void _registerForLiveSymbols(CheckLiveSymbolsFunc checkfn);
568 
569   void _registerForDeadSymbols(CheckDeadSymbolsFunc checkfn);
570 
571   void _registerForRegionChanges(CheckRegionChangesFunc checkfn);
572 
573   void _registerForPointerEscape(CheckPointerEscapeFunc checkfn);
574 
575   void _registerForConstPointerEscape(CheckPointerEscapeFunc checkfn);
576 
577   void _registerForEvalAssume(EvalAssumeFunc checkfn);
578 
579   void _registerForEvalCall(EvalCallFunc checkfn);
580 
581   void _registerForEndOfTranslationUnit(CheckEndOfTranslationUnit checkfn);
582 
583 //===----------------------------------------------------------------------===//
584 // Internal registration functions for events.
585 //===----------------------------------------------------------------------===//
586 
587   using EventTag = void *;
588   using CheckEventFunc = CheckerFn<void (const void *event)>;
589 
590   template <typename EVENT>
_registerListenerForEvent(CheckEventFunc checkfn)591   void _registerListenerForEvent(CheckEventFunc checkfn) {
592     EventInfo &info = Events[&EVENT::Tag];
593     info.Checkers.push_back(checkfn);
594   }
595 
596   template <typename EVENT>
_registerDispatcherForEvent()597   void _registerDispatcherForEvent() {
598     EventInfo &info = Events[&EVENT::Tag];
599     info.HasDispatcher = true;
600   }
601 
602   template <typename EVENT>
_dispatchEvent(const EVENT & event)603   void _dispatchEvent(const EVENT &event) const {
604     EventsTy::const_iterator I = Events.find(&EVENT::Tag);
605     if (I == Events.end())
606       return;
607     const EventInfo &info = I->second;
608     for (const auto &Checker : info.Checkers)
609       Checker(&event);
610   }
611 
612 //===----------------------------------------------------------------------===//
613 // Implementation details.
614 //===----------------------------------------------------------------------===//
615 
616 private:
617   template <typename CHECKER>
destruct(void * obj)618   static void destruct(void *obj) { delete static_cast<CHECKER *>(obj); }
619 
620   template <typename T>
getTag()621   static void *getTag() { static int tag; return &tag; }
622 
623   llvm::DenseMap<CheckerTag, CheckerRef> CheckerTags;
624 
625   std::vector<CheckerDtor> CheckerDtors;
626 
627   struct DeclCheckerInfo {
628     CheckDeclFunc CheckFn;
629     HandlesDeclFunc IsForDeclFn;
630   };
631   std::vector<DeclCheckerInfo> DeclCheckers;
632 
633   std::vector<CheckDeclFunc> BodyCheckers;
634 
635   using CachedDeclCheckers = SmallVector<CheckDeclFunc, 4>;
636   using CachedDeclCheckersMapTy = llvm::DenseMap<unsigned, CachedDeclCheckers>;
637   CachedDeclCheckersMapTy CachedDeclCheckersMap;
638 
639   struct StmtCheckerInfo {
640     CheckStmtFunc CheckFn;
641     HandlesStmtFunc IsForStmtFn;
642     bool IsPreVisit;
643   };
644   std::vector<StmtCheckerInfo> StmtCheckers;
645 
646   using CachedStmtCheckers = SmallVector<CheckStmtFunc, 4>;
647   using CachedStmtCheckersMapTy = llvm::DenseMap<unsigned, CachedStmtCheckers>;
648   CachedStmtCheckersMapTy CachedStmtCheckersMap;
649 
650   const CachedStmtCheckers &getCachedStmtCheckersFor(const Stmt *S,
651                                                      bool isPreVisit);
652 
653   /// Returns the checkers that have registered for callbacks of the
654   /// given \p Kind.
655   const std::vector<CheckObjCMessageFunc> &
656   getObjCMessageCheckers(ObjCMessageVisitKind Kind) const;
657 
658   std::vector<CheckObjCMessageFunc> PreObjCMessageCheckers;
659   std::vector<CheckObjCMessageFunc> PostObjCMessageCheckers;
660   std::vector<CheckObjCMessageFunc> ObjCMessageNilCheckers;
661 
662   std::vector<CheckCallFunc> PreCallCheckers;
663   std::vector<CheckCallFunc> PostCallCheckers;
664 
665   std::vector<CheckLocationFunc> LocationCheckers;
666 
667   std::vector<CheckBindFunc> BindCheckers;
668 
669   std::vector<CheckEndAnalysisFunc> EndAnalysisCheckers;
670 
671   std::vector<CheckBeginFunctionFunc> BeginFunctionCheckers;
672   std::vector<CheckEndFunctionFunc> EndFunctionCheckers;
673 
674   std::vector<CheckBranchConditionFunc> BranchConditionCheckers;
675 
676   std::vector<CheckNewAllocatorFunc> NewAllocatorCheckers;
677 
678   std::vector<CheckLiveSymbolsFunc> LiveSymbolsCheckers;
679 
680   std::vector<CheckDeadSymbolsFunc> DeadSymbolsCheckers;
681 
682   std::vector<CheckRegionChangesFunc> RegionChangesCheckers;
683 
684   std::vector<CheckPointerEscapeFunc> PointerEscapeCheckers;
685 
686   std::vector<EvalAssumeFunc> EvalAssumeCheckers;
687 
688   std::vector<EvalCallFunc> EvalCallCheckers;
689 
690   std::vector<CheckEndOfTranslationUnit> EndOfTranslationUnitCheckers;
691 
692   struct EventInfo {
693     SmallVector<CheckEventFunc, 4> Checkers;
694     bool HasDispatcher = false;
695 
696     EventInfo() = default;
697   };
698 
699   using EventsTy = llvm::DenseMap<EventTag, EventInfo>;
700   EventsTy Events;
701 };
702 
703 } // namespace ento
704 
705 } // namespace clang
706 
707 #endif // LLVM_CLANG_STATICANALYZER_CORE_CHECKERMANAGER_H
708