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