[clang] 98edc0c - [clang][Interp] Fix member pointer temporaries
Timm Bäder via cfe-commits
cfe-commits at lists.llvm.org
Fri Jul 12 07:37:27 PDT 2024
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, "");
+}
More information about the cfe-commits
mailing list