===================================================================
@@ -1699,10 +1699,6 @@ struct GTY((variable_size)) lang_type {
/* Nonzero means that this class is on a path leading to a new vtable. */
#define BINFO_VTABLE_PATH_MARKED(NODE) BINFO_FLAG_1 (NODE)
-/* Nonzero means B (a BINFO) has its own vtable. Any copies will not
- have this flag set. */
-#define BINFO_NEW_VTABLE_MARKED(B) (BINFO_FLAG_2 (B))
-
/* Compare a BINFO_TYPE with another type for equality. For a binfo,
this is functionally equivalent to using same_type_p, but
measurably faster. At least one of the arguments must be a
===================================================================
@@ -1430,7 +1430,9 @@ gimple_get_relevant_ref_binfo (tree ref,
return NULL_TREE;
base_binfo = get_first_base_binfo_with_virtuals (binfo);
- if (base_binfo && BINFO_TYPE (base_binfo) != TREE_TYPE (field))
+ if (base_binfo
+ && (BINFO_TYPE (base_binfo) != TREE_TYPE (field)
+ || BINFO_NEW_VTABLE_MARKED (base_binfo)))
{
tree d_binfo;
@@ -1465,6 +1467,7 @@ gimple_fold_obj_type_ref_known_binfo (HO
HOST_WIDE_INT i;
tree v, fndecl, delta;
+ gcc_assert (BINFO_NEW_VTABLE_MARKED (known_binfo));
v = BINFO_VIRTUALS (known_binfo);
i = 0;
while (i != token)
===================================================================
@@ -0,0 +1,25 @@
+// { dg-do compile }
+
+struct c1 {};
+
+struct c10 : c1
+{
+ virtual void foo ();
+};
+
+struct c11 : c10, c1 // // { dg-warning "" }
+{
+ virtual void f6 ();
+};
+
+struct c28 : virtual c11
+{
+ void f6 ();
+};
+
+void check_c28 ()
+{
+ c28 obj;
+ c11 *ptr = &obj;
+ ptr->f6 ();
+}
===================================================================
@@ -2365,7 +2365,6 @@ struct GTY(()) tree_type {
/* Flags for language dependent use. */
#define BINFO_MARKED(NODE) TREE_LANG_FLAG_0(TREE_BINFO_CHECK(NODE))
#define BINFO_FLAG_1(NODE) TREE_LANG_FLAG_1(TREE_BINFO_CHECK(NODE))
-#define BINFO_FLAG_2(NODE) TREE_LANG_FLAG_2(TREE_BINFO_CHECK(NODE))
#define BINFO_FLAG_3(NODE) TREE_LANG_FLAG_3(TREE_BINFO_CHECK(NODE))
#define BINFO_FLAG_4(NODE) TREE_LANG_FLAG_4(TREE_BINFO_CHECK(NODE))
#define BINFO_FLAG_5(NODE) TREE_LANG_FLAG_5(TREE_BINFO_CHECK(NODE))
@@ -2374,6 +2373,10 @@ struct GTY(()) tree_type {
/* The actual data type node being inherited in this basetype. */
#define BINFO_TYPE(NODE) TREE_TYPE (TREE_BINFO_CHECK(NODE))
+/* Nonzero means B (a BINFO) has its own vtable. Any copies will not
+ have this flag set. */
+#define BINFO_NEW_VTABLE_MARKED(NODE) TREE_LANG_FLAG_2(TREE_BINFO_CHECK(NODE))
+
/* The offset where this basetype appears in its containing type.
BINFO_OFFSET slot holds the offset (in bytes)
from the base of the complete object to the base of the part of the
===================================================================
@@ -0,0 +1,68 @@
+/* Verify that virtual calls are folded even when a typecast to an
+ ancestor is involved along the way. */
+/* { dg-do run } */
+/* { dg-options "-O -fdump-tree-optimized-slim" } */
+
+extern "C" void abort (void);
+
+class A
+{
+public:
+ int data;
+ virtual int foo (int i);
+};
+
+class A_2 : public A
+{
+public:
+ int data_2;
+ virtual int baz (int i);
+};
+
+class B : public virtual A_2
+{
+public:
+ virtual int bah (int i);
+};
+
+int A::foo (int i)
+{
+ return i + 2;
+}
+
+int A_2::baz (int i)
+{
+ return i * 15;
+}
+
+int B::bah (int i)
+{
+ return i + 10;
+}
+
+int __attribute__ ((noinline,noclone)) get_input(void)
+{
+ return 1;
+}
+
+static inline int middleman_1 (class A *obj, int i)
+{
+ return obj->foo (i);
+}
+
+static inline int middleman_2 (class A *obj, int i)
+{
+ return middleman_1 (obj, i);
+}
+
+int main (int argc, char *argv[])
+{
+ class B b;
+
+ if (middleman_2 (&b, get_input ()) != 3)
+ abort ();
+ return 0;
+}
+
+/* { dg-final { scan-tree-dump "= B::.*foo" "optimized" } } */
+/* { dg-final { cleanup-tree-dump "optimized" } } */