diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp --- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -2028,9 +2028,12 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl( FunctionDecl *D, TemplateParameterList *TemplateParams, RewriteKind FunctionRewriteKind) { + const FunctionDecl *Definition = D; + D->isDefined(Definition, true); + // Check whether there is already a function template specialization for // this declaration. - FunctionTemplateDecl *FunctionTemplate = D->getDescribedFunctionTemplate(); + FunctionTemplateDecl *FunctionTemplate = Definition->getDescribedFunctionTemplate(); if (FunctionTemplate && !TemplateParams) { ArrayRef Innermost = TemplateArgs.getInnermost(); @@ -2152,11 +2155,11 @@ if (!isFriend && D->isOutOfLine() && !D->isLocalExternDecl()) { assert(D->getDeclContext()->isFileContext()); LexicalDC = D->getDeclContext(); - } - else if (D->isLocalExternDecl()) { + } else if (D->isLocalExternDecl()) { LexicalDC = SemaRef.CurContext; + } else if (isFriend && Definition != D) { + LexicalDC = const_cast(Definition->getLexicalDeclContext()); } - Function->setLexicalDeclContext(LexicalDC); // Attach the parameters 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); +}