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

Reply via email to