aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMark Mitchell <mark@codesourcery.com>2005-12-03 01:02:33 +0000
committerMark Mitchell <mmitchel@gcc.gnu.org>2005-12-03 01:02:33 +0000
commit50b56799f728d43ffa0fc941bf6757908bc76f46 (patch)
tree490c2963de08fb5bab58a5be8baff8aaef7160b7
parent0889ab4a1a25a1a4e16ba5c09142acf8ace42a76 (diff)
downloadgcc-50b56799f728d43ffa0fc941bf6757908bc76f46.zip
gcc-50b56799f728d43ffa0fc941bf6757908bc76f46.tar.gz
gcc-50b56799f728d43ffa0fc941bf6757908bc76f46.tar.bz2
re PR c++/24173 (ICE with garbage collection)
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
-rw-r--r--gcc/cp/ChangeLog6
-rw-r--r--gcc/cp/decl.c8
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/g++.dg/template/friend40.C16
4 files changed, 33 insertions, 2 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 1197d02..b2b3009 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -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
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index 71aac1a..ca2e221 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -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
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 41888c8..415cd85 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -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
index 0000000..39dd994
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/friend40.C
@@ -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>());
+}