Checker.h revision d699ade396154238d2fa89bb09fdcfb79e5587d2
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,
374          typename CHECK17=check::_VoidCheck,typename CHECK18=check::_VoidCheck>
375class Checker;
376
377template <>
378class Checker<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, check::_VoidCheck, check::_VoidCheck,
383                check::_VoidCheck, check::_VoidCheck, check::_VoidCheck>
384  : public CheckerBase
385{
386public:
387  static void _register(void *checker, CheckerManager &mgr) { }
388};
389
390template <typename CHECK1, typename CHECK2, typename CHECK3, typename CHECK4,
391          typename CHECK5, typename CHECK6, typename CHECK7, typename CHECK8,
392          typename CHECK9, typename CHECK10,typename CHECK11,typename CHECK12,
393          typename CHECK13,typename CHECK14,typename CHECK15,typename CHECK16,
394          typename CHECK17,typename CHECK18>
395class Checker
396    : public CHECK1,
397      public Checker<CHECK2, CHECK3, CHECK4, CHECK5, CHECK6, CHECK7, CHECK8,
398                     CHECK9, CHECK10,CHECK11,CHECK12,CHECK13,CHECK14,CHECK15,
399                     CHECK16,CHECK17,CHECK18> {
400public:
401  template <typename CHECKER>
402  static void _register(CHECKER *checker, CheckerManager &mgr) {
403    CHECK1::_register(checker, mgr);
404    Checker<CHECK2, CHECK3, CHECK4, CHECK5, CHECK6, CHECK7, CHECK8,
405            CHECK9, CHECK10,CHECK11,CHECK12,CHECK13,CHECK14,CHECK15,
406            CHECK16,CHECK17,CHECK18>::_register(checker, mgr);
407  }
408};
409
410template <typename EVENT>
411class EventDispatcher {
412  CheckerManager *Mgr;
413public:
414  EventDispatcher() : Mgr(0) { }
415
416  template <typename CHECKER>
417  static void _register(CHECKER *checker, CheckerManager &mgr) {
418    mgr._registerDispatcherForEvent<EVENT>();
419    static_cast<EventDispatcher<EVENT> *>(checker)->Mgr = &mgr;
420  }
421
422  void dispatchEvent(const EVENT &event) const {
423    Mgr->_dispatchEvent(event);
424  }
425};
426
427/// \brief We dereferenced a location that may be null.
428struct ImplicitNullDerefEvent {
429  SVal Location;
430  bool IsLoad;
431  ExplodedNode *SinkNode;
432  BugReporter *BR;
433};
434
435} // end ento namespace
436
437} // end clang namespace
438
439#endif
440