Blame SOURCES/gcc32-c++-reregister-specialization.patch

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