1*700637cbSDimitry Andric //===------------------------- MemberPointer.cpp ----------------*- 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 #include "MemberPointer.h" 10*700637cbSDimitry Andric #include "Context.h" 11*700637cbSDimitry Andric #include "FunctionPointer.h" 12*700637cbSDimitry Andric #include "Program.h" 13*700637cbSDimitry Andric #include "Record.h" 14*700637cbSDimitry Andric 15*700637cbSDimitry Andric namespace clang { 16*700637cbSDimitry Andric namespace interp { 17*700637cbSDimitry Andric toPointer(const Context & Ctx) const18*700637cbSDimitry Andricstd::optional<Pointer> MemberPointer::toPointer(const Context &Ctx) const { 19*700637cbSDimitry Andric if (!Dcl || isa<FunctionDecl>(Dcl)) 20*700637cbSDimitry Andric return Base; 21*700637cbSDimitry Andric assert((isa<FieldDecl, IndirectFieldDecl>(Dcl))); 22*700637cbSDimitry Andric 23*700637cbSDimitry Andric if (!Base.isBlockPointer()) 24*700637cbSDimitry Andric return std::nullopt; 25*700637cbSDimitry Andric 26*700637cbSDimitry Andric Pointer CastedBase = 27*700637cbSDimitry Andric (PtrOffset < 0 ? Base.atField(-PtrOffset) : Base.atFieldSub(PtrOffset)); 28*700637cbSDimitry Andric 29*700637cbSDimitry Andric const Record *BaseRecord = CastedBase.getRecord(); 30*700637cbSDimitry Andric if (!BaseRecord) 31*700637cbSDimitry Andric return std::nullopt; 32*700637cbSDimitry Andric 33*700637cbSDimitry Andric unsigned Offset = 0; 34*700637cbSDimitry Andric Offset += CastedBase.block()->getDescriptor()->getMetadataSize(); 35*700637cbSDimitry Andric 36*700637cbSDimitry Andric if (const auto *FD = dyn_cast<FieldDecl>(Dcl)) { 37*700637cbSDimitry Andric if (FD->getParent() == BaseRecord->getDecl()) 38*700637cbSDimitry Andric return CastedBase.atField(BaseRecord->getField(FD)->Offset); 39*700637cbSDimitry Andric 40*700637cbSDimitry Andric const RecordDecl *FieldParent = FD->getParent(); 41*700637cbSDimitry Andric const Record *FieldRecord = Ctx.getRecord(FieldParent); 42*700637cbSDimitry Andric 43*700637cbSDimitry Andric Offset += FieldRecord->getField(FD)->Offset; 44*700637cbSDimitry Andric if (Offset > CastedBase.block()->getSize()) 45*700637cbSDimitry Andric return std::nullopt; 46*700637cbSDimitry Andric 47*700637cbSDimitry Andric if (const RecordDecl *BaseDecl = Base.getDeclPtr().getRecord()->getDecl(); 48*700637cbSDimitry Andric BaseDecl != FieldParent) 49*700637cbSDimitry Andric Offset += Ctx.collectBaseOffset(FieldParent, BaseDecl); 50*700637cbSDimitry Andric 51*700637cbSDimitry Andric } else { 52*700637cbSDimitry Andric const auto *IFD = cast<IndirectFieldDecl>(Dcl); 53*700637cbSDimitry Andric 54*700637cbSDimitry Andric for (const NamedDecl *ND : IFD->chain()) { 55*700637cbSDimitry Andric const FieldDecl *F = cast<FieldDecl>(ND); 56*700637cbSDimitry Andric const RecordDecl *FieldParent = F->getParent(); 57*700637cbSDimitry Andric const Record *FieldRecord = Ctx.getRecord(FieldParent); 58*700637cbSDimitry Andric Offset += FieldRecord->getField(F)->Offset; 59*700637cbSDimitry Andric } 60*700637cbSDimitry Andric } 61*700637cbSDimitry Andric 62*700637cbSDimitry Andric assert(BaseRecord); 63*700637cbSDimitry Andric if (Offset > CastedBase.block()->getSize()) 64*700637cbSDimitry Andric return std::nullopt; 65*700637cbSDimitry Andric 66*700637cbSDimitry Andric assert(Offset <= CastedBase.block()->getSize()); 67*700637cbSDimitry Andric return Pointer(const_cast<Block *>(Base.block()), Offset, Offset); 68*700637cbSDimitry Andric } 69*700637cbSDimitry Andric toFunctionPointer(const Context & Ctx) const70*700637cbSDimitry AndricFunctionPointer MemberPointer::toFunctionPointer(const Context &Ctx) const { 71*700637cbSDimitry Andric return FunctionPointer(Ctx.getProgram().getFunction(cast<FunctionDecl>(Dcl))); 72*700637cbSDimitry Andric } 73*700637cbSDimitry Andric toAPValue(const ASTContext & ASTCtx) const74*700637cbSDimitry AndricAPValue MemberPointer::toAPValue(const ASTContext &ASTCtx) const { 75*700637cbSDimitry Andric if (isZero()) 76*700637cbSDimitry Andric return APValue(static_cast<ValueDecl *>(nullptr), /*IsDerivedMember=*/false, 77*700637cbSDimitry Andric /*Path=*/{}); 78*700637cbSDimitry Andric 79*700637cbSDimitry Andric if (hasBase()) 80*700637cbSDimitry Andric return Base.toAPValue(ASTCtx); 81*700637cbSDimitry Andric 82*700637cbSDimitry Andric return APValue(getDecl(), /*IsDerivedMember=*/false, 83*700637cbSDimitry Andric /*Path=*/{}); 84*700637cbSDimitry Andric } 85*700637cbSDimitry Andric 86*700637cbSDimitry Andric } // namespace interp 87*700637cbSDimitry Andric } // namespace clang 88