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