Skip to content

Commit 82ce829

Browse files
authored
[clang][bytecode] Don't call dtors of anonymous unions (#110087)
1 parent 0e24611 commit 82ce829

File tree

4 files changed

+44
-1
lines changed

4 files changed

+44
-1
lines changed

clang/lib/AST/ByteCode/Compiler.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5302,6 +5302,9 @@ bool Compiler<Emitter>::compileDestructor(const CXXDestructorDecl *Dtor) {
53025302
}
53035303

53045304
for (const Record::Base &Base : llvm::reverse(R->bases())) {
5305+
if (Base.R->isAnonymousUnion())
5306+
continue;
5307+
53055308
if (!this->emitGetPtrBase(Base.Offset, SourceInfo{}))
53065309
return false;
53075310
if (!this->emitRecordDestruction(Base.R))
@@ -6147,6 +6150,7 @@ bool Compiler<Emitter>::emitComplexComparison(const Expr *LHS, const Expr *RHS,
61476150
template <class Emitter>
61486151
bool Compiler<Emitter>::emitRecordDestruction(const Record *R) {
61496152
assert(R);
6153+
assert(!R->isAnonymousUnion());
61506154
const CXXDestructorDecl *Dtor = R->getDestructor();
61516155
if (!Dtor || Dtor->isTrivial())
61526156
return true;
@@ -6202,6 +6206,9 @@ bool Compiler<Emitter>::emitDestruction(const Descriptor *Desc) {
62026206
}
62036207

62046208
assert(Desc->ElemRecord);
6209+
if (Desc->ElemRecord->isAnonymousUnion())
6210+
return true;
6211+
62056212
return this->emitRecordDestruction(Desc->ElemRecord);
62066213
}
62076214

clang/lib/AST/ByteCode/Record.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,8 @@ Record::Record(const RecordDecl *Decl, BaseList &&SrcBases,
1616
FieldList &&SrcFields, VirtualBaseList &&SrcVirtualBases,
1717
unsigned VirtualSize, unsigned BaseSize)
1818
: Decl(Decl), Bases(std::move(SrcBases)), Fields(std::move(SrcFields)),
19-
BaseSize(BaseSize), VirtualSize(VirtualSize), IsUnion(Decl->isUnion()) {
19+
BaseSize(BaseSize), VirtualSize(VirtualSize), IsUnion(Decl->isUnion()),
20+
IsAnonymousUnion(IsUnion && Decl->isAnonymousStructOrUnion()) {
2021
for (Base &V : SrcVirtualBases)
2122
VirtualBases.push_back({V.Decl, V.Offset + BaseSize, V.Desc, V.R});
2223

clang/lib/AST/ByteCode/Record.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,8 @@ class Record final {
5454
const std::string getName() const;
5555
/// Checks if the record is a union.
5656
bool isUnion() const { return IsUnion; }
57+
/// Checks if the record is an anonymous union.
58+
bool isAnonymousUnion() const { return IsAnonymousUnion; }
5759
/// Returns the size of the record.
5860
unsigned getSize() const { return BaseSize; }
5961
/// Returns the full size of the record, including records.
@@ -134,6 +136,8 @@ class Record final {
134136
unsigned VirtualSize;
135137
/// If this record is a union.
136138
bool IsUnion;
139+
/// If this is an anonymous union.
140+
bool IsAnonymousUnion;
137141
};
138142

139143
} // namespace interp

clang/test/AST/ByteCode/cxx23.cpp

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -238,3 +238,34 @@ namespace TwosComplementShifts {
238238
static_assert(-3 >> 1 == -2);
239239
static_assert(-7 >> 1 == -4);
240240
}
241+
242+
namespace AnonUnionDtor {
243+
struct A {
244+
A ();
245+
~A();
246+
};
247+
248+
template <class T>
249+
struct opt
250+
{
251+
union { // all20-note {{is not literal}}
252+
char c;
253+
T data;
254+
};
255+
256+
constexpr opt() {}
257+
258+
constexpr ~opt() {
259+
if (engaged)
260+
data.~T();
261+
}
262+
263+
bool engaged = false;
264+
};
265+
266+
consteval void foo() {
267+
opt<A> a; // all20-error {{variable of non-literal type}}
268+
}
269+
270+
void bar() { foo(); }
271+
}

0 commit comments

Comments
 (0)