Checker.h revision 9be6e7ce5788e50c62d40c59b0bbc2ea423683f7
15738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project//== Checker.h - Registration mechanism for checkers -------------*- C++ -*--=//
25738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project//
35738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project//                     The LLVM Compiler Infrastructure
45738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project//
55738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project// This file is distributed under the University of Illinois Open Source
65738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project// License. See LICENSE.TXT for details.
75738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project//
85738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project//===----------------------------------------------------------------------===//
95738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project//
105738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project//  This file defines Checker, used to create and register checkers.
115738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project//
125738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project//===----------------------------------------------------------------------===//
135738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
145738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#ifndef LLVM_CLANG_SA_CORE_CHECKER
155738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#define LLVM_CLANG_SA_CORE_CHECKER
165738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
175738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#include "clang/StaticAnalyzer/Core/CheckerManager.h"
185738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h"
195738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#include "llvm/Support/Casting.h"
205738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
215738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Projectnamespace clang {
225738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Projectnamespace ento {
235738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project  class BugReporter;
245738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
255738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Projectnamespace check {
265738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
275738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Projectstruct _VoidCheck {
285738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project  static void _register(void *checker, CheckerManager &mgr) { }
295738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project};
305738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
315738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Projecttemplate <typename DECL>
325738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Projectclass ASTDecl {
335738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project  template <typename CHECKER>
345738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project  static void _checkDecl(void *checker, const Decl *D, AnalysisManager& mgr,
355738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                         BugReporter &BR) {
365738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    ((const CHECKER *)checker)->checkASTDecl(llvm::cast<DECL>(D), mgr, BR);
375738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project  }
385738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
395738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project  static bool _handlesDecl(const Decl *D) {
405738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    return llvm::isa<DECL>(D);
415738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project  }
425738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Projectpublic:
435738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project  template <typename CHECKER>
445738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project  static void _register(CHECKER *checker, CheckerManager &mgr) {
455738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    mgr._registerForDecl(CheckerManager::CheckDeclFunc(checker,
465738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                                                       _checkDecl<CHECKER>),
475738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                         _handlesDecl);
485738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project  }
495738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project};
505738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
515738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Projectclass ASTCodeBody {
525738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project  template <typename CHECKER>
535738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project  static void _checkBody(void *checker, const Decl *D, AnalysisManager& mgr,
545738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                         BugReporter &BR) {
555738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    ((const CHECKER *)checker)->checkASTCodeBody(D, mgr, BR);
565738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project  }
575738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
585738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Projectpublic:
595738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project  template <typename CHECKER>
605738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project  static void _register(CHECKER *checker, CheckerManager &mgr) {
615738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    mgr._registerForBody(CheckerManager::CheckDeclFunc(checker,
625738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                                                       _checkBody<CHECKER>));
635738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project  }
645738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project};
655738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
665738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Projectclass EndOfTranslationUnit {
675738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project  template <typename CHECKER>
685738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project  static void _checkEndOfTranslationUnit(void *checker,
695738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                                         const TranslationUnitDecl *TU,
70                                         AnalysisManager& mgr,
71                                         BugReporter &BR) {
72    ((const CHECKER *)checker)->checkEndOfTranslationUnit(TU, mgr, BR);
73  }
74
75public:
76  template <typename CHECKER>
77  static void _register(CHECKER *checker, CheckerManager &mgr){
78    mgr._registerForEndOfTranslationUnit(
79                              CheckerManager::CheckEndOfTranslationUnit(checker,
80                                          _checkEndOfTranslationUnit<CHECKER>));
81  }
82};
83
84template <typename STMT>
85class PreStmt {
86  template <typename CHECKER>
87  static void _checkStmt(void *checker, const Stmt *S, CheckerContext &C) {
88    ((const CHECKER *)checker)->checkPreStmt(llvm::cast<STMT>(S), C);
89  }
90
91  static bool _handlesStmt(const Stmt *S) {
92    return llvm::isa<STMT>(S);
93  }
94public:
95  template <typename CHECKER>
96  static void _register(CHECKER *checker, CheckerManager &mgr) {
97    mgr._registerForPreStmt(CheckerManager::CheckStmtFunc(checker,
98                                                          _checkStmt<CHECKER>),
99                            _handlesStmt);
100  }
101};
102
103template <typename STMT>
104class PostStmt {
105  template <typename CHECKER>
106  static void _checkStmt(void *checker, const Stmt *S, CheckerContext &C) {
107    ((const CHECKER *)checker)->checkPostStmt(llvm::cast<STMT>(S), C);
108  }
109
110  static bool _handlesStmt(const Stmt *S) {
111    return llvm::isa<STMT>(S);
112  }
113public:
114  template <typename CHECKER>
115  static void _register(CHECKER *checker, CheckerManager &mgr) {
116    mgr._registerForPostStmt(CheckerManager::CheckStmtFunc(checker,
117                                                           _checkStmt<CHECKER>),
118                             _handlesStmt);
119  }
120};
121
122class PreObjCMessage {
123  template <typename CHECKER>
124  static void _checkObjCMessage(void *checker, const ObjCMessage &msg,
125                                CheckerContext &C) {
126    ((const CHECKER *)checker)->checkPreObjCMessage(msg, C);
127  }
128
129public:
130  template <typename CHECKER>
131  static void _register(CHECKER *checker, CheckerManager &mgr) {
132    mgr._registerForPreObjCMessage(
133     CheckerManager::CheckObjCMessageFunc(checker, _checkObjCMessage<CHECKER>));
134  }
135};
136
137class PostObjCMessage {
138  template <typename CHECKER>
139  static void _checkObjCMessage(void *checker, const ObjCMessage &msg,
140                                CheckerContext &C) {
141    ((const CHECKER *)checker)->checkPostObjCMessage(msg, C);
142  }
143
144public:
145  template <typename CHECKER>
146  static void _register(CHECKER *checker, CheckerManager &mgr) {
147    mgr._registerForPostObjCMessage(
148     CheckerManager::CheckObjCMessageFunc(checker, _checkObjCMessage<CHECKER>));
149  }
150};
151
152class Location {
153  template <typename CHECKER>
154  static void _checkLocation(void *checker, const SVal &location, bool isLoad,
155                             CheckerContext &C) {
156    ((const CHECKER *)checker)->checkLocation(location, isLoad, C);
157  }
158
159public:
160  template <typename CHECKER>
161  static void _register(CHECKER *checker, CheckerManager &mgr) {
162    mgr._registerForLocation(
163           CheckerManager::CheckLocationFunc(checker, _checkLocation<CHECKER>));
164  }
165};
166
167class Bind {
168  template <typename CHECKER>
169  static void _checkBind(void *checker, const SVal &location, const SVal &val,
170                         CheckerContext &C) {
171    ((const CHECKER *)checker)->checkBind(location, val, C);
172  }
173
174public:
175  template <typename CHECKER>
176  static void _register(CHECKER *checker, CheckerManager &mgr) {
177    mgr._registerForBind(
178           CheckerManager::CheckBindFunc(checker, _checkBind<CHECKER>));
179  }
180};
181
182class EndAnalysis {
183  template <typename CHECKER>
184  static void _checkEndAnalysis(void *checker, ExplodedGraph &G,
185                                BugReporter &BR, ExprEngine &Eng) {
186    ((const CHECKER *)checker)->checkEndAnalysis(G, BR, Eng);
187  }
188
189public:
190  template <typename CHECKER>
191  static void _register(CHECKER *checker, CheckerManager &mgr) {
192    mgr._registerForEndAnalysis(
193     CheckerManager::CheckEndAnalysisFunc(checker, _checkEndAnalysis<CHECKER>));
194  }
195};
196
197class EndPath {
198  template <typename CHECKER>
199  static void _checkEndPath(void *checker, EndOfFunctionNodeBuilder &B,
200                            ExprEngine &Eng) {
201    ((const CHECKER *)checker)->checkEndPath(B, Eng);
202  }
203
204public:
205  template <typename CHECKER>
206  static void _register(CHECKER *checker, CheckerManager &mgr) {
207    mgr._registerForEndPath(
208     CheckerManager::CheckEndPathFunc(checker, _checkEndPath<CHECKER>));
209  }
210};
211
212class BranchCondition {
213  template <typename CHECKER>
214  static void _checkBranchCondition(void *checker, const Stmt *condition,
215                                    BranchNodeBuilder &B, ExprEngine &Eng) {
216    ((const CHECKER *)checker)->checkBranchCondition(condition, B, Eng);
217  }
218
219public:
220  template <typename CHECKER>
221  static void _register(CHECKER *checker, CheckerManager &mgr) {
222    mgr._registerForBranchCondition(
223      CheckerManager::CheckBranchConditionFunc(checker,
224                                               _checkBranchCondition<CHECKER>));
225  }
226};
227
228class LiveSymbols {
229  template <typename CHECKER>
230  static void _checkLiveSymbols(void *checker, const GRState *state,
231                                SymbolReaper &SR) {
232    ((const CHECKER *)checker)->checkLiveSymbols(state, SR);
233  }
234
235public:
236  template <typename CHECKER>
237  static void _register(CHECKER *checker, CheckerManager &mgr) {
238    mgr._registerForLiveSymbols(
239     CheckerManager::CheckLiveSymbolsFunc(checker, _checkLiveSymbols<CHECKER>));
240  }
241};
242
243class DeadSymbols {
244  template <typename CHECKER>
245  static void _checkDeadSymbols(void *checker,
246                                SymbolReaper &SR, CheckerContext &C) {
247    ((const CHECKER *)checker)->checkDeadSymbols(SR, C);
248  }
249
250public:
251  template <typename CHECKER>
252  static void _register(CHECKER *checker, CheckerManager &mgr) {
253    mgr._registerForDeadSymbols(
254     CheckerManager::CheckDeadSymbolsFunc(checker, _checkDeadSymbols<CHECKER>));
255  }
256};
257
258class RegionChanges {
259  template <typename CHECKER>
260  static const GRState *_checkRegionChanges(void *checker, const GRState *state,
261                            const StoreManager::InvalidatedSymbols *invalidated,
262                                            const MemRegion * const *Begin,
263                                            const MemRegion * const *End) {
264    return ((const CHECKER *)checker)->checkRegionChanges(state, invalidated,
265                                                          Begin, End);
266  }
267  template <typename CHECKER>
268  static bool _wantsRegionChangeUpdate(void *checker, const GRState *state) {
269    return ((const CHECKER *)checker)->wantsRegionChangeUpdate(state);
270  }
271
272public:
273  template <typename CHECKER>
274  static void _register(CHECKER *checker, CheckerManager &mgr) {
275    mgr._registerForRegionChanges(
276          CheckerManager::CheckRegionChangesFunc(checker,
277                                                 _checkRegionChanges<CHECKER>),
278          CheckerManager::WantsRegionChangeUpdateFunc(checker,
279                                            _wantsRegionChangeUpdate<CHECKER>));
280  }
281};
282
283template <typename EVENT>
284class Event {
285  template <typename CHECKER>
286  static void _checkEvent(void *checker, const void *event) {
287    ((const CHECKER *)checker)->checkEvent(*(const EVENT *)event);
288  }
289public:
290  template <typename CHECKER>
291  static void _register(CHECKER *checker, CheckerManager &mgr) {
292    mgr._registerListenerForEvent<EVENT>(
293                 CheckerManager::CheckEventFunc(checker, _checkEvent<CHECKER>));
294  }
295};
296
297} // end check namespace
298
299namespace eval {
300
301class Assume {
302  template <typename CHECKER>
303  static const GRState *_evalAssume(void *checker, const GRState *state,
304                                    const SVal &cond, bool assumption) {
305    return ((const CHECKER *)checker)->evalAssume(state, cond, assumption);
306  }
307
308public:
309  template <typename CHECKER>
310  static void _register(CHECKER *checker, CheckerManager &mgr) {
311    mgr._registerForEvalAssume(
312                 CheckerManager::EvalAssumeFunc(checker, _evalAssume<CHECKER>));
313  }
314};
315
316class Call {
317  template <typename CHECKER>
318  static bool _evalCall(void *checker, const CallExpr *CE, CheckerContext &C) {
319    return ((const CHECKER *)checker)->evalCall(CE, C);
320  }
321
322public:
323  template <typename CHECKER>
324  static void _register(CHECKER *checker, CheckerManager &mgr) {
325    mgr._registerForEvalCall(
326                     CheckerManager::EvalCallFunc(checker, _evalCall<CHECKER>));
327  }
328};
329
330} // end eval namespace
331
332template <typename CHECK1, typename CHECK2=check::_VoidCheck,
333          typename CHECK3=check::_VoidCheck, typename CHECK4=check::_VoidCheck,
334          typename CHECK5=check::_VoidCheck, typename CHECK6=check::_VoidCheck,
335          typename CHECK7=check::_VoidCheck, typename CHECK8=check::_VoidCheck,
336          typename CHECK9=check::_VoidCheck, typename CHECK10=check::_VoidCheck,
337          typename CHECK11=check::_VoidCheck,typename CHECK12=check::_VoidCheck>
338class Checker;
339
340template <>
341class Checker<check::_VoidCheck, check::_VoidCheck, check::_VoidCheck,
342                check::_VoidCheck, check::_VoidCheck, check::_VoidCheck,
343                check::_VoidCheck, check::_VoidCheck, check::_VoidCheck,
344                check::_VoidCheck, check::_VoidCheck, check::_VoidCheck> {
345public:
346  static void _register(void *checker, CheckerManager &mgr) { }
347};
348
349template <typename CHECK1, typename CHECK2, typename CHECK3, typename CHECK4,
350          typename CHECK5, typename CHECK6, typename CHECK7, typename CHECK8,
351          typename CHECK9, typename CHECK10,typename CHECK11,typename CHECK12>
352class Checker
353    : public CHECK1,
354      public Checker<CHECK2, CHECK3, CHECK4, CHECK5, CHECK6, CHECK7, CHECK8,
355                       CHECK9, CHECK10, CHECK11, CHECK12> {
356public:
357  template <typename CHECKER>
358  static void _register(CHECKER *checker, CheckerManager &mgr) {
359    CHECK1::_register(checker, mgr);
360    Checker<CHECK2, CHECK3, CHECK4, CHECK5, CHECK6, CHECK7, CHECK8, CHECK9,
361              CHECK10, CHECK11,CHECK12>::_register(checker, mgr);
362  }
363};
364
365template <typename EVENT>
366class EventDispatcher {
367  CheckerManager *Mgr;
368public:
369  EventDispatcher() : Mgr(0) { }
370
371  template <typename CHECKER>
372  static void _register(CHECKER *checker, CheckerManager &mgr) {
373    mgr._registerDispatcherForEvent<EVENT>();
374    static_cast<EventDispatcher<EVENT> *>(checker)->Mgr = &mgr;
375  }
376
377  void dispatchEvent(const EVENT &event) const {
378    Mgr->_dispatchEvent(event);
379  }
380};
381
382/// \brief We dereferenced a location that may be null.
383struct ImplicitNullDerefEvent {
384  SVal Location;
385  bool IsLoad;
386  ExplodedNode *SinkNode;
387  BugReporter *BR;
388};
389
390} // end ento namespace
391
392} // end clang namespace
393
394#endif
395