OSDN Git Service

PR c++/35144
authorjakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 12 Feb 2008 18:35:05 +0000 (18:35 +0000)
committerjakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 12 Feb 2008 18:35:05 +0000 (18:35 +0000)
* 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.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@132264 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/tree-ssa/pr35144.C [new file with mode: 0644]
gcc/tree-sra.c

index 553f349..8eb01b6 100644 (file)
@@ -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.
index 40c0ba2..f8d824d 100644 (file)
@@ -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 (file)
index 0000000..f0bb7bb
--- /dev/null
@@ -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);
+}
index df6c6dc..26f1af4 100644 (file)
@@ -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);
     }