2012-03-06 Richard Guenther <rguenther@suse.de>
authorrguenth <rguenth@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 6 Mar 2012 09:54:06 +0000 (09:54 +0000)
committerrguenth <rguenth@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 6 Mar 2012 09:54:06 +0000 (09:54 +0000)
PR lto/52097
* lto.c (uniquify_nodes): Merge TYPE_FIELDS of variant types.

* gcc.dg/lto/pr52097_0.c: New testcase.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@184981 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/lto/ChangeLog
gcc/lto/lto.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/lto/pr52097_0.c [new file with mode: 0644]

index 6d074db..16624e6 100644 (file)
@@ -1,3 +1,8 @@
+2012-03-06  Richard Guenther  <rguenther@suse.de>
+
+       PR lto/52097
+       * lto.c (uniquify_nodes): Merge TYPE_FIELDS of variant types.
+
 2012-02-28  Richard Guenther  <rguenther@suse.de>
 
        PR lto/52400
index f267d2a..83b5391 100644 (file)
@@ -798,6 +798,41 @@ uniquify_nodes (struct data_in *data_in, unsigned from)
              TYPE_NEXT_VARIANT (mv) = t;
              if (RECORD_OR_UNION_TYPE_P (t))
                TYPE_BINFO (t) = TYPE_BINFO (mv);
+             /* Preserve the invariant that type variants share their
+                TYPE_FIELDS.  */
+             if (RECORD_OR_UNION_TYPE_P (t)
+                 && TYPE_FIELDS (mv) != TYPE_FIELDS (t))
+               {
+                 tree f1, f2;
+                 for (f1 = TYPE_FIELDS (mv), f2 = TYPE_FIELDS (t);
+                      f1 && f2; f1 = TREE_CHAIN (f1), f2 = TREE_CHAIN (f2))
+                   {
+                     unsigned ix;
+                     gcc_assert (f1 != f2
+                                 && DECL_NAME (f1) == DECL_NAME (f2));
+                     if (!streamer_tree_cache_lookup (cache, f2, &ix))
+                       gcc_unreachable ();
+                     /* If we're going to replace an element which we'd
+                        still visit in the next iterations, we wouldn't
+                        handle it, so do it here.  We do have to handle it
+                        even though the field_decl itself will be removed,
+                        as it could refer to e.g. integer_cst which we
+                        wouldn't reach via any other way, hence they
+                        (and their type) would stay uncollected.  */
+                     /* ???  We should rather make sure to replace all
+                        references to f2 with f1.  That means handling
+                        COMPONENT_REFs and CONSTRUCTOR elements in
+                        lto_fixup_types and special-case the field-decl
+                        operand handling.  */
+                     /* ???  Not sure the above is all relevant in this
+                        path canonicalizing TYPE_FIELDS to that of the
+                        main variant.  */
+                     if (ix < i)
+                       lto_fixup_types (f2);
+                     streamer_tree_cache_insert_at (cache, f1, ix);
+                   }
+                 TYPE_FIELDS (t) = TYPE_FIELDS (mv);
+               }
            }
 
          /* Finally adjust our main variant and fix it up.  */
index b6d68df..45b04e9 100644 (file)
@@ -1,3 +1,8 @@
+2012-03-06  Richard Guenther  <rguenther@suse.de>
+
+       PR lto/52097
+       * gcc.dg/lto/pr52097_0.c: New testcase.
+
 2012-03-06  Oleg Endo  <olegendo@gcc.gnu.org>
 
        PR target/51244
diff --git a/gcc/testsuite/gcc.dg/lto/pr52097_0.c b/gcc/testsuite/gcc.dg/lto/pr52097_0.c
new file mode 100644 (file)
index 0000000..cd4af5d
--- /dev/null
@@ -0,0 +1,20 @@
+/* { dg-lto-do link } */
+/* { dg-lto-options { { -O -flto -fexceptions -fnon-call-exceptions --param allow-store-data-races=0 } } } */
+
+typedef struct { unsigned int e0 : 16; } s1;
+typedef struct { unsigned int e0 : 16; } s2;
+typedef struct { s1 i1; s2 i2; } io;
+
+static io *i;
+
+void f1 (void)
+{
+  s1 x0;
+  i->i1 = x0;
+}
+
+int main ()
+{
+  f1 ();
+  return 0;
+}