[clang] [clang] fix crash on qualified friend function definitions (PR #186398)
via cfe-commits
cfe-commits at lists.llvm.org
Fri Apr 10 11:01:11 PDT 2026
https://github.com/Serosh-commits updated https://github.com/llvm/llvm-project/pull/186398
>From 00a22a4bd343225eef148b608034ad1df90a98be Mon Sep 17 00:00:00 2001
From: Serosh-commits <janmejayapanda400 at gmail.com>
Date: Wed, 8 Apr 2026 02:34:56 +0530
Subject: [PATCH 1/5] [Clang] Fix friend function crash
---
clang/docs/ReleaseNotes.rst | 1 +
clang/lib/Sema/SemaDeclCXX.cpp | 17 +++++++++++++++++
clang/test/SemaCXX/gh185341.cpp | 17 +++++++++++++++++
3 files changed, 35 insertions(+)
create mode 100644 clang/test/SemaCXX/gh185341.cpp
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 613d87668be18..330c46b2eaaf3 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -243,6 +243,7 @@ Bug Fixes to Attribute Support
Bug Fixes to C++ Support
^^^^^^^^^^^^^^^^^^^^^^^^
+- Fixed a crash when a function template is defined as a non-template friend with a global scope qualifier. (#GH185341)
- Fixed a crash when instantiating ``requires`` expressions involving substitution failures in C++ concepts. (#GH176402)
- Fixed a crash when a default argument is passed to an explicit object parameter. (#GH176639)
- Fixed a crash when diagnosing an invalid static member function with an explicit object parameter (#GH177741)
diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp
index 5837ecd6b9163..9e9b57814b8de 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -18238,6 +18238,20 @@ NamedDecl *Sema::ActOnFriendFunctionDecl(Scope *S, Declarator &D,
DiagnoseUnexpandedParameterPack(SS, UPPC_FriendDeclaration))
return nullptr;
+ bool IsEarlyRecovered = false;
+ if (D.isFunctionDefinition() && SS.isNotEmpty()) {
+ auto Kind = SS.getScopeRep().getKind();
+ if (Kind == NestedNameSpecifier::Kind::Global ||
+ Kind == NestedNameSpecifier::Kind::Namespace) {
+ if (D.getName().getKind() != UnqualifiedIdKind::IK_TemplateId) {
+ Diag(SS.getRange().getBegin(), diag::err_qualified_friend_def)
+ << SS.getScopeRep() << FixItHint::CreateRemoval(SS.getRange());
+ SS.clear();
+ IsEarlyRecovered = true;
+ }
+ }
+ }
+
// The context we found the declaration in, or in which we should
// create the declaration.
DeclContext *DC;
@@ -18395,6 +18409,9 @@ NamedDecl *Sema::ActOnFriendFunctionDecl(Scope *S, Declarator &D,
DCScope = &FakeDCScope;
}
+ if (IsEarlyRecovered)
+ Previous.clear();
+
bool AddToScope = true;
NamedDecl *ND = ActOnFunctionDeclarator(DCScope, D, DC, TInfo, Previous,
TemplateParams, AddToScope);
diff --git a/clang/test/SemaCXX/gh185341.cpp b/clang/test/SemaCXX/gh185341.cpp
new file mode 100644
index 0000000000000..de2bb8c34382d
--- /dev/null
+++ b/clang/test/SemaCXX/gh185341.cpp
@@ -0,0 +1,17 @@
+// RUN: %clang_cc1 -std=c++23 -fsyntax-only -verify %s
+
+template<class>
+struct D;
+
+template<class T>
+void foo(D<T>);
+
+template<class T>
+struct D {
+ friend void ::foo(D) {} // expected-error {{friend function definition cannot be qualified with '::'}}
+};
+
+int main() {
+ foo(D<int>{});
+}
+
>From 1d9836e334559fe7760c3f67780422928ca4147b Mon Sep 17 00:00:00 2001
From: Serosh-commits <janmejayapanda400 at gmail.com>
Date: Thu, 9 Apr 2026 21:07:40 +0530
Subject: [PATCH 2/5] fix the chain
---
clang/lib/Sema/SemaDeclCXX.cpp | 4 ----
1 file changed, 4 deletions(-)
diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp
index 9e9b57814b8de..ac3a21a0c9a06 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -18238,7 +18238,6 @@ NamedDecl *Sema::ActOnFriendFunctionDecl(Scope *S, Declarator &D,
DiagnoseUnexpandedParameterPack(SS, UPPC_FriendDeclaration))
return nullptr;
- bool IsEarlyRecovered = false;
if (D.isFunctionDefinition() && SS.isNotEmpty()) {
auto Kind = SS.getScopeRep().getKind();
if (Kind == NestedNameSpecifier::Kind::Global ||
@@ -18247,7 +18246,6 @@ NamedDecl *Sema::ActOnFriendFunctionDecl(Scope *S, Declarator &D,
Diag(SS.getRange().getBegin(), diag::err_qualified_friend_def)
<< SS.getScopeRep() << FixItHint::CreateRemoval(SS.getRange());
SS.clear();
- IsEarlyRecovered = true;
}
}
}
@@ -18409,8 +18407,6 @@ NamedDecl *Sema::ActOnFriendFunctionDecl(Scope *S, Declarator &D,
DCScope = &FakeDCScope;
}
- if (IsEarlyRecovered)
- Previous.clear();
bool AddToScope = true;
NamedDecl *ND = ActOnFunctionDeclarator(DCScope, D, DC, TInfo, Previous,
>From 1c8d7a96a70ae0546850242e3a3c9a3f26cbf1cc Mon Sep 17 00:00:00 2001
From: Serosh-commits <janmejayapanda400 at gmail.com>
Date: Thu, 9 Apr 2026 21:21:07 +0530
Subject: [PATCH 3/5] nit
---
clang/lib/Sema/SemaDeclCXX.cpp | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp
index ac3a21a0c9a06..93cbe1c650ead 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -18406,8 +18406,7 @@ NamedDecl *Sema::ActOnFriendFunctionDecl(Scope *S, Declarator &D,
FakeDCScope.setEntity(DC);
DCScope = &FakeDCScope;
}
-
-
+
bool AddToScope = true;
NamedDecl *ND = ActOnFunctionDeclarator(DCScope, D, DC, TInfo, Previous,
TemplateParams, AddToScope);
>From d81f0e447788fb714fae8426097d767d7654f804 Mon Sep 17 00:00:00 2001
From: Serosh-commits <janmejayapanda400 at gmail.com>
Date: Thu, 9 Apr 2026 21:33:41 +0530
Subject: [PATCH 4/5] nit
---
clang/lib/Sema/SemaDeclCXX.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp
index 93cbe1c650ead..4c2816801118a 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -18406,7 +18406,7 @@ NamedDecl *Sema::ActOnFriendFunctionDecl(Scope *S, Declarator &D,
FakeDCScope.setEntity(DC);
DCScope = &FakeDCScope;
}
-
+
bool AddToScope = true;
NamedDecl *ND = ActOnFunctionDeclarator(DCScope, D, DC, TInfo, Previous,
TemplateParams, AddToScope);
>From 757e151edb790b72c25780013a52059f48cf918c Mon Sep 17 00:00:00 2001
From: Serosh-commits <janmejayapanda400 at gmail.com>
Date: Fri, 10 Apr 2026 22:52:39 +0530
Subject: [PATCH 5/5] fix ci
---
clang/lib/Sema/SemaDeclCXX.cpp | 19 +++++++++----------
1 file changed, 9 insertions(+), 10 deletions(-)
diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp
index 4c2816801118a..b5c7ef93e4b27 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -18238,15 +18238,16 @@ NamedDecl *Sema::ActOnFriendFunctionDecl(Scope *S, Declarator &D,
DiagnoseUnexpandedParameterPack(SS, UPPC_FriendDeclaration))
return nullptr;
- if (D.isFunctionDefinition() && SS.isNotEmpty()) {
+ bool isTemplateId = D.getName().getKind() == UnqualifiedIdKind::IK_TemplateId;
+
+ if (D.isFunctionDefinition() && SS.isNotEmpty() && !isTemplateId) {
auto Kind = SS.getScopeRep().getKind();
- if (Kind == NestedNameSpecifier::Kind::Global ||
- Kind == NestedNameSpecifier::Kind::Namespace) {
- if (D.getName().getKind() != UnqualifiedIdKind::IK_TemplateId) {
- Diag(SS.getRange().getBegin(), diag::err_qualified_friend_def)
- << SS.getScopeRep() << FixItHint::CreateRemoval(SS.getRange());
- SS.clear();
- }
+ bool IsNamespaceOrGlobal = Kind == NestedNameSpecifier::Kind::Global ||
+ Kind == NestedNameSpecifier::Kind::Namespace;
+ if (IsNamespaceOrGlobal) {
+ Diag(SS.getRange().getBegin(), diag::err_qualified_friend_def)
+ << SS.getScopeRep() << FixItHint::CreateRemoval(SS.getRange());
+ SS.clear();
}
}
@@ -18257,8 +18258,6 @@ NamedDecl *Sema::ActOnFriendFunctionDecl(Scope *S, Declarator &D,
LookupResult Previous(*this, NameInfo, LookupOrdinaryName,
RedeclarationKind::ForExternalRedeclaration);
- bool isTemplateId = D.getName().getKind() == UnqualifiedIdKind::IK_TemplateId;
-
// There are five cases here.
// - There's no scope specifier and we're in a local class. Only look
// for functions declared in the immediately-enclosing block scope.
More information about the cfe-commits
mailing list