[clang] [clang][Sema]fix crash of invalid friend declaration with storage-class specifier (PR #190597)

2026-06-08 Thread via cfe-commits

github-actions[bot] wrote:



@firstmoonlight Congratulations on having your first Pull Request (PR) merged 
into the LLVM Project!

Your changes will be combined with recent changes from other authors, then 
tested by our [build bots](https://lab.llvm.org/buildbot/). If there is a 
problem with a build, you may receive a report in an email or a comment on this 
PR.

Please check whether problems have been caused by your change specifically, as 
the builds can include changes from many authors. It is not uncommon for your 
change to be included in a build that fails due to someone else's changes, or 
infrastructure issues.

How to do this, and the rest of the post-merge process, is covered in detail 
[here](https://llvm.org/docs/MyFirstTypoFix.html#myfirsttypofix-issues-after-landing-your-pr).

If your change does cause a problem, it may be reverted, or you can revert it 
yourself. This is a normal part of [LLVM 
development](https://llvm.org/docs/DeveloperPolicy.html#patch-reversion-policy).
 You can fix your changes and open a new PR to merge them again.

If you don't get any reports, no action is required from you. Your changes are 
working as expected, well done!


https://github.com/llvm/llvm-project/pull/190597
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang][Sema]fix crash of invalid friend declaration with storage-class specifier (PR #190597)

2026-06-08 Thread Aaron Ballman via cfe-commits

https://github.com/AaronBallman closed 
https://github.com/llvm/llvm-project/pull/190597
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang][Sema]fix crash of invalid friend declaration with storage-class specifier (PR #190597)

2026-06-08 Thread Aaron Ballman via cfe-commits

https://github.com/AaronBallman auto_merge_enabled 
https://github.com/llvm/llvm-project/pull/190597
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang][Sema]fix crash of invalid friend declaration with storage-class specifier (PR #190597)

2026-06-08 Thread via cfe-commits

firstmoonlight wrote:

> Do you need someone to land this? I will be traveling soon but hopefully 
> @AaronBallman can take care of it

Thanks! Yes, please let @Aaron Ballman take care of landing it.

I've been pretty busy with work lately and haven't been following this closely. 
Thanks for the reminder.




https://github.com/llvm/llvm-project/pull/190597
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang][Sema]fix crash of invalid friend declaration with storage-class specifier (PR #190597)

2026-06-08 Thread via cfe-commits

https://github.com/firstmoonlight updated 
https://github.com/llvm/llvm-project/pull/190597

>From e6b542ad65ca92878235cc8787c9f329f52c398d Mon Sep 17 00:00:00 2001
From: victorl 
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


[clang] [clang][Sema]fix crash of invalid friend declaration with storage-class specifier (PR #190597)

2026-05-06 Thread via cfe-commits

firstmoonlight wrote:

> Does you PR also fix: #196001

Yes, I've verified that this PR also fixes #196001. The root cause is the same: 
the early return in type specifier checking prevents proper recovery.


https://github.com/llvm/llvm-project/pull/190597
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang][Sema]fix crash of invalid friend declaration with storage-class specifier (PR #190597)

2026-05-06 Thread via cfe-commits

https://github.com/firstmoonlight updated 
https://github.com/llvm/llvm-project/pull/190597

>From 6014a94423f619ea101608f48aa0d20f7e761ab5 Mon Sep 17 00:00:00 2001
From: victorl 
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


[clang] [clang][Sema]fix crash of invalid friend declaration with storage-class specifier (PR #190597)

2026-05-06 Thread Shafik Yaghmour via cfe-commits

shafik wrote:

Does you PR also fix: https://github.com/llvm/llvm-project/issues/196001

https://github.com/llvm/llvm-project/pull/190597
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang][Sema]fix crash of invalid friend declaration with storage-class specifier (PR #190597)

2026-05-05 Thread Corentin Jabot via cfe-commits

https://github.com/cor3ntin approved this pull request.

Thanks

https://github.com/llvm/llvm-project/pull/190597
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang][Sema]fix crash of invalid friend declaration with storage-class specifier (PR #190597)

2026-04-21 Thread via cfe-commits

https://github.com/firstmoonlight updated 
https://github.com/llvm/llvm-project/pull/190597

>From a64173fcc8f4bd095bb14530cee6a9f6b9deea4c Mon Sep 17 00:00:00 2001
From: victorl 
Date: Wed, 8 Apr 2026 21:41:05 +0800
Subject: [PATCH 1/4] [clang][Sema]fix crash of invalid friend declaration with
 storage-class specifier

---
 clang/include/clang/Sema/DeclSpec.h  |   2 +
 clang/lib/Sema/DeclSpec.cpp  | 157 ---
 clang/test/CXX/class/class.friend/p6.cpp |   1 +
 3 files changed, 83 insertions(+), 77 deletions(-)

diff --git a/clang/include/clang/Sema/DeclSpec.h 
b/clang/include/clang/Sema/DeclSpec.h
index 6e5421c7072c7..d9e41679ba6ea 100644
--- a/clang/include/clang/Sema/DeclSpec.h
+++ b/clang/include/clang/Sema/DeclSpec.h
@@ -887,6 +887,8 @@ 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);
+
   const WrittenBuiltinSpecs& getWrittenBuiltinSpecs() const {
 return writtenBS;
   }
diff --git a/clang/lib/Sema/DeclSpec.cpp b/clang/lib/Sema/DeclSpec.cpp
index 479a959e0aadc..68197dd872c21 100644
--- a/clang/lib/Sema/DeclSpec.cpp
+++ b/clang/lib/Sema/DeclSpec.cpp
@@ -1162,6 +1162,76 @@ void DeclSpec::Finish(Sema &S, const PrintingPolicy 
&Policy) {
 
   // Check the type specifier components first. No checking for an invalid
   // type.
+  CheckTypeSpec(S, Policy);
+
+  // C++ [class.friend]p6:
+  //   No storage-class-specifier shall appear in the decl-specifier-seq
+  //   of a friend declaration.
+  if (isFriendSpecified() &&
+  (getStorageClassSpec() || getThreadStorageClassSpec())) {
+SmallString<32> SpecName;
+SourceLocation SCLoc;
+FixItHint StorageHint, ThreadHint;
+
+if (DeclSpec::SCS SC = getStorageClassSpec()) {
+  SpecName = getSpecifierName(SC);
+  SCLoc = getStorageClassSpecLoc();
+  StorageHint = FixItHint::CreateRemoval(SCLoc);
+}
+
+if (DeclSpec::TSCS TSC = getThreadStorageClassSpec()) {
+  if (!SpecName.empty())
+SpecName += " ";
+  SpecName += getSpecifierName(TSC);
+  SCLoc = getThreadStorageClassSpecLoc();
+  ThreadHint = FixItHint::CreateRemoval(SCLoc);
+}
+
+S.Diag(SCLoc, diag::err_friend_decl_spec)
+<< SpecName << StorageHint << ThreadHint;
+
+ClearStorageClassSpecs();
+  }
+
+  // C++11 [dcl.fct.spec]p5:
+  //   The virtual specifier shall be used only in the initial
+  //   declaration of a non-static class member function;
+  // C++11 [dcl.fct.spec]p6:
+  //   The explicit specifier shall be used only in the declaration of
+  //   a constructor or conversion function within its class
+  //   definition;
+  if (isFriendSpecified() && (isVirtualSpecified() || hasExplicitSpecifier())) 
{
+StringRef Keyword;
+FixItHint Hint;
+SourceLocation SCLoc;
+
+if (isVirtualSpecified()) {
+  Keyword = "virtual";
+  SCLoc = getVirtualSpecLoc();
+  Hint = FixItHint::CreateRemoval(SCLoc);
+} else {
+  Keyword = "explicit";
+  SCLoc = getExplicitSpecLoc();
+  Hint = FixItHint::CreateRemoval(getExplicitSpecRange());
+}
+
+S.Diag(SCLoc, diag::err_friend_decl_spec) << Keyword << Hint;
+
+FS_virtual_specified = false;
+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'?
+}
+
+void DeclSpec::CheckTypeSpec(Sema &S, const PrintingPolicy &Policy) {
   if (TypeSpecType == TST_error)
 return;
 
@@ -1228,8 +1298,8 @@ void DeclSpec::Finish(Sema &S, const PrintingPolicy 
&Policy) {
(TypeSpecType != TST_int) && (TypeSpecType != TST_int128)) ||
   TypeAltiVecPixel) {
 S.Diag(TSTLoc, diag::err_invalid_vector_bool_decl_spec)
-  << (TypeAltiVecPixel ? "__pixel" :
- getSpecifierName((TST)TypeSpecType, Policy));
+<< (TypeAltiVecPixel ? "__pixel"
+ : getSpecifierName((TST)TypeSpecType, 
Policy));
   }
   // vector bool __int128 requires Power10 (or ZVector).
   if ((TypeSpecType == TST_int128) &&
@@ -1345,10 +1415,8 @@ void DeclSpec::Finish(Sema &S, const PrintingPolicy 
&Policy) {
   // use. Need information about the backend.
   if (TypeSpecComplex != TSC_unspecified) {
 if (TypeSpecType == TST_unspecified) {
-  S.Diag(TSCLoc, diag::ext_plain_complex)
-<< FixItHint::CreateInsertion(
-  S.getLocForEndOfToken(getTypeSpecComplexLoc()),
- " double");
+  S.Diag(TSCLoc, diag::ext_plain_complex) << FixItHint::CreateInsertion(
+  S.getLocForEndOfToken(getTypeSpecComplexLoc()),

[clang] [clang][Sema]fix crash of invalid friend declaration with storage-class specifier (PR #190597)

2026-04-21 Thread Corentin Jabot via cfe-commits

cor3ntin wrote:

This change needs a release note.
Please add an entry to `clang/docs/ReleaseNotes.rst` in the section the most 
adapted to the change, and referencing any Github issue this change fixes. 
Thanks!

https://github.com/llvm/llvm-project/pull/190597
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang][Sema]fix crash of invalid friend declaration with storage-class specifier (PR #190597)

2026-04-21 Thread via cfe-commits

https://github.com/firstmoonlight edited 
https://github.com/llvm/llvm-project/pull/190597
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits