OSDN Git Service

* cp-tree.h (BINFO_FOR_VBASE): Adjust documentation.
authormmitchel <mmitchel@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 22 Mar 2000 21:43:45 +0000 (21:43 +0000)
committermmitchel <mmitchel@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 22 Mar 2000 21:43:45 +0000 (21:43 +0000)
(CANONICAL_BINFO): New macro.
(BINFO_NEW_VTABLE_MARKED): Use it.
(SET_BINFO_NEW_VTABLE_MARKED): Likewise.
(CLEAR_BINFO_NEW_VTABLE_MARKED): Likewise.
* class.c (dfs_build_vbase_offset_vtbl_entries): Use BINFO_TYPE,
not TREE_TYPE.
(build_primary_vtable): Adjust usage of BINFO_NEW_VTABLE_MARKED.
(build_secondary_vtable): Likewise.
(dfs_finish_vtbls): Likewise.
(dfs_accumulate_vtbl_inits): Likewise.
(accumulate_vtbl_inits): New function.
(finish_vtbls): Make sure that virtual bases come after
non-virtual bases in the vtable group.
(record_base_offsets): Don't save and restore TREE_VIA_VIRTUAL.
(finish_struct_1): Adjust usage of BINFO_NEW_VTABLE_MARKED.
* search.c (struct vbase_info): Move definition.
(marked_new_vtable_p): Adjust usage of BINFO_NEW_VTABLE_MARKED.
(unmarked_new_vtable_p): Likewise.
(dfs_mark_vtable_path): Remove.
(dfs_mark_new_vtable): Remove.
(dfs_unmark_new_vtable): Likewise.
(dfs_clear_search_slot): Likewise.
(dfs_find_vbases):  Adjust usage of BINFO_NEW_VTABLE_MARKED.
(dfs_clear_vbase_slots): Likewise.
(init_vbase_pointers): LIkewise.

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

gcc/cp/ChangeLog
gcc/cp/class.c
gcc/cp/cp-tree.h
gcc/cp/search.c
gcc/testsuite/g++.old-deja/g++.abi/vtable.C [new file with mode: 0644]

index de6a2eb..33d688f 100644 (file)
@@ -1,3 +1,32 @@
+2000-03-22  Mark Mitchell  <mark@codesourcery.com>
+
+       * cp-tree.h (BINFO_FOR_VBASE): Adjust documentation.
+       (CANONICAL_BINFO): New macro.
+       (BINFO_NEW_VTABLE_MARKED): Use it.
+       (SET_BINFO_NEW_VTABLE_MARKED): Likewise.
+       (CLEAR_BINFO_NEW_VTABLE_MARKED): Likewise.
+       * class.c (dfs_build_vbase_offset_vtbl_entries): Use BINFO_TYPE,
+       not TREE_TYPE.
+       (build_primary_vtable): Adjust usage of BINFO_NEW_VTABLE_MARKED.
+       (build_secondary_vtable): Likewise.
+       (dfs_finish_vtbls): Likewise.
+       (dfs_accumulate_vtbl_inits): Likewise.
+       (accumulate_vtbl_inits): New function.
+       (finish_vtbls): Make sure that virtual bases come after
+       non-virtual bases in the vtable group.
+       (record_base_offsets): Don't save and restore TREE_VIA_VIRTUAL.
+       (finish_struct_1): Adjust usage of BINFO_NEW_VTABLE_MARKED.
+       * search.c (struct vbase_info): Move definition.
+       (marked_new_vtable_p): Adjust usage of BINFO_NEW_VTABLE_MARKED.
+       (unmarked_new_vtable_p): Likewise.
+       (dfs_mark_vtable_path): Remove.
+       (dfs_mark_new_vtable): Remove.
+       (dfs_unmark_new_vtable): Likewise.
+       (dfs_clear_search_slot): Likewise.
+       (dfs_find_vbases):  Adjust usage of BINFO_NEW_VTABLE_MARKED.
+       (dfs_clear_vbase_slots): Likewise.
+       (init_vbase_pointers): LIkewise.
+       
 2000-03-22  Jason Merrill  <jason@casey.cygnus.com>
 
        * typeck.c (type_after_usual_arithmetic_conversions): Prefer a
