aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Jambor <mjambor@suse.cz>2010-11-02 16:22:52 +0100
committerMartin Jambor <jamborm@gcc.gnu.org>2010-11-02 16:22:52 +0100
commit4c2030661e0a9bce68786f72e4d0da1be5caf3a5 (patch)
tree6b301cc7b78e84ad831cce83f66b80281b61bc17
parent7a2b3e20767d3d11776e4c5bbb12d751e7ba748f (diff)
downloadgcc-4c2030661e0a9bce68786f72e4d0da1be5caf3a5.zip
gcc-4c2030661e0a9bce68786f72e4d0da1be5caf3a5.tar.gz
gcc-4c2030661e0a9bce68786f72e4d0da1be5caf3a5.tar.bz2
re PR middle-end/46120 (g++.dg/ipa/ivinline-?.C)
2010-11-02 Martin Jambor <mjambor@suse.cz> PR middle-end/46120 * tree.c (get_binfo_at_offset): Bail out on artificial fields. Identify primary bases according to their offsets. * testsuite/g++.dg/ipa/ivinline-9.C: New test. From-SVN: r166192
-rw-r--r--gcc/ChangeLog6
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/g++.dg/ipa/ivinline-9.C93
-rw-r--r--gcc/tree.c40
4 files changed, 125 insertions, 19 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index c946683..a347b05 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,5 +1,11 @@
2010-11-02 Martin Jambor <mjambor@suse.cz>
+ PR middle-end/46120
+ * tree.c (get_binfo_at_offset): Bail out on artificial
+ fields. Identify primary bases according to their offsets.
+
+2010-11-02 Martin Jambor <mjambor@suse.cz>
+
PR tree-optimization/45875
* gimple-fold.c (get_first_base_binfo_with_virtuals): Removed.
(gimple_get_relevant_ref_binfo): Detect primary bases according to
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index aa80464..471b009 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,5 +1,10 @@
2010-11-02 Martin Jambor <mjambor@suse.cz>
+ PR middle-end/46120
+ * g++.dg/ipa/ivinline-9.C: New test.
+
+2010-11-02 Martin Jambor <mjambor@suse.cz>
+
PR tree-optimization/45875
* g++.dg/torture/pr45875.C: New test.
diff --git a/gcc/testsuite/g++.dg/ipa/ivinline-9.C b/gcc/testsuite/g++.dg/ipa/ivinline-9.C
new file mode 100644
index 0000000..429b6f4
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ipa/ivinline-9.C
@@ -0,0 +1,93 @@
+/* Verify that simple virtual calls are inlined even without early
+ inlining, even when a typecast to an ancestor is involved along the
+ way and that ancestor itself has an ancestor wich is not the
+ primary base class. */
+/* { dg-do run } */
+/* { dg-options "-O3 -fdump-ipa-inline -fno-early-inlining -fno-ipa-cp" } */
+
+extern "C" void abort (void);
+
+class Distraction
+{
+public:
+ float f;
+ double d;
+ Distraction ()
+ {
+ f = 8.3;
+ d = 10.2;
+ }
+ virtual float bar (float z);
+};
+
+class A
+{
+public:
+ int data;
+ virtual int foo (int i);
+};
+/*
+class D2
+{
+public:
+ virtual float baz (float z)
+ {
+ abort();
+ }
+};
+*/
+class A2 : public Distraction, public A
+{
+ int i2;
+};
+
+class B : public A2
+{
+public:
+ virtual int foo (int i);
+};
+
+float Distraction::bar (float z)
+{
+ f += z;
+ return f/2;
+}
+
+int A::foo (int i)
+{
+ return i + 1;
+}
+
+int B::foo (int i)
+{
+ return i + 2;
+}
+
+int __attribute__ ((noinline,noclone)) get_input(void)
+{
+ return 1;
+}
+
+static int middleman_1 (class A *obj, int i)
+{
+ return obj->foo (i);
+}
+
+static int middleman_2 (class B *obj, int i)
+{
+ return middleman_1 (obj, i);
+}
+
+int main (int argc, char *argv[])
+{
+ class B b;
+ int i;
+
+ for (i = 0; i < get_input (); i++)
+ if (middleman_2 (&b, get_input ()) != 3)
+ abort ();
+ return 0;
+}
+
+/* { dg-final { scan-ipa-dump "B::foo\[^\\n\]*inline copy in int main" "inline" } } */
+/* { dg-final { cleanup-ipa-dump "inline" } } */
diff --git a/gcc/tree.c b/gcc/tree.c
index a746031..1cc99f0 100644
--- a/gcc/tree.c
+++ b/gcc/tree.c
@@ -10906,16 +10906,17 @@ lhd_gcc_personality (void)
tree
get_binfo_at_offset (tree binfo, HOST_WIDE_INT offset, tree expected_type)
{
- tree type;
+ tree type = TREE_TYPE (binfo);
- type = TREE_TYPE (binfo);
- while (offset > 0)
+ while (true)
{
- tree base_binfo, found_binfo;
HOST_WIDE_INT pos, size;
tree fld;
int i;
+ gcc_checking_assert (offset >= 0);
+ if (type == expected_type)
+ return binfo;
if (TREE_CODE (type) != RECORD_TYPE)
return NULL_TREE;
@@ -10929,27 +10930,28 @@ get_binfo_at_offset (tree binfo, HOST_WIDE_INT offset, tree expected_type)
if (pos <= offset && (pos + size) > offset)
break;
}
- if (!fld)
+ if (!fld || !DECL_ARTIFICIAL (fld))
return NULL_TREE;
- found_binfo = NULL_TREE;
- for (i = 0; BINFO_BASE_ITERATE (binfo, i, base_binfo); i++)
- if (TREE_TYPE (base_binfo) == TREE_TYPE (fld))
- {
- found_binfo = base_binfo;
- break;
- }
-
- if (!found_binfo)
- return NULL_TREE;
+ /* Offset 0 indicates the primary base, whose vtable contents are
+ represented in the binfo for the derived class. */
+ if (offset != 0)
+ {
+ tree base_binfo, found_binfo = NULL_TREE;
+ for (i = 0; BINFO_BASE_ITERATE (binfo, i, base_binfo); i++)
+ if (TREE_TYPE (base_binfo) == TREE_TYPE (fld))
+ {
+ found_binfo = base_binfo;
+ break;
+ }
+ if (!found_binfo)
+ return NULL_TREE;
+ binfo = found_binfo;
+ }
type = TREE_TYPE (fld);
- binfo = found_binfo;
offset -= pos;
}
- if (type != expected_type)
- return NULL_TREE;
- return binfo;
}
/* Returns true if X is a typedef decl. */