OSDN Git Service

PR c++/24173
authormmitchel <mmitchel@138bc75d-0d04-0410-961f-82ee72b054a4>
Sat, 3 Dec 2005 01:02:33 +0000 (01:02 +0000)
committermmitchel <mmitchel@138bc75d-0d04-0410-961f-82ee72b054a4>
Sat, 3 Dec 2005 01:02:33 +0000 (01:02 +0000)
* decl.c (duplicate_decls): Don't rely on DECL_TEMPLATE_INFO after
clobbering newdecl.
PR c++/24173
* g++.dg/template/friend40.C: New test.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@107983 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/cp/ChangeLog
gcc/cp/decl.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/template/friend40.C [new file with mode: 0644]

index 1197d02..b2b3009 100644 (file)
@@ -1,3 +1,9 @@
+2005-12-02  Mark Mitchell  <mark@codesourcery.com>
+
+       PR c++/24173
+       * decl.c (duplicate_decls): Don't rely on DECL_TEMPLATE_INFO after
+       clobbering newdecl.
+
 2005-12-02  Richard Guenther  <rguenther@suse.de>
 
        * semantics.c (simplify_aggr_init_expr): Use buildN instead
index 71aac1a..ca2e221 100644 (file)
@@ -1054,6 +1054,7 @@ duplicate_decls (tree newdecl, tree olddecl, bool newdecl_is_friend)
   unsigned olddecl_uid = DECL_UID (olddecl);
   int olddecl_friend = 0, types_match = 0, hidden_friend = 0;
   int new_defines_function = 0;
+  tree new_template;
 
   if (newdecl == olddecl)
     return olddecl;
@@ -1690,6 +1691,7 @@ duplicate_decls (tree newdecl, tree olddecl, bool newdecl_is_friend)
   if (! DECL_EXTERNAL (olddecl))
     DECL_EXTERNAL (newdecl) = 0;
 
+  new_template = NULL_TREE;
   if (DECL_LANG_SPECIFIC (newdecl) && DECL_LANG_SPECIFIC (olddecl))
     {
       DECL_INTERFACE_KNOWN (newdecl) |= DECL_INTERFACE_KNOWN (olddecl);
@@ -1712,6 +1714,8 @@ duplicate_decls (tree newdecl, tree olddecl, bool newdecl_is_friend)
        DECL_LANG_SPECIFIC (olddecl)->decl_flags.u2;
       DECL_NONCONVERTING_P (newdecl) = DECL_NONCONVERTING_P (olddecl);
       DECL_REPO_AVAILABLE_P (newdecl) = DECL_REPO_AVAILABLE_P (olddecl);
+      if (DECL_TEMPLATE_INFO (newdecl))
+       new_template = DECL_TI_TEMPLATE (newdecl);
       DECL_TEMPLATE_INFO (newdecl) = DECL_TEMPLATE_INFO (olddecl);
       DECL_INITIALIZED_IN_CLASS_P (newdecl)
        |= DECL_INITIALIZED_IN_CLASS_P (olddecl);
@@ -1873,7 +1877,7 @@ duplicate_decls (tree newdecl, tree olddecl, bool newdecl_is_friend)
       memcpy ((char *) olddecl + sizeof (struct tree_decl_common),
              (char *) newdecl + sizeof (struct tree_decl_common),
              sizeof (struct tree_function_decl) - sizeof (struct tree_decl_common));
-      if (DECL_TEMPLATE_INFO (newdecl))
+      if (new_template)
        /* If newdecl is a template instantiation, it is possible that
           the following sequence of events has occurred:
 
@@ -1896,7 +1900,7 @@ duplicate_decls (tree newdecl, tree olddecl, bool newdecl_is_friend)
           instantiations so that if we try to do the instantiation
           again we won't get the clobbered declaration.  */
        reregister_specialization (newdecl,
-                                  DECL_TI_TEMPLATE (newdecl),
+                                  new_template,
                                   olddecl);
     }
   else
index 41888c8..415cd85 100644 (file)
@@ -1,3 +1,8 @@
+2005-12-02  Mark Mitchell  <mark@codesourcery.com>
+
+       PR c++/24173
+       * g++.dg/template/friend40.C: New test.
+       
 2005-12-02  Jakub Jelinek  <jakub@redhat.com>
 
        PR target/25199
diff --git a/gcc/testsuite/g++.dg/template/friend40.C b/gcc/testsuite/g++.dg/template/friend40.C
new file mode 100644 (file)
index 0000000..39dd994
--- /dev/null
@@ -0,0 +1,16 @@
+// PR c++/24173
+// { dg-options "--param ggc-min-expand=0 --param ggc-min-heapsize=0" }
+
+template <int> struct A;
+
+void foo(A<0>);
+
+template<int> struct A
+{
+  friend void foo(A<0>);
+};
+
+void bar()
+{
+  foo(A<0>());
+}