index 12095ad..216d7e3 100644 (file)
@@ -161,6 +161,7 @@ static tree dfs_search_base_offsets PARAMS ((tree, void *));
 static int layout_conflict_p PARAMS ((tree, varray_type));
 static unsigned HOST_WIDE_INT end_of_class PARAMS ((tree, int));
 static void layout_empty_base PARAMS ((tree, tree, varray_type));
+static void accumulate_vtbl_inits PARAMS ((tree, tree));
 
 /* Variables shared between class.c and call.c.  */
 
@@ -276,7 +277,7 @@ dfs_build_vbase_offset_vtbl_entries (binfo, data)
 
       /* Remember the index to the vbase offset for this virtual
         base.  */
-      vbase = BINFO_FOR_VBASE (TREE_TYPE (binfo), TREE_PURPOSE (list));
+      vbase = BINFO_FOR_VBASE (BINFO_TYPE (binfo), TREE_PURPOSE (list));
       if (!TREE_VALUE (list))
        BINFO_VPTR_FIELD (vbase) = build_int_2 (-1, 0);
       else
@@ -1072,7 +1073,7 @@ build_primary_vtable (binfo, type)
     {
       tree offset;
 
-      if (BINFO_NEW_VTABLE_MARKED (binfo))
+      if (BINFO_NEW_VTABLE_MARKED (binfo, type))
        /* We have already created a vtable for this base, so there's
           no need to do it again.  */
        return 0;
@@ -1106,7 +1107,7 @@ build_primary_vtable (binfo, type)
   TYPE_BINFO_VIRTUALS (type) = virtuals;
 
   binfo = TYPE_BINFO (type);
-  SET_BINFO_NEW_VTABLE_MARKED (binfo);
+  SET_BINFO_NEW_VTABLE_MARKED (binfo, type);
   return 1;
 }
 
@@ -1147,14 +1148,14 @@ build_secondary_vtable (binfo, for_type)
                                                  current_class_type),
                        170);
 
-  if (BINFO_NEW_VTABLE_MARKED (binfo))
+  if (BINFO_NEW_VTABLE_MARKED (binfo, current_class_type))
     /* We already created a vtable for this base.  There's no need to
        do it again.  */
     return 0;
 
   /* Remember that we've created a vtable for this BINFO, so that we
      don't try to do so again.  */
-  SET_BINFO_NEW_VTABLE_MARKED (binfo);
+  SET_BINFO_NEW_VTABLE_MARKED (binfo, current_class_type);
   
   /* Make fresh virtual list, so we can smash it later.  */
   BINFO_VIRTUALS (binfo) = copy_list (BINFO_VIRTUALS (binfo));
@@ -2760,13 +2761,15 @@ dfs_finish_vtbls (binfo, data)
      tree binfo;
      void *data;
 {
+  tree t = (tree) data;
+
   if (!BINFO_PRIMARY_MARKED_P (binfo)
       && CLASSTYPE_VFIELDS (BINFO_TYPE (binfo))
-      && BINFO_NEW_VTABLE_MARKED (binfo))
+      && BINFO_NEW_VTABLE_MARKED (binfo, t))
     initialize_vtable (binfo, 
-                      build_vtbl_initializer (binfo, (tree) data));
+                      build_vtbl_initializer (binfo, t));
 
-  CLEAR_BINFO_NEW_VTABLE_MARKED (binfo);
+  CLEAR_BINFO_NEW_VTABLE_MARKED (binfo, t);
   SET_BINFO_MARKED (binfo);
 
   return NULL_TREE;
