This revision was landed with ongoing or failed builds. This revision was automatically updated to reflect the committed changes. Closed by commit rG921b45a855f0: [Sema]Select correct lexical context during template instantiate (authored by HerrCai0907).
Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D149009/new/ https://reviews.llvm.org/D149009 Files: clang/lib/Sema/SemaTemplateDeduction.cpp clang/lib/Sema/SemaTemplateInstantiateDecl.cpp clang/test/SemaTemplate/template-friend-definition-in-template.cpp Index: clang/test/SemaTemplate/template-friend-definition-in-template.cpp =================================================================== --- /dev/null +++ clang/test/SemaTemplate/template-friend-definition-in-template.cpp @@ -0,0 +1,26 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s +// expected-no-diagnostics + +template <class F1> int foo1(F1 X1); + +template <int A1> struct A { + template <class F2> friend int foo1(F2 X2) { + return A1; + } +}; + +template struct A<1>; +int main() { + foo1(1.0); +} + +template <class F1> int foo2(F1 X1); + +template <int A1> struct B { + template <class F2> friend int foo2(F2 X2) { + return A1; + } +}; + +template struct B<1>; +template int foo2<float>(float X1); Index: clang/lib/Sema/SemaTemplateInstantiateDecl.cpp =================================================================== --- clang/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ clang/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -4662,11 +4662,7 @@ ActiveInstType &ActiveInst = SemaRef.CodeSynthesisContexts.back(); if (ActiveInst.Kind == ActiveInstType::ExplicitTemplateArgumentSubstitution || ActiveInst.Kind == ActiveInstType::DeducedTemplateArgumentSubstitution) { - if (FunctionTemplateDecl *FunTmpl - = dyn_cast<FunctionTemplateDecl>(ActiveInst.Entity)) { - assert(FunTmpl->getTemplatedDecl() == Tmpl && - "Deduction from the wrong function template?"); - (void) FunTmpl; + if (isa<FunctionTemplateDecl>(ActiveInst.Entity)) { SemaRef.InstantiatingSpecializations.erase( {ActiveInst.Entity->getCanonicalDecl(), ActiveInst.Kind}); atTemplateEnd(SemaRef.TemplateInstCallbacks, SemaRef, ActiveInst); Index: clang/lib/Sema/SemaTemplateDeduction.cpp =================================================================== --- clang/lib/Sema/SemaTemplateDeduction.cpp +++ clang/lib/Sema/SemaTemplateDeduction.cpp @@ -3591,11 +3591,28 @@ DeclContext *Owner = FunctionTemplate->getDeclContext(); if (FunctionTemplate->getFriendObjectKind()) Owner = FunctionTemplate->getLexicalDeclContext(); + FunctionDecl *FD = FunctionTemplate->getTemplatedDecl(); + // additional check for inline friend, + // ``` + // template <class F1> int foo(F1 X); + // template <int A1> struct A { + // template <class F1> friend int foo(F1 X) { return A1; } + // }; + // template struct A<1>; + // int a = foo(1.0); + // ``` + const FunctionDecl *FDFriend; + if (FD->getFriendObjectKind() == Decl::FriendObjectKind::FOK_None && + FD->isDefined(FDFriend, /*CheckForPendingFriendDefinition*/ true) && + FDFriend->getFriendObjectKind() != Decl::FriendObjectKind::FOK_None) { + FD = const_cast<FunctionDecl *>(FDFriend); + Owner = FD->getLexicalDeclContext(); + } MultiLevelTemplateArgumentList SubstArgs( FunctionTemplate, CanonicalDeducedArgumentList->asArray(), /*Final=*/false); Specialization = cast_or_null<FunctionDecl>( - SubstDecl(FunctionTemplate->getTemplatedDecl(), Owner, SubstArgs)); + SubstDecl(FD, Owner, SubstArgs)); if (!Specialization || Specialization->isInvalidDecl()) return TDK_SubstitutionFailure;
Index: clang/test/SemaTemplate/template-friend-definition-in-template.cpp =================================================================== --- /dev/null +++ clang/test/SemaTemplate/template-friend-definition-in-template.cpp @@ -0,0 +1,26 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s +// expected-no-diagnostics + +template <class F1> int foo1(F1 X1); + +template <int A1> struct A { + template <class F2> friend int foo1(F2 X2) { + return A1; + } +}; + +template struct A<1>; +int main() { + foo1(1.0); +} + +template <class F1> int foo2(F1 X1); + +template <int A1> struct B { + template <class F2> friend int foo2(F2 X2) { + return A1; + } +}; + +template struct B<1>; +template int foo2<float>(float X1); Index: clang/lib/Sema/SemaTemplateInstantiateDecl.cpp =================================================================== --- clang/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ clang/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -4662,11 +4662,7 @@ ActiveInstType &ActiveInst = SemaRef.CodeSynthesisContexts.back(); if (ActiveInst.Kind == ActiveInstType::ExplicitTemplateArgumentSubstitution || ActiveInst.Kind == ActiveInstType::DeducedTemplateArgumentSubstitution) { - if (FunctionTemplateDecl *FunTmpl - = dyn_cast<FunctionTemplateDecl>(ActiveInst.Entity)) { - assert(FunTmpl->getTemplatedDecl() == Tmpl && - "Deduction from the wrong function template?"); - (void) FunTmpl; + if (isa<FunctionTemplateDecl>(ActiveInst.Entity)) { SemaRef.InstantiatingSpecializations.erase( {ActiveInst.Entity->getCanonicalDecl(), ActiveInst.Kind}); atTemplateEnd(SemaRef.TemplateInstCallbacks, SemaRef, ActiveInst); Index: clang/lib/Sema/SemaTemplateDeduction.cpp =================================================================== --- clang/lib/Sema/SemaTemplateDeduction.cpp +++ clang/lib/Sema/SemaTemplateDeduction.cpp @@ -3591,11 +3591,28 @@ DeclContext *Owner = FunctionTemplate->getDeclContext(); if (FunctionTemplate->getFriendObjectKind()) Owner = FunctionTemplate->getLexicalDeclContext(); + FunctionDecl *FD = FunctionTemplate->getTemplatedDecl(); + // additional check for inline friend, + // ``` + // template <class F1> int foo(F1 X); + // template <int A1> struct A { + // template <class F1> friend int foo(F1 X) { return A1; } + // }; + // template struct A<1>; + // int a = foo(1.0); + // ``` + const FunctionDecl *FDFriend; + if (FD->getFriendObjectKind() == Decl::FriendObjectKind::FOK_None && + FD->isDefined(FDFriend, /*CheckForPendingFriendDefinition*/ true) && + FDFriend->getFriendObjectKind() != Decl::FriendObjectKind::FOK_None) { + FD = const_cast<FunctionDecl *>(FDFriend); + Owner = FD->getLexicalDeclContext(); + } MultiLevelTemplateArgumentList SubstArgs( FunctionTemplate, CanonicalDeducedArgumentList->asArray(), /*Final=*/false); Specialization = cast_or_null<FunctionDecl>( - SubstDecl(FunctionTemplate->getTemplatedDecl(), Owner, SubstArgs)); + SubstDecl(FD, Owner, SubstArgs)); if (!Specialization || Specialization->isInvalidDecl()) return TDK_SubstitutionFailure;
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits