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