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 CheckerFrontend;
43class CheckerBackend;
44class CheckerContext;
45class CheckerRegistry;
46struct CheckerRegistryData;
47class ExplodedGraph;
48class ExplodedNode;
49class ExplodedNodeSet;
50class ExprEngine;
51struct EvalCallOptions;
52class MemRegion;
53class 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 CheckerBackend *Checker;
69
70 CheckerFn(CheckerBackend *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 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 const LangOptions &getLangOpts() const { return LangOpts; }
168 const AnalyzerOptions &getAnalyzerOptions() const { return AOptions; }
169 const Preprocessor &getPreprocessor() const {
170 assert(PP);
171 return *PP;
172 }
173 const CheckerRegistryData &getCheckerRegistryData() const {
174 return *RegistryData;
175 }
176 DiagnosticsEngine &getDiagnostics() const { return Diags; }
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>
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>
218 CHECKER *registerChecker(AT &&...Args) {
219 CHECKER *Chk = getChecker<CHECKER>(std::forward<AT>(Args)...);
220 Chk->enable(*this);
221 return Chk;
222 }
223
224 template <typename CHECKER> bool isRegisteredChecker() {
225 return CheckerTags.contains(Val: 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
250 void runCheckersForPreStmt(ExplodedNodeSet &Dst,
251 const ExplodedNodeSet &Src,
252 const Stmt *S,
253 ExprEngine &Eng) {
254 runCheckersForStmt(/*isPreVisit=*/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=*/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.
278 void runCheckersForPreObjCMessage(ExplodedNodeSet &Dst,
279 const ExplodedNodeSet &Src,
280 const ObjCMethodCall &msg,
281 ExprEngine &Eng) {
282 runCheckersForObjCMessage(visitKind: 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(visitKind: ObjCMessageVisitKind::Post, Dst, Src, msg, Eng,
292 wasInlined);
293 }
294
295 /// Run checkers for visiting an obj-c message to nil.
296 void runCheckersForObjCMessageNil(ExplodedNodeSet &Dst,
297 const ExplodedNodeSet &Src,
298 const ObjCMethodCall &msg,
299 ExprEngine &Eng) {
300 runCheckersForObjCMessage(visitKind: 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.
312 void runCheckersForPreCall(ExplodedNodeSet &Dst, const ExplodedNodeSet &Src,
313 const CallEvent &Call, ExprEngine &Eng) {
314 runCheckersForCallEvent(/*isPreVisit=*/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=*/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>
604 void _registerListenerForEvent(CheckEventFunc checkfn) {
605 EventInfo &info = Events[&EVENT::Tag];
606 info.Checkers.push_back(Elt: checkfn);
607 }
608
609 template <typename EVENT>
610 void _registerDispatcherForEvent() {
611 EventInfo &info = Events[&EVENT::Tag];
612 info.HasDispatcher = true;
613 }
614
615 template <typename 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
629private:
630 template <typename T>
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

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