1a07aba5dSTimm Baeder //===------------------------- MemberPointer.cpp ----------------*- C++ -*-===// 2a07aba5dSTimm Baeder // 3a07aba5dSTimm Baeder // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4a07aba5dSTimm Baeder // See https://llvm.org/LICENSE.txt for license information. 5a07aba5dSTimm Baeder // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6a07aba5dSTimm Baeder // 7a07aba5dSTimm Baeder //===----------------------------------------------------------------------===// 8a07aba5dSTimm Baeder 9a07aba5dSTimm Baeder #include "MemberPointer.h" 10a07aba5dSTimm Baeder #include "Context.h" 11a07aba5dSTimm Baeder #include "FunctionPointer.h" 12a07aba5dSTimm Baeder #include "Program.h" 13a07aba5dSTimm Baeder #include "Record.h" 14a07aba5dSTimm Baeder 15a07aba5dSTimm Baeder namespace clang { 16a07aba5dSTimm Baeder namespace interp { 17a07aba5dSTimm Baeder 18a07aba5dSTimm Baeder std::optional<Pointer> MemberPointer::toPointer(const Context &Ctx) const { 19a07aba5dSTimm Baeder if (!Dcl || isa<FunctionDecl>(Dcl)) 20a07aba5dSTimm Baeder return Base; 21c6605a08STimm Baeder assert((isa<FieldDecl, IndirectFieldDecl>(Dcl))); 22a07aba5dSTimm Baeder 23a07aba5dSTimm Baeder if (!Base.isBlockPointer()) 24a07aba5dSTimm Baeder return std::nullopt; 25a07aba5dSTimm Baeder 26a07aba5dSTimm Baeder Pointer CastedBase = 27a07aba5dSTimm Baeder (PtrOffset < 0 ? Base.atField(-PtrOffset) : Base.atFieldSub(PtrOffset)); 28a07aba5dSTimm Baeder 29a07aba5dSTimm Baeder const Record *BaseRecord = CastedBase.getRecord(); 30a07aba5dSTimm Baeder if (!BaseRecord) 31a07aba5dSTimm Baeder return std::nullopt; 32a07aba5dSTimm Baeder 33c6605a08STimm Baeder unsigned Offset = 0; 34c6605a08STimm Baeder Offset += CastedBase.block()->getDescriptor()->getMetadataSize(); 35c6605a08STimm Baeder 36c6605a08STimm Baeder if (const auto *FD = dyn_cast<FieldDecl>(Dcl)) { 37a07aba5dSTimm Baeder if (FD->getParent() == BaseRecord->getDecl()) 38a07aba5dSTimm Baeder return CastedBase.atField(BaseRecord->getField(FD)->Offset); 39a07aba5dSTimm Baeder 40a07aba5dSTimm Baeder const RecordDecl *FieldParent = FD->getParent(); 41a07aba5dSTimm Baeder const Record *FieldRecord = Ctx.getRecord(FieldParent); 42a07aba5dSTimm Baeder 43a07aba5dSTimm Baeder Offset += FieldRecord->getField(FD)->Offset; 44a07aba5dSTimm Baeder if (Offset > CastedBase.block()->getSize()) 45a07aba5dSTimm Baeder return std::nullopt; 46a07aba5dSTimm Baeder 47a07aba5dSTimm Baeder if (const RecordDecl *BaseDecl = Base.getDeclPtr().getRecord()->getDecl(); 48a07aba5dSTimm Baeder BaseDecl != FieldParent) 49a07aba5dSTimm Baeder Offset += Ctx.collectBaseOffset(FieldParent, BaseDecl); 50a07aba5dSTimm Baeder 51c6605a08STimm Baeder } else { 52c6605a08STimm Baeder const auto *IFD = cast<IndirectFieldDecl>(Dcl); 53c6605a08STimm Baeder 54c6605a08STimm Baeder for (const NamedDecl *ND : IFD->chain()) { 55c6605a08STimm Baeder const FieldDecl *F = cast<FieldDecl>(ND); 56c6605a08STimm Baeder const RecordDecl *FieldParent = F->getParent(); 57c6605a08STimm Baeder const Record *FieldRecord = Ctx.getRecord(FieldParent); 58c6605a08STimm Baeder Offset += FieldRecord->getField(F)->Offset; 59c6605a08STimm Baeder } 60c6605a08STimm Baeder } 61c6605a08STimm Baeder 62c6605a08STimm Baeder assert(BaseRecord); 63a07aba5dSTimm Baeder if (Offset > CastedBase.block()->getSize()) 64a07aba5dSTimm Baeder return std::nullopt; 65a07aba5dSTimm Baeder 66a07aba5dSTimm Baeder assert(Offset <= CastedBase.block()->getSize()); 67a07aba5dSTimm Baeder return Pointer(const_cast<Block *>(Base.block()), Offset, Offset); 68a07aba5dSTimm Baeder } 69a07aba5dSTimm Baeder 70a07aba5dSTimm Baeder FunctionPointer MemberPointer::toFunctionPointer(const Context &Ctx) const { 71a07aba5dSTimm Baeder return FunctionPointer(Ctx.getProgram().getFunction(cast<FunctionDecl>(Dcl))); 72a07aba5dSTimm Baeder } 73a07aba5dSTimm Baeder 74a07aba5dSTimm Baeder APValue MemberPointer::toAPValue(const ASTContext &ASTCtx) const { 75a07aba5dSTimm Baeder if (isZero()) 76a07aba5dSTimm Baeder return APValue(static_cast<ValueDecl *>(nullptr), /*IsDerivedMember=*/false, 77a07aba5dSTimm Baeder /*Path=*/{}); 78a07aba5dSTimm Baeder 79a07aba5dSTimm Baeder if (hasBase()) 80a07aba5dSTimm Baeder return Base.toAPValue(ASTCtx); 81a07aba5dSTimm Baeder 82*f3111cc7STimm Bäder return APValue(getDecl(), /*IsDerivedMember=*/false, 83a07aba5dSTimm Baeder /*Path=*/{}); 84a07aba5dSTimm Baeder } 85a07aba5dSTimm Baeder 86a07aba5dSTimm Baeder } // namespace interp 87a07aba5dSTimm Baeder } // namespace clang 88