summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2008-02-12 19:35:05 +0100
committerJakub Jelinek <jakub@gcc.gnu.org>2008-02-12 19:35:05 +0100
commite4521d118a44d6e3b07612ac3fa9fe93eea17403 (patch)
tree0c5b420a4940a7a869b6ac259ffcc50432cdc046
parentd7b8033f3e4f59d5ff54ab68fe5667467a52a273 (diff)
downloadgcc-e4521d118a44d6e3b07612ac3fa9fe93eea17403.tar.gz
re PR c++/35144 (ICE in generate_element_copy)
PR c++/35144 * tree-sra.c (sra_build_assignment): fold_convert SRC if copying non-compatible pointers. (generate_element_copy): If SRC and DST are RECORD_TYPEs with different FIELD_DECLs, try harder by comparing field offsets, sizes and types. * g++.dg/tree-ssa/pr35144.C: New test. From-SVN: r132264
-rw-r--r--gcc/ChangeLog7
-rw-r--r--gcc/testsuite/ChangeLog3
-rw-r--r--gcc/testsuite/g++.dg/tree-ssa/pr35144.C30
-rw-r--r--gcc/tree-sra.c38
4 files changed, 75 insertions, 3 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 553f34922c5..8eb01b693fb 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,5 +1,12 @@
2008-02-12 Jakub Jelinek <jakub@redhat.com>
+ PR c++/35144
+ * tree-sra.c (sra_build_assignment): fold_convert SRC if copying
+ non-compatible pointers.
+ (generate_element_copy): If SRC and DST are RECORD_TYPEs with
+ different FIELD_DECLs, try harder by comparing field offsets, sizes
+ and types.
+
PR inline-asm/35160
* function.c (match_asm_constraints_1): Don't replace the same input
multiple times.
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 40c0ba2165d..f8d824d177b 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,5 +1,8 @@
2008-02-12 Jakub Jelinek <jakub@redhat.com>
+ PR c++/35144
+ * g++.dg/tree-ssa/pr35144.C: New test.
+
PR inline-asm/35160
* gcc.target/i386/pr35160.c: New test.
diff --git a/gcc/testsuite/g++.dg/tree-ssa/pr35144.C b/gcc/testsuite/g++.dg/tree-ssa/pr35144.C
new file mode 100644
index 00000000000..f0bb7bb6363
--- /dev/null
+++ b/gcc/testsuite/g++.dg/tree-ssa/pr35144.C
@@ -0,0 +1,30 @@
+// PR c++/35144
+// { dg-do compile }
+// { dg-options "-O2" }
+
+struct A
+{
+ int baz ();
+};
+
+typedef int (A::*P) ();
+
+struct B
+{
+ B ();
+ int foo (P x, int y = 0);
+};
+
+struct C
+{
+ typedef int (B::*Q) (P, int);
+ void bar (Q x) { c = x; }
+ Q c;
+};
+
+extern C c;
+
+B::B ()
+{
+ c.bar ((C::Q) &B::foo);
+}
diff --git a/gcc/tree-sra.c b/gcc/tree-sra.c
index df6c6dc7be6..26f1af4196a 100644
--- a/gcc/tree-sra.c
+++ b/gcc/tree-sra.c
@@ -1,7 +1,7 @@
/* Scalar Replacement of Aggregates (SRA) converts some structure
references into scalar references, exposing them to the scalar
optimizers.
- Copyright (C) 2003, 2004, 2005, 2006, 2007
+ Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008
Free Software Foundation, Inc.
Contributed by Diego Novillo <dnovillo@redhat.com>
@@ -2270,7 +2270,13 @@ sra_build_assignment (tree dst, tree src)
Since such accesses under different types require compatibility
anyway, there's little point in making tests and/or adding
conversions to ensure the types of src and dst are the same.
- So we just assume type differences at this point are ok. */
+ So we just assume type differences at this point are ok.
+ The only exception we make here are pointer types, which can be different
+ in e.g. structurally equal, but non-identical RECORD_TYPEs. */
+ if (POINTER_TYPE_P (TREE_TYPE (dst))
+ && !useless_type_conversion_p (TREE_TYPE (dst), TREE_TYPE (src)))
+ src = fold_convert (TREE_TYPE (dst), src);
+
return build_gimple_modify_stmt (dst, src);
}
@@ -2600,7 +2606,33 @@ generate_element_copy (struct sra_elt *dst, struct sra_elt *src, tree *list_p)
continue;
}
- gcc_assert (sc);
+
+ /* If DST and SRC are structs with the same elements, but do not have
+ the same TYPE_MAIN_VARIANT, then lookup of DST FIELD_DECL in SRC
+ will fail. Try harder by finding the corresponding FIELD_DECL
+ in SRC. */
+ if (!sc)
+ {
+ tree f;
+
+ gcc_assert (useless_type_conversion_p (dst->type, src->type));
+ gcc_assert (TREE_CODE (dc->element) == FIELD_DECL);
+ for (f = TYPE_FIELDS (src->type); f ; f = TREE_CHAIN (f))
+ if (simple_cst_equal (DECL_FIELD_OFFSET (f),
+ DECL_FIELD_OFFSET (dc->element)) > 0
+ && simple_cst_equal (DECL_FIELD_BIT_OFFSET (f),
+ DECL_FIELD_BIT_OFFSET (dc->element)) > 0
+ && simple_cst_equal (DECL_SIZE (f),
+ DECL_SIZE (dc->element)) > 0
+ && (useless_type_conversion_p (TREE_TYPE (dc->element),
+ TREE_TYPE (f))
+ || (POINTER_TYPE_P (TREE_TYPE (dc->element))
+ && POINTER_TYPE_P (TREE_TYPE (f)))))
+ break;
+ gcc_assert (f != NULL_TREE);
+ sc = lookup_element (src, f, NULL, NO_INSERT);
+ }
+
generate_element_copy (dc, sc, list_p);
}