[PATCH] Remove NEWDECL from WEAK_DECLS chain in merge_decls (PR c++/20961)
Jakub Jelinek
jakub@redhat.com
Thu May 5 18:41:00 GMT 2005
Hi!
In merge_weak, if NEWDECL is weak and OLDDECL is not, NEWDECL is replaced
with OLDDECL in weak_decls chain, but not so if both NEWDECL and OLDDECL
are weak already when merge_weak is called. But merge_weak is called
by C/C++ duplicate_decls when we know NEWDECL is going to be not used
any more, and C++ even ggc_free's it.
Without this patch, weak_decls contains a ggc_free'd memory and thus
can crash in various interesting ways.
Ok to commit if it bootstraps and passes regtesting? For 4.0 as well,
as this appears to be a 4.0/4.1 regression?
2005-05-05 Jakub Jelinek <jakub@redhat.com>
PR c++/20961
* varasm.c (merge_weak): Remove NEWDECL from WEAK_DECLS chain
if both NEWDECL and OLDDECL are already weak.
* g++.dg/ext/weak3.C: New test.
--- gcc/varasm.c.jj 2005-04-29 09:18:11.000000000 +0200
+++ gcc/varasm.c 2005-05-05 20:07:37.000000000 +0200
@@ -4303,7 +4303,21 @@ void
merge_weak (tree newdecl, tree olddecl)
{
if (DECL_WEAK (newdecl) == DECL_WEAK (olddecl))
- return;
+ {
+ if (DECL_WEAK (newdecl) && SUPPORTS_WEAK)
+ {
+ tree *pwd;
+ /* We put the NEWDECL on the weak_decls list at some point
+ and OLDDECL as well. Keep just OLDDECL on the list. */
+ for (pwd = &weak_decls; *pwd; pwd = &TREE_CHAIN (*pwd))
+ if (TREE_VALUE (*pwd) == newdecl)
+ {
+ *pwd = TREE_CHAIN (*pwd);
+ break;
+ }
+ }
+ return;
+ }
if (DECL_WEAK (newdecl))
{
--- gcc/testsuite/g++.dg/ext/weak3.C.jj 2005-05-05 20:10:34.000000000 +0200
+++ gcc/testsuite/g++.dg/ext/weak3.C 2005-05-05 20:12:24.000000000 +0200
@@ -0,0 +1,17 @@
+// PR c++/20961
+// Test for #pragma weak and __attribute__((weak)) being used together.
+// { dg-do compile }
+// { dg-require-weak "" }
+// { dg-options "" }
+
+// { dg-final { scan-assembler "weak\[^ \t\]*\[ \t\]_?_Z3foov" } }
+
+int foo ();
+#pragma weak foo
+
+int
+__attribute__((weak))
+foo ()
+{
+ return 0;
+}
Jakub
More information about the Gcc-patches
mailing list