Blob Blame History Raw
2003-07-14  Mark Mitchell  <mark@codesourcery.com>

	PR c++/7053
	* pt.c (unregister_specialization): Rename to ...
	(reregister_specialization): ... this.
	(tsubst_friend_function): Use it.
	(regenerate_decl_from_template): Likewise.

	* g++.dg/template/friend20.C: New test.

--- gcc/cp/pt.c	14 Jul 2003 10:08:58 -0000	1.635.2.33
+++ gcc/cp/pt.c	14 Jul 2003 20:18:18 -0000	1.635.2.34
@@ -128,7 +128,7 @@ static tree retrieve_specialization PARA
 static tree retrieve_local_specialization PARAMS ((tree));
 static tree register_specialization PARAMS ((tree, tree, tree));
 static void register_local_specialization PARAMS ((tree, tree));
-static int unregister_specialization PARAMS ((tree, tree));
+static int reregister_specialization PARAMS ((tree, tree, tree));
 static tree reduce_template_parm_level PARAMS ((tree, tree, int));
 static tree build_template_decl PARAMS ((tree, tree));
 static int mark_template_parm PARAMS ((tree, void *));
@@ -969,13 +969,11 @@ register_specialization (spec, tmpl, arg
 }
 
 /* Unregister the specialization SPEC as a specialization of TMPL.
-   Returns nonzero if the SPEC was listed as a specialization of
-   TMPL.  */
+   Replace it with NEW_SPEC, if NEW_SPEC is non-NULL.  Returns true
+   if the SPEC was listed as a specialization of TMPL.  */
 
 static int
-unregister_specialization (spec, tmpl)
-     tree spec;
-     tree tmpl;
+reregister_specialization (tree spec, tree tmpl, tree new_spec)
 {
   tree* s;
 
@@ -984,7 +982,10 @@ unregister_specialization (spec, tmpl)
        s = &TREE_CHAIN (*s))
     if (TREE_VALUE (*s) == spec)
       {
-	*s = TREE_CHAIN (*s);
+	if (!new_spec)
+	  *s = TREE_CHAIN (*s);
+	else
+	  TREE_VALUE (*s) = new_spec;
 	return 1;
       }
 
@@ -4807,8 +4808,9 @@ tsubst_friend_function (decl, args)
 	      DECL_TEMPLATE_INFO (old_decl) = new_friend_template_info;
 
 	      if (TREE_CODE (old_decl) != TEMPLATE_DECL)
-		/* duplicate_decls will take care of this case.  */
-		;
+		reregister_specialization (new_friend,
+					   most_general_template (old_decl),
+					   old_decl);
 	      else 
 		{
 		  tree t;
@@ -9897,7 +9899,7 @@ regenerate_decl_from_template (decl, tmp
      instantiation of a specialization, which it isn't: it's a full
      instantiation.  */
   gen_tmpl = most_general_template (tmpl);
-  unregistered = unregister_specialization (decl, gen_tmpl);
+  unregistered = reregister_specialization (decl, gen_tmpl, NULL_TREE);
 
   /* If the DECL was not unregistered then something peculiar is
      happening: we created a specialization but did not call
--- gcc/testsuite/g++.dg/template/friend20.C	2004-12-09 13:34:01.422415552 +0100
+++ gcc/testsuite/g++.dg/template/friend20.C	2003-07-15 02:29:07.000000000 +0200
@@ -0,0 +1,15 @@
+template <class T>
+struct A
+{
+  friend void bar(A<T> a) {}
+};
+
+void bar(A<int>);
+
+int main()
+{
+  A<int> a;
+
+  bar(a);
+}
+