cp-tree.h (flag_new_abi): Move.
authorMark Mitchell <mark@codesourcery.com>
Mon, 17 Jan 2000 04:08:01 +0000 (04:08 +0000)
committerMark Mitchell <mmitchel@gcc.gnu.org>
Mon, 17 Jan 2000 04:08:01 +0000 (04:08 +0000)
* cp-tree.h (flag_new_abi): Move.
(flag_use_cxa_atexit): Likewise.
(flag_honor_std): Likewise.
(flag_rtti): Likewise.
(vbase_offsets_in_vtable_p): Define.
(vptrs_present_everywhere_p): Likewise.
(TYPE_CONTAINS_VPTR_P): Likewise.
(dfs_walk_real): Declare.
* class.c (build_vbase_pointer_fields): Check
vbase_offsets_in_vtable_p.
(dfs_build_vbase_offset_vtbl_entries): Record the vbase indices in
BINFO_VPTR_FIELD.
(build_vbase_offset_vtbl_entries): Simplify.
(build_vbase_offset_vtbl_entries): Adjust.
(build_vbase_pointer): Add ability to look up vbase offsets in
vtable.
(start_vtable): New function.
(add_virtual_function): Use it.
(determine_primary_base): Use TYPE_CONTAINS_VPTR_P.
(num_extra_vtbl_entries): Use vbase_offsets_in_vtable_p.
(build_vtbl_initializer): Take the type of the complete object as
input.  Use it to correctly calculate vbase offsets.
(dfs_finish_vtbls): Pass the complete type to
build_vtbl_initializer.
(check_bases_and_members): Use TYPE_CONTAINS_VPTR_P.
(create_vtable_ptr): Create a vtable even if there are no
new virtual functions, under the new ABI.
(finish_struct_1): Likewise.
(get_vfield_name): Use TYPE_CONTAINS_VPTR_P.
* decl.c (exapnd_static_init): Remove call to
preserve_initializer.
* decl2.c (mark_vtable_entries): Tweak to handle vbase offsets in
vtables.
* init.c (initialize_vtbl_ptrs): Initialize them in pre-order.
(expand_virtual_init): Use vbase_offsets_in_vtable_p.
(construct_virtual_bases): Don't initialize virtual base pointers
under the new ABI.
(build_aggr_init): Clean up comment.
(expand_aggr_init_1): Likewise.
* rtti.c (expand_class_desc): Store the virtual function table
index where the vbase offset lives in the offset field.
* search.c (dfs_walk_real): Make it global.
(dfs_debug_mark): Use TYPE_CONTAINS_VPTR_P.
* tree.c (make_binfo): Don't clear BINFO_VPTR_FIELD.

* tinfo.h (USItype): Make it signed under the new ABI.
* tinfo.cc (convert_to_base): New function.  Encapsulate base
conversion logic here.
(__class_type_info::do_upcast): Use it.
(__class_type_info::do_dyncast): Likewise.
(__class_type_info::do_find_public_subobj): Likewise.

From-SVN: r31452

gcc/cp/ChangeLog
gcc/cp/class.c
gcc/cp/cp-tree.h
gcc/cp/decl.c
gcc/cp/decl2.c
gcc/cp/init.c
gcc/cp/rtti.c
gcc/cp/search.c
gcc/cp/tinfo.cc
gcc/cp/tinfo.h
gcc/cp/tree.c

index a8d7922bc6c1d6bf17d7c0fe03589ab676592bb3..f8f2bdf285d78f14f542c25d65b57cf0e80e3abc 100644 (file)
@@ -1,5 +1,57 @@
 2000-01-16  Mark Mitchell  <mark@codesourcery.com>
 
+       * cp-tree.h (flag_new_abi): Move.
+       (flag_use_cxa_atexit): Likewise.
+       (flag_honor_std): Likewise.
+       (flag_rtti): Likewise.
+       (vbase_offsets_in_vtable_p): Define.
+       (vptrs_present_everywhere_p): Likewise.
+       (TYPE_CONTAINS_VPTR_P): Likewise.
+       (dfs_walk_real): Declare.
+       * class.c (build_vbase_pointer_fields): Check
+       vbase_offsets_in_vtable_p.
+       (dfs_build_vbase_offset_vtbl_entries): Record the vbase indices in
+       BINFO_VPTR_FIELD.
+       (build_vbase_offset_vtbl_entries): Simplify.
+       (build_vbase_offset_vtbl_entries): Adjust.
+       (build_vbase_pointer): Add ability to look up vbase offsets in
+       vtable. 
+       (start_vtable): New function.
+       (add_virtual_function): Use it.
+       (determine_primary_base): Use TYPE_CONTAINS_VPTR_P.
+       (num_extra_vtbl_entries): Use vbase_offsets_in_vtable_p.
+       (build_vtbl_initializer): Take the type of the complete object as
+       input.  Use it to correctly calculate vbase offsets.
+       (dfs_finish_vtbls): Pass the complete type to
+       build_vtbl_initializer.
+       (check_bases_and_members): Use TYPE_CONTAINS_VPTR_P.
+       (create_vtable_ptr): Create a vtable even if there are no
+       new virtual functions, under the new ABI.
+       (finish_struct_1): Likewise.
+       (get_vfield_name): Use TYPE_CONTAINS_VPTR_P.
+       * decl.c (exapnd_static_init): Remove call to
+       preserve_initializer.
+       * decl2.c (mark_vtable_entries): Tweak to handle vbase offsets in
+       vtables.
+       * init.c (initialize_vtbl_ptrs): Initialize them in pre-order.
+       (expand_virtual_init): Use vbase_offsets_in_vtable_p.
+       (construct_virtual_bases): Don't initialize virtual base pointers
+       under the new ABI.
+       (build_aggr_init): Clean up comment.
+       (expand_aggr_init_1): Likewise.
+       * rtti.c (expand_class_desc): Store the virtual function table
+       index where the vbase offset lives in the offset field.
+       * search.c (dfs_walk_real): Make it global.
+       (dfs_debug_mark): Use TYPE_CONTAINS_VPTR_P.
+       * tree.c (make_binfo): Don't clear BINFO_VPTR_FIELD.
+       
+       * tinfo.h (USItype): Make it signed under the new ABI.
+       * tinfo.cc (convert_to_base): New function.  Encapsulate base
+       conversion logic here.
+       (__class_type_info::do_upcast): Use it.
+       (__class_type_info::do_dyncast): Likewise.
+       (__class_type_info::do_find_public_subobj): Likewise.
+       
        * init.c (construct_virtual_bases): Don't look up the addresses of
        virtual bases at run-time.
 
