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