Checker.h revision f236b6503a4dbc44c1fccb8756bd57c9d0efdf05
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(llvm::cast<DECL>(D), mgr, BR);
38  }
39
40  static bool _handlesDecl(const Decl *D) {
41    return llvm::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(llvm::cast<STMT>(S), C);
90  }
91
92  static bool _handlesStmt(const Stmt *S) {
93    return llvm::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(llvm::cast<STMT>(S), C);
109  }
110
111  static bool _handlesStmt(const Stmt *S) {
112    return llvm::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 ObjCMessage &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 ObjCMessage &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 Location {
154  template <typename CHECKER>
155  static void _checkLocation(void *checker,
156                             const SVal &location, bool isLoad, const Stmt *S,
157                             CheckerContext &C) {
158    ((const CHECKER *)checker)->checkLocation(location, isLoad, S, C);
159  }
160
161public:
162  template <typename CHECKER>
163  static void _register(CHECKER *checker, CheckerManager &mgr) {
164    mgr._registerForLocation(
165           CheckerManager::CheckLocationFunc(checker, _checkLocation<CHECKER>));
166  }
167};
168
169class Bind {
170  template <typename CHECKER>
171  static void _checkBind(void *checker,
172                         const SVal &location, const SVal &val, const Stmt *S,
173                         CheckerContext &C) {
174    ((const CHECKER *)checker)->checkBind(location, val, S, C);
175  }
176
177public:
178  template <typename CHECKER>
179  static void _register(CHECKER *checker, CheckerManager &mgr) {
180    mgr._registerForBind(
181           CheckerManager::CheckBindFunc(checker, _checkBind<CHECKER>));
182  }
183};
184
185class EndAnalysis {
186  template <typename CHECKER>
187  static void _checkEndAnalysis(void *checker, ExplodedGraph &G,
188                                BugReporter &BR, ExprEngine &Eng) {
189    ((const CHECKER *)checker)->checkEndAnalysis(G, BR, Eng);
190  }
191
192public:
193  template <typename CHECKER>
194  static void _register(CHECKER *checker, CheckerManager &mgr) {
195    mgr._registerForEndAnalysis(
196     CheckerManager::CheckEndAnalysisFunc(checker, _checkEndAnalysis<CHECKER>));
197  }
198};
199
200class EndPath {
201  template <typename CHECKER>
202  static void _checkEndPath(void *checker,
203                            CheckerContext &C) {
204    ((const CHECKER *)checker)->checkEndPath(C);
205  }
206
207public:
208  template <typename CHECKER>
209  static void _register(CHECKER *checker, CheckerManager &mgr) {
210    mgr._registerForEndPath(
211     CheckerManager::CheckEndPathFunc(checker, _checkEndPath<CHECKER>));
212  }
213};
214
215class BranchCondition {
216  template <typename CHECKER>
217  static void _checkBranchCondition(void *checker, const Stmt *Condition,
218                                    CheckerContext & C) {
219    ((const CHECKER *)checker)->checkBranchCondition(Condition, C);
220  }
221
222public:
223  template <typename CHECKER>
224  static void _register(CHECKER *checker, CheckerManager &mgr) {
225    mgr._registerForBranchCondition(
226      CheckerManager::CheckBranchConditionFunc(checker,
227                                               _checkBranchCondition<CHECKER>));
228  }
229};
230
231class LiveSymbols {
232  template <typename CHECKER>
233  static void _checkLiveSymbols(void *checker, const ProgramState *state,
234                                SymbolReaper &SR) {
235    ((const CHECKER *)checker)->checkLiveSymbols(state, SR);
236  }
237
238public:
239  template <typename CHECKER>
240  static void _register(CHECKER *checker, CheckerManager &mgr) {
241    mgr._registerForLiveSymbols(
242     CheckerManager::CheckLiveSymbolsFunc(checker, _checkLiveSymbols<CHECKER>));
243  }
244};
245
246class DeadSymbols {
247  template <typename CHECKER>
248  static void _checkDeadSymbols(void *checker,
249                                SymbolReaper &SR, CheckerContext &C) {
250    ((const CHECKER *)checker)->checkDeadSymbols(SR, C);
251  }
252
253public:
254  template <typename CHECKER>
255  static void _register(CHECKER *checker, CheckerManager &mgr) {
256    mgr._registerForDeadSymbols(
257     CheckerManager::CheckDeadSymbolsFunc(checker, _checkDeadSymbols<CHECKER>));
258  }
259};
260
261class RegionChanges {
262  template <typename CHECKER>
263  static const ProgramState *
264  _checkRegionChanges(void *checker,
265                      const ProgramState *state,
266                      const StoreManager::InvalidatedSymbols *invalidated,
267                      ArrayRef<const MemRegion *> Explicits,
268                      ArrayRef<const MemRegion *> Regions) {
269    return ((const CHECKER *)checker)->checkRegionChanges(state, invalidated,
270                                                          Explicits, Regions);
271  }
272  template <typename CHECKER>
273  static bool _wantsRegionChangeUpdate(void *checker,
274                                       const ProgramState *state) {
275    return ((const CHECKER *)checker)->wantsRegionChangeUpdate(state);
276  }
277
278public:
279  template <typename CHECKER>
280  static void _register(CHECKER *checker, CheckerManager &mgr) {
281    mgr._registerForRegionChanges(
282          CheckerManager::CheckRegionChangesFunc(checker,
283                                                 _checkRegionChanges<CHECKER>),
284          CheckerManager::WantsRegionChangeUpdateFunc(checker,
285                                            _wantsRegionChangeUpdate<CHECKER>));
286  }
287};
288
289template <typename EVENT>
290class Event {
291  template <typename CHECKER>
292  static void _checkEvent(void *checker, const void *event) {
293    ((const CHECKER *)checker)->checkEvent(*(const EVENT *)event);
294  }
295public:
296  template <typename CHECKER>
297  static void _register(CHECKER *checker, CheckerManager &mgr) {
298    mgr._registerListenerForEvent<EVENT>(
299                 CheckerManager::CheckEventFunc(checker, _checkEvent<CHECKER>));
300  }
301};
302
303} // end check namespace
304
305namespace eval {
306
307class Assume {
308  template <typename CHECKER>
309  static const ProgramState *_evalAssume(void *checker,
310                                         const ProgramState *state,
311                                         const SVal &cond,
312                                         bool assumption) {
313    return ((const CHECKER *)checker)->evalAssume(state, cond, assumption);
314  }
315
316public:
317  template <typename CHECKER>
318  static void _register(CHECKER *checker, CheckerManager &mgr) {
319    mgr._registerForEvalAssume(
320                 CheckerManager::EvalAssumeFunc(checker, _evalAssume<CHECKER>));
321  }
322};
323
324class Call {
325  template <typename CHECKER>
326  static bool _evalCall(void *checker, const CallExpr *CE, CheckerContext &C) {
327    return ((const CHECKER *)checker)->evalCall(CE, C);
328  }
329
330public:
331  template <typename CHECKER>
332  static void _register(CHECKER *checker, CheckerManager &mgr) {
333    mgr._registerForEvalCall(
334                     CheckerManager::EvalCallFunc(checker, _evalCall<CHECKER>));
335  }
336};
337
338class InlineCall {
339  template <typename CHECKER>
340  static bool _inlineCall(void *checker, const CallExpr *CE,
341                                         ExprEngine &Eng,
342                                         ExplodedNode *Pred,
343                                         ExplodedNodeSet &Dst) {
344    return ((const CHECKER *)checker)->inlineCall(CE, Eng, Pred, Dst);
345  }
346
347public:
348  template <typename CHECKER>
349  static void _register(CHECKER *checker, CheckerManager &mgr) {
350    mgr._registerForInlineCall(
351                 CheckerManager::InlineCallFunc(checker, _inlineCall<CHECKER>));
352  }
353};
354
355} // end eval namespace
356
357class CheckerBase : public ProgramPointTag {
358public:
359  StringRef getTagDescription() const;
360
361  /// See CheckerManager::runCheckersForPrintState.
362  virtual void printState(raw_ostream &Out, const ProgramState *State,
363                          const char *NL, const char *Sep) const { }
364};
365
366template <typename CHECK1, typename CHECK2=check::_VoidCheck,
367          typename CHECK3=check::_VoidCheck, typename CHECK4=check::_VoidCheck,
368          typename CHECK5=check::_VoidCheck, typename CHECK6=check::_VoidCheck,
369          typename CHECK7=check::_VoidCheck, typename CHECK8=check::_VoidCheck,
370          typename CHECK9=check::_VoidCheck, typename CHECK10=check::_VoidCheck,
371          typename CHECK11=check::_VoidCheck,typename CHECK12=check::_VoidCheck,
372          typename CHECK13=check::_VoidCheck,typename CHECK14=check::_VoidCheck,
373          typename CHECK15=check::_VoidCheck,typename CHECK16=check::_VoidCheck>
374class Checker;
375
376template <>
377class Checker<check::_VoidCheck, check::_VoidCheck, check::_VoidCheck,
378                check::_VoidCheck, check::_VoidCheck, check::_VoidCheck,
379                check::_VoidCheck, check::_VoidCheck, check::_VoidCheck,
380                check::_VoidCheck, check::_VoidCheck, check::_VoidCheck,
381                check::_VoidCheck, check::_VoidCheck, check::_VoidCheck,
382                check::_VoidCheck>
383  : public CheckerBase
384{
385public:
386  static void _register(void *checker, CheckerManager &mgr) { }
387};
388
389template <typename CHECK1, typename CHECK2, typename CHECK3, typename CHECK4,
390          typename CHECK5, typename CHECK6, typename CHECK7, typename CHECK8,
391          typename CHECK9, typename CHECK10,typename CHECK11,typename CHECK12,
392          typename CHECK13,typename CHECK14,typename CHECK15,typename CHECK16>
393class Checker
394    : public CHECK1,
395      public Checker<CHECK2, CHECK3, CHECK4, CHECK5, CHECK6, CHECK7, CHECK8,
396                     CHECK9, CHECK10,CHECK11,CHECK12,CHECK13,CHECK14,CHECK15,
397                     CHECK16> {
398public:
399  template <typename CHECKER>
400  static void _register(CHECKER *checker, CheckerManager &mgr) {
401    CHECK1::_register(checker, mgr);
402    Checker<CHECK2, CHECK3, CHECK4, CHECK5, CHECK6, CHECK7, CHECK8,
403            CHECK9, CHECK10,CHECK11,CHECK12,CHECK13,CHECK14,CHECK15,
404            CHECK16>::_register(checker, mgr);
405  }
406};
407
408template <typename EVENT>
409class EventDispatcher {
410  CheckerManager *Mgr;
411public:
412  EventDispatcher() : Mgr(0) { }
413
414  template <typename CHECKER>
415  static void _register(CHECKER *checker, CheckerManager &mgr) {
416    mgr._registerDispatcherForEvent<EVENT>();
417    static_cast<EventDispatcher<EVENT> *>(checker)->Mgr = &mgr;
418  }
419
420  void dispatchEvent(const EVENT &event) const {
421    Mgr->_dispatchEvent(event);
422  }
423};
424
425/// \brief We dereferenced a location that may be null.
426struct ImplicitNullDerefEvent {
427  SVal Location;
428  bool IsLoad;
429  ExplodedNode *SinkNode;
430  BugReporter *BR;
431};
432
433} // end ento namespace
434
435} // end clang namespace
436
437#endif
438