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_STATICANALYZER_CORE_CHECKER_H
15 #define LLVM_CLANG_STATICANALYZER_CORE_CHECKER_H
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 template <typename DECL>
29 class ASTDecl {
30   template <typename CHECKER>
_checkDecl(void * checker,const Decl * D,AnalysisManager & mgr,BugReporter & BR)31   static void _checkDecl(void *checker, const Decl *D, AnalysisManager& mgr,
32                          BugReporter &BR) {
33     ((const CHECKER *)checker)->checkASTDecl(cast<DECL>(D), mgr, BR);
34   }
35 
_handlesDecl(const Decl * D)36   static bool _handlesDecl(const Decl *D) {
37     return isa<DECL>(D);
38   }
39 public:
40   template <typename CHECKER>
_register(CHECKER * checker,CheckerManager & mgr)41   static void _register(CHECKER *checker, CheckerManager &mgr) {
42     mgr._registerForDecl(CheckerManager::CheckDeclFunc(checker,
43                                                        _checkDecl<CHECKER>),
44                          _handlesDecl);
45   }
46 };
47 
48 class ASTCodeBody {
49   template <typename CHECKER>
_checkBody(void * checker,const Decl * D,AnalysisManager & mgr,BugReporter & BR)50   static void _checkBody(void *checker, const Decl *D, AnalysisManager& mgr,
51                          BugReporter &BR) {
52     ((const CHECKER *)checker)->checkASTCodeBody(D, mgr, BR);
53   }
54 
55 public:
56   template <typename CHECKER>
_register(CHECKER * checker,CheckerManager & mgr)57   static void _register(CHECKER *checker, CheckerManager &mgr) {
58     mgr._registerForBody(CheckerManager::CheckDeclFunc(checker,
59                                                        _checkBody<CHECKER>));
60   }
61 };
62 
63 class EndOfTranslationUnit {
64   template <typename CHECKER>
_checkEndOfTranslationUnit(void * checker,const TranslationUnitDecl * TU,AnalysisManager & mgr,BugReporter & BR)65   static void _checkEndOfTranslationUnit(void *checker,
66                                          const TranslationUnitDecl *TU,
67                                          AnalysisManager& mgr,
68                                          BugReporter &BR) {
69     ((const CHECKER *)checker)->checkEndOfTranslationUnit(TU, mgr, BR);
70   }
71 
72 public:
73   template <typename CHECKER>
_register(CHECKER * checker,CheckerManager & mgr)74   static void _register(CHECKER *checker, CheckerManager &mgr){
75     mgr._registerForEndOfTranslationUnit(
76                               CheckerManager::CheckEndOfTranslationUnit(checker,
77                                           _checkEndOfTranslationUnit<CHECKER>));
78   }
79 };
80 
81 template <typename STMT>
82 class PreStmt {
83   template <typename CHECKER>
_checkStmt(void * checker,const Stmt * S,CheckerContext & C)84   static void _checkStmt(void *checker, const Stmt *S, CheckerContext &C) {
85     ((const CHECKER *)checker)->checkPreStmt(cast<STMT>(S), C);
86   }
87 
_handlesStmt(const Stmt * S)88   static bool _handlesStmt(const Stmt *S) {
89     return isa<STMT>(S);
90   }
91 public:
92   template <typename CHECKER>
_register(CHECKER * checker,CheckerManager & mgr)93   static void _register(CHECKER *checker, CheckerManager &mgr) {
94     mgr._registerForPreStmt(CheckerManager::CheckStmtFunc(checker,
95                                                           _checkStmt<CHECKER>),
96                             _handlesStmt);
97   }
98 };
99 
100 template <typename STMT>
101 class PostStmt {
102   template <typename CHECKER>
_checkStmt(void * checker,const Stmt * S,CheckerContext & C)103   static void _checkStmt(void *checker, const Stmt *S, CheckerContext &C) {
104     ((const CHECKER *)checker)->checkPostStmt(cast<STMT>(S), C);
105   }
106 
_handlesStmt(const Stmt * S)107   static bool _handlesStmt(const Stmt *S) {
108     return isa<STMT>(S);
109   }
110 public:
111   template <typename CHECKER>
_register(CHECKER * checker,CheckerManager & mgr)112   static void _register(CHECKER *checker, CheckerManager &mgr) {
113     mgr._registerForPostStmt(CheckerManager::CheckStmtFunc(checker,
114                                                            _checkStmt<CHECKER>),
115                              _handlesStmt);
116   }
117 };
118 
119 class PreObjCMessage {
120   template <typename CHECKER>
_checkObjCMessage(void * checker,const ObjCMethodCall & msg,CheckerContext & C)121   static void _checkObjCMessage(void *checker, const ObjCMethodCall &msg,
122                                 CheckerContext &C) {
123     ((const CHECKER *)checker)->checkPreObjCMessage(msg, C);
124   }
125 
126 public:
127   template <typename CHECKER>
_register(CHECKER * checker,CheckerManager & mgr)128   static void _register(CHECKER *checker, CheckerManager &mgr) {
129     mgr._registerForPreObjCMessage(
130      CheckerManager::CheckObjCMessageFunc(checker, _checkObjCMessage<CHECKER>));
131   }
132 };
133 
134 class PostObjCMessage {
135   template <typename CHECKER>
_checkObjCMessage(void * checker,const ObjCMethodCall & msg,CheckerContext & C)136   static void _checkObjCMessage(void *checker, const ObjCMethodCall &msg,
137                                 CheckerContext &C) {
138     ((const CHECKER *)checker)->checkPostObjCMessage(msg, C);
139   }
140 
141 public:
142   template <typename CHECKER>
_register(CHECKER * checker,CheckerManager & mgr)143   static void _register(CHECKER *checker, CheckerManager &mgr) {
144     mgr._registerForPostObjCMessage(
145      CheckerManager::CheckObjCMessageFunc(checker, _checkObjCMessage<CHECKER>));
146   }
147 };
148 
149 class PreCall {
150   template <typename CHECKER>
_checkCall(void * checker,const CallEvent & msg,CheckerContext & C)151   static void _checkCall(void *checker, const CallEvent &msg,
152                          CheckerContext &C) {
153     ((const CHECKER *)checker)->checkPreCall(msg, C);
154   }
155 
156 public:
157   template <typename CHECKER>
_register(CHECKER * checker,CheckerManager & mgr)158   static void _register(CHECKER *checker, CheckerManager &mgr) {
159     mgr._registerForPreCall(
160      CheckerManager::CheckCallFunc(checker, _checkCall<CHECKER>));
161   }
162 };
163 
164 class PostCall {
165   template <typename CHECKER>
_checkCall(void * checker,const CallEvent & msg,CheckerContext & C)166   static void _checkCall(void *checker, const CallEvent &msg,
167                          CheckerContext &C) {
168     ((const CHECKER *)checker)->checkPostCall(msg, C);
169   }
170 
171 public:
172   template <typename CHECKER>
_register(CHECKER * checker,CheckerManager & mgr)173   static void _register(CHECKER *checker, CheckerManager &mgr) {
174     mgr._registerForPostCall(
175      CheckerManager::CheckCallFunc(checker, _checkCall<CHECKER>));
176   }
177 };
178 
179 class Location {
180   template <typename CHECKER>
_checkLocation(void * checker,const SVal & location,bool isLoad,const Stmt * S,CheckerContext & C)181   static void _checkLocation(void *checker,
182                              const SVal &location, bool isLoad, const Stmt *S,
183                              CheckerContext &C) {
184     ((const CHECKER *)checker)->checkLocation(location, isLoad, S, C);
185   }
186 
187 public:
188   template <typename CHECKER>
_register(CHECKER * checker,CheckerManager & mgr)189   static void _register(CHECKER *checker, CheckerManager &mgr) {
190     mgr._registerForLocation(
191            CheckerManager::CheckLocationFunc(checker, _checkLocation<CHECKER>));
192   }
193 };
194 
195 class Bind {
196   template <typename CHECKER>
_checkBind(void * checker,const SVal & location,const SVal & val,const Stmt * S,CheckerContext & C)197   static void _checkBind(void *checker,
198                          const SVal &location, const SVal &val, const Stmt *S,
199                          CheckerContext &C) {
200     ((const CHECKER *)checker)->checkBind(location, val, S, C);
201   }
202 
203 public:
204   template <typename CHECKER>
_register(CHECKER * checker,CheckerManager & mgr)205   static void _register(CHECKER *checker, CheckerManager &mgr) {
206     mgr._registerForBind(
207            CheckerManager::CheckBindFunc(checker, _checkBind<CHECKER>));
208   }
209 };
210 
211 class EndAnalysis {
212   template <typename CHECKER>
_checkEndAnalysis(void * checker,ExplodedGraph & G,BugReporter & BR,ExprEngine & Eng)213   static void _checkEndAnalysis(void *checker, ExplodedGraph &G,
214                                 BugReporter &BR, ExprEngine &Eng) {
215     ((const CHECKER *)checker)->checkEndAnalysis(G, BR, Eng);
216   }
217 
218 public:
219   template <typename CHECKER>
_register(CHECKER * checker,CheckerManager & mgr)220   static void _register(CHECKER *checker, CheckerManager &mgr) {
221     mgr._registerForEndAnalysis(
222      CheckerManager::CheckEndAnalysisFunc(checker, _checkEndAnalysis<CHECKER>));
223   }
224 };
225 
226 class EndFunction {
227   template <typename CHECKER>
_checkEndFunction(void * checker,CheckerContext & C)228   static void _checkEndFunction(void *checker,
229                                 CheckerContext &C) {
230     ((const CHECKER *)checker)->checkEndFunction(C);
231   }
232 
233 public:
234   template <typename CHECKER>
_register(CHECKER * checker,CheckerManager & mgr)235   static void _register(CHECKER *checker, CheckerManager &mgr) {
236     mgr._registerForEndFunction(
237      CheckerManager::CheckEndFunctionFunc(checker, _checkEndFunction<CHECKER>));
238   }
239 };
240 
241 class BranchCondition {
242   template <typename CHECKER>
_checkBranchCondition(void * checker,const Stmt * Condition,CheckerContext & C)243   static void _checkBranchCondition(void *checker, const Stmt *Condition,
244                                     CheckerContext & C) {
245     ((const CHECKER *)checker)->checkBranchCondition(Condition, C);
246   }
247 
248 public:
249   template <typename CHECKER>
_register(CHECKER * checker,CheckerManager & mgr)250   static void _register(CHECKER *checker, CheckerManager &mgr) {
251     mgr._registerForBranchCondition(
252       CheckerManager::CheckBranchConditionFunc(checker,
253                                                _checkBranchCondition<CHECKER>));
254   }
255 };
256 
257 class LiveSymbols {
258   template <typename CHECKER>
_checkLiveSymbols(void * checker,ProgramStateRef state,SymbolReaper & SR)259   static void _checkLiveSymbols(void *checker, ProgramStateRef state,
260                                 SymbolReaper &SR) {
261     ((const CHECKER *)checker)->checkLiveSymbols(state, SR);
262   }
263 
264 public:
265   template <typename CHECKER>
_register(CHECKER * checker,CheckerManager & mgr)266   static void _register(CHECKER *checker, CheckerManager &mgr) {
267     mgr._registerForLiveSymbols(
268      CheckerManager::CheckLiveSymbolsFunc(checker, _checkLiveSymbols<CHECKER>));
269   }
270 };
271 
272 class DeadSymbols {
273   template <typename CHECKER>
_checkDeadSymbols(void * checker,SymbolReaper & SR,CheckerContext & C)274   static void _checkDeadSymbols(void *checker,
275                                 SymbolReaper &SR, CheckerContext &C) {
276     ((const CHECKER *)checker)->checkDeadSymbols(SR, C);
277   }
278 
279 public:
280   template <typename CHECKER>
_register(CHECKER * checker,CheckerManager & mgr)281   static void _register(CHECKER *checker, CheckerManager &mgr) {
282     mgr._registerForDeadSymbols(
283      CheckerManager::CheckDeadSymbolsFunc(checker, _checkDeadSymbols<CHECKER>));
284   }
285 };
286 
287 class RegionChanges {
288   template <typename CHECKER>
289   static ProgramStateRef
_checkRegionChanges(void * checker,ProgramStateRef state,const InvalidatedSymbols * invalidated,ArrayRef<const MemRegion * > Explicits,ArrayRef<const MemRegion * > Regions,const CallEvent * Call)290   _checkRegionChanges(void *checker,
291                       ProgramStateRef state,
292                       const InvalidatedSymbols *invalidated,
293                       ArrayRef<const MemRegion *> Explicits,
294                       ArrayRef<const MemRegion *> Regions,
295                       const CallEvent *Call) {
296     return ((const CHECKER *)checker)->checkRegionChanges(state, invalidated,
297                                                       Explicits, Regions, Call);
298   }
299   template <typename CHECKER>
_wantsRegionChangeUpdate(void * checker,ProgramStateRef state)300   static bool _wantsRegionChangeUpdate(void *checker,
301                                        ProgramStateRef state) {
302     return ((const CHECKER *)checker)->wantsRegionChangeUpdate(state);
303   }
304 
305 public:
306   template <typename CHECKER>
_register(CHECKER * checker,CheckerManager & mgr)307   static void _register(CHECKER *checker, CheckerManager &mgr) {
308     mgr._registerForRegionChanges(
309           CheckerManager::CheckRegionChangesFunc(checker,
310                                                  _checkRegionChanges<CHECKER>),
311           CheckerManager::WantsRegionChangeUpdateFunc(checker,
312                                             _wantsRegionChangeUpdate<CHECKER>));
313   }
314 };
315 
316 class PointerEscape {
317   template <typename CHECKER>
318   static ProgramStateRef
_checkPointerEscape(void * Checker,ProgramStateRef State,const InvalidatedSymbols & Escaped,const CallEvent * Call,PointerEscapeKind Kind,RegionAndSymbolInvalidationTraits * ETraits)319   _checkPointerEscape(void *Checker,
320                      ProgramStateRef State,
321                      const InvalidatedSymbols &Escaped,
322                      const CallEvent *Call,
323                      PointerEscapeKind Kind,
324                      RegionAndSymbolInvalidationTraits *ETraits) {
325 
326     if (!ETraits)
327       return ((const CHECKER *)Checker)->checkPointerEscape(State,
328                                                             Escaped,
329                                                             Call,
330                                                             Kind);
331 
332     InvalidatedSymbols RegularEscape;
333     for (InvalidatedSymbols::const_iterator I = Escaped.begin(),
334                                             E = Escaped.end(); I != E; ++I)
335       if (!ETraits->hasTrait(*I,
336               RegionAndSymbolInvalidationTraits::TK_PreserveContents) &&
337           !ETraits->hasTrait(*I,
338               RegionAndSymbolInvalidationTraits::TK_SuppressEscape))
339         RegularEscape.insert(*I);
340 
341     if (RegularEscape.empty())
342       return State;
343 
344     return ((const CHECKER *)Checker)->checkPointerEscape(State,
345                                                           RegularEscape,
346                                                           Call,
347                                                           Kind);
348   }
349 
350 public:
351   template <typename CHECKER>
_register(CHECKER * checker,CheckerManager & mgr)352   static void _register(CHECKER *checker, CheckerManager &mgr) {
353     mgr._registerForPointerEscape(
354           CheckerManager::CheckPointerEscapeFunc(checker,
355                                                 _checkPointerEscape<CHECKER>));
356   }
357 };
358 
359 class ConstPointerEscape {
360   template <typename CHECKER>
361   static ProgramStateRef
_checkConstPointerEscape(void * Checker,ProgramStateRef State,const InvalidatedSymbols & Escaped,const CallEvent * Call,PointerEscapeKind Kind,RegionAndSymbolInvalidationTraits * ETraits)362   _checkConstPointerEscape(void *Checker,
363                       ProgramStateRef State,
364                       const InvalidatedSymbols &Escaped,
365                       const CallEvent *Call,
366                       PointerEscapeKind Kind,
367                       RegionAndSymbolInvalidationTraits *ETraits) {
368 
369     if (!ETraits)
370       return State;
371 
372     InvalidatedSymbols ConstEscape;
373     for (InvalidatedSymbols::const_iterator I = Escaped.begin(),
374                                             E = Escaped.end(); I != E; ++I)
375       if (ETraits->hasTrait(*I,
376               RegionAndSymbolInvalidationTraits::TK_PreserveContents) &&
377           !ETraits->hasTrait(*I,
378               RegionAndSymbolInvalidationTraits::TK_SuppressEscape))
379         ConstEscape.insert(*I);
380 
381     if (ConstEscape.empty())
382       return State;
383 
384     return ((const CHECKER *)Checker)->checkConstPointerEscape(State,
385                                                                ConstEscape,
386                                                                Call,
387                                                                Kind);
388   }
389 
390 public:
391   template <typename CHECKER>
_register(CHECKER * checker,CheckerManager & mgr)392   static void _register(CHECKER *checker, CheckerManager &mgr) {
393     mgr._registerForPointerEscape(
394       CheckerManager::CheckPointerEscapeFunc(checker,
395                                             _checkConstPointerEscape<CHECKER>));
396   }
397 };
398 
399 
400 template <typename EVENT>
401 class Event {
402   template <typename CHECKER>
_checkEvent(void * checker,const void * event)403   static void _checkEvent(void *checker, const void *event) {
404     ((const CHECKER *)checker)->checkEvent(*(const EVENT *)event);
405   }
406 public:
407   template <typename CHECKER>
_register(CHECKER * checker,CheckerManager & mgr)408   static void _register(CHECKER *checker, CheckerManager &mgr) {
409     mgr._registerListenerForEvent<EVENT>(
410                  CheckerManager::CheckEventFunc(checker, _checkEvent<CHECKER>));
411   }
412 };
413 
414 } // end check namespace
415 
416 namespace eval {
417 
418 class Assume {
419   template <typename CHECKER>
_evalAssume(void * checker,ProgramStateRef state,const SVal & cond,bool assumption)420   static ProgramStateRef _evalAssume(void *checker,
421                                          ProgramStateRef state,
422                                          const SVal &cond,
423                                          bool assumption) {
424     return ((const CHECKER *)checker)->evalAssume(state, cond, assumption);
425   }
426 
427 public:
428   template <typename CHECKER>
_register(CHECKER * checker,CheckerManager & mgr)429   static void _register(CHECKER *checker, CheckerManager &mgr) {
430     mgr._registerForEvalAssume(
431                  CheckerManager::EvalAssumeFunc(checker, _evalAssume<CHECKER>));
432   }
433 };
434 
435 class Call {
436   template <typename CHECKER>
_evalCall(void * checker,const CallExpr * CE,CheckerContext & C)437   static bool _evalCall(void *checker, const CallExpr *CE, CheckerContext &C) {
438     return ((const CHECKER *)checker)->evalCall(CE, C);
439   }
440 
441 public:
442   template <typename CHECKER>
_register(CHECKER * checker,CheckerManager & mgr)443   static void _register(CHECKER *checker, CheckerManager &mgr) {
444     mgr._registerForEvalCall(
445                      CheckerManager::EvalCallFunc(checker, _evalCall<CHECKER>));
446   }
447 };
448 
449 } // end eval namespace
450 
451 class CheckerBase : public ProgramPointTag {
452   CheckName Name;
453   friend class ::clang::ento::CheckerManager;
454 
455 public:
456   StringRef getTagDescription() const override;
457   CheckName getCheckName() const;
458 
459   /// See CheckerManager::runCheckersForPrintState.
printState(raw_ostream & Out,ProgramStateRef State,const char * NL,const char * Sep)460   virtual void printState(raw_ostream &Out, ProgramStateRef State,
461                           const char *NL, const char *Sep) const { }
462 };
463 
464 /// Dump checker name to stream.
465 raw_ostream& operator<<(raw_ostream &Out, const CheckerBase &Checker);
466 
467 /// Tag that can use a checker name as a message provider
468 /// (see SimpleProgramPointTag).
469 class CheckerProgramPointTag : public SimpleProgramPointTag {
470 public:
471   CheckerProgramPointTag(StringRef CheckerName, StringRef Msg);
472   CheckerProgramPointTag(const CheckerBase *Checker, StringRef Msg);
473 };
474 
475 template <typename CHECK1, typename... CHECKs>
476 class Checker : public CHECK1, public CHECKs..., public CheckerBase {
477 public:
478   template <typename CHECKER>
_register(CHECKER * checker,CheckerManager & mgr)479   static void _register(CHECKER *checker, CheckerManager &mgr) {
480     CHECK1::_register(checker, mgr);
481     Checker<CHECKs...>::_register(checker, mgr);
482   }
483 };
484 
485 template <typename CHECK1>
486 class Checker<CHECK1> : public CHECK1, public CheckerBase {
487 public:
488   template <typename CHECKER>
_register(CHECKER * checker,CheckerManager & mgr)489   static void _register(CHECKER *checker, CheckerManager &mgr) {
490     CHECK1::_register(checker, mgr);
491   }
492 };
493 
494 template <typename EVENT>
495 class EventDispatcher {
496   CheckerManager *Mgr;
497 public:
EventDispatcher()498   EventDispatcher() : Mgr(nullptr) { }
499 
500   template <typename CHECKER>
_register(CHECKER * checker,CheckerManager & mgr)501   static void _register(CHECKER *checker, CheckerManager &mgr) {
502     mgr._registerDispatcherForEvent<EVENT>();
503     static_cast<EventDispatcher<EVENT> *>(checker)->Mgr = &mgr;
504   }
505 
dispatchEvent(const EVENT & event)506   void dispatchEvent(const EVENT &event) const {
507     Mgr->_dispatchEvent(event);
508   }
509 };
510 
511 /// \brief We dereferenced a location that may be null.
512 struct ImplicitNullDerefEvent {
513   SVal Location;
514   bool IsLoad;
515   ExplodedNode *SinkNode;
516   BugReporter *BR;
517 };
518 
519 /// \brief A helper class which wraps a boolean value set to false by default.
520 ///
521 /// This class should behave exactly like 'bool' except that it doesn't need to
522 /// be explicitly initialized.
523 struct DefaultBool {
524   bool val;
DefaultBoolDefaultBool525   DefaultBool() : val(false) {}
526   /*implicit*/ operator bool&() { return val; }
527   /*implicit*/ operator const bool&() const { return val; }
528   DefaultBool &operator=(bool b) { val = b; return *this; }
529 };
530 
531 } // end ento namespace
532 
533 } // end clang namespace
534 
535 #endif
536