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