This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

C++ PATCH: VTT implementation



This patch implements VTTs (i.e., the fix for the thunks bug) for the
new ABI -- minus one minor optimization that I'll get to relatively
shortly.  VTTs were probably the most major remaining bit of
functionality, except for name-mangling (which Alex has mostly
completed; I'll be making a few additions and checking that in while
Alex implements the ABI all over again in another compiler...), and
exception-handling (which I understand will be contributed soon).

In addition, I came across an interesting code-generation bug that
dates back to (at least) EGCS 1.1:

  int i;

  struct A { ~A (); };
  A::~A () { i = 1; }

  struct B : virtual public A {};

  struct C {
    C ();
    B b;
  };

  C::C () { throw 3; }

  int main () {
    try { 
       C c;
    } catch (...) {
    }

    if (i != 1)
      return 1;
  }

Here, we were not destroying the A subobject when C's constructor
threw an exception.  Oops.  Fixed, and test included in the patch.

--
Mark Mitchell                   mark@codesourcery.com
CodeSourcery, LLC               http://www.codesourcery.com

2000-05-25  Mark Mitchell  <mark@codesourcery.com>

	Finish implementation of VTTs.
	* cp-tree.h (cp_tree_index): Add CPTI_VTT_PARM_TYPE and
	CPTI_VTT_PARM_IDENTIFIER.
	(vtt_parm_identifier): New macro.
	(vtt_parm_type): Likewise.
	(BINFO_SUBVTT_INDEX): Likewise.
	(BINFO_VPTR_INDEX): Likewise.
	(struct lang_decl): Add vtt_parm.
	(DECL_VTT_PARM): New macro.
	(DECL_USE_VTT_PARM): Likewise.
	(DECL_NEEDS_VTT_PARM_P): Likewise.
	(get_vtt_name): Declare.
	(build_artifical_parm): Likewise.
	(fixup_all_virtual_upcast_offsets): Likewise.
	(expand_indirect_vtbls_init): Remove.
	* call.c (build_new_method_call): Pass the vtt to subobject
	constructors and destructors.
	* class.c (get_vtt_name): Give it external linkage.
	(build_clone): Handle the magic VTT parameters for clones.
	(clone_function_decl): Fix typo in comment.
	(build_vtt): Keep track of the indices in the VTTs where various
	entities are stored.
	(build_vtt_inits): Likewise.
	(dfs_build_vtt_inits): Likewise.
	(build_ctor_vtbl_group): Tweak type of construction vtables.
	(dfs_accumulate_vtbl_inits): Build vtables for all bases, even
	primary bases, when building construction vtables.
	* decl.c (duplicate_decls): Handle DECL_VTT_PARM.
	(initialize_predefined_identifiers): Add vtt_parm_identifier.
	(init_decl_processing): Initialize vtt_parm_type.
	(grokfndecl): Use DECL_OVERLOADED_OPERATOR_P.
	(lang_mark_tree): Make vtt_parm.
	* decl2.c (build_artificial_parm): New function.
	(maybe_retrofit_in_chrg): Use it.  Add VTT parameters.
	(grokclassfn): Use build_artificial_parm.
	* init.c (initialize_vtbl_ptrs): Call
	fixup_all_virtual_upcast_offsets directly.
	(perform_member_init): Use the complete subobject destructor for
	member cleanups.
	(build_vtbl_address): New function.
	(expand_virtual_init): Handle VTTs.
	* optimize (maybe_clone_body): Likewise.
	* search.c (fixup_all_virtual_upcast_offsets): Give it external
	linkage.
	(expand_indirect_vtbls_init): Remove.
	* semantics.c (setup_vtbl_ptr): Fix typos in comment.
	* tree.c (make_binfo): Make them bigger.

Index: testsuite/g++.old-deja/g++.other/vbase1.C
===================================================================
RCS file: vbase1.C
diff -N vbase1.C
*** /dev/null	Tue May  5 13:32:27 1998
--- vbase1.C	Thu May 25 16:15:14 2000
***************
*** 0 ****
--- 1,51 ----
+ // Origin: Mark Mitchell <mark@codesourcery.com>
+ // Special g++ Options: -w
+ 
+ int result;
+ 
+ struct A {
+   A ();
+ 
+   int i;
+ };
+ 
+ A* ap;
+ 
+ A::A ()
+ {
+   ap = this;
+ }
+ 
+ struct B : virtual public A
+ {
+   B ();
+   ~B ();
+ 
+   int j;
+ };
+ 
+ B::B () {
+   if ((A*) this != ap)
+     result = 1;
+ }
+ 
+ B::~B () {
+   if ((A*) this != ap)
+     result = 1;
+ }
+ 
+ struct C : public B {
+ };
+ 
+ struct D : public C, public B
+ {
+ };
+ 
+ int main ()
+ {
+   {
+     D d;
+   }
+ 
+   return result;
+ }
Index: testsuite/g++.old-deja/g++.other/vbase2.C
===================================================================
RCS file: vbase2.C
diff -N vbase2.C
*** /dev/null	Tue May  5 13:32:27 1998
--- vbase2.C	Thu May 25 16:15:14 2000
***************
*** 0 ****
--- 1,36 ----
+ // Origin: Mark Mitchell <mark@codesourcery.com>
+ 
+ int i;
+ 
+ struct A
+ {
+   ~A ();
+ };
+ 
+ A::~A () {
+   i = 1;
+ }
+ 
+ struct B : virtual public A {
+ };
+ 
+ struct C {
+   C ();
+ 
+   B b;
+ };
+ 
+ C::C () {
+   throw 3;
+ }
+ 
+ int main () 
+ {
+   try { 
+     C c;
+   } catch (...) {
+   }
+ 
+   if (i != 1)
+     return 1;
+ }
Index: cp/call.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cp/call.c,v
retrieving revision 1.215
diff -c -p -r1.215 call.c
*** call.c	2000/05/24 22:56:53	1.215
--- call.c	2000/05/25 23:14:45
*************** build_new_method_call (instance, name, a
*** 4321,4326 ****
--- 4321,4352 ----
  	     old ABI.  */
  	  name = constructor_p ? ctor_identifier : dtor_identifier;
  	}
