1 //== Checker.h - Registration mechanism for checkers -------------*- C++ -*--=//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This file defines Checker, used to create and register checkers.
12 //===----------------------------------------------------------------------===//
14 #ifndef LLVM_CLANG_SA_CORE_CHECKER
15 #define LLVM_CLANG_SA_CORE_CHECKER
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"
29 static void _register(void *checker, CheckerManager &mgr) { }
32 template <typename DECL>
34 template <typename CHECKER>
35 static void _checkDecl(void *checker, const Decl *D, AnalysisManager& mgr,
37 ((const CHECKER *)checker)->checkASTDecl(cast<DECL>(D), mgr, BR);
40 static bool _handlesDecl(const Decl *D) {
44 template <typename CHECKER>
45 static void _register(CHECKER *checker, CheckerManager &mgr) {
46 mgr._registerForDecl(CheckerManager::CheckDeclFunc(checker,
53 template <typename CHECKER>
54 static void _checkBody(void *checker, const Decl *D, AnalysisManager& mgr,
56 ((const CHECKER *)checker)->checkASTCodeBody(D, mgr, BR);
60 template <typename CHECKER>
61 static void _register(CHECKER *checker, CheckerManager &mgr) {
62 mgr._registerForBody(CheckerManager::CheckDeclFunc(checker,
63 _checkBody<CHECKER>));
67 class EndOfTranslationUnit {
68 template <typename CHECKER>
69 static void _checkEndOfTranslationUnit(void *checker,
70 const TranslationUnitDecl *TU,
73 ((const CHECKER *)checker)->checkEndOfTranslationUnit(TU, mgr, BR);
77 template <typename CHECKER>
78 static void _register(CHECKER *checker, CheckerManager &mgr){
79 mgr._registerForEndOfTranslationUnit(
80 CheckerManager::CheckEndOfTranslationUnit(checker,
81 _checkEndOfTranslationUnit<CHECKER>));
85 template <typename STMT>
87 template <typename CHECKER>
88 static void _checkStmt(void *checker, const Stmt *S, CheckerContext &C) {
89 ((const CHECKER *)checker)->checkPreStmt(cast<STMT>(S), C);
92 static bool _handlesStmt(const Stmt *S) {
96 template <typename CHECKER>
97 static void _register(CHECKER *checker, CheckerManager &mgr) {
98 mgr._registerForPreStmt(CheckerManager::CheckStmtFunc(checker,
104 template <typename STMT>
106 template <typename CHECKER>
107 static void _checkStmt(void *checker, const Stmt *S, CheckerContext &C) {
108 ((const CHECKER *)checker)->checkPostStmt(cast<STMT>(S), C);
111 static bool _handlesStmt(const Stmt *S) {
115 template <typename CHECKER>
116 static void _register(CHECKER *checker, CheckerManager &mgr) {
117 mgr._registerForPostStmt(CheckerManager::CheckStmtFunc(checker,
118 _checkStmt<CHECKER>),
123 class PreObjCMessage {
124 template <typename CHECKER>
125 static void _checkObjCMessage(void *checker, const ObjCMethodCall &msg,
127 ((const CHECKER *)checker)->checkPreObjCMessage(msg, C);
131 template <typename CHECKER>
132 static void _register(CHECKER *checker, CheckerManager &mgr) {
133 mgr._registerForPreObjCMessage(
134 CheckerManager::CheckObjCMessageFunc(checker, _checkObjCMessage<CHECKER>));
138 class PostObjCMessage {
139 template <typename CHECKER>
140 static void _checkObjCMessage(void *checker, const ObjCMethodCall &msg,
142 ((const CHECKER *)checker)->checkPostObjCMessage(msg, C);
146 template <typename CHECKER>
147 static void _register(CHECKER *checker, CheckerManager &mgr) {
148 mgr._registerForPostObjCMessage(
149 CheckerManager::CheckObjCMessageFunc(checker, _checkObjCMessage<CHECKER>));
154 template <typename CHECKER>
155 static void _checkCall(void *checker, const CallEvent &msg,
157 ((const CHECKER *)checker)->checkPreCall(msg, C);
161 template <typename CHECKER>
162 static void _register(CHECKER *checker, CheckerManager &mgr) {
163 mgr._registerForPreCall(
164 CheckerManager::CheckCallFunc(checker, _checkCall<CHECKER>));
169 template <typename CHECKER>
170 static void _checkCall(void *checker, const CallEvent &msg,
172 ((const CHECKER *)checker)->checkPostCall(msg, C);
176 template <typename CHECKER>
177 static void _register(CHECKER *checker, CheckerManager &mgr) {
178 mgr._registerForPostCall(
179 CheckerManager::CheckCallFunc(checker, _checkCall<CHECKER>));
184 template <typename CHECKER>
185 static void _checkLocation(void *checker,
186 const SVal &location, bool isLoad, const Stmt *S,
188 ((const CHECKER *)checker)->checkLocation(location, isLoad, S, C);
192 template <typename CHECKER>
193 static void _register(CHECKER *checker, CheckerManager &mgr) {
194 mgr._registerForLocation(
195 CheckerManager::CheckLocationFunc(checker, _checkLocation<CHECKER>));
200 template <typename CHECKER>
201 static void _checkBind(void *checker,
202 const SVal &location, const SVal &val, const Stmt *S,
204 ((const CHECKER *)checker)->checkBind(location, val, S, C);
208 template <typename CHECKER>
209 static void _register(CHECKER *checker, CheckerManager &mgr) {
210 mgr._registerForBind(
211 CheckerManager::CheckBindFunc(checker, _checkBind<CHECKER>));
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);
223 template <typename CHECKER>
224 static void _register(CHECKER *checker, CheckerManager &mgr) {
225 mgr._registerForEndAnalysis(
226 CheckerManager::CheckEndAnalysisFunc(checker, _checkEndAnalysis<CHECKER>));
231 template <typename CHECKER>
232 static void _checkEndFunction(void *checker,
234 ((const CHECKER *)checker)->checkEndFunction(C);
238 template <typename CHECKER>
239 static void _register(CHECKER *checker, CheckerManager &mgr) {
240 mgr._registerForEndFunction(
241 CheckerManager::CheckEndFunctionFunc(checker, _checkEndFunction<CHECKER>));
245 class BranchCondition {
246 template <typename CHECKER>
247 static void _checkBranchCondition(void *checker, const Stmt *Condition,
248 CheckerContext & C) {
249 ((const CHECKER *)checker)->checkBranchCondition(Condition, C);
253 template <typename CHECKER>
254 static void _register(CHECKER *checker, CheckerManager &mgr) {
255 mgr._registerForBranchCondition(
256 CheckerManager::CheckBranchConditionFunc(checker,
257 _checkBranchCondition<CHECKER>));
262 template <typename CHECKER>
263 static void _checkLiveSymbols(void *checker, ProgramStateRef state,
265 ((const CHECKER *)checker)->checkLiveSymbols(state, SR);
269 template <typename CHECKER>
270 static void _register(CHECKER *checker, CheckerManager &mgr) {
271 mgr._registerForLiveSymbols(
272 CheckerManager::CheckLiveSymbolsFunc(checker, _checkLiveSymbols<CHECKER>));
277 template <typename CHECKER>
278 static void _checkDeadSymbols(void *checker,
279 SymbolReaper &SR, CheckerContext &C) {
280 ((const CHECKER *)checker)->checkDeadSymbols(SR, C);
284 template <typename CHECKER>
285 static void _register(CHECKER *checker, CheckerManager &mgr) {
286 mgr._registerForDeadSymbols(
287 CheckerManager::CheckDeadSymbolsFunc(checker, _checkDeadSymbols<CHECKER>));
291 class 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);
303 template <typename CHECKER>
304 static bool _wantsRegionChangeUpdate(void *checker,
305 ProgramStateRef state) {
306 return ((const CHECKER *)checker)->wantsRegionChangeUpdate(state);
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>));
320 class 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) {
331 return ((const CHECKER *)Checker)->checkPointerEscape(State,
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);
345 if (RegularEscape.empty())
348 return ((const CHECKER *)Checker)->checkPointerEscape(State,
355 template <typename CHECKER>
356 static void _register(CHECKER *checker, CheckerManager &mgr) {
357 mgr._registerForPointerEscape(
358 CheckerManager::CheckPointerEscapeFunc(checker,
359 _checkPointerEscape<CHECKER>));
363 class 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) {
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);
385 if (ConstEscape.empty())
388 return ((const CHECKER *)Checker)->checkConstPointerEscape(State,
395 template <typename CHECKER>
396 static void _register(CHECKER *checker, CheckerManager &mgr) {
397 mgr._registerForPointerEscape(
398 CheckerManager::CheckPointerEscapeFunc(checker,
399 _checkConstPointerEscape<CHECKER>));
404 template <typename EVENT>
406 template <typename CHECKER>
407 static void _checkEvent(void *checker, const void *event) {
408 ((const CHECKER *)checker)->checkEvent(*(const EVENT *)event);
411 template <typename CHECKER>
412 static void _register(CHECKER *checker, CheckerManager &mgr) {
413 mgr._registerListenerForEvent<EVENT>(
414 CheckerManager::CheckEventFunc(checker, _checkEvent<CHECKER>));
418 } // end check namespace
423 template <typename CHECKER>
424 static ProgramStateRef _evalAssume(void *checker,
425 ProgramStateRef state,
428 return ((const CHECKER *)checker)->evalAssume(state, cond, assumption);
432 template <typename CHECKER>
433 static void _register(CHECKER *checker, CheckerManager &mgr) {
434 mgr._registerForEvalAssume(
435 CheckerManager::EvalAssumeFunc(checker, _evalAssume<CHECKER>));
440 template <typename CHECKER>
441 static bool _evalCall(void *checker, const CallExpr *CE, CheckerContext &C) {
442 return ((const CHECKER *)checker)->evalCall(CE, C);
446 template <typename CHECKER>
447 static void _register(CHECKER *checker, CheckerManager &mgr) {
448 mgr._registerForEvalCall(
449 CheckerManager::EvalCallFunc(checker, _evalCall<CHECKER>));
453 } // end eval namespace
455 class CheckerBase : public ProgramPointTag {
457 friend class ::clang::ento::CheckerManager;
460 StringRef getTagDescription() const override;
461 CheckName getCheckName() const;
463 /// See CheckerManager::runCheckersForPrintState.
464 virtual void printState(raw_ostream &Out, ProgramStateRef State,
465 const char *NL, const char *Sep) const { }
468 /// Dump checker name to stream.
469 raw_ostream& operator<<(raw_ostream &Out, const CheckerBase &Checker);
471 /// Tag that can use a checker name as a message provider
472 /// (see SimpleProgramPointTag).
473 class CheckerProgramPointTag : public SimpleProgramPointTag {
475 CheckerProgramPointTag(StringRef CheckerName, StringRef Msg);
476 CheckerProgramPointTag(const CheckerBase *Checker, StringRef Msg);
479 template <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>
494 class Checker<check::_VoidCheck>
497 virtual void anchor();
499 static void _register(void *checker, CheckerManager &mgr) { }
502 template <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>
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> {
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);
525 template <typename EVENT>
526 class EventDispatcher {
529 EventDispatcher() : Mgr(nullptr) { }
531 template <typename CHECKER>
532 static void _register(CHECKER *checker, CheckerManager &mgr) {
533 mgr._registerDispatcherForEvent<EVENT>();
534 static_cast<EventDispatcher<EVENT> *>(checker)->Mgr = &mgr;
537 void dispatchEvent(const EVENT &event) const {
538 Mgr->_dispatchEvent(event);
542 /// \brief We dereferenced a location that may be null.
543 struct ImplicitNullDerefEvent {
546 ExplodedNode *SinkNode;
550 /// \brief A helper class which wraps a boolean value set to false by default.
552 /// This class should behave exactly like 'bool' except that it doesn't need to
553 /// be explicitly initialized.
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; }
562 } // end ento namespace
564 } // end clang namespace