diff mbox

[C++] Fix up TREE_READONLY handling in duplicate_decls (PR c++/71528)

Message ID 20160614192140.GG7387@tucnak.redhat.com
State New
Headers show

Commit Message

Jakub Jelinek June 14, 2016, 7:21 p.m. UTC
Hi!

The following testcase is miscompiled, because during cp_finish_decl when
handling the initializer of the reference we clear TREE_READONLY, because
it needs to be initialized at runtime, but the (useless) later extern
decl has TREE_READONLY set and when we are merging the two decls, we set
TREE_READONLY on the old decl back.  The middle-end then sees TREE_READONLY
variable and because it has NULL DECL_INITIAL, assumes it is all zeros.

This patch prevents it by honoring TREE_READONLY from the decl with
an initializer (if any) instead of oring TREE_READONLY from both decls.

Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk (and
after some time for 6.x)?

2016-06-14  Jakub Jelinek  <jakub@redhat.com>

	PR c++/71528
	* decl.c (duplicate_decls): For DECL_INITIALIZED_P non-external
	olddecl vars, preserve their TREE_READONLY bit.

	* g++.dg/opt/pr71528.C: New test.


	Jakub

Comments

Jason Merrill June 14, 2016, 7:30 p.m. UTC | #1
On Tue, Jun 14, 2016 at 3:21 PM, Jakub Jelinek <jakub@redhat.com> wrote:
> Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk (and
> after some time for 6.x)?

Yes.

Jason
diff mbox

Patch

--- gcc/cp/decl.c.jj	2016-06-13 20:45:11.000000000 +0200
+++ gcc/cp/decl.c	2016-06-14 16:08:03.796145254 +0200
@@ -2066,6 +2066,14 @@  duplicate_decls (tree newdecl, tree oldd
       if (VAR_P (newdecl))
 	{
 	  DECL_THIS_EXTERN (newdecl) |= DECL_THIS_EXTERN (olddecl);
+	  /* For already initialized vars, TREE_READONLY could have been
+	     cleared in cp_finish_decl, because the var needs runtime
+	     initialization or destruction.  Make sure not to set
+	     TREE_READONLY on it again.  */
+	  if (DECL_INITIALIZED_P (olddecl)
+	      && !DECL_EXTERNAL (olddecl)
+	      && !TREE_READONLY (olddecl))
+	    TREE_READONLY (newdecl) = 0;
 	  DECL_INITIALIZED_P (newdecl) |= DECL_INITIALIZED_P (olddecl);
 	  DECL_NONTRIVIALLY_INITIALIZED_P (newdecl)
 	    |= DECL_NONTRIVIALLY_INITIALIZED_P (olddecl);
--- gcc/testsuite/g++.dg/opt/pr71528.C.jj	2016-06-14 16:17:06.161368105 +0200
+++ gcc/testsuite/g++.dg/opt/pr71528.C	2016-06-14 16:10:12.000000000 +0200
@@ -0,0 +1,23 @@ 
+// PR c++/71528
+// { dg-do run }
+// { dg-options "-O2" }
+
+extern int &x;
+int y;
+
+int &
+foo ()
+{
+  return y;
+}
+
+int &x = foo ();
+
+int
+main ()
+{
+  if (&x != &y)
+    __builtin_abort ();
+}
+
+extern int &x;