1//== Checker.h - Registration mechanism for checkers -------------*- C++ -*--=//
2//
3//                     The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10//  This file defines Checker, used to create and register checkers.
11//
12//===----------------------------------------------------------------------===//
13
14#ifndef LLVM_CLANG_STATICANALYZER_CORE_CHECKER_H
15#define LLVM_CLANG_STATICANALYZER_CORE_CHECKER_H
16
17#include "clang/Analysis/ProgramPoint.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,
258                                CheckerContext &C) {
259    ((const CHECKER *)checker)->checkEndFunction(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 LiveSymbols {
287  template <typename CHECKER>
288  static void _checkLiveSymbols(void *checker, ProgramStateRef state,
289                                SymbolReaper &SR) {
290    ((const CHECKER *)checker)->checkLiveSymbols(state, SR);
291  }
292
293public:
294  template <typename CHECKER>
295  static void _register(CHECKER *checker, CheckerManager &mgr) {
296    mgr._registerForLiveSymbols(
297     CheckerManager::CheckLiveSymbolsFunc(checker, _checkLiveSymbols<CHECKER>));
298  }
299};
300
301class DeadSymbols {
302  template <typename CHECKER>
303  static void _checkDeadSymbols(void *checker,
304                                SymbolReaper &SR, CheckerContext &C) {
305    ((const CHECKER *)checker)->checkDeadSymbols(SR, C);
306  }
307
308public:
309  template <typename CHECKER>
310  static void _register(CHECKER *checker, CheckerManager &mgr) {
311    mgr._registerForDeadSymbols(
312     CheckerManager::CheckDeadSymbolsFunc(checker, _checkDeadSymbols<CHECKER>));
313  }
314};
315
316class RegionChanges {
317  template <typename CHECKER>
318  static ProgramStateRef
319  _checkRegionChanges(void *checker,
320                      ProgramStateRef state,
321                      const InvalidatedSymbols *invalidated,
322                      ArrayRef<const MemRegion *> Explicits,
323                      ArrayRef<const MemRegion *> Regions,
324                      const CallEvent *Call) {
325    return ((const CHECKER *)checker)->checkRegionChanges(state, invalidated,
326                                                      Explicits, Regions, Call);
327  }
328  template <typename CHECKER>
329  static bool _wantsRegionChangeUpdate(void *checker,
330                                       ProgramStateRef state) {
331    return ((const CHECKER *)checker)->wantsRegionChangeUpdate(state);
332  }
333
334public:
335  template <typename CHECKER>
336  static void _register(CHECKER *checker, CheckerManager &mgr) {
337    mgr._registerForRegionChanges(
338          CheckerManager::CheckRegionChangesFunc(checker,
339                                                 _checkRegionChanges<CHECKER>),
340          CheckerManager::WantsRegionChangeUpdateFunc(checker,
341                                            _wantsRegionChangeUpdate<CHECKER>));
342  }
343};
344
345class PointerEscape {
346  template <typename CHECKER>
347  static ProgramStateRef
348  _checkPointerEscape(void *Checker,
349                     ProgramStateRef State,
350                     const InvalidatedSymbols &Escaped,
351                     const CallEvent *Call,
352                     PointerEscapeKind Kind,
353                     RegionAndSymbolInvalidationTraits *ETraits) {
354
355    if (!ETraits)
356      return ((const CHECKER *)Checker)->checkPointerEscape(State,
357                                                            Escaped,
358                                                            Call,
359                                                            Kind);
360
361    InvalidatedSymbols RegularEscape;
362    for (InvalidatedSymbols::const_iterator I = Escaped.begin(),
363                                            E = Escaped.end(); I != E; ++I)
364      if (!ETraits->hasTrait(*I,
365              RegionAndSymbolInvalidationTraits::TK_PreserveContents) &&
366          !ETraits->hasTrait(*I,
367              RegionAndSymbolInvalidationTraits::TK_SuppressEscape))
368        RegularEscape.insert(*I);
369
370    if (RegularEscape.empty())
371      return State;
372
373    return ((const CHECKER *)Checker)->checkPointerEscape(State,
374                                                          RegularEscape,
375                                                          Call,
376                                                          Kind);
377  }
378
379public:
380  template <typename CHECKER>
381  static void _register(CHECKER *checker, CheckerManager &mgr) {
382    mgr._registerForPointerEscape(
383          CheckerManager::CheckPointerEscapeFunc(checker,
384                                                _checkPointerEscape<CHECKER>));
385  }
386};
387
388class ConstPointerEscape {
389  template <typename CHECKER>
390  static ProgramStateRef
391  _checkConstPointerEscape(void *Checker,
392                      ProgramStateRef State,
393                      const InvalidatedSymbols &Escaped,
394                      const CallEvent *Call,
395                      PointerEscapeKind Kind,
396                      RegionAndSymbolInvalidationTraits *ETraits) {
397
398    if (!ETraits)
399      return State;
400
401    InvalidatedSymbols ConstEscape;
402    for (InvalidatedSymbols::const_iterator I = Escaped.begin(),
403                                            E = Escaped.end(); I != E; ++I)
404      if (ETraits->hasTrait(*I,
405              RegionAndSymbolInvalidationTraits::TK_PreserveContents) &&
406          !ETraits->hasTrait(*I,
407              RegionAndSymbolInvalidationTraits::TK_SuppressEscape))
408        ConstEscape.insert(*I);
409
410    if (ConstEscape.empty())
411      return State;
412
413    return ((const CHECKER *)Checker)->checkConstPointerEscape(State,
414                                                               ConstEscape,
415                                                               Call,
416                                                               Kind);
417  }
418
419public:
420  template <typename CHECKER>
421  static void _register(CHECKER *checker, CheckerManager &mgr) {
422    mgr._registerForPointerEscape(
423      CheckerManager::CheckPointerEscapeFunc(checker,
424                                            _checkConstPointerEscape<CHECKER>));
425  }
426};
427
428
429template <typename EVENT>
430class Event {
431  template <typename CHECKER>
432  static void _checkEvent(void *checker, const void *event) {
433    ((const CHECKER *)checker)->checkEvent(*(const EVENT *)event);
434  }
435public:
436  template <typename CHECKER>
437  static void _register(CHECKER *checker, CheckerManager &mgr) {
438    mgr._registerListenerForEvent<EVENT>(
439                 CheckerManager::CheckEventFunc(checker, _checkEvent<CHECKER>));
440  }
441};
442
443} // end check namespace
444
445namespace eval {
446
447class Assume {
448  template <typename CHECKER>
449  static ProgramStateRef _evalAssume(void *checker,
450                                         ProgramStateRef state,
451                                         const SVal &cond,
452                                         bool assumption) {
453    return ((const CHECKER *)checker)->evalAssume(state, cond, assumption);
454  }
455
456public:
457  template <typename CHECKER>
458  static void _register(CHECKER *checker, CheckerManager &mgr) {
459    mgr._registerForEvalAssume(
460                 CheckerManager::EvalAssumeFunc(checker, _evalAssume<CHECKER>));
461  }
462};
463
464class Call {
465  template <typename CHECKER>
466  static bool _evalCall(void *checker, const CallExpr *CE, CheckerContext &C) {
467    return ((const CHECKER *)checker)->evalCall(CE, C);
468  }
469
470public:
471  template <typename CHECKER>
472  static void _register(CHECKER *checker, CheckerManager &mgr) {
473    mgr._registerForEvalCall(
474                     CheckerManager::EvalCallFunc(checker, _evalCall<CHECKER>));
475  }
476};
477
478} // end eval namespace
479
480class CheckerBase : public ProgramPointTag {
481  CheckName Name;
482  friend class ::clang::ento::CheckerManager;
483
484public:
485  StringRef getTagDescription() const override;
486  CheckName getCheckName() const;
487
488  /// See CheckerManager::runCheckersForPrintState.
489  virtual void printState(raw_ostream &Out, ProgramStateRef State,
490                          const char *NL, const char *Sep) const { }
491};
492
493/// Dump checker name to stream.
494raw_ostream& operator<<(raw_ostream &Out, const CheckerBase &Checker);
495
496/// Tag that can use a checker name as a message provider
497/// (see SimpleProgramPointTag).
498class CheckerProgramPointTag : public SimpleProgramPointTag {
499public:
500  CheckerProgramPointTag(StringRef CheckerName, StringRef Msg);
501  CheckerProgramPointTag(const CheckerBase *Checker, StringRef Msg);
502};
503
504template <typename CHECK1, typename... CHECKs>
505class Checker : public CHECK1, public CHECKs..., public CheckerBase {
506public:
507  template <typename CHECKER>
508  static void _register(CHECKER *checker, CheckerManager &mgr) {
509    CHECK1::_register(checker, mgr);
510    Checker<CHECKs...>::_register(checker, mgr);
511  }
512};
513
514template <typename CHECK1>
515class Checker<CHECK1> : public CHECK1, public CheckerBase {
516public:
517  template <typename CHECKER>
518  static void _register(CHECKER *checker, CheckerManager &mgr) {
519    CHECK1::_register(checker, mgr);
520  }
521};
522
523template <typename EVENT>
524class EventDispatcher {
525  CheckerManager *Mgr;
526public:
527  EventDispatcher() : Mgr(nullptr) { }
528
529  template <typename CHECKER>
530  static void _register(CHECKER *checker, CheckerManager &mgr) {
531    mgr._registerDispatcherForEvent<EVENT>();
532    static_cast<EventDispatcher<EVENT> *>(checker)->Mgr = &mgr;
533  }
534
535  void dispatchEvent(const EVENT &event) const {
536    Mgr->_dispatchEvent(event);
537  }
538};
539
540/// \brief We dereferenced a location that may be null.
541struct ImplicitNullDerefEvent {
542  SVal Location;
543  bool IsLoad;
544  ExplodedNode *SinkNode;
545  BugReporter *BR;
546  // When true, the dereference is in the source code directly. When false, the
547  // dereference might happen later (for example pointer passed to a parameter
548  // that is marked with nonnull attribute.)
549  bool IsDirectDereference;
550};
551
552/// \brief A helper class which wraps a boolean value set to false by default.
553///
554/// This class should behave exactly like 'bool' except that it doesn't need to
555/// be explicitly initialized.
556struct DefaultBool {
557  bool val;
558  DefaultBool() : val(false) {}
559  /*implicit*/ operator bool&() { return val; }
560  /*implicit*/ operator const bool&() const { return val; }
561  DefaultBool &operator=(bool b) { val = b; return *this; }
562};
563
564} // end ento namespace
565
566} // end clang namespace
567
568#endif
569