Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-05-10 08:37:10

0001 //== Checker.h - Registration mechanism for checkers -------------*- C++ -*--=//
0002 //
0003 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
0004 // See https://llvm.org/LICENSE.txt for license information.
0005 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
0006 //
0007 //===----------------------------------------------------------------------===//
0008 //
0009 //  This file defines Checker, used to create and register checkers.
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 } // end check namespace
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 } // end eval namespace
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   /// See CheckerManager::runCheckersForPrintState.
0496   virtual void printState(raw_ostream &Out, ProgramStateRef State,
0497                           const char *NL, const char *Sep) const { }
0498 };
0499 
0500 /// Dump checker name to stream.
0501 raw_ostream& operator<<(raw_ostream &Out, const CheckerBase &Checker);
0502 
0503 /// Tag that can use a checker name as a message provider
0504 /// (see SimpleProgramPointTag).
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 /// We dereferenced a location that may be null.
0548 struct ImplicitNullDerefEvent {
0549   SVal Location;
0550   bool IsLoad;
0551   ExplodedNode *SinkNode;
0552   BugReporter *BR;
0553   // When true, the dereference is in the source code directly. When false, the
0554   // dereference might happen later (for example pointer passed to a parameter
0555   // that is marked with nonnull attribute.)
0556   bool IsDirectDereference;
0557 
0558   static int Tag;
0559 };
0560 
0561 } // end ento namespace
0562 
0563 } // end clang namespace
0564 
0565 #endif