1*700637cbSDimitry Andric //===------------------------- MemberPointer.h ------------------*- C++ -*-===// 2*700637cbSDimitry Andric // 3*700637cbSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*700637cbSDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5*700637cbSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*700637cbSDimitry Andric // 7*700637cbSDimitry Andric //===----------------------------------------------------------------------===// 8*700637cbSDimitry Andric 9*700637cbSDimitry Andric #ifndef LLVM_CLANG_AST_INTERP_MEMBER_POINTER_H 10*700637cbSDimitry Andric #define LLVM_CLANG_AST_INTERP_MEMBER_POINTER_H 11*700637cbSDimitry Andric 12*700637cbSDimitry Andric #include "Pointer.h" 13*700637cbSDimitry Andric #include <optional> 14*700637cbSDimitry Andric 15*700637cbSDimitry Andric namespace clang { 16*700637cbSDimitry Andric class ASTContext; 17*700637cbSDimitry Andric namespace interp { 18*700637cbSDimitry Andric 19*700637cbSDimitry Andric class Context; 20*700637cbSDimitry Andric class FunctionPointer; 21*700637cbSDimitry Andric 22*700637cbSDimitry Andric class MemberPointer final { 23*700637cbSDimitry Andric private: 24*700637cbSDimitry Andric Pointer Base; 25*700637cbSDimitry Andric const ValueDecl *Dcl = nullptr; 26*700637cbSDimitry Andric int32_t PtrOffset = 0; 27*700637cbSDimitry Andric MemberPointer(Pointer Base,const ValueDecl * Dcl,int32_t PtrOffset)28*700637cbSDimitry Andric MemberPointer(Pointer Base, const ValueDecl *Dcl, int32_t PtrOffset) 29*700637cbSDimitry Andric : Base(Base), Dcl(Dcl), PtrOffset(PtrOffset) {} 30*700637cbSDimitry Andric 31*700637cbSDimitry Andric public: 32*700637cbSDimitry Andric MemberPointer() = default; MemberPointer(Pointer Base,const ValueDecl * Dcl)33*700637cbSDimitry Andric MemberPointer(Pointer Base, const ValueDecl *Dcl) : Base(Base), Dcl(Dcl) {} MemberPointer(uint32_t Address,const Descriptor * D)34*700637cbSDimitry Andric MemberPointer(uint32_t Address, const Descriptor *D) { 35*700637cbSDimitry Andric // We only reach this for Address == 0, when creating a null member pointer. 36*700637cbSDimitry Andric assert(Address == 0); 37*700637cbSDimitry Andric } 38*700637cbSDimitry Andric MemberPointer(const ValueDecl * D)39*700637cbSDimitry Andric MemberPointer(const ValueDecl *D) : Dcl(D) { 40*700637cbSDimitry Andric assert((isa<FieldDecl, IndirectFieldDecl, CXXMethodDecl>(D))); 41*700637cbSDimitry Andric } 42*700637cbSDimitry Andric getIntegerRepresentation()43*700637cbSDimitry Andric uint64_t getIntegerRepresentation() const { 44*700637cbSDimitry Andric assert( 45*700637cbSDimitry Andric false && 46*700637cbSDimitry Andric "getIntegerRepresentation() shouldn't be reachable for MemberPointers"); 47*700637cbSDimitry Andric return 17; 48*700637cbSDimitry Andric } 49*700637cbSDimitry Andric 50*700637cbSDimitry Andric std::optional<Pointer> toPointer(const Context &Ctx) const; 51*700637cbSDimitry Andric 52*700637cbSDimitry Andric FunctionPointer toFunctionPointer(const Context &Ctx) const; 53*700637cbSDimitry Andric getBase()54*700637cbSDimitry Andric Pointer getBase() const { 55*700637cbSDimitry Andric if (PtrOffset < 0) 56*700637cbSDimitry Andric return Base.atField(-PtrOffset); 57*700637cbSDimitry Andric return Base.atFieldSub(PtrOffset); 58*700637cbSDimitry Andric } isMemberFunctionPointer()59*700637cbSDimitry Andric bool isMemberFunctionPointer() const { 60*700637cbSDimitry Andric return isa_and_nonnull<CXXMethodDecl>(Dcl); 61*700637cbSDimitry Andric } getMemberFunction()62*700637cbSDimitry Andric const CXXMethodDecl *getMemberFunction() const { 63*700637cbSDimitry Andric return dyn_cast_if_present<CXXMethodDecl>(Dcl); 64*700637cbSDimitry Andric } getField()65*700637cbSDimitry Andric const FieldDecl *getField() const { 66*700637cbSDimitry Andric return dyn_cast_if_present<FieldDecl>(Dcl); 67*700637cbSDimitry Andric } 68*700637cbSDimitry Andric hasDecl()69*700637cbSDimitry Andric bool hasDecl() const { return Dcl; } getDecl()70*700637cbSDimitry Andric const ValueDecl *getDecl() const { return Dcl; } 71*700637cbSDimitry Andric atInstanceBase(unsigned Offset)72*700637cbSDimitry Andric MemberPointer atInstanceBase(unsigned Offset) const { 73*700637cbSDimitry Andric if (Base.isZero()) 74*700637cbSDimitry Andric return MemberPointer(Base, Dcl, Offset); 75*700637cbSDimitry Andric return MemberPointer(this->Base, Dcl, Offset + PtrOffset); 76*700637cbSDimitry Andric } 77*700637cbSDimitry Andric takeInstance(Pointer Instance)78*700637cbSDimitry Andric MemberPointer takeInstance(Pointer Instance) const { 79*700637cbSDimitry Andric assert(this->Base.isZero()); 80*700637cbSDimitry Andric return MemberPointer(Instance, this->Dcl, this->PtrOffset); 81*700637cbSDimitry Andric } 82*700637cbSDimitry Andric 83*700637cbSDimitry Andric APValue toAPValue(const ASTContext &) const; 84*700637cbSDimitry Andric isZero()85*700637cbSDimitry Andric bool isZero() const { return Base.isZero() && !Dcl; } hasBase()86*700637cbSDimitry Andric bool hasBase() const { return !Base.isZero(); } isWeak()87*700637cbSDimitry Andric bool isWeak() const { 88*700637cbSDimitry Andric if (const auto *MF = getMemberFunction()) 89*700637cbSDimitry Andric return MF->isWeak(); 90*700637cbSDimitry Andric return false; 91*700637cbSDimitry Andric } 92*700637cbSDimitry Andric print(llvm::raw_ostream & OS)93*700637cbSDimitry Andric void print(llvm::raw_ostream &OS) const { 94*700637cbSDimitry Andric OS << "MemberPtr(" << Base << " " << (const void *)Dcl << " + " << PtrOffset 95*700637cbSDimitry Andric << ")"; 96*700637cbSDimitry Andric } 97*700637cbSDimitry Andric toDiagnosticString(const ASTContext & Ctx)98*700637cbSDimitry Andric std::string toDiagnosticString(const ASTContext &Ctx) const { 99*700637cbSDimitry Andric return toAPValue(Ctx).getAsString(Ctx, Dcl->getType()); 100*700637cbSDimitry Andric } 101*700637cbSDimitry Andric compare(const MemberPointer & RHS)102*700637cbSDimitry Andric ComparisonCategoryResult compare(const MemberPointer &RHS) const { 103*700637cbSDimitry Andric if (this->Dcl == RHS.Dcl) 104*700637cbSDimitry Andric return ComparisonCategoryResult::Equal; 105*700637cbSDimitry Andric return ComparisonCategoryResult::Unordered; 106*700637cbSDimitry Andric } 107*700637cbSDimitry Andric }; 108*700637cbSDimitry Andric 109*700637cbSDimitry Andric inline llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, MemberPointer FP) { 110*700637cbSDimitry Andric FP.print(OS); 111*700637cbSDimitry Andric return OS; 112*700637cbSDimitry Andric } 113*700637cbSDimitry Andric 114*700637cbSDimitry Andric } // namespace interp 115*700637cbSDimitry Andric } // namespace clang 116*700637cbSDimitry Andric 117*700637cbSDimitry Andric #endif 118