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