diff options
Diffstat (limited to 'clang/lib/AST/Interp/Descriptor.cpp')
| -rw-r--r-- | clang/lib/AST/Interp/Descriptor.cpp | 70 |
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); |
