]> CyberLeo.Net >> Repos - FreeBSD/releng/10.2.git/blob - contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/Checker.h
- Copy stable/10@285827 to releng/10.2 in preparation for 10.2-RC1
[FreeBSD/releng/10.2.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(cast<DECL>(D), mgr, BR);
38   }
39
40   static bool _handlesDecl(const Decl *D) {
41     return 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(cast<STMT>(S), C);
90   }
91
92   static bool _handlesStmt(const Stmt *S) {
93     return 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(cast<STMT>(S), C);
109   }
110
111   static bool _handlesStmt(const Stmt *S) {
112     return 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 ObjCMethodCall &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 ObjCMethodCall &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 PreCall {
154   template <typename CHECKER>
155   static void _checkCall(void *checker, const CallEvent &msg,
156                          CheckerContext &C) {
157     ((const CHECKER *)checker)->checkPreCall(msg, C);
158   }
159
160 public:
161   template <typename CHECKER>
162   static void _register(CHECKER *checker, CheckerManager &mgr) {
163     mgr._registerForPreCall(
164      CheckerManager::CheckCallFunc(checker, _checkCall<CHECKER>));
165   }
166 };
167
168 class PostCall {
169   template <typename CHECKER>
170   static void _checkCall(void *checker, const CallEvent &msg,
171                          CheckerContext &C) {
172     ((const CHECKER *)checker)->checkPostCall(msg, C);
173   }
174
175 public:
176   template <typename CHECKER>
177   static void _register(CHECKER *checker, CheckerManager &mgr) {
178     mgr._registerForPostCall(
179      CheckerManager::CheckCallFunc(checker, _checkCall<CHECKER>));
180   }
181 };
182
183 class Location {
184   template <typename CHECKER>
185   static void _checkLocation(void *checker,
186                              const SVal &location, bool isLoad, const Stmt *S,
187                              CheckerContext &C) {
188     ((const CHECKER *)checker)->checkLocation(location, isLoad, S, C);
189   }
190
191 public:
192   template <typename CHECKER>
193   static void _register(CHECKER *checker, CheckerManager &mgr) {
194     mgr._registerForLocation(
195            CheckerManager::CheckLocationFunc(checker, _checkLocation<CHECKER>));
196   }
197 };
198
199 class Bind {
200   template <typename CHECKER>
201   static void _checkBind(void *checker,
202                          const SVal &location, const SVal &val, const Stmt *S,
203                          CheckerContext &C) {
204     ((const CHECKER *)checker)->checkBind(location, val, S, C);
205   }
206
207 public:
208   template <typename CHECKER>
209   static void _register(CHECKER *checker, CheckerManager &mgr) {
210     mgr._registerForBind(
211            CheckerManager::CheckBindFunc(checker, _checkBind<CHECKER>));
212   }
213 };
214
215 class EndAnalysis {
216   template <typename CHECKER>
217   static void _checkEndAnalysis(void *checker, ExplodedGraph &G,
218                                 BugReporter &BR, ExprEngine &Eng) {
219     ((const CHECKER *)checker)->checkEndAnalysis(G, BR, Eng);
220   }
221
222 public:
223   template <typename CHECKER>
224   static void _register(CHECKER *checker, CheckerManager &mgr) {
225     mgr._registerForEndAnalysis(
226      CheckerManager::CheckEndAnalysisFunc(checker, _checkEndAnalysis<CHECKER>));
227   }
228 };
229
230 class EndFunction {
231   template <typename CHECKER>
232   static void _checkEndFunction(void *checker,
233                                 CheckerContext &C) {
234     ((const CHECKER *)checker)->checkEndFunction(C);
235   }
236
237 public:
238   template <typename CHECKER>
239   static void _register(CHECKER *checker, CheckerManager &mgr) {
240     mgr._registerForEndFunction(
241      CheckerManager::CheckEndFunctionFunc(checker, _checkEndFunction<CHECKER>));
242   }
243 };
244
245 class BranchCondition {
246   template <typename CHECKER>
247   static void _checkBranchCondition(void *checker, const Stmt *Condition,
248                                     CheckerContext & C) {
249     ((const CHECKER *)checker)->checkBranchCondition(Condition, C);
250   }
251
252 public:
253   template <typename CHECKER>
254   static void _register(CHECKER *checker, CheckerManager &mgr) {
255     mgr._registerForBranchCondition(
256       CheckerManager::CheckBranchConditionFunc(checker,
257                                                _checkBranchCondition<CHECKER>));
258   }
259 };
260
261 class LiveSymbols {
262   template <typename CHECKER>
263   static void _checkLiveSymbols(void *checker, ProgramStateRef state,
264                                 SymbolReaper &SR) {
265     ((const CHECKER *)checker)->checkLiveSymbols(state, SR);
266   }
267
268 public:
269   template <typename CHECKER>
270   static void _register(CHECKER *checker, CheckerManager &mgr) {
271     mgr._registerForLiveSymbols(
272      CheckerManager::CheckLiveSymbolsFunc(checker, _checkLiveSymbols<CHECKER>));
273   }
274 };
275
276 class DeadSymbols {
277   template <typename CHECKER>
278   static void _checkDeadSymbols(void *checker,
279                                 SymbolReaper &SR, CheckerContext &C) {
280     ((const CHECKER *)checker)->checkDeadSymbols(SR, C);
281   }
282
283 public:
284   template <typename CHECKER>
285   static void _register(CHECKER *checker, CheckerManager &mgr) {
286     mgr._registerForDeadSymbols(
287      CheckerManager::CheckDeadSymbolsFunc(checker, _checkDeadSymbols<CHECKER>));
288   }
289 };
290
291 class RegionChanges {
292   template <typename CHECKER>
293   static ProgramStateRef 
294   _checkRegionChanges(void *checker,
295                       ProgramStateRef state,
296                       const InvalidatedSymbols *invalidated,
297                       ArrayRef<const MemRegion *> Explicits,
298                       ArrayRef<const MemRegion *> Regions,
299                       const CallEvent *Call) {
300     return ((const CHECKER *)checker)->checkRegionChanges(state, invalidated,
301                                                       Explicits, Regions, Call);
302   }
303   template <typename CHECKER>
304   static bool _wantsRegionChangeUpdate(void *checker,
305                                        ProgramStateRef state) {
306     return ((const CHECKER *)checker)->wantsRegionChangeUpdate(state);
307   }
308
309 public:
310   template <typename CHECKER>
311   static void _register(CHECKER *checker, CheckerManager &mgr) {
312     mgr._registerForRegionChanges(
313           CheckerManager::CheckRegionChangesFunc(checker,
314                                                  _checkRegionChanges<CHECKER>),
315           CheckerManager::WantsRegionChangeUpdateFunc(checker,
316                                             _wantsRegionChangeUpdate<CHECKER>));
317   }
318 };
319
320 class PointerEscape {
321   template <typename CHECKER>
322   static ProgramStateRef
323   _checkPointerEscape(void *Checker,
324                      ProgramStateRef State,
325                      const InvalidatedSymbols &Escaped,
326                      const CallEvent *Call,
327                      PointerEscapeKind Kind,
328                      RegionAndSymbolInvalidationTraits *ETraits) {
329
330     if (!ETraits)
331       return ((const CHECKER *)Checker)->checkPointerEscape(State,
332                                                             Escaped,
333                                                             Call,
334                                                             Kind);
335
336     InvalidatedSymbols RegularEscape;
337     for (InvalidatedSymbols::const_iterator I = Escaped.begin(), 
338                                             E = Escaped.end(); I != E; ++I)
339       if (!ETraits->hasTrait(*I,
340               RegionAndSymbolInvalidationTraits::TK_PreserveContents) &&
341           !ETraits->hasTrait(*I,
342               RegionAndSymbolInvalidationTraits::TK_SuppressEscape))
343         RegularEscape.insert(*I);
344
345     if (RegularEscape.empty())
346       return State;
347
348     return ((const CHECKER *)Checker)->checkPointerEscape(State,
349                                                           RegularEscape,
350                                                           Call,
351                                                           Kind);
352   }
353
354 public:
355   template <typename CHECKER>
356   static void _register(CHECKER *checker, CheckerManager &mgr) {
357     mgr._registerForPointerEscape(
358           CheckerManager::CheckPointerEscapeFunc(checker,
359                                                 _checkPointerEscape<CHECKER>));
360   }
361 };
362
363 class ConstPointerEscape {
364   template <typename CHECKER>
365   static ProgramStateRef
366   _checkConstPointerEscape(void *Checker,
367                       ProgramStateRef State,
368                       const InvalidatedSymbols &Escaped,
369                       const CallEvent *Call,
370                       PointerEscapeKind Kind,
371                       RegionAndSymbolInvalidationTraits *ETraits) {
372
373     if (!ETraits)
374       return State;
375
376     InvalidatedSymbols ConstEscape;
377     for (InvalidatedSymbols::const_iterator I = Escaped.begin(), 
378                                             E = Escaped.end(); I != E; ++I)
379       if (ETraits->hasTrait(*I,
380               RegionAndSymbolInvalidationTraits::TK_PreserveContents) &&
381           !ETraits->hasTrait(*I,
382               RegionAndSymbolInvalidationTraits::TK_SuppressEscape))
383         ConstEscape.insert(*I);
384
385     if (ConstEscape.empty())
386       return State;
387
388     return ((const CHECKER *)Checker)->checkConstPointerEscape(State,
389                                                                ConstEscape,
390                                                                Call,
391                                                                Kind);
392   }
393
394 public:
395   template <typename CHECKER>
396   static void _register(CHECKER *checker, CheckerManager &mgr) {
397     mgr._registerForPointerEscape(
398       CheckerManager::CheckPointerEscapeFunc(checker,
399                                             _checkConstPointerEscape<CHECKER>));
400   }
401 };
402
403   
404 template <typename EVENT>
405 class Event {
406   template <typename CHECKER>
407   static void _checkEvent(void *checker, const void *event) {
408     ((const CHECKER *)checker)->checkEvent(*(const EVENT *)event);
409   }
410 public:
411   template <typename CHECKER>
412   static void _register(CHECKER *checker, CheckerManager &mgr) {
413     mgr._registerListenerForEvent<EVENT>(
414                  CheckerManager::CheckEventFunc(checker, _checkEvent<CHECKER>));
415   }
416 };
417
418 } // end check namespace
419
420 namespace eval {
421
422 class Assume {
423   template <typename CHECKER>
424   static ProgramStateRef _evalAssume(void *checker,
425                                          ProgramStateRef state,
426                                          const SVal &cond,
427                                          bool assumption) {
428     return ((const CHECKER *)checker)->evalAssume(state, cond, assumption);
429   }
430
431 public:
432   template <typename CHECKER>
433   static void _register(CHECKER *checker, CheckerManager &mgr) {
434     mgr._registerForEvalAssume(
435                  CheckerManager::EvalAssumeFunc(checker, _evalAssume<CHECKER>));
436   }
437 };
438
439 class Call {
440   template <typename CHECKER>
441   static bool _evalCall(void *checker, const CallExpr *CE, CheckerContext &C) {
442     return ((const CHECKER *)checker)->evalCall(CE, C);
443   }
444
445 public:
446   template <typename CHECKER>
447   static void _register(CHECKER *checker, CheckerManager &mgr) {
448     mgr._registerForEvalCall(
449                      CheckerManager::EvalCallFunc(checker, _evalCall<CHECKER>));
450   }
451 };
452
453 } // end eval namespace
454
455 class CheckerBase : public ProgramPointTag {
456 public:
457   StringRef getTagDescription() const;
458
459   /// See CheckerManager::runCheckersForPrintState.
460   virtual void printState(raw_ostream &Out, ProgramStateRef State,
461                           const char *NL, const char *Sep) const { }
462 };
463   
464 template <typename CHECK1, typename CHECK2=check::_VoidCheck,
465           typename CHECK3=check::_VoidCheck, typename CHECK4=check::_VoidCheck,
466           typename CHECK5=check::_VoidCheck, typename CHECK6=check::_VoidCheck,
467           typename CHECK7=check::_VoidCheck, typename CHECK8=check::_VoidCheck,
468           typename CHECK9=check::_VoidCheck, typename CHECK10=check::_VoidCheck,
469           typename CHECK11=check::_VoidCheck,typename CHECK12=check::_VoidCheck,
470           typename CHECK13=check::_VoidCheck,typename CHECK14=check::_VoidCheck,
471           typename CHECK15=check::_VoidCheck,typename CHECK16=check::_VoidCheck,
472           typename CHECK17=check::_VoidCheck,typename CHECK18=check::_VoidCheck,
473           typename CHECK19=check::_VoidCheck,typename CHECK20=check::_VoidCheck,
474           typename CHECK21=check::_VoidCheck,typename CHECK22=check::_VoidCheck,
475           typename CHECK23=check::_VoidCheck,typename CHECK24=check::_VoidCheck>
476 class Checker;
477
478 template <>
479 class Checker<check::_VoidCheck>
480   : public CheckerBase 
481 {
482   virtual void anchor();
483 public:
484   static void _register(void *checker, CheckerManager &mgr) { }
485 };
486
487 template <typename CHECK1, typename CHECK2, typename CHECK3, typename CHECK4,
488           typename CHECK5, typename CHECK6, typename CHECK7, typename CHECK8,
489           typename CHECK9, typename CHECK10,typename CHECK11,typename CHECK12,
490           typename CHECK13,typename CHECK14,typename CHECK15,typename CHECK16,
491           typename CHECK17,typename CHECK18,typename CHECK19,typename CHECK20,
492           typename CHECK21,typename CHECK22,typename CHECK23,typename CHECK24>
493 class Checker
494     : public CHECK1,
495       public Checker<CHECK2, CHECK3, CHECK4, CHECK5, CHECK6, CHECK7,
496                      CHECK8, CHECK9, CHECK10,CHECK11,CHECK12,CHECK13,
497                      CHECK14,CHECK15,CHECK16,CHECK17,CHECK18,CHECK19,
498                      CHECK20,CHECK21,CHECK22,CHECK23,CHECK24> {
499 public:
500   template <typename CHECKER>
501   static void _register(CHECKER *checker, CheckerManager &mgr) {
502     CHECK1::_register(checker, mgr);
503     Checker<CHECK2, CHECK3, CHECK4, CHECK5, CHECK6, CHECK7,
504             CHECK8, CHECK9, CHECK10,CHECK11,CHECK12,CHECK13,
505             CHECK14,CHECK15,CHECK16,CHECK17,CHECK18,CHECK19,
506             CHECK20,CHECK21,CHECK22,CHECK23,CHECK24>::_register(checker, mgr);
507   }
508 };
509
510 template <typename EVENT>
511 class EventDispatcher {
512   CheckerManager *Mgr;
513 public:
514   EventDispatcher() : Mgr(0) { }
515
516   template <typename CHECKER>
517   static void _register(CHECKER *checker, CheckerManager &mgr) {
518     mgr._registerDispatcherForEvent<EVENT>();
519     static_cast<EventDispatcher<EVENT> *>(checker)->Mgr = &mgr;
520   }
521
522   void dispatchEvent(const EVENT &event) const {
523     Mgr->_dispatchEvent(event);
524   }
525 };
526
527 /// \brief We dereferenced a location that may be null.
528 struct ImplicitNullDerefEvent {
529   SVal Location;
530   bool IsLoad;
531   ExplodedNode *SinkNode;
532   BugReporter *BR;
533 };
534
535 /// \brief A helper class which wraps a boolean value set to false by default.
536 ///
537 /// This class should behave exactly like 'bool' except that it doesn't need to
538 /// be explicitly initialized.
539 struct DefaultBool {
540   bool val;
541   DefaultBool() : val(false) {}
542   /*implicit*/ operator bool&() { return val; }
543   /*implicit*/ operator const bool&() const { return val; }
544   DefaultBool &operator=(bool b) { val = b; return *this; }
545 };
546
547 } // end ento namespace
548
549 } // end clang namespace
550
551 #endif