[clang] [clang][bytecode] Don't call dtors of anonymous unions (PR #110087)
Timm Baeder via cfe-commits
cfe-commits at lists.llvm.org
Thu Sep 26 00:44:19 PDT 2024
https://github.com/tbaederr created https://github.com/llvm/llvm-project/pull/110087
None
>From d54a46d9ccc3eed3be0d319f26c49f069a68a9e6 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Timm=20B=C3=A4der?= <tbaeder at redhat.com>
Date: Thu, 26 Sep 2024 09:41:33 +0200
Subject: [PATCH] [clang][bytecode] Don't call dtors of anonymous unions
---
clang/lib/AST/ByteCode/Compiler.cpp | 7 +++++++
clang/lib/AST/ByteCode/Record.cpp | 3 ++-
clang/lib/AST/ByteCode/Record.h | 4 ++++
clang/test/AST/ByteCode/cxx23.cpp | 31 +++++++++++++++++++++++++++++
4 files changed, 44 insertions(+), 1 deletion(-)
diff --git a/clang/lib/AST/ByteCode/Compiler.cpp b/clang/lib/AST/ByteCode/Compiler.cpp
index e54b6568d7060b..6e3ea6bd070bc1 100644
--- a/clang/lib/AST/ByteCode/Compiler.cpp
+++ b/clang/lib/AST/ByteCode/Compiler.cpp
@@ -5302,6 +5302,9 @@ bool Compiler<Emitter>::compileDestructor(const CXXDestructorDecl *Dtor) {
}
for (const Record::Base &Base : llvm::reverse(R->bases())) {
+ if (Base.R->isAnonymousUnion())
+ continue;
+
if (!this->emitGetPtrBase(Base.Offset, SourceInfo{}))
return false;
if (!this->emitRecordDestruction(Base.R))
@@ -6147,6 +6150,7 @@ bool Compiler<Emitter>::emitComplexComparison(const Expr *LHS, const Expr *RHS,
template <class Emitter>
bool Compiler<Emitter>::emitRecordDestruction(const Record *R) {
assert(R);
+ assert(!R->isAnonymousUnion());
const CXXDestructorDecl *Dtor = R->getDestructor();
if (!Dtor || Dtor->isTrivial())
return true;
@@ -6202,6 +6206,9 @@ bool Compiler<Emitter>::emitDestruction(const Descriptor *Desc) {
}
assert(Desc->ElemRecord);
+ if (Desc->ElemRecord->isAnonymousUnion())
+ return true;
+
return this->emitRecordDestruction(Desc->ElemRecord);
}
diff --git a/clang/lib/AST/ByteCode/Record.cpp b/clang/lib/AST/ByteCode/Record.cpp
index ec1b55da347af6..0c06bec7e5508e 100644
--- a/clang/lib/AST/ByteCode/Record.cpp
+++ b/clang/lib/AST/ByteCode/Record.cpp
@@ -16,7 +16,8 @@ Record::Record(const RecordDecl *Decl, BaseList &&SrcBases,
FieldList &&SrcFields, VirtualBaseList &&SrcVirtualBases,
unsigned VirtualSize, unsigned BaseSize)
: Decl(Decl), Bases(std::move(SrcBases)), Fields(std::move(SrcFields)),
- BaseSize(BaseSize), VirtualSize(VirtualSize), IsUnion(Decl->isUnion()) {
+ BaseSize(BaseSize), VirtualSize(VirtualSize), IsUnion(Decl->isUnion()),
+ IsAnonymousUnion(IsUnion && Decl->isAnonymousStructOrUnion()) {
for (Base &V : SrcVirtualBases)
VirtualBases.push_back({V.Decl, V.Offset + BaseSize, V.Desc, V.R});
diff --git a/clang/lib/AST/ByteCode/Record.h b/clang/lib/AST/ByteCode/Record.h
index 83e15b125f77a9..7a5c482e4efccd 100644
--- a/clang/lib/AST/ByteCode/Record.h
+++ b/clang/lib/AST/ByteCode/Record.h
@@ -54,6 +54,8 @@ class Record final {
const std::string getName() const;
/// Checks if the record is a union.
bool isUnion() const { return IsUnion; }
+ /// Checks if the record is an anonymous union.
+ bool isAnonymousUnion() const { return IsAnonymousUnion; }
/// Returns the size of the record.
unsigned getSize() const { return BaseSize; }
/// Returns the full size of the record, including records.
@@ -134,6 +136,8 @@ class Record final {
unsigned VirtualSize;
/// If this record is a union.
bool IsUnion;
+ /// If this is an anonymous union.
+ bool IsAnonymousUnion;
};
} // namespace interp
diff --git a/clang/test/AST/ByteCode/cxx23.cpp b/clang/test/AST/ByteCode/cxx23.cpp
index 756eec5b825605..9d7e9d753e6d2f 100644
--- a/clang/test/AST/ByteCode/cxx23.cpp
+++ b/clang/test/AST/ByteCode/cxx23.cpp
@@ -238,3 +238,34 @@ namespace TwosComplementShifts {
static_assert(-3 >> 1 == -2);
static_assert(-7 >> 1 == -4);
}
+
+namespace AnonUnionDtor {
+ struct A {
+ A ();
+ ~A();
+ };
+
+ template <class T>
+ struct opt
+ {
+ union { // all20-note {{is not literal}}
+ char c;
+ T data;
+ };
+
+ constexpr opt() {}
+
+ constexpr ~opt() {
+ if (engaged)
+ data.~T();
+ }
+
+ bool engaged = false;
+ };
+
+ consteval void foo() {
+ opt<A> a; // all20-error {{variable of non-literal type}}
+ }
+
+ void bar() { foo(); }
+}
More information about the cfe-commits
mailing list