diff --git a/clang/lib/Sema/SemaTemplateDeduction.cpp b/clang/lib/Sema/SemaTemplateDeduction.cpp --- a/clang/lib/Sema/SemaTemplateDeduction.cpp +++ b/clang/lib/Sema/SemaTemplateDeduction.cpp @@ -3591,11 +3591,19 @@ DeclContext *Owner = FunctionTemplate->getDeclContext(); if (FunctionTemplate->getFriendObjectKind()) Owner = FunctionTemplate->getLexicalDeclContext(); + FunctionDecl *FD = FunctionTemplate->getTemplatedDecl(); + const FunctionDecl *FDFriend; + if (FD->getFriendObjectKind() == Decl::FriendObjectKind::FOK_None && + FD->isDefined(FDFriend, true) && + FDFriend->getFriendObjectKind() != Decl::FriendObjectKind::FOK_None) { + FD = const_cast(FDFriend); + Owner = FD->getDescribedFunctionTemplate()->getLexicalDeclContext(); + } MultiLevelTemplateArgumentList SubstArgs( FunctionTemplate, CanonicalDeducedArgumentList->asArray(), /*Final=*/false); Specialization = cast_or_null( - SubstDecl(FunctionTemplate->getTemplatedDecl(), Owner, SubstArgs)); + SubstDecl(FD, Owner, SubstArgs)); if (!Specialization || Specialization->isInvalidDecl()) return TDK_SubstitutionFailure; diff --git a/clang/test/SemaTemplate/template-friend-definition-in-template.cpp b/clang/test/SemaTemplate/template-friend-definition-in-template.cpp new file mode 100644 --- /dev/null +++ b/clang/test/SemaTemplate/template-friend-definition-in-template.cpp @@ -0,0 +1,15 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s +// expected-no-diagnostics + +template int foo(F1 X1); + +template struct A { + template friend int foo(F2 X2) { + return A1; + } +}; + +template struct A<1>; +int main() { + foo(1.0); +}