OSDN Git Service

* class.c (dfs_find_final_overrider): Adjust so that the most
authormmitchel <mmitchel@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 14 Nov 2002 16:59:23 +0000 (16:59 +0000)
committermmitchel <mmitchel@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 14 Nov 2002 16:59:23 +0000 (16:59 +0000)
derived object is a binfo, rather than a class type.
(find_final_overrider): Likewise.
(add_vcall_offset_vtbl_entries_1): Simplify accordingly.
(add_vcall_offset): Likewise.

* g++.dg/abi/vcall1.C: New test.

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

gcc/cp/ChangeLog
gcc/cp/class.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/abi/vcall1.C [new file with mode: 0644]

index 0b5b670..5550411 100644 (file)
@@ -1,3 +1,11 @@
+2002-11-14  Mark Mitchell  <mark@codesourcery.com>
+
+       * class.c (dfs_find_final_overrider): Adjust so that the most
+       derived object is a binfo, rather than a class type.
+       (find_final_overrider): Likewise.
+       (add_vcall_offset_vtbl_entries_1): Simplify accordingly.
+       (add_vcall_offset): Likewise.
+
 2002-11-09  Kriang Lerdsuwanakij  <lerdsuwa@users.sourceforge.net>
 
        PR c++/8389
index 2ca45a6..3c2084d 100644 (file)
@@ -2220,9 +2220,11 @@ dfs_find_final_overrider (binfo, data)
       method = NULL_TREE;
       /* We've found a path to the declaring base.  Walk down the path
         looking for an overrider for FN.  */
-      for (path = reverse_path (binfo);
-          path;
-          path = TREE_CHAIN (path))
+      path = reverse_path (binfo);
+      while (!same_type_p (BINFO_TYPE (TREE_VALUE (path)),
+                          ffod->most_derived_type))
+       path = TREE_CHAIN (path);
+      while (path)
        {
          method = look_for_overrides_here (BINFO_TYPE (TREE_VALUE (path)),
                                            ffod->fn);
@@ -2231,6 +2233,8 @@ dfs_find_final_overrider (binfo, data)
              path = TREE_VALUE (path);
              break;
            }
+
+         path = TREE_CHAIN (path);
        }
 
       /* If we found an overrider, record the overriding function, and
@@ -2264,12 +2268,12 @@ dfs_find_final_overrider (binfo, data)
 
 /* Returns a TREE_LIST whose TREE_PURPOSE is the final overrider for
    FN and whose TREE_VALUE is the binfo for the base where the
-   overriding occurs.  BINFO (in the hierarchy dominated by T) is the
-   base object in which FN is declared.  */
+   overriding occurs.  BINFO (in the hierarchy dominated by the binfo
+   DERIVED) is the base object in which FN is declared.  */
 
 static tree
-find_final_overrider (t, binfo, fn)
-     tree t;
+find_final_overrider (derived, binfo, fn)
+     tree derived;
      tree binfo;
      tree fn;
 {
@@ -2295,10 +2299,10 @@ find_final_overrider (t, binfo, fn)
      different overriders along any two, then there is a problem.  */
   ffod.fn = fn;
   ffod.declaring_base = binfo;
-  ffod.most_derived_type = t;
+  ffod.most_derived_type = BINFO_TYPE (derived);
   ffod.candidates = NULL_TREE;
 
-  dfs_walk (TYPE_BINFO (t),
+  dfs_walk (derived,
            dfs_find_final_overrider,
            NULL,
            &ffod);
@@ -2306,7 +2310,8 @@ find_final_overrider (t, binfo, fn)
   /* If there was no winner, issue an error message.  */
   if (!ffod.candidates || TREE_CHAIN (ffod.candidates))
     {
-      error ("no unique final overrider for `%D' in `%T'", fn, t);
+      error ("no unique final overrider for `%D' in `%T'", fn, 
+            BINFO_TYPE (derived));
       return error_mark_node;
     }
 
@@ -2365,7 +2370,7 @@ update_vtable_entry_for_fn (t, binfo, fn, virtuals)
   first_defn = b;
 
   /* Find the final overrider.  */
-  overrider = find_final_overrider (t, b, fn);
+  overrider = find_final_overrider (TYPE_BINFO (t), b, fn);
   if (overrider == error_mark_node)
     return;
 
@@ -7909,14 +7914,6 @@ add_vcall_offset_vtbl_entries_1 (binfo, vid)
      tree binfo;
      vtbl_init_data* vid;
 {
-  tree binfo_in_rtti;
-
-  if (vid->ctor_vtbl_p)
-    binfo_in_rtti = (get_original_base
-                    (binfo, TYPE_BINFO (BINFO_TYPE (vid->rtti_binfo))));
-  else
-    binfo_in_rtti = binfo;
-
   /* Make entries for the rest of the virtuals.  */
   if (abi_version_at_least (2))
     {
@@ -7928,7 +7925,7 @@ add_vcall_offset_vtbl_entries_1 (binfo, vid)
           orig_fn;
           orig_fn = TREE_CHAIN (orig_fn))
        if (DECL_VINDEX (orig_fn))
-         add_vcall_offset (orig_fn, binfo_in_rtti, vid);
+         add_vcall_offset (orig_fn, binfo, vid);
     }
   else
     {
@@ -7993,18 +7990,15 @@ add_vcall_offset_vtbl_entries_1 (binfo, vid)
          if (!same_type_p (DECL_CONTEXT (orig_fn), BINFO_TYPE (binfo)))
            continue;
 
-         add_vcall_offset (orig_fn, binfo_in_rtti, vid);
+         add_vcall_offset (orig_fn, binfo, vid);
        }
     }
 }
 
