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

Reply via email to