//== 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