Checker.h revision 66c40400e7d6272b0cd675ada18dd62c1f0362c7
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, ProgramStateRef 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 ProgramStateRef
264  _checkRegionChanges(void *checker,
265                      ProgramStateRef state,
266                      const StoreManager::InvalidatedSymbols *invalidated,
267                      ArrayRef<const MemRegion *> Explicits,
268                      ArrayRef<const MemRegion *> Regions,
269                      const CallOrObjCMessage *Call) {
270    return ((const CHECKER *)checker)->checkRegionChanges(state, invalidated,
271                                                      Explicits, Regions, Call);
272  }
273  template <typename CHECKER>
274  static bool _wantsRegionChangeUpdate(void *checker,
275                                       ProgramStateRef 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 ProgramStateRef _evalAssume(void *checker,
311                                         ProgramStateRef 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, ProgramStateRef 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,
375          typename CHECK17=check::_VoidCheck,typename CHECK18=check::_VoidCheck>
376class Checker;
377
378template <>
379class Checker<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                check::_VoidCheck, check::_VoidCheck, check::_VoidCheck>
385  : public CheckerBase
386{
387  virtual void anchor();
388public:
389  static void _register(void *checker, CheckerManager &mgr) { }
390};
391
392template <typename CHECK1, typename CHECK2, typename CHECK3, typename CHECK4,
393          typename CHECK5, typename CHECK6, typename CHECK7, typename CHECK8,
394          typename CHECK9, typename CHECK10,typename CHECK11,typename CHECK12,
395          typename CHECK13,typename CHECK14,typename CHECK15,typename CHECK16,
396          typename CHECK17,typename CHECK18>
397class Checker
398    : public CHECK1,
399      public Checker<CHECK2, CHECK3, CHECK4, CHECK5, CHECK6, CHECK7, CHECK8,
400                     CHECK9, CHECK10,CHECK11,CHECK12,CHECK13,CHECK14,CHECK15,
401                     CHECK16,CHECK17,CHECK18> {
402public:
403  template <typename CHECKER>
404  static void _register(CHECKER *checker, CheckerManager &mgr) {
405    CHECK1::_register(checker, mgr);
406    Checker<CHECK2, CHECK3, CHECK4, CHECK5, CHECK6, CHECK7, CHECK8,
407            CHECK9, CHECK10,CHECK11,CHECK12,CHECK13,CHECK14,CHECK15,
408            CHECK16,CHECK17,CHECK18>::_register(checker, mgr);
409  }
410};
411
412template <typename EVENT>
413class EventDispatcher {
414  CheckerManager *Mgr;
415public:
416  EventDispatcher() : Mgr(0) { }
417
418  template <typename CHECKER>
419  static void _register(CHECKER *checker, CheckerManager &mgr) {
420    mgr._registerDispatcherForEvent<EVENT>();
421    static_cast<EventDispatcher<EVENT> *>(checker)->Mgr = &mgr;
422  }
423
424  void dispatchEvent(const EVENT &event) const {
425    Mgr->_dispatchEvent(event);
426  }
427};
428
429/// \brief We dereferenced a location that may be null.
430struct ImplicitNullDerefEvent {
431  SVal Location;
432  bool IsLoad;
433  ExplodedNode *SinkNode;
434  BugReporter *BR;
435};
436
437} // end ento namespace
438
439} // end clang namespace
440
441#endif
442