]> CyberLeo.Net >> Repos - FreeBSD/stable/9.git/blob - contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/Checker.h
Copy head to stable/9 as part of 9.0-RELEASE release cycle.
[FreeBSD/stable/9.git] / contrib / llvm / tools / clang / include / clang / StaticAnalyzer / Core / Checker.h
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/StaticAnalyzer/Core/CheckerManager.h"
18 #include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h"
19 #include "llvm/Support/Casting.h"
20
21 namespace clang {
22 namespace ento {
23   class BugReporter;
24
25 namespace check {
26
27 struct _VoidCheck {
28   static void _register(void *checker, CheckerManager &mgr) { }
29 };
30
31 template <typename DECL>
32 class ASTDecl {
33   template <typename CHECKER>
34   static void _checkDecl(void *checker, const Decl *D, AnalysisManager& mgr,
35                          BugReporter &BR) {
36     ((const CHECKER *)checker)->checkASTDecl(llvm::cast<DECL>(D), mgr, BR);
37   }
38
39   static bool _handlesDecl(const Decl *D) {
40     return llvm::isa<DECL>(D);
41   }
42 public:
43   template <typename CHECKER>
44   static void _register(CHECKER *checker, CheckerManager &mgr) {
45     mgr._registerForDecl(CheckerManager::CheckDeclFunc(checker,
46                                                        _checkDecl<CHECKER>),
47                          _handlesDecl);
48   }
49 };
50
51 class ASTCodeBody {
52   template <typename CHECKER>
53   static void _checkBody(void *checker, const Decl *D, AnalysisManager& mgr,
54                          BugReporter &BR) {
55     ((const CHECKER *)checker)->checkASTCodeBody(D, mgr, BR);
56   }
57
58 public:
59   template <typename CHECKER>
60   static void _register(CHECKER *checker, CheckerManager &mgr) {
61     mgr._registerForBody(CheckerManager::CheckDeclFunc(checker,
62                                                        _checkBody<CHECKER>));
63   }
64 };
65
66 class EndOfTranslationUnit {
67   template <typename CHECKER>
68   static void _checkEndOfTranslationUnit(void *checker,
69                                          const TranslationUnitDecl *TU, 
70                                          AnalysisManager& mgr,
71                                          BugReporter &BR) {
72     ((const CHECKER *)checker)->checkEndOfTranslationUnit(TU, mgr, BR);
73   }
74
75 public:
76   template <typename CHECKER>
77   static void _register(CHECKER *checker, CheckerManager &mgr){
78     mgr._registerForEndOfTranslationUnit(
79                               CheckerManager::CheckEndOfTranslationUnit(checker,
80                                           _checkEndOfTranslationUnit<CHECKER>));
81   }
82 };
83
84 template <typename STMT>
85 class PreStmt {
86   template <typename CHECKER>
87   static void _checkStmt(void *checker, const Stmt *S, CheckerContext &C) {
88     ((const CHECKER *)checker)->checkPreStmt(llvm::cast<STMT>(S), C);
89   }
90
91   static bool _handlesStmt(const Stmt *S) {
92     return llvm::isa<STMT>(S);
93   }
94 public:
95   template <typename CHECKER>
96   static void _register(CHECKER *checker, CheckerManager &mgr) {
97     mgr._registerForPreStmt(CheckerManager::CheckStmtFunc(checker,
98                                                           _checkStmt<CHECKER>),
99                             _handlesStmt);
100   }
101 };
102
103 template <typename STMT>
104 class PostStmt {
105   template <typename CHECKER>
106   static void _checkStmt(void *checker, const Stmt *S, CheckerContext &C) {
107     ((const CHECKER *)checker)->checkPostStmt(llvm::cast<STMT>(S), C);
108   }
109
110   static bool _handlesStmt(const Stmt *S) {
111     return llvm::isa<STMT>(S);
112   }
113 public:
114   template <typename CHECKER>
115   static void _register(CHECKER *checker, CheckerManager &mgr) {
116     mgr._registerForPostStmt(CheckerManager::CheckStmtFunc(checker,
117                                                            _checkStmt<CHECKER>),
118                              _handlesStmt);
119   }
120 };
121
122 class PreObjCMessage {
123   template <typename CHECKER>
124   static void _checkObjCMessage(void *checker, const ObjCMessage &msg,
125                                 CheckerContext &C) {
126     ((const CHECKER *)checker)->checkPreObjCMessage(msg, C);
127   }
128
129 public:
130   template <typename CHECKER>
131   static void _register(CHECKER *checker, CheckerManager &mgr) {
132     mgr._registerForPreObjCMessage(
133      CheckerManager::CheckObjCMessageFunc(checker, _checkObjCMessage<CHECKER>));
134   }
135 };
136
137 class PostObjCMessage {
138   template <typename CHECKER>
139   static void _checkObjCMessage(void *checker, const ObjCMessage &msg,
140                                 CheckerContext &C) {
141     ((const CHECKER *)checker)->checkPostObjCMessage(msg, C);
142   }
143
144 public:
145   template <typename CHECKER>
146   static void _register(CHECKER *checker, CheckerManager &mgr) {
147     mgr._registerForPostObjCMessage(
148      CheckerManager::CheckObjCMessageFunc(checker, _checkObjCMessage<CHECKER>));
149   }
150 };
151
152 class Location {
153   template <typename CHECKER>
154   static void _checkLocation(void *checker, const SVal &location, bool isLoad,
155                              CheckerContext &C) {
156     ((const CHECKER *)checker)->checkLocation(location, isLoad, C);
157   }
158
159 public:
160   template <typename CHECKER>
161   static void _register(CHECKER *checker, CheckerManager &mgr) {
162     mgr._registerForLocation(
163            CheckerManager::CheckLocationFunc(checker, _checkLocation<CHECKER>));
164   }
165 };
166
167 class Bind {
168   template <typename CHECKER>
169   static void _checkBind(void *checker, const SVal &location, const SVal &val,
170                          CheckerContext &C) {
171     ((const CHECKER *)checker)->checkBind(location, val, C);
172   }
173
174 public:
175   template <typename CHECKER>
176   static void _register(CHECKER *checker, CheckerManager &mgr) {
177     mgr._registerForBind(
178            CheckerManager::CheckBindFunc(checker, _checkBind<CHECKER>));
179   }
180 };
181
182 class EndAnalysis {
183   template <typename CHECKER>
184   static void _checkEndAnalysis(void *checker, ExplodedGraph &G,
185                                 BugReporter &BR, ExprEngine &Eng) {
186     ((const CHECKER *)checker)->checkEndAnalysis(G, BR, Eng);
187   }
188
189 public:
190   template <typename CHECKER>
191   static void _register(CHECKER *checker, CheckerManager &mgr) {
192     mgr._registerForEndAnalysis(
193      CheckerManager::CheckEndAnalysisFunc(checker, _checkEndAnalysis<CHECKER>));
194   }
195 };
196
197 class EndPath {
198   template <typename CHECKER>
199   static void _checkEndPath(void *checker, EndOfFunctionNodeBuilder &B,
200                             ExprEngine &Eng) {
201     ((const CHECKER *)checker)->checkEndPath(B, Eng);
202   }
203
204 public:
205   template <typename CHECKER>
206   static void _register(CHECKER *checker, CheckerManager &mgr) {
207     mgr._registerForEndPath(
208      CheckerManager::CheckEndPathFunc(checker, _checkEndPath<CHECKER>));
209   }
210 };
211
212 class BranchCondition {
213   template <typename CHECKER>
214   static void _checkBranchCondition(void *checker, const Stmt *condition,
215                                     BranchNodeBuilder &B, ExprEngine &Eng) {
216     ((const CHECKER *)checker)->checkBranchCondition(condition, B, Eng);
217   }
218
219 public:
220   template <typename CHECKER>
221   static void _register(CHECKER *checker, CheckerManager &mgr) {
222     mgr._registerForBranchCondition(
223       CheckerManager::CheckBranchConditionFunc(checker,
224                                                _checkBranchCondition<CHECKER>));
225   }
226 };
227
228 class LiveSymbols {
229   template <typename CHECKER>
230   static void _checkLiveSymbols(void *checker, const GRState *state,
231                                 SymbolReaper &SR) {
232     ((const CHECKER *)checker)->checkLiveSymbols(state, SR);
233   }
234
235 public:
236   template <typename CHECKER>
237   static void _register(CHECKER *checker, CheckerManager &mgr) {
238     mgr._registerForLiveSymbols(
239      CheckerManager::CheckLiveSymbolsFunc(checker, _checkLiveSymbols<CHECKER>));
240   }
241 };
242
243 class DeadSymbols {
244   template <typename CHECKER>
245   static void _checkDeadSymbols(void *checker,
246                                 SymbolReaper &SR, CheckerContext &C) {
247     ((const CHECKER *)checker)->checkDeadSymbols(SR, C);
248   }
249
250 public:
251   template <typename CHECKER>
252   static void _register(CHECKER *checker, CheckerManager &mgr) {
253     mgr._registerForDeadSymbols(
254      CheckerManager::CheckDeadSymbolsFunc(checker, _checkDeadSymbols<CHECKER>));
255   }
256 };
257
258 class RegionChanges {
259   template <typename CHECKER>
260   static const GRState *_checkRegionChanges(void *checker, const GRState *state,
261                             const StoreManager::InvalidatedSymbols *invalidated,
262                                             const MemRegion * const *Begin,
263                                             const MemRegion * const *End) {
264     return ((const CHECKER *)checker)->checkRegionChanges(state, invalidated,
265                                                           Begin, End);
266   }
267   template <typename CHECKER>
268   static bool _wantsRegionChangeUpdate(void *checker, const GRState *state) {
269     return ((const CHECKER *)checker)->wantsRegionChangeUpdate(state);
270   }
271
272 public:
273   template <typename CHECKER>
274   static void _register(CHECKER *checker, CheckerManager &mgr) {
275     mgr._registerForRegionChanges(
276           CheckerManager::CheckRegionChangesFunc(checker,
277                                                  _checkRegionChanges<CHECKER>),
278           CheckerManager::WantsRegionChangeUpdateFunc(checker,
279                                             _wantsRegionChangeUpdate<CHECKER>));
280   }
281 };
282
283 template <typename EVENT>
284 class Event {
285   template <typename CHECKER>
286   static void _checkEvent(void *checker, const void *event) {
287     ((const CHECKER *)checker)->checkEvent(*(const EVENT *)event);
288   }
289 public:
290   template <typename CHECKER>
291   static void _register(CHECKER *checker, CheckerManager &mgr) {
292     mgr._registerListenerForEvent<EVENT>(
293                  CheckerManager::CheckEventFunc(checker, _checkEvent<CHECKER>));
294   }
295 };
296
297 } // end check namespace
298
299 namespace eval {
300
301 class Assume {
302   template <typename CHECKER>
303   static const GRState *_evalAssume(void *checker, const GRState *state,
304                                     const SVal &cond, bool assumption) {
305     return ((const CHECKER *)checker)->evalAssume(state, cond, assumption);
306   }
307
308 public:
309   template <typename CHECKER>
310   static void _register(CHECKER *checker, CheckerManager &mgr) {
311     mgr._registerForEvalAssume(
312                  CheckerManager::EvalAssumeFunc(checker, _evalAssume<CHECKER>));
313   }
314 };
315
316 class Call {
317   template <typename CHECKER>
318   static bool _evalCall(void *checker, const CallExpr *CE, CheckerContext &C) {
319     return ((const CHECKER *)checker)->evalCall(CE, C);
320   }
321
322 public:
323   template <typename CHECKER>
324   static void _register(CHECKER *checker, CheckerManager &mgr) {
325     mgr._registerForEvalCall(
326                      CheckerManager::EvalCallFunc(checker, _evalCall<CHECKER>));
327   }
328 };
329
330 } // end eval namespace
331
332 template <typename CHECK1, typename CHECK2=check::_VoidCheck,
333           typename CHECK3=check::_VoidCheck, typename CHECK4=check::_VoidCheck,
334           typename CHECK5=check::_VoidCheck, typename CHECK6=check::_VoidCheck,
335           typename CHECK7=check::_VoidCheck, typename CHECK8=check::_VoidCheck,
336           typename CHECK9=check::_VoidCheck, typename CHECK10=check::_VoidCheck,
337           typename CHECK11=check::_VoidCheck,typename CHECK12=check::_VoidCheck>
338 class Checker;
339
340 template <>
341 class Checker<check::_VoidCheck, check::_VoidCheck, check::_VoidCheck,
342                 check::_VoidCheck, check::_VoidCheck, check::_VoidCheck,
343                 check::_VoidCheck, check::_VoidCheck, check::_VoidCheck,
344                 check::_VoidCheck, check::_VoidCheck, check::_VoidCheck> {
345 public:
346   static void _register(void *checker, CheckerManager &mgr) { }
347 };
348
349 template <typename CHECK1, typename CHECK2, typename CHECK3, typename CHECK4,
350           typename CHECK5, typename CHECK6, typename CHECK7, typename CHECK8,
351           typename CHECK9, typename CHECK10,typename CHECK11,typename CHECK12>
352 class Checker
353     : public CHECK1,
354       public Checker<CHECK2, CHECK3, CHECK4, CHECK5, CHECK6, CHECK7, CHECK8,
355                        CHECK9, CHECK10, CHECK11, CHECK12> {
356 public:
357   template <typename CHECKER>
358   static void _register(CHECKER *checker, CheckerManager &mgr) {
359     CHECK1::_register(checker, mgr);
360     Checker<CHECK2, CHECK3, CHECK4, CHECK5, CHECK6, CHECK7, CHECK8, CHECK9,
361               CHECK10, CHECK11,CHECK12>::_register(checker, mgr);
362   }
363 };
364
365 template <typename EVENT>
366 class EventDispatcher {
367   CheckerManager *Mgr;
368 public:
369   EventDispatcher() : Mgr(0) { }
370
371   template <typename CHECKER>
372   static void _register(CHECKER *checker, CheckerManager &mgr) {
373     mgr._registerDispatcherForEvent<EVENT>();
374     static_cast<EventDispatcher<EVENT> *>(checker)->Mgr = &mgr;
375   }
376
377   void dispatchEvent(const EVENT &event) const {
378     Mgr->_dispatchEvent(event);
379   }
380 };
381
382 /// \brief We dereferenced a location that may be null.
383 struct ImplicitNullDerefEvent {
384   SVal Location;
385   bool IsLoad;
386   ExplodedNode *SinkNode;
387   BugReporter *BR;
388 };
389
390 } // end ento namespace
391
392 } // end clang namespace
393
394 #endif