Author: Timm Bäder Date: 2024-07-12T16:37:04+02:00 New Revision: 98edc0cb1f4ca53bd2d490916566ff7d217110f8
URL: https://github.com/llvm/llvm-project/commit/98edc0cb1f4ca53bd2d490916566ff7d217110f8 DIFF: https://github.com/llvm/llvm-project/commit/98edc0cb1f4ca53bd2d490916566ff7d217110f8.diff LOG: [clang][Interp] Fix member pointer temporaries PT_MemberPtr also needs its ctor/dtor called, so add that. However, this exposed a problem in initializing virtual bases, so fix that as well. Added: Modified: clang/lib/AST/Interp/Descriptor.cpp clang/test/AST/Interp/memberpointers.cpp Removed: ################################################################################ diff --git a/clang/lib/AST/Interp/Descriptor.cpp b/clang/lib/AST/Interp/Descriptor.cpp index afafae088aca0..a3801a01688c8 100644 --- a/clang/lib/AST/Interp/Descriptor.cpp +++ b/clang/lib/AST/Interp/Descriptor.cpp @@ -162,8 +162,7 @@ static void initField(Block *B, std::byte *Ptr, bool IsConst, bool IsMutable, } static void initBase(Block *B, std::byte *Ptr, bool IsConst, bool IsMutable, - bool IsActive, const Descriptor *D, unsigned FieldOffset, - bool IsVirtualBase) { + bool IsActive, const Descriptor *D, unsigned FieldOffset) { assert(D); assert(D->ElemRecord); @@ -179,43 +178,46 @@ static void initBase(Block *B, std::byte *Ptr, bool IsConst, bool IsMutable, for (const auto &V : D->ElemRecord->bases()) initBase(B, Ptr + FieldOffset, IsConst, IsMutable, IsActive, V.Desc, - V.Offset, false); + V.Offset); for (const auto &F : D->ElemRecord->fields()) - initField(B, Ptr + FieldOffset, IsConst, IsMutable, IsActive, IsUnion, F.Desc, - F.Offset); - - // If this is initializing a virtual base, we do NOT want to consider its - // virtual bases, those are already flattened into the parent record when - // creating it. - if (IsVirtualBase) - return; - - for (const auto &V : D->ElemRecord->virtual_bases()) - initBase(B, Ptr + FieldOffset, IsConst, IsMutable, IsActive, V.Desc, - V.Offset, true); + initField(B, Ptr + FieldOffset, IsConst, IsMutable, IsActive, IsUnion, + F.Desc, F.Offset); } static void ctorRecord(Block *B, std::byte *Ptr, bool IsConst, bool IsMutable, bool IsActive, const Descriptor *D) { for (const auto &V : D->ElemRecord->bases()) - initBase(B, Ptr, IsConst, IsMutable, IsActive, V.Desc, V.Offset, false); + initBase(B, Ptr, IsConst, IsMutable, IsActive, V.Desc, V.Offset); for (const auto &F : D->ElemRecord->fields()) initField(B, Ptr, IsConst, IsMutable, IsActive, D->ElemRecord->isUnion(), 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, V.Desc, V.Offset); +} + +static void destroyField(Block *B, std::byte *Ptr, const Descriptor *D, + unsigned FieldOffset) { + if (auto Fn = D->DtorFn) + Fn(B, Ptr + FieldOffset, D); +} + +static void destroyBase(Block *B, std::byte *Ptr, const Descriptor *D, + unsigned FieldOffset) { + assert(D); + assert(D->ElemRecord); + + for (const auto &V : D->ElemRecord->bases()) + destroyBase(B, Ptr + FieldOffset, V.Desc, V.Offset); + for (const auto &F : D->ElemRecord->fields()) + destroyField(B, Ptr + FieldOffset, F.Desc, F.Offset); } static void dtorRecord(Block *B, std::byte *Ptr, const Descriptor *D) { - auto DtorSub = [=](unsigned SubOff, const Descriptor *F) { - if (auto Fn = F->DtorFn) - Fn(B, Ptr + SubOff, F); - }; for (const auto &F : D->ElemRecord->bases()) - DtorSub(F.Offset, F.Desc); + destroyBase(B, Ptr, F.Desc, F.Offset); for (const auto &F : D->ElemRecord->fields()) - DtorSub(F.Offset, F.Desc); + destroyField(B, Ptr, F.Desc, F.Offset); for (const auto &F : D->ElemRecord->virtual_bases()) - DtorSub(F.Offset, F.Desc); + destroyBase(B, Ptr, F.Desc, F.Offset); } static void moveRecord(Block *B, const std::byte *Src, std::byte *Dst, @@ -238,6 +240,8 @@ static BlockCtorFn getCtorPrim(PrimType Type) { return ctorTy<PrimConv<PT_IntAP>::T>; if (Type == PT_IntAPS) return ctorTy<PrimConv<PT_IntAPS>::T>; + if (Type == PT_MemberPtr) + return ctorTy<PrimConv<PT_MemberPtr>::T>; COMPOSITE_TYPE_SWITCH(Type, return ctorTy<T>, return nullptr); } @@ -251,6 +255,8 @@ static BlockDtorFn getDtorPrim(PrimType Type) { return dtorTy<PrimConv<PT_IntAP>::T>; if (Type == PT_IntAPS) return dtorTy<PrimConv<PT_IntAPS>::T>; + if (Type == PT_MemberPtr) + return dtorTy<PrimConv<PT_MemberPtr>::T>; COMPOSITE_TYPE_SWITCH(Type, return dtorTy<T>, return nullptr); } diff --git a/clang/test/AST/Interp/memberpointers.cpp b/clang/test/AST/Interp/memberpointers.cpp index 54d73fe86ca18..178d2e23f1266 100644 --- a/clang/test/AST/Interp/memberpointers.cpp +++ b/clang/test/AST/Interp/memberpointers.cpp @@ -195,3 +195,15 @@ namespace { use(psr->*&S::x); } } + +namespace MemPtrTemporary { + struct A { + constexpr int f() const { return 5; } + }; + + constexpr int apply(const A &a, int (A::*ff)() const) { + return (a.*ff)(); + } + + static_assert(apply(A(), &A::f) == 5, ""); +} _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits