Index: lib/AST/Decl.cpp =================================================================== --- lib/AST/Decl.cpp +++ lib/AST/Decl.cpp @@ -3152,19 +3152,13 @@ "template"); return getPrimaryTemplate()->getTemplatedDecl(); } - + if (FunctionTemplateDecl *Primary = getPrimaryTemplate()) { - while (Primary->getInstantiatedFromMemberTemplate()) { - // If we have hit a point where the user provided a specialization of - // this template, we're done looking. - if (Primary->isMemberSpecialization()) - break; - Primary = Primary->getInstantiatedFromMemberTemplate(); - } - + if (FunctionTemplateDecl *Def = Primary->getDefinition()) + Primary = Def; return Primary->getTemplatedDecl(); - } - + } + return getInstantiatedFromMemberFunction(); } Index: lib/Sema/SemaTemplateInstantiate.cpp =================================================================== --- lib/Sema/SemaTemplateInstantiate.cpp +++ lib/Sema/SemaTemplateInstantiate.cpp @@ -164,6 +164,13 @@ RelativeToPrimary = false; continue; } + + if (Pattern && Pattern->getFriendObjectKind() && + Function->getDeclContext()->isFileContext()) { + Ctx = const_cast(Pattern->getLexicalDeclContext()); + RelativeToPrimary = false; + continue; + } } else if (CXXRecordDecl *Rec = dyn_cast(Ctx)) { if (ClassTemplateDecl *ClassTemplate = Rec->getDescribedClassTemplate()) { QualType T = ClassTemplate->getInjectedClassNameSpecialization(); Index: test/SemaTemplate/instantiate-friend-function.cpp =================================================================== --- /dev/null +++ test/SemaTemplate/instantiate-friend-function.cpp @@ -0,0 +1,63 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s +// RUN: %clang_cc1 -S -triple i686-pc-linux-gnu -std=c++11 %s -o - | FileCheck %s +// expected-no-diagnostics + +template void func_01(T *x); +template +struct C1 { + template friend void func_01(T *x) {} +}; + +C1 v1a; + +void use_01(int *x) { + func_01(x); +} +// CHECK: _Z7func_01IiEvPT_: + + +template +struct C2 { + template friend void func_02(T *x) {} +}; + +C2 v2a; +template void func_02(T *x); + +void use_02(int *x) { + func_02(x); +} +// CHECK: _Z7func_02IiEvPT_: + + +template +struct C3a { + template friend void func_03(T *x) {} +}; +template +struct C3b { + template friend void func_03(T *x) {} +}; + +template void func_03(T *x) {} + +void use_03(int *x) { + func_03(x); +} +// CHECK: _Z7func_03IiEvPT_: + + +template constexpr int func_04(const T x); +template +struct C4 { + template friend constexpr int func_04(const T x) { return sizeof(T); } +}; + +C4 v4; + +void use_04(int *x) { + static_assert(func_04(short(122)) == sizeof(short), "Invalid calculation"); + static_assert(func_04(122) == sizeof(int), "Invalid calculation"); + static_assert(func_04(122L) == sizeof(long), "Invalid calculation"); + static_assert(func_04(122LL) == sizeof(long long), "Invalid calculation"); +}