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;

Reply via email to