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