http://gcc.gnu.org/bugzilla/show_bug.cgi?id=59775

--- Comment #9 from Jan Hubicka <hubicka at ucw dot cz> ---
This is fix I am testing. It makes get_binfo_at_offset to walk down the
non-virtual
part of the hiearchy until it hits the proper base.

I hope to significantly simplify get_binfo_at_offset by making it to walk bases
only and use get_class_context to walk structure fields/array indexes. In that
case
it would make more sense to implement it same was as record_target_from_binfo
(i.e.
omit the fields walk completely and only care about bases), but for 4.9 I think
this
can be resonable fix.

Honza

Index: tree.c
===================================================================
--- tree.c    (revision 206542)
+++ tree.c    (working copy)
@@ -11995,16 +11995,35 @@ get_binfo_at_offset (tree binfo, HOST_WI
      represented in the binfo for the derived class.  */
       else if (offset != 0)
     {
-      tree base_binfo, found_binfo = NULL_TREE;
-      for (i = 0; BINFO_BASE_ITERATE (binfo, i, base_binfo); i++)
-        if (types_same_for_odr (TREE_TYPE (base_binfo), TREE_TYPE (fld)))
-          {
-        found_binfo = base_binfo;
-        break;
-          }
-      if (!found_binfo)
-        return NULL_TREE;
-      binfo = found_binfo;
+      tree base_binfo, binfo2 = binfo;
+
+      /* Find BINFO corresponding to FLD.  This is bit harder
+         by a fact that in virtual inheritance we may need to walk down
+         the non-virtual inheritance chain.  */
+      while (true)
+        {
+          tree containing_binfo = NULL, found_binfo = NULL;
+          for (i = 0; BINFO_BASE_ITERATE (binfo2, i, base_binfo); i++)
+        if (types_same_for_odr (TREE_TYPE (base_binfo), TREE_TYPE (fld)))
+          {
+            found_binfo = base_binfo;
+            break;
+          }
+        else
+          if (BINFO_OFFSET (base_binfo) - BINFO_OFFSET (binfo) < pos
+              && (!containing_binfo
+              || (BINFO_OFFSET (containing_binfo)
+                  < BINFO_OFFSET (base_binfo))))
+            containing_binfo = base_binfo;
+          if (found_binfo)
+        {
+          binfo = found_binfo;
+          break;
+        }
+          if (!containing_binfo)
+        return NULL_TREE;
+          binfo2 = containing_binfo;
+        }
     }

       type = TREE_TYPE (fld);

Reply via email to