[clang] [clang][Interp] Do not call dtors of union members (PR #102739)
Timm Baeder via cfe-commits
cfe-commits at lists.llvm.org
Sat Aug 10 03:56:47 PDT 2024
https://github.com/tbaederr created https://github.com/llvm/llvm-project/pull/102739
None
>From f4ccc8a5d705bcc0eb6a573f24b0bc3e80aa7b5e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Timm=20B=C3=A4der?= <tbaeder at redhat.com>
Date: Sat, 10 Aug 2024 11:21:25 +0200
Subject: [PATCH] [clang][Interp] Do not call dtors of union members
---
clang/lib/AST/Interp/Compiler.cpp | 25 ++++++++---------
clang/test/AST/Interp/unions.cpp | 46 +++++++++++++++++++++++++++++++
2 files changed, 58 insertions(+), 13 deletions(-)
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
More information about the cfe-commits
mailing list