https://github.com/mizvekov updated https://github.com/llvm/llvm-project/pull/207301
>From 764e84b6a1035b8df52a2ac2d1c40b3641226808 Mon Sep 17 00:00:00 2001 From: Matheus Izvekov <[email protected]> Date: Thu, 2 Jul 2026 17:16:52 -0300 Subject: [PATCH] [clang] fix redeclarations of the injected class name The declaration used to represent an injected class name should never be part of any redeclaration chain. Fixes #202320 --- clang/docs/ReleaseNotes.md | 1 + clang/lib/Sema/SemaDecl.cpp | 25 +++++++++++-------- .../SemaCXX/injected-class-name-crash.cpp | 7 ++++++ 3 files changed, 22 insertions(+), 11 deletions(-) diff --git a/clang/docs/ReleaseNotes.md b/clang/docs/ReleaseNotes.md index ba9572e2e7c59..a60504f1b9ae6 100644 --- a/clang/docs/ReleaseNotes.md +++ b/clang/docs/ReleaseNotes.md @@ -798,6 +798,7 @@ latest release, please see the [Clang Web Site](https://clang.llvm.org) or the when used inside decltype in the return type. (#GH180460) - Fixed a crash when evaluating uninitialized GCC vector/ext_vector_type vectors in `constexpr`. (#GH180044) - Fixed a crash when `explicit(bool)` is used with an incomplete enumeration. (#GH183887) +- Fix crash-on-invalid caused by qualified forward declarations. (#GH202320) - Fixed a crash on `typeid` of incomplete local types during template instantiation. (#GH63242), (#GH176397) - Fixed spurious diagnostics produced when checking if constraints are equivalent for redeclarations, which could make the program mistakenly ill-formed. diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index f6d1d7a7877c7..813aebf263f97 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -18447,16 +18447,6 @@ Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, SourceLocation KWLoc, Previous.resolveKind(); } } - } else if (auto *RD = dyn_cast<CXXRecordDecl>(PrevDecl); - TUK == TagUseKind::Reference && RD && - RD->isInjectedClassName()) { - // If lookup found the injected class name, the previous declaration is - // the class being injected into. - PrevDecl = cast<TagDecl>(RD->getDeclContext()); - Previous.clear(); - Previous.addDecl(PrevDecl); - Previous.resolveKind(); - IsInjectedClassName = true; } } @@ -18488,6 +18478,18 @@ Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, SourceLocation KWLoc, if (TUK == TagUseKind::Reference || TUK == TagUseKind::Friend || isDeclInScope(DirectPrevDecl, SearchDC, S, SS.isNotEmpty() || isMemberSpecialization)) { + + if (auto *RD = dyn_cast<CXXRecordDecl>(PrevDecl); + RD && RD->isInjectedClassName()) { + // If lookup found the injected class name, the previous declaration + // is the class being injected into. + Previous.clear(); + PrevDecl = PrevTagDecl = cast<CXXRecordDecl>(RD->getDeclContext()); + Previous.addDecl(PrevDecl); + Previous.resolveKind(); + IsInjectedClassName = true; + } + // Make sure that this wasn't declared as an enum and now used as a // struct or something similar. if (!isAcceptableTagRedeclaration(PrevTagDecl, Kind, @@ -18688,7 +18690,8 @@ Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, SourceLocation KWLoc, // Okay, we're going to make a redeclaration. If this is some kind // of reference, make sure we build the redeclaration in the same DC // as the original, and ignore the current access specifier. - if (TUK == TagUseKind::Friend || TUK == TagUseKind::Reference) { + if (TUK == TagUseKind::Friend || TUK == TagUseKind::Reference || + IsInjectedClassName) { SearchDC = PrevTagDecl->getDeclContext(); AS = AS_none; } diff --git a/clang/test/SemaCXX/injected-class-name-crash.cpp b/clang/test/SemaCXX/injected-class-name-crash.cpp index a044ba064b58e..141762fe41d93 100644 --- a/clang/test/SemaCXX/injected-class-name-crash.cpp +++ b/clang/test/SemaCXX/injected-class-name-crash.cpp @@ -9,3 +9,10 @@ struct X : public Foo<Bar { // expected-error {{unknown template name 'Foo'}} ex template <class T> X<T>::X() { } + +namespace GH202320 { + struct S { S f(); }; + struct S::S; + // expected-error@-1 {{forward declaration of struct cannot have a nested name specifier}} + S S::f() { return S(); } +} // namespace GH202320 _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
