HerrCai0907 created this revision. HerrCai0907 added reviewers: aaron.ballman, erichkeane, shafik. Herald added a project: All. HerrCai0907 requested review of this revision. Herald added a project: clang. Herald added a subscriber: cfe-commits.
This patch wants to fix inline friend decl like 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); Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D149009 Files: 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,15 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s +// expected-no-diagnostics + +template <class F1> int foo(F1 X1); + +template <int A1> struct A { + template <class F2> friend int foo(F2 X2) { + return A1; + } +}; + +template struct A<1>; +int main() { + foo(1.0); +} Index: clang/lib/Sema/SemaTemplateInstantiateDecl.cpp =================================================================== --- clang/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ 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<TemplateArgument> 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<DeclContext *>(Definition->getLexicalDeclContext()); } - Function->setLexicalDeclContext(LexicalDC); // Attach the parameters
Index: clang/test/SemaTemplate/template-friend-definition-in-template.cpp =================================================================== --- /dev/null +++ clang/test/SemaTemplate/template-friend-definition-in-template.cpp @@ -0,0 +1,15 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s +// expected-no-diagnostics + +template <class F1> int foo(F1 X1); + +template <int A1> struct A { + template <class F2> friend int foo(F2 X2) { + return A1; + } +}; + +template struct A<1>; +int main() { + foo(1.0); +} Index: clang/lib/Sema/SemaTemplateInstantiateDecl.cpp =================================================================== --- clang/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ 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<TemplateArgument> 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<DeclContext *>(Definition->getLexicalDeclContext()); } - Function->setLexicalDeclContext(LexicalDC); // Attach the parameters
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits