[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