index a557292757d307b5bae8f2954e157437ed30c14f..8c1073e64bf4fa6dd0fb1fdc158a6e28a878d3cf 100644 (file)
@@ -115,7 +115,7 @@ static tree resolve_address_of_overloaded_function PROTO((tree, tree, int,
                                                          int, tree));
 static void build_vtable_entry_ref PROTO((tree, tree, tree));
 static tree build_vtable_entry_for_fn PROTO((tree, tree));
-static tree build_vtbl_initializer PROTO((tree));
+static tree build_vtbl_initializer PROTO((tree, tree));
 static int count_fields PROTO((tree));
 static int add_fields_to_vec PROTO((tree, tree, int));
 static void check_bitfield_decl PROTO((tree));
@@ -145,7 +145,8 @@ static void remove_base_fields PROTO((tree));
 static tree dfs_set_offset_for_shared_vbases PROTO((tree, void *));
 static tree dfs_set_offset_for_unshared_vbases PROTO((tree, void *));
 static tree dfs_build_vbase_offset_vtbl_entries PROTO((tree, void *));
-static tree build_vbase_offset_vtbl_entries PROTO((tree));
+static tree build_vbase_offset_vtbl_entries PROTO((tree, tree));
+static void start_vtable PROTO((tree, int *));
 
 /* Variables shared between class.c and call.c.  */
 
@@ -178,9 +179,12 @@ build_vbase_pointer_fields (rec, empty_p)
   tree decl;
   int i;
 
-  /* Handle basetypes almost like fields, but record their
-     offsets differently.  */
+  /* Under the new ABI, there are no vbase pointers in the object.
+     Instead, the offsets are stored in the vtable.  */
+  if (vbase_offsets_in_vtable_p ())
+    return NULL_TREE;
 
+  /* Loop over the baseclasses, adding vbase pointers as needed.  */
   for (i = 0; i < n_baseclasses; i++)
     {
       register tree base_binfo = TREE_VEC_ELT (binfos, i);
@@ -251,10 +255,27 @@ dfs_build_vbase_offset_vtbl_entries (binfo, data)
   else if (TREE_VIA_VIRTUAL (binfo))
     {
       tree init;
+      tree vbase;
+
+      /* Remember the index to the vbase offset for this virtual
+        base.  */
+      vbase = BINFO_FOR_VBASE (TREE_TYPE (binfo), TREE_PURPOSE (list));
+      if (!TREE_VALUE (list))
+       BINFO_VPTR_FIELD (vbase) = build_int_2 (-1, 0);
+      else
+       {
+         BINFO_VPTR_FIELD (vbase) = TREE_PURPOSE (TREE_VALUE (list));
+         BINFO_VPTR_FIELD (vbase) = ssize_binop (MINUS_EXPR,
+                                                 BINFO_VPTR_FIELD (vbase),
+                                                 integer_one_node);
+       }
 
+      /* And record the offset at which this virtual base lies in the
+        vtable.  */
       init = BINFO_OFFSET (binfo);
-      init = build1 (NOP_EXPR, vtable_entry_type, init);
-      TREE_VALUE (list) = tree_cons (NULL_TREE, init, TREE_VALUE (list));
+      TREE_VALUE (list) = tree_cons (BINFO_VPTR_FIELD (vbase),
+                                    init, 
+                                    TREE_VALUE (list));
     }
 
   SET_BINFO_VTABLE_PATH_MARKED (binfo);
@@ -262,69 +283,46 @@ dfs_build_vbase_offset_vtbl_entries (binfo, data)
   return NULL_TREE;
 }
 
-/* Returns the initializers for the vbase offset entries in the
-   vtable, in reverse order.  */
+/* Returns the initializers for the vbase offset entries in the vtable
+   for BINFO (which is part of the class hierarchy dominated by T), in
+   reverse order.  */
 
 static tree
-build_vbase_offset_vtbl_entries (binfo)
+build_vbase_offset_vtbl_entries (binfo, t)
      tree binfo;
