aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/ChangeLog7
-rw-r--r--gcc/lto-streamer-out.c62
-rw-r--r--gcc/testsuite/ChangeLog8
-rw-r--r--gcc/testsuite/gcc.dg/lto/pr60720_0.c15
-rw-r--r--gcc/testsuite/gcc.dg/lto/pr60720_1.c1
5 files changed, 77 insertions, 16 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 4d1bc3d..0267359 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,10 @@
+2014-04-14 Richard Biener <rguenther@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.
+
2014-04-14 Christian Bruel <christian.bruel@st.com>
* config/sh/sh-mem.cc (sh_expand_strlen): Unroll last word.
diff --git a/gcc/lto-streamer-out.c b/gcc/lto-streamer-out.c
index 69b5a79..b193d73 100644
--- a/gcc/lto-streamer-out.c
+++ b/gcc/lto-streamer-out.c
@@ -2022,6 +2022,29 @@ copy_function (struct cgraph_node *node)
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. */
@@ -2043,24 +2066,33 @@ lto_output (void)
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)
+ 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));
+ 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);
+ 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);
}
}
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 3b85529..6c49b9a 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,4 +1,10 @@
-2014-01-20 Christian Bruel <christian.bruel@st.com>
+2014-04-14 Richard Biener <rguenther@suse.de>
+
+ PR lto/60720
+ * gcc.dg/lto/pr60720_0.c: New testcase.
+ * gcc.dg/lto/pr60720_1.c: Likewise.
+
+2014-04-14 Christian Bruel <christian.bruel@st.com>
* gcc.target/sh/memset.c: New test.
diff --git a/gcc/testsuite/gcc.dg/lto/pr60720_0.c b/gcc/testsuite/gcc.dg/lto/pr60720_0.c
new file mode 100644
index 0000000..79cef5d
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/lto/pr60720_0.c
@@ -0,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]; }
diff --git a/gcc/testsuite/gcc.dg/lto/pr60720_1.c b/gcc/testsuite/gcc.dg/lto/pr60720_1.c
new file mode 100644
index 0000000..6d1a0d4
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/lto/pr60720_1.c
@@ -0,0 +1 @@
+int x;