Skip to content

Commit 86691f8

Browse files
authored
[clang][Interp] Do not call dtors of union members (#102739)
1 parent 979abf1 commit 86691f8

File tree

2 files changed

+58
-13
lines changed

2 files changed

+58
-13
lines changed

clang/lib/AST/Interp/Compiler.cpp

Lines changed: 12 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -5552,22 +5552,21 @@ bool Compiler<Emitter>::emitComplexComparison(const Expr *LHS, const Expr *RHS,
55525552
template <class Emitter>
55535553
bool Compiler<Emitter>::emitRecordDestruction(const Record *R) {
55545554
assert(R);
5555-
// First, destroy all fields.
5556-
for (const Record::Field &Field : llvm::reverse(R->fields())) {
5557-
const Descriptor *D = Field.Desc;
5558-
if (!D->isPrimitive() && !D->isPrimitiveArray()) {
5559-
if (!this->emitGetPtrField(Field.Offset, SourceInfo{}))
5560-
return false;
5561-
if (!this->emitDestruction(D))
5562-
return false;
5563-
if (!this->emitPopPtr(SourceInfo{}))
5564-
return false;
5555+
if (!R->isUnion()) {
5556+
// First, destroy all fields.
5557+
for (const Record::Field &Field : llvm::reverse(R->fields())) {
5558+
const Descriptor *D = Field.Desc;
5559+
if (!D->isPrimitive() && !D->isPrimitiveArray()) {
5560+
if (!this->emitGetPtrField(Field.Offset, SourceInfo{}))
5561+
return false;
5562+
if (!this->emitDestruction(D))
5563+
return false;
5564+
if (!this->emitPopPtr(SourceInfo{}))
5565+
return false;
5566+
}
55655567
}
55665568
}
55675569

5568-
// FIXME: Unions need to be handled differently here. We don't want to
5569-
// call the destructor of its members.
5570-
55715570
// Now emit the destructor and recurse into base classes.
55725571
if (const CXXDestructorDecl *Dtor = R->getDestructor();
55735572
Dtor && !Dtor->isTrivial()) {

clang/test/AST/Interp/unions.cpp

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,4 +152,50 @@ namespace IndirectFieldDecl {
152152
};
153153
static_assert(C().a == 1, "");
154154
}
155+
156+
namespace UnionDtor {
157+
158+
union U {
159+
int *I;
160+
constexpr U(int *I) : I(I) {}
161+
constexpr ~U() {
162+
*I = 10;
163+
}
164+
};
165+
166+
constexpr int foo() {
167+
int a = 100;
168+
{
169+
U u(&a);
170+
}
171+
return a;
172+
}
173+
static_assert(foo() == 10);
174+
}
175+
176+
namespace UnionMemberDtor {
177+
class UM {
178+
public:
179+
int &I;
180+
constexpr UM(int &I) : I(I) {}
181+
constexpr ~UM() { I = 200; }
182+
};
183+
184+
union U {
185+
UM um;
186+
constexpr U(int &I) : um(I) {}
187+
constexpr ~U() {
188+
}
189+
};
190+
191+
constexpr int foo() {
192+
int a = 100;
193+
{
194+
U u(a);
195+
}
196+
197+
return a;
198+
}
199+
static_assert(foo() == 100);
200+
}
155201
#endif

0 commit comments

Comments
 (0)