• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 {
_register_VoidCheck29   static void _register(void *checker, CheckerManager &mgr) { }
30 };
31 
32 template <typename DECL>
33 class ASTDecl {
34   template <typename CHECKER>
_checkDecl(void * checker,const Decl * D,AnalysisManager & mgr,BugReporter & BR)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 
_handlesDecl(const Decl * D)40   static bool _handlesDecl(const Decl *D) {
41     return isa<DECL>(D);
42   }
43 public:
44   template <typename CHECKER>
_register(CHECKER * checker,CheckerManager & mgr)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>
_checkBody(void * checker,const Decl * D,AnalysisManager & mgr,BugReporter & BR)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>
_register(CHECKER * checker,CheckerManager & mgr)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>
_checkEndOfTranslationUnit(void * checker,const TranslationUnitDecl * TU,AnalysisManager & mgr,BugReporter & BR)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>
_register(CHECKER * checker,CheckerManager & mgr)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>
_checkStmt(void * checker,const Stmt * S,CheckerContext & C)88   static void _checkStmt(void *checker, const Stmt *S, CheckerContext &C) {
89     ((const CHECKER *)checker)->checkPreStmt(cast<STMT>(S), C);
90   }
91 
_handlesStmt(const Stmt * S)92   static bool _handlesStmt(const Stmt *S) {
93     return isa<STMT>(S);
94   }
95 public:
96   template <typename CHECKER>
_register(CHECKER * checker,CheckerManager & mgr)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>
_checkStmt(void * checker,const Stmt * S,CheckerContext & C)107   static void _checkStmt(void *checker, const Stmt *S, CheckerContext &C) {
108     ((const CHECKER *)checker)->checkPostStmt(cast<STMT>(S), C);
109   }
110 
_handlesStmt(const Stmt * S)111   static bool _handlesStmt(const Stmt *S) {
112     return isa<STMT>(S);
113   }
114 public:
115   template <typename CHECKER>
_register(CHECKER * checker,CheckerManager & mgr)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>
_checkObjCMessage(void * checker,const ObjCMethodCall & msg,CheckerContext & C)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>
_register(CHECKER * checker,CheckerManager & mgr)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>
_checkObjCMessage(void * checker,const ObjCMethodCall & msg,CheckerContext & C)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>
_register(CHECKER * checker,CheckerManager & mgr)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>
_checkCall(void * checker,const CallEvent & msg,CheckerContext & C)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>
_register(CHECKER * checker,CheckerManager & mgr)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>
_checkCall(void * checker,const CallEvent & msg,CheckerContext & C)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>
_register(CHECKER * checker,CheckerManager & mgr)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>
_checkLocation(void * checker,const SVal & location,bool isLoad,const Stmt * S,CheckerContext & C)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>
_register(CHECKER * checker,CheckerManager & mgr)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>
_checkBind(void * checker,const SVal & location,const SVal & val,const Stmt * S,CheckerContext & C)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>
_register(CHECKER * checker,CheckerManager & mgr)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>
_checkEndAnalysis(void * checker,ExplodedGraph & G,BugReporter & BR,ExprEngine & Eng)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>
_register(CHECKER * checker,CheckerManager & mgr)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>
_checkEndFunction(void * checker,CheckerContext & C)232   static void _checkEndFunction(void *checker,
233                                 CheckerContext &C) {
234     ((const CHECKER *)checker)->checkEndFunction(C);
235   }
236 
237 public:
238   template <typename CHECKER>
_register(CHECKER * checker,CheckerManager & mgr)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>
_checkBranchCondition(void * checker,const Stmt * Condition,CheckerContext & C)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>
_register(CHECKER * checker,CheckerManager & mgr)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>
_checkLiveSymbols(void * checker,ProgramStateRef state,SymbolReaper & SR)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>
_register(CHECKER * checker,CheckerManager & mgr)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>
_checkDeadSymbols(void * checker,SymbolReaper & SR,CheckerContext & C)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>
_register(CHECKER * checker,CheckerManager & mgr)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
_checkRegionChanges(void * checker,ProgramStateRef state,const InvalidatedSymbols * invalidated,ArrayRef<const MemRegion * > Explicits,ArrayRef<const MemRegion * > Regions,const CallEvent * Call)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>
_wantsRegionChangeUpdate(void * checker,ProgramStateRef state)304   static bool _wantsRegionChangeUpdate(void *checker,
305                                        ProgramStateRef state) {
306     return ((const CHECKER *)checker)->wantsRegionChangeUpdate(state);
307   }
308 
309 public:
310   template <typename CHECKER>
_register(CHECKER * checker,CheckerManager & mgr)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
_checkPointerEscape(void * checker,ProgramStateRef State,const InvalidatedSymbols & Escaped,const CallEvent * Call,PointerEscapeKind Kind,bool IsConst)323   _checkPointerEscape(void *checker,
324                      ProgramStateRef State,
325                      const InvalidatedSymbols &Escaped,
326                      const CallEvent *Call,
327                      PointerEscapeKind Kind,
328                     bool IsConst) {
329     if (!IsConst)
330       return ((const CHECKER *)checker)->checkPointerEscape(State,
331                                                             Escaped,
332                                                             Call,
333                                                             Kind);
334     return State;
335   }
336 
337 public:
338   template <typename CHECKER>
_register(CHECKER * checker,CheckerManager & mgr)339   static void _register(CHECKER *checker, CheckerManager &mgr) {
340     mgr._registerForPointerEscape(
341           CheckerManager::CheckPointerEscapeFunc(checker,
342                                                 _checkPointerEscape<CHECKER>));
343   }
344 };
345 
346 class ConstPointerEscape {
347   template <typename CHECKER>
348   static ProgramStateRef
_checkConstPointerEscape(void * checker,ProgramStateRef State,const InvalidatedSymbols & Escaped,const CallEvent * Call,PointerEscapeKind Kind,bool IsConst)349   _checkConstPointerEscape(void *checker,
350                       ProgramStateRef State,
351                       const InvalidatedSymbols &Escaped,
352                       const CallEvent *Call,
353                       PointerEscapeKind Kind,
354                       bool IsConst) {
355     if (IsConst)
356       return ((const CHECKER *)checker)->checkConstPointerEscape(State,
357                                                                  Escaped,
358                                                                  Call,
359                                                                  Kind);
360     return State;
361   }
362 
363 public:
364   template <typename CHECKER>
_register(CHECKER * checker,CheckerManager & mgr)365   static void _register(CHECKER *checker, CheckerManager &mgr) {
366     mgr._registerForPointerEscape(
367       CheckerManager::CheckPointerEscapeFunc(checker,
368                                             _checkConstPointerEscape<CHECKER>));
369   }
370 };
371 
372 
373 template <typename EVENT>
374 class Event {
375   template <typename CHECKER>
_checkEvent(void * checker,const void * event)376   static void _checkEvent(void *checker, const void *event) {
377     ((const CHECKER *)checker)->checkEvent(*(const EVENT *)event);
378   }
379 public:
380   template <typename CHECKER>
_register(CHECKER * checker,CheckerManager & mgr)381   static void _register(CHECKER *checker, CheckerManager &mgr) {
382     mgr._registerListenerForEvent<EVENT>(
383                  CheckerManager::CheckEventFunc(checker, _checkEvent<CHECKER>));
384   }
385 };
386 
387 } // end check namespace
388 
389 namespace eval {
390 
391 class Assume {
392   template <typename CHECKER>
_evalAssume(void * checker,ProgramStateRef state,const SVal & cond,bool assumption)393   static ProgramStateRef _evalAssume(void *checker,
394                                          ProgramStateRef state,
395                                          const SVal &cond,
396                                          bool assumption) {
397     return ((const CHECKER *)checker)->evalAssume(state, cond, assumption);
398   }
399 
400 public:
401   template <typename CHECKER>
_register(CHECKER * checker,CheckerManager & mgr)402   static void _register(CHECKER *checker, CheckerManager &mgr) {
403     mgr._registerForEvalAssume(
404                  CheckerManager::EvalAssumeFunc(checker, _evalAssume<CHECKER>));
405   }
406 };
407 
408 class Call {
409   template <typename CHECKER>
_evalCall(void * checker,const CallExpr * CE,CheckerContext & C)410   static bool _evalCall(void *checker, const CallExpr *CE, CheckerContext &C) {
411     return ((const CHECKER *)checker)->evalCall(CE, C);
412   }
413 
414 public:
415   template <typename CHECKER>
_register(CHECKER * checker,CheckerManager & mgr)416   static void _register(CHECKER *checker, CheckerManager &mgr) {
417     mgr._registerForEvalCall(
418                      CheckerManager::EvalCallFunc(checker, _evalCall<CHECKER>));
419   }
420 };
421 
422 } // end eval namespace
423 
424 class CheckerBase : public ProgramPointTag {
425 public:
426   StringRef getTagDescription() const;
427 
428   /// See CheckerManager::runCheckersForPrintState.
printState(raw_ostream & Out,ProgramStateRef State,const char * NL,const char * Sep)429   virtual void printState(raw_ostream &Out, ProgramStateRef State,
430                           const char *NL, const char *Sep) const { }
431 };
432 
433 template <typename CHECK1, typename CHECK2=check::_VoidCheck,
434           typename CHECK3=check::_VoidCheck, typename CHECK4=check::_VoidCheck,
435           typename CHECK5=check::_VoidCheck, typename CHECK6=check::_VoidCheck,
436           typename CHECK7=check::_VoidCheck, typename CHECK8=check::_VoidCheck,
437           typename CHECK9=check::_VoidCheck, typename CHECK10=check::_VoidCheck,
438           typename CHECK11=check::_VoidCheck,typename CHECK12=check::_VoidCheck,
439           typename CHECK13=check::_VoidCheck,typename CHECK14=check::_VoidCheck,
440           typename CHECK15=check::_VoidCheck,typename CHECK16=check::_VoidCheck,
441           typename CHECK17=check::_VoidCheck,typename CHECK18=check::_VoidCheck,
442           typename CHECK19=check::_VoidCheck,typename CHECK20=check::_VoidCheck,
443           typename CHECK21=check::_VoidCheck,typename CHECK22=check::_VoidCheck,
444           typename CHECK23=check::_VoidCheck,typename CHECK24=check::_VoidCheck>
445 class Checker;
446 
447 template <>
448 class Checker<check::_VoidCheck>
449   : public CheckerBase
450 {
451   virtual void anchor();
452 public:
_register(void * checker,CheckerManager & mgr)453   static void _register(void *checker, CheckerManager &mgr) { }
454 };
455 
456 template <typename CHECK1, typename CHECK2, typename CHECK3, typename CHECK4,
457           typename CHECK5, typename CHECK6, typename CHECK7, typename CHECK8,
458           typename CHECK9, typename CHECK10,typename CHECK11,typename CHECK12,
459           typename CHECK13,typename CHECK14,typename CHECK15,typename CHECK16,
460           typename CHECK17,typename CHECK18,typename CHECK19,typename CHECK20,
461           typename CHECK21,typename CHECK22,typename CHECK23,typename CHECK24>
462 class Checker
463     : public CHECK1,
464       public Checker<CHECK2, CHECK3, CHECK4, CHECK5, CHECK6, CHECK7,
465                      CHECK8, CHECK9, CHECK10,CHECK11,CHECK12,CHECK13,
466                      CHECK14,CHECK15,CHECK16,CHECK17,CHECK18,CHECK19,
467                      CHECK20,CHECK21,CHECK22,CHECK23,CHECK24> {
468 public:
469   template <typename CHECKER>
_register(CHECKER * checker,CheckerManager & mgr)470   static void _register(CHECKER *checker, CheckerManager &mgr) {
471     CHECK1::_register(checker, mgr);
472     Checker<CHECK2, CHECK3, CHECK4, CHECK5, CHECK6, CHECK7,
473             CHECK8, CHECK9, CHECK10,CHECK11,CHECK12,CHECK13,
474             CHECK14,CHECK15,CHECK16,CHECK17,CHECK18,CHECK19,
475             CHECK20,CHECK21,CHECK22,CHECK23,CHECK24>::_register(checker, mgr);
476   }
477 };
478 
479 template <typename EVENT>
480 class EventDispatcher {
481   CheckerManager *Mgr;
482 public:
EventDispatcher()483   EventDispatcher() : Mgr(0) { }
484 
485   template <typename CHECKER>
_register(CHECKER * checker,CheckerManager & mgr)486   static void _register(CHECKER *checker, CheckerManager &mgr) {
487     mgr._registerDispatcherForEvent<EVENT>();
488     static_cast<EventDispatcher<EVENT> *>(checker)->Mgr = &mgr;
489   }
490 
dispatchEvent(const EVENT & event)491   void dispatchEvent(const EVENT &event) const {
492     Mgr->_dispatchEvent(event);
493   }
494 };
495 
496 /// \brief We dereferenced a location that may be null.
497 struct ImplicitNullDerefEvent {
498   SVal Location;
499   bool IsLoad;
500   ExplodedNode *SinkNode;
501   BugReporter *BR;
502 };
503 
504 /// \brief A helper class which wraps a boolean value set to false by default.
505 ///
506 /// This class should behave exactly like 'bool' except that it doesn't need to
507 /// be explicitly initialized.
508 struct DefaultBool {
509   bool val;
DefaultBoolDefaultBool510   DefaultBool() : val(false) {}
511   /*implicit*/ operator bool&() { return val; }
512   /*implicit*/ operator const bool&() const { return val; }
513   DefaultBool &operator=(bool b) { val = b; return *this; }
514 };
515 
516 } // end ento namespace
517 
518 } // end clang namespace
519 
520 #endif
521