On Mon, 31 Mar 2014, Richard Biener wrote: > > 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.
It turns out that changing the tree structure while doing a DFS walk is a bad idea so the following patch instead does it at lto_output time (and restricts it to necessary cases, handled-component-refs wrapping the decls). LTO bootstrapped and tested on x86_64-unknown-linux-gnu, queued for stage1. Richard. 2014-04-01 Richard Biener <rguent...@suse.de> PR lto/60720 * lto-streamer-out.c (wrap_refs): New function. (lto_output): 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) *************** copy_function (struct cgraph_node *node) *** 2024,2029 **** --- 2024,2052 ---- lto_end_section (); } + /* Wrap symbol references in *TP inside a type-preserving MEM_REF. */ + + static tree + wrap_refs (tree *tp, int *ws, void *) + { + tree t = *tp; + if (handled_component_p (t) + && TREE_CODE (TREE_OPERAND (t, 0)) == VAR_DECL) + { + tree decl = TREE_OPERAND (t, 0); + tree ptrtype = build_pointer_type (TREE_TYPE (decl)); + TREE_OPERAND (t, 0) = build2 (MEM_REF, TREE_TYPE (decl), + build1 (ADDR_EXPR, ptrtype, decl), + build_int_cst (ptrtype, 0)); + TREE_THIS_VOLATILE (TREE_OPERAND (t, 0)) = TREE_THIS_VOLATILE (decl); + *ws = 0; + } + else if (TREE_CODE (t) == CONSTRUCTOR) + ; + else if (!EXPR_P (t)) + *ws = 0; + return NULL_TREE; + } /* Main entry point from the pass manager. */ *************** lto_output (void) *** 2045,2068 **** for (i = 0; i < n_nodes; i++) { symtab_node *snode = lto_symtab_encoder_deref (encoder, i); ! cgraph_node *node = dyn_cast <cgraph_node> (snode); ! if (node ! && lto_symtab_encoder_encode_body_p (encoder, node) ! && !node->alias) { #ifdef ENABLE_CHECKING ! gcc_assert (!bitmap_bit_p (output, DECL_UID (node->decl))); ! bitmap_set_bit (output, DECL_UID (node->decl)); #endif ! decl_state = lto_new_out_decl_state (); ! lto_push_out_decl_state (decl_state); ! if (gimple_has_body_p (node->decl) || !flag_wpa) ! output_function (node); ! else ! copy_function (node); ! gcc_assert (lto_get_out_decl_state () == decl_state); ! lto_pop_out_decl_state (); ! lto_record_function_out_decl_state (node->decl, decl_state); } } --- 2068,2100 ---- for (i = 0; i < n_nodes; i++) { symtab_node *snode = lto_symtab_encoder_deref (encoder, i); ! if (cgraph_node *node = dyn_cast <cgraph_node> (snode)) { + if (lto_symtab_encoder_encode_body_p (encoder, node) + && !node->alias) + { #ifdef ENABLE_CHECKING ! gcc_assert (!bitmap_bit_p (output, DECL_UID (node->decl))); ! bitmap_set_bit (output, DECL_UID (node->decl)); #endif ! decl_state = lto_new_out_decl_state (); ! lto_push_out_decl_state (decl_state); ! if (gimple_has_body_p (node->decl) || !flag_wpa) ! output_function (node); ! else ! copy_function (node); ! gcc_assert (lto_get_out_decl_state () == decl_state); ! lto_pop_out_decl_state (); ! lto_record_function_out_decl_state (node->decl, decl_state); ! } ! } ! else if (varpool_node *node = dyn_cast <varpool_node> (snode)) ! { ! /* Wrap symbol references inside the ctor in a type ! preserving MEM_REF. */ ! tree ctor = DECL_INITIAL (node->decl); ! if (ctor && !in_lto_p) ! walk_tree (&ctor, wrap_refs, NULL, NULL); } } 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;