+     tree t;
 {
-  tree type;
   tree inits;
   tree init;
+  tree list;
 
   /* Under the old ABI, pointers to virtual bases are stored in each
      object.  */
-  if (!flag_new_abi)
+  if (!vbase_offsets_in_vtable_p ())
     return NULL_TREE;
 
   /* If there are no virtual baseclasses, then there is nothing to
      do.  */
-  type = BINFO_TYPE (binfo);
-  if (!TYPE_USES_VIRTUAL_BASECLASSES (type))
+  if (!TYPE_USES_VIRTUAL_BASECLASSES (BINFO_TYPE (binfo)))
     return NULL_TREE;
 
   inits = NULL_TREE;
 
-  /* Under the new ABI, the vtable contains offsets to all virtual
-     bases.  The ABI specifies different layouts depending on whether
-     or not *all* of the bases of this type are virtual.  */
-  if (CLASSTYPE_N_BASECLASSES (type) 
-      == list_length (CLASSTYPE_VBASECLASSES (type)))
-    {
-      /* In this case, the offsets are allocated from right to left of
-        the declaration order in which the virtual bases appear.  */
-      int i;
-
-      for (i = 0; i < BINFO_N_BASETYPES (binfo); ++i)
-       {
-         tree vbase = BINFO_BASETYPE (binfo, i);
-         init = BINFO_OFFSET (vbase);
-         init = build1 (NOP_EXPR, vtable_entry_type, init);
-         inits = tree_cons (NULL_TREE, init, inits);
-       }
-    }
-  else
-    {
-      tree list;
-
-      /* While in this case, the offsets are allocated in the reverse
-        order of a depth-first left-to-right traversal of the
-        hierarchy.  We use BINFO_VTABLE_PATH_MARKED because we are
-        ourselves during a dfs_walk, and so BINFO_MARKED is already
-        in use.  */
-      list = build_tree_list (type, NULL_TREE);
-      TREE_TYPE (list) = binfo;
-      dfs_walk (binfo,
-               dfs_build_vbase_offset_vtbl_entries,
-               dfs_vtable_path_unmarked_real_bases_queue_p,
-               list);
-      dfs_walk (binfo,
-               dfs_vtable_path_unmark,
-               dfs_vtable_path_marked_real_bases_queue_p,
-               list);
-      inits = nreverse (TREE_VALUE (list));
-    }
+  /* The offsets are allocated in the reverse order of a
+     depth-first left-to-right traversal of the hierarchy.  We use
+     BINFO_VTABLE_PATH_MARKED because we are ourselves during a
+     dfs_walk, and so BINFO_MARKED is already in use.  */
+  list = build_tree_list (t, NULL_TREE);
+  TREE_TYPE (list) = binfo;
+  dfs_walk (binfo,
+           dfs_build_vbase_offset_vtbl_entries,
+           dfs_vtable_path_unmarked_real_bases_queue_p,
+           list);
+  dfs_walk (binfo,
+           dfs_vtable_path_unmark,
+           dfs_vtable_path_marked_real_bases_queue_p,
+           list);
+  inits = nreverse (TREE_VALUE (list));
 
   /* We've now got offsets in the right oder.  However, the offsets
      we've stored are offsets from the beginning of the complete
@@ -334,9 +332,13 @@ build_vbase_offset_vtbl_entries (binfo)
       tree exp = TREE_VALUE (init);
 
       exp = ssize_binop (MINUS_EXPR, exp, BINFO_OFFSET (binfo));
-      exp = build1 (NOP_EXPR, vtable_entry_type, TREE_VALUE (init));
+      exp = build1 (NOP_EXPR, vtable_entry_type, exp);
       exp = fold (exp);
       TREE_CONSTANT (exp) = 1;
+      /* The dfs_build_vbase_offset_vtbl_entries routine uses the
+        TREE_PURPOSE to scribble in.  But, we need to clear it now so
+        that the values are not perceived as labeled initializers.  */
+      TREE_PURPOSE (init) = NULL_TREE;
       TREE_VALUE (init) = exp;
     }
 
@@ -344,16 +346,41 @@ build_vbase_offset_vtbl_entries (binfo)
 }
 
 /* Returns a pointer to the virtual base class of EXP that has the
-   indicated TYPE.  */
+   indicated TYPE.  EXP is of class type, not a pointer type.  */
 
 static tree
 build_vbase_pointer (exp, type)
      tree exp, type;
 {
-  char *name;
-  FORMAT_VBASE_NAME (name, type);
-
-  return build_component_ref (exp, get_identifier (name), NULL_TREE, 0);
+  if (vbase_offsets_in_vtable_p ())
+    {
+      tree vbase;
+      tree vbase_ptr;
+
+      /* Find the shared copy of TYPE; that's where the vtable offset
+        is recorded.  */
+      vbase = BINFO_FOR_VBASE (type, TREE_TYPE (exp));
+      /* Find the virtual function table pointer.  */
+      vbase_ptr = build_vfield_ref (exp, TREE_TYPE (exp));
+      /* Compute the location where the offset will lie.  */
+      vbase_ptr = build_binary_op (PLUS_EXPR, 
+                                  vbase_ptr,
+                                  BINFO_VPTR_FIELD (vbase));
+      vbase_ptr = build1 (NOP_EXPR, 
+                         build_pointer_type (ptrdiff_type_node),
+                         vbase_ptr);
+      /* Add the contents of this location to EXP.  */
+      return build (PLUS_EXPR,
+                   build_pointer_type (type),
+                   build_unary_op (ADDR_EXPR, exp, /*noconvert=*/0),
+                   build1 (INDIRECT_REF, ptrdiff_type_node, vbase_ptr));
+    }
+  else
+    {
+      char *name;
+      FORMAT_VBASE_NAME (name, type);
+      return build_component_ref (exp, get_identifier (name), NULL_TREE, 0);
+    }
 }
 
 /* Build multi-level access to EXPR using hierarchy path PATH.
@@ -1100,6 +1127,25 @@ get_vtable_entry_n (virtuals, n)
   return virtuals;
 }
 
+/* Call this function whenever its known that a vtable for T is going
+   to be needed.  It's safe to call it more than once.  *HAS_VIRTUAL_P
+   is initialized to the number of slots that are reserved at the
+   beginning of the vtable for RTTI information.  */
+
+static void
+start_vtable (t, has_virtual_p)
+     tree t;
+     int *has_virtual_p;
+{
+  if (*has_virtual_p == 0 && ! CLASSTYPE_COM_INTERFACE (t))
+    {
+      if (flag_vtable_thunks)
+       *has_virtual_p = 2;
+      else
+       *has_virtual_p = 1;
+    }
+}
+
 /* Add a virtual function to all the appropriate vtables for the class
    T.  DECL_VINDEX(X) should be error_mark_node, if we want to
    allocate a new slot in our table.  If it is error_mark_node, we
@@ -1139,13 +1185,7 @@ add_virtual_function (pv, phv, has_virtual, fndecl, t)
       /* If we are using thunks, use two slots at the front, one
         for the offset pointer, one for the tdesc pointer.
          For ARM-style vtables, use the same slot for both.  */
