https://github.com/akash-manna-sky updated 
https://github.com/llvm/llvm-project/pull/217942

>From d282ef1337f3f30e5b13628c913274a30a6c23bb Mon Sep 17 00:00:00 2001
From: Akash Manna <[email protected]>
Date: Fri, 21 Aug 2026 20:25:14 +0530
Subject: [PATCH 1/2] [clang] Fix "Unions cannot be dynamic classes" assertion
 on ill-formed qualified member definitions (#213854)

A qualified member function definition inside another class body, like
void B::foo() {} in a union, is diagnosed but kept for recovery with its
semantic parent B while lexically nested in the union. When the method is
implicitly virtual, CXXRecordDecl::addedMember marked the lexical class
polymorphic, so the union reached record layout as a dynamic class and
tripped the assertion. Skip members of a different class in addedMember;
only friends (already skipped) and these recovery leftovers can be in
that position.

Fixes #213854
---
 clang/docs/ReleaseNotes.md      |  6 +++++
 clang/lib/AST/DeclCXX.cpp       |  5 ++++
 clang/test/SemaCXX/GH213854.cpp | 42 +++++++++++++++++++++++++++++++++
 3 files changed, 53 insertions(+)
 create mode 100644 clang/test/SemaCXX/GH213854.cpp

diff --git a/clang/docs/ReleaseNotes.md b/clang/docs/ReleaseNotes.md
index 8c9467ca7b742..b4410f52d87e4 100644
--- a/clang/docs/ReleaseNotes.md
+++ b/clang/docs/ReleaseNotes.md
@@ -528,6 +528,12 @@ features cannot lower the translation-unit ABI level;
   parameter that follows a parameter pack (e.g.
   `template <typename... T> S::S(T..., int = 10) {}`).  (#GH216211)
 
+- Fixed a crash when an ill-formed qualified member function definition written
+  inside a class (e.g. a definition of a virtual member of a nested class)
+  incorrectly caused the enclosing class to be treated as a polymorphic class,
+  which asserted during record layout when the enclosing class was a union.
+  (#GH213854)
+
 #### Bug Fixes to AST Handling
 
 - Fixed a non-deterministic ordering of unused local typedefs that made
diff --git a/clang/lib/AST/DeclCXX.cpp b/clang/lib/AST/DeclCXX.cpp
index f0da56542ae7e..ed0c9512f8b6f 100644
--- a/clang/lib/AST/DeclCXX.cpp
+++ b/clang/lib/AST/DeclCXX.cpp
@@ -758,6 +758,11 @@ void CXXRecordDecl::addedMember(Decl *D) {
   if (D->getFriendObjectKind() || D->isInvalidDecl())
     return;
 
+  // Ignore members of a different class, which can appear here during error
+  // recovery for an ill-formed qualified member declaration.
+  if (!D->getDeclContext()->Equals(this))
+    return;
+
   auto *FunTmpl = dyn_cast<FunctionTemplateDecl>(D);
   if (FunTmpl)
     D = FunTmpl->getTemplatedDecl();
diff --git a/clang/test/SemaCXX/GH213854.cpp b/clang/test/SemaCXX/GH213854.cpp
new file mode 100644
index 0000000000000..96c4e6049aa1d
--- /dev/null
+++ b/clang/test/SemaCXX/GH213854.cpp
@@ -0,0 +1,42 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+
+namespace reduced {
+union Union {
+  class A {
+    virtual void foo();
+  };
+  class B : public A {
+  };
+  void B::foo() {} // expected-error {{non-friend class member 'foo' cannot 
have a qualified name}}
+};
+
+static_assert(!__is_polymorphic(Union), "");
+
+void uni(void (*fn)(Union), Union arg1) {
+  fn(arg1);
+}
+
+struct Struct {
+  class A {
+    virtual void foo();
+  };
+  class B : public A {
+  };
+  void B::foo() {} // expected-error {{non-friend class member 'foo' cannot 
have a qualified name}}
+};
+
+static_assert(!__is_polymorphic(Struct), "");
+} // namespace reduced
+
+// Verbatim reproducer from GH213854; the missing closing brace is intentional.
+union Union { // expected-note {{to match this '{'}}
+  class A {
+  virtual void foo();
+  };
+  class B : public A {
+  };
+  void B::foo() {} // expected-error {{non-friend class member 'foo' cannot 
have a qualified name}}
+void uni(void (*fn)(union Union), union Union arg1) {
+    fn(arg1);
+}
+// expected-error {{expected '}'}} expected-error@-1 {{expected ';' after 
union}}
\ No newline at end of file

>From 001d3130e998c000e12521a47455735989f2c901 Mon Sep 17 00:00:00 2001
From: Akash Manna <[email protected]>
Date: Sat, 22 Aug 2026 15:03:29 +0530
Subject: [PATCH 2/2] shorten this sentences in RealeaseNotes.md and add new
 lines at the end of the test file

---
 clang/docs/ReleaseNotes.md      | 6 ++----
 clang/test/SemaCXX/GH213854.cpp | 2 +-
 2 files changed, 3 insertions(+), 5 deletions(-)

diff --git a/clang/docs/ReleaseNotes.md b/clang/docs/ReleaseNotes.md
index b4410f52d87e4..4a158838563a9 100644
--- a/clang/docs/ReleaseNotes.md
+++ b/clang/docs/ReleaseNotes.md
@@ -528,10 +528,8 @@ features cannot lower the translation-unit ABI level;
   parameter that follows a parameter pack (e.g.
   `template <typename... T> S::S(T..., int = 10) {}`).  (#GH216211)
 
-- Fixed a crash when an ill-formed qualified member function definition written
-  inside a class (e.g. a definition of a virtual member of a nested class)
-  incorrectly caused the enclosing class to be treated as a polymorphic class,
-  which asserted during record layout when the enclosing class was a union.
+- Fixed an assertion when an ill-formed qualified member function definition
+  inside a union caused the union to be treated as a polymorphic class.
   (#GH213854)
 
 #### Bug Fixes to AST Handling
diff --git a/clang/test/SemaCXX/GH213854.cpp b/clang/test/SemaCXX/GH213854.cpp
index 96c4e6049aa1d..82dc81914298b 100644
--- a/clang/test/SemaCXX/GH213854.cpp
+++ b/clang/test/SemaCXX/GH213854.cpp
@@ -39,4 +39,4 @@ union Union { // expected-note {{to match this '{'}}
 void uni(void (*fn)(union Union), union Union arg1) {
     fn(arg1);
 }
-// expected-error {{expected '}'}} expected-error@-1 {{expected ';' after 
union}}
\ No newline at end of file
+// expected-error {{expected '}'}} expected-error@-1 {{expected ';' after 
union}}

_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to