The following patch makes sure we wrap symbol references in global initializers the same as we do for IL references - inside a MEM_REF that guards their context against type changes due to symbol merging (and thus in this case against ICEs when processing an ARRAY_REF around a non-array object).
LTO bootstrap & regtest running on x86_64-unknown-linux-gnu. Richard. 2014-03-31 Richard Biener <rguent...@suse.de> PR lto/60720 * lto-streamer-out.c (wrap_refs): New function. (get_symbol_initial_value): Wrap symbol references in global initializes in type-preserving MEM_REFs. * gcc.dg/lto/pr60720_0.c: New testcase. * gcc.dg/lto/pr60720_1.c: Likewise. Index: gcc/lto-streamer-out.c =================================================================== *** gcc/lto-streamer-out.c (revision 208955) --- gcc/lto-streamer-out.c (working copy) *************** lto_is_streamable (tree expr) *** 313,318 **** --- 313,339 ---- } + /* Wrap symbol references in *TP inside a type-preserving MEM_REF. */ + + static tree + wrap_refs (tree *tp, int *ws, void *) + { + tree t = *tp; + if (TREE_CODE (t) == VAR_DECL) + { + tree ptrtype = build_pointer_type (TREE_TYPE (t)); + *tp = build2 (MEM_REF, TREE_TYPE (t), + build1 (ADDR_EXPR, ptrtype, t), + build_int_cst (ptrtype, 0)); + *ws = 0; + } + else if (TREE_CODE (t) == CONSTRUCTOR) + ; + else if (!EXPR_P (t)) + *ws = 0; + return NULL_TREE; + } + /* For EXPR lookup and return what we want to stream to OB as DECL_INITIAL. */ static tree *************** get_symbol_initial_value (struct output_ *** 340,345 **** --- 361,374 ---- initial = error_mark_node; } + /* Wrap all symbol references inside the initializer in a MEM_REF + to preserve the type at the use even in case the symbol is + prevailed by one with a different type. We can safely skip this + during WPA. */ + if (!in_lto_p + && initial && initial != error_mark_node) + walk_tree (&initial, wrap_refs, NULL, NULL); + return initial; } Index: gcc/testsuite/gcc.dg/lto/pr60720_0.c =================================================================== *** gcc/testsuite/gcc.dg/lto/pr60720_0.c (revision 0) --- gcc/testsuite/gcc.dg/lto/pr60720_0.c (working copy) *************** *** 0 **** --- 1,15 ---- + /* { dg-lto-do run } */ + /* { dg-extra-ld-options { -w } } */ + + /* ??? lto.exp does not allow to scan for + :1:12: warning: type of 'x' does not match original declaration + extern int x[]; + ^ + :1:5: note: previously declared here + int x; + ^ */ + + extern int x[]; + int *foo[] = { &x[0] }; + + int main() { return *foo[0]; } Index: gcc/testsuite/gcc.dg/lto/pr60720_1.c =================================================================== *** gcc/testsuite/gcc.dg/lto/pr60720_1.c (revision 0) --- gcc/testsuite/gcc.dg/lto/pr60720_1.c (working copy) *************** *** 0 **** --- 1 ---- + int x;