Checker.h revision dff6ef903ff4fcb43b5ea292ecd772e381393b5d
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(llvm::cast<DECL>(D), mgr, BR);
38  }
39
40  static bool _handlesDecl(const Decl *D) {
41    return llvm::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(llvm::cast<STMT>(S), C);
90  }
91
92  static bool _handlesStmt(const Stmt *S) {
93    return llvm::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(llvm::cast<STMT>(S), C);
109  }
110
111  static bool _handlesStmt(const Stmt *S) {
112    return llvm::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 ObjCMessage &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 ObjCMessage &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 Location {
154  template <typename CHECKER>
155  static void _checkLocation(void *checker, const SVal &location, bool isLoad,
156                             CheckerContext &C) {
157    ((const CHECKER *)checker)->checkLocation(location, isLoad, C);
158  }
159
160public:
161  template <typename CHECKER>
162  static void _register(CHECKER *checker, CheckerManager &mgr) {
163    mgr._registerForLocation(
164           CheckerManager::CheckLocationFunc(checker, _checkLocation<CHECKER>));
165  }
166};
167
168class Bind {
169  template <typename CHECKER>
170  static void _checkBind(void *checker, const SVal &location, const SVal &val,
171                         CheckerContext &C) {
172    ((const CHECKER *)checker)->checkBind(location, val, C);
173  }
174
175public:
176  template <typename CHECKER>
177  static void _register(CHECKER *checker, CheckerManager &mgr) {
178    mgr._registerForBind(
179           CheckerManager::CheckBindFunc(checker, _checkBind<CHECKER>));
180  }
181};
182
183class EndAnalysis {
184  template <typename CHECKER>
185  static void _checkEndAnalysis(void *checker, ExplodedGraph &G,
186                                BugReporter &BR, ExprEngine &Eng) {
187    ((const CHECKER *)checker)->checkEndAnalysis(G, BR, Eng);
188  }
189
190public:
191  template <typename CHECKER>
192  static void _register(CHECKER *checker, CheckerManager &mgr) {
193    mgr._registerForEndAnalysis(
194     CheckerManager::CheckEndAnalysisFunc(checker, _checkEndAnalysis<CHECKER>));
195  }
196};
197
198class EndPath {
199  template <typename CHECKER>
200  static void _checkEndPath(void *checker, EndOfFunctionNodeBuilder &B,
201                            ExprEngine &Eng) {
202    ((const CHECKER *)checker)->checkEndPath(B, Eng);
203  }
204
205public:
206  template <typename CHECKER>
207  static void _register(CHECKER *checker, CheckerManager &mgr) {
208    mgr._registerForEndPath(
209     CheckerManager::CheckEndPathFunc(checker, _checkEndPath<CHECKER>));
210  }
211};
212
213class BranchCondition {
214  template <typename CHECKER>
215  static void _checkBranchCondition(void *checker, const Stmt *condition,
216                                    BranchNodeBuilder &B, ExprEngine &Eng) {
217    ((const CHECKER *)checker)->checkBranchCondition(condition, B, Eng);
218  }
219
220public:
221  template <typename CHECKER>
222  static void _register(CHECKER *checker, CheckerManager &mgr) {
223    mgr._registerForBranchCondition(
224      CheckerManager::CheckBranchConditionFunc(checker,
225                                               _checkBranchCondition<CHECKER>));
226  }
227};
228
229class LiveSymbols {
230  template <typename CHECKER>
231  static void _checkLiveSymbols(void *checker, const ProgramState *state,
232                                SymbolReaper &SR) {
233    ((const CHECKER *)checker)->checkLiveSymbols(state, SR);
234  }
235
236public:
237  template <typename CHECKER>
238  static void _register(CHECKER *checker, CheckerManager &mgr) {
239    mgr._registerForLiveSymbols(
240     CheckerManager::CheckLiveSymbolsFunc(checker, _checkLiveSymbols<CHECKER>));
241  }
242};
243
244class DeadSymbols {
245  template <typename CHECKER>
246  static void _checkDeadSymbols(void *checker,
247                                SymbolReaper &SR, CheckerContext &C) {
248    ((const CHECKER *)checker)->checkDeadSymbols(SR, C);
249  }
250
251public:
252  template <typename CHECKER>
253  static void _register(CHECKER *checker, CheckerManager &mgr) {
254    mgr._registerForDeadSymbols(
255     CheckerManager::CheckDeadSymbolsFunc(checker, _checkDeadSymbols<CHECKER>));
256  }
257};
258
259class RegionChanges {
260  template <typename CHECKER>
261  static const ProgramState *
262  _checkRegionChanges(void *checker,
263                      const ProgramState *state,
264                      const StoreManager::InvalidatedSymbols *invalidated,
265                      ArrayRef<const MemRegion *> Explicits,
266                      ArrayRef<const MemRegion *> Regions) {
267    return ((const CHECKER *)checker)->checkRegionChanges(state, invalidated,
268                                                          Explicits, Regions);
269  }
270  template <typename CHECKER>
271  static bool _wantsRegionChangeUpdate(void *checker,
272                                       const ProgramState *state) {
273    return ((const CHECKER *)checker)->wantsRegionChangeUpdate(state);
274  }
275
276public:
277  template <typename CHECKER>
278  static void _register(CHECKER *checker, CheckerManager &mgr) {
279    mgr._registerForRegionChanges(
280          CheckerManager::CheckRegionChangesFunc(checker,
281                                                 _checkRegionChanges<CHECKER>),
282          CheckerManager::WantsRegionChangeUpdateFunc(checker,
283                                            _wantsRegionChangeUpdate<CHECKER>));
284  }
285};
286
287template <typename EVENT>
288class Event {
289  template <typename CHECKER>
290  static void _checkEvent(void *checker, const void *event) {
291    ((const CHECKER *)checker)->checkEvent(*(const EVENT *)event);
292  }
293public:
294  template <typename CHECKER>
295  static void _register(CHECKER *checker, CheckerManager &mgr) {
296    mgr._registerListenerForEvent<EVENT>(
297                 CheckerManager::CheckEventFunc(checker, _checkEvent<CHECKER>));
298  }
299};
300
301} // end check namespace
302
303namespace eval {
304
305class Assume {
306  template <typename CHECKER>
307  static const ProgramState *_evalAssume(void *checker,
308                                         const ProgramState *state,
309                                         const SVal &cond,
310                                         bool assumption) {
311    return ((const CHECKER *)checker)->evalAssume(state, cond, assumption);
312  }
313
314public:
315  template <typename CHECKER>
316  static void _register(CHECKER *checker, CheckerManager &mgr) {
317    mgr._registerForEvalAssume(
318                 CheckerManager::EvalAssumeFunc(checker, _evalAssume<CHECKER>));
319  }
320};
321
322class Call {
323  template <typename CHECKER>
324  static bool _evalCall(void *checker, const CallExpr *CE, CheckerContext &C) {
325    return ((const CHECKER *)checker)->evalCall(CE, C);
326  }
327
328public:
329  template <typename CHECKER>
330  static void _register(CHECKER *checker, CheckerManager &mgr) {
331    mgr._registerForEvalCall(
332                     CheckerManager::EvalCallFunc(checker, _evalCall<CHECKER>));
333  }
334};
335
336class InlineCall {
337  template <typename CHECKER>
338  static bool _inlineCall(void *checker, const CallExpr *CE,
339                                         ExprEngine &Eng,
340                                         ExplodedNode *Pred,
341                                         ExplodedNodeSet &Dst) {
342    return ((const CHECKER *)checker)->inlineCall(CE, Eng, Pred, Dst);
343  }
344
345public:
346  template <typename CHECKER>
347  static void _register(CHECKER *checker, CheckerManager &mgr) {
348    mgr._registerForInlineCall(
349                 CheckerManager::InlineCallFunc(checker, _inlineCall<CHECKER>));
350  }
351};
352
353} // end eval namespace
354
355class CheckerBase : public ProgramPointTag {
356public:
357  StringRef getTagDescription() const;
358
359  /// See CheckerManager::runCheckersForPrintState.
360  virtual void printState(raw_ostream &Out, const ProgramState *State,
361                          const char *NL, const char *Sep) const { }
362};
363
364template <typename CHECK1, typename CHECK2=check::_VoidCheck,
365          typename CHECK3=check::_VoidCheck, typename CHECK4=check::_VoidCheck,
366          typename CHECK5=check::_VoidCheck, typename CHECK6=check::_VoidCheck,
367          typename CHECK7=check::_VoidCheck, typename CHECK8=check::_VoidCheck,
368          typename CHECK9=check::_VoidCheck, typename CHECK10=check::_VoidCheck,
369          typename CHECK11=check::_VoidCheck,typename CHECK12=check::_VoidCheck,
370          typename CHECK13=check::_VoidCheck,typename CHECK14=check::_VoidCheck,
371          typename CHECK15=check::_VoidCheck,typename CHECK16=check::_VoidCheck>
372class Checker;
373
374template <>
375class Checker<check::_VoidCheck, check::_VoidCheck, check::_VoidCheck,
376                check::_VoidCheck, check::_VoidCheck, check::_VoidCheck,
377                check::_VoidCheck, check::_VoidCheck, check::_VoidCheck,
378                check::_VoidCheck, check::_VoidCheck, check::_VoidCheck,
379                check::_VoidCheck, check::_VoidCheck, check::_VoidCheck,
380                check::_VoidCheck>
381  : public CheckerBase
382{
383public:
384  static void _register(void *checker, CheckerManager &mgr) { }
385};
386
387template <typename CHECK1, typename CHECK2, typename CHECK3, typename CHECK4,
388          typename CHECK5, typename CHECK6, typename CHECK7, typename CHECK8,
389          typename CHECK9, typename CHECK10,typename CHECK11,typename CHECK12,
390          typename CHECK13,typename CHECK14,typename CHECK15,typename CHECK16>
391class Checker
392    : public CHECK1,
393      public Checker<CHECK2, CHECK3, CHECK4, CHECK5, CHECK6, CHECK7, CHECK8,
394                     CHECK9, CHECK10,CHECK11,CHECK12,CHECK13,CHECK14,CHECK15,
395                     CHECK16> {
396public:
397  template <typename CHECKER>
398  static void _register(CHECKER *checker, CheckerManager &mgr) {
399    CHECK1::_register(checker, mgr);
400    Checker<CHECK2, CHECK3, CHECK4, CHECK5, CHECK6, CHECK7, CHECK8,
401            CHECK9, CHECK10,CHECK11,CHECK12,CHECK13,CHECK14,CHECK15,
402            CHECK16>::_register(checker, mgr);
403  }
404};
405
406template <typename EVENT>
407class EventDispatcher {
408  CheckerManager *Mgr;
409public:
410  EventDispatcher() : Mgr(0) { }
411
412  template <typename CHECKER>
413  static void _register(CHECKER *checker, CheckerManager &mgr) {
414    mgr._registerDispatcherForEvent<EVENT>();
415    static_cast<EventDispatcher<EVENT> *>(checker)->Mgr = &mgr;
416  }
417
418  void dispatchEvent(const EVENT &event) const {
419    Mgr->_dispatchEvent(event);
420  }
421};
422
423/// \brief We dereferenced a location that may be null.
424struct ImplicitNullDerefEvent {
425  SVal Location;
426  bool IsLoad;
427  ExplodedNode *SinkNode;
428  BugReporter *BR;
429};
430
431} // end ento namespace
432
433} // end clang namespace
434
435#endif
436