xref: /freebsd/contrib/llvm-project/clang/lib/AST/Interp/MemberPointer.h (revision 7fdf597e96a02165cfe22ff357b857d5fa15ed8a)
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