]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
re PR middle-end/46120 (g++.dg/ipa/ivinline-?.C)
authorMartin Jambor <mjambor@suse.cz>
Tue, 2 Nov 2010 15:22:52 +0000 (16:22 +0100)
committerMartin Jambor <jamborm@gcc.gnu.org>
Tue, 2 Nov 2010 15:22:52 +0000 (16:22 +0100)
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

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

index c946683d46e2f6bf99ee44add3a65857409111ed..a347b05182c7a2b46c538774baa6e2ea777e2d3c 100644 (file)
@@ -1,3 +1,9 @@
+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
index aa80464b054e2e3a9fd49ae098c63fe456621687..471b009da58309425c82581785c0dc1b05343106 100644 (file)
@@ -1,3 +1,8 @@
+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
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 a74603156586de0784fb80ab1a1dca6da940a967..1cc99f07c67a697fcecc3008cf19e1d5d403a3fd 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.  */