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
15namespace clang {
16class ASTContext;
17namespace interp {
18
19class Context;
20class FunctionPointer;
21
22class MemberPointer final {
23private:
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
31public:
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(Off: -PtrOffset);
57 return Base.atFieldSub(Off: PtrOffset);
58 }
59 bool isMemberFunctionPointer() const {
60 return isa_and_nonnull<CXXMethodDecl>(Val: Dcl);
61 }
62 const CXXMethodDecl *getMemberFunction() const {
63 return dyn_cast_if_present<CXXMethodDecl>(Val: Dcl);
64 }
65 const FieldDecl *getField() const {
66 return dyn_cast_if_present<FieldDecl>(Val: 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
104inline 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