+       /* If we're call a subobject constructor or destructor for a
+ 	 subobject that uses virtual base classes, then we need to
+ 	 pass down a pointer to a VTT for the subobject.  */
+       else if ((name == base_ctor_identifier
+ 		|| name == base_dtor_identifier)
+ 	       && TYPE_USES_VIRTUAL_BASECLASSES (basetype))
+ 	{
+ 	  tree vtt;
+ 	  tree sub_vtt;
+ 
+ 	  /* If the current function is a complete object constructor
+ 	     or destructor, then we fetch the VTT directly.
+ 	     Otherwise, we look it up using the VTT we were given.  */
+ 	  vtt = IDENTIFIER_GLOBAL_VALUE (get_vtt_name (current_class_type));
+ 	  vtt = build_unary_op (ADDR_EXPR, vtt, /*noconvert=*/1);
+ 	  vtt = build (COND_EXPR, TREE_TYPE (vtt), 
+ 		       DECL_USE_VTT_PARM (current_function_decl),
+ 		       DECL_VTT_PARM (current_function_decl),
+ 		       vtt);
+ 
+ 	  sub_vtt = build (PLUS_EXPR, TREE_TYPE (vtt), vtt,
+ 			   BINFO_SUBVTT_INDEX (basetype_path));
+ 	  sub_vtt = build_indirect_ref (sub_vtt, NULL);
+ 
+ 	  args = tree_cons (NULL_TREE, sub_vtt, args);
+ 	}
      }
    else
      pretty_name = name;
Index: cp/class.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cp/class.c,v
retrieving revision 1.306
diff -c -p -r1.306 class.c
*** class.c	2000/05/24 06:15:02	1.306
--- class.c	2000/05/25 23:14:50
*************** static void update_vtable_entry_for_fn P
*** 181,187 ****
  static tree copy_virtuals PARAMS ((tree));
  static void build_ctor_vtbl_group PARAMS ((tree, tree));
  static void build_vtt PARAMS ((tree));
! static tree *build_vtt_inits PARAMS ((tree, tree, tree *));
  static tree dfs_build_vtt_inits PARAMS ((tree, void *));
  static tree dfs_fixup_binfo_vtbls PARAMS ((tree, void *));
  
--- 181,187 ----
  static tree copy_virtuals PARAMS ((tree));
  static void build_ctor_vtbl_group PARAMS ((tree, tree));
  static void build_vtt PARAMS ((tree));
! static tree *build_vtt_inits PARAMS ((tree, tree, tree *, tree *));
  static tree dfs_build_vtt_inits PARAMS ((tree, void *));
  static tree dfs_fixup_binfo_vtbls PARAMS ((tree, void *));
  
*************** get_vtable_name (type)
*** 635,641 ****
  /* Return an IDENTIFIER_NODE for the name of the virtual table table
     for TYPE.  */
  
! static tree
  get_vtt_name (type)
       tree type;
  {
--- 635,641 ----
  /* Return an IDENTIFIER_NODE for the name of the virtual table table
     for TYPE.  */
  
! tree
  get_vtt_name (type)
       tree type;
  {
*************** build_clone (fn, name)
*** 3957,3962 ****
--- 3957,3964 ----
    DECL_PENDING_INLINE_P (clone) = 0;
    /* And it hasn't yet been deferred.  */
    DECL_DEFERRED_FN (clone) = 0;
+   /* There's no magic VTT parameter in the clone.  */
+   DECL_VTT_PARM (clone) = NULL_TREE;
  
    /* The base-class destructor is not virtual.  */
    if (name == base_dtor_identifier)
*************** build_clone (fn, name)
*** 3981,3986 ****
--- 3983,3992 ----
        parmtypes = TREE_CHAIN (parmtypes);
        /* Skip the in-charge parameter.  */
        parmtypes = TREE_CHAIN (parmtypes);
+        /* If this is subobject constructor or destructor, add the vtt
+ 	 parameter.  */
+       if (DECL_NEEDS_VTT_PARM_P (clone))
+ 	parmtypes = hash_tree_chain (vtt_parm_type, parmtypes);
        TREE_TYPE (clone) 
  	= build_cplus_method_type (basetype,
  				   TREE_TYPE (TREE_TYPE (clone)),
*************** build_clone (fn, name)
*** 4002,4007 ****
--- 4008,4025 ----
  	    = TREE_CHAIN (TREE_CHAIN (DECL_ARGUMENTS (clone)));
  	  DECL_HAS_IN_CHARGE_PARM_P (clone) = 0;
  	}
+ 
+       /* Add the VTT parameter.  */
+       if (DECL_NEEDS_VTT_PARM_P (clone))
+ 	{
+ 	  tree parm;
+ 
+ 	  parm = build_artificial_parm (vtt_parm_identifier,
+ 					vtt_parm_type);
+ 	  TREE_CHAIN (parm) = TREE_CHAIN (DECL_ARGUMENTS (clone));
+ 	  TREE_CHAIN (DECL_ARGUMENTS (clone)) = parm;
+ 	}
+ 
        for (parms = DECL_ARGUMENTS (clone); parms; parms = TREE_CHAIN (parms))
  	{
  	  DECL_CONTEXT (parms) = clone;
*************** clone_function_decl (fn, update_method_v
*** 4063,4069 ****
      {
        my_friendly_assert (DECL_MAYBE_IN_CHARGE_DESTRUCTOR_P (fn), 20000411);
  
!       /* For each destructor, we need two variants: an in-charge
  	 version, a not-in-charge version, and an in-charge deleting
  	 version.  We clone the deleting version first because that
  	 means it will go second on the TYPE_METHODS list -- and that
--- 4081,4087 ----
      {
        my_friendly_assert (DECL_MAYBE_IN_CHARGE_DESTRUCTOR_P (fn), 20000411);
  
!       /* For each destructor, we need three variants: an in-charge
  	 version, a not-in-charge version, and an in-charge deleting
  	 version.  We clone the deleting version first because that
  	 means it will go second on the TYPE_METHODS list -- and that
*************** build_vtt (t)
*** 6474,6479 ****
--- 6492,6498 ----
    tree inits;
    tree type;
    tree vtt;
+   tree index;
  
    /* Under the old ABI, we don't use VTTs.  */
    if (!flag_new_abi)
*************** build_vtt (t)
*** 6481,6487 ****
  
    /* Build up the initializers for the VTT.  */
    inits = NULL_TREE;
!   build_vtt_inits (TYPE_BINFO (t), t, &inits);
  
    /* If we didn't need a VTT, we're done.  */
    if (!inits)
--- 6500,6507 ----
  
    /* Build up the initializers for the VTT.  */
    inits = NULL_TREE;
!   index = size_zero_node;
!   build_vtt_inits (TYPE_BINFO (t), t, &inits, &index);
  
    /* If we didn't need a VTT, we're done.  */
    if (!inits)
*************** build_vtt (t)
*** 6499,6511 ****
  
  /* Recursively build the VTT-initializer for BINFO (which is in the
     hierarchy dominated by T).  INITS points to the end of the
!    initializer list to date.  */
  
  static tree *
! build_vtt_inits (binfo, t, inits)
       tree binfo;
       tree t;
       tree *inits;
  {
    int i;
    tree b;
--- 6519,6533 ----
  
  /* Recursively build the VTT-initializer for BINFO (which is in the
     hierarchy dominated by T).  INITS points to the end of the
!    initializer list to date.  INDEX is the VTT index where the next
!    element will be placed.  */
  
  static tree *
! build_vtt_inits (binfo, t, inits, index)
       tree binfo;
       tree t;
       tree *inits;
+      tree *index;
  {
    int i;
    tree b;
*************** build_vtt_inits (binfo, t, inits)
*** 6521,6548 ****
       VTT.  */
    ctor_vtbl_p = !same_type_p (TREE_TYPE (binfo), t);
    if (ctor_vtbl_p)
!     build_ctor_vtbl_group (binfo, t);
  
    /* Add the address of the primary vtable for the complete object.  */
    init = BINFO_VTABLE (binfo);
    if (TREE_CODE (init) == TREE_LIST)
      init = TREE_PURPOSE (init);
    *inits = build_tree_list (NULL_TREE, init);
    inits = &TREE_CHAIN (*inits);
! 
    /* Recursively add the secondary VTTs for non-virtual bases.  */
    for (i = 0; i < BINFO_N_BASETYPES (binfo); ++i)
      {
        b = BINFO_BASETYPE (binfo, i);
        if (!TREE_VIA_VIRTUAL (b))
! 	inits = build_vtt_inits (BINFO_BASETYPE (binfo, i), t, inits);
      }
! 
    /* Add secondary virtual pointers for all subobjects of BINFO with
       either virtual bases or virtual functions overridden along a
       virtual path between the declaration and D, except subobjects
       that are non-virtual primary bases.  */
    secondary_vptrs = build_tree_list (BINFO_TYPE (binfo), NULL_TREE);
    dfs_walk_real (binfo,
  		 dfs_build_vtt_inits,
  		 NULL,
--- 6543,6579 ----
       VTT.  */
    ctor_vtbl_p = !same_type_p (TREE_TYPE (binfo), t);
    if (ctor_vtbl_p)
!     {
!       build_ctor_vtbl_group (binfo, t);
  
+       /* Record the offset in the VTT where this sub-VTT can be found.  */
+       BINFO_SUBVTT_INDEX (binfo) = *index;
+     }
+ 
    /* Add the address of the primary vtable for the complete object.  */
    init = BINFO_VTABLE (binfo);
    if (TREE_CODE (init) == TREE_LIST)
      init = TREE_PURPOSE (init);
    *inits = build_tree_list (NULL_TREE, init);
    inits = &TREE_CHAIN (*inits);
!   BINFO_VPTR_INDEX (binfo) = *index;
!   *index = size_binop (PLUS_EXPR, *index, TYPE_SIZE_UNIT (ptr_type_node));
! 		       
    /* Recursively add the secondary VTTs for non-virtual bases.  */
    for (i = 0; i < BINFO_N_BASETYPES (binfo); ++i)
      {
        b = BINFO_BASETYPE (binfo, i);
        if (!TREE_VIA_VIRTUAL (b))
! 	inits = build_vtt_inits (BINFO_BASETYPE (binfo, i), t, inits,
! 				 index);
      }
!       
    /* Add secondary virtual pointers for all subobjects of BINFO with
       either virtual bases or virtual functions overridden along a
       virtual path between the declaration and D, except subobjects
       that are non-virtual primary bases.  */
    secondary_vptrs = build_tree_list (BINFO_TYPE (binfo), NULL_TREE);
+   TREE_TYPE (secondary_vptrs) = *index;
    dfs_walk_real (binfo,
  		 dfs_build_vtt_inits,
  		 NULL,
*************** build_vtt_inits (binfo, t, inits)
*** 6550,6555 ****
--- 6581,6587 ----
  		 secondary_vptrs);
    dfs_walk (binfo, dfs_fixup_binfo_vtbls, dfs_marked_real_bases_queue_p,
  	    BINFO_TYPE (binfo));
+   *index = TREE_TYPE (secondary_vptrs);
  
    /* The secondary vptrs come back in reverse order.  After we reverse
       them, and add the INITS, the last init will be the first element
*************** build_vtt_inits (binfo, t, inits)
*** 6571,6577 ****
  	continue;
  
        vbase = binfo_for_vbase (BINFO_TYPE (b), t);
!       inits = build_vtt_inits (vbase, t, inits);
      }
  
    return inits;
--- 6603,6609 ----
  	continue;
  
        vbase = binfo_for_vbase (BINFO_TYPE (b), t);
!       inits = build_vtt_inits (vbase, t, inits, index);
      }
  
    return inits;
*************** dfs_build_vtt_inits (binfo, data)
*** 6587,6592 ****
--- 6619,6625 ----
    tree l; 
    tree t;
    tree init;
+   tree index;
  
    l = (tree) data;
    t = TREE_PURPOSE (l);
*************** dfs_build_vtt_inits (binfo, data)
*** 6612,6624 ****
      /* FIXME: Implement this.  */
      ;
  
!   /* Add the initializer for this secondary vptr.  */
    init = BINFO_VTABLE (binfo);
    if (TREE_CODE (init) == TREE_LIST)
      init = TREE_PURPOSE (init);
- 
    TREE_VALUE (l) = tree_cons (NULL_TREE, init, TREE_VALUE (l));
!   
    return NULL_TREE;
  }
  
--- 6645,6662 ----
      /* FIXME: Implement this.  */
      ;
  
!   /* Record the index where this secondary vptr can be found.  */
!   index = TREE_TYPE (l);
!   BINFO_VPTR_INDEX (binfo) = index;
!   TREE_TYPE (l) = size_binop (PLUS_EXPR, index, 
! 			      TYPE_SIZE_UNIT (ptr_type_node));
! 
!   /* Add the initializer for the secondary vptr itself.  */
    init = BINFO_VTABLE (binfo);
    if (TREE_CODE (init) == TREE_LIST)
      init = TREE_PURPOSE (init);
    TREE_VALUE (l) = tree_cons (NULL_TREE, init, TREE_VALUE (l));
! 
    return NULL_TREE;
  }
  
*************** build_ctor_vtbl_group (binfo, t)
*** 6665,6671 ****
    /* Build a version of VTBL (with the wrong type) for use in
       constructing the addresses of secondary vtables in the
       construction vtable group.  */
!   vtbl = build_vtable (BINFO_TYPE (binfo), id, vtable_entry_type);
    list = build_tree_list (vtbl, NULL_TREE);
    accumulate_vtbl_inits (binfo, TYPE_BINFO (TREE_TYPE (binfo)),
  			 binfo, t, list);
--- 6703,6709 ----
    /* Build a version of VTBL (with the wrong type) for use in
       constructing the addresses of secondary vtables in the
       construction vtable group.  */
!   vtbl = build_vtable (BINFO_TYPE (binfo), id, ptr_type_node);
    list = build_tree_list (vtbl, NULL_TREE);
    accumulate_vtbl_inits (binfo, TYPE_BINFO (TREE_TYPE (binfo)),
  			 binfo, t, list);
*************** dfs_accumulate_vtbl_inits (binfo, orig_b
*** 6762,6768 ****
    if (BINFO_NEW_VTABLE_MARKED (binfo, t)
        /* We need a new vtable, even for a primary base, when we're
  	 building a construction vtable.  */
!       || (ctor_vtbl_p && orig_binfo == rtti_binfo))
      {
        tree vtbl;
        tree index;
--- 6800,6806 ----
    if (BINFO_NEW_VTABLE_MARKED (binfo, t)
        /* We need a new vtable, even for a primary base, when we're
  	 building a construction vtable.  */
!       || (ctor_vtbl_p && CLASSTYPE_VFIELDS (BINFO_TYPE (binfo))))
      {
        tree vtbl;
        tree index;
Index: cp/cp-tree.h
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cp/cp-tree.h,v
retrieving revision 1.460
diff -c -p -r1.460 cp-tree.h
*** cp-tree.h	2000/05/24 22:56:53	1.460
--- cp-tree.h	2000/05/25 23:14:53
*************** enum cp_tree_index
*** 530,535 ****
--- 530,536 ----
      CPTI_DELTA_TYPE,
      CPTI_VTABLE_INDEX_TYPE,
      CPTI_CLEANUP_TYPE,
+     CPTI_VTT_PARM_TYPE,
  
      CPTI_TI_DESC_TYPE,
      CPTI_BLTN_DESC_TYPE,
*************** enum cp_tree_index
*** 578,583 ****
--- 579,585 ----
      CPTI_DELTA2_IDENTIFIER,
      CPTI_DELTA_IDENTIFIER,
      CPTI_IN_CHARGE_IDENTIFIER,
+     CPTI_VTT_PARM_IDENTIFIER,
      CPTI_INDEX_IDENTIFIER,
      CPTI_NELTS_IDENTIFIER,
      CPTI_THIS_IDENTIFIER,
*************** extern tree cp_global_trees[CPTI_MAX];
*** 690,695 ****
--- 692,702 ----
  #define delta2_identifier               cp_global_trees[CPTI_DELTA2_IDENTIFIER]
  #define delta_identifier                cp_global_trees[CPTI_DELTA_IDENTIFIER]
  #define in_charge_identifier            cp_global_trees[CPTI_IN_CHARGE_IDENTIFIER]
+ 
+ /* The name of the parameter that contains a pointer to the VTT to use
+    for this subobject constructor or destructor.  */
+ #define vtt_parm_identifier             cp_global_trees[CPTI_VTT_PARM_IDENTIFIER]
+ 
  #define index_identifier                cp_global_trees[CPTI_INDEX_IDENTIFIER]
  #define nelts_identifier                cp_global_trees[CPTI_NELTS_IDENTIFIER]
  #define this_identifier                 cp_global_trees[CPTI_THIS_IDENTIFIER]
*************** extern tree cp_global_trees[CPTI_MAX];
*** 731,736 ****
--- 738,747 ----
  /* The type of a destructor.  */
  #define cleanup_type                    cp_global_trees[CPTI_CLEANUP_TYPE]
  
+ /* The type of the vtt parameter passed to subobject constructors and
+    destructors.  */
+ #define vtt_parm_type                   cp_global_trees[CPTI_VTT_PARM_TYPE]
+ 
  /* Global state.  */
  
  struct stmt_tree {
*************** struct lang_type
*** 1755,1760 ****
--- 1766,1779 ----
     is primary *somewhere* in the hierarchy.  */
  #define BINFO_VBASE_PRIMARY_P(NODE) TREE_LANG_FLAG_6 (NODE)
  
+ /* The index in the VTT where this subobject's sub-VTT can be found.
+    NULL_TREE if there is no sub-VTT.  */
+ #define BINFO_SUBVTT_INDEX(NODE) TREE_VEC_ELT ((NODE), 8)
+ 
+ /* The index in the VTT where the vptr for this subobject can be
+    found.  NULL_TREE if there is no secondary vptr in the VTT.  */
+ #define BINFO_VPTR_INDEX(NODE) TREE_VEC_ELT ((NODE), 9)
+ 
  /* Used by various search routines.  */
  #define IDENTIFIER_MARKED(NODE) TREE_LANG_FLAG_0 (NODE)
  
*************** struct lang_decl
*** 1884,1889 ****
--- 1903,1911 ----
    /* In a FUNCTION_DECL, this is DECL_CLONED_FUNCTION.  */
    tree cloned_function;
  
+   /* In a FUNCTION_DECL, this is VTT_PARM.  */
+   tree vtt_parm;
+ 
    union
    {
      tree sorted_fields;
*************** struct lang_decl
*** 1972,1977 ****
--- 1994,2018 ----
  #define DECL_CLONED_FUNCTION(NODE) \
    (DECL_LANG_SPECIFIC (NODE)->cloned_function)
  
+ /* In a maybe-in-charge constructor or destructor, this is the VTT
+    parameter.  It's not actually on the DECL_ARGUMENTS list.  */
+ #define DECL_VTT_PARM(NODE) \
+   (DECL_LANG_SPECIFIC (NODE)->vtt_parm)
+ 
+ /* If there's a DECL_VTT_PARM, this is a magic variable that indicates
+    whether or not the VTT parm should be used.  In a subobject
+    constructor, `true' is substituted for this value; in a complete
+    object constructor, `false' is substituted instead.  */
+ #define DECL_USE_VTT_PARM(NODE) \
+   (TREE_CHAIN (DECL_VTT_PARM (NODE)))
+ 
+ /* Non-zero if NODE is a FUNCTION_DECL for which a VTT parameter is
+    required.  */
+ #define DECL_NEEDS_VTT_PARM_P(NODE)			\
+   (TYPE_USES_VIRTUAL_BASECLASSES (DECL_CONTEXT (NODE))	\
+    && (DECL_BASE_CONSTRUCTOR_P (NODE)			\
+        || DECL_BASE_DESTRUCTOR_P (NODE)))
+ 
  /* Non-zero if NODE is a user-defined conversion operator.  */
  #define DECL_CONV_FN_P(NODE) \
    (IDENTIFIER_TYPENAME_P (DECL_NAME (NODE)))
*************** extern void maybe_note_name_used_in_clas
*** 3820,3825 ****
--- 3861,3867 ----
  extern void note_name_declared_in_class         PARAMS ((tree, tree));
  extern tree get_vtbl_decl_for_binfo             PARAMS ((tree));
  extern tree in_charge_arg_for_name              PARAMS ((tree));
+ extern tree get_vtt_name                        PARAMS ((tree));
  
  /* in cvt.c */
  extern tree convert_to_reference		PARAMS ((tree, tree, int, int, tree));
*************** extern void mark_used				PARAMS ((tree))
*** 4054,4059 ****
--- 4096,4102 ----
  extern tree handle_class_head			PARAMS ((tree, tree, tree));
  extern tree lookup_arg_dependent                PARAMS ((tree, tree, tree));
  extern void finish_static_data_member_decl      PARAMS ((tree, tree, tree, int));
+ extern tree build_artificial_parm               PARAMS ((tree, tree));
  
  /* in parse.y */
  extern void cp_parse_init			PARAMS ((void));
*************** extern tree lookup_nested_tag			PARAMS (
*** 4303,4309 ****
  extern tree get_matching_virtual		PARAMS ((tree, tree, int));
  extern void get_pure_virtuals		        PARAMS ((tree));
  extern tree init_vbase_pointers			PARAMS ((tree, tree));
- extern void expand_indirect_vtbls_init		PARAMS ((tree));
  extern void get_vbase_types			PARAMS ((tree));
  extern void maybe_suppress_debug_info		PARAMS ((tree));
  extern void note_debug_info_needed		PARAMS ((tree));
--- 4346,4351 ----
*************** extern tree unmarked_vtable_pathp       
*** 4340,4345 ****
--- 4382,4388 ----
  extern tree convert_pointer_to_vbase            PARAMS ((tree, tree));
  extern tree find_vbase_instance                 PARAMS ((tree, tree));
  extern tree binfo_for_vbase                     PARAMS ((tree, tree));
+ extern void fixup_all_virtual_upcast_offsets    PARAMS ((tree));
  
  /* in semantics.c */
  extern void finish_expr_stmt                    PARAMS ((tree));
Index: cp/decl.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cp/decl.c,v
retrieving revision 1.611
diff -c -p -r1.611 decl.c
*** decl.c	2000/05/24 22:56:53	1.611
--- decl.c	2000/05/25 23:15:03
*************** duplicate_decls (newdecl, olddecl)
*** 3369,3374 ****
--- 3369,3375 ----
        DECL_VIRTUAL_P (newdecl) |= DECL_VIRTUAL_P (olddecl);
        DECL_NEEDS_FINAL_OVERRIDER_P (newdecl) |= DECL_NEEDS_FINAL_OVERRIDER_P (olddecl);
        DECL_THIS_STATIC (newdecl) |= DECL_THIS_STATIC (olddecl);
+       DECL_VTT_PARM (newdecl) = DECL_VTT_PARM (olddecl);
        new_defines_function = DECL_INITIAL (newdecl) != NULL_TREE;
  
        /* Optionally warn about more than one declaration for the same
*************** initialize_predefined_identifiers () 
*** 6074,6079 ****
--- 6075,6081 ----
      { "__pfn_or_delta2", &pfn_or_delta2_identifier, 0 },
      { "_vptr", &vptr_identifier, 0 },
      { "__cp_push_exception", &cp_push_exception_identifier, 0 },
+     { "__vtt_parm", &vtt_parm_identifier, 0 },
      { NULL, NULL, 0 }
    };
  
*************** init_decl_processing ()
*** 6325,6330 ****
--- 6327,6333 ----
    const_ptr_type_node
      = build_pointer_type (build_qualified_type (void_type_node,
  						TYPE_QUAL_CONST));
+   vtt_parm_type = build_pointer_type (const_ptr_type_node);
    c_common_nodes_and_builtins (1, flag_no_builtin, flag_no_nonansi_builtin);
    lang_type_promotes_to = convert_type_from_ellipsis;
  
*************** grokfndecl (ctype, type, declarator, ori
*** 8740,8746 ****
        quals = NULL_TREE;
      }
  
!   if (IDENTIFIER_OPNAME_P (DECL_NAME (decl)))
      grok_op_properties (decl, virtualp, check < 0);
  
    if (ctype && decl_function_context (decl))
--- 8743,8749 ----
        quals = NULL_TREE;
      }
  
!   if (DECL_OVERLOADED_OPERATOR_P (decl))
      grok_op_properties (decl, virtualp, check < 0);
  
    if (ctype && decl_function_context (decl))
*************** lang_mark_tree (t)
*** 14744,14749 ****
--- 14747,14753 ----
  	      ggc_mark_tree (ld->befriending_classes);
  	      ggc_mark_tree (ld->saved_tree);
  	      ggc_mark_tree (ld->cloned_function);
+ 	      ggc_mark_tree (ld->vtt_parm);
  	      if (TREE_CODE (t) == TYPE_DECL)
  		ggc_mark_tree (ld->u.sorted_fields);
  	      else if (TREE_CODE (t) == FUNCTION_DECL
Index: cp/decl2.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cp/decl2.c,v
retrieving revision 1.353
diff -c -p -r1.353 decl2.c
*** decl2.c	2000/05/24 22:56:53	1.353
--- decl2.c	2000/05/25 23:15:06
*************** grok_x_components (specs)
*** 924,929 ****
--- 924,945 ----
        break;
  }
  
+ /* Returns a PARM_DECL for a parameter of the indicated TYPE, with the
+    indicated NAME.  */
+ 
+ tree
+ build_artificial_parm (name, type)
+      tree name;
+      tree type;
+ {
+   tree parm;
+ 
+   parm = build_decl (PARM_DECL, name, type);
+   SET_DECL_ARTIFICIAL (parm);
+   DECL_ARG_TYPE (parm) = type;
+   return parm;
+ }
+ 
  /* Constructors for types with virtual baseclasses need an "in-charge" flag
     saying whether this constructor is responsible for initialization of
     virtual baseclasses or not.  All destructors also need this "in-charge"
*************** maybe_retrofit_in_chrg (fn)
*** 956,965 ****
      return;
  
    /* First add it to DECL_ARGUMENTS...  */
!   parm = build_decl (PARM_DECL, in_charge_identifier, integer_type_node);
!   /* Mark the artificial `__in_chrg' parameter as "artificial".  */
!   SET_DECL_ARTIFICIAL (parm);
!   DECL_ARG_TYPE (parm) = integer_type_node;
    TREE_READONLY (parm) = 1;
    parms = DECL_ARGUMENTS (fn);
    TREE_CHAIN (parm) = TREE_CHAIN (parms);
--- 972,978 ----
      return;
  
    /* First add it to DECL_ARGUMENTS...  */
!   parm = build_artificial_parm (in_charge_identifier, integer_type_node);
    TREE_READONLY (parm) = 1;
    parms = DECL_ARGUMENTS (fn);
    TREE_CHAIN (parm) = TREE_CHAIN (parms);
*************** maybe_retrofit_in_chrg (fn)
*** 978,983 ****
--- 991,1008 ----
  
    /* Now we've got the in-charge parameter.  */
    DECL_HAS_IN_CHARGE_PARM_P (fn) = 1;
+ 
+   /* If this is a subobject constructor or destructor, our caller will
+      pass us a pointer to our VTT.  */
+   if (flag_new_abi && TYPE_USES_VIRTUAL_BASECLASSES (DECL_CONTEXT (fn)))
+     {
+       DECL_VTT_PARM (fn) = build_artificial_parm (vtt_parm_identifier, 
+ 						  vtt_parm_type);
+       DECL_CONTEXT (DECL_VTT_PARM (fn)) = fn;
+       DECL_USE_VTT_PARM (fn) = build_artificial_parm (NULL_TREE,
+ 						      boolean_type_node);
+       DECL_CONTEXT (DECL_USE_VTT_PARM (fn)) = fn;
+     }
  }
  
  /* Classes overload their constituent function names automatically.
*************** grokclassfn (ctype, function, flags, qua
*** 1032,1043 ****
  	 assigned to.  */
        this_quals |= TYPE_QUAL_CONST;
        qual_type = cp_build_qualified_type (type, this_quals);
!       parm = build_decl (PARM_DECL, this_identifier, qual_type);
        c_apply_type_quals_to_decl (this_quals, parm);
  
-       /* Mark the artificial `this' parameter as "artificial".  */
-       SET_DECL_ARTIFICIAL (parm);
-       DECL_ARG_TYPE (parm) = type;
        /* We can make this a register, so long as we don't
  	 accidentally complain if someone tries to take its address.  */
        DECL_REGISTER (parm) = 1;
--- 1057,1065 ----
  	 assigned to.  */
        this_quals |= TYPE_QUAL_CONST;
        qual_type = cp_build_qualified_type (type, this_quals);
!       parm = build_artificial_parm (this_identifier, qual_type);
        c_apply_type_quals_to_decl (this_quals, parm);
  
        /* We can make this a register, so long as we don't
  	 accidentally complain if someone tries to take its address.  */
        DECL_REGISTER (parm) = 1;
Index: cp/init.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cp/init.c,v
retrieving revision 1.193
diff -c -p -r1.193 init.c
*** init.c	2000/05/24 22:56:54	1.193
--- init.c	2000/05/25 23:15:08
*************** static tree build_new_1	PARAMS ((tree));
*** 53,58 ****
--- 53,59 ----
  static tree get_cookie_size PARAMS ((tree));
  static tree build_dtor_call PARAMS ((tree, special_function_kind, int));
  static tree build_field_list PARAMS ((tree, tree, int *));
+ static tree build_vtbl_address PARAMS ((tree));
  
  /* Set up local variable for this file.  MUST BE CALLED AFTER
     INIT_DECL_PROCESSING.  */
*************** initialize_vtbl_ptrs (addr)
*** 172,178 ****
  		 NULL, dfs_unmarked_real_bases_queue_p, list);
    dfs_walk (TYPE_BINFO (type), dfs_unmark,
  	    dfs_marked_real_bases_queue_p, type);
!   expand_indirect_vtbls_init (addr);
  }
  
  /* Subroutine of emit_base_init.  */
--- 173,186 ----
  		 NULL, dfs_unmarked_real_bases_queue_p, list);
    dfs_walk (TYPE_BINFO (type), dfs_unmark,
  	    dfs_marked_real_bases_queue_p, type);
! 
!   /* If we're not using thunks, we may need to adjust the deltas in
!      the vtable to handle virtual base classes correctly.  When we are
!      using thunks, we either use construction vtables (which are
!      preloaded with the right answers) or nothing (in which case
!      vitual function calls sometimes don't work right.)  */
!   if (TYPE_USES_VIRTUAL_BASECLASSES (type) && !flag_vtable_thunks)
!     fixup_all_virtual_upcast_offsets (addr);
  }
  
  /* Subroutine of emit_base_init.  */
*************** perform_member_init (member, init, expli
*** 276,282 ****
  
        expr = build_component_ref (current_class_ref, member, NULL_TREE,
  				  explicit);
!       expr = build_delete (type, expr, sfk_base_destructor,
  			   LOOKUP_NONVIRTUAL|LOOKUP_DESTRUCTOR, 0);
  
        if (expr != error_mark_node)
--- 284,290 ----
  
        expr = build_component_ref (current_class_ref, member, NULL_TREE,
  				  explicit);
!       expr = build_delete (type, expr, sfk_complete_destructor,
  			   LOOKUP_NONVIRTUAL|LOOKUP_DESTRUCTOR, 0);
  
        if (expr != error_mark_node)
*************** emit_base_init ()
*** 726,731 ****
--- 734,765 ----
      }
  }
  
+ /* Returns the address of the vtable (i.e., the value that should be
+    assigned to the vptr) for BINFO.  */
+ 
+ static tree
+ build_vtbl_address (binfo)
+      tree binfo;
+ {
+   tree vtbl;
+ 
+   /* Figure out what vtable BINFO's vtable is based on, and mark it as
+      used.  */
+   vtbl = get_vtbl_decl_for_binfo (binfo);
+   assemble_external (vtbl);
+   TREE_USED (vtbl) = 1;
+ 
+   /* Now compute the address to use when initializing the vptr.  */
+   vtbl = BINFO_VTABLE (binfo);
+   if (TREE_CODE (vtbl) == VAR_DECL)
+     {
+       vtbl = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (vtbl)), vtbl);
+       TREE_CONSTANT (vtbl) = 1;
+     }
+ 
+   return vtbl;
+ }
+ 
  /* This code sets up the virtual function tables appropriate for
     the pointer DECL.  It is a one-ply initialization.
  
*************** expand_virtual_init (binfo, decl)
*** 739,761 ****
    tree type = BINFO_TYPE (binfo);
    tree vtbl, vtbl_ptr;
    tree vtype, vtype_binfo;
!   tree b;
  
    /* Compute the location of the vtable.  */
    vtype = DECL_CONTEXT (TYPE_VFIELD (type));
    vtype_binfo = get_binfo (vtype, TREE_TYPE (TREE_TYPE (decl)), 0);
!   b = binfo_value (DECL_FIELD_CONTEXT (TYPE_VFIELD (type)), binfo);
! 
!   /* Figure out what vtable BINFO's vtable is based on, and mark it as
!      used.  */
!   vtbl = get_vtbl_decl_for_binfo (b);
!   assemble_external (vtbl);
!   TREE_USED (vtbl) = 1;
! 
!   /* Now compute the address to use when initializing the vptr.  */
!   vtbl = BINFO_VTABLE (b);
!   if (TREE_CODE (vtbl) == VAR_DECL)
!     vtbl = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (vtbl)), vtbl);
  
    /* Compute the location of the vtpr.  */
    decl = convert_pointer_to_real (vtype_binfo, decl);
--- 773,812 ----
    tree type = BINFO_TYPE (binfo);
    tree vtbl, vtbl_ptr;
    tree vtype, vtype_binfo;
!   tree vtt_index;
  
    /* Compute the location of the vtable.  */
    vtype = DECL_CONTEXT (TYPE_VFIELD (type));
    vtype_binfo = get_binfo (vtype, TREE_TYPE (TREE_TYPE (decl)), 0);
!   
!   /* Compute the initializer for vptr.  */
!   vtbl = build_vtbl_address (binfo);
! 
!   /* Under the new ABI, we may get this vptr from a VTT, if this is a
!      subobject constructor or subobject destructor.  */
!   vtt_index = BINFO_VPTR_INDEX (binfo);
!   if (vtt_index)
!     {
!       tree vtbl2;
!       tree vtt_parm;
! 
!       /* Compute the value to use, when there's a VTT.  */
!       vtt_parm = DECL_VTT_PARM (current_function_decl);
!       vtbl2 = build (PLUS_EXPR, 
! 		     TREE_TYPE (vtt_parm), 
! 		     vtt_parm,
! 		     vtt_index);
!       vtbl2 = build1 (INDIRECT_REF, TREE_TYPE (vtbl), vtbl2);
! 
!       /* The actual initializer is the VTT value only in the subobject
! 	 constructor.  In maybe_clone_body we'll substitute NULL for
! 	 the vtt_parm in the case of the non-subobject constructor.  */
!       vtbl = build (COND_EXPR, 
! 		    TREE_TYPE (vtbl), 
! 		    DECL_USE_VTT_PARM (current_function_decl),
! 		    vtbl2, 
! 		    vtbl);
!     }
  
    /* Compute the location of the vtpr.  */
    decl = convert_pointer_to_real (vtype_binfo, decl);
Index: cp/optimize.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cp/optimize.c,v
retrieving revision 1.33
diff -c -p -r1.33 optimize.c
*** optimize.c	2000/05/23 06:31:16	1.33
--- optimize.c	2000/05/25 23:15:08
*************** maybe_clone_body (fn)
*** 902,907 ****
--- 902,911 ----
        DECL_SOURCE_LINE (clone) = DECL_SOURCE_LINE (fn);
        DECL_INLINE (clone) = DECL_INLINE (fn);
        DECL_THIS_INLINE (clone) = DECL_THIS_INLINE (fn);
+       DECL_COMDAT (clone) = DECL_COMDAT (fn);
+       DECL_WEAK (clone) = DECL_WEAK (fn);
+       DECL_ONE_ONLY (clone) = DECL_ONE_ONLY (fn);
+       DECL_SECTION_NAME (clone) = DECL_SECTION_NAME (fn);
  
        /* Start processing the function.  */
        push_to_top_level ();
*************** maybe_clone_body (fn)
*** 934,940 ****
  	      in_charge = in_charge_arg_for_name (DECL_NAME (clone));
  	      splay_tree_insert (id.decl_map,
  				 (splay_tree_key) parm,
! 				 (splay_tree_key) in_charge);
  	    }
  	  /* Map other parameters to their equivalents in the cloned
  	     function.  */
--- 938,968 ----
  	      in_charge = in_charge_arg_for_name (DECL_NAME (clone));
  	      splay_tree_insert (id.decl_map,
  				 (splay_tree_key) parm,
! 				 (splay_tree_value) in_charge);
! 
! 	      /* For a subobject constructor or destructor, the next
! 		 argument is the VTT parameter.  Remap the VTT_PARM
! 		 from the CLONE to this parameter.  */
! 	      if (DECL_NEEDS_VTT_PARM_P (clone))
! 		{
! 		  splay_tree_insert (id.decl_map,
! 				     (splay_tree_key) DECL_VTT_PARM (fn),
! 				     (splay_tree_value) clone_parm);
! 		  splay_tree_insert (id.decl_map,
! 				     (splay_tree_key) DECL_USE_VTT_PARM (fn),
! 				     (splay_tree_value) boolean_true_node);
! 		  clone_parm = TREE_CHAIN (clone_parm);
! 		}
! 	      /* Otherwise, map the VTT parameter to `NULL'.  */
! 	      else if (DECL_VTT_PARM (fn))
! 		{
! 		  splay_tree_insert (id.decl_map,
! 				     (splay_tree_key) DECL_VTT_PARM (fn),
! 				     (splay_tree_value) null_pointer_node);
! 		  splay_tree_insert (id.decl_map,
! 				     (splay_tree_key) DECL_USE_VTT_PARM (fn),
! 				     (splay_tree_value) boolean_false_node);
! 		}
  	    }
  	  /* Map other parameters to their equivalents in the cloned
  	     function.  */
