124 lines · c
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-exception6//7//===----------------------------------------------------------------------===//8 9#ifndef LLVM_CLANG_AST_INTERP_MEMBER_POINTER_H10#define LLVM_CLANG_AST_INTERP_MEMBER_POINTER_H11 12#include "Pointer.h"13#include <optional>14 15namespace clang {16class ASTContext;17namespace interp {18 19class Context;20class FunctionPointer;21 22class MemberPointer final {23private:24 Pointer Base;25 const ValueDecl *Dcl = nullptr;26 int32_t PtrOffset = 0;27 28 MemberPointer(Pointer Base, const ValueDecl *Dcl, int32_t PtrOffset)29 : Base(Base), Dcl(Dcl), PtrOffset(PtrOffset) {}30 31public:32 MemberPointer() = default;33 MemberPointer(Pointer Base, const ValueDecl *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 ValueDecl *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 bool isBaseCastPossible() const {55 if (PtrOffset < 0)56 return true;57 return static_cast<uint64_t>(PtrOffset) <= Base.getByteOffset();58 }59 60 Pointer getBase() const {61 if (PtrOffset < 0)62 return Base.atField(-PtrOffset);63 return Base.atFieldSub(PtrOffset);64 }65 bool isMemberFunctionPointer() const {66 return isa_and_nonnull<CXXMethodDecl>(Dcl);67 }68 const CXXMethodDecl *getMemberFunction() const {69 return dyn_cast_if_present<CXXMethodDecl>(Dcl);70 }71 const FieldDecl *getField() const {72 return dyn_cast_if_present<FieldDecl>(Dcl);73 }74 75 bool hasDecl() const { return Dcl; }76 const ValueDecl *getDecl() const { return Dcl; }77 78 MemberPointer atInstanceBase(unsigned Offset) const {79 if (Base.isZero())80 return MemberPointer(Base, Dcl, Offset);81 return MemberPointer(this->Base, Dcl, Offset + PtrOffset);82 }83 84 MemberPointer takeInstance(Pointer Instance) const {85 assert(this->Base.isZero());86 return MemberPointer(Instance, this->Dcl, this->PtrOffset);87 }88 89 APValue toAPValue(const ASTContext &) const;90 91 bool isZero() const { return Base.isZero() && !Dcl; }92 bool hasBase() const { return !Base.isZero(); }93 bool isWeak() const {94 if (const auto *MF = getMemberFunction())95 return MF->isWeak();96 return false;97 }98 99 void print(llvm::raw_ostream &OS) const {100 OS << "MemberPtr(" << Base << " " << (const void *)Dcl << " + " << PtrOffset101 << ")";102 }103 104 std::string toDiagnosticString(const ASTContext &Ctx) const {105 return toAPValue(Ctx).getAsString(Ctx, Dcl->getType());106 }107 108 ComparisonCategoryResult compare(const MemberPointer &RHS) const {109 if (this->Dcl == RHS.Dcl)110 return ComparisonCategoryResult::Equal;111 return ComparisonCategoryResult::Unordered;112 }113};114 115inline llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, MemberPointer FP) {116 FP.print(OS);117 return OS;118}119 120} // namespace interp121} // namespace clang122 123#endif124