]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
re PR c++/24173 (ICE with garbage collection)
authorMark Mitchell <mark@codesourcery.com>
Sat, 3 Dec 2005 01:02:33 +0000 (01:02 +0000)
committerMark Mitchell <mmitchel@gcc.gnu.org>
Sat, 3 Dec 2005 01:02:33 +0000 (01:02 +0000)
PR c++/24173
* decl.c (duplicate_decls): Don't rely on DECL_TEMPLATE_INFO after
clobbering newdecl.
PR c++/24173
* g++.dg/template/friend40.C: New test.

From-SVN: r107983

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

index 1197d0225547b31bf2eab1d86df30bb03b6562ca..b2b30097ac75e99c9e8176c56d2eafb2558cb29a 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 71aac1a1717d5fbb04744e8c028ebf15678b696d..ca2e221d0f40f54620196220d2b86c3f56002ee1 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 41888c827e0fb36663f64092b1705708d93505cc..415cd85679c7e8570dd50870adc031184cd8bc90 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>());
+}