Checker.h revision 651f13cea278ec967336033dd032faef0e9fc2ec
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 {
456  CheckName Name;
457  friend class ::clang::ento::CheckerManager;
458
459public:
460  StringRef getTagDescription() const override;
461  CheckName getCheckName() const;
462
463  /// See CheckerManager::runCheckersForPrintState.
464  virtual void printState(raw_ostream &Out, ProgramStateRef State,
465                          const char *NL, const char *Sep) const { }
466};
467
468/// Dump checker name to stream.
469raw_ostream& operator<<(raw_ostream &Out, const CheckerBase &Checker);
470
471/// Tag that can use a checker name as a message provider
472/// (see SimpleProgramPointTag).
473class CheckerProgramPointTag : public SimpleProgramPointTag {
474public:
475  CheckerProgramPointTag(StringRef CheckerName, StringRef Msg);
476  CheckerProgramPointTag(const CheckerBase *Checker, StringRef Msg);
477};
478
479template <typename CHECK1, typename CHECK2=check::_VoidCheck,
480          typename CHECK3=check::_VoidCheck, typename CHECK4=check::_VoidCheck,
481          typename CHECK5=check::_VoidCheck, typename CHECK6=check::_VoidCheck,
482          typename CHECK7=check::_VoidCheck, typename CHECK8=check::_VoidCheck,
483          typename CHECK9=check::_VoidCheck, typename CHECK10=check::_VoidCheck,
484          typename CHECK11=check::_VoidCheck,typename CHECK12=check::_VoidCheck,
485          typename CHECK13=check::_VoidCheck,typename CHECK14=check::_VoidCheck,
486          typename CHECK15=check::_VoidCheck,typename CHECK16=check::_VoidCheck,
487          typename CHECK17=check::_VoidCheck,typename CHECK18=check::_VoidCheck,
488          typename CHECK19=check::_VoidCheck,typename CHECK20=check::_VoidCheck,
489          typename CHECK21=check::_VoidCheck,typename CHECK22=check::_VoidCheck,
490          typename CHECK23=check::_VoidCheck,typename CHECK24=check::_VoidCheck>
491class Checker;
492
493template <>
494class Checker<check::_VoidCheck>
495  : public CheckerBase
496{
497  virtual void anchor();
498public:
499  static void _register(void *checker, CheckerManager &mgr) { }
500};
501
502template <typename CHECK1, typename CHECK2, typename CHECK3, typename CHECK4,
503          typename CHECK5, typename CHECK6, typename CHECK7, typename CHECK8,
504          typename CHECK9, typename CHECK10,typename CHECK11,typename CHECK12,
505          typename CHECK13,typename CHECK14,typename CHECK15,typename CHECK16,
506          typename CHECK17,typename CHECK18,typename CHECK19,typename CHECK20,
507          typename CHECK21,typename CHECK22,typename CHECK23,typename CHECK24>
508class Checker
509    : public CHECK1,
510      public Checker<CHECK2, CHECK3, CHECK4, CHECK5, CHECK6, CHECK7,
511                     CHECK8, CHECK9, CHECK10,CHECK11,CHECK12,CHECK13,
512                     CHECK14,CHECK15,CHECK16,CHECK17,CHECK18,CHECK19,
513                     CHECK20,CHECK21,CHECK22,CHECK23,CHECK24> {
514public:
515  template <typename CHECKER>
516  static void _register(CHECKER *checker, CheckerManager &mgr) {
517    CHECK1::_register(checker, mgr);
518    Checker<CHECK2, CHECK3, CHECK4, CHECK5, CHECK6, CHECK7,
519            CHECK8, CHECK9, CHECK10,CHECK11,CHECK12,CHECK13,
520            CHECK14,CHECK15,CHECK16,CHECK17,CHECK18,CHECK19,
521            CHECK20,CHECK21,CHECK22,CHECK23,CHECK24>::_register(checker, mgr);
522  }
523};
524
525template <typename EVENT>
526class EventDispatcher {
527  CheckerManager *Mgr;
528public:
529  EventDispatcher() : Mgr(0) { }
530
531  template <typename CHECKER>
532  static void _register(CHECKER *checker, CheckerManager &mgr) {
533    mgr._registerDispatcherForEvent<EVENT>();
534    static_cast<EventDispatcher<EVENT> *>(checker)->Mgr = &mgr;
535  }
536
537  void dispatchEvent(const EVENT &event) const {
538    Mgr->_dispatchEvent(event);
539  }
540};
541
542/// \brief We dereferenced a location that may be null.
543struct ImplicitNullDerefEvent {
544  SVal Location;
545  bool IsLoad;
546  ExplodedNode *SinkNode;
547  BugReporter *BR;
548};
549
550/// \brief A helper class which wraps a boolean value set to false by default.
551///
552/// This class should behave exactly like 'bool' except that it doesn't need to
553/// be explicitly initialized.
554struct DefaultBool {
555  bool val;
556  DefaultBool() : val(false) {}
557  /*implicit*/ operator bool&() { return val; }
558  /*implicit*/ operator const bool&() const { return val; }
559  DefaultBool &operator=(bool b) { val = b; return *this; }
560};
561
562} // end ento namespace
563
564} // end clang namespace
565
566#endif
567