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
