[clang] [clang] fix crash in friend definition (PR #186398)
via cfe-commits
cfe-commits at lists.llvm.org
Fri Mar 13 06:56:02 PDT 2026
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-clang
Author: Serosh (Serosh-commits)
<details>
<summary>Changes</summary>
Mark invalid friend definitions with `setInvalidDecl()` and skip the redecl chain search in `InstantiateFunctionDefinition` for friend-instantiated functions, which don't follow standard template redecl rules
fixes #<!-- -->185341
---
Full diff: https://github.com/llvm/llvm-project/pull/186398.diff
4 Files Affected:
- (modified) clang/docs/ReleaseNotes.rst (+1)
- (modified) clang/lib/Sema/SemaDeclCXX.cpp (+3)
- (modified) clang/lib/Sema/SemaTemplateInstantiateDecl.cpp (+4-1)
- (added) clang/test/SemaCXX/gh185341.cpp (+17)
``````````diff
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..d966a3c1a25fd 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -18452,10 +18452,12 @@ NamedDecl *Sema::ActOnFriendFunctionDecl(Scope *S, Declarator &D,
DB << SS.getScopeRep();
if (DC->isFileContext())
DB << FixItHint::CreateRemoval(SS.getRange());
+ ND->setInvalidDecl();
// Friend function defined in a local class.
} else if (FunctionContainingLocalClass) {
Diag(NameInfo.getBeginLoc(), diag::err_friend_def_in_local_class);
+ ND->setInvalidDecl();
// Per [basic.pre]p4, a template-id is not a name. Therefore, if we have
// a template-id, the function name is not unqualified because these is
@@ -18465,6 +18467,7 @@ NamedDecl *Sema::ActOnFriendFunctionDecl(Scope *S, Declarator &D,
// and diagnose them as such.
} else if (isTemplateId) {
Diag(NameInfo.getBeginLoc(), diag::err_friend_specialization_def);
+ ND->setInvalidDecl();
}
}
diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
index e74c41517ecbf..9e1416bac212c 100644
--- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -5563,6 +5563,8 @@ void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation,
// corresponding declaration of the function.
assert(ExistingDefn->isThisDeclarationInstantiatedFromAFriendDefinition());
Function = const_cast<FunctionDecl*>(ExistingDefn);
+ if (Function->isInvalidDecl())
+ return;
}
#ifndef NDEBUG
@@ -5888,7 +5890,8 @@ void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation,
Primary &&
!isGenericLambdaCallOperatorOrStaticInvokerSpecialization(Function) &&
Function->getTemplateSpecializationKind() !=
- TSK_ExplicitSpecialization) {
+ TSK_ExplicitSpecialization &&
+ !Function->isThisDeclarationInstantiatedFromAFriendDefinition()) {
auto It = llvm::find_if(Primary->redecls(),
[](const RedeclarableTemplateDecl *RTD) {
return cast<FunctionTemplateDecl>(RTD)
diff --git a/clang/test/SemaCXX/gh185341.cpp b/clang/test/SemaCXX/gh185341.cpp
new file mode 100644
index 0000000000000..fb3ae259ccd6e
--- /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>{});
+}
\ No newline at end of file
``````````
</details>
https://github.com/llvm/llvm-project/pull/186398
More information about the cfe-commits
mailing list