-      if (*has_virtual == 0 && ! CLASSTYPE_COM_INTERFACE (t))
-       {
-         if (flag_vtable_thunks)
-           *has_virtual = 2;
-         else
-           *has_virtual = 1;
-       }
+      start_vtable (t, has_virtual);
 
       /* Build a new INT_CST for this DECL_VINDEX.  */
       {
@@ -1767,7 +1807,7 @@ determine_primary_base (t, has_virtual_p)
       tree base_binfo = TREE_VEC_ELT (TYPE_BINFO_BASETYPES (t), i);
       tree basetype = BINFO_TYPE (base_binfo);
 
-      if (TYPE_POLYMORPHIC_P (basetype))
+      if (TYPE_CONTAINS_VPTR_P (basetype))
        {
          /* Even a virtual baseclass can contain our RTTI
             information.  But, we prefer a non-virtual polymorphic
@@ -2287,9 +2327,8 @@ num_extra_vtbl_entries (binfo)
   tree type;
   int entries;
 
-
   /* Under the old ABI, there are no entries at negative offsets.  */
-  if (!flag_new_abi)
+  if (!vbase_offsets_in_vtable_p ())
     return size_zero_node;
 
   type = BINFO_TYPE (binfo);
@@ -2317,18 +2356,20 @@ size_extra_vtbl_entries (binfo)
   return fold (offset);
 }
 
-/* Construct the initializer for BINFOs virtual function table.  */
+/* Construct the initializer for BINFOs virtual function table.  BINFO
+   is part of the hierarchy dominated by T.  */
 
 static tree
-build_vtbl_initializer (binfo)
+build_vtbl_initializer (binfo, t)
      tree binfo;
+     tree t;
 {
   tree v = BINFO_VIRTUALS (binfo);
   tree inits = NULL_TREE;
   tree type = BINFO_TYPE (binfo);
 
   /* Add entries to the vtable for offsets to our virtual bases.  */
-  inits = build_vbase_offset_vtbl_entries (binfo);
+  inits = build_vbase_offset_vtbl_entries (binfo, t);
 
   /* Process the RTTI stuff at the head of the list.  If we're not
      using vtable thunks, then the RTTI entry is just an ordinary
@@ -2397,7 +2438,7 @@ build_vtbl_initializer (binfo)
 static tree
 dfs_finish_vtbls (binfo, data)
      tree binfo;
-     void *data ATTRIBUTE_UNUSED;
+     void *data;
 {
   if (!BINFO_PRIMARY_MARKED_P (binfo)
       && CLASSTYPE_VFIELDS (BINFO_TYPE (binfo))
@@ -2409,7 +2450,7 @@ dfs_finish_vtbls (binfo, data)
       decl = BINFO_VTABLE (binfo);
       context = DECL_CONTEXT (decl);
       DECL_CONTEXT (decl) = 0;
-      DECL_INITIAL (decl) = build_vtbl_initializer (binfo);
+      DECL_INITIAL (decl) = build_vtbl_initializer (binfo, (tree) data);
       cp_finish_decl (decl, DECL_INITIAL (decl), NULL_TREE, 0);
       DECL_CONTEXT (decl) = context;
     }
@@ -4112,9 +4153,9 @@ check_bases_and_members (t, empty_p)
   /* Check all the method declarations.  */
   check_methods (t);
 
-  /* A nearly-empty class has to be polymorphic; a nearly empty class
-     contains a vptr.  */
-  if (!TYPE_POLYMORPHIC_P (t))
+  /* A nearly-empty class has to be vptr-containing; a nearly empty
+     class contains just a vptr.  */
+  if (!TYPE_CONTAINS_VPTR_P (t))
     CLASSTYPE_NEARLY_EMPTY_P (t) = 0;
 
   /* Do some bookkeeping that will guide the generation of implicitly
@@ -4177,6 +4218,12 @@ create_vtable_ptr (t, empty_p, has_virtual_p,
       add_virtual_function (pending_virtuals_p, pending_hard_virtuals_p,
                            has_virtual_p, fn, t);
 
+  /* Even if there weren't any new virtual functions, we might need a
+     new virtual function table if we're supposed to include vptrs in
+     all classes that need them.  */
+  if (TYPE_CONTAINS_VPTR_P (t) && vptrs_present_everywhere_p ())
+    start_vtable (t, has_virtual_p);
+    
   /* If we couldn't find an appropriate base class, create a new field
      here.  */
   if (*has_virtual_p && !TYPE_VFIELD (t))
@@ -4771,7 +4818,7 @@ finish_struct_1 (t)
       TYPE_VFIELD (t) = vfield;
     }
 
-  if (flag_rtti && TYPE_POLYMORPHIC_P (t) && !pending_hard_virtuals)
+  if (flag_rtti && TYPE_CONTAINS_VPTR_P (t) && !pending_hard_virtuals)
     modify_all_vtables (t, NULL_TREE);
 
   for (pending_hard_virtuals = nreverse (pending_hard_virtuals);
@@ -4802,9 +4849,9 @@ finish_struct_1 (t)
        }
     }
 
