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

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