xref: /freebsd/contrib/llvm-project/clang/lib/AST/ByteCode/MemberPointer.h (revision 700637cbb5e582861067a11aaca4d053546871d2)
1*700637cbSDimitry Andric //===------------------------- MemberPointer.h ------------------*- C++ -*-===//
2*700637cbSDimitry Andric //
3*700637cbSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*700637cbSDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5*700637cbSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*700637cbSDimitry Andric //
7*700637cbSDimitry Andric //===----------------------------------------------------------------------===//
8*700637cbSDimitry Andric 
9*700637cbSDimitry Andric #ifndef LLVM_CLANG_AST_INTERP_MEMBER_POINTER_H
10*700637cbSDimitry Andric #define LLVM_CLANG_AST_INTERP_MEMBER_POINTER_H
11*700637cbSDimitry Andric 
12*700637cbSDimitry Andric #include "Pointer.h"
13*700637cbSDimitry Andric #include <optional>
14*700637cbSDimitry Andric 
15*700637cbSDimitry Andric namespace clang {
16*700637cbSDimitry Andric class ASTContext;
17*700637cbSDimitry Andric namespace interp {
18*700637cbSDimitry Andric 
19*700637cbSDimitry Andric class Context;
20*700637cbSDimitry Andric class FunctionPointer;
21*700637cbSDimitry Andric 
22*700637cbSDimitry Andric class MemberPointer final {
23*700637cbSDimitry Andric private:
24*700637cbSDimitry Andric   Pointer Base;
25*700637cbSDimitry Andric   const ValueDecl *Dcl = nullptr;
26*700637cbSDimitry Andric   int32_t PtrOffset = 0;
27*700637cbSDimitry Andric 
MemberPointer(Pointer Base,const ValueDecl * Dcl,int32_t PtrOffset)28*700637cbSDimitry Andric   MemberPointer(Pointer Base, const ValueDecl *Dcl, int32_t PtrOffset)
29*700637cbSDimitry Andric       : Base(Base), Dcl(Dcl), PtrOffset(PtrOffset) {}
30*700637cbSDimitry Andric 
31*700637cbSDimitry Andric public:
32*700637cbSDimitry Andric   MemberPointer() = default;
MemberPointer(Pointer Base,const ValueDecl * Dcl)33*700637cbSDimitry Andric   MemberPointer(Pointer Base, const ValueDecl *Dcl) : Base(Base), Dcl(Dcl) {}
MemberPointer(uint32_t Address,const Descriptor * D)34*700637cbSDimitry Andric   MemberPointer(uint32_t Address, const Descriptor *D) {
35*700637cbSDimitry Andric     // We only reach this for Address == 0, when creating a null member pointer.
36*700637cbSDimitry Andric     assert(Address == 0);
37*700637cbSDimitry Andric   }
38*700637cbSDimitry Andric 
MemberPointer(const ValueDecl * D)39*700637cbSDimitry Andric   MemberPointer(const ValueDecl *D) : Dcl(D) {
40*700637cbSDimitry Andric     assert((isa<FieldDecl, IndirectFieldDecl, CXXMethodDecl>(D)));
41*700637cbSDimitry Andric   }
42*700637cbSDimitry Andric 
getIntegerRepresentation()43*700637cbSDimitry Andric   uint64_t getIntegerRepresentation() const {
44*700637cbSDimitry Andric     assert(
45*700637cbSDimitry Andric         false &&
46*700637cbSDimitry Andric         "getIntegerRepresentation() shouldn't be reachable for MemberPointers");
47*700637cbSDimitry Andric     return 17;
48*700637cbSDimitry Andric   }
49*700637cbSDimitry Andric 
50*700637cbSDimitry Andric   std::optional<Pointer> toPointer(const Context &Ctx) const;
51*700637cbSDimitry Andric 
52*700637cbSDimitry Andric   FunctionPointer toFunctionPointer(const Context &Ctx) const;
53*700637cbSDimitry Andric 
getBase()54*700637cbSDimitry Andric   Pointer getBase() const {
55*700637cbSDimitry Andric     if (PtrOffset < 0)
56*700637cbSDimitry Andric       return Base.atField(-PtrOffset);
57*700637cbSDimitry Andric     return Base.atFieldSub(PtrOffset);
58*700637cbSDimitry Andric   }
isMemberFunctionPointer()59*700637cbSDimitry Andric   bool isMemberFunctionPointer() const {
60*700637cbSDimitry Andric     return isa_and_nonnull<CXXMethodDecl>(Dcl);
61*700637cbSDimitry Andric   }
getMemberFunction()62*700637cbSDimitry Andric   const CXXMethodDecl *getMemberFunction() const {
63*700637cbSDimitry Andric     return dyn_cast_if_present<CXXMethodDecl>(Dcl);
64*700637cbSDimitry Andric   }
getField()65*700637cbSDimitry Andric   const FieldDecl *getField() const {
66*700637cbSDimitry Andric     return dyn_cast_if_present<FieldDecl>(Dcl);
67*700637cbSDimitry Andric   }
68*700637cbSDimitry Andric 
hasDecl()69*700637cbSDimitry Andric   bool hasDecl() const { return Dcl; }
getDecl()70*700637cbSDimitry Andric   const ValueDecl *getDecl() const { return Dcl; }
71*700637cbSDimitry Andric 
atInstanceBase(unsigned Offset)72*700637cbSDimitry Andric   MemberPointer atInstanceBase(unsigned Offset) const {
73*700637cbSDimitry Andric     if (Base.isZero())
74*700637cbSDimitry Andric       return MemberPointer(Base, Dcl, Offset);
75*700637cbSDimitry Andric     return MemberPointer(this->Base, Dcl, Offset + PtrOffset);
76*700637cbSDimitry Andric   }
77*700637cbSDimitry Andric 
takeInstance(Pointer Instance)78*700637cbSDimitry Andric   MemberPointer takeInstance(Pointer Instance) const {
79*700637cbSDimitry Andric     assert(this->Base.isZero());
80*700637cbSDimitry Andric     return MemberPointer(Instance, this->Dcl, this->PtrOffset);
81*700637cbSDimitry Andric   }
82*700637cbSDimitry Andric 
83*700637cbSDimitry Andric   APValue toAPValue(const ASTContext &) const;
84*700637cbSDimitry Andric 
isZero()85*700637cbSDimitry Andric   bool isZero() const { return Base.isZero() && !Dcl; }
hasBase()86*700637cbSDimitry Andric   bool hasBase() const { return !Base.isZero(); }
isWeak()87*700637cbSDimitry Andric   bool isWeak() const {
88*700637cbSDimitry Andric     if (const auto *MF = getMemberFunction())
89*700637cbSDimitry Andric       return MF->isWeak();
90*700637cbSDimitry Andric     return false;
91*700637cbSDimitry Andric   }
92*700637cbSDimitry Andric 
print(llvm::raw_ostream & OS)93*700637cbSDimitry Andric   void print(llvm::raw_ostream &OS) const {
94*700637cbSDimitry Andric     OS << "MemberPtr(" << Base << " " << (const void *)Dcl << " + " << PtrOffset
95*700637cbSDimitry Andric        << ")";
96*700637cbSDimitry Andric   }
97*700637cbSDimitry Andric 
toDiagnosticString(const ASTContext & Ctx)98*700637cbSDimitry Andric   std::string toDiagnosticString(const ASTContext &Ctx) const {
99*700637cbSDimitry Andric     return toAPValue(Ctx).getAsString(Ctx, Dcl->getType());
100*700637cbSDimitry Andric   }
101*700637cbSDimitry Andric 
compare(const MemberPointer & RHS)102*700637cbSDimitry Andric   ComparisonCategoryResult compare(const MemberPointer &RHS) const {
103*700637cbSDimitry Andric     if (this->Dcl == RHS.Dcl)
104*700637cbSDimitry Andric       return ComparisonCategoryResult::Equal;
105*700637cbSDimitry Andric     return ComparisonCategoryResult::Unordered;
106*700637cbSDimitry Andric   }
107*700637cbSDimitry Andric };
108*700637cbSDimitry Andric 
109*700637cbSDimitry Andric inline llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, MemberPointer FP) {
110*700637cbSDimitry Andric   FP.print(OS);
111*700637cbSDimitry Andric   return OS;
112*700637cbSDimitry Andric }
113*700637cbSDimitry Andric 
114*700637cbSDimitry Andric } // namespace interp
115*700637cbSDimitry Andric } // namespace clang
116*700637cbSDimitry Andric 
117*700637cbSDimitry Andric #endif
118