1//== Checker.h - Registration mechanism for checkers -------------*- C++ -*--=//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This file defines Checker, used to create and register checkers.
10//
11//===----------------------------------------------------------------------===//
12
13#ifndef LLVM_CLANG_STATICANALYZER_CORE_CHECKER_H
14#define LLVM_CLANG_STATICANALYZER_CORE_CHECKER_H
15
16#include "clang/Analysis/ProgramPoint.h"
17#include "clang/Basic/LangOptions.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
28template <typename DECL>
29class ASTDecl {
30 template <typename CHECKER>
31 static void _checkDecl(void *checker, const Decl *D, AnalysisManager& mgr,
32 BugReporter &BR) {
33 ((const CHECKER *)checker)->checkASTDecl(cast<DECL>(D), mgr, BR);
34 }
35
36 static bool _handlesDecl(const Decl *D) {
37 return isa<DECL>(D);
38 }
39public:
40 template <typename CHECKER>
41 static void _register(CHECKER *checker, CheckerManager &mgr) {
42 mgr._registerForDecl(checkfn: CheckerManager::CheckDeclFunc(checker,
43 _checkDecl<CHECKER>),
44 isForDeclFn: _handlesDecl);
45 }
46};
47
48class ASTCodeBody {
49 template <typename CHECKER>
50 static void _checkBody(void *checker, const Decl *D, AnalysisManager& mgr,
51 BugReporter &BR) {
52 ((const CHECKER *)checker)->checkASTCodeBody(D, mgr, BR);
53 }
54
55public:
56 template <typename CHECKER>
57 static void _register(CHECKER *checker, CheckerManager &mgr) {
58 mgr._registerForBody(checkfn: CheckerManager::CheckDeclFunc(checker,
59 _checkBody<CHECKER>));
60 }
61};
62
63class EndOfTranslationUnit {
64 template <typename CHECKER>
65 static void _checkEndOfTranslationUnit(void *checker,
66 const TranslationUnitDecl *TU,
67 AnalysisManager& mgr,
68 BugReporter &BR) {
69 ((const CHECKER *)checker)->checkEndOfTranslationUnit(TU, mgr, BR);
70 }
71
72public:
73 template <typename CHECKER>
74 static void _register(CHECKER *checker, CheckerManager &mgr){
75 mgr._registerForEndOfTranslationUnit(
76 checkfn: CheckerManager::CheckEndOfTranslationUnit(checker,
77 _checkEndOfTranslationUnit<CHECKER>));
78 }
79};
80
81template <typename STMT>
82class PreStmt {
83 template <typename CHECKER>
84 static void _checkStmt(void *checker, const Stmt *S, CheckerContext &C) {
85 ((const CHECKER *)checker)->checkPreStmt(cast<STMT>(S), C);
86 }
87
88 static bool _handlesStmt(const Stmt *S) {
89 return isa<STMT>(S);
90 }
91public:
92 template <typename CHECKER>
93 static void _register(CHECKER *checker, CheckerManager &mgr) {
94 mgr._registerForPreStmt(checkfn: CheckerManager::CheckStmtFunc(checker,
95 _checkStmt<CHECKER>),
96 isForStmtFn: _handlesStmt);
97 }
98};
99
100template <typename STMT>
101class PostStmt {
102 template <typename CHECKER>
103 static void _checkStmt(void *checker, const Stmt *S, CheckerContext &C) {
104 ((const CHECKER *)checker)->checkPostStmt(cast<STMT>(S), C);
105 }
106
107 static bool _handlesStmt(const Stmt *S) {
108 return isa<STMT>(S);
109 }
110public:
111 template <typename CHECKER>
112 static void _register(CHECKER *checker, CheckerManager &mgr) {
113 mgr._registerForPostStmt(checkfn: CheckerManager::CheckStmtFunc(checker,
114 _checkStmt<CHECKER>),
115 isForStmtFn: _handlesStmt);
116 }
117};
118
119class PreObjCMessage {
120 template <typename CHECKER>
121 static void _checkObjCMessage(void *checker, const ObjCMethodCall &msg,
122 CheckerContext &C) {
123 ((const CHECKER *)checker)->checkPreObjCMessage(msg, C);
124 }
125
126public:
127 template <typename CHECKER>
128 static void _register(CHECKER *checker, CheckerManager &mgr) {
129 mgr._registerForPreObjCMessage(
130 checkfn: CheckerManager::CheckObjCMessageFunc(checker, _checkObjCMessage<CHECKER>));
131 }
132};
133
134class ObjCMessageNil {
135 template <typename CHECKER>
136 static void _checkObjCMessage(void *checker, const ObjCMethodCall &msg,
137 CheckerContext &C) {
138 ((const CHECKER *)checker)->checkObjCMessageNil(msg, C);
139 }
140
141public:
142 template <typename CHECKER>
143 static void _register(CHECKER *checker, CheckerManager &mgr) {
144 mgr._registerForObjCMessageNil(
145 checkfn: CheckerManager::CheckObjCMessageFunc(checker, _checkObjCMessage<CHECKER>));
146 }
147};
148
149class PostObjCMessage {
150 template <typename CHECKER>
151 static void _checkObjCMessage(void *checker, const ObjCMethodCall &msg,
152 CheckerContext &C) {
153 ((const CHECKER *)checker)->checkPostObjCMessage(msg, C);
154 }
155
156public:
157 template <typename CHECKER>
158 static void _register(CHECKER *checker, CheckerManager &mgr) {
159 mgr._registerForPostObjCMessage(
160 checkfn: CheckerManager::CheckObjCMessageFunc(checker, _checkObjCMessage<CHECKER>));
161 }
162};
163
164class PreCall {
165 template <typename CHECKER>
166 static void _checkCall(void *checker, const CallEvent &msg,
167 CheckerContext &C) {
168 ((const CHECKER *)checker)->checkPreCall(msg, C);
169 }
170
171public:
172 template <typename CHECKER>
173 static void _register(CHECKER *checker, CheckerManager &mgr) {
174 mgr._registerForPreCall(
175 checkfn: CheckerManager::CheckCallFunc(checker, _checkCall<CHECKER>));
176 }
177};
178
179class PostCall {
180 template <typename CHECKER>
181 static void _checkCall(void *checker, const CallEvent &msg,
182 CheckerContext &C) {
183 ((const CHECKER *)checker)->checkPostCall(msg, C);
184 }
185
186public:
187 template <typename CHECKER>
188 static void _register(CHECKER *checker, CheckerManager &mgr) {
189 mgr._registerForPostCall(
190 checkfn: CheckerManager::CheckCallFunc(checker, _checkCall<CHECKER>));
191 }
192};
193
194class Location {
195 template <typename CHECKER>
196 static void _checkLocation(void *checker, SVal location, bool isLoad,
197 const Stmt *S, CheckerContext &C) {
198 ((const CHECKER *)checker)->checkLocation(location, isLoad, S, C);
199 }
200
201public:
202 template <typename CHECKER>
203 static void _register(CHECKER *checker, CheckerManager &mgr) {
204 mgr._registerForLocation(
205 checkfn: CheckerManager::CheckLocationFunc(checker, _checkLocation<CHECKER>));
206 }
207};
208
209class Bind {
210 template <typename CHECKER>
211 static void _checkBind(void *checker, SVal location, SVal val, const Stmt *S,
212 CheckerContext &C) {
213 ((const CHECKER *)checker)->checkBind(location, val, S, C);
214 }
215
216public:
217 template <typename CHECKER>
218 static void _register(CHECKER *checker, CheckerManager &mgr) {
219 mgr._registerForBind(
220 checkfn: CheckerManager::CheckBindFunc(checker, _checkBind<CHECKER>));
221 }
222};
223
224class EndAnalysis {
225 template <typename CHECKER>
226 static void _checkEndAnalysis(void *checker, ExplodedGraph &G,
227 BugReporter &BR, ExprEngine &Eng) {
228 ((const CHECKER *)checker)->checkEndAnalysis(G, BR, Eng);
229 }
230
231public:
232 template <typename CHECKER>
233 static void _register(CHECKER *checker, CheckerManager &mgr) {
234 mgr._registerForEndAnalysis(
235 checkfn: CheckerManager::CheckEndAnalysisFunc(checker, _checkEndAnalysis<CHECKER>));
236 }
237};
238
239class BeginFunction {
240 template <typename CHECKER>
241 static void _checkBeginFunction(void *checker, CheckerContext &C) {
242 ((const CHECKER *)checker)->checkBeginFunction(C);
243 }
244
245public:
246 template <typename CHECKER>
247 static void _register(CHECKER *checker, CheckerManager &mgr) {
248 mgr._registerForBeginFunction(checkfn: CheckerManager::CheckBeginFunctionFunc(
249 checker, _checkBeginFunction<CHECKER>));
250 }
251};
252
253class EndFunction {
254 template <typename CHECKER>
255 static void _checkEndFunction(void *checker, const ReturnStmt *RS,
256 CheckerContext &C) {
257 ((const CHECKER *)checker)->checkEndFunction(RS, C);
258 }
259
260public:
261 template <typename CHECKER>
262 static void _register(CHECKER *checker, CheckerManager &mgr) {
263 mgr._registerForEndFunction(
264 checkfn: CheckerManager::CheckEndFunctionFunc(checker, _checkEndFunction<CHECKER>));
265 }
266};
267
268class BranchCondition {
269 template <typename CHECKER>
270 static void _checkBranchCondition(void *checker, const Stmt *Condition,
271 CheckerContext & C) {
272 ((const CHECKER *)checker)->checkBranchCondition(Condition, C);
273 }
274
275public:
276 template <typename CHECKER>
277 static void _register(CHECKER *checker, CheckerManager &mgr) {
278 mgr._registerForBranchCondition(
279 checkfn: CheckerManager::CheckBranchConditionFunc(checker,
280 _checkBranchCondition<CHECKER>));
281 }
282};
283
284class NewAllocator {
285 template <typename CHECKER>
286 static void _checkNewAllocator(void *checker, const CXXAllocatorCall &Call,
287 CheckerContext &C) {
288 ((const CHECKER *)checker)->checkNewAllocator(Call, C);
289 }
290
291public:
292 template <typename CHECKER>
293 static void _register(CHECKER *checker, CheckerManager &mgr) {
294 mgr._registerForNewAllocator(
295 checkfn: CheckerManager::CheckNewAllocatorFunc(checker,
296 _checkNewAllocator<CHECKER>));
297 }
298};
299
300class LiveSymbols {
301 template <typename CHECKER>
302 static void _checkLiveSymbols(void *checker, ProgramStateRef state,
303 SymbolReaper &SR) {
304 ((const CHECKER *)checker)->checkLiveSymbols(state, SR);
305 }
306
307public:
308 template <typename CHECKER>
309 static void _register(CHECKER *checker, CheckerManager &mgr) {
310 mgr._registerForLiveSymbols(
311 checkfn: CheckerManager::CheckLiveSymbolsFunc(checker, _checkLiveSymbols<CHECKER>));
312 }
313};
314
315class DeadSymbols {
316 template <typename CHECKER>
317 static void _checkDeadSymbols(void *checker,
318 SymbolReaper &SR, CheckerContext &C) {
319 ((const CHECKER *)checker)->checkDeadSymbols(SR, C);
320 }
321
322public:
323 template <typename CHECKER>
324 static void _register(CHECKER *checker, CheckerManager &mgr) {
325 mgr._registerForDeadSymbols(
326 checkfn: CheckerManager::CheckDeadSymbolsFunc(checker, _checkDeadSymbols<CHECKER>));
327 }
328};
329
330class RegionChanges {
331 template <typename CHECKER>
332 static ProgramStateRef
333 _checkRegionChanges(void *checker,
334 ProgramStateRef state,
335 const InvalidatedSymbols *invalidated,
336 ArrayRef<const MemRegion *> Explicits,
337 ArrayRef<const MemRegion *> Regions,
338 const LocationContext *LCtx,
339 const CallEvent *Call) {
340 return ((const CHECKER *) checker)->checkRegionChanges(state, invalidated,
341 Explicits, Regions,
342 LCtx, Call);
343 }
344
345public:
346 template <typename CHECKER>
347 static void _register(CHECKER *checker, CheckerManager &mgr) {
348 mgr._registerForRegionChanges(
349 checkfn: CheckerManager::CheckRegionChangesFunc(checker,
350 _checkRegionChanges<CHECKER>));
351 }
352};
353
354class PointerEscape {
355 template <typename CHECKER>
356 static ProgramStateRef
357 _checkPointerEscape(void *Checker,
358 ProgramStateRef State,
359 const InvalidatedSymbols &Escaped,
360 const CallEvent *Call,
361 PointerEscapeKind Kind,
362 RegionAndSymbolInvalidationTraits *ETraits) {
363
364 if (!ETraits)
365 return ((const CHECKER *)Checker)->checkPointerEscape(State,
366 Escaped,
367 Call,
368 Kind);
369
370 InvalidatedSymbols RegularEscape;
371 for (SymbolRef Sym : Escaped)
372 if (!ETraits->hasTrait(
373 Sym, IK: RegionAndSymbolInvalidationTraits::TK_PreserveContents) &&
374 !ETraits->hasTrait(
375 Sym, IK: RegionAndSymbolInvalidationTraits::TK_SuppressEscape))
376 RegularEscape.insert(V: Sym);
377
378 if (RegularEscape.empty())
379 return State;
380
381 return ((const CHECKER *)Checker)->checkPointerEscape(State,
382 RegularEscape,
383 Call,
384 Kind);
385 }
386
387public:
388 template <typename CHECKER>
389 static void _register(CHECKER *checker, CheckerManager &mgr) {
390 mgr._registerForPointerEscape(
391 checkfn: CheckerManager::CheckPointerEscapeFunc(checker,
392 _checkPointerEscape<CHECKER>));
393 }
394};
395
396class ConstPointerEscape {
397 template <typename CHECKER>
398 static ProgramStateRef
399 _checkConstPointerEscape(void *Checker,
400 ProgramStateRef State,
401 const InvalidatedSymbols &Escaped,
402 const CallEvent *Call,
403 PointerEscapeKind Kind,
404 RegionAndSymbolInvalidationTraits *ETraits) {
405
406 if (!ETraits)
407 return State;
408
409 InvalidatedSymbols ConstEscape;
410 for (SymbolRef Sym : Escaped) {
411 if (ETraits->hasTrait(
412 Sym, IK: RegionAndSymbolInvalidationTraits::TK_PreserveContents) &&
413 !ETraits->hasTrait(
414 Sym, IK: RegionAndSymbolInvalidationTraits::TK_SuppressEscape))
415 ConstEscape.insert(V: Sym);
416 }
417
418 if (ConstEscape.empty())
419 return State;
420
421 return ((const CHECKER *)Checker)->checkConstPointerEscape(State,
422 ConstEscape,
423 Call,
424 Kind);
425 }
426
427public:
428 template <typename CHECKER>
429 static void _register(CHECKER *checker, CheckerManager &mgr) {
430 mgr._registerForPointerEscape(
431 checkfn: CheckerManager::CheckPointerEscapeFunc(checker,
432 _checkConstPointerEscape<CHECKER>));
433 }
434};
435
436
437template <typename EVENT>
438class Event {
439 template <typename CHECKER>
440 static void _checkEvent(void *checker, const void *event) {
441 ((const CHECKER *)checker)->checkEvent(*(const EVENT *)event);
442 }
443public:
444 template <typename CHECKER>
445 static void _register(CHECKER *checker, CheckerManager &mgr) {
446 mgr._registerListenerForEvent<EVENT>(
447 CheckerManager::CheckEventFunc(checker, _checkEvent<CHECKER>));
448 }
449};
450
451} // end check namespace
452
453namespace eval {
454
455class Assume {
456 template <typename CHECKER>
457 static ProgramStateRef _evalAssume(void *checker, ProgramStateRef state,
458 SVal cond, bool assumption) {
459 return ((const CHECKER *)checker)->evalAssume(state, cond, assumption);
460 }
461
462public:
463 template <typename CHECKER>
464 static void _register(CHECKER *checker, CheckerManager &mgr) {
465 mgr._registerForEvalAssume(
466 checkfn: CheckerManager::EvalAssumeFunc(checker, _evalAssume<CHECKER>));
467 }
468};
469
470class Call {
471 template <typename CHECKER>
472 static bool _evalCall(void *checker, const CallEvent &Call,
473 CheckerContext &C) {
474 return ((const CHECKER *)checker)->evalCall(Call, C);
475 }
476
477public:
478 template <typename CHECKER>
479 static void _register(CHECKER *checker, CheckerManager &mgr) {
480 mgr._registerForEvalCall(
481 checkfn: CheckerManager::EvalCallFunc(checker, _evalCall<CHECKER>));
482 }
483};
484
485} // end eval namespace
486
487class CheckerBase : public ProgramPointTag {
488 CheckerNameRef Name;
489 friend class ::clang::ento::CheckerManager;
490
491public:
492 StringRef getTagDescription() const override;
493 CheckerNameRef getCheckerName() const;
494
495 /// See CheckerManager::runCheckersForPrintState.
496 virtual void printState(raw_ostream &Out, ProgramStateRef State,
497 const char *NL, const char *Sep) const { }
498};
499
500/// Dump checker name to stream.
501raw_ostream& operator<<(raw_ostream &Out, const CheckerBase &Checker);
502
503/// Tag that can use a checker name as a message provider
504/// (see SimpleProgramPointTag).
505class CheckerProgramPointTag : public SimpleProgramPointTag {
506public:
507 CheckerProgramPointTag(StringRef CheckerName, StringRef Msg);
508 CheckerProgramPointTag(const CheckerBase *Checker, StringRef Msg);
509};
510
511template <typename CHECK1, typename... CHECKs>
512class Checker : public CHECK1, public CHECKs..., public CheckerBase {
513public:
514 template <typename CHECKER>
515 static void _register(CHECKER *checker, CheckerManager &mgr) {
516 CHECK1::_register(checker, mgr);
517 Checker<CHECKs...>::_register(checker, mgr);
518 }
519};
520
521template <typename CHECK1>
522class Checker<CHECK1> : public CHECK1, public CheckerBase {
523public:
524 template <typename CHECKER>
525 static void _register(CHECKER *checker, CheckerManager &mgr) {
526 CHECK1::_register(checker, mgr);
527 }
528};
529
530template <typename EVENT>
531class EventDispatcher {
532 CheckerManager *Mgr = nullptr;
533public:
534 EventDispatcher() = default;
535
536 template <typename CHECKER>
537 static void _register(CHECKER *checker, CheckerManager &mgr) {
538 mgr._registerDispatcherForEvent<EVENT>();
539 static_cast<EventDispatcher<EVENT> *>(checker)->Mgr = &mgr;
540 }
541
542 void dispatchEvent(const EVENT &event) const {
543 Mgr->_dispatchEvent(event);
544 }
545};
546
547/// We dereferenced a location that may be null.
548struct ImplicitNullDerefEvent {
549 SVal Location;
550 bool IsLoad;
551 ExplodedNode *SinkNode;
552 BugReporter *BR;
553 // When true, the dereference is in the source code directly. When false, the
554 // dereference might happen later (for example pointer passed to a parameter
555 // that is marked with nonnull attribute.)
556 bool IsDirectDereference;
557
558 static int Tag;
559};
560
561} // end ento namespace
562
563} // end clang namespace
564
565#endif
566

source code of clang/include/clang/StaticAnalyzer/Core/Checker.h