[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