- //== Checker.h - Registration mechanism for checkers -------------*- C++ -*--=// 
- // 
- // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 
- // See https://llvm.org/LICENSE.txt for license information. 
- // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 
- // 
- //===----------------------------------------------------------------------===// 
- // 
- //  This file defines Checker, used to create and register checkers. 
- // 
- //===----------------------------------------------------------------------===// 
-   
- #ifndef LLVM_CLANG_STATICANALYZER_CORE_CHECKER_H 
- #define LLVM_CLANG_STATICANALYZER_CORE_CHECKER_H 
-   
- #include "clang/Analysis/ProgramPoint.h" 
- #include "clang/Basic/LangOptions.h" 
- #include "clang/StaticAnalyzer/Core/CheckerManager.h" 
- #include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h" 
- #include "llvm/Support/Casting.h" 
-   
- namespace clang { 
- namespace ento { 
-   class BugReporter; 
-   
- namespace check { 
-   
- template <typename DECL> 
- class ASTDecl { 
-   template <typename CHECKER> 
-   static void _checkDecl(void *checker, const Decl *D, AnalysisManager& mgr, 
-                          BugReporter &BR) { 
-     ((const CHECKER *)checker)->checkASTDecl(cast<DECL>(D), mgr, BR); 
-   } 
-   
-   static bool _handlesDecl(const Decl *D) { 
-     return isa<DECL>(D); 
-   } 
- public: 
-   template <typename CHECKER> 
-   static void _register(CHECKER *checker, CheckerManager &mgr) { 
-     mgr._registerForDecl(CheckerManager::CheckDeclFunc(checker, 
-                                                        _checkDecl<CHECKER>), 
-                          _handlesDecl); 
-   } 
- }; 
-   
- class ASTCodeBody { 
-   template <typename CHECKER> 
-   static void _checkBody(void *checker, const Decl *D, AnalysisManager& mgr, 
-                          BugReporter &BR) { 
-     ((const CHECKER *)checker)->checkASTCodeBody(D, mgr, BR); 
-   } 
-   
- public: 
-   template <typename CHECKER> 
-   static void _register(CHECKER *checker, CheckerManager &mgr) { 
-     mgr._registerForBody(CheckerManager::CheckDeclFunc(checker, 
-                                                        _checkBody<CHECKER>)); 
-   } 
- }; 
-   
- class EndOfTranslationUnit { 
-   template <typename CHECKER> 
-   static void _checkEndOfTranslationUnit(void *checker, 
-                                          const TranslationUnitDecl *TU, 
-                                          AnalysisManager& mgr, 
-                                          BugReporter &BR) { 
-     ((const CHECKER *)checker)->checkEndOfTranslationUnit(TU, mgr, BR); 
-   } 
-   
- public: 
-   template <typename CHECKER> 
-   static void _register(CHECKER *checker, CheckerManager &mgr){ 
-     mgr._registerForEndOfTranslationUnit( 
-                               CheckerManager::CheckEndOfTranslationUnit(checker, 
-                                           _checkEndOfTranslationUnit<CHECKER>)); 
-   } 
- }; 
-   
- template <typename STMT> 
- class PreStmt { 
-   template <typename CHECKER> 
-   static void _checkStmt(void *checker, const Stmt *S, CheckerContext &C) { 
-     ((const CHECKER *)checker)->checkPreStmt(cast<STMT>(S), C); 
-   } 
-   
-   static bool _handlesStmt(const Stmt *S) { 
-     return isa<STMT>(S); 
-   } 
- public: 
-   template <typename CHECKER> 
-   static void _register(CHECKER *checker, CheckerManager &mgr) { 
-     mgr._registerForPreStmt(CheckerManager::CheckStmtFunc(checker, 
-                                                           _checkStmt<CHECKER>), 
-                             _handlesStmt); 
-   } 
- }; 
-   
- template <typename STMT> 
- class PostStmt { 
-   template <typename CHECKER> 
-   static void _checkStmt(void *checker, const Stmt *S, CheckerContext &C) { 
-     ((const CHECKER *)checker)->checkPostStmt(cast<STMT>(S), C); 
-   } 
-   
-   static bool _handlesStmt(const Stmt *S) { 
-     return isa<STMT>(S); 
-   } 
- public: 
-   template <typename CHECKER> 
-   static void _register(CHECKER *checker, CheckerManager &mgr) { 
-     mgr._registerForPostStmt(CheckerManager::CheckStmtFunc(checker, 
-                                                            _checkStmt<CHECKER>), 
-                              _handlesStmt); 
-   } 
- }; 
-   
- class PreObjCMessage { 
-   template <typename CHECKER> 
-   static void _checkObjCMessage(void *checker, const ObjCMethodCall &msg, 
-                                 CheckerContext &C) { 
-     ((const CHECKER *)checker)->checkPreObjCMessage(msg, C); 
-   } 
-   
- public: 
-   template <typename CHECKER> 
-   static void _register(CHECKER *checker, CheckerManager &mgr) { 
-     mgr._registerForPreObjCMessage( 
-      CheckerManager::CheckObjCMessageFunc(checker, _checkObjCMessage<CHECKER>)); 
-   } 
- }; 
-   
- class ObjCMessageNil { 
-   template <typename CHECKER> 
-   static void _checkObjCMessage(void *checker, const ObjCMethodCall &msg, 
-                                 CheckerContext &C) { 
-     ((const CHECKER *)checker)->checkObjCMessageNil(msg, C); 
-   } 
-   
- public: 
-   template <typename CHECKER> 
-   static void _register(CHECKER *checker, CheckerManager &mgr) { 
-     mgr._registerForObjCMessageNil( 
-      CheckerManager::CheckObjCMessageFunc(checker, _checkObjCMessage<CHECKER>)); 
-   } 
- }; 
-   
- class PostObjCMessage { 
-   template <typename CHECKER> 
-   static void _checkObjCMessage(void *checker, const ObjCMethodCall &msg, 
-                                 CheckerContext &C) { 
-     ((const CHECKER *)checker)->checkPostObjCMessage(msg, C); 
-   } 
-   
- public: 
-   template <typename CHECKER> 
-   static void _register(CHECKER *checker, CheckerManager &mgr) { 
-     mgr._registerForPostObjCMessage( 
-      CheckerManager::CheckObjCMessageFunc(checker, _checkObjCMessage<CHECKER>)); 
-   } 
- }; 
-   
- class PreCall { 
-   template <typename CHECKER> 
-   static void _checkCall(void *checker, const CallEvent &msg, 
-                          CheckerContext &C) { 
-     ((const CHECKER *)checker)->checkPreCall(msg, C); 
-   } 
-   
- public: 
-   template <typename CHECKER> 
-   static void _register(CHECKER *checker, CheckerManager &mgr) { 
-     mgr._registerForPreCall( 
-      CheckerManager::CheckCallFunc(checker, _checkCall<CHECKER>)); 
-   } 
- }; 
-   
- class PostCall { 
-   template <typename CHECKER> 
-   static void _checkCall(void *checker, const CallEvent &msg, 
-                          CheckerContext &C) { 
-     ((const CHECKER *)checker)->checkPostCall(msg, C); 
-   } 
-   
- public: 
-   template <typename CHECKER> 
-   static void _register(CHECKER *checker, CheckerManager &mgr) { 
-     mgr._registerForPostCall( 
-      CheckerManager::CheckCallFunc(checker, _checkCall<CHECKER>)); 
-   } 
- }; 
-   
- class Location { 
-   template <typename CHECKER> 
-   static void _checkLocation(void *checker, 
-                              const SVal &location, bool isLoad, const Stmt *S, 
-                              CheckerContext &C) { 
-     ((const CHECKER *)checker)->checkLocation(location, isLoad, S, C); 
-   } 
-   
- public: 
-   template <typename CHECKER> 
-   static void _register(CHECKER *checker, CheckerManager &mgr) { 
-     mgr._registerForLocation( 
-            CheckerManager::CheckLocationFunc(checker, _checkLocation<CHECKER>)); 
-   } 
- }; 
-   
- class Bind { 
-   template <typename CHECKER> 
-   static void _checkBind(void *checker, 
-                          const SVal &location, const SVal &val, const Stmt *S, 
-                          CheckerContext &C) { 
-     ((const CHECKER *)checker)->checkBind(location, val, S, C); 
-   } 
-   
- public: 
-   template <typename CHECKER> 
-   static void _register(CHECKER *checker, CheckerManager &mgr) { 
-     mgr._registerForBind( 
-            CheckerManager::CheckBindFunc(checker, _checkBind<CHECKER>)); 
-   } 
- }; 
-   
- class EndAnalysis { 
-   template <typename CHECKER> 
-   static void _checkEndAnalysis(void *checker, ExplodedGraph &G, 
-                                 BugReporter &BR, ExprEngine &Eng) { 
-     ((const CHECKER *)checker)->checkEndAnalysis(G, BR, Eng); 
-   } 
-   
- public: 
-   template <typename CHECKER> 
-   static void _register(CHECKER *checker, CheckerManager &mgr) { 
-     mgr._registerForEndAnalysis( 
-      CheckerManager::CheckEndAnalysisFunc(checker, _checkEndAnalysis<CHECKER>)); 
-   } 
- }; 
-   
- class BeginFunction { 
-   template <typename CHECKER> 
-   static void _checkBeginFunction(void *checker, CheckerContext &C) { 
-     ((const CHECKER *)checker)->checkBeginFunction(C); 
-   } 
-   
- public: 
-   template <typename CHECKER> 
-   static void _register(CHECKER *checker, CheckerManager &mgr) { 
-     mgr._registerForBeginFunction(CheckerManager::CheckBeginFunctionFunc( 
-         checker, _checkBeginFunction<CHECKER>)); 
-   } 
- }; 
-   
- class EndFunction { 
-   template <typename CHECKER> 
-   static void _checkEndFunction(void *checker, const ReturnStmt *RS, 
-                                 CheckerContext &C) { 
-     ((const CHECKER *)checker)->checkEndFunction(RS, C); 
-   } 
-   
- public: 
-   template <typename CHECKER> 
-   static void _register(CHECKER *checker, CheckerManager &mgr) { 
-     mgr._registerForEndFunction( 
-      CheckerManager::CheckEndFunctionFunc(checker, _checkEndFunction<CHECKER>)); 
-   } 
- }; 
-   
- class BranchCondition { 
-   template <typename CHECKER> 
-   static void _checkBranchCondition(void *checker, const Stmt *Condition, 
-                                     CheckerContext & C) { 
-     ((const CHECKER *)checker)->checkBranchCondition(Condition, C); 
-   } 
-   
- public: 
-   template <typename CHECKER> 
-   static void _register(CHECKER *checker, CheckerManager &mgr) { 
-     mgr._registerForBranchCondition( 
-       CheckerManager::CheckBranchConditionFunc(checker, 
-                                                _checkBranchCondition<CHECKER>)); 
-   } 
- }; 
-   
- class NewAllocator { 
-   template <typename CHECKER> 
-   static void _checkNewAllocator(void *checker, const CXXAllocatorCall &Call, 
-                                  CheckerContext &C) { 
-     ((const CHECKER *)checker)->checkNewAllocator(Call, C); 
-   } 
-   
- public: 
-   template <typename CHECKER> 
-   static void _register(CHECKER *checker, CheckerManager &mgr) { 
-     mgr._registerForNewAllocator( 
-         CheckerManager::CheckNewAllocatorFunc(checker, 
-                                               _checkNewAllocator<CHECKER>)); 
-   } 
- }; 
-   
- class LiveSymbols { 
-   template <typename CHECKER> 
-   static void _checkLiveSymbols(void *checker, ProgramStateRef state, 
-                                 SymbolReaper &SR) { 
-     ((const CHECKER *)checker)->checkLiveSymbols(state, SR); 
-   } 
-   
- public: 
-   template <typename CHECKER> 
-   static void _register(CHECKER *checker, CheckerManager &mgr) { 
-     mgr._registerForLiveSymbols( 
-      CheckerManager::CheckLiveSymbolsFunc(checker, _checkLiveSymbols<CHECKER>)); 
-   } 
- }; 
-   
- class DeadSymbols { 
-   template <typename CHECKER> 
-   static void _checkDeadSymbols(void *checker, 
-                                 SymbolReaper &SR, CheckerContext &C) { 
-     ((const CHECKER *)checker)->checkDeadSymbols(SR, C); 
-   } 
-   
- public: 
-   template <typename CHECKER> 
-   static void _register(CHECKER *checker, CheckerManager &mgr) { 
-     mgr._registerForDeadSymbols( 
-      CheckerManager::CheckDeadSymbolsFunc(checker, _checkDeadSymbols<CHECKER>)); 
-   } 
- }; 
-   
- class RegionChanges { 
-   template <typename CHECKER> 
-   static ProgramStateRef 
-   _checkRegionChanges(void *checker, 
-                       ProgramStateRef state, 
-                       const InvalidatedSymbols *invalidated, 
-                       ArrayRef<const MemRegion *> Explicits, 
-                       ArrayRef<const MemRegion *> Regions, 
-                       const LocationContext *LCtx, 
-                       const CallEvent *Call) { 
-     return ((const CHECKER *) checker)->checkRegionChanges(state, invalidated, 
-                                                            Explicits, Regions, 
-                                                            LCtx, Call); 
-   } 
-   
- public: 
-   template <typename CHECKER> 
-   static void _register(CHECKER *checker, CheckerManager &mgr) { 
-     mgr._registerForRegionChanges( 
-           CheckerManager::CheckRegionChangesFunc(checker, 
-                                                  _checkRegionChanges<CHECKER>)); 
-   } 
- }; 
-   
- class PointerEscape { 
-   template <typename CHECKER> 
-   static ProgramStateRef 
-   _checkPointerEscape(void *Checker, 
-                      ProgramStateRef State, 
-                      const InvalidatedSymbols &Escaped, 
-                      const CallEvent *Call, 
-                      PointerEscapeKind Kind, 
-                      RegionAndSymbolInvalidationTraits *ETraits) { 
-   
-     if (!ETraits) 
-       return ((const CHECKER *)Checker)->checkPointerEscape(State, 
-                                                             Escaped, 
-                                                             Call, 
-                                                             Kind); 
-   
-     InvalidatedSymbols RegularEscape; 
-     for (InvalidatedSymbols::const_iterator I = Escaped.begin(), 
-                                             E = Escaped.end(); I != E; ++I) 
-       if (!ETraits->hasTrait(*I, 
-               RegionAndSymbolInvalidationTraits::TK_PreserveContents) && 
-           !ETraits->hasTrait(*I, 
-               RegionAndSymbolInvalidationTraits::TK_SuppressEscape)) 
-         RegularEscape.insert(*I); 
-   
-     if (RegularEscape.empty()) 
-       return State; 
-   
-     return ((const CHECKER *)Checker)->checkPointerEscape(State, 
-                                                           RegularEscape, 
-                                                           Call, 
-                                                           Kind); 
-   } 
-   
- public: 
-   template <typename CHECKER> 
-   static void _register(CHECKER *checker, CheckerManager &mgr) { 
-     mgr._registerForPointerEscape( 
-           CheckerManager::CheckPointerEscapeFunc(checker, 
-                                                 _checkPointerEscape<CHECKER>)); 
-   } 
- }; 
-   
- class ConstPointerEscape { 
-   template <typename CHECKER> 
-   static ProgramStateRef 
-   _checkConstPointerEscape(void *Checker, 
-                       ProgramStateRef State, 
-                       const InvalidatedSymbols &Escaped, 
-                       const CallEvent *Call, 
-                       PointerEscapeKind Kind, 
-                       RegionAndSymbolInvalidationTraits *ETraits) { 
-   
-     if (!ETraits) 
-       return State; 
-   
-     InvalidatedSymbols ConstEscape; 
-     for (InvalidatedSymbols::const_iterator I = Escaped.begin(), 
-                                             E = Escaped.end(); I != E; ++I) 
-       if (ETraits->hasTrait(*I, 
-               RegionAndSymbolInvalidationTraits::TK_PreserveContents) && 
-           !ETraits->hasTrait(*I, 
-               RegionAndSymbolInvalidationTraits::TK_SuppressEscape)) 
-         ConstEscape.insert(*I); 
-   
-     if (ConstEscape.empty()) 
-       return State; 
-   
-     return ((const CHECKER *)Checker)->checkConstPointerEscape(State, 
-                                                                ConstEscape, 
-                                                                Call, 
-                                                                Kind); 
-   } 
-   
- public: 
-   template <typename CHECKER> 
-   static void _register(CHECKER *checker, CheckerManager &mgr) { 
-     mgr._registerForPointerEscape( 
-       CheckerManager::CheckPointerEscapeFunc(checker, 
-                                             _checkConstPointerEscape<CHECKER>)); 
-   } 
- }; 
-   
-   
- template <typename EVENT> 
- class Event { 
-   template <typename CHECKER> 
-   static void _checkEvent(void *checker, const void *event) { 
-     ((const CHECKER *)checker)->checkEvent(*(const EVENT *)event); 
-   } 
- public: 
-   template <typename CHECKER> 
-   static void _register(CHECKER *checker, CheckerManager &mgr) { 
-     mgr._registerListenerForEvent<EVENT>( 
-                  CheckerManager::CheckEventFunc(checker, _checkEvent<CHECKER>)); 
-   } 
- }; 
-   
- } // end check namespace 
-   
- namespace eval { 
-   
- class Assume { 
-   template <typename CHECKER> 
-   static ProgramStateRef _evalAssume(void *checker, 
-                                          ProgramStateRef state, 
-                                          const SVal &cond, 
-                                          bool assumption) { 
-     return ((const CHECKER *)checker)->evalAssume(state, cond, assumption); 
-   } 
-   
- public: 
-   template <typename CHECKER> 
-   static void _register(CHECKER *checker, CheckerManager &mgr) { 
-     mgr._registerForEvalAssume( 
-                  CheckerManager::EvalAssumeFunc(checker, _evalAssume<CHECKER>)); 
-   } 
- }; 
-   
- class Call { 
-   template <typename CHECKER> 
-   static bool _evalCall(void *checker, const CallEvent &Call, 
-                         CheckerContext &C) { 
-     return ((const CHECKER *)checker)->evalCall(Call, C); 
-   } 
-   
- public: 
-   template <typename CHECKER> 
-   static void _register(CHECKER *checker, CheckerManager &mgr) { 
-     mgr._registerForEvalCall( 
-                      CheckerManager::EvalCallFunc(checker, _evalCall<CHECKER>)); 
-   } 
- }; 
-   
- } // end eval namespace 
-   
- class CheckerBase : public ProgramPointTag { 
-   CheckerNameRef Name; 
-   friend class ::clang::ento::CheckerManager; 
-   
- public: 
-   StringRef getTagDescription() const override; 
-   CheckerNameRef getCheckerName() const; 
-   
-   /// See CheckerManager::runCheckersForPrintState. 
-   virtual void printState(raw_ostream &Out, ProgramStateRef State, 
-                           const char *NL, const char *Sep) const { } 
- }; 
-   
- /// Dump checker name to stream. 
- raw_ostream& operator<<(raw_ostream &Out, const CheckerBase &Checker); 
-   
- /// Tag that can use a checker name as a message provider 
- /// (see SimpleProgramPointTag). 
- class CheckerProgramPointTag : public SimpleProgramPointTag { 
- public: 
-   CheckerProgramPointTag(StringRef CheckerName, StringRef Msg); 
-   CheckerProgramPointTag(const CheckerBase *Checker, StringRef Msg); 
- }; 
-   
- template <typename CHECK1, typename... CHECKs> 
- class Checker : public CHECK1, public CHECKs..., public CheckerBase { 
- public: 
-   template <typename CHECKER> 
-   static void _register(CHECKER *checker, CheckerManager &mgr) { 
-     CHECK1::_register(checker, mgr); 
-     Checker<CHECKs...>::_register(checker, mgr); 
-   } 
- }; 
-   
- template <typename CHECK1> 
- class Checker<CHECK1> : public CHECK1, public CheckerBase { 
- public: 
-   template <typename CHECKER> 
-   static void _register(CHECKER *checker, CheckerManager &mgr) { 
-     CHECK1::_register(checker, mgr); 
-   } 
- }; 
-   
- template <typename EVENT> 
- class EventDispatcher { 
-   CheckerManager *Mgr; 
- public: 
-   EventDispatcher() : Mgr(nullptr) { } 
-   
-   template <typename CHECKER> 
-   static void _register(CHECKER *checker, CheckerManager &mgr) { 
-     mgr._registerDispatcherForEvent<EVENT>(); 
-     static_cast<EventDispatcher<EVENT> *>(checker)->Mgr = &mgr; 
-   } 
-   
-   void dispatchEvent(const EVENT &event) const { 
-     Mgr->_dispatchEvent(event); 
-   } 
- }; 
-   
- /// We dereferenced a location that may be null. 
- struct ImplicitNullDerefEvent { 
-   SVal Location; 
-   bool IsLoad; 
-   ExplodedNode *SinkNode; 
-   BugReporter *BR; 
-   // When true, the dereference is in the source code directly. When false, the 
-   // dereference might happen later (for example pointer passed to a parameter 
-   // that is marked with nonnull attribute.) 
-   bool IsDirectDereference; 
-   
-   static int Tag; 
- }; 
-   
- } // end ento namespace 
-   
- } // end clang namespace 
-   
- #endif 
-