@@ -2781,15 +2784,16 @@ dfs_accumulate_vtbl_inits (binfo, data)
      tree binfo;
      void *data;
 {
+  tree l;
+  tree t;
+
+  l = (tree) data;
+  t = TREE_PURPOSE (l);
+
   if (!BINFO_PRIMARY_MARKED_P (binfo)
       && CLASSTYPE_VFIELDS (BINFO_TYPE (binfo))
-      && BINFO_NEW_VTABLE_MARKED (binfo))
+      && BINFO_NEW_VTABLE_MARKED (binfo, t))
     {
-      tree l;
-      tree t;
-
-      l = (tree) data;
-      t = TREE_PURPOSE (l);
 
       /* If this is a secondary vtable, record its location.  */
       if (binfo != TYPE_BINFO (t))
@@ -2807,19 +2811,34 @@ dfs_accumulate_vtbl_inits (binfo, data)
                                 size_int (list_length (TREE_VALUE (l)))));
        }
 
-      /* Add the initializers for this vtable to the initailizers for
+      /* Add the initializers for this vtable to the initializers for
         the other vtables we've already got.  */
       TREE_VALUE (l) 
        = chainon (TREE_VALUE (l),
                   build_vtbl_initializer (binfo, t));
     }
 
-  CLEAR_BINFO_NEW_VTABLE_MARKED (binfo);
-  SET_BINFO_MARKED (binfo);
+  CLEAR_BINFO_NEW_VTABLE_MARKED (binfo, t);
 
   return NULL_TREE;
 }
 
+/* Add the vtbl initializers for BINFO (and its non-primary,
+   non-virtual bases) to the list of INITS.  */
+
+static void
+accumulate_vtbl_inits (binfo, inits)
+     tree binfo;
+     tree inits;
+{
+  /* Walk the BINFO and its bases.  */
+  dfs_walk_real (binfo,
+                dfs_accumulate_vtbl_inits,
+                NULL, 
+                dfs_skip_vbases,
+                inits);
+}
+
 /* Create all the necessary vtables for T and its base classes.  */
 
 static void
@@ -2829,26 +2848,31 @@ finish_vtbls (t)
   if (merge_primary_and_secondary_vtables_p ())
     {
       tree list;
+      tree vbase;
 
       /* Under the new ABI, we lay out the primary and secondary
         vtables in one contiguous vtable.  The primary vtable is
-        first, followed by the secondary vtables as encountered in a
-        pre-order depth-first left-to-right traversal.  */
+        first, followed by the non-virtual secondary vtables in
+        inheritance graph order.  */
       list = build_tree_list (t, NULL_TREE);
-      dfs_walk_real (TYPE_BINFO (t), 
-                    dfs_accumulate_vtbl_inits,
-                    NULL, 
-                    dfs_unmarked_real_bases_queue_p, 
-                    list);
+      accumulate_vtbl_inits (TYPE_BINFO (t), list);
+      /* Then come the virtual bases, also in inheritance graph
+        order.  */
+      for (vbase = CLASSTYPE_VBASECLASSES (t);
+          vbase;
+          vbase = TREE_CHAIN (vbase))
+       accumulate_vtbl_inits (vbase, list);
+
       if (TYPE_BINFO_VTABLE (t))
        initialize_vtable (TYPE_BINFO (t), TREE_VALUE (list));
     }
   else
-    dfs_walk (TYPE_BINFO (t), dfs_finish_vtbls, 
-             dfs_unmarked_real_bases_queue_p, t);
-
-  dfs_walk (TYPE_BINFO (t), dfs_unmark, 
-           dfs_marked_real_bases_queue_p, t);
+    {
+      dfs_walk (TYPE_BINFO (t), dfs_finish_vtbls, 
+               dfs_unmarked_real_bases_queue_p, t);
+      dfs_walk (TYPE_BINFO (t), dfs_unmark, 
+               dfs_marked_real_bases_queue_p, t);
+    }
 }
 
 /* True if we should override the given BASE_FNDECL with the given
@@ -4142,17 +4166,10 @@ record_base_offsets (binfo, base_offsets)
      tree binfo;
      varray_type *base_offsets;
 {
-  int virtual_p;
-
-  /* If BINFO is virtual, we still want to mention its offset in
-     BASE_OFFSETS.  */
-  virtual_p = TREE_VIA_VIRTUAL (binfo);
-  TREE_VIA_VIRTUAL (binfo) = 0;
   dfs_walk (binfo,
            dfs_record_base_offsets,
            dfs_skip_vbases,
            base_offsets);
