[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