https://github.com/firstmoonlight updated https://github.com/llvm/llvm-project/pull/190597
>From 6014a94423f619ea101608f48aa0d20f7e761ab5 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 cb19b80b7e994..09f7647969558 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -579,6 +579,7 @@ Bug Fixes to C++ Support - Fixed a crash in Itanium C++ name mangling for a lambda in a local class field initializer inside a constructor/destructor. (#GH176395) - Fixed crashes in Itanium C++ name mangling for lambdas with trailing requires-clauses involving requires-expressions. (#GH100774) (#GH123854) - Fixed an invalid rejection and assertion failure while generating ``operator=`` for fields with the ``__restrict`` qualifier. (#GH37979) +- 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 61706bc8f4229..be4a8bba6be83 100644 --- a/clang/include/clang/Sema/DeclSpec.h +++ b/clang/include/clang/Sema/DeclSpec.h @@ -888,6 +888,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
