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  <ja...@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.

--- 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;

        Jakub

Reply via email to