]> CyberLeo.Net >> Repos - FreeBSD/releng/9.0.git/blob - contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/Checker.h
Copy stable/9 to releng/9.0 as part of the FreeBSD 9.0-RELEASE release
[FreeBSD/releng/9.0.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/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
22 namespace clang {
23 namespace ento {
24   class BugReporter;
25
26 namespace check {
27
28 struct _VoidCheck {
29   static void _register(void *checker, CheckerManager &mgr) { }
30 };
31
32 template <typename DECL>
33 class 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   }
43 public:
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
52 class 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
59 public:
60   template <typename CHECKER>
61   static void _register(CHECKER *checker, CheckerManager &mgr) {
62     mgr._registerForBody(CheckerManager::CheckDeclFunc(checker,
63                                                        _checkBody<CHECKER>));
64   }
65 };
66
67 class 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
76 public:
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
85 template <typename STMT>
86 class 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   }
95 public:
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
104 template <typename STMT>
105 class 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   }
114 public:
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
123 class 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
130 public:
131   template <typename CHECKER>
132   static void _register(CHECKER *checker, CheckerManager &mgr) {
133     mgr._registerForPreObjCMessage(
134      CheckerManager::CheckObjCMessageFunc(checker, _checkObjCMessage<CHECKER>));
135   }
136 };
137
138 class 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
145 public:
146   template <typename CHECKER>
147   static void _register(CHECKER *checker, CheckerManager &mgr) {
148     mgr._registerForPostObjCMessage(
149      CheckerManager::CheckObjCMessageFunc(checker, _checkObjCMessage<CHECKER>));
150   }
151 };
152
153 class 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
161 public:
162   template <typename CHECKER>
163   static void _register(CHECKER *checker, CheckerManager &mgr) {
164     mgr._registerForLocation(
165            CheckerManager::CheckLocationFunc(checker, _checkLocation<CHECKER>));
166   }
167 };
168
169 class 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
177 public:
178   template <typename CHECKER>
179   static void _register(CHECKER *checker, CheckerManager &mgr) {
180     mgr._registerForBind(
181            CheckerManager::CheckBindFunc(checker, _checkBind<CHECKER>));
182   }
183 };
184
185 class 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
192 public:
193   template <typename CHECKER>
194   static void _register(CHECKER *checker, CheckerManager &mgr) {
195     mgr._registerForEndAnalysis(
196      CheckerManager::CheckEndAnalysisFunc(checker, _checkEndAnalysis<CHECKER>));
197   }
198 };
199
200 class EndPath {
201   template <typename CHECKER>
202   static void _checkEndPath(void *checker, EndOfFunctionNodeBuilder &B,
203                             ExprEngine &Eng) {
204     ((const CHECKER *)checker)->checkEndPath(B, Eng);
205   }
206
207 public:
208   template <typename CHECKER>
209   static void _register(CHECKER *checker, CheckerManager &mgr) {
210     mgr._registerForEndPath(
211      CheckerManager::CheckEndPathFunc(checker, _checkEndPath<CHECKER>));
212   }
213 };
214
215 class BranchCondition {
216   template <typename CHECKER>
217   static void _checkBranchCondition(void *checker, const Stmt *condition,
218                                     BranchNodeBuilder &B, ExprEngine &Eng) {
219     ((const CHECKER *)checker)->checkBranchCondition(condition, B, Eng);
220   }
221
222 public:
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
231 class 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
238 public:
239   template <typename CHECKER>
240   static void _register(CHECKER *checker, CheckerManager &mgr) {
241     mgr._registerForLiveSymbols(
242      CheckerManager::CheckLiveSymbolsFunc(checker, _checkLiveSymbols<CHECKER>));
243   }
244 };
245
246 class 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
253 public:
254   template <typename CHECKER>
255   static void _register(CHECKER *checker, CheckerManager &mgr) {
256     mgr._registerForDeadSymbols(
257      CheckerManager::CheckDeadSymbolsFunc(checker, _checkDeadSymbols<CHECKER>));
258   }
259 };
260
261 class 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
278 public:
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
289 template <typename EVENT>
290 class Event {
291   template <typename CHECKER>
292   static void _checkEvent(void *checker, const void *event) {
293     ((const CHECKER *)checker)->checkEvent(*(const EVENT *)event);
294   }
295 public:
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
305 namespace eval {
306
307 class 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
316 public:
317   template <typename CHECKER>
318   static void _register(CHECKER *checker, CheckerManager &mgr) {
319     mgr._registerForEvalAssume(
320                  CheckerManager::EvalAssumeFunc(checker, _evalAssume<CHECKER>));
321   }
322 };
323
324 class 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
330 public:
331   template <typename CHECKER>
332   static void _register(CHECKER *checker, CheckerManager &mgr) {
333     mgr._registerForEvalCall(
334                      CheckerManager::EvalCallFunc(checker, _evalCall<CHECKER>));
335   }
336 };
337
338 class 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
347 public:
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
357 class CheckerBase : public ProgramPointTag {
358 public:
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   
366 template <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 class Checker;
375
376 template <>
377 class 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 {
385 public:
386   static void _register(void *checker, CheckerManager &mgr) { }
387 };
388
389 template <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>
393 class Checker
394     : public CHECK1,
395       public Checker<CHECK2, CHECK3, CHECK4, CHECK5, CHECK6, CHECK7, CHECK8,
396                      CHECK9, CHECK10,CHECK11,CHECK12,CHECK13,CHECK14,CHECK15,
397                      CHECK16> {
398 public:
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
408 template <typename EVENT>
409 class EventDispatcher {
410   CheckerManager *Mgr;
411 public:
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.
426 struct 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