xref: /freebsd/contrib/llvm-project/clang/lib/AST/ByteCode/MemberPointer.h (revision 700637cbb5e582861067a11aaca4d053546871d2)
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 ValueDecl *Dcl = nullptr;
26   int32_t PtrOffset = 0;
27 
MemberPointer(Pointer Base,const ValueDecl * Dcl,int32_t PtrOffset)28   MemberPointer(Pointer Base, const ValueDecl *Dcl, int32_t PtrOffset)
29       : Base(Base), Dcl(Dcl), PtrOffset(PtrOffset) {}
30 
31 public:
32   MemberPointer() = default;
MemberPointer(Pointer Base,const ValueDecl * Dcl)33   MemberPointer(Pointer Base, const ValueDecl *Dcl) : Base(Base), Dcl(Dcl) {}
MemberPointer(uint32_t Address,const Descriptor * D)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 
MemberPointer(const ValueDecl * D)39   MemberPointer(const ValueDecl *D) : Dcl(D) {
40     assert((isa<FieldDecl, IndirectFieldDecl, CXXMethodDecl>(D)));
41   }
42 
getIntegerRepresentation()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 
getBase()54   Pointer getBase() const {
55     if (PtrOffset < 0)
56       return Base.atField(-PtrOffset);
57     return Base.atFieldSub(PtrOffset);
58   }
isMemberFunctionPointer()59   bool isMemberFunctionPointer() const {
60     return isa_and_nonnull<CXXMethodDecl>(Dcl);
61   }
getMemberFunction()62   const CXXMethodDecl *getMemberFunction() const {
63     return dyn_cast_if_present<CXXMethodDecl>(Dcl);
64   }
getField()65   const FieldDecl *getField() const {
66     return dyn_cast_if_present<FieldDecl>(Dcl);
67   }
68 
hasDecl()69   bool hasDecl() const { return Dcl; }
getDecl()70   const ValueDecl *getDecl() const { return Dcl; }
71 
atInstanceBase(unsigned Offset)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 
takeInstance(Pointer Instance)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 
isZero()85   bool isZero() const { return Base.isZero() && !Dcl; }
hasBase()86   bool hasBase() const { return !Base.isZero(); }
isWeak()87   bool isWeak() const {
88     if (const auto *MF = getMemberFunction())
89       return MF->isWeak();
90     return false;
91   }
92 
print(llvm::raw_ostream & OS)93   void print(llvm::raw_ostream &OS) const {
94     OS << "MemberPtr(" << Base << " " << (const void *)Dcl << " + " << PtrOffset
95        << ")";
96   }
97 
toDiagnosticString(const ASTContext & Ctx)98   std::string toDiagnosticString(const ASTContext &Ctx) const {
99     return toAPValue(Ctx).getAsString(Ctx, Dcl->getType());
100   }
101 
compare(const MemberPointer & RHS)102   ComparisonCategoryResult compare(const MemberPointer &RHS) const {
103     if (this->Dcl == RHS.Dcl)
104       return ComparisonCategoryResult::Equal;
105     return ComparisonCategoryResult::Unordered;
106   }
107 };
108 
109 inline llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, MemberPointer FP) {
110   FP.print(OS);
111   return OS;
112 }
113 
114 } // namespace interp
115 } // namespace clang
116 
117 #endif
118