This is another fix I postponed for 4.8 (or 4.7.1 if it doesn't have any fallout). We fail to honor the (unwritten) rule that type variants ought to share their TYPE_FIELDs. Which breaks users that compare FIELD_DECLs by pointers.
This should also save some memory at WPA/LTRANS stage. LTO bootstrapped and tested on x86_64-unknown-linux-gnu, applied to trunk. Richard. 2012-03-06 Richard Guenther <rguent...@suse.de> PR lto/52097 * lto.c (uniquify_nodes): Merge TYPE_FIELDS of variant types. * gcc.dg/lto/pr52097_0.c: New testcase. Index: gcc/lto/lto.c =================================================================== --- gcc/lto/lto.c (revision 184200) +++ gcc/lto/lto.c (working copy) @@ -805,6 +805,41 @@ uniquify_nodes (struct data_in *data_in, 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: gcc/testsuite/gcc.dg/lto/pr52097_0.c =================================================================== --- gcc/testsuite/gcc.dg/lto/pr52097_0.c (revision 0) +++ gcc/testsuite/gcc.dg/lto/pr52097_0.c (revision 0) @@ -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; +}