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_SA_CORE_CHECKER
15#define LLVM_CLANG_SA_CORE_CHECKER
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
28struct _VoidCheck {
29  static void _register(void *checker, CheckerManager &mgr) { }
30};
31
32template <typename DECL>
33class ASTDecl {
34  template <typename CHECKER>
35  static void _checkDecl(void *checker, const Decl *D, AnalysisManager& mgr,
36                         BugReporter &BR) {
37    ((const CHECKER *)checker)->checkASTDecl(cast<DECL>(D), mgr, BR);
38  }
39
40  static bool _handlesDecl(const Decl *D) {
41    return isa<DECL>(D);
42  }
43public:
44  template <typename CHECKER>
45  static void _register(CHECKER *checker, CheckerManager &mgr) {
46    mgr._registerForDecl(CheckerManager::CheckDeclFunc(checker,
47                                                       _checkDecl<CHECKER>),
48                         _handlesDecl);
49  }
50};
51
52class ASTCodeBody {
53  template <typename CHECKER>
54  static void _checkBody(void *checker, const Decl *D, AnalysisManager& mgr,
55                         BugReporter &BR) {
56    ((const CHECKER *)checker)->checkASTCodeBody(D, mgr, BR);
57  }
58
59public:
60  template <typename CHECKER>
61  static void _register(CHECKER *checker, CheckerManager &mgr) {
62    mgr._registerForBody(CheckerManager::CheckDeclFunc(checker,
63                                                       _checkBody<CHECKER>));
64  }
65};
66
67class EndOfTranslationUnit {
68  template <typename CHECKER>
69  static void _checkEndOfTranslationUnit(void *checker,
70                                         const TranslationUnitDecl *TU,
71                                         AnalysisManager& mgr,
72                                         BugReporter &BR) {
73    ((const CHECKER *)checker)->checkEndOfTranslationUnit(TU, mgr, BR);
74  }
75
76public:
77  template <typename CHECKER>
78  static void _register(CHECKER *checker, CheckerManager &mgr){
79    mgr._registerForEndOfTranslationUnit(
80                              CheckerManager::CheckEndOfTranslationUnit(checker,
81                                          _checkEndOfTranslationUnit<CHECKER>));
82  }
83};
84
85template <typename STMT>
86class PreStmt {
87  template <typename CHECKER>
88  static void _checkStmt(void *checker, const Stmt *S, CheckerContext &C) {
89    ((const CHECKER *)checker)->checkPreStmt(cast<STMT>(S), C);
90  }
91
92  static bool _handlesStmt(const Stmt *S) {
93    return isa<STMT>(S);
94  }
95public:
96  template <typename CHECKER>
97  static void _register(CHECKER *checker, CheckerManager &mgr) {
98    mgr._registerForPreStmt(CheckerManager::CheckStmtFunc(checker,
99                                                          _checkStmt<CHECKER>),
100                            _handlesStmt);
101  }
102};
103
104template <typename STMT>
105class PostStmt {
106  template <typename CHECKER>
107  static void _checkStmt(void *checker, const Stmt *S, CheckerContext &C) {
108    ((const CHECKER *)checker)->checkPostStmt(cast<STMT>(S), C);
109  }
110
111  static bool _handlesStmt(const Stmt *S) {
112    return isa<STMT>(S);
113  }
114public:
115  template <typename CHECKER>
116  static void _register(CHECKER *checker, CheckerManager &mgr) {
117    mgr._registerForPostStmt(CheckerManager::CheckStmtFunc(checker,
118                                                           _checkStmt<CHECKER>),
119                             _handlesStmt);
120  }
121};
122
123class PreObjCMessage {
124  template <typename CHECKER>
125  static void _checkObjCMessage(void *checker, const ObjCMethodCall &msg,
126                                CheckerContext &C) {
127    ((const CHECKER *)checker)->checkPreObjCMessage(msg, C);
128  }
129
130public:
131  template <typename CHECKER>
132  static void _register(CHECKER *checker, CheckerManager &mgr) {
133    mgr._registerForPreObjCMessage(
134     CheckerManager::CheckObjCMessageFunc(checker, _checkObjCMessage<CHECKER>));
135  }
136};
137
138class PostObjCMessage {
139  template <typename CHECKER>
140  static void _checkObjCMessage(void *checker, const ObjCMethodCall &msg,
141                                CheckerContext &C) {
142    ((const CHECKER *)checker)->checkPostObjCMessage(msg, C);
143  }
144
145public:
146  template <typename CHECKER>
147  static void _register(CHECKER *checker, CheckerManager &mgr) {
148    mgr._registerForPostObjCMessage(
149     CheckerManager::CheckObjCMessageFunc(checker, _checkObjCMessage<CHECKER>));
150  }
151};
152
153class PreCall {
154  template <typename CHECKER>
155  static void _checkCall(void *checker, const CallEvent &msg,
156                         CheckerContext &C) {
157    ((const CHECKER *)checker)->checkPreCall(msg, C);
158  }
159
160public:
161  template <typename CHECKER>
162  static void _register(CHECKER *checker, CheckerManager &mgr) {
163    mgr._registerForPreCall(
164     CheckerManager::CheckCallFunc(checker, _checkCall<CHECKER>));
165  }
166};
167
168class PostCall {
169  template <typename CHECKER>
170  static void _checkCall(void *checker, const CallEvent &msg,
171                         CheckerContext &C) {
172    ((const CHECKER *)checker)->checkPostCall(msg, C);
173  }
174
175public:
176  template <typename CHECKER>
177  static void _register(CHECKER *checker, CheckerManager &mgr) {
178    mgr._registerForPostCall(
179     CheckerManager::CheckCallFunc(checker, _checkCall<CHECKER>));
180  }
181};
182
183class Location {
184  template <typename CHECKER>
185  static void _checkLocation(void *checker,
186                             const SVal &location, bool isLoad, const Stmt *S,
187                             CheckerContext &C) {
188    ((const CHECKER *)checker)->checkLocation(location, isLoad, S, C);
189  }
190
191public:
192  template <typename CHECKER>
193  static void _register(CHECKER *checker, CheckerManager &mgr) {
194    mgr._registerForLocation(
195           CheckerManager::CheckLocationFunc(checker, _checkLocation<CHECKER>));
196  }
197};
198
199class Bind {
200  template <typename CHECKER>
201  static void _checkBind(void *checker,
202                         const SVal &location, const SVal &val, const Stmt *S,
203                         CheckerContext &C) {
204    ((const CHECKER *)checker)->checkBind(location, val, S, C);
205  }
206
207public:
208  template <typename CHECKER>
209  static void _register(CHECKER *checker, CheckerManager &mgr) {
210    mgr._registerForBind(
211           CheckerManager::CheckBindFunc(checker, _checkBind<CHECKER>));
212  }
213};
214
215class EndAnalysis {
216  template <typename CHECKER>
217  static void _checkEndAnalysis(void *checker, ExplodedGraph &G,
218                                BugReporter &BR, ExprEngine &Eng) {
219    ((const CHECKER *)checker)->checkEndAnalysis(G, BR, Eng);
220  }
221
222public:
223  template <typename CHECKER>
224  static void _register(CHECKER *checker, CheckerManager &mgr) {
225    mgr._registerForEndAnalysis(
226     CheckerManager::CheckEndAnalysisFunc(checker, _checkEndAnalysis<CHECKER>));
227  }
228};
229
230class EndFunction {
231  template <typename CHECKER>
232  static void _checkEndFunction(void *checker,
233                                CheckerContext &C) {
234    ((const CHECKER *)checker)->checkEndFunction(C);
235  }
236
237public:
238  template <typename CHECKER>
239  static void _register(CHECKER *checker, CheckerManager &mgr) {
240    mgr._registerForEndFunction(
241     CheckerManager::CheckEndFunctionFunc(checker, _checkEndFunction<CHECKER>));
242  }
243};
244
245class BranchCondition {
246  template <typename CHECKER>
247  static void _checkBranchCondition(void *checker, const Stmt *Condition,
248                                    CheckerContext & C) {
249    ((const CHECKER *)checker)->checkBranchCondition(Condition, C);
250  }
251
252public:
253  template <typename CHECKER>
254  static void _register(CHECKER *checker, CheckerManager &mgr) {
255    mgr._registerForBranchCondition(
256      CheckerManager::CheckBranchConditionFunc(checker,
257                                               _checkBranchCondition<CHECKER>));
258  }
259};
260
261class LiveSymbols {
262  template <typename CHECKER>
263  static void _checkLiveSymbols(void *checker, ProgramStateRef state,
264                                SymbolReaper &SR) {
265    ((const CHECKER *)checker)->checkLiveSymbols(state, SR);
266  }
267
268public:
269  template <typename CHECKER>
270  static void _register(CHECKER *checker, CheckerManager &mgr) {
271    mgr._registerForLiveSymbols(
272     CheckerManager::CheckLiveSymbolsFunc(checker, _checkLiveSymbols<CHECKER>));
273  }
274};
275
276class DeadSymbols {
277  template <typename CHECKER>
278  static void _checkDeadSymbols(void *checker,
279                                SymbolReaper &SR, CheckerContext &C) {
280    ((const CHECKER *)checker)->checkDeadSymbols(SR, C);
281  }
282
283public:
284  template <typename CHECKER>
285  static void _register(CHECKER *checker, CheckerManager &mgr) {
286    mgr._registerForDeadSymbols(
287     CheckerManager::CheckDeadSymbolsFunc(checker, _checkDeadSymbols<CHECKER>));
288  }
289};
290
291class RegionChanges {
292  template <typename CHECKER>
293  static ProgramStateRef
294  _checkRegionChanges(void *checker,
295                      ProgramStateRef state,
296                      const InvalidatedSymbols *invalidated,
297                      ArrayRef<const MemRegion *> Explicits,
298                      ArrayRef<const MemRegion *> Regions,
299                      const CallEvent *Call) {
300    return ((const CHECKER *)checker)->checkRegionChanges(state, invalidated,
301                                                      Explicits, Regions, Call);
302  }
303  template <typename CHECKER>
304  static bool _wantsRegionChangeUpdate(void *checker,
305                                       ProgramStateRef state) {
306    return ((const CHECKER *)checker)->wantsRegionChangeUpdate(state);
307  }
308
309public:
310  template <typename CHECKER>
311  static void _register(CHECKER *checker, CheckerManager &mgr) {
312    mgr._registerForRegionChanges(
313          CheckerManager::CheckRegionChangesFunc(checker,
314                                                 _checkRegionChanges<CHECKER>),
315          CheckerManager::WantsRegionChangeUpdateFunc(checker,
316                                            _wantsRegionChangeUpdate<CHECKER>));
317  }
318};
319
320class PointerEscape {
321  template <typename CHECKER>
322  static ProgramStateRef
323  _checkPointerEscape(void *checker,
324                     ProgramStateRef State,
325                     const InvalidatedSymbols &Escaped,
326                     const CallEvent *Call,
327                     PointerEscapeKind Kind) {
328    return ((const CHECKER *)checker)->checkPointerEscape(State,
329                                                          Escaped,
330                                                          Call,
331                                                          Kind);
332  }
333
334public:
335  template <typename CHECKER>
336  static void _register(CHECKER *checker, CheckerManager &mgr) {
337    mgr._registerForPointerEscape(
338          CheckerManager::CheckPointerEscapeFunc(checker,
339                                                _checkPointerEscape<CHECKER>));
340  }
341};
342
343template <typename EVENT>
344class Event {
345  template <typename CHECKER>
346  static void _checkEvent(void *checker, const void *event) {
347    ((const CHECKER *)checker)->checkEvent(*(const EVENT *)event);
348  }
349public:
350  template <typename CHECKER>
351  static void _register(CHECKER *checker, CheckerManager &mgr) {
352    mgr._registerListenerForEvent<EVENT>(
353                 CheckerManager::CheckEventFunc(checker, _checkEvent<CHECKER>));
354  }
355};
356
357} // end check namespace
358
359namespace eval {
360
361class Assume {
362  template <typename CHECKER>
363  static ProgramStateRef _evalAssume(void *checker,
364                                         ProgramStateRef state,
365                                         const SVal &cond,
366                                         bool assumption) {
367    return ((const CHECKER *)checker)->evalAssume(state, cond, assumption);
368  }
369
370public:
371  template <typename CHECKER>
372  static void _register(CHECKER *checker, CheckerManager &mgr) {
373    mgr._registerForEvalAssume(
374                 CheckerManager::EvalAssumeFunc(checker, _evalAssume<CHECKER>));
375  }
376};
377
378class Call {
379  template <typename CHECKER>
380  static bool _evalCall(void *checker, const CallExpr *CE, CheckerContext &C) {
381    return ((const CHECKER *)checker)->evalCall(CE, C);
382  }
383
384public:
385  template <typename CHECKER>
386  static void _register(CHECKER *checker, CheckerManager &mgr) {
387    mgr._registerForEvalCall(
388                     CheckerManager::EvalCallFunc(checker, _evalCall<CHECKER>));
389  }
390};
391
392} // end eval namespace
393
394class CheckerBase : public ProgramPointTag {
395public:
396  StringRef getTagDescription() const;
397
398  /// See CheckerManager::runCheckersForPrintState.
399  virtual void printState(raw_ostream &Out, ProgramStateRef State,
400                          const char *NL, const char *Sep) const { }
401};
402
403template <typename CHECK1, typename CHECK2=check::_VoidCheck,
404          typename CHECK3=check::_VoidCheck, typename CHECK4=check::_VoidCheck,
405          typename CHECK5=check::_VoidCheck, typename CHECK6=check::_VoidCheck,
406          typename CHECK7=check::_VoidCheck, typename CHECK8=check::_VoidCheck,
407          typename CHECK9=check::_VoidCheck, typename CHECK10=check::_VoidCheck,
408          typename CHECK11=check::_VoidCheck,typename CHECK12=check::_VoidCheck,
409          typename CHECK13=check::_VoidCheck,typename CHECK14=check::_VoidCheck,
410          typename CHECK15=check::_VoidCheck,typename CHECK16=check::_VoidCheck,
411          typename CHECK17=check::_VoidCheck,typename CHECK18=check::_VoidCheck,
412          typename CHECK19=check::_VoidCheck,typename CHECK20=check::_VoidCheck,
413          typename CHECK21=check::_VoidCheck,typename CHECK22=check::_VoidCheck,
414          typename CHECK23=check::_VoidCheck,typename CHECK24=check::_VoidCheck>
415class Checker;
416
417template <>
418class Checker<check::_VoidCheck>
419  : public CheckerBase
420{
421  virtual void anchor();
422public:
423  static void _register(void *checker, CheckerManager &mgr) { }
424};
425
426template <typename CHECK1, typename CHECK2, typename CHECK3, typename CHECK4,
427          typename CHECK5, typename CHECK6, typename CHECK7, typename CHECK8,
428          typename CHECK9, typename CHECK10,typename CHECK11,typename CHECK12,
429          typename CHECK13,typename CHECK14,typename CHECK15,typename CHECK16,
430          typename CHECK17,typename CHECK18,typename CHECK19,typename CHECK20,
431          typename CHECK21,typename CHECK22,typename CHECK23,typename CHECK24>
432class Checker
433    : public CHECK1,
434      public Checker<CHECK2, CHECK3, CHECK4, CHECK5, CHECK6, CHECK7,
435                     CHECK8, CHECK9, CHECK10,CHECK11,CHECK12,CHECK13,
436                     CHECK14,CHECK15,CHECK16,CHECK17,CHECK18,CHECK19,
437                     CHECK20,CHECK21,CHECK22,CHECK23,CHECK24> {
438public:
439  template <typename CHECKER>
440  static void _register(CHECKER *checker, CheckerManager &mgr) {
441    CHECK1::_register(checker, mgr);
442    Checker<CHECK2, CHECK3, CHECK4, CHECK5, CHECK6, CHECK7,
443            CHECK8, CHECK9, CHECK10,CHECK11,CHECK12,CHECK13,
444            CHECK14,CHECK15,CHECK16,CHECK17,CHECK18,CHECK19,
445            CHECK20,CHECK21,CHECK22,CHECK23,CHECK24>::_register(checker, mgr);
446  }
447};
448
449template <typename EVENT>
450class EventDispatcher {
451  CheckerManager *Mgr;
452public:
453  EventDispatcher() : Mgr(0) { }
454
455  template <typename CHECKER>
456  static void _register(CHECKER *checker, CheckerManager &mgr) {
457    mgr._registerDispatcherForEvent<EVENT>();
458    static_cast<EventDispatcher<EVENT> *>(checker)->Mgr = &mgr;
459  }
460
461  void dispatchEvent(const EVENT &event) const {
462    Mgr->_dispatchEvent(event);
463  }
464};
465
466/// \brief We dereferenced a location that may be null.
467struct ImplicitNullDerefEvent {
468  SVal Location;
469  bool IsLoad;
470  ExplodedNode *SinkNode;
471  BugReporter *BR;
472};
473
474/// \brief A helper class which wraps a boolean value set to false by default.
475struct DefaultBool {
476  bool val;
477  DefaultBool() : val(false) {}
478  operator bool() const { return val; }
479  DefaultBool &operator=(bool b) { val = b; return *this; }
480};
481
482} // end ento namespace
483
484} // end clang namespace
485
486#endif
487