https://github.com/Serosh-commits created https://github.com/llvm/llvm-project/pull/186398
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 >From b88d19cdd09a75427d6599415860f0778d0972ef Mon Sep 17 00:00:00 2001 From: Serosh-commits <[email protected]> Date: Fri, 13 Mar 2026 19:21:29 +0530 Subject: [PATCH] [Clang] Fix crash in friend definition Fix assertion failure in instantiation. --- clang/docs/ReleaseNotes.rst | 1 + clang/lib/Sema/SemaDeclCXX.cpp | 3 +++ clang/lib/Sema/SemaTemplateInstantiateDecl.cpp | 5 ++++- clang/test/SemaCXX/gh185341.cpp | 17 +++++++++++++++++ 4 files changed, 25 insertions(+), 1 deletion(-) 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..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 _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