-  TREE_VIA_VIRTUAL (binfo) = virtual_p;
 }
 
 /* Returns non-NULL if there is already an entry in DATA (which is
@@ -5308,7 +5325,7 @@ finish_struct_1 (t)
            }
          build_primary_vtable (NULL_TREE, t);
        }
-      else if (! BINFO_NEW_VTABLE_MARKED (TYPE_BINFO (t)))
+      else if (! BINFO_NEW_VTABLE_MARKED (TYPE_BINFO (t), t))
        /* Here we know enough to change the type of our virtual
           function table, but we will wait until later this function.  */
        build_primary_vtable (CLASSTYPE_PRIMARY_BINFO (t), t);
index 04fd943..9ccd28a 100644 (file)
@@ -1566,10 +1566,19 @@ struct lang_type
    (also distinct from the copies in the TYPE_BINFO hierarchy.)  */
 #define CLASSTYPE_VBASECLASSES(NODE) (TYPE_LANG_SPECIFIC(NODE)->vbases)
 
-/* The BINFO (if any) for the virtual baseclass T of the class C.  */
+/* The BINFO (if any) for the virtual baseclass T of the class C from
+   the CLASSTYPE_VBASECLASSES list.  */
 #define BINFO_FOR_VBASE(T, C) \
   (binfo_member (T, CLASSTYPE_VBASECLASSES (C)))
 
+/* For a non-virtual BINFO, the BINFO itself; for a virtual BINFO, the
+   BINFO_FOR_VBASE.  C is the most derived class for the hierarchy
+   containing BINFO.  */
+#define CANONICAL_BINFO(BINFO, C)              \
+  (TREE_VIA_VIRTUAL (BINFO)                    \
+   ? BINFO_FOR_VBASE (BINFO_TYPE (BINFO), C)   \
+   : BINFO)
+
 /* Number of direct baseclasses of NODE.  */
 #define CLASSTYPE_N_BASECLASSES(NODE) \
   (BINFO_N_BASETYPES (TYPE_BINFO (NODE)))
@@ -1704,11 +1713,14 @@ struct lang_type
 #define SET_BINFO_VTABLE_PATH_MARKED(NODE) (TREE_VIA_VIRTUAL(NODE)?SET_CLASSTYPE_MARKED3(BINFO_TYPE(NODE)):(TREE_LANG_FLAG_3(NODE)=1))
 #define CLEAR_BINFO_VTABLE_PATH_MARKED(NODE) (TREE_VIA_VIRTUAL(NODE)?CLEAR_CLASSTYPE_MARKED3(BINFO_TYPE(NODE)):(TREE_LANG_FLAG_3(NODE)=0))
 
-/* Nonzero means that this class has a new vtable.  */
-#define BINFO_NEW_VTABLE_MARKED(NODE) \
-  (TREE_VIA_VIRTUAL(NODE)?CLASSTYPE_MARKED4(BINFO_TYPE(NODE)):TREE_LANG_FLAG_4(NODE))
-#define SET_BINFO_NEW_VTABLE_MARKED(NODE) (TREE_VIA_VIRTUAL(NODE)?SET_CLASSTYPE_MARKED4(BINFO_TYPE(NODE)):(TREE_LANG_FLAG_4(NODE)=1))
-#define CLEAR_BINFO_NEW_VTABLE_MARKED(NODE) (TREE_VIA_VIRTUAL(NODE)?CLEAR_CLASSTYPE_MARKED4(BINFO_TYPE(NODE)):(TREE_LANG_FLAG_4(NODE)=0))
+/* Nonzero means B (a BINFO) needs a new vtable.  B is part of the
+   hierarchy dominated by C.  */
+#define BINFO_NEW_VTABLE_MARKED(B, C) \
+  (TREE_LANG_FLAG_4 (CANONICAL_BINFO (B, C)))
+#define SET_BINFO_NEW_VTABLE_MARKED(B, C) \
+  (BINFO_NEW_VTABLE_MARKED (B, C) = 1)
+#define CLEAR_BINFO_NEW_VTABLE_MARKED(B, C) \
+  (BINFO_NEW_VTABLE_MARKED (B, C) = 0)
 
 /* Nonzero means this class has done dfs_pushdecls.  */
 #define BINFO_PUSHDECLS_MARKED(NODE) BINFO_VTABLE_PATH_MARKED (NODE)
