File indexing completed on 2026-05-10 08:37:10
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013 #ifndef LLVM_CLANG_STATICANALYZER_CORE_CHECKER_H
0014 #define LLVM_CLANG_STATICANALYZER_CORE_CHECKER_H
0015
0016 #include "clang/Analysis/ProgramPoint.h"
0017 #include "clang/Basic/LangOptions.h"
0018 #include "clang/StaticAnalyzer/Core/CheckerManager.h"
0019 #include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h"
0020 #include "llvm/Support/Casting.h"
0021
0022 namespace clang {
0023 namespace ento {
0024 class BugReporter;
0025
0026 namespace check {
0027
0028 template <typename DECL>
0029 class ASTDecl {
0030 template <typename CHECKER>
0031 static void _checkDecl(void *checker, const Decl *D, AnalysisManager& mgr,
0032 BugReporter &BR) {
0033 ((const CHECKER *)checker)->checkASTDecl(cast<DECL>(D), mgr, BR);
0034 }
0035
0036 static bool _handlesDecl(const Decl *D) {
0037 return isa<DECL>(D);
0038 }
0039 public:
0040 template <typename CHECKER>
0041 static void _register(CHECKER *checker, CheckerManager &mgr) {
0042 mgr._registerForDecl(CheckerManager::CheckDeclFunc(checker,
0043 _checkDecl<CHECKER>),
0044 _handlesDecl);
0045 }
0046 };
0047
0048 class ASTCodeBody {
0049 template <typename CHECKER>
0050 static void _checkBody(void *checker, const Decl *D, AnalysisManager& mgr,
0051 BugReporter &BR) {
0052 ((const CHECKER *)checker)->checkASTCodeBody(D, mgr, BR);
0053 }
0054
0055 public:
0056 template <typename CHECKER>
0057 static void _register(CHECKER *checker, CheckerManager &mgr) {
0058 mgr._registerForBody(CheckerManager::CheckDeclFunc(checker,
0059 _checkBody<CHECKER>));
0060 }
0061 };
0062
0063 class EndOfTranslationUnit {
0064 template <typename CHECKER>
0065 static void _checkEndOfTranslationUnit(void *checker,
0066 const TranslationUnitDecl *TU,
0067 AnalysisManager& mgr,
0068 BugReporter &BR) {
0069 ((const CHECKER *)checker)->checkEndOfTranslationUnit(TU, mgr, BR);
0070 }
0071
0072 public:
0073 template <typename CHECKER>
0074 static void _register(CHECKER *checker, CheckerManager &mgr){
0075 mgr._registerForEndOfTranslationUnit(
0076 CheckerManager::CheckEndOfTranslationUnit(checker,
0077 _checkEndOfTranslationUnit<CHECKER>));
0078 }
0079 };
0080
0081 template <typename STMT>
0082 class PreStmt {
0083 template <typename CHECKER>
0084 static void _checkStmt(void *checker, const Stmt *S, CheckerContext &C) {
0085 ((const CHECKER *)checker)->checkPreStmt(cast<STMT>(S), C);
0086 }
0087
0088 static bool _handlesStmt(const Stmt *S) {
0089 return isa<STMT>(S);
0090 }
0091 public:
0092 template <typename CHECKER>
0093 static void _register(CHECKER *checker, CheckerManager &mgr) {
0094 mgr._registerForPreStmt(CheckerManager::CheckStmtFunc(checker,
0095 _checkStmt<CHECKER>),
0096 _handlesStmt);
0097 }
0098 };
0099
0100 template <typename STMT>
0101 class PostStmt {
0102 template <typename CHECKER>
0103 static void _checkStmt(void *checker, const Stmt *S, CheckerContext &C) {
0104 ((const CHECKER *)checker)->checkPostStmt(cast<STMT>(S), C);
0105 }
0106
0107 static bool _handlesStmt(const Stmt *S) {
0108 return isa<STMT>(S);
0109 }
0110 public:
0111 template <typename CHECKER>
0112 static void _register(CHECKER *checker, CheckerManager &mgr) {
0113 mgr._registerForPostStmt(CheckerManager::CheckStmtFunc(checker,
0114 _checkStmt<CHECKER>),
0115 _handlesStmt);
0116 }
0117 };
0118
0119 class PreObjCMessage {
0120 template <typename CHECKER>
0121 static void _checkObjCMessage(void *checker, const ObjCMethodCall &msg,
0122 CheckerContext &C) {
0123 ((const CHECKER *)checker)->checkPreObjCMessage(msg, C);
0124 }
0125
0126 public:
0127 template <typename CHECKER>
0128 static void _register(CHECKER *checker, CheckerManager &mgr) {
0129 mgr._registerForPreObjCMessage(
0130 CheckerManager::CheckObjCMessageFunc(checker, _checkObjCMessage<CHECKER>));
0131 }
0132 };
0133
0134 class ObjCMessageNil {
0135 template <typename CHECKER>
0136 static void _checkObjCMessage(void *checker, const ObjCMethodCall &msg,
0137 CheckerContext &C) {
0138 ((const CHECKER *)checker)->checkObjCMessageNil(msg, C);
0139 }
0140
0141 public:
0142 template <typename CHECKER>
0143 static void _register(CHECKER *checker, CheckerManager &mgr) {
0144 mgr._registerForObjCMessageNil(
0145 CheckerManager::CheckObjCMessageFunc(checker, _checkObjCMessage<CHECKER>));
0146 }
0147 };
0148
0149 class PostObjCMessage {
0150 template <typename CHECKER>
0151 static void _checkObjCMessage(void *checker, const ObjCMethodCall &msg,
0152 CheckerContext &C) {
0153 ((const CHECKER *)checker)->checkPostObjCMessage(msg, C);
0154 }
0155
0156 public:
0157 template <typename CHECKER>
0158 static void _register(CHECKER *checker, CheckerManager &mgr) {
0159 mgr._registerForPostObjCMessage(
0160 CheckerManager::CheckObjCMessageFunc(checker, _checkObjCMessage<CHECKER>));
0161 }
0162 };
0163
0164 class PreCall {
0165 template <typename CHECKER>
0166 static void _checkCall(void *checker, const CallEvent &msg,
0167 CheckerContext &C) {
0168 ((const CHECKER *)checker)->checkPreCall(msg, C);
0169 }
0170
0171 public:
0172 template <typename CHECKER>
0173 static void _register(CHECKER *checker, CheckerManager &mgr) {
0174 mgr._registerForPreCall(
0175 CheckerManager::CheckCallFunc(checker, _checkCall<CHECKER>));
0176 }
0177 };
0178
0179 class PostCall {
0180 template <typename CHECKER>
0181 static void _checkCall(void *checker, const CallEvent &msg,
0182 CheckerContext &C) {
0183 ((const CHECKER *)checker)->checkPostCall(msg, C);
0184 }
0185
0186 public:
0187 template <typename CHECKER>
0188 static void _register(CHECKER *checker, CheckerManager &mgr) {
0189 mgr._registerForPostCall(
0190 CheckerManager::CheckCallFunc(checker, _checkCall<CHECKER>));
0191 }
0192 };
0193
0194 class Location {
0195 template <typename CHECKER>
0196 static void _checkLocation(void *checker, SVal location, bool isLoad,
0197 const Stmt *S, CheckerContext &C) {
0198 ((const CHECKER *)checker)->checkLocation(location, isLoad, S, C);
0199 }
0200
0201 public:
0202 template <typename CHECKER>
0203 static void _register(CHECKER *checker, CheckerManager &mgr) {
0204 mgr._registerForLocation(
0205 CheckerManager::CheckLocationFunc(checker, _checkLocation<CHECKER>));
0206 }
0207 };
0208
0209 class Bind {
0210 template <typename CHECKER>
0211 static void _checkBind(void *checker, SVal location, SVal val, const Stmt *S,
0212 CheckerContext &C) {
0213 ((const CHECKER *)checker)->checkBind(location, val, S, C);
0214 }
0215
0216 public:
0217 template <typename CHECKER>
0218 static void _register(CHECKER *checker, CheckerManager &mgr) {
0219 mgr._registerForBind(
0220 CheckerManager::CheckBindFunc(checker, _checkBind<CHECKER>));
0221 }
0222 };
0223
0224 class EndAnalysis {
0225 template <typename CHECKER>
0226 static void _checkEndAnalysis(void *checker, ExplodedGraph &G,
0227 BugReporter &BR, ExprEngine &Eng) {
0228 ((const CHECKER *)checker)->checkEndAnalysis(G, BR, Eng);
0229 }
0230
0231 public:
0232 template <typename CHECKER>
0233 static void _register(CHECKER *checker, CheckerManager &mgr) {
0234 mgr._registerForEndAnalysis(
0235 CheckerManager::CheckEndAnalysisFunc(checker, _checkEndAnalysis<CHECKER>));
0236 }
0237 };
0238
0239 class BeginFunction {
0240 template <typename CHECKER>
0241 static void _checkBeginFunction(void *checker, CheckerContext &C) {
0242 ((const CHECKER *)checker)->checkBeginFunction(C);
0243 }
0244
0245 public:
0246 template <typename CHECKER>
0247 static void _register(CHECKER *checker, CheckerManager &mgr) {
0248 mgr._registerForBeginFunction(CheckerManager::CheckBeginFunctionFunc(
0249 checker, _checkBeginFunction<CHECKER>));
0250 }
0251 };
0252
0253 class EndFunction {
0254 template <typename CHECKER>
0255 static void _checkEndFunction(void *checker, const ReturnStmt *RS,
0256 CheckerContext &C) {
0257 ((const CHECKER *)checker)->checkEndFunction(RS, C);
0258 }
0259
0260 public:
0261 template <typename CHECKER>
0262 static void _register(CHECKER *checker, CheckerManager &mgr) {
0263 mgr._registerForEndFunction(
0264 CheckerManager::CheckEndFunctionFunc(checker, _checkEndFunction<CHECKER>));
0265 }
0266 };
0267
0268 class BranchCondition {
0269 template <typename CHECKER>
0270 static void _checkBranchCondition(void *checker, const Stmt *Condition,
0271 CheckerContext & C) {
0272 ((const CHECKER *)checker)->checkBranchCondition(Condition, C);
0273 }
0274
0275 public:
0276 template <typename CHECKER>
0277 static void _register(CHECKER *checker, CheckerManager &mgr) {
0278 mgr._registerForBranchCondition(
0279 CheckerManager::CheckBranchConditionFunc(checker,
0280 _checkBranchCondition<CHECKER>));
0281 }
0282 };
0283
0284 class NewAllocator {
0285 template <typename CHECKER>
0286 static void _checkNewAllocator(void *checker, const CXXAllocatorCall &Call,
0287 CheckerContext &C) {
0288 ((const CHECKER *)checker)->checkNewAllocator(Call, C);
0289 }
0290
0291 public:
0292 template <typename CHECKER>
0293 static void _register(CHECKER *checker, CheckerManager &mgr) {
0294 mgr._registerForNewAllocator(
0295 CheckerManager::CheckNewAllocatorFunc(checker,
0296 _checkNewAllocator<CHECKER>));
0297 }
0298 };
0299
0300 class LiveSymbols {
0301 template <typename CHECKER>
0302 static void _checkLiveSymbols(void *checker, ProgramStateRef state,
0303 SymbolReaper &SR) {
0304 ((const CHECKER *)checker)->checkLiveSymbols(state, SR);
0305 }
0306
0307 public:
0308 template <typename CHECKER>
0309 static void _register(CHECKER *checker, CheckerManager &mgr) {
0310 mgr._registerForLiveSymbols(
0311 CheckerManager::CheckLiveSymbolsFunc(checker, _checkLiveSymbols<CHECKER>));
0312 }
0313 };
0314
0315 class DeadSymbols {
0316 template <typename CHECKER>
0317 static void _checkDeadSymbols(void *checker,
0318 SymbolReaper &SR, CheckerContext &C) {
0319 ((const CHECKER *)checker)->checkDeadSymbols(SR, C);
0320 }
0321
0322 public:
0323 template <typename CHECKER>
0324 static void _register(CHECKER *checker, CheckerManager &mgr) {
0325 mgr._registerForDeadSymbols(
0326 CheckerManager::CheckDeadSymbolsFunc(checker, _checkDeadSymbols<CHECKER>));
0327 }
0328 };
0329
0330 class RegionChanges {
0331 template <typename CHECKER>
0332 static ProgramStateRef
0333 _checkRegionChanges(void *checker,
0334 ProgramStateRef state,
0335 const InvalidatedSymbols *invalidated,
0336 ArrayRef<const MemRegion *> Explicits,
0337 ArrayRef<const MemRegion *> Regions,
0338 const LocationContext *LCtx,
0339 const CallEvent *Call) {
0340 return ((const CHECKER *) checker)->checkRegionChanges(state, invalidated,
0341 Explicits, Regions,
0342 LCtx, Call);
0343 }
0344
0345 public:
0346 template <typename CHECKER>
0347 static void _register(CHECKER *checker, CheckerManager &mgr) {
0348 mgr._registerForRegionChanges(
0349 CheckerManager::CheckRegionChangesFunc(checker,
0350 _checkRegionChanges<CHECKER>));
0351 }
0352 };
0353
0354 class PointerEscape {
0355 template <typename CHECKER>
0356 static ProgramStateRef
0357 _checkPointerEscape(void *Checker,
0358 ProgramStateRef State,
0359 const InvalidatedSymbols &Escaped,
0360 const CallEvent *Call,
0361 PointerEscapeKind Kind,
0362 RegionAndSymbolInvalidationTraits *ETraits) {
0363
0364 if (!ETraits)
0365 return ((const CHECKER *)Checker)->checkPointerEscape(State,
0366 Escaped,
0367 Call,
0368 Kind);
0369
0370 InvalidatedSymbols RegularEscape;
0371 for (SymbolRef Sym : Escaped)
0372 if (!ETraits->hasTrait(
0373 Sym, RegionAndSymbolInvalidationTraits::TK_PreserveContents) &&
0374 !ETraits->hasTrait(
0375 Sym, RegionAndSymbolInvalidationTraits::TK_SuppressEscape))
0376 RegularEscape.insert(Sym);
0377
0378 if (RegularEscape.empty())
0379 return State;
0380
0381 return ((const CHECKER *)Checker)->checkPointerEscape(State,
0382 RegularEscape,
0383 Call,
0384 Kind);
0385 }
0386
0387 public:
0388 template <typename CHECKER>
0389 static void _register(CHECKER *checker, CheckerManager &mgr) {
0390 mgr._registerForPointerEscape(
0391 CheckerManager::CheckPointerEscapeFunc(checker,
0392 _checkPointerEscape<CHECKER>));
0393 }
0394 };
0395
0396 class ConstPointerEscape {
0397 template <typename CHECKER>
0398 static ProgramStateRef
0399 _checkConstPointerEscape(void *Checker,
0400 ProgramStateRef State,
0401 const InvalidatedSymbols &Escaped,
0402 const CallEvent *Call,
0403 PointerEscapeKind Kind,
0404 RegionAndSymbolInvalidationTraits *ETraits) {
0405
0406 if (!ETraits)
0407 return State;
0408
0409 InvalidatedSymbols ConstEscape;
0410 for (SymbolRef Sym : Escaped) {
0411 if (ETraits->hasTrait(
0412 Sym, RegionAndSymbolInvalidationTraits::TK_PreserveContents) &&
0413 !ETraits->hasTrait(
0414 Sym, RegionAndSymbolInvalidationTraits::TK_SuppressEscape))
0415 ConstEscape.insert(Sym);
0416 }
0417
0418 if (ConstEscape.empty())
0419 return State;
0420
0421 return ((const CHECKER *)Checker)->checkConstPointerEscape(State,
0422 ConstEscape,
0423 Call,
0424 Kind);
0425 }
0426
0427 public:
0428 template <typename CHECKER>
0429 static void _register(CHECKER *checker, CheckerManager &mgr) {
0430 mgr._registerForPointerEscape(
0431 CheckerManager::CheckPointerEscapeFunc(checker,
0432 _checkConstPointerEscape<CHECKER>));
0433 }
0434 };
0435
0436
0437 template <typename EVENT>
0438 class Event {
0439 template <typename CHECKER>
0440 static void _checkEvent(void *checker, const void *event) {
0441 ((const CHECKER *)checker)->checkEvent(*(const EVENT *)event);
0442 }
0443 public:
0444 template <typename CHECKER>
0445 static void _register(CHECKER *checker, CheckerManager &mgr) {
0446 mgr._registerListenerForEvent<EVENT>(
0447 CheckerManager::CheckEventFunc(checker, _checkEvent<CHECKER>));
0448 }
0449 };
0450
0451 }
0452
0453 namespace eval {
0454
0455 class Assume {
0456 template <typename CHECKER>
0457 static ProgramStateRef _evalAssume(void *checker, ProgramStateRef state,
0458 SVal cond, bool assumption) {
0459 return ((const CHECKER *)checker)->evalAssume(state, cond, assumption);
0460 }
0461
0462 public:
0463 template <typename CHECKER>
0464 static void _register(CHECKER *checker, CheckerManager &mgr) {
0465 mgr._registerForEvalAssume(
0466 CheckerManager::EvalAssumeFunc(checker, _evalAssume<CHECKER>));
0467 }
0468 };
0469
0470 class Call {
0471 template <typename CHECKER>
0472 static bool _evalCall(void *checker, const CallEvent &Call,
0473 CheckerContext &C) {
0474 return ((const CHECKER *)checker)->evalCall(Call, C);
0475 }
0476
0477 public:
0478 template <typename CHECKER>
0479 static void _register(CHECKER *checker, CheckerManager &mgr) {
0480 mgr._registerForEvalCall(
0481 CheckerManager::EvalCallFunc(checker, _evalCall<CHECKER>));
0482 }
0483 };
0484
0485 }
0486
0487 class CheckerBase : public ProgramPointTag {
0488 CheckerNameRef Name;
0489 friend class ::clang::ento::CheckerManager;
0490
0491 public:
0492 StringRef getTagDescription() const override;
0493 CheckerNameRef getCheckerName() const;
0494
0495
0496 virtual void printState(raw_ostream &Out, ProgramStateRef State,
0497 const char *NL, const char *Sep) const { }
0498 };
0499
0500
0501 raw_ostream& operator<<(raw_ostream &Out, const CheckerBase &Checker);
0502
0503
0504
0505 class CheckerProgramPointTag : public SimpleProgramPointTag {
0506 public:
0507 CheckerProgramPointTag(StringRef CheckerName, StringRef Msg);
0508 CheckerProgramPointTag(const CheckerBase *Checker, StringRef Msg);
0509 };
0510
0511 template <typename CHECK1, typename... CHECKs>
0512 class Checker : public CHECK1, public CHECKs..., public CheckerBase {
0513 public:
0514 template <typename CHECKER>
0515 static void _register(CHECKER *checker, CheckerManager &mgr) {
0516 CHECK1::_register(checker, mgr);
0517 Checker<CHECKs...>::_register(checker, mgr);
0518 }
0519 };
0520
0521 template <typename CHECK1>
0522 class Checker<CHECK1> : public CHECK1, public CheckerBase {
0523 public:
0524 template <typename CHECKER>
0525 static void _register(CHECKER *checker, CheckerManager &mgr) {
0526 CHECK1::_register(checker, mgr);
0527 }
0528 };
0529
0530 template <typename EVENT>
0531 class EventDispatcher {
0532 CheckerManager *Mgr = nullptr;
0533 public:
0534 EventDispatcher() = default;
0535
0536 template <typename CHECKER>
0537 static void _register(CHECKER *checker, CheckerManager &mgr) {
0538 mgr._registerDispatcherForEvent<EVENT>();
0539 static_cast<EventDispatcher<EVENT> *>(checker)->Mgr = &mgr;
0540 }
0541
0542 void dispatchEvent(const EVENT &event) const {
0543 Mgr->_dispatchEvent(event);
0544 }
0545 };
0546
0547
0548 struct ImplicitNullDerefEvent {
0549 SVal Location;
0550 bool IsLoad;
0551 ExplodedNode *SinkNode;
0552 BugReporter *BR;
0553
0554
0555
0556 bool IsDirectDereference;
0557
0558 static int Tag;
0559 };
0560
0561 }
0562
0563 }
0564
0565 #endif