Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/clang/lib/AST/ByteCode/MemberPointer.cpp
213799 views
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
18
std::optional<Pointer> MemberPointer::toPointer(const Context &Ctx) const {
19
if (!Dcl || isa<FunctionDecl>(Dcl))
20
return Base;
21
assert((isa<FieldDecl, IndirectFieldDecl>(Dcl)));
22
23
if (!Base.isBlockPointer())
24
return std::nullopt;
25
26
Pointer CastedBase =
27
(PtrOffset < 0 ? Base.atField(-PtrOffset) : Base.atFieldSub(PtrOffset));
28
29
const Record *BaseRecord = CastedBase.getRecord();
30
if (!BaseRecord)
31
return std::nullopt;
32
33
unsigned Offset = 0;
34
Offset += CastedBase.block()->getDescriptor()->getMetadataSize();
35
36
if (const auto *FD = dyn_cast<FieldDecl>(Dcl)) {
37
if (FD->getParent() == BaseRecord->getDecl())
38
return CastedBase.atField(BaseRecord->getField(FD)->Offset);
39
40
const RecordDecl *FieldParent = FD->getParent();
41
const Record *FieldRecord = Ctx.getRecord(FieldParent);
42
43
Offset += FieldRecord->getField(FD)->Offset;
44
if (Offset > CastedBase.block()->getSize())
45
return std::nullopt;
46
47
if (const RecordDecl *BaseDecl = Base.getDeclPtr().getRecord()->getDecl();
48
BaseDecl != FieldParent)
49
Offset += Ctx.collectBaseOffset(FieldParent, BaseDecl);
50
51
} else {
52
const auto *IFD = cast<IndirectFieldDecl>(Dcl);
53
54
for (const NamedDecl *ND : IFD->chain()) {
55
const FieldDecl *F = cast<FieldDecl>(ND);
56
const RecordDecl *FieldParent = F->getParent();
57
const Record *FieldRecord = Ctx.getRecord(FieldParent);
58
Offset += FieldRecord->getField(F)->Offset;
59
}
60
}
61
62
assert(BaseRecord);
63
if (Offset > CastedBase.block()->getSize())
64
return std::nullopt;
65
66
assert(Offset <= CastedBase.block()->getSize());
67
return Pointer(const_cast<Block *>(Base.block()), Offset, Offset);
68
}
69
70
FunctionPointer MemberPointer::toFunctionPointer(const Context &Ctx) const {
71
return FunctionPointer(Ctx.getProgram().getFunction(cast<FunctionDecl>(Dcl)));
72
}
73
74
APValue MemberPointer::toAPValue(const ASTContext &ASTCtx) const {
75
if (isZero())
76
return APValue(static_cast<ValueDecl *>(nullptr), /*IsDerivedMember=*/false,
77
/*Path=*/{});
78
79
if (hasBase())
80
return Base.toAPValue(ASTCtx);
81
82
return APValue(getDecl(), /*IsDerivedMember=*/false,
83
/*Path=*/{});
84
}
85
86
} // namespace interp
87
} // namespace clang
88
89