index 9d75476..314dab9 100644 (file)
@@ -76,6 +76,15 @@ pop_stack_level (stack)
 #define search_level stack_level
 static struct search_level *search_stack;
 
+struct vbase_info 
+{
+  /* The class dominating the hierarchy.  */
+  tree type;
+  tree decl_ptr;
+  tree inits;
+  tree vbase_types;
+};
+
 static tree next_baselink PARAMS ((tree));
 static tree get_vbase_1 PARAMS ((tree, tree, unsigned int *));
 static tree lookup_field_1 PARAMS ((tree, tree));
@@ -2537,17 +2546,21 @@ unmarked_vtable_pathp (binfo, data)
 static tree 
 marked_new_vtablep (binfo, data) 
      tree binfo;
-     void *data ATTRIBUTE_UNUSED;
+     void *data;
 {
-  return BINFO_NEW_VTABLE_MARKED (binfo) ? binfo : NULL_TREE; 
+  struct vbase_info *vi = (struct vbase_info *) data;
+
+  return BINFO_NEW_VTABLE_MARKED (binfo, vi->type) ? binfo : NULL_TREE; 
 }
 
 static tree
 unmarked_new_vtablep (binfo, data) 
      tree binfo;
-     void *data ATTRIBUTE_UNUSED;
+     void *data;
 { 
-  return !BINFO_NEW_VTABLE_MARKED (binfo) ? binfo : NULL_TREE; 
+  struct vbase_info *vi = (struct vbase_info *) data;
+
+  return !BINFO_NEW_VTABLE_MARKED (binfo, vi->type) ? binfo : NULL_TREE; 
 }
 
 static tree
@@ -2614,31 +2627,7 @@ dfs_vtable_path_unmark (binfo, data)
   return NULL_TREE;
 }
 
-#if 0
-static void
-dfs_mark_vtable_path (binfo) tree binfo;
-{ SET_BINFO_VTABLE_PATH_MARKED (binfo); }
-
-static void
-dfs_mark_new_vtable (binfo) tree binfo;
-{ SET_BINFO_NEW_VTABLE_MARKED (binfo); }
-
-static void
-dfs_unmark_new_vtable (binfo) tree binfo;
-{ CLEAR_BINFO_NEW_VTABLE_MARKED (binfo); }
-
-static void
-dfs_clear_search_slot (binfo) tree binfo;
-{ CLASSTYPE_SEARCH_SLOT (BINFO_TYPE (binfo)) = 0; }
-#endif
 \f
-struct vbase_info 
-{
-  tree decl_ptr;
-  tree inits;
-  tree vbase_types;
-};
-
 /*  Attach to the type of the virtual base class, the pointer to the
     virtual base class.  */
 
@@ -2668,7 +2657,7 @@ dfs_find_vbases (binfo, data)
        }
     }
   SET_BINFO_VTABLE_PATH_MARKED (binfo);
-  SET_BINFO_NEW_VTABLE_MARKED (binfo);
+  SET_BINFO_NEW_VTABLE_MARKED (binfo, vi->type);
 
   return NULL_TREE;
 }
@@ -2737,12 +2726,14 @@ dfs_init_vbase_pointers (binfo, data)
 static tree
 dfs_clear_vbase_slots (binfo, data)
      tree binfo;
