sepavloff updated this revision to Diff 106914. sepavloff added a comment. Aligned implementation with https://reviews.llvm.org/D21508.
https://reviews.llvm.org/D21767 Files: lib/AST/Decl.cpp lib/Sema/SemaTemplateInstantiate.cpp test/SemaTemplate/instantiate-friend-function.cpp
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<typename T> void func_01(T *x); +template<typename T1> +struct C1 { + template<typename T> friend void func_01(T *x) {} +}; + +C1<int> v1a; + +void use_01(int *x) { + func_01(x); +} +// CHECK: _Z7func_01IiEvPT_: + + +template<typename T1> +struct C2 { + template<typename T> friend void func_02(T *x) {} +}; + +C2<int> v2a; +template<typename T> void func_02(T *x); + +void use_02(int *x) { + func_02(x); +} +// CHECK: _Z7func_02IiEvPT_: + + +template<typename T1> +struct C3a { + template<typename T> friend void func_03(T *x) {} +}; +template<typename T1> +struct C3b { + template<typename T> friend void func_03(T *x) {} +}; + +template<typename T> void func_03(T *x) {} + +void use_03(int *x) { + func_03(x); +} +// CHECK: _Z7func_03IiEvPT_: + + +template<typename T> constexpr int func_04(const T x); +template<typename T1> +struct C4 { + template<typename T> friend constexpr int func_04(const T x) { return sizeof(T); } +}; + +C4<int> 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"); +} Index: lib/Sema/SemaTemplateInstantiate.cpp =================================================================== --- lib/Sema/SemaTemplateInstantiate.cpp +++ lib/Sema/SemaTemplateInstantiate.cpp @@ -165,6 +165,13 @@ RelativeToPrimary = false; continue; } + + if (Pattern && Pattern->getFriendObjectKind() != Decl::FOK_None && + Function->getDeclContext()->isFileContext()) { + Ctx = const_cast<DeclContext*>(Pattern->getLexicalDeclContext()); + RelativeToPrimary = false; + continue; + } } else if (CXXRecordDecl *Rec = dyn_cast<CXXRecordDecl>(Ctx)) { if (ClassTemplateDecl *ClassTemplate = Rec->getDescribedClassTemplate()) { QualType T = ClassTemplate->getInjectedClassNameSpecialization(); Index: lib/AST/Decl.cpp =================================================================== --- lib/AST/Decl.cpp +++ lib/AST/Decl.cpp @@ -3249,7 +3249,23 @@ } llvm_unreachable("All TSK values handled."); } - + +static FunctionTemplateDecl *getPatternFor(FunctionTemplateDecl *FTD) { + for (auto I : FTD->redecls()) { + auto D = cast<FunctionTemplateDecl>(I); + // If we have hit a point where the user provided a specialization of + // this template, we're done looking. + if (D->isMemberSpecialization()) + return D; + if (D->isThisDeclarationADefinition()) + return D; + if (FunctionTemplateDecl *Orig = D->getInstantiatedFromMemberTemplate()) + if (FunctionTemplateDecl *Def = getPatternFor(Orig)) + return Def; + } + return nullptr; +} + FunctionDecl *FunctionDecl::getTemplateInstantiationPattern() const { // Handle class scope explicit specialization special case. if (getTemplateSpecializationKind() == TSK_ExplicitSpecialization) { @@ -3274,14 +3290,8 @@ } 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 = getPatternFor(Primary)) + Primary = Def; return getDefinitionOrSelf(Primary->getTemplatedDecl()); }
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits