summaryrefslogtreecommitdiff
path: root/clang/lib/AST/Interp/Descriptor.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib/AST/Interp/Descriptor.cpp')
-rw-r--r--clang/lib/AST/Interp/Descriptor.cpp70
1 files changed, 45 insertions, 25 deletions
diff --git a/clang/lib/AST/Interp/Descriptor.cpp b/clang/lib/AST/Interp/Descriptor.cpp
index 671f2c03d7e5..634413b2f2f5 100644
--- a/clang/lib/AST/Interp/Descriptor.cpp
+++ b/clang/lib/AST/Interp/Descriptor.cpp
@@ -20,7 +20,7 @@ using namespace clang;
using namespace clang::interp;
template <typename T>
-static void ctorTy(Block *, std::byte *Ptr, bool, bool, bool,
+static void ctorTy(Block *, std::byte *Ptr, bool, bool, bool, bool,
const Descriptor *) {
new (Ptr) T();
}
@@ -40,7 +40,7 @@ static void moveTy(Block *, const std::byte *Src, std::byte *Dst,
}
template <typename T>
-static void ctorArrayTy(Block *, std::byte *Ptr, bool, bool, bool,
+static void ctorArrayTy(Block *, std::byte *Ptr, bool, bool, bool, bool,
const Descriptor *D) {
new (Ptr) InitMapPtr(std::nullopt);
@@ -76,14 +76,15 @@ static void moveArrayTy(Block *, const std::byte *Src, std::byte *Dst,
Src += sizeof(InitMapPtr);
Dst += sizeof(InitMapPtr);
for (unsigned I = 0, NE = D->getNumElems(); I < NE; ++I) {
- const auto *SrcPtr = &reinterpret_cast<const T *>(Src)[I];
+ auto *SrcPtr = &reinterpret_cast<T *>(const_cast<std::byte *>(Src))[I];
auto *DstPtr = &reinterpret_cast<T *>(Dst)[I];
new (DstPtr) T(std::move(*SrcPtr));
}
}
static void ctorArrayDesc(Block *B, std::byte *Ptr, bool IsConst,
- bool IsMutable, bool IsActive, const Descriptor *D) {
+ bool IsMutable, bool IsActive, bool InUnion,
+ const Descriptor *D) {
const unsigned NumElems = D->getNumElems();
const unsigned ElemSize =
D->ElemDesc->getAllocSize() + sizeof(InlineDescriptor);
@@ -102,9 +103,11 @@ static void ctorArrayDesc(Block *B, std::byte *Ptr, bool IsConst,
Desc->IsActive = IsActive;
Desc->IsConst = IsConst || D->IsConst;
Desc->IsFieldMutable = IsMutable || D->IsMutable;
+ Desc->InUnion = InUnion;
+
if (auto Fn = D->ElemDesc->CtorFn)
Fn(B, ElemLoc, Desc->IsConst, Desc->IsFieldMutable, IsActive,
- D->ElemDesc);
+ Desc->InUnion || SD->isUnion(), D->ElemDesc);
}
}
@@ -146,25 +149,26 @@ static void moveArrayDesc(Block *B, const std::byte *Src, std::byte *Dst,
}
static void initField(Block *B, std::byte *Ptr, bool IsConst, bool IsMutable,
- bool IsActive, bool IsUnion, const Descriptor *D,
- unsigned FieldOffset) {
+ bool IsActive, bool IsUnionField, bool InUnion,
+ const Descriptor *D, unsigned FieldOffset) {
auto *Desc = reinterpret_cast<InlineDescriptor *>(Ptr + FieldOffset) - 1;
Desc->Offset = FieldOffset;
Desc->Desc = D;
Desc->IsInitialized = D->IsArray;
Desc->IsBase = false;
- Desc->IsActive = IsActive && !IsUnion;
+ Desc->IsActive = IsActive && !IsUnionField;
+ Desc->InUnion = InUnion;
Desc->IsConst = IsConst || D->IsConst;
Desc->IsFieldMutable = IsMutable || D->IsMutable;
if (auto Fn = D->CtorFn)
Fn(B, Ptr + FieldOffset, Desc->IsConst, Desc->IsFieldMutable,
- Desc->IsActive, D);
+ Desc->IsActive, InUnion || D->isUnion(), D);
}
static void initBase(Block *B, std::byte *Ptr, bool IsConst, bool IsMutable,
- bool IsActive, const Descriptor *D, unsigned FieldOffset,
- bool IsVirtualBase) {
+ bool IsActive, bool InUnion, const Descriptor *D,
+ unsigned FieldOffset, bool IsVirtualBase) {
assert(D);
assert(D->ElemRecord);
@@ -180,21 +184,26 @@ static void initBase(Block *B, std::byte *Ptr, bool IsConst, bool IsMutable,
Desc->IsFieldMutable = IsMutable || D->IsMutable;
for (const auto &V : D->ElemRecord->bases())
- initBase(B, Ptr + FieldOffset, IsConst, IsMutable, IsActive, V.Desc,
- V.Offset, false);
+ initBase(B, Ptr + FieldOffset, IsConst, IsMutable, IsActive, InUnion,
+ V.Desc, V.Offset, false);
for (const auto &F : D->ElemRecord->fields())
- initField(B, Ptr + FieldOffset, IsConst, IsMutable, IsActive, IsUnion,
- F.Desc, F.Offset);
+ initField(B, Ptr + FieldOffset, IsConst, IsMutable, IsActive, InUnion,
+ IsUnion, F.Desc, F.Offset);
}
static void ctorRecord(Block *B, std::byte *Ptr, bool IsConst, bool IsMutable,
- bool IsActive, const Descriptor *D) {
+ bool IsActive, bool InUnion, const Descriptor *D) {
for (const auto &V : D->ElemRecord->bases())
- initBase(B, Ptr, IsConst, IsMutable, IsActive, V.Desc, V.Offset, false);
- for (const auto &F : D->ElemRecord->fields())
- initField(B, Ptr, IsConst, IsMutable, IsActive, D->ElemRecord->isUnion(), F.Desc, F.Offset);
+ initBase(B, Ptr, IsConst, IsMutable, IsActive, false, V.Desc, V.Offset,
+ false);
+ for (const auto &F : D->ElemRecord->fields()) {
+ bool IsUnionField = D->isUnion();
+ initField(B, Ptr, IsConst, IsMutable, IsActive, IsUnionField,
+ InUnion || IsUnionField, F.Desc, F.Offset);
+ }
for (const auto &V : D->ElemRecord->virtual_bases())
- initBase(B, Ptr, IsConst, IsMutable, IsActive, V.Desc, V.Offset, true);
+ initBase(B, Ptr, IsConst, IsMutable, IsActive, false, V.Desc, V.Offset,
+ true);
}
static void destroyField(Block *B, std::byte *Ptr, const Descriptor *D,
@@ -225,12 +234,21 @@ static void dtorRecord(Block *B, std::byte *Ptr, const Descriptor *D) {
static void moveRecord(Block *B, const std::byte *Src, std::byte *Dst,
const Descriptor *D) {
- for (const auto &F : D->ElemRecord->fields()) {
- auto FieldOff = F.Offset;
- auto *FieldDesc = F.Desc;
+ assert(D);
+ assert(D->ElemRecord);
- if (auto Fn = FieldDesc->MoveFn)
- Fn(B, Src + FieldOff, Dst + FieldOff, FieldDesc);
+ // FIXME: There might be cases where we need to move over the (v)bases as
+ // well.
+ for (const auto &F : D->ElemRecord->fields()) {
+ auto FieldOffset = F.Offset;
+ const auto *SrcDesc =
+ reinterpret_cast<const InlineDescriptor *>(Src + FieldOffset) - 1;
+ auto *DestDesc =
+ reinterpret_cast<InlineDescriptor *>(Dst + FieldOffset) - 1;
+ std::memcpy(DestDesc, SrcDesc, sizeof(InlineDescriptor));
+
+ if (auto Fn = F.Desc->MoveFn)
+ Fn(B, Src + FieldOffset, Dst + FieldOffset, F.Desc);
}
}
@@ -394,6 +412,8 @@ SourceLocation Descriptor::getLocation() const {
llvm_unreachable("Invalid descriptor type");
}
+bool Descriptor::isUnion() const { return isRecord() && ElemRecord->isUnion(); }
+
InitMap::InitMap(unsigned N)
: UninitFields(N), Data(std::make_unique<T[]>(numFields(N))) {
std::fill_n(data(), numFields(N), 0);