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 Decl;
32class LocationContext;
33class Stmt;
34class TranslationUnitDecl;
35
36namespace ento {
37
38class AnalysisManager;
39class CXXAllocatorCall;
40class BugReporter;
41class CallEvent;
42class CheckerBase;
43class CheckerContext;
44class CheckerRegistry;
45struct CheckerRegistryData;
46class ExplodedGraph;
47class ExplodedNode;
48class ExplodedNodeSet;
49class ExprEngine;
50struct EvalCallOptions;
51class MemRegion;
52class NodeBuilderContext;
53class ObjCMethodCall;
54class RegionAndSymbolInvalidationTraits;
55class SVal;
56class SymbolReaper;
57
58template <typename T> class CheckerFn;
59
60template <typename RET, typename... Ps>
61class CheckerFn<RET(Ps...)> {
62 using Func = RET (*)(void *, Ps...);
63
64 Func Fn;
65
66public:
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.
78enum 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).
106class CheckerNameRef {
107 friend class ::clang::ento::CheckerRegistry;
108
109 StringRef Name;
110
111 explicit CheckerNameRef(StringRef Name) : Name(Name) {}
112
113public:
114 CheckerNameRef() = default;
115
116 StringRef getName() const { return Name; }
117 operator StringRef() const { return Name; }
118};
119
120enum class ObjCMessageVisitKind {
121 Pre,
122 Post,
123 MessageNil
124};
125
126class 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
135public:
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(x: 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=*/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=*/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(visitKind: 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(visitKind: 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(visitKind: 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=*/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=*/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>
591 void _registerListenerForEvent(CheckEventFunc checkfn) {
592 EventInfo &info = Events[&EVENT::Tag];
593 info.Checkers.push_back(Elt: checkfn);
594 }
595
596 template <typename EVENT>
597 void _registerDispatcherForEvent() {
598 EventInfo &info = Events[&EVENT::Tag];
599 info.HasDispatcher = true;
600 }
601
602 template <typename 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
616private:
617 template <typename CHECKER>
618 static void destruct(void *obj) { delete static_cast<CHECKER *>(obj); }
619
620 template <typename T>
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

source code of clang/include/clang/StaticAnalyzer/Core/CheckerManager.h