diff options
author | Jakub Jelinek <jakub@redhat.com> | 2008-02-12 19:35:05 +0100 |
---|---|---|
committer | Jakub Jelinek <jakub@gcc.gnu.org> | 2008-02-12 19:35:05 +0100 |
commit | e4521d118a44d6e3b07612ac3fa9fe93eea17403 (patch) | |
tree | 0c5b420a4940a7a869b6ac259ffcc50432cdc046 | |
parent | d7b8033f3e4f59d5ff54ab68fe5667467a52a273 (diff) | |
download | gcc-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/ChangeLog | 7 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 3 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/tree-ssa/pr35144.C | 30 | ||||
-rw-r--r-- | gcc/tree-sra.c | 38 |
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); } |