mirror of
https://github.com/llvm/llvm-project.git
synced 2025-04-28 21:06:06 +00:00
88 lines
2.7 KiB
C++
88 lines
2.7 KiB
C++
//===------------------------- MemberPointer.cpp ----------------*- C++ -*-===//
|
|
//
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "MemberPointer.h"
|
|
#include "Context.h"
|
|
#include "FunctionPointer.h"
|
|
#include "Program.h"
|
|
#include "Record.h"
|
|
|
|
namespace clang {
|
|
namespace interp {
|
|
|
|
std::optional<Pointer> MemberPointer::toPointer(const Context &Ctx) const {
|
|
if (!Dcl || isa<FunctionDecl>(Dcl))
|
|
return Base;
|
|
assert((isa<FieldDecl, IndirectFieldDecl>(Dcl)));
|
|
|
|
if (!Base.isBlockPointer())
|
|
return std::nullopt;
|
|
|
|
Pointer CastedBase =
|
|
(PtrOffset < 0 ? Base.atField(-PtrOffset) : Base.atFieldSub(PtrOffset));
|
|
|
|
const Record *BaseRecord = CastedBase.getRecord();
|
|
if (!BaseRecord)
|
|
return std::nullopt;
|
|
|
|
unsigned Offset = 0;
|
|
Offset += CastedBase.block()->getDescriptor()->getMetadataSize();
|
|
|
|
if (const auto *FD = dyn_cast<FieldDecl>(Dcl)) {
|
|
if (FD->getParent() == BaseRecord->getDecl())
|
|
return CastedBase.atField(BaseRecord->getField(FD)->Offset);
|
|
|
|
const RecordDecl *FieldParent = FD->getParent();
|
|
const Record *FieldRecord = Ctx.getRecord(FieldParent);
|
|
|
|
Offset += FieldRecord->getField(FD)->Offset;
|
|
if (Offset > CastedBase.block()->getSize())
|
|
return std::nullopt;
|
|
|
|
if (const RecordDecl *BaseDecl = Base.getDeclPtr().getRecord()->getDecl();
|
|
BaseDecl != FieldParent)
|
|
Offset += Ctx.collectBaseOffset(FieldParent, BaseDecl);
|
|
|
|
} else {
|
|
const auto *IFD = cast<IndirectFieldDecl>(Dcl);
|
|
|
|
for (const NamedDecl *ND : IFD->chain()) {
|
|
const FieldDecl *F = cast<FieldDecl>(ND);
|
|
const RecordDecl *FieldParent = F->getParent();
|
|
const Record *FieldRecord = Ctx.getRecord(FieldParent);
|
|
Offset += FieldRecord->getField(F)->Offset;
|
|
}
|
|
}
|
|
|
|
assert(BaseRecord);
|
|
if (Offset > CastedBase.block()->getSize())
|
|
return std::nullopt;
|
|
|
|
assert(Offset <= CastedBase.block()->getSize());
|
|
return Pointer(const_cast<Block *>(Base.block()), Offset, Offset);
|
|
}
|
|
|
|
FunctionPointer MemberPointer::toFunctionPointer(const Context &Ctx) const {
|
|
return FunctionPointer(Ctx.getProgram().getFunction(cast<FunctionDecl>(Dcl)));
|
|
}
|
|
|
|
APValue MemberPointer::toAPValue(const ASTContext &ASTCtx) const {
|
|
if (isZero())
|
|
return APValue(static_cast<ValueDecl *>(nullptr), /*IsDerivedMember=*/false,
|
|
/*Path=*/{});
|
|
|
|
if (hasBase())
|
|
return Base.toAPValue(ASTCtx);
|
|
|
|
return APValue(getDecl(), /*IsDerivedMember=*/false,
|
|
/*Path=*/{});
|
|
}
|
|
|
|
} // namespace interp
|
|
} // namespace clang
|