xref: /freebsd/contrib/llvm-project/clang/include/clang/StaticAnalyzer/Core/Checker.h (revision 700637cbb5e582861067a11aaca4d053546871d2)
1 //== Checker.h - Registration mechanism for checkers -------------*- 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 //  This file defines Checker, used to create and register checkers.
10 //
11 //===----------------------------------------------------------------------===//
12 
13 #ifndef LLVM_CLANG_STATICANALYZER_CORE_CHECKER_H
14 #define LLVM_CLANG_STATICANALYZER_CORE_CHECKER_H
15 
16 #include "clang/Analysis/ProgramPoint.h"
17 #include "clang/Basic/LangOptions.h"
18 #include "clang/StaticAnalyzer/Core/CheckerManager.h"
19 #include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h"
20 #include "llvm/Support/Casting.h"
21 
22 namespace clang {
23 namespace ento {
24   class BugReporter;
25 
26 namespace check {
27 
28 template <typename DECL>
29 class ASTDecl {
30   template <typename CHECKER>
_checkDecl(void * checker,const Decl * D,AnalysisManager & mgr,BugReporter & BR)31   static void _checkDecl(void *checker, const Decl *D, AnalysisManager& mgr,
32                          BugReporter &BR) {
33     ((const CHECKER *)checker)->checkASTDecl(cast<DECL>(D), mgr, BR);
34   }
35 
_handlesDecl(const Decl * D)36   static bool _handlesDecl(const Decl *D) {
37     return isa<DECL>(D);
38   }
39 public:
40   template <typename CHECKER>
_register(CHECKER * checker,CheckerManager & mgr)41   static void _register(CHECKER *checker, CheckerManager &mgr) {
42     mgr._registerForDecl(CheckerManager::CheckDeclFunc(checker,
43                                                        _checkDecl<CHECKER>),
44                          _handlesDecl);
45   }
46 };
47 
48 class ASTCodeBody {
49   template <typename CHECKER>
_checkBody(void * checker,const Decl * D,AnalysisManager & mgr,BugReporter & BR)50   static void _checkBody(void *checker, const Decl *D, AnalysisManager& mgr,
51                          BugReporter &BR) {
52     ((const CHECKER *)checker)->checkASTCodeBody(D, mgr, BR);
53   }
54 
55 public:
56   template <typename CHECKER>
_register(CHECKER * checker,CheckerManager & mgr)57   static void _register(CHECKER *checker, CheckerManager &mgr) {
58     mgr._registerForBody(CheckerManager::CheckDeclFunc(checker,
59                                                        _checkBody<CHECKER>));
60   }
61 };
62 
63 class EndOfTranslationUnit {
64   template <typename CHECKER>
_checkEndOfTranslationUnit(void * checker,const TranslationUnitDecl * TU,AnalysisManager & mgr,BugReporter & BR)65   static void _checkEndOfTranslationUnit(void *checker,
66                                          const TranslationUnitDecl *TU,
67                                          AnalysisManager& mgr,
68                                          BugReporter &BR) {
69     ((const CHECKER *)checker)->checkEndOfTranslationUnit(TU, mgr, BR);
70   }
71 
72 public:
73   template <typename CHECKER>
_register(CHECKER * checker,CheckerManager & mgr)74   static void _register(CHECKER *checker, CheckerManager &mgr){
75     mgr._registerForEndOfTranslationUnit(
76                               CheckerManager::CheckEndOfTranslationUnit(checker,
77                                           _checkEndOfTranslationUnit<CHECKER>));
78   }
79 };
80 
81 template <typename STMT>
82 class PreStmt {
83   template <typename CHECKER>
_checkStmt(void * checker,const Stmt * S,CheckerContext & C)84   static void _checkStmt(void *checker, const Stmt *S, CheckerContext &C) {
85     ((const CHECKER *)checker)->checkPreStmt(cast<STMT>(S), C);
86   }
87 
_handlesStmt(const Stmt * S)88   static bool _handlesStmt(const Stmt *S) {
89     return isa<STMT>(S);
90   }
91 public:
92   template <typename CHECKER>
_register(CHECKER * checker,CheckerManager & mgr)93   static void _register(CHECKER *checker, CheckerManager &mgr) {
94     mgr._registerForPreStmt(CheckerManager::CheckStmtFunc(checker,
95                                                           _checkStmt<CHECKER>),
96                             _handlesStmt);
97   }
98 };
99 
100 template <typename STMT>
101 class PostStmt {
102   template <typename CHECKER>
_checkStmt(void * checker,const Stmt * S,CheckerContext & C)103   static void _checkStmt(void *checker, const Stmt *S, CheckerContext &C) {
104     ((const CHECKER *)checker)->checkPostStmt(cast<STMT>(S), C);
105   }
106 
_handlesStmt(const Stmt * S)107   static bool _handlesStmt(const Stmt *S) {
108     return isa<STMT>(S);
109   }
110 public:
111   template <typename CHECKER>
_register(CHECKER * checker,CheckerManager & mgr)112   static void _register(CHECKER *checker, CheckerManager &mgr) {
113     mgr._registerForPostStmt(CheckerManager::CheckStmtFunc(checker,
114                                                            _checkStmt<CHECKER>),
115                              _handlesStmt);
116   }
117 };
118 
119 class PreObjCMessage {
120   template <typename CHECKER>
_checkObjCMessage(void * checker,const ObjCMethodCall & msg,CheckerContext & C)121   static void _checkObjCMessage(void *checker, const ObjCMethodCall &msg,
122                                 CheckerContext &C) {
123     ((const CHECKER *)checker)->checkPreObjCMessage(msg, C);
124   }
125 
126 public:
127   template <typename CHECKER>
_register(CHECKER * checker,CheckerManager & mgr)128   static void _register(CHECKER *checker, CheckerManager &mgr) {
129     mgr._registerForPreObjCMessage(
130      CheckerManager::CheckObjCMessageFunc(checker, _checkObjCMessage<CHECKER>));
131   }
132 };
133 
134 class ObjCMessageNil {
135   template <typename CHECKER>
_checkObjCMessage(void * checker,const ObjCMethodCall & msg,CheckerContext & C)136   static void _checkObjCMessage(void *checker, const ObjCMethodCall &msg,
137                                 CheckerContext &C) {
138     ((const CHECKER *)checker)->checkObjCMessageNil(msg, C);
139   }
140 
141 public:
142   template <typename CHECKER>
_register(CHECKER * checker,CheckerManager & mgr)143   static void _register(CHECKER *checker, CheckerManager &mgr) {
144     mgr._registerForObjCMessageNil(
145      CheckerManager::CheckObjCMessageFunc(checker, _checkObjCMessage<CHECKER>));
146   }
147 };
148 
149 class PostObjCMessage {
150   template <typename CHECKER>
_checkObjCMessage(void * checker,const ObjCMethodCall & msg,CheckerContext & C)151   static void _checkObjCMessage(void *checker, const ObjCMethodCall &msg,
152                                 CheckerContext &C) {
153     ((const CHECKER *)checker)->checkPostObjCMessage(msg, C);
154   }
155 
156 public:
157   template <typename CHECKER>
_register(CHECKER * checker,CheckerManager & mgr)158   static void _register(CHECKER *checker, CheckerManager &mgr) {
159     mgr._registerForPostObjCMessage(
160      CheckerManager::CheckObjCMessageFunc(checker, _checkObjCMessage<CHECKER>));
161   }
162 };
163 
164 class PreCall {
165   template <typename CHECKER>
_checkCall(void * checker,const CallEvent & msg,CheckerContext & C)166   static void _checkCall(void *checker, const CallEvent &msg,
167                          CheckerContext &C) {
168     ((const CHECKER *)checker)->checkPreCall(msg, C);
169   }
170 
171 public:
172   template <typename CHECKER>
_register(CHECKER * checker,CheckerManager & mgr)173   static void _register(CHECKER *checker, CheckerManager &mgr) {
174     mgr._registerForPreCall(
175      CheckerManager::CheckCallFunc(checker, _checkCall<CHECKER>));
176   }
177 };
178 
179 class PostCall {
180   template <typename CHECKER>
_checkCall(void * checker,const CallEvent & msg,CheckerContext & C)181   static void _checkCall(void *checker, const CallEvent &msg,
182                          CheckerContext &C) {
183     ((const CHECKER *)checker)->checkPostCall(msg, C);
184   }
185 
186 public:
187   template <typename CHECKER>
_register(CHECKER * checker,CheckerManager & mgr)188   static void _register(CHECKER *checker, CheckerManager &mgr) {
189     mgr._registerForPostCall(
190      CheckerManager::CheckCallFunc(checker, _checkCall<CHECKER>));
191   }
192 };
193 
194 class Location {
195   template <typename CHECKER>
_checkLocation(void * checker,SVal location,bool isLoad,const Stmt * S,CheckerContext & C)196   static void _checkLocation(void *checker, SVal location, bool isLoad,
197                              const Stmt *S, CheckerContext &C) {
198     ((const CHECKER *)checker)->checkLocation(location, isLoad, S, C);
199   }
200 
201 public:
202   template <typename CHECKER>
_register(CHECKER * checker,CheckerManager & mgr)203   static void _register(CHECKER *checker, CheckerManager &mgr) {
204     mgr._registerForLocation(
205            CheckerManager::CheckLocationFunc(checker, _checkLocation<CHECKER>));
206   }
207 };
208 
209 class Bind {
210   template <typename CHECKER>
_checkBind(void * checker,SVal location,SVal val,const Stmt * S,CheckerContext & C)211   static void _checkBind(void *checker, SVal location, SVal val, const Stmt *S,
212                          CheckerContext &C) {
213     ((const CHECKER *)checker)->checkBind(location, val, S, C);
214   }
215 
216 public:
217   template <typename CHECKER>
_register(CHECKER * checker,CheckerManager & mgr)218   static void _register(CHECKER *checker, CheckerManager &mgr) {
219     mgr._registerForBind(
220            CheckerManager::CheckBindFunc(checker, _checkBind<CHECKER>));
221   }
222 };
223 
224 class BlockEntrance {
225   template <typename CHECKER>
_checkBlockEntrance(void * Checker,const clang::BlockEntrance & Entrance,CheckerContext & C)226   static void _checkBlockEntrance(void *Checker,
227                                   const clang::BlockEntrance &Entrance,
228                                   CheckerContext &C) {
229     ((const CHECKER *)Checker)->checkBlockEntrance(Entrance, C);
230   }
231 
232 public:
233   template <typename CHECKER>
_register(CHECKER * checker,CheckerManager & mgr)234   static void _register(CHECKER *checker, CheckerManager &mgr) {
235     mgr._registerForBlockEntrance(CheckerManager::CheckBlockEntranceFunc(
236         checker, _checkBlockEntrance<CHECKER>));
237   }
238 };
239 
240 class EndAnalysis {
241   template <typename CHECKER>
_checkEndAnalysis(void * checker,ExplodedGraph & G,BugReporter & BR,ExprEngine & Eng)242   static void _checkEndAnalysis(void *checker, ExplodedGraph &G,
243                                 BugReporter &BR, ExprEngine &Eng) {
244     ((const CHECKER *)checker)->checkEndAnalysis(G, BR, Eng);
245   }
246 
247 public:
248   template <typename CHECKER>
_register(CHECKER * checker,CheckerManager & mgr)249   static void _register(CHECKER *checker, CheckerManager &mgr) {
250     mgr._registerForEndAnalysis(
251      CheckerManager::CheckEndAnalysisFunc(checker, _checkEndAnalysis<CHECKER>));
252   }
253 };
254 
255 class BeginFunction {
256   template <typename CHECKER>
_checkBeginFunction(void * checker,CheckerContext & C)257   static void _checkBeginFunction(void *checker, CheckerContext &C) {
258     ((const CHECKER *)checker)->checkBeginFunction(C);
259   }
260 
261 public:
262   template <typename CHECKER>
_register(CHECKER * checker,CheckerManager & mgr)263   static void _register(CHECKER *checker, CheckerManager &mgr) {
264     mgr._registerForBeginFunction(CheckerManager::CheckBeginFunctionFunc(
265         checker, _checkBeginFunction<CHECKER>));
266   }
267 };
268 
269 class EndFunction {
270   template <typename CHECKER>
_checkEndFunction(void * checker,const ReturnStmt * RS,CheckerContext & C)271   static void _checkEndFunction(void *checker, const ReturnStmt *RS,
272                                 CheckerContext &C) {
273     ((const CHECKER *)checker)->checkEndFunction(RS, C);
274   }
275 
276 public:
277   template <typename CHECKER>
_register(CHECKER * checker,CheckerManager & mgr)278   static void _register(CHECKER *checker, CheckerManager &mgr) {
279     mgr._registerForEndFunction(
280      CheckerManager::CheckEndFunctionFunc(checker, _checkEndFunction<CHECKER>));
281   }
282 };
283 
284 class BranchCondition {
285   template <typename CHECKER>
_checkBranchCondition(void * checker,const Stmt * Condition,CheckerContext & C)286   static void _checkBranchCondition(void *checker, const Stmt *Condition,
287                                     CheckerContext & C) {
288     ((const CHECKER *)checker)->checkBranchCondition(Condition, C);
289   }
290 
291 public:
292   template <typename CHECKER>
_register(CHECKER * checker,CheckerManager & mgr)293   static void _register(CHECKER *checker, CheckerManager &mgr) {
294     mgr._registerForBranchCondition(
295       CheckerManager::CheckBranchConditionFunc(checker,
296                                                _checkBranchCondition<CHECKER>));
297   }
298 };
299 
300 class NewAllocator {
301   template <typename CHECKER>
_checkNewAllocator(void * checker,const CXXAllocatorCall & Call,CheckerContext & C)302   static void _checkNewAllocator(void *checker, const CXXAllocatorCall &Call,
303                                  CheckerContext &C) {
304     ((const CHECKER *)checker)->checkNewAllocator(Call, C);
305   }
306 
307 public:
308   template <typename CHECKER>
_register(CHECKER * checker,CheckerManager & mgr)309   static void _register(CHECKER *checker, CheckerManager &mgr) {
310     mgr._registerForNewAllocator(
311         CheckerManager::CheckNewAllocatorFunc(checker,
312                                               _checkNewAllocator<CHECKER>));
313   }
314 };
315 
316 class LiveSymbols {
317   template <typename CHECKER>
_checkLiveSymbols(void * checker,ProgramStateRef state,SymbolReaper & SR)318   static void _checkLiveSymbols(void *checker, ProgramStateRef state,
319                                 SymbolReaper &SR) {
320     ((const CHECKER *)checker)->checkLiveSymbols(state, SR);
321   }
322 
323 public:
324   template <typename CHECKER>
_register(CHECKER * checker,CheckerManager & mgr)325   static void _register(CHECKER *checker, CheckerManager &mgr) {
326     mgr._registerForLiveSymbols(
327      CheckerManager::CheckLiveSymbolsFunc(checker, _checkLiveSymbols<CHECKER>));
328   }
329 };
330 
331 class DeadSymbols {
332   template <typename CHECKER>
_checkDeadSymbols(void * checker,SymbolReaper & SR,CheckerContext & C)333   static void _checkDeadSymbols(void *checker,
334                                 SymbolReaper &SR, CheckerContext &C) {
335     ((const CHECKER *)checker)->checkDeadSymbols(SR, C);
336   }
337 
338 public:
339   template <typename CHECKER>
_register(CHECKER * checker,CheckerManager & mgr)340   static void _register(CHECKER *checker, CheckerManager &mgr) {
341     mgr._registerForDeadSymbols(
342      CheckerManager::CheckDeadSymbolsFunc(checker, _checkDeadSymbols<CHECKER>));
343   }
344 };
345 
346 class RegionChanges {
347   template <typename CHECKER>
348   static ProgramStateRef
_checkRegionChanges(void * checker,ProgramStateRef state,const InvalidatedSymbols * invalidated,ArrayRef<const MemRegion * > Explicits,ArrayRef<const MemRegion * > Regions,const LocationContext * LCtx,const CallEvent * Call)349   _checkRegionChanges(void *checker,
350                       ProgramStateRef state,
351                       const InvalidatedSymbols *invalidated,
352                       ArrayRef<const MemRegion *> Explicits,
353                       ArrayRef<const MemRegion *> Regions,
354                       const LocationContext *LCtx,
355                       const CallEvent *Call) {
356     return ((const CHECKER *) checker)->checkRegionChanges(state, invalidated,
357                                                            Explicits, Regions,
358                                                            LCtx, Call);
359   }
360 
361 public:
362   template <typename CHECKER>
_register(CHECKER * checker,CheckerManager & mgr)363   static void _register(CHECKER *checker, CheckerManager &mgr) {
364     mgr._registerForRegionChanges(
365           CheckerManager::CheckRegionChangesFunc(checker,
366                                                  _checkRegionChanges<CHECKER>));
367   }
368 };
369 
370 class PointerEscape {
371   template <typename CHECKER>
372   static ProgramStateRef
_checkPointerEscape(void * Checker,ProgramStateRef State,const InvalidatedSymbols & Escaped,const CallEvent * Call,PointerEscapeKind Kind,RegionAndSymbolInvalidationTraits * ETraits)373   _checkPointerEscape(void *Checker,
374                      ProgramStateRef State,
375                      const InvalidatedSymbols &Escaped,
376                      const CallEvent *Call,
377                      PointerEscapeKind Kind,
378                      RegionAndSymbolInvalidationTraits *ETraits) {
379 
380     if (!ETraits)
381       return ((const CHECKER *)Checker)->checkPointerEscape(State,
382                                                             Escaped,
383                                                             Call,
384                                                             Kind);
385 
386     InvalidatedSymbols RegularEscape;
387     for (SymbolRef Sym : Escaped)
388       if (!ETraits->hasTrait(
389               Sym, RegionAndSymbolInvalidationTraits::TK_PreserveContents) &&
390           !ETraits->hasTrait(
391               Sym, RegionAndSymbolInvalidationTraits::TK_SuppressEscape))
392         RegularEscape.insert(Sym);
393 
394     if (RegularEscape.empty())
395       return State;
396 
397     return ((const CHECKER *)Checker)->checkPointerEscape(State,
398                                                           RegularEscape,
399                                                           Call,
400                                                           Kind);
401   }
402 
403 public:
404   template <typename CHECKER>
_register(CHECKER * checker,CheckerManager & mgr)405   static void _register(CHECKER *checker, CheckerManager &mgr) {
406     mgr._registerForPointerEscape(
407           CheckerManager::CheckPointerEscapeFunc(checker,
408                                                 _checkPointerEscape<CHECKER>));
409   }
410 };
411 
412 class ConstPointerEscape {
413   template <typename CHECKER>
414   static ProgramStateRef
_checkConstPointerEscape(void * Checker,ProgramStateRef State,const InvalidatedSymbols & Escaped,const CallEvent * Call,PointerEscapeKind Kind,RegionAndSymbolInvalidationTraits * ETraits)415   _checkConstPointerEscape(void *Checker,
416                       ProgramStateRef State,
417                       const InvalidatedSymbols &Escaped,
418                       const CallEvent *Call,
419                       PointerEscapeKind Kind,
420                       RegionAndSymbolInvalidationTraits *ETraits) {
421 
422     if (!ETraits)
423       return State;
424 
425     InvalidatedSymbols ConstEscape;
426     for (SymbolRef Sym : Escaped) {
427       if (ETraits->hasTrait(
428               Sym, RegionAndSymbolInvalidationTraits::TK_PreserveContents) &&
429           !ETraits->hasTrait(
430               Sym, RegionAndSymbolInvalidationTraits::TK_SuppressEscape))
431         ConstEscape.insert(Sym);
432     }
433 
434     if (ConstEscape.empty())
435       return State;
436 
437     return ((const CHECKER *)Checker)->checkConstPointerEscape(State,
438                                                                ConstEscape,
439                                                                Call,
440                                                                Kind);
441   }
442 
443 public:
444   template <typename CHECKER>
_register(CHECKER * checker,CheckerManager & mgr)445   static void _register(CHECKER *checker, CheckerManager &mgr) {
446     mgr._registerForPointerEscape(
447       CheckerManager::CheckPointerEscapeFunc(checker,
448                                             _checkConstPointerEscape<CHECKER>));
449   }
450 };
451 
452 
453 template <typename EVENT>
454 class Event {
455   template <typename CHECKER>
_checkEvent(void * checker,const void * event)456   static void _checkEvent(void *checker, const void *event) {
457     ((const CHECKER *)checker)->checkEvent(*(const EVENT *)event);
458   }
459 public:
460   template <typename CHECKER>
_register(CHECKER * checker,CheckerManager & mgr)461   static void _register(CHECKER *checker, CheckerManager &mgr) {
462     mgr._registerListenerForEvent<EVENT>(
463                  CheckerManager::CheckEventFunc(checker, _checkEvent<CHECKER>));
464   }
465 };
466 
467 } // end check namespace
468 
469 namespace eval {
470 
471 class Assume {
472   template <typename CHECKER>
_evalAssume(void * checker,ProgramStateRef state,SVal cond,bool assumption)473   static ProgramStateRef _evalAssume(void *checker, ProgramStateRef state,
474                                      SVal cond, bool assumption) {
475     return ((const CHECKER *)checker)->evalAssume(state, cond, assumption);
476   }
477 
478 public:
479   template <typename CHECKER>
_register(CHECKER * checker,CheckerManager & mgr)480   static void _register(CHECKER *checker, CheckerManager &mgr) {
481     mgr._registerForEvalAssume(
482                  CheckerManager::EvalAssumeFunc(checker, _evalAssume<CHECKER>));
483   }
484 };
485 
486 class Call {
487   template <typename CHECKER>
_evalCall(void * checker,const CallEvent & Call,CheckerContext & C)488   static bool _evalCall(void *checker, const CallEvent &Call,
489                         CheckerContext &C) {
490     return ((const CHECKER *)checker)->evalCall(Call, C);
491   }
492 
493 public:
494   template <typename CHECKER>
_register(CHECKER * checker,CheckerManager & mgr)495   static void _register(CHECKER *checker, CheckerManager &mgr) {
496     mgr._registerForEvalCall(
497                      CheckerManager::EvalCallFunc(checker, _evalCall<CHECKER>));
498   }
499 };
500 
501 } // end eval namespace
502 
503 /// A `CheckerFrontend` instance is what the user recognizes as "one checker":
504 /// it has a public canonical name (injected from the `CheckerManager`), can be
505 /// enabled or disabled, can have associated checker options and can be printed
506 /// as the "source" of bug reports.
507 /// The singleton instance of a simple `Checker<...>` is-a `CheckerFrontend`
508 /// (for historical reasons, to preserve old straightforward code), while the
509 /// singleton instance of a `CheckerFamily<...>` class owns multiple
510 /// `CheckerFrontend` instances as data members.
511 /// Modeling checkers that are hidden from the user but can be enabled or
512 /// disabled separately (as dependencies of other checkers) are also considered
513 /// to be `CheckerFrontend`s.
514 class CheckerFrontend {
515   /// The `Name` is nullopt if and only if the checker is disabled.
516   std::optional<CheckerNameRef> Name;
517 
518 public:
enable(CheckerManager & Mgr)519   void enable(CheckerManager &Mgr) {
520     assert(!Name && "Checker part registered twice!");
521     Name = Mgr.getCurrentCheckerName();
522   }
isEnabled()523   bool isEnabled() const { return Name.has_value(); }
getName()524   CheckerNameRef getName() const { return *Name; }
525 };
526 
527 /// `CheckerBackend` is an abstract base class that serves as the common
528 /// ancestor of all the `Checker<...>` and `CheckerFamily<...>` classes which
529 /// can create `ExplodedNode`s (by acting as a `ProgramPointTag`) and can be
530 /// registered to handle various checker callbacks. (Moreover the debug
531 /// callback `printState` is also introduced here.)
532 class CheckerBackend : public ProgramPointTag {
533 public:
534   /// Debug state dump callback, see CheckerManager::runCheckersForPrintState.
535   /// Default implementation does nothing.
536   virtual void printState(raw_ostream &Out, ProgramStateRef State,
537                           const char *NL, const char *Sep) const;
538 };
539 
540 /// The non-templated common ancestor of all the simple `Checker<...>` classes.
541 class CheckerBase : public CheckerFrontend, public CheckerBackend {
542 public:
543   /// Attached to nodes created by this checker class when the ExplodedGraph is
544   /// dumped for debugging.
545   StringRef getDebugTag() const override;
546 };
547 
548 /// Simple checker classes that implement one frontend (i.e. checker name)
549 /// should derive from this template and specify all the implemented callbacks
550 /// (i.e. classes like `check::PreStmt` or `eval::Call`) as template arguments
551 /// of `Checker`.
552 template <typename... CHECKs>
553 class Checker : public CheckerBase, public CHECKs... {
554 public:
555   using BlockEntrance = clang::BlockEntrance;
556 
557   template <typename CHECKER>
_register(CHECKER * Chk,CheckerManager & Mgr)558   static void _register(CHECKER *Chk, CheckerManager &Mgr) {
559     (CHECKs::_register(Chk, Mgr), ...);
560   }
561 };
562 
563 /// Checker families (where a single backend class implements multiple related
564 /// frontends) should derive from this template and specify all the implemented
565 /// callbacks (i.e. classes like `check::PreStmt` or `eval::Call`) as template
566 /// arguments of `FamilyChecker.`
567 ///
568 /// NOTE: Classes deriving from `CheckerFamily` must implement the pure virtual
569 /// method `StringRef getDebugTag()` which is inherited from `ProgramPointTag`
570 /// and should return the name of the class as a string.
571 ///
572 /// Obviously, this boilerplate is not a good thing, but unfortunately there is
573 /// no portable way to stringify the name of a type (e.g. class), so any
574 /// portable implementation of `getDebugTag` would need to take the name of
575 /// the class from *somewhere* where it's present as a string -- and then
576 /// directly placing it in a method override is much simpler than loading it
577 /// from `Checkers.td`.
578 ///
579 /// Note that the existing `CLASS` field in `Checkers.td` is not suitable for
580 /// our goals, because instead of storing the same class name for each
581 /// frontend, in fact each frontendchecker needs to have its own unique value
582 /// there (to ensure that the names of the register methods are all unique).
583 template <typename... CHECKs>
584 class CheckerFamily : public CheckerBackend, public CHECKs... {
585 public:
586   using BlockEntrance = clang::BlockEntrance;
587 
588   template <typename CHECKER>
_register(CHECKER * Chk,CheckerManager & Mgr)589   static void _register(CHECKER *Chk, CheckerManager &Mgr) {
590     (CHECKs::_register(Chk, Mgr), ...);
591   }
592 };
593 
594 template <typename EVENT>
595 class EventDispatcher {
596   CheckerManager *Mgr = nullptr;
597 public:
598   EventDispatcher() = default;
599 
600   template <typename CHECKER>
_register(CHECKER * checker,CheckerManager & mgr)601   static void _register(CHECKER *checker, CheckerManager &mgr) {
602     mgr._registerDispatcherForEvent<EVENT>();
603     static_cast<EventDispatcher<EVENT> *>(checker)->Mgr = &mgr;
604   }
605 
dispatchEvent(const EVENT & event)606   void dispatchEvent(const EVENT &event) const {
607     Mgr->_dispatchEvent(event);
608   }
609 };
610 
611 /// We dereferenced a location that may be null.
612 struct ImplicitNullDerefEvent {
613   SVal Location;
614   bool IsLoad;
615   ExplodedNode *SinkNode;
616   BugReporter *BR;
617   // When true, the dereference is in the source code directly. When false, the
618   // dereference might happen later (for example pointer passed to a parameter
619   // that is marked with nonnull attribute.)
620   bool IsDirectDereference;
621 
622   static int Tag;
623 };
624 
625 } // end ento namespace
626 
627 } // end clang namespace
628 
629 #endif
630