-  /* Under our model of GC, every C++ class gets its own virtual
-     function table, at least virtually.  */
-  if (pending_virtuals)
+  /* If necessary, create the vtable for this class.  */
+  if (pending_virtuals
+      || (TYPE_CONTAINS_VPTR_P (t) && vptrs_present_everywhere_p ()))
     {
       pending_virtuals = nreverse (pending_virtuals);
       /* We must enter these virtuals into the table.  */
@@ -4836,6 +4883,8 @@ finish_struct_1 (t)
 
       CLASSTYPE_NEEDS_VIRTUAL_REINIT (t) = 1;
     }
+  /* If we didn't need a new vtable, see if we should copy one from
+     the base.  */
   else if (CLASSTYPE_HAS_PRIMARY_BASE_P (t))
     {
       tree binfo = CLASSTYPE_PRIMARY_BINFO (t);
@@ -4855,7 +4904,7 @@ finish_struct_1 (t)
        CLASSTYPE_NEEDS_VIRTUAL_REINIT (t) = 1;
     }
 
-  if (TYPE_POLYMORPHIC_P (t))
+  if (TYPE_CONTAINS_VPTR_P (t))
     {
       CLASSTYPE_VSIZE (t) = has_virtual;
       if (CLASSTYPE_HAS_PRIMARY_BASE_P (t))
@@ -6004,7 +6053,7 @@ get_vfield_name (type)
   char *buf;
 
   while (BINFO_BASETYPES (binfo)
-        && TYPE_POLYMORPHIC_P (BINFO_TYPE (BINFO_BASETYPE (binfo, 0)))
+        && TYPE_CONTAINS_VPTR_P (BINFO_TYPE (BINFO_BASETYPE (binfo, 0)))
         && ! TREE_VIA_VIRTUAL (BINFO_BASETYPE (binfo, 0)))
     binfo = BINFO_BASETYPE (binfo, 0);
 
index 2101cae0a5f331d6c5c0671f3ad68ca127a7326c..b171b1fdf57607b315aadc8011a63be926271854 100644 (file)
@@ -177,7 +177,44 @@ Boston, MA 02111-1307, USA.  */
 #define RECORD_OR_UNION_TYPE_CHECK(NODE)       NODE
 
 #endif
+\f
+/* ABI control.  */
+
+/* Nonzero to enable experimental ABI changes.  */
+
+extern int flag_new_abi;
+
+/* Nonzero to use __cxa_atexit, rather than atexit, to register
+   destructors for local statics and global objects.  */
+
+extern int flag_use_cxa_atexit;
+
+/* Nonzero to not ignore namespace std. */
 
+extern int flag_honor_std;
+
+/* Nonzero means generate 'rtti' that give run-time type information.  */
+
+extern int flag_rtti;
+
+/* Nonzero if virtual base class offsets are stored in the virtual
+   function table.  Zero if, instead, a pointer to the virtual base is
+   stored in the object itself.  */
+#define vbase_offsets_in_vtable_p() (flag_new_abi)
+
+/* Nonzero if a derived class that needs a vptr should always get one,
+   even if a non-primary base class already has one.  For example,
+   given:
+
+     struct S { int i; virtual void f(); };
+     struct T : virtual public S {};
+
+   one could either reuse the vptr in `S' for `T', or create a new
+   vptr for `T'.  If this flag is nonzero we choose the latter
+   alternative; otherwise, we choose the former.  */
+#define vptrs_present_everywhere_p() (flag_new_abi)
+
+\f
 /* Language-dependent contents of an identifier.  */
 
 struct lang_identifier
@@ -2156,6 +2193,12 @@ struct lang_decl
    polymorphic class.  */
 #define TYPE_POLYMORPHIC_P(NODE) (TREE_LANG_FLAG_2 (NODE))
 
+/* Nonzero if this class has a virtual function table pointer.  */
+#define TYPE_CONTAINS_VPTR_P(NODE)             \
+  (TYPE_POLYMORPHIC_P (NODE)                   \
+   || (vbase_offsets_in_vtable_p ()            \
+       && TYPE_USES_VIRTUAL_BASECLASSES (NODE)))
+
 extern int flag_new_for_scope;
 
 /* This flag is true of a local VAR_DECL if it was declared in a for
@@ -3160,10 +3203,6 @@ extern struct pending_inline *pending_inlines;
 
 extern int flag_this_is_variable;
 
-/* Nonzero means generate 'rtti' that give run-time type information.  */
-
-extern int flag_rtti;
-
 /* Nonzero means do emit exported implementations of functions even if
    they can be inlined.  */
 
@@ -3187,19 +3226,6 @@ extern int flag_implicit_templates;
 
 extern int flag_weak;
 
-/* Nonzero to enable experimental ABI changes.  */
-
-extern int flag_new_abi;
-
-/* Nonzero to use __cxa_atexit, rather than atexit, to register
-   destructors for local statics and global objects.  */
-
-extern int flag_use_cxa_atexit;
-
-/* Nonzero to not ignore namespace std. */
-
-extern int flag_honor_std;
-
 /* Nonzero if we should expand functions calls inline at the tree
    level, rather than at the RTL level.  */
 
@@ -3961,6 +3987,11 @@ extern tree dfs_walk                            PROTO((tree,
                                                       tree (*)(tree, void *),
                                                       tree (*) (tree, void *),
                                                       void *));
+extern tree dfs_walk_real                      PROTO ((tree, 
+                                                      tree (*) (tree, void *),
+                                                      tree (*) (tree, void *),
+                                                      tree (*) (tree, void *),
+                                                      void *));
 extern tree dfs_unmark                          PROTO((tree, void *));
 extern tree dfs_vbase_unmark                    PROTO((tree, void *));
 extern tree dfs_vtable_path_unmark              PROTO((tree, void *));
index d8a57e56f2b119d284bb8ea500ea13e175ab11cf..0a5dc568f48059ba08a8668081822e20d450f1b5 100644 (file)
@@ -8201,15 +8201,7 @@ expand_static_init (decl, init)
       finish_if_stmt ();
     }
   else