-     void *data ATTRIBUTE_UNUSED;
+     void *data;
 {
   tree type = BINFO_TYPE (binfo);
+  struct vbase_info *vi = (struct vbase_info *) data;
+
   CLASSTYPE_SEARCH_SLOT (type) = 0;
   CLEAR_BINFO_VTABLE_PATH_MARKED (binfo);
-  CLEAR_BINFO_NEW_VTABLE_MARKED (binfo);
+  CLEAR_BINFO_NEW_VTABLE_MARKED (binfo, vi->type);
   return NULL_TREE;
 }
 
@@ -2760,6 +2751,7 @@ init_vbase_pointers (type, decl_ptr)
 
       /* Find all the virtual base classes, marking them for later
         initialization.  */
+      vi.type = type;
       vi.decl_ptr = decl_ptr;
       vi.vbase_types = CLASSTYPE_VBASECLASSES (type);
       vi.inits = NULL_TREE;
@@ -2773,7 +2765,7 @@ init_vbase_pointers (type, decl_ptr)
                     marked_vtable_pathp,
                     &vi);
 
-      dfs_walk (binfo, dfs_clear_vbase_slots, marked_new_vtablep, 0);
+      dfs_walk (binfo, dfs_clear_vbase_slots, marked_new_vtablep, &vi);
       flag_this_is_variable = old_flag;
       return vi.inits;
     }
@@ -3088,12 +3080,13 @@ expand_indirect_vtbls_init (binfo, decl_ptr)
     {
       tree vbases = CLASSTYPE_VBASECLASSES (type);
       struct vbase_info vi;
+      vi.type = type;
       vi.decl_ptr = decl_ptr;
       vi.vbase_types = vbases;
 
       dfs_walk (binfo, dfs_find_vbases, unmarked_new_vtablep, &vi);
       fixup_all_virtual_upcast_offsets (type, vi.decl_ptr);
-      dfs_walk (binfo, dfs_clear_vbase_slots, marked_new_vtablep, 0);
+      dfs_walk (binfo, dfs_clear_vbase_slots, marked_new_vtablep, &vi);
     }
 }
 
diff --git a/gcc/testsuite/g++.old-deja/g++.abi/vtable.C b/gcc/testsuite/g++.old-deja/g++.abi/vtable.C
new file mode 100644 (file)
index 0000000..aafcad8
--- /dev/null
@@ -0,0 +1,82 @@
+// Test various aspects of vtable layout.
+// Special g++ Options: -fno-strict-aliasing
+// Origin: Mark Mitchell <mark@codesourcery.com>
+
+#if defined (__GXX_ABI_VERSION) && __GXX_ABI_VERSION >= 100
+
+struct S0
+{
+  virtual void h ()
+  {
+  }
+
+  int k;
+};
+
+
+struct S1 
+{
+  virtual void f () 
+  {
+  }
+
+  int i;
+};
+
+struct S2 : virtual public S0
+{
+  virtual void g ()
+  {
+  }
+
+  int j;
+};
+
+struct S3 
+{
+  virtual void k () 
+  {
+  }
+
+  int l;
+};
+
+struct S4 : public virtual S1, public S2, public S3
+{
+};
+
+inline void* vtable (void *object)
+{
+  // The vptr is always the first part of the object.
+  return * (void **) object;
+}
+
+int main ()
+{
+  // The vtable layout order for S4 should consist of S4's primary
+  // vtable (shared with S2), followed by the vtable for S3 (because
+  // it is a non-virtual base).  Then, these should be followed by the
+  // the vtables for S1 and S0, which are virtual.
+  S4 s4;
+  S0 *s0 = &s4;
+  S1 *s1 = &s4;
+  S2 *s2 = &s4;
+  S3 *s3 = &s4;
+  
+  if (vtable (&s4) != vtable (s2))
+    return 1;
+    if (vtable (s2) >= vtable (s3))
+    return 2;
+  if (vtable (s3) >= vtable (s1))
+    return 3;
+  if (vtable (s1) >= vtable (s0))
+    return 4;
+}
+
+#else /* !(defined (__GXX_ABI_VERSION) && __GXX_ABI_VERSION >= 100) */
+
+int main () 
+{
+}
+
+#endif /* !(defined (__GXX_ABI_VERSION) && __GXX_ABI_VERSION >= 100) */