-/* Add a vcall offset entry for ORIG_FN to the vtable.  In a
-   construction vtable, BINFO_IN_RTTI is the base corresponding to the
-   vtable base in VID->RTTI_BINFO.  */
+/* Add a vcall offset entry for ORIG_FN to the vtable.  */
 
 static void
-add_vcall_offset (tree orig_fn, tree binfo_in_rtti,
-                 vtbl_init_data *vid)
+add_vcall_offset (tree orig_fn, tree binfo, vtbl_init_data *vid)
 {
   size_t i;
   tree vcall_offset;
@@ -8045,35 +8039,23 @@ add_vcall_offset (tree orig_fn, tree binfo_in_rtti,
   if (vid->generate_vcall_entries)
     {
       tree base;
-      tree base_binfo;
       tree fn;
 
       /* Find the overriding function.  */
-      fn = find_final_overrider (BINFO_TYPE (vid->rtti_binfo), 
-                                binfo_in_rtti, orig_fn);
+      fn = find_final_overrider (vid->rtti_binfo, binfo, orig_fn);
       if (fn == error_mark_node)
        vcall_offset = build1 (NOP_EXPR, vtable_entry_type,
                               integer_zero_node);
       else
        {
-         fn = TREE_PURPOSE (fn);
-         /* The FN comes from BASE.  So, we must calculate the
-            adjustment from vid->vbase to BASE.  We can just look for
-            BASE in the complete object because we are converting
-            from a virtual base, so if there were multiple copies,
-            there would not be a unique final overrider and
-            vid->derived would be ill-formed.  */
-         base = DECL_CONTEXT (fn);
-         base_binfo = lookup_base (vid->derived, base, ba_any, NULL);
-
-         /* Compute the vcall offset.  */
-         /* As mentioned above, the vbase we're working on is a
-            primary base of vid->binfo.  But it might be a lost
-            primary, so its BINFO_OFFSET might be wrong, so we just
-            use the BINFO_OFFSET from vid->binfo.  */
-         vcall_offset = BINFO_OFFSET (vid->binfo);
-         vcall_offset = size_diffop (BINFO_OFFSET (base_binfo),
-                                     vcall_offset);
+         base = TREE_VALUE (fn);
+
+         /* The vbase we're working on is a primary base of
+            vid->binfo.  But it might be a lost primary, so its
+            BINFO_OFFSET might be wrong, so we just use the
+            BINFO_OFFSET from vid->binfo.  */
+         vcall_offset = size_diffop (BINFO_OFFSET (base),
+                                     BINFO_OFFSET (vid->binfo));
          vcall_offset = fold (build1 (NOP_EXPR, vtable_entry_type,
                                       vcall_offset));
        }
index 968777c..3caf7d8 100644 (file)
@@ -1,3 +1,7 @@
+2002-11-14  Mark Mitchell  <mark@codesourcery.com>
+
+       * g++.dg/abi/vcall1.C: New test.
+
 2002-11-14  Jakub Jelinek  <jakub@redhat.com>
 
        * gcc.dg/20021029-1.c: New test.
diff --git a/gcc/testsuite/g++.dg/abi/vcall1.C b/gcc/testsuite/g++.dg/abi/vcall1.C
new file mode 100644 (file)
index 0000000..00830cd
--- /dev/null
@@ -0,0 +1,36 @@
+// { dg-do run }
+// { dg-options "-w" }
+
+extern "C" void abort ();
+
+struct B;
+
+B* b;
+
+struct A {
+  virtual void f () {}
+};
+
+struct B : virtual public A {
+  B () {
+    b = this;
+    ((A*) this)->f ();
+  }
+
+  virtual void f () {
+    if (this != b)
+      abort ();
+  }
+};
+
+struct C : public B {
+};
+
+struct D : public C, public B {
+  virtual void f () {}
+};
+
+int main () {
+  D d;
+}
+