xref: /llvm-project/clang/lib/AST/ByteCode/MemberPointer.h (revision 6f81c878ecd40acf1a0364e0ea5c9e6ea87407a2)
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