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

Reply via email to