Index: cp/search.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cp/search.c,v
retrieving revision 1.180
diff -c -p -r1.180 search.c
*** search.c	2000/05/22 01:08:46	1.180
--- search.c	2000/05/25 23:15:10
*************** static int protected_accessible_p PARAMS
*** 144,150 ****
  static int friend_accessible_p PARAMS ((tree, tree, tree));
  static void setup_class_bindings PARAMS ((tree, int));
  static int template_self_reference_p PARAMS ((tree, tree));
- static void fixup_all_virtual_upcast_offsets PARAMS ((tree, tree));
  static tree get_shared_vbase_if_not_primary PARAMS ((tree, void *));
  static tree dfs_find_vbase_instance PARAMS ((tree, void *));
  static tree dfs_get_pure_virtuals PARAMS ((tree, void *));
--- 144,149 ----
*************** fixup_virtual_upcast_offsets (real_binfo
*** 2770,2783 ****
  /* Fixup all the virtual upcast offsets for TYPE.  DECL_PTR is the
     address of the sub-object being initialized.  */
  
! static void
! fixup_all_virtual_upcast_offsets (type, decl_ptr)
!      tree type;
       tree decl_ptr;
  {
    tree if_stmt;
    tree in_charge_node;
    tree vbases;
  
    /* Only tweak the vtables if we're in charge.  */
    in_charge_node = current_in_charge_parm;
--- 2769,2782 ----
  /* Fixup all the virtual upcast offsets for TYPE.  DECL_PTR is the
     address of the sub-object being initialized.  */
  
! void
! fixup_all_virtual_upcast_offsets (decl_ptr)
       tree decl_ptr;
  {
    tree if_stmt;
    tree in_charge_node;
    tree vbases;
+   tree type;
  
    /* Only tweak the vtables if we're in charge.  */
    in_charge_node = current_in_charge_parm;
*************** fixup_all_virtual_upcast_offsets (type, 
*** 2791,2796 ****
--- 2790,2796 ----
    
    /* Iterate through the virtual bases, fixing up the upcast offset
       for each one.  */
+   type = TREE_TYPE (TREE_TYPE (decl_ptr));
    for (vbases = CLASSTYPE_VBASECLASSES (type);
         vbases;
         vbases = TREE_CHAIN (vbases))
*************** fixup_all_virtual_upcast_offsets (type, 
*** 2818,2839 ****
    /* Close out the if-statement.  */
    finish_then_clause (if_stmt);
    finish_if_stmt ();
- }
- 
- /* Generate the code needed to initialize all the virtual function
-    table slots of all the virtual baseclasses.  ADDR points to the
-    address of the complete object we are initializing.  */
- 
- void
- expand_indirect_vtbls_init (addr)
-      tree addr;
- {
-   tree type;
- 
-   type = TREE_TYPE (TREE_TYPE (addr));
- 
-   if (TYPE_USES_VIRTUAL_BASECLASSES (type))
-     fixup_all_virtual_upcast_offsets (type, addr);
  }
  
  /* get virtual base class types.
--- 2818,2823 ----
Index: cp/semantics.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cp/semantics.c,v
retrieving revision 1.144
diff -c -p -r1.144 semantics.c
*** semantics.c	2000/05/24 18:48:08	1.144
--- semantics.c	2000/05/25 23:15:12
*************** setup_vtbl_ptr ()
*** 1257,1271 ****
        tree compound_stmt;
        int saved_cfnd;
  
!       /* If the dtor is empty, and we know there is not possible way we
! 	 could use any vtable entries, before they are possibly set by
! 	 a base class dtor, we don't have to setup the vtables, as we
! 	 know that any base class dtoring will set up any vtables it
! 	 needs.  We avoid MI, because one base class dtor can do a
  	 virtual dispatch to an overridden function that would need to
  	 have a non-related vtable set up, we cannot avoid setting up
! 	 vtables in that case.  We could change this to see if there is
! 	 just one vtable.  */
        if_stmt = begin_if_stmt ();
  
        /* If it is not safe to avoid setting up the vtables, then
--- 1257,1271 ----
        tree compound_stmt;
        int saved_cfnd;
  
!       /* If the dtor is empty, and we know there is not any possible
! 	 way we could use any vtable entries, before they are possibly
! 	 set by a base class dtor, we don't have to setup the vtables,
! 	 as we know that any base class dtor will set up any vtables
! 	 it needs.  We avoid MI, because one base class dtor can do a
  	 virtual dispatch to an overridden function that would need to
  	 have a non-related vtable set up, we cannot avoid setting up
! 	 vtables in that case.  We could change this to see if there
! 	 is just one vtable.  */
        if_stmt = begin_if_stmt ();
  
        /* If it is not safe to avoid setting up the vtables, then
Index: cp/tree.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cp/tree.c,v
retrieving revision 1.197
diff -c -p -r1.197 tree.c
*** tree.c	2000/05/09 19:55:51	1.197
--- tree.c	2000/05/25 23:15:13
*************** make_binfo (offset, binfo, vtable, virtu
*** 847,853 ****
       tree offset, binfo;
       tree vtable, virtuals;
  {
!   tree new_binfo = make_tree_vec (8);
    tree type;
  
    if (TREE_CODE (binfo) == TREE_VEC)
--- 847,853 ----
       tree offset, binfo;
       tree vtable, virtuals;
  {
!   tree new_binfo = make_tree_vec (10);
    tree type;
  
    if (TREE_CODE (binfo) == TREE_VEC)



Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]