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_STATICANALYZER_CORE_CHECKER_H
15 #define LLVM_CLANG_STATICANALYZER_CORE_CHECKER_H
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"
28 template <typename DECL>
30 template <typename CHECKER>
31 static void _checkDecl(void *checker, const Decl *D, AnalysisManager& mgr,
33 ((const CHECKER *)checker)->checkASTDecl(cast<DECL>(D), mgr, BR);
36 static bool _handlesDecl(const Decl *D) {
40 template <typename CHECKER>
41 static void _register(CHECKER *checker, CheckerManager &mgr) {
42 mgr._registerForDecl(CheckerManager::CheckDeclFunc(checker,
49 template <typename CHECKER>
50 static void _checkBody(void *checker, const Decl *D, AnalysisManager& mgr,
52 ((const CHECKER *)checker)->checkASTCodeBody(D, mgr, BR);
56 template <typename CHECKER>
57 static void _register(CHECKER *checker, CheckerManager &mgr) {
58 mgr._registerForBody(CheckerManager::CheckDeclFunc(checker,
59 _checkBody<CHECKER>));
63 class EndOfTranslationUnit {
64 template <typename CHECKER>
65 static void _checkEndOfTranslationUnit(void *checker,
66 const TranslationUnitDecl *TU,
69 ((const CHECKER *)checker)->checkEndOfTranslationUnit(TU, mgr, BR);
73 template <typename CHECKER>
74 static void _register(CHECKER *checker, CheckerManager &mgr){
75 mgr._registerForEndOfTranslationUnit(
76 CheckerManager::CheckEndOfTranslationUnit(checker,
77 _checkEndOfTranslationUnit<CHECKER>));
81 template <typename STMT>
83 template <typename CHECKER>
84 static void _checkStmt(void *checker, const Stmt *S, CheckerContext &C) {
85 ((const CHECKER *)checker)->checkPreStmt(cast<STMT>(S), C);
88 static bool _handlesStmt(const Stmt *S) {
92 template <typename CHECKER>
93 static void _register(CHECKER *checker, CheckerManager &mgr) {
94 mgr._registerForPreStmt(CheckerManager::CheckStmtFunc(checker,
100 template <typename STMT>
102 template <typename CHECKER>
103 static void _checkStmt(void *checker, const Stmt *S, CheckerContext &C) {
104 ((const CHECKER *)checker)->checkPostStmt(cast<STMT>(S), C);
107 static bool _handlesStmt(const Stmt *S) {
111 template <typename CHECKER>
112 static void _register(CHECKER *checker, CheckerManager &mgr) {
113 mgr._registerForPostStmt(CheckerManager::CheckStmtFunc(checker,
114 _checkStmt<CHECKER>),
119 class PreObjCMessage {
120 template <typename CHECKER>
121 static void _checkObjCMessage(void *checker, const ObjCMethodCall &msg,
123 ((const CHECKER *)checker)->checkPreObjCMessage(msg, C);
127 template <typename CHECKER>
128 static void _register(CHECKER *checker, CheckerManager &mgr) {
129 mgr._registerForPreObjCMessage(
130 CheckerManager::CheckObjCMessageFunc(checker, _checkObjCMessage<CHECKER>));
134 class ObjCMessageNil {
135 template <typename CHECKER>
136 static void _checkObjCMessage(void *checker, const ObjCMethodCall &msg,
138 ((const CHECKER *)checker)->checkObjCMessageNil(msg, C);
142 template <typename CHECKER>
143 static void _register(CHECKER *checker, CheckerManager &mgr) {
144 mgr._registerForObjCMessageNil(
145 CheckerManager::CheckObjCMessageFunc(checker, _checkObjCMessage<CHECKER>));
149 class PostObjCMessage {
150 template <typename CHECKER>
151 static void _checkObjCMessage(void *checker, const ObjCMethodCall &msg,
153 ((const CHECKER *)checker)->checkPostObjCMessage(msg, C);
157 template <typename CHECKER>
158 static void _register(CHECKER *checker, CheckerManager &mgr) {
159 mgr._registerForPostObjCMessage(
160 CheckerManager::CheckObjCMessageFunc(checker, _checkObjCMessage<CHECKER>));
165 template <typename CHECKER>
166 static void _checkCall(void *checker, const CallEvent &msg,
168 ((const CHECKER *)checker)->checkPreCall(msg, C);
172 template <typename CHECKER>
173 static void _register(CHECKER *checker, CheckerManager &mgr) {
174 mgr._registerForPreCall(
175 CheckerManager::CheckCallFunc(checker, _checkCall<CHECKER>));
180 template <typename CHECKER>
181 static void _checkCall(void *checker, const CallEvent &msg,
183 ((const CHECKER *)checker)->checkPostCall(msg, C);
187 template <typename CHECKER>
188 static void _register(CHECKER *checker, CheckerManager &mgr) {
189 mgr._registerForPostCall(
190 CheckerManager::CheckCallFunc(checker, _checkCall<CHECKER>));
195 template <typename CHECKER>
196 static void _checkLocation(void *checker,
197 const SVal &location, bool isLoad, const Stmt *S,
199 ((const CHECKER *)checker)->checkLocation(location, isLoad, S, C);
203 template <typename CHECKER>
204 static void _register(CHECKER *checker, CheckerManager &mgr) {
205 mgr._registerForLocation(
206 CheckerManager::CheckLocationFunc(checker, _checkLocation<CHECKER>));
211 template <typename CHECKER>
212 static void _checkBind(void *checker,
213 const SVal &location, const SVal &val, const Stmt *S,
215 ((const CHECKER *)checker)->checkBind(location, val, S, C);
219 template <typename CHECKER>
220 static void _register(CHECKER *checker, CheckerManager &mgr) {
221 mgr._registerForBind(
222 CheckerManager::CheckBindFunc(checker, _checkBind<CHECKER>));
227 template <typename CHECKER>
228 static void _checkEndAnalysis(void *checker, ExplodedGraph &G,
229 BugReporter &BR, ExprEngine &Eng) {
230 ((const CHECKER *)checker)->checkEndAnalysis(G, BR, Eng);
234 template <typename CHECKER>
235 static void _register(CHECKER *checker, CheckerManager &mgr) {
236 mgr._registerForEndAnalysis(
237 CheckerManager::CheckEndAnalysisFunc(checker, _checkEndAnalysis<CHECKER>));
241 class BeginFunction {
242 template <typename CHECKER>
243 static void _checkBeginFunction(void *checker, CheckerContext &C) {
244 ((const CHECKER *)checker)->checkBeginFunction(C);
248 template <typename CHECKER>
249 static void _register(CHECKER *checker, CheckerManager &mgr) {
250 mgr._registerForBeginFunction(CheckerManager::CheckBeginFunctionFunc(
251 checker, _checkBeginFunction<CHECKER>));
256 template <typename CHECKER>
257 static void _checkEndFunction(void *checker,
259 ((const CHECKER *)checker)->checkEndFunction(C);
263 template <typename CHECKER>
264 static void _register(CHECKER *checker, CheckerManager &mgr) {
265 mgr._registerForEndFunction(
266 CheckerManager::CheckEndFunctionFunc(checker, _checkEndFunction<CHECKER>));
270 class BranchCondition {
271 template <typename CHECKER>
272 static void _checkBranchCondition(void *checker, const Stmt *Condition,
273 CheckerContext & C) {
274 ((const CHECKER *)checker)->checkBranchCondition(Condition, C);
278 template <typename CHECKER>
279 static void _register(CHECKER *checker, CheckerManager &mgr) {
280 mgr._registerForBranchCondition(
281 CheckerManager::CheckBranchConditionFunc(checker,
282 _checkBranchCondition<CHECKER>));
287 template <typename CHECKER>
288 static void _checkLiveSymbols(void *checker, ProgramStateRef state,
290 ((const CHECKER *)checker)->checkLiveSymbols(state, SR);
294 template <typename CHECKER>
295 static void _register(CHECKER *checker, CheckerManager &mgr) {
296 mgr._registerForLiveSymbols(
297 CheckerManager::CheckLiveSymbolsFunc(checker, _checkLiveSymbols<CHECKER>));
302 template <typename CHECKER>
303 static void _checkDeadSymbols(void *checker,
304 SymbolReaper &SR, CheckerContext &C) {
305 ((const CHECKER *)checker)->checkDeadSymbols(SR, C);
309 template <typename CHECKER>
310 static void _register(CHECKER *checker, CheckerManager &mgr) {
311 mgr._registerForDeadSymbols(
312 CheckerManager::CheckDeadSymbolsFunc(checker, _checkDeadSymbols<CHECKER>));
316 class RegionChanges {
317 template <typename CHECKER>
318 static ProgramStateRef
319 _checkRegionChanges(void *checker,
320 ProgramStateRef state,
321 const InvalidatedSymbols *invalidated,
322 ArrayRef<const MemRegion *> Explicits,
323 ArrayRef<const MemRegion *> Regions,
324 const LocationContext *LCtx,
325 const CallEvent *Call) {
326 return ((const CHECKER *) checker)->checkRegionChanges(state, invalidated,
332 template <typename CHECKER>
333 static void _register(CHECKER *checker, CheckerManager &mgr) {
334 mgr._registerForRegionChanges(
335 CheckerManager::CheckRegionChangesFunc(checker,
336 _checkRegionChanges<CHECKER>));
340 class PointerEscape {
341 template <typename CHECKER>
342 static ProgramStateRef
343 _checkPointerEscape(void *Checker,
344 ProgramStateRef State,
345 const InvalidatedSymbols &Escaped,
346 const CallEvent *Call,
347 PointerEscapeKind Kind,
348 RegionAndSymbolInvalidationTraits *ETraits) {
351 return ((const CHECKER *)Checker)->checkPointerEscape(State,
356 InvalidatedSymbols RegularEscape;
357 for (InvalidatedSymbols::const_iterator I = Escaped.begin(),
358 E = Escaped.end(); I != E; ++I)
359 if (!ETraits->hasTrait(*I,
360 RegionAndSymbolInvalidationTraits::TK_PreserveContents) &&
361 !ETraits->hasTrait(*I,
362 RegionAndSymbolInvalidationTraits::TK_SuppressEscape))
363 RegularEscape.insert(*I);
365 if (RegularEscape.empty())
368 return ((const CHECKER *)Checker)->checkPointerEscape(State,
375 template <typename CHECKER>
376 static void _register(CHECKER *checker, CheckerManager &mgr) {
377 mgr._registerForPointerEscape(
378 CheckerManager::CheckPointerEscapeFunc(checker,
379 _checkPointerEscape<CHECKER>));
383 class ConstPointerEscape {
384 template <typename CHECKER>
385 static ProgramStateRef
386 _checkConstPointerEscape(void *Checker,
387 ProgramStateRef State,
388 const InvalidatedSymbols &Escaped,
389 const CallEvent *Call,
390 PointerEscapeKind Kind,
391 RegionAndSymbolInvalidationTraits *ETraits) {
396 InvalidatedSymbols ConstEscape;
397 for (InvalidatedSymbols::const_iterator I = Escaped.begin(),
398 E = Escaped.end(); I != E; ++I)
399 if (ETraits->hasTrait(*I,
400 RegionAndSymbolInvalidationTraits::TK_PreserveContents) &&
401 !ETraits->hasTrait(*I,
402 RegionAndSymbolInvalidationTraits::TK_SuppressEscape))
403 ConstEscape.insert(*I);
405 if (ConstEscape.empty())
408 return ((const CHECKER *)Checker)->checkConstPointerEscape(State,
415 template <typename CHECKER>
416 static void _register(CHECKER *checker, CheckerManager &mgr) {
417 mgr._registerForPointerEscape(
418 CheckerManager::CheckPointerEscapeFunc(checker,
419 _checkConstPointerEscape<CHECKER>));
424 template <typename EVENT>
426 template <typename CHECKER>
427 static void _checkEvent(void *checker, const void *event) {
428 ((const CHECKER *)checker)->checkEvent(*(const EVENT *)event);
431 template <typename CHECKER>
432 static void _register(CHECKER *checker, CheckerManager &mgr) {
433 mgr._registerListenerForEvent<EVENT>(
434 CheckerManager::CheckEventFunc(checker, _checkEvent<CHECKER>));
438 } // end check namespace
443 template <typename CHECKER>
444 static ProgramStateRef _evalAssume(void *checker,
445 ProgramStateRef state,
448 return ((const CHECKER *)checker)->evalAssume(state, cond, assumption);
452 template <typename CHECKER>
453 static void _register(CHECKER *checker, CheckerManager &mgr) {
454 mgr._registerForEvalAssume(
455 CheckerManager::EvalAssumeFunc(checker, _evalAssume<CHECKER>));
460 template <typename CHECKER>
461 static bool _evalCall(void *checker, const CallExpr *CE, CheckerContext &C) {
462 return ((const CHECKER *)checker)->evalCall(CE, C);
466 template <typename CHECKER>
467 static void _register(CHECKER *checker, CheckerManager &mgr) {
468 mgr._registerForEvalCall(
469 CheckerManager::EvalCallFunc(checker, _evalCall<CHECKER>));
473 } // end eval namespace
475 class CheckerBase : public ProgramPointTag {
477 friend class ::clang::ento::CheckerManager;
480 StringRef getTagDescription() const override;
481 CheckName getCheckName() const;
483 /// See CheckerManager::runCheckersForPrintState.
484 virtual void printState(raw_ostream &Out, ProgramStateRef State,
485 const char *NL, const char *Sep) const { }
488 /// Dump checker name to stream.
489 raw_ostream& operator<<(raw_ostream &Out, const CheckerBase &Checker);
491 /// Tag that can use a checker name as a message provider
492 /// (see SimpleProgramPointTag).
493 class CheckerProgramPointTag : public SimpleProgramPointTag {
495 CheckerProgramPointTag(StringRef CheckerName, StringRef Msg);
496 CheckerProgramPointTag(const CheckerBase *Checker, StringRef Msg);
499 template <typename CHECK1, typename... CHECKs>
500 class Checker : public CHECK1, public CHECKs..., public CheckerBase {
502 template <typename CHECKER>
503 static void _register(CHECKER *checker, CheckerManager &mgr) {
504 CHECK1::_register(checker, mgr);
505 Checker<CHECKs...>::_register(checker, mgr);
509 template <typename CHECK1>
510 class Checker<CHECK1> : public CHECK1, public CheckerBase {
512 template <typename CHECKER>
513 static void _register(CHECKER *checker, CheckerManager &mgr) {
514 CHECK1::_register(checker, mgr);
518 template <typename EVENT>
519 class EventDispatcher {
522 EventDispatcher() : Mgr(nullptr) { }
524 template <typename CHECKER>
525 static void _register(CHECKER *checker, CheckerManager &mgr) {
526 mgr._registerDispatcherForEvent<EVENT>();
527 static_cast<EventDispatcher<EVENT> *>(checker)->Mgr = &mgr;
530 void dispatchEvent(const EVENT &event) const {
531 Mgr->_dispatchEvent(event);
535 /// \brief We dereferenced a location that may be null.
536 struct ImplicitNullDerefEvent {
539 ExplodedNode *SinkNode;
541 // When true, the dereference is in the source code directly. When false, the
542 // dereference might happen later (for example pointer passed to a parameter
543 // that is marked with nonnull attribute.)
544 bool IsDirectDereference;
547 /// \brief A helper class which wraps a boolean value set to false by default.
549 /// This class should behave exactly like 'bool' except that it doesn't need to
550 /// be explicitly initialized.
553 DefaultBool() : val(false) {}
554 /*implicit*/ operator bool&() { return val; }
555 /*implicit*/ operator const bool&() const { return val; }
556 DefaultBool &operator=(bool b) { val = b; return *this; }
559 } // end ento namespace
561 } // end clang namespace