Checker.h revision af498a28797c075c48d7e943df5f5a8e78ed8eb0
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                                    NodeBuilder &B, ExplodedNode *Pred,
219                                    ExprEngine &Eng) {
220    ((const CHECKER *)checker)->checkBranchCondition(condition, B, Pred, Eng);
221  }
222
223public:
224  template <typename CHECKER>
225  static void _register(CHECKER *checker, CheckerManager &mgr) {
226    mgr._registerForBranchCondition(
227      CheckerManager::CheckBranchConditionFunc(checker,
228                                               _checkBranchCondition<CHECKER>));
229  }
230};
231
232class LiveSymbols {
233  template <typename CHECKER>
234  static void _checkLiveSymbols(void *checker, const ProgramState *state,
235                                SymbolReaper &SR) {
236    ((const CHECKER *)checker)->checkLiveSymbols(state, SR);
237  }
238
239public:
240  template <typename CHECKER>
241  static void _register(CHECKER *checker, CheckerManager &mgr) {
242    mgr._registerForLiveSymbols(
243     CheckerManager::CheckLiveSymbolsFunc(checker, _checkLiveSymbols<CHECKER>));
244  }
245};
246
247class DeadSymbols {
248  template <typename CHECKER>
249  static void _checkDeadSymbols(void *checker,
250                                SymbolReaper &SR, CheckerContext &C) {
251    ((const CHECKER *)checker)->checkDeadSymbols(SR, C);
252  }
253
254public:
255  template <typename CHECKER>
256  static void _register(CHECKER *checker, CheckerManager &mgr) {
257    mgr._registerForDeadSymbols(
258     CheckerManager::CheckDeadSymbolsFunc(checker, _checkDeadSymbols<CHECKER>));
259  }
260};
261
262class RegionChanges {
263  template <typename CHECKER>
264  static const ProgramState *
265  _checkRegionChanges(void *checker,
266                      const ProgramState *state,
267                      const StoreManager::InvalidatedSymbols *invalidated,
268                      ArrayRef<const MemRegion *> Explicits,
269                      ArrayRef<const MemRegion *> Regions) {
270    return ((const CHECKER *)checker)->checkRegionChanges(state, invalidated,
271                                                          Explicits, Regions);
272  }
273  template <typename CHECKER>
274  static bool _wantsRegionChangeUpdate(void *checker,
275                                       const ProgramState *state) {
276    return ((const CHECKER *)checker)->wantsRegionChangeUpdate(state);
277  }
278
279public:
280  template <typename CHECKER>
281  static void _register(CHECKER *checker, CheckerManager &mgr) {
282    mgr._registerForRegionChanges(
283          CheckerManager::CheckRegionChangesFunc(checker,
284                                                 _checkRegionChanges<CHECKER>),
285          CheckerManager::WantsRegionChangeUpdateFunc(checker,
286                                            _wantsRegionChangeUpdate<CHECKER>));
287  }
288};
289
290template <typename EVENT>
291class Event {
292  template <typename CHECKER>
293  static void _checkEvent(void *checker, const void *event) {
294    ((const CHECKER *)checker)->checkEvent(*(const EVENT *)event);
295  }
296public:
297  template <typename CHECKER>
298  static void _register(CHECKER *checker, CheckerManager &mgr) {
299    mgr._registerListenerForEvent<EVENT>(
300                 CheckerManager::CheckEventFunc(checker, _checkEvent<CHECKER>));
301  }
302};
303
304} // end check namespace
305
306namespace eval {
307
308class Assume {
309  template <typename CHECKER>
310  static const ProgramState *_evalAssume(void *checker,
311                                         const ProgramState *state,
312                                         const SVal &cond,
313                                         bool assumption) {
314    return ((const CHECKER *)checker)->evalAssume(state, cond, assumption);
315  }
316
317public:
318  template <typename CHECKER>
319  static void _register(CHECKER *checker, CheckerManager &mgr) {
320    mgr._registerForEvalAssume(
321                 CheckerManager::EvalAssumeFunc(checker, _evalAssume<CHECKER>));
322  }
323};
324
325class Call {
326  template <typename CHECKER>
327  static bool _evalCall(void *checker, const CallExpr *CE, CheckerContext &C) {
328    return ((const CHECKER *)checker)->evalCall(CE, C);
329  }
330
331public:
332  template <typename CHECKER>
333  static void _register(CHECKER *checker, CheckerManager &mgr) {
334    mgr._registerForEvalCall(
335                     CheckerManager::EvalCallFunc(checker, _evalCall<CHECKER>));
336  }
337};
338
339class InlineCall {
340  template <typename CHECKER>
341  static bool _inlineCall(void *checker, const CallExpr *CE,
342                                         ExprEngine &Eng,
343                                         ExplodedNode *Pred,
344                                         ExplodedNodeSet &Dst) {
345    return ((const CHECKER *)checker)->inlineCall(CE, Eng, Pred, Dst);
346  }
347
348public:
349  template <typename CHECKER>
350  static void _register(CHECKER *checker, CheckerManager &mgr) {
351    mgr._registerForInlineCall(
352                 CheckerManager::InlineCallFunc(checker, _inlineCall<CHECKER>));
353  }
354};
355
356} // end eval namespace
357
358class CheckerBase : public ProgramPointTag {
359public:
360  StringRef getTagDescription() const;
361
362  /// See CheckerManager::runCheckersForPrintState.
363  virtual void printState(raw_ostream &Out, const ProgramState *State,
364                          const char *NL, const char *Sep) const { }
365};
366
367template <typename CHECK1, typename CHECK2=check::_VoidCheck,
368          typename CHECK3=check::_VoidCheck, typename CHECK4=check::_VoidCheck,
369          typename CHECK5=check::_VoidCheck, typename CHECK6=check::_VoidCheck,
370          typename CHECK7=check::_VoidCheck, typename CHECK8=check::_VoidCheck,
371          typename CHECK9=check::_VoidCheck, typename CHECK10=check::_VoidCheck,
372          typename CHECK11=check::_VoidCheck,typename CHECK12=check::_VoidCheck,
373          typename CHECK13=check::_VoidCheck,typename CHECK14=check::_VoidCheck,
374          typename CHECK15=check::_VoidCheck,typename CHECK16=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>
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>
394class Checker
395    : public CHECK1,
396      public Checker<CHECK2, CHECK3, CHECK4, CHECK5, CHECK6, CHECK7, CHECK8,
397                     CHECK9, CHECK10,CHECK11,CHECK12,CHECK13,CHECK14,CHECK15,
398                     CHECK16> {
399public:
400  template <typename CHECKER>
401  static void _register(CHECKER *checker, CheckerManager &mgr) {
402    CHECK1::_register(checker, mgr);
403    Checker<CHECK2, CHECK3, CHECK4, CHECK5, CHECK6, CHECK7, CHECK8,
404            CHECK9, CHECK10,CHECK11,CHECK12,CHECK13,CHECK14,CHECK15,
405            CHECK16>::_register(checker, mgr);
406  }
407};
408
409template <typename EVENT>
410class EventDispatcher {
411  CheckerManager *Mgr;
412public:
413  EventDispatcher() : Mgr(0) { }
414
415  template <typename CHECKER>
416  static void _register(CHECKER *checker, CheckerManager &mgr) {
417    mgr._registerDispatcherForEvent<EVENT>();
418    static_cast<EventDispatcher<EVENT> *>(checker)->Mgr = &mgr;
419  }
420
421  void dispatchEvent(const EVENT &event) const {
422    Mgr->_dispatchEvent(event);
423  }
424};
425
426/// \brief We dereferenced a location that may be null.
427struct ImplicitNullDerefEvent {
428  SVal Location;
429  bool IsLoad;
430  ExplodedNode *SinkNode;
431  BugReporter *BR;
432};
433
434} // end ento namespace
435
436} // end clang namespace
437
438#endif
439