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