-    {
-      /* This code takes into account memory allocation policy of
-        `start_decl'.  Namely, if TYPE_NEEDS_CONSTRUCTING does not
-        hold for this object, then we must make permanent the storage
-        currently in the temporary obstack.  */
-      if (!TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (decl)))
-       preserve_initializer ();
-      static_aggregates = tree_cons (init, decl, static_aggregates);
-    }
+    static_aggregates = tree_cons (init, decl, static_aggregates);
 }
 
 /* Finish the declaration of a catch-parameter.  */
index 40b656ff73d7e4b665c013104a2fc5644014ab2e..10d071e4ec3769f76c975eac6aefaa0676f0e3ca 100644 (file)
@@ -2296,8 +2296,9 @@ mark_vtable_entries (decl)
       fnaddr = (flag_vtable_thunks ? TREE_VALUE (entries) 
                : FNADDR_FROM_VTABLE_ENTRY (TREE_VALUE (entries)));
 
-      if (TREE_CODE (fnaddr) == NOP_EXPR)
-       /* RTTI offset.  */
+      if (TREE_CODE (fnaddr) != ADDR_EXPR)
+       /* This entry is an offset: a virtual base class offset, a
+          virtual call offset, and RTTI offset, etc.  */
        continue;
 
       fn = TREE_OPERAND (fnaddr, 0);
index 3828ddf499bef0320865e434b4d12451aa1e0bab..b5a1ac43bf8344de2850c80be3f11520c3e0a492 100644 (file)
@@ -119,8 +119,12 @@ initialize_vtbl_ptrs (type, addr)
 {
   tree list = build_tree_list (type, addr);
 
-  dfs_walk (TYPE_BINFO (type), dfs_initialize_vtbl_ptrs, 
-           dfs_unmarked_real_bases_queue_p, list);
+  /* Walk through the hierarchy, initializing the vptr in each base
+     class.  We do these in pre-order because under the new ABI we
+     can't find the virtual bases for a class until we've initialized
+     the vtbl for that class.  */
+  dfs_walk_real (TYPE_BINFO (type), dfs_initialize_vtbl_ptrs, 
+                NULL, dfs_unmarked_real_bases_queue_p, list);
   dfs_walk (TYPE_BINFO (type), dfs_unmark,
            dfs_marked_real_bases_queue_p, type);
   if (TYPE_USES_VIRTUAL_BASECLASSES (type))
@@ -657,7 +661,7 @@ expand_virtual_init (binfo, decl)
   vtbl = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (vtbl)), vtbl);
   /* Under the new ABI, we need to point into the middle of the
      vtable.  */
-  if (flag_new_abi)
+  if (vbase_offsets_in_vtable_p ())
     vtbl = build (PLUS_EXPR, TREE_TYPE (vtbl), vtbl, 
                  size_extra_vtbl_entries (binfo));
 
@@ -720,7 +724,7 @@ expand_aggr_vbase_init_1 (binfo, exp, addr, init_list)
 /* Construct the virtual base-classes of THIS_REF (whose address is
    THIS_PTR).  The object has the indicated TYPE.  The construction
    actually takes place only if FLAG is non-zero.  INIT_LIST is list
-   of initialization for constructor to perform.  */
+   of initializations for constructors to perform.  */
 
 static void
 construct_virtual_bases (type, this_ref, this_ptr, init_list, flag)
@@ -731,21 +735,25 @@ construct_virtual_bases (type, this_ref, this_ptr, init_list, flag)
      tree flag;
 {
   tree vbases;
-  tree result;
-  tree if_stmt;
 
   /* If there are no virtual baseclasses, we shouldn't even be here.  */
   my_friendly_assert (TYPE_USES_VIRTUAL_BASECLASSES (type), 19990621);
 
   /* First set the pointers in our object that tell us where to find
      our virtual baseclasses.  */
-  if_stmt = begin_if_stmt ();
-  finish_if_stmt_cond (flag, if_stmt);
-  result = init_vbase_pointers (type, this_ptr);
-  if (result)
-    finish_expr_stmt (build_compound_expr (result));
-  finish_then_clause (if_stmt);
-  finish_if_stmt ();
+  if (!vbase_offsets_in_vtable_p ())
+    {
+      tree if_stmt;
+      tree result;
+
+      if_stmt = begin_if_stmt ();
+      finish_if_stmt_cond (flag, if_stmt);
+      result = init_vbase_pointers (type, this_ptr);
+      if (result)
+       finish_expr_stmt (build_compound_expr (result));
+      finish_then_clause (if_stmt);
+      finish_if_stmt ();
+    }
 
   /* Now, run through the baseclasses, initializing each.  */ 
   for (vbases = CLASSTYPE_VBASECLASSES (type); vbases;
@@ -1019,11 +1027,6 @@ finish_init_stmts (stmt_expr, compound_stmt)
    If `init' is a CONSTRUCTOR, then we emit a warning message,
    explaining that such initializations are invalid.
 
-   ALIAS_THIS is nonzero iff we are initializing something which is
-   essentially an alias for current_class_ref.  In this case, the base
-   constructor may move it on us, and we must keep track of such
-   deviations.
-
    If INIT resolves to a CALL_EXPR which happens to return
    something of the type we are looking for, then we know
    that we can safely use that call to perform the
@@ -1217,8 +1220,6 @@ expand_default_init (binfo, true_exp, exp, init, flags)
    from TRUE_EXP.  In constructors, we don't know anything about
    the value being initialized.
 
-   ALIAS_THIS serves the same purpose it serves for expand_aggr_init.
-
    FLAGS is just passes to `build_method_call'.  See that function for
    its description.  */
 
index 74113aba2c65751133caddf8cdfed8e7438e5722..cddefe7dae2a28c0d20be897aed0a65b2a18689f 100644 (file)
@@ -1,5 +1,5 @@
 /* RunTime Type Identification
-   Copyright (C) 1995, 96-97, 1998, 1999 Free Software Foundation, Inc.
+   Copyright (C) 1995, 96-97, 1998, 1999, 2000 Free Software Foundation, Inc.
    Mostly written by Jason Merrill (jason@cygnus.com).
 
 This file is part of GNU CC.
@@ -811,7 +811,8 @@ expand_class_desc (tdecl, type)
                             (type_info_type_node,
                              TYPE_QUAL_CONST)));
       fields [1] = build_lang_decl
-       (FIELD_DECL, NULL_TREE, unsigned_intSI_type_node);
+       (FIELD_DECL, NULL_TREE, 
+        flag_new_abi ? intSI_type_node : unsigned_intSI_type_node);
       DECL_BIT_FIELD (fields[1]) = 1;
       DECL_FIELD_SIZE (fields[1]) = 29;
 
@@ -839,15 +840,26 @@ expand_class_desc (tdecl, type)
 
       if (TREE_VIA_VIRTUAL (binfo))
        {
-         tree t = BINFO_TYPE (binfo);
-         const char *name;
-         tree field;
-
-         FORMAT_VBASE_NAME (name, t);
-         field = lookup_field (type, get_identifier (name), 0, 0);
-         offset = size_binop (FLOOR_DIV_EXPR, 
-               DECL_FIELD_BITPOS (field), size_int (BITS_PER_UNIT));
-         offset = convert (sizetype, offset);
+         if (!vbase_offsets_in_vtable_p ())
+           {
+             tree t = BINFO_TYPE (binfo);
+             const char *name;
+             tree field;
+
+             FORMAT_VBASE_NAME (name, t);
+             field = lookup_field (type, get_identifier (name), 0, 0);
+             offset = size_binop (FLOOR_DIV_EXPR, 
+                                  DECL_FIELD_BITPOS (field), 
+                                  size_int (BITS_PER_UNIT));
+             offset = convert (sizetype, offset);
+           }
+         else
+           {
+             /* Under the new ABI, we store the vtable offset at which
+                the virtual base offset can be found.  */
+             tree vbase = BINFO_FOR_VBASE (BINFO_TYPE (binfo), type);
+             offset = convert (sizetype, BINFO_VPTR_FIELD (vbase));
+           }
        }
       else
        offset = BINFO_OFFSET (binfo);
index 697bf8b214e59fda0410519e4f291b0501e31d40..d29cdb57705144bdd56a3ff3d0fd305a6da9495a 100644 (file)
@@ -126,11 +126,6 @@ static tree bfs_walk
               void *));
 static tree lookup_field_queue_p PROTO((tree, void *));
 static tree lookup_field_r PROTO((tree, void *));
-static tree dfs_walk_real PROTO ((tree, 
-                                 tree (*) (tree, void *),
-                                 tree (*) (tree, void *),
-                                 tree (*) (tree, void *),
-                                 void *));
 static tree get_virtuals_named_this_r PROTO ((tree, void *));
 static tree context_for_name_lookup PROTO ((tree));
 static tree canonical_binfo PROTO ((tree));
@@ -1773,7 +1768,7 @@ bfs_walk (binfo, fn, qfn, data)
    performed, and PREFN is called in preorder, while POSTFN is called
    in postorder.  */
 
-static tree
+tree
 dfs_walk_real (binfo, prefn, postfn, qfn, data)
      tree binfo;
      tree (*prefn) PROTO((tree, void *));
@@ -3200,9 +3195,9 @@ maybe_suppress_debug_info (t)
     TYPE_DECL_SUPPRESS_DEBUG (TYPE_MAIN_DECL (t)) = 1;
   else if (CLASSTYPE_INTERFACE_KNOWN (t))
     /* Don't set it.  */;
-  /* If the class has virtual functions, write out the debug info
-     along with the vtable.  */
-  else if (TYPE_POLYMORPHIC_P (t))
+  /* If the class has a vtable, write out the debug info along with
+     the vtable.  */
+  else if (TYPE_CONTAINS_VPTR_P (t))
     TYPE_DECL_SUPPRESS_DEBUG (TYPE_MAIN_DECL (t)) = 1;
 
   /* Otherwise, just emit the debug info normally.  */
index 1d4885c926460ba7b3aa2728d80fca9c5a5d0dae..18a00b0b19a4464a175d41fd41077ff02a808b08 100644 (file)
@@ -1,5 +1,5 @@
 // Methods for type_info for -*- C++ -*- Run Time Type Identification.
-// Copyright (C) 1994, 1996, 1998, 1999 Free Software Foundation
+// Copyright (C) 1994, 1996, 1998, 1999, 2000 Free Software Foundation
 
 // This file is part of GNU CC.
 
 #include "tinfo.h"
 #include "new"                 // for placement new
 
+namespace
+{
+// ADDR is a pointer to an object.  Convert it to a pointer to a base,
+// using OFFSET.
+inline void*
+convert_to_base (void *addr, bool is_virtual, USItype offset)
+{
+  if (!addr)
+    return NULL;
+
+  if (!is_virtual)
+    return (char *) addr + offset;
+
+#ifdef __GXX_ABI_VERSION
+  // Under the new ABI, the offset gives us an index into the vtable,
+  // which contains an offset to the virtual base.  The vptr is always
+  // the first thing in the object.
+  std::ptrdiff_t *vtable = *((std::ptrdiff_t **) addr);
+  return ((char *) addr) + vtable[offset];
+#else
+  // Under the old ABI, the offset gives us the address of a pointer
+  // to the virtual base.
+  return *((void **) ((char *) addr + offset));
+#endif
+}
+
+}
+
 // This file contains the minimal working set necessary to link with code
 // that uses virtual functions and -frtti but does not actually use RTTI
 // functionality.
@@ -254,14 +282,11 @@ do_upcast (sub_kind access_path,
       upcast_result result2;
       void *p = objptr;
       sub_kind sub_access = access_path;
-      if (p)
-        p = (char *)p + base_list[i].offset;
+      p = convert_to_base (p, 
+                          base_list[i].is_virtual,
+                          base_list[i].offset);
       if (base_list[i].is_virtual)
-        {
-          if (p)
-            p = *(void **)p;
-         sub_access = sub_kind (sub_access | contained_virtual_mask);
-        }
+       sub_access = sub_kind (sub_access | contained_virtual_mask);
       if (base_list[i].access != PUBLIC)
         sub_access = sub_kind (sub_access & ~contained_public_mask);
       if (base_list[i].base->do_upcast (sub_access, target, p, result2))
@@ -344,13 +369,13 @@ do_dyncast (int boff, sub_kind access_path,
   for (size_t i = n_bases; i--;)
     {
       dyncast_result result2;
-      void *p = (char *)objptr + base_list[i].offset;
+      void *p;
       sub_kind sub_access = access_path;
+      p = convert_to_base (objptr, 
+                          base_list[i].is_virtual,
+                          base_list[i].offset);
       if (base_list[i].is_virtual)
-        {
-         p = *(void **)p;
-         sub_access = sub_kind (sub_access | contained_virtual_mask);
-       }
+       sub_access = sub_kind (sub_access | contained_virtual_mask);
       if (base_list[i].access != PUBLIC)
         sub_access = sub_kind (sub_access & ~contained_public_mask);
       
@@ -492,13 +517,15 @@ do_find_public_subobj (int boff, const type_info &subtype, void *objptr, void *s
     {
       if (base_list[i].access != PUBLIC)
         continue; // Not public, can't be here.
-      void *p = (char *)objptr + base_list[i].offset;
-      if (base_list[i].is_virtual)
-        {
-          if (boff == -1)
-            continue; // Not a virtual base, so can't be here.
-          p = *(void **)p;
-        }
+      void *p;
+
+      if (base_list[i].is_virtual && boff == -1)
+       // Not a virtual base, so can't be here.
+       continue;
+      
+      p = convert_to_base (objptr, 
+                          base_list[i].is_virtual,
+                          base_list[i].offset);
 
       sub_kind base_kind = base_list[i].base->do_find_public_subobj
                               (boff, subtype, p, subptr);
index 39be84edde500232bb03d9ff3f9f203256d0c342..116c7a8dd0f796c5e1e4c77353cb1f59fd2e56d7 100644 (file)
@@ -1,5 +1,5 @@
 // RTTI support internals for -*- C++ -*-
-// Copyright (C) 1994, 1995, 1996, 1998, 1999 Free Software Foundation
+// Copyright (C) 1994, 1995, 1996, 1998, 1999, 2000 Free Software Foundation
 
 #include "typeinfo"
 
@@ -167,7 +167,11 @@ public:
 
 // type_info for a general class.
 
+#ifdef __GXX_ABI_VERSION
+typedef int USItype __attribute__ ((mode (SI)));
+#else
 typedef unsigned int USItype   __attribute__ ((mode (SI)));
+#endif
 
 struct __class_type_info : public __user_type_info {
   enum access { PUBLIC = 1, PROTECTED = 2, PRIVATE = 3 };
index a951b5f719731a5f9d39aa78f26681222828a0c7..3c342d5f87727f214f98d9c15db223817ccbe33b 100644 (file)
@@ -860,7 +860,6 @@ make_binfo (offset, binfo, vtable, virtuals)
   BINFO_OFFSET (new_binfo) = offset;
   BINFO_VTABLE (new_binfo) = vtable;
   BINFO_VIRTUALS (new_binfo) = virtuals;
-  BINFO_VPTR_FIELD (new_binfo) = NULL_TREE;
 
   if (binfo && BINFO_BASETYPES (binfo) != NULL_TREE)
     BINFO_BASETYPES (new_binfo) = copy_node (BINFO_BASETYPES (binfo));