[clang] 86691f8 - [clang][Interp] Do not call dtors of union members (#102739)

via cfe-commits cfe-commits at lists.llvm.org
Sat Aug 10 04:45:34 PDT 2024


Author: Timm Baeder
Date: 2024-08-10T13:45:30+02:00
New Revision: 86691f8d7e86176db7409ccafb7a79964221720a

URL: https://github.com/llvm/llvm-project/commit/86691f8d7e86176db7409ccafb7a79964221720a
DIFF: https://github.com/llvm/llvm-project/commit/86691f8d7e86176db7409ccafb7a79964221720a.diff

LOG: [clang][Interp] Do not call dtors of union members (#102739)

Added: 
    

Modified: 
    clang/lib/AST/Interp/Compiler.cpp
    clang/test/AST/Interp/unions.cpp

Removed: 
    


################################################################################
diff  --git a/clang/lib/AST/Interp/Compiler.cpp b/clang/lib/AST/Interp/Compiler.cpp
index 0d72e33c1c7d2..d0e4d409b6580 100644
--- a/clang/lib/AST/Interp/Compiler.cpp
+++ b/clang/lib/AST/Interp/Compiler.cpp
@@ -5552,22 +5552,21 @@ bool Compiler<Emitter>::emitComplexComparison(const Expr *LHS, const Expr *RHS,
 template <class Emitter>
 bool Compiler<Emitter>::emitRecordDestruction(const Record *R) {
   assert(R);
-  // First, destroy all fields.
-  for (const Record::Field &Field : llvm::reverse(R->fields())) {
-    const Descriptor *D = Field.Desc;
-    if (!D->isPrimitive() && !D->isPrimitiveArray()) {
-      if (!this->emitGetPtrField(Field.Offset, SourceInfo{}))
-        return false;
-      if (!this->emitDestruction(D))
-        return false;
-      if (!this->emitPopPtr(SourceInfo{}))
-        return false;
+  if (!R->isUnion()) {
+    // First, destroy all fields.
+    for (const Record::Field &Field : llvm::reverse(R->fields())) {
+      const Descriptor *D = Field.Desc;
+      if (!D->isPrimitive() && !D->isPrimitiveArray()) {
+        if (!this->emitGetPtrField(Field.Offset, SourceInfo{}))
+          return false;
+        if (!this->emitDestruction(D))
+          return false;
+        if (!this->emitPopPtr(SourceInfo{}))
+          return false;
+      }
     }
   }
 
-  // FIXME: Unions need to be handled 
diff erently here. We don't want to
-  //   call the destructor of its members.
-
   // Now emit the destructor and recurse into base classes.
   if (const CXXDestructorDecl *Dtor = R->getDestructor();
       Dtor && !Dtor->isTrivial()) {

diff  --git a/clang/test/AST/Interp/unions.cpp b/clang/test/AST/Interp/unions.cpp
index d615b3584b30b..b0b279831405d 100644
--- a/clang/test/AST/Interp/unions.cpp
+++ b/clang/test/AST/Interp/unions.cpp
@@ -152,4 +152,50 @@ namespace IndirectFieldDecl {
   };
   static_assert(C().a == 1, "");
 }
+
+namespace UnionDtor {
+
+  union U {
+    int *I;
+    constexpr U(int *I) : I(I) {}
+    constexpr ~U() {
+      *I = 10;
+    }
+  };
+
+  constexpr int foo() {
+    int a = 100;
+    {
+      U u(&a);
+    }
+    return a;
+  }
+  static_assert(foo() == 10);
+}
+
+namespace UnionMemberDtor {
+  class UM {
+  public:
+    int &I;
+    constexpr UM(int &I) : I(I) {}
+    constexpr ~UM() { I = 200; }
+  };
+
+  union U {
+    UM um;
+    constexpr U(int &I) : um(I) {}
+    constexpr ~U() {
+    }
+  };
+
+  constexpr int foo() {
+    int a = 100;
+    {
+      U u(a);
+    }
+
+    return a;
+  }
+  static_assert(foo() == 100);
+}
 #endif


        


More information about the cfe-commits mailing list