From feb3b88ad7ea6de3d0f63b41226f0b90c36a0c07 Mon Sep 17 00:00:00 2001
From: Jason Merrill <jason@redhat.com>
Date: Wed, 7 Apr 2010 11:54:42 -0400
Subject: [PATCH] re PR c++/38392 (Template friend function injection)

	PR c++/38392
	* pt.c (tsubst_friend_function): Instatiate a friend that has already
	been used.

From-SVN: r158073
---
 gcc/cp/ChangeLog                         |  4 ++++
 gcc/cp/pt.c                              | 17 ++++++++++++-----
 gcc/testsuite/ChangeLog                  |  3 +++
 gcc/testsuite/g++.dg/template/friend51.C | 17 +++++++++++++++++
 4 files changed, 36 insertions(+), 5 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/template/friend51.C

diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index d3b0788218d3..6e048cad8b96 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,5 +1,9 @@
 2010-04-07  Jason Merrill  <jason@redhat.com>
 
+	PR c++/38392
+	* pt.c (tsubst_friend_function): Instatiate a friend that has already
+	been used.
+
 	* pt.c (print_template_statistics): New.
 	* cp-tree.h: Declare it.
 	* tree.c (cxx_print_statistics): Call it.
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index d1c33d652772..1c0e13ea4dcc 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -7330,11 +7330,18 @@ tsubst_friend_function (tree decl, tree args)
 	      DECL_TEMPLATE_INFO (old_decl) = new_friend_template_info;
 
 	      if (TREE_CODE (old_decl) != TEMPLATE_DECL)
-		/* We should have called reregister_specialization in
-		   duplicate_decls.  */
-		gcc_assert (retrieve_specialization (new_template,
-						     new_args, 0)
-			    == old_decl);
+		{
+		  /* We should have called reregister_specialization in
+		     duplicate_decls.  */
+		  gcc_assert (retrieve_specialization (new_template,
+						       new_args, 0)
+			      == old_decl);
+
+		  /* Instantiate it if the global has already been used.  */
+		  if (DECL_ODR_USED (old_decl))
+		    instantiate_decl (old_decl, /*defer_ok=*/true,
+				      /*expl_inst_class_mem_p=*/false);
+		}
 	      else
 		{
 		  tree t;
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 3138c8a3d1cf..3df0787cc8bc 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,5 +1,8 @@
 2010-04-07  Jason Merrill  <jason@redhat.com>
 
+	PR c++/38392
+	* g++.dg/template/friend51.C: New test.
+
 	PR c++/41970
 	* g++.old-deja/g++.other/linkage1.C: Adjust.
 
diff --git a/gcc/testsuite/g++.dg/template/friend51.C b/gcc/testsuite/g++.dg/template/friend51.C
new file mode 100644
index 000000000000..d2d1ad799d88
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/friend51.C
@@ -0,0 +1,17 @@
+// PR c++/38392
+// { dg-do link }
+
+void Function();
+
+int main()
+{
+  Function();
+}
+
+template <typename T>
+struct Test
+{
+  friend void Function() { }
+};
+
+template class Test<int>;
-- 
GitLab