Checker.h revision 360784
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
22namespace clang {
23namespace ento {
24  class BugReporter;
25
26namespace check {
27
28template <typename DECL>
29class ASTDecl {
30  template <typename CHECKER>
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
36  static bool _handlesDecl(const Decl *D) {
37    return isa<DECL>(D);
38  }
39public:
40  template <typename CHECKER>
41  static void _register(CHECKER *checker, CheckerManager &mgr) {
42    mgr._registerForDecl(CheckerManager::CheckDeclFunc(checker,
43                                                       _checkDecl<CHECKER>),
44                         _handlesDecl);
45  }
46};
47
48class ASTCodeBody {
49  template <typename CHECKER>
50  static void _checkBody(void *checker, const Decl *D, AnalysisManager& mgr,
51                         BugReporter &BR) {
52    ((const CHECKER *)checker)->checkASTCodeBody(D, mgr, BR);
53  }
54
55public:
56  template <typename CHECKER>
57  static void _register(CHECKER *checker, CheckerManager &mgr) {
58    mgr._registerForBody(CheckerManager::CheckDeclFunc(checker,
59                                                       _checkBody<CHECKER>));
60  }
61};
62
63class EndOfTranslationUnit {
64  template <typename CHECKER>
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
72public:
73  template <typename CHECKER>
74  static void _register(CHECKER *checker, CheckerManager &mgr){
75    mgr._registerForEndOfTranslationUnit(
76                              CheckerManager::CheckEndOfTranslationUnit(checker,
77                                          _checkEndOfTranslationUnit<CHECKER>));
78  }
79};
80
81template <typename STMT>
82class PreStmt {
83  template <typename CHECKER>
84  static void _checkStmt(void *checker, const Stmt *S, CheckerContext &C) {
85    ((const CHECKER *)checker)->checkPreStmt(cast<STMT>(S), C);
86  }
87
88  static bool _handlesStmt(const Stmt *S) {
89    return isa<STMT>(S);
90  }
91public:
92  template <typename CHECKER>
93  static void _register(CHECKER *checker, CheckerManager &mgr) {
94    mgr._registerForPreStmt(CheckerManager::CheckStmtFunc(checker,
95                                                          _checkStmt<CHECKER>),
96                            _handlesStmt);
97  }
98};
99
100template <typename STMT>
101class PostStmt {
102  template <typename CHECKER>
103  static void _checkStmt(void *checker, const Stmt *S, CheckerContext &C) {
104    ((const CHECKER *)checker)->checkPostStmt(cast<STMT>(S), C);
105  }
106
107  static bool _handlesStmt(const Stmt *S) {
108    return isa<STMT>(S);
109  }
110public:
111  template <typename CHECKER>
112  static void _register(CHECKER *checker, CheckerManager &mgr) {
113    mgr._registerForPostStmt(CheckerManager::CheckStmtFunc(checker,
114                                                           _checkStmt<CHECKER>),
115                             _handlesStmt);
116  }
117};
118
119class PreObjCMessage {
120  template <typename CHECKER>
121  static void _checkObjCMessage(void *checker, const ObjCMethodCall &msg,
122                                CheckerContext &C) {
123    ((const CHECKER *)checker)->checkPreObjCMessage(msg, C);
124  }
125
126public:
127  template <typename CHECKER>
128  static void _register(CHECKER *checker, CheckerManager &mgr) {
129    mgr._registerForPreObjCMessage(
130     CheckerManager::CheckObjCMessageFunc(checker, _checkObjCMessage<CHECKER>));
131  }
132};
133
134class ObjCMessageNil {
135  template <typename CHECKER>
136  static void _checkObjCMessage(void *checker, const ObjCMethodCall &msg,
137                                CheckerContext &C) {
138    ((const CHECKER *)checker)->checkObjCMessageNil(msg, C);
139  }
140
141public:
142  template <typename CHECKER>
143  static void _register(CHECKER *checker, CheckerManager &mgr) {
144    mgr._registerForObjCMessageNil(
145     CheckerManager::CheckObjCMessageFunc(checker, _checkObjCMessage<CHECKER>));
146  }
147};
148
149class PostObjCMessage {
150  template <typename CHECKER>
151  static void _checkObjCMessage(void *checker, const ObjCMethodCall &msg,
152                                CheckerContext &C) {
153    ((const CHECKER *)checker)->checkPostObjCMessage(msg, C);
154  }
155
156public:
157  template <typename CHECKER>
158  static void _register(CHECKER *checker, CheckerManager &mgr) {
159    mgr._registerForPostObjCMessage(
160     CheckerManager::CheckObjCMessageFunc(checker, _checkObjCMessage<CHECKER>));
161  }
162};
163
164class PreCall {
165  template <typename CHECKER>
166  static void _checkCall(void *checker, const CallEvent &msg,
167                         CheckerContext &C) {
168    ((const CHECKER *)checker)->checkPreCall(msg, C);
169  }
170
171public:
172  template <typename CHECKER>
173  static void _register(CHECKER *checker, CheckerManager &mgr) {
174    mgr._registerForPreCall(
175     CheckerManager::CheckCallFunc(checker, _checkCall<CHECKER>));
176  }
177};
178
179class PostCall {
180  template <typename CHECKER>
181  static void _checkCall(void *checker, const CallEvent &msg,
182                         CheckerContext &C) {
183    ((const CHECKER *)checker)->checkPostCall(msg, C);
184  }
185
186public:
187  template <typename CHECKER>
188  static void _register(CHECKER *checker, CheckerManager &mgr) {
189    mgr._registerForPostCall(
190     CheckerManager::CheckCallFunc(checker, _checkCall<CHECKER>));
191  }
192};
193
194class Location {
195  template <typename CHECKER>
196  static void _checkLocation(void *checker,
197                             const SVal &location, bool isLoad, const Stmt *S,
198                             CheckerContext &C) {
199    ((const CHECKER *)checker)->checkLocation(location, isLoad, S, C);
200  }
201
202public:
203  template <typename CHECKER>
204  static void _register(CHECKER *checker, CheckerManager &mgr) {
205    mgr._registerForLocation(
206           CheckerManager::CheckLocationFunc(checker, _checkLocation<CHECKER>));
207  }
208};
209
210class Bind {
211  template <typename CHECKER>
212  static void _checkBind(void *checker,
213                         const SVal &location, const SVal &val, const Stmt *S,
214                         CheckerContext &C) {
215    ((const CHECKER *)checker)->checkBind(location, val, S, C);
216  }
217
218public:
219  template <typename CHECKER>
220  static void _register(CHECKER *checker, CheckerManager &mgr) {
221    mgr._registerForBind(
222           CheckerManager::CheckBindFunc(checker, _checkBind<CHECKER>));
223  }
224};
225
226class EndAnalysis {
227  template <typename CHECKER>
228  static void _checkEndAnalysis(void *checker, ExplodedGraph &G,
229                                BugReporter &BR, ExprEngine &Eng) {
230    ((const CHECKER *)checker)->checkEndAnalysis(G, BR, Eng);
231  }
232
233public:
234  template <typename CHECKER>
235  static void _register(CHECKER *checker, CheckerManager &mgr) {
236    mgr._registerForEndAnalysis(
237     CheckerManager::CheckEndAnalysisFunc(checker, _checkEndAnalysis<CHECKER>));
238  }
239};
240
241class BeginFunction {
242  template <typename CHECKER>
243  static void _checkBeginFunction(void *checker, CheckerContext &C) {
244    ((const CHECKER *)checker)->checkBeginFunction(C);
245  }
246
247public:
248  template <typename CHECKER>
249  static void _register(CHECKER *checker, CheckerManager &mgr) {
250    mgr._registerForBeginFunction(CheckerManager::CheckBeginFunctionFunc(
251        checker, _checkBeginFunction<CHECKER>));
252  }
253};
254
255class EndFunction {
256  template <typename CHECKER>
257  static void _checkEndFunction(void *checker, const ReturnStmt *RS,
258                                CheckerContext &C) {
259    ((const CHECKER *)checker)->checkEndFunction(RS, C);
260  }
261
262public:
263  template <typename CHECKER>
264  static void _register(CHECKER *checker, CheckerManager &mgr) {
265    mgr._registerForEndFunction(
266     CheckerManager::CheckEndFunctionFunc(checker, _checkEndFunction<CHECKER>));
267  }
268};
269
270class BranchCondition {
271  template <typename CHECKER>
272  static void _checkBranchCondition(void *checker, const Stmt *Condition,
273                                    CheckerContext & C) {
274    ((const CHECKER *)checker)->checkBranchCondition(Condition, C);
275  }
276
277public:
278  template <typename CHECKER>
279  static void _register(CHECKER *checker, CheckerManager &mgr) {
280    mgr._registerForBranchCondition(
281      CheckerManager::CheckBranchConditionFunc(checker,
282                                               _checkBranchCondition<CHECKER>));
283  }
284};
285
286class NewAllocator {
287  template <typename CHECKER>
288  static void _checkNewAllocator(void *checker, const CXXNewExpr *NE,
289                                 SVal Target, CheckerContext &C) {
290    ((const CHECKER *)checker)->checkNewAllocator(NE, Target, C);
291  }
292
293public:
294  template <typename CHECKER>
295  static void _register(CHECKER *checker, CheckerManager &mgr) {
296    mgr._registerForNewAllocator(
297        CheckerManager::CheckNewAllocatorFunc(checker,
298                                              _checkNewAllocator<CHECKER>));
299  }
300};
301
302class LiveSymbols {
303  template <typename CHECKER>
304  static void _checkLiveSymbols(void *checker, ProgramStateRef state,
305                                SymbolReaper &SR) {
306    ((const CHECKER *)checker)->checkLiveSymbols(state, SR);
307  }
308
309public:
310  template <typename CHECKER>
311  static void _register(CHECKER *checker, CheckerManager &mgr) {
312    mgr._registerForLiveSymbols(
313     CheckerManager::CheckLiveSymbolsFunc(checker, _checkLiveSymbols<CHECKER>));
314  }
315};
316
317class DeadSymbols {
318  template <typename CHECKER>
319  static void _checkDeadSymbols(void *checker,
320                                SymbolReaper &SR, CheckerContext &C) {
321    ((const CHECKER *)checker)->checkDeadSymbols(SR, C);
322  }
323
324public:
325  template <typename CHECKER>
326  static void _register(CHECKER *checker, CheckerManager &mgr) {
327    mgr._registerForDeadSymbols(
328     CheckerManager::CheckDeadSymbolsFunc(checker, _checkDeadSymbols<CHECKER>));
329  }
330};
331
332class RegionChanges {
333  template <typename CHECKER>
334  static ProgramStateRef
335  _checkRegionChanges(void *checker,
336                      ProgramStateRef state,
337                      const InvalidatedSymbols *invalidated,
338                      ArrayRef<const MemRegion *> Explicits,
339                      ArrayRef<const MemRegion *> Regions,
340                      const LocationContext *LCtx,
341                      const CallEvent *Call) {
342    return ((const CHECKER *) checker)->checkRegionChanges(state, invalidated,
343                                                           Explicits, Regions,
344                                                           LCtx, Call);
345  }
346
347public:
348  template <typename CHECKER>
349  static void _register(CHECKER *checker, CheckerManager &mgr) {
350    mgr._registerForRegionChanges(
351          CheckerManager::CheckRegionChangesFunc(checker,
352                                                 _checkRegionChanges<CHECKER>));
353  }
354};
355
356class PointerEscape {
357  template <typename CHECKER>
358  static ProgramStateRef
359  _checkPointerEscape(void *Checker,
360                     ProgramStateRef State,
361                     const InvalidatedSymbols &Escaped,
362                     const CallEvent *Call,
363                     PointerEscapeKind Kind,
364                     RegionAndSymbolInvalidationTraits *ETraits) {
365
366    if (!ETraits)
367      return ((const CHECKER *)Checker)->checkPointerEscape(State,
368                                                            Escaped,
369                                                            Call,
370                                                            Kind);
371
372    InvalidatedSymbols RegularEscape;
373    for (InvalidatedSymbols::const_iterator I = Escaped.begin(),
374                                            E = Escaped.end(); I != E; ++I)
375      if (!ETraits->hasTrait(*I,
376              RegionAndSymbolInvalidationTraits::TK_PreserveContents) &&
377          !ETraits->hasTrait(*I,
378              RegionAndSymbolInvalidationTraits::TK_SuppressEscape))
379        RegularEscape.insert(*I);
380
381    if (RegularEscape.empty())
382      return State;
383
384    return ((const CHECKER *)Checker)->checkPointerEscape(State,
385                                                          RegularEscape,
386                                                          Call,
387                                                          Kind);
388  }
389
390public:
391  template <typename CHECKER>
392  static void _register(CHECKER *checker, CheckerManager &mgr) {
393    mgr._registerForPointerEscape(
394          CheckerManager::CheckPointerEscapeFunc(checker,
395                                                _checkPointerEscape<CHECKER>));
396  }
397};
398
399class ConstPointerEscape {
400  template <typename CHECKER>
401  static ProgramStateRef
402  _checkConstPointerEscape(void *Checker,
403                      ProgramStateRef State,
404                      const InvalidatedSymbols &Escaped,
405                      const CallEvent *Call,
406                      PointerEscapeKind Kind,
407                      RegionAndSymbolInvalidationTraits *ETraits) {
408
409    if (!ETraits)
410      return State;
411
412    InvalidatedSymbols ConstEscape;
413    for (InvalidatedSymbols::const_iterator I = Escaped.begin(),
414                                            E = Escaped.end(); I != E; ++I)
415      if (ETraits->hasTrait(*I,
416              RegionAndSymbolInvalidationTraits::TK_PreserveContents) &&
417          !ETraits->hasTrait(*I,
418              RegionAndSymbolInvalidationTraits::TK_SuppressEscape))
419        ConstEscape.insert(*I);
420
421    if (ConstEscape.empty())
422      return State;
423
424    return ((const CHECKER *)Checker)->checkConstPointerEscape(State,
425                                                               ConstEscape,
426                                                               Call,
427                                                               Kind);
428  }
429
430public:
431  template <typename CHECKER>
432  static void _register(CHECKER *checker, CheckerManager &mgr) {
433    mgr._registerForPointerEscape(
434      CheckerManager::CheckPointerEscapeFunc(checker,
435                                            _checkConstPointerEscape<CHECKER>));
436  }
437};
438
439
440template <typename EVENT>
441class Event {
442  template <typename CHECKER>
443  static void _checkEvent(void *checker, const void *event) {
444    ((const CHECKER *)checker)->checkEvent(*(const EVENT *)event);
445  }
446public:
447  template <typename CHECKER>
448  static void _register(CHECKER *checker, CheckerManager &mgr) {
449    mgr._registerListenerForEvent<EVENT>(
450                 CheckerManager::CheckEventFunc(checker, _checkEvent<CHECKER>));
451  }
452};
453
454} // end check namespace
455
456namespace eval {
457
458class Assume {
459  template <typename CHECKER>
460  static ProgramStateRef _evalAssume(void *checker,
461                                         ProgramStateRef state,
462                                         const SVal &cond,
463                                         bool assumption) {
464    return ((const CHECKER *)checker)->evalAssume(state, cond, assumption);
465  }
466
467public:
468  template <typename CHECKER>
469  static void _register(CHECKER *checker, CheckerManager &mgr) {
470    mgr._registerForEvalAssume(
471                 CheckerManager::EvalAssumeFunc(checker, _evalAssume<CHECKER>));
472  }
473};
474
475class Call {
476  template <typename CHECKER>
477  static bool _evalCall(void *checker, const CallEvent &Call,
478                        CheckerContext &C) {
479    return ((const CHECKER *)checker)->evalCall(Call, C);
480  }
481
482public:
483  template <typename CHECKER>
484  static void _register(CHECKER *checker, CheckerManager &mgr) {
485    mgr._registerForEvalCall(
486                     CheckerManager::EvalCallFunc(checker, _evalCall<CHECKER>));
487  }
488};
489
490} // end eval namespace
491
492class CheckerBase : public ProgramPointTag {
493  CheckerNameRef Name;
494  friend class ::clang::ento::CheckerManager;
495
496public:
497  StringRef getTagDescription() const override;
498  CheckerNameRef getCheckerName() const;
499
500  /// See CheckerManager::runCheckersForPrintState.
501  virtual void printState(raw_ostream &Out, ProgramStateRef State,
502                          const char *NL, const char *Sep) const { }
503};
504
505/// Dump checker name to stream.
506raw_ostream& operator<<(raw_ostream &Out, const CheckerBase &Checker);
507
508/// Tag that can use a checker name as a message provider
509/// (see SimpleProgramPointTag).
510class CheckerProgramPointTag : public SimpleProgramPointTag {
511public:
512  CheckerProgramPointTag(StringRef CheckerName, StringRef Msg);
513  CheckerProgramPointTag(const CheckerBase *Checker, StringRef Msg);
514};
515
516template <typename CHECK1, typename... CHECKs>
517class Checker : public CHECK1, public CHECKs..., public CheckerBase {
518public:
519  template <typename CHECKER>
520  static void _register(CHECKER *checker, CheckerManager &mgr) {
521    CHECK1::_register(checker, mgr);
522    Checker<CHECKs...>::_register(checker, mgr);
523  }
524};
525
526template <typename CHECK1>
527class Checker<CHECK1> : public CHECK1, public CheckerBase {
528public:
529  template <typename CHECKER>
530  static void _register(CHECKER *checker, CheckerManager &mgr) {
531    CHECK1::_register(checker, mgr);
532  }
533};
534
535template <typename EVENT>
536class EventDispatcher {
537  CheckerManager *Mgr;
538public:
539  EventDispatcher() : Mgr(nullptr) { }
540
541  template <typename CHECKER>
542  static void _register(CHECKER *checker, CheckerManager &mgr) {
543    mgr._registerDispatcherForEvent<EVENT>();
544    static_cast<EventDispatcher<EVENT> *>(checker)->Mgr = &mgr;
545  }
546
547  void dispatchEvent(const EVENT &event) const {
548    Mgr->_dispatchEvent(event);
549  }
550};
551
552/// We dereferenced a location that may be null.
553struct ImplicitNullDerefEvent {
554  SVal Location;
555  bool IsLoad;
556  ExplodedNode *SinkNode;
557  BugReporter *BR;
558  // When true, the dereference is in the source code directly. When false, the
559  // dereference might happen later (for example pointer passed to a parameter
560  // that is marked with nonnull attribute.)
561  bool IsDirectDereference;
562
563  static int Tag;
564};
565
566/// A helper class which wraps a boolean value set to false by default.
567///
568/// This class should behave exactly like 'bool' except that it doesn't need to
569/// be explicitly initialized.
570struct DefaultBool {
571  bool val;
572  DefaultBool() : val(false) {}
573  /*implicit*/ operator bool&() { return val; }
574  /*implicit*/ operator const bool&() const { return val; }
575  DefaultBool &operator=(bool b) { val = b; return *this; }
576};
577
578} // end ento namespace
579
580} // end clang namespace
581
582#endif
583