llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-clang
Author: Akash Manna (akash-manna-sky)
<details>
<summary>Changes</summary>
Fixes #<!-- -->213854
An ill-formed qualified member definition like `void B::foo() {}` inside a
union gets diagnosed, but recovery keeps the declaration around: it belongs to
`B` semantically while sitting lexically inside the union. Because `B::foo`
overrides a virtual function, `CXXRecordDecl::addedMember` — which runs on the
lexical class — marked the union polymorphic, and record layout later asserted
with `"Unions cannot be dynamic classes."`. A non-union enclosing class hits
the same bug silently and just gets a bogus vtable pointer.
The fix is to make `addedMember` ignore declarations that belong to a different
class, right next to the existing friend/invalid filter. Only these recovery
leftovers can end up in that position, so valid code is unaffected, and the
recovery and assertion both stay as they are. Also added a regression test
(reduced union/struct cases plus the verbatim reproducer) and a release note.
LLM tools were used for this contribution. I've reviewed, built, and tested the
change myself before pushing to GitHub.
---
Full diff: https://github.com/llvm/llvm-project/pull/217942.diff
3 Files Affected:
- (modified) clang/docs/ReleaseNotes.md (+6)
- (modified) clang/lib/AST/DeclCXX.cpp (+5)
- (added) clang/test/SemaCXX/GH213854.cpp (+42)
``````````diff
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
``````````
</details>
https://github.com/llvm/llvm-project/pull/217942
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits