2010-11-02 Martin Jambor <mjambor@suse.cz>
authorjamborm <jamborm@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 2 Nov 2010 15:22:52 +0000 (15:22 +0000)
committerjamborm <jamborm@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 2 Nov 2010 15:22:52 +0000 (15:22 +0000)
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.

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

gcc/ChangeLog
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/ipa/ivinline-9.C [new file with mode: 0644]
gcc/tree.c

index c946683..a347b05 100644 (file)
@@ -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
index aa80464..471b009 100644 (file)
@@ -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 (file)
index 0000000..429b6f4
--- /dev/null
@@ -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" } } */
index a746031..1cc99f0 100644 (file)
@@ -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.  */