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

via cfe-commits cfe-commits at lists.llvm.org
Sat Aug 10 07:43:11 PDT 2024


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-clang

Author: Timm Baeder (tbaederr)

<details>
<summary>Changes</summary>



---
Full diff: https://github.com/llvm/llvm-project/pull/102739.diff


2 Files Affected:

- (modified) clang/lib/AST/Interp/Compiler.cpp (+12-13) 
- (modified) clang/test/AST/Interp/unions.cpp (+46) 


``````````diff
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 differently 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

``````````

</details>


https://github.com/llvm/llvm-project/pull/102739


More information about the cfe-commits mailing list