https://github.com/firstmoonlight updated https://github.com/llvm/llvm-project/pull/190597
>From e6b542ad65ca92878235cc8787c9f329f52c398d Mon Sep 17 00:00:00 2001 From: victorl <[email protected]> Date: Wed, 8 Apr 2026 21:41:05 +0800 Subject: [PATCH] [clang][Sema]fix crash of invalid friend declaration with storage-class specifier Fix an assertion in ActOnFriendTypeDecl triggered by friend declarations with storage-class specifiers. The fix factors out type specifier validation into CheckTypeSpec and moves the early return logic there. This allows the caller to proceed with remaining checks even if a type specifier is invalid, preventing the downstream assertion. --- clang/docs/ReleaseNotes.rst | 1 + clang/include/clang/Sema/DeclSpec.h | 4 ++++ clang/lib/Sema/DeclSpec.cpp | 25 ++++++++++++++++-------- clang/test/CXX/class/class.friend/p6.cpp | 1 + 4 files changed, 23 insertions(+), 8 deletions(-) diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index f97e90634396a..f8bb0b48e2512 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -733,6 +733,7 @@ Bug Fixes to C++ Support - Fixed a use-after-free bug when parsing default arguments containing lambdas in declarations with template-id declarators. (#GH196725) - Fixed a crash in constant evaluation using placement new on an array which was later initialized. (#GH196450) - Fixed an issue where Clang incorrectly accepted invalid unqualified uses of local nested class names outside their declaring scope. (#GH184622) +- Fixed a crash when parsing invalid friend declaration with storage-class specifier. (#GH186569) Bug Fixes to AST Handling ^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/clang/include/clang/Sema/DeclSpec.h b/clang/include/clang/Sema/DeclSpec.h index b3c459821c79c..6e7f9cd6e3d38 100644 --- a/clang/include/clang/Sema/DeclSpec.h +++ b/clang/include/clang/Sema/DeclSpec.h @@ -889,6 +889,10 @@ class DeclSpec { /// DeclSpec is guaranteed self-consistent, even if an error occurred. void Finish(Sema &S, const PrintingPolicy &Policy); + void CheckTypeSpec(Sema &S, const PrintingPolicy &Policy); + + void CheckFriendSpec(Sema &S, const PrintingPolicy &Policy); + const WrittenBuiltinSpecs& getWrittenBuiltinSpecs() const { return writtenBS; } diff --git a/clang/lib/Sema/DeclSpec.cpp b/clang/lib/Sema/DeclSpec.cpp index 660b1805c450e..2add7c6aa3080 100644 --- a/clang/lib/Sema/DeclSpec.cpp +++ b/clang/lib/Sema/DeclSpec.cpp @@ -1162,6 +1162,20 @@ void DeclSpec::Finish(Sema &S, const PrintingPolicy &Policy) { // Check the type specifier components first. No checking for an invalid // type. + CheckTypeSpec(S, Policy); + + CheckFriendSpec(S, Policy); + + assert(!TypeSpecOwned || isDeclRep((TST)TypeSpecType)); + + // Okay, now we can infer the real type. + + // TODO: return "auto function" and other bad things based on the real type. + + // 'data definition has no type or storage class'? +} + +void DeclSpec::CheckTypeSpec(Sema &S, const PrintingPolicy &Policy) { if (TypeSpecType == TST_error) return; @@ -1441,6 +1455,9 @@ void DeclSpec::Finish(Sema &S, const PrintingPolicy &Policy) { S.Diag(ConstexprLoc, diag::warn_cxx20_compat_consteval); else if (getConstexprSpecifier() == ConstexprSpecKind::Constinit) S.Diag(ConstexprLoc, diag::warn_cxx20_compat_constinit); +} + +void DeclSpec::CheckFriendSpec(Sema &S, const PrintingPolicy &Policy) { // C++ [class.friend]p6: // No storage-class-specifier shall appear in the decl-specifier-seq // of a friend declaration. @@ -1498,14 +1515,6 @@ void DeclSpec::Finish(Sema &S, const PrintingPolicy &Policy) { FS_explicit_specifier = ExplicitSpecifier(); FS_virtualLoc = FS_explicitLoc = SourceLocation(); } - - assert(!TypeSpecOwned || isDeclRep((TST) TypeSpecType)); - - // Okay, now we can infer the real type. - - // TODO: return "auto function" and other bad things based on the real type. - - // 'data definition has no type or storage class'? } bool DeclSpec::isMissingDeclaratorOk() { diff --git a/clang/test/CXX/class/class.friend/p6.cpp b/clang/test/CXX/class/class.friend/p6.cpp index e4c59f781e3de..a96dd8a3d4e4a 100644 --- a/clang/test/CXX/class/class.friend/p6.cpp +++ b/clang/test/CXX/class/class.friend/p6.cpp @@ -19,4 +19,5 @@ class A { #else friend thread_local class G; // expected-error {{'thread_local' is invalid in friend declarations}} #endif + friend register enum; // expected-error {{expected identifier or '{'}} expected-error {{'register' is invalid in friend declarations}} }; _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
