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