summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/ChangeLog18
-rw-r--r--gcc/gimple-streamer-in.c2
-rw-r--r--gcc/gimple.c2
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/g++.dg/lto/pr51572-2_0.C16
-rw-r--r--gcc/tree-streamer-in.c3
-rw-r--r--gcc/tree-streamer-out.c3
-rw-r--r--gcc/tree.c6
8 files changed, 48 insertions, 7 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 214635a830b..c874164d590 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,21 @@
+2011-12-19 Richard Guenther <rguenther@suse.de>
+
+ PR lto/51572
+ * tree.c (free_lang_data_in_type): Do not unlink TYPE_DECL
+ from TYPE_FIELDS.
+ (find_decls_types_r): Walk TYPE_DECLs in TYPE_FIELDS.
+ * tree-streamer-out.c (write_ts_field_decl_tree_pointers): Do
+ not stream TREE_CHAIN.
+ (write_ts_type_non_common_tree_pointers): Stream TYPE_FIELDS
+ using streamer_write_chain.
+ * tree-streamer-in.c (lto_input_ts_field_decl_tree_pointers):
+ Do not stream TREE_CHAIN.
+ (lto_input_ts_type_non_common_tree_pointers): Stream TYPE_FIELDS
+ using streamer_read_chain.
+ * gimple-streamer-in.c (input_gimple_stmt): Skip non-FIELD_DECLs.
+ * gimple.c (gimple_canonical_types_compatible_p): Properly
+ handle trailing non-FIELD_DECLs in TYPE_FIELDS.
+
2011-12-19 Andreas Schwab <schwab@linux-m68k.org>
* configure: Regenerate.
diff --git a/gcc/gimple-streamer-in.c b/gcc/gimple-streamer-in.c
index dc112d0dd93..1b6bf4bd6d7 100644
--- a/gcc/gimple-streamer-in.c
+++ b/gcc/gimple-streamer-in.c
@@ -162,6 +162,8 @@ input_gimple_stmt (struct lto_input_block *ib, struct data_in *data_in,
type = DECL_CONTEXT (field);
for (tem = TYPE_FIELDS (type); tem; tem = TREE_CHAIN (tem))
{
+ if (TREE_CODE (tem) != FIELD_DECL)
+ continue;
if (tem == field)
break;
if (DECL_NONADDRESSABLE_P (tem)
diff --git a/gcc/gimple.c b/gcc/gimple.c
index 3a90358bae6..1f8f1027128 100644
--- a/gcc/gimple.c
+++ b/gcc/gimple.c
@@ -4702,7 +4702,7 @@ gimple_canonical_types_compatible_p (tree t1, tree t2)
/* For aggregate types, all the fields must be the same. */
for (f1 = TYPE_FIELDS (t1), f2 = TYPE_FIELDS (t2);
- f1 && f2;
+ f1 || f2;
f1 = TREE_CHAIN (f1), f2 = TREE_CHAIN (f2))
{
/* Skip non-fields. */
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index a8c71f2d0a9..bf2b3c18a71 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2011-12-19 Richard Guenther <rguenther@suse.de>
+
+ PR lto/51572
+ * g++.dg/lto/pr51572-2_0.C: New testcase.
+
2011-12-19 Dodji Seketeli <dodji@redhat.com>
PR c++/51477
diff --git a/gcc/testsuite/g++.dg/lto/pr51572-2_0.C b/gcc/testsuite/g++.dg/lto/pr51572-2_0.C
new file mode 100644
index 00000000000..f7de4f06aef
--- /dev/null
+++ b/gcc/testsuite/g++.dg/lto/pr51572-2_0.C
@@ -0,0 +1,16 @@
+// Copy of g++.dg/debug/pr45660
+// { dg-lto-do link }
+// { dg-lto-options { { -g -flto } } }
+
+int
+main ()
+{
+ struct S
+ {
+ typedef void (**T) (void);
+ static T i (void) { return 0; }
+ };
+ S s;
+ if (s.i ())
+ *s.i () = 0;
+}
diff --git a/gcc/tree-streamer-in.c b/gcc/tree-streamer-in.c
index 919a5be3060..8a18a995b75 100644
--- a/gcc/tree-streamer-in.c
+++ b/gcc/tree-streamer-in.c
@@ -643,7 +643,6 @@ lto_input_ts_field_decl_tree_pointers (struct lto_input_block *ib,
DECL_QUALIFIER (expr) = stream_read_tree (ib, data_in);
DECL_FIELD_BIT_OFFSET (expr) = stream_read_tree (ib, data_in);
DECL_FCONTEXT (expr) = stream_read_tree (ib, data_in);
- TREE_CHAIN (expr) = streamer_read_chain (ib, data_in);
}
@@ -706,7 +705,7 @@ lto_input_ts_type_non_common_tree_pointers (struct lto_input_block *ib,
else if (TREE_CODE (expr) == ARRAY_TYPE)
TYPE_DOMAIN (expr) = stream_read_tree (ib, data_in);
else if (RECORD_OR_UNION_TYPE_P (expr))
- TYPE_FIELDS (expr) = stream_read_tree (ib, data_in);
+ TYPE_FIELDS (expr) = streamer_read_chain (ib, data_in);
else if (TREE_CODE (expr) == FUNCTION_TYPE
|| TREE_CODE (expr) == METHOD_TYPE)
TYPE_ARG_TYPES (expr) = stream_read_tree (ib, data_in);
diff --git a/gcc/tree-streamer-out.c b/gcc/tree-streamer-out.c
index 897c2115807..0e4d278fb5a 100644
--- a/gcc/tree-streamer-out.c
+++ b/gcc/tree-streamer-out.c
@@ -553,7 +553,6 @@ write_ts_field_decl_tree_pointers (struct output_block *ob, tree expr,
stream_write_tree (ob, DECL_QUALIFIER (expr), ref_p);
stream_write_tree (ob, DECL_FIELD_BIT_OFFSET (expr), ref_p);
stream_write_tree (ob, DECL_FCONTEXT (expr), ref_p);
- streamer_write_chain (ob, TREE_CHAIN (expr), ref_p);
}
@@ -609,7 +608,7 @@ write_ts_type_non_common_tree_pointers (struct output_block *ob, tree expr,
else if (TREE_CODE (expr) == ARRAY_TYPE)
stream_write_tree (ob, TYPE_DOMAIN (expr), ref_p);
else if (RECORD_OR_UNION_TYPE_P (expr))
- stream_write_tree (ob, TYPE_FIELDS (expr), ref_p);
+ streamer_write_chain (ob, TYPE_FIELDS (expr), ref_p);
else if (TREE_CODE (expr) == FUNCTION_TYPE
|| TREE_CODE (expr) == METHOD_TYPE)
stream_write_tree (ob, TYPE_ARG_TYPES (expr), ref_p);
diff --git a/gcc/tree.c b/gcc/tree.c
index 247c6013d85..d7bbae3c675 100644
--- a/gcc/tree.c
+++ b/gcc/tree.c
@@ -4477,7 +4477,8 @@ free_lang_data_in_type (tree type)
member = TYPE_FIELDS (type);
while (member)
{
- if (TREE_CODE (member) == FIELD_DECL)
+ if (TREE_CODE (member) == FIELD_DECL
+ || TREE_CODE (member) == TYPE_DECL)
{
if (prev)
TREE_CHAIN (prev) = member;
@@ -4872,7 +4873,8 @@ find_decls_types_r (tree *tp, int *ws, void *data)
tem = TYPE_FIELDS (t);
while (tem)
{
- if (TREE_CODE (tem) == FIELD_DECL)
+ if (TREE_CODE (tem) == FIELD_DECL
+ || TREE_CODE (tem) == TYPE_DECL)
fld_worklist_push (tem, fld);
tem = TREE_CHAIN (tem);
}