Checker.h revision b7a747b0c271faeeb8d0f886f0e691eb25f637d9
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
22namespace clang {
23namespace ento {
24  class BugReporter;
25
26namespace check {
27
28struct _VoidCheck {
29  static void _register(void *checker, CheckerManager &mgr) { }
30};
31
32template <typename DECL>
33class 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  }
43public:
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
52class 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
59public:
60  template <typename CHECKER>
61  static void _register(CHECKER *checker, CheckerManager &mgr) {
62    mgr._registerForBody(CheckerManager::CheckDeclFunc(checker,
63                                                       _checkBody<CHECKER>));
64  }
65};
66
67class 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
76public:
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
85template <typename STMT>
86class 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  }
95public:
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
104template <typename STMT>
105class 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  }
114public:
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
123class 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
130public:
131  template <typename CHECKER>
132  static void _register(CHECKER *checker, CheckerManager &mgr) {
133    mgr._registerForPreObjCMessage(
134     CheckerManager::CheckObjCMessageFunc(checker, _checkObjCMessage<CHECKER>));
135  }
136};
137
138class 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
145public:
146  template <typename CHECKER>
147  static void _register(CHECKER *checker, CheckerManager &mgr) {
148    mgr._registerForPostObjCMessage(
149     CheckerManager::CheckObjCMessageFunc(checker, _checkObjCMessage<CHECKER>));
150  }
151};
152
153class 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
160public:
161  template <typename CHECKER>
162  static void _register(CHECKER *checker, CheckerManager &mgr) {
163    mgr._registerForPreCall(
164     CheckerManager::CheckCallFunc(checker, _checkCall<CHECKER>));
165  }
166};
167
168class 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
175public:
176  template <typename CHECKER>
177  static void _register(CHECKER *checker, CheckerManager &mgr) {
178    mgr._registerForPostCall(
179     CheckerManager::CheckCallFunc(checker, _checkCall<CHECKER>));
180  }
181};
182
183class 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
191public:
192  template <typename CHECKER>
193  static void _register(CHECKER *checker, CheckerManager &mgr) {
194    mgr._registerForLocation(
195           CheckerManager::CheckLocationFunc(checker, _checkLocation<CHECKER>));
196  }
197};
198
199class 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
207public:
208  template <typename CHECKER>
209  static void _register(CHECKER *checker, CheckerManager &mgr) {
210    mgr._registerForBind(
211           CheckerManager::CheckBindFunc(checker, _checkBind<CHECKER>));
212  }
213};
214
215class 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
222public:
223  template <typename CHECKER>
224  static void _register(CHECKER *checker, CheckerManager &mgr) {
225    mgr._registerForEndAnalysis(
226     CheckerManager::CheckEndAnalysisFunc(checker, _checkEndAnalysis<CHECKER>));
227  }
228};
229
230class EndFunction {
231  template <typename CHECKER>
232  static void _checkEndFunction(void *checker,
233                                CheckerContext &C) {
234    ((const CHECKER *)checker)->checkEndFunction(C);
235  }
236
237public:
238  template <typename CHECKER>
239  static void _register(CHECKER *checker, CheckerManager &mgr) {
240    mgr._registerForEndFunction(
241     CheckerManager::CheckEndFunctionFunc(checker, _checkEndFunction<CHECKER>));
242  }
243};
244
245class 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
252public:
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
261class 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
268public:
269  template <typename CHECKER>
270  static void _register(CHECKER *checker, CheckerManager &mgr) {
271    mgr._registerForLiveSymbols(
272     CheckerManager::CheckLiveSymbolsFunc(checker, _checkLiveSymbols<CHECKER>));
273  }
274};
275
276class 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
283public:
284  template <typename CHECKER>
285  static void _register(CHECKER *checker, CheckerManager &mgr) {
286    mgr._registerForDeadSymbols(
287     CheckerManager::CheckDeadSymbolsFunc(checker, _checkDeadSymbols<CHECKER>));
288  }
289};
290
291class 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
309public:
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
320class 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
354public:
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
363class 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
394public:
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
404template <typename EVENT>
405class Event {
406  template <typename CHECKER>
407  static void _checkEvent(void *checker, const void *event) {
408    ((const CHECKER *)checker)->checkEvent(*(const EVENT *)event);
409  }
410public:
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
420namespace eval {
421
422class 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
431public:
432  template <typename CHECKER>
433  static void _register(CHECKER *checker, CheckerManager &mgr) {
434    mgr._registerForEvalAssume(
435                 CheckerManager::EvalAssumeFunc(checker, _evalAssume<CHECKER>));
436  }
437};
438
439class 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
445public:
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
455class CheckerBase : public ProgramPointTag {
456public:
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
464template <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>
476class Checker;
477
478template <>
479class Checker<check::_VoidCheck>
480  : public CheckerBase
481{
482  virtual void anchor();
483public:
484  static void _register(void *checker, CheckerManager &mgr) { }
485};
486
487template <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>
493class 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> {
499public:
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
510template <typename EVENT>
511class EventDispatcher {
512  CheckerManager *Mgr;
513public:
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.
528struct 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.
539struct 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
552