diff options
| -rw-r--r-- | gcc/cp/ChangeLog | 15 | ||||
| -rw-r--r-- | gcc/cp/class.c | 122 | ||||
| -rw-r--r-- | gcc/cp/cp-tree.h | 2 | ||||
| -rw-r--r-- | gcc/testsuite/ChangeLog | 4 | ||||
| -rw-r--r-- | gcc/testsuite/g++.old-deja/g++.abi/vtable3.h | 12 | 
5 files changed, 106 insertions, 49 deletions
| diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 4b0b80b..2d7dace 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,18 @@ +2001-02-27  Nathan Sidwell  <nathan@codesourcery.com> + +	Fix ctor vtable vcall offsets. +	* class.c (struct vtbl_init_data_s): Add rtti_binfo member. +	(build_rtt_vtbl_entries): Lose RTTI_BINFO parameter. +	(get_matching_base): Remove. +	(get_original_base): New function. +	(build_vtbl_initializer): Initialize vid.rtti_binfo.  +	Use a virtual thunk for a ctor vtable with an index +	(add_vcall_offset_vtbl_entries_1): Check if binfo has lost a +	primary base within a constructor vtable. Only set +	BV_VCALL_INDEX when not a constructor vtable. Adjust vcall offset +	when primary base has been lost. +	* cp-tree.h (BINFO_VIRTUALS): Remove ambiguity from comment. +  2001-02-26  Jeffrey Oldham  <oldham@codesourcery.com>  	* call.c (joust): Ensure more_specialized()'s argument length diff --git a/gcc/cp/class.c b/gcc/cp/class.c index 2ba9e03..8af19c5 100644 --- a/gcc/cp/class.c +++ b/gcc/cp/class.c @@ -66,8 +66,11 @@ typedef struct vtbl_init_data_s  {    /* The base for which we're building initializers.  */    tree binfo; -  /* The binfo for the most-derived type.  */ +  /* The type of the most-derived type.  */    tree derived; +  /* The binfo for the dynamic type. This will be TYPE_BINFO (derived), +     unless ctor_vtbl_p is true.  */ +  tree rtti_binfo;    /* The negative-index vtable initializers built up so far.  These       are in order from least negative index to most negative index.  */    tree inits; @@ -182,7 +185,7 @@ static void accumulate_vtbl_inits PARAMS ((tree, tree, tree, tree, tree));  static tree dfs_accumulate_vtbl_inits PARAMS ((tree, tree, tree, tree,  					       tree));  static void set_vindex PARAMS ((tree, int *)); -static void build_rtti_vtbl_entries PARAMS ((tree, tree, vtbl_init_data *)); +static void build_rtti_vtbl_entries PARAMS ((tree, vtbl_init_data *));  static void build_vcall_and_vbase_vtbl_entries PARAMS ((tree,   							vtbl_init_data *));  static void force_canonical_binfo_r PARAMS ((tree, tree, tree, tree)); @@ -199,7 +202,7 @@ static tree *build_vtt_inits PARAMS ((tree, tree, tree *, tree *));  static tree dfs_build_secondary_vptr_vtt_inits PARAMS ((tree, void *));  static tree dfs_ctor_vtable_bases_queue_p PARAMS ((tree, void *data));  static tree dfs_fixup_binfo_vtbls PARAMS ((tree, void *)); -static tree get_matching_base PARAMS ((tree, tree)); +static tree get_original_base PARAMS ((tree, tree));  static tree dfs_get_primary_binfo PARAMS ((tree, void*));  static int record_subobject_offset PARAMS ((tree, tree, splay_tree));  static int check_subobject_offset PARAMS ((tree, tree, splay_tree)); @@ -6830,32 +6833,31 @@ build_vtt (t)    initialize_array (vtt, inits);  } -/* The type corresponding to BINFO is a base class of T, but BINFO is -   in the base class hierarchy of a class derived from T.  Return the -   base, in T's hierarchy, that corresponds to BINFO.  */ +/* The type corresponding to BASE_BINFO is a base of the type of BINFO, but +   from within some heirarchy which is inherited from the type of BINFO. +   Return BASE_BINFO's equivalent binfo from the hierarchy dominated by +   BINFO.  */  static tree -get_matching_base (binfo, t) +get_original_base (base_binfo, binfo) +     tree base_binfo;       tree binfo; -     tree t;  {    tree derived; -  int i; - -  if (same_type_p (BINFO_TYPE (binfo), t)) +  int ix; +   +  if (same_type_p (BINFO_TYPE (base_binfo), BINFO_TYPE (binfo)))      return binfo; - -  if (TREE_VIA_VIRTUAL (binfo)) -    return binfo_for_vbase (BINFO_TYPE (binfo), t); - -  derived = get_matching_base (BINFO_INHERITANCE_CHAIN (binfo), t); -  for (i = 0; i < BINFO_N_BASETYPES (derived); ++i) -    if (same_type_p (BINFO_TYPE (BINFO_BASETYPE (derived, i)), -		     BINFO_TYPE (binfo))) -      return BINFO_BASETYPE (derived, i); - -  my_friendly_abort (20000628); -  return NULL_TREE; +  if (TREE_VIA_VIRTUAL (base_binfo)) +    return binfo_for_vbase (BINFO_TYPE (base_binfo), BINFO_TYPE (binfo)); +  derived = get_original_base (BINFO_INHERITANCE_CHAIN (base_binfo), binfo); +   +  for (ix = 0; ix != BINFO_N_BASETYPES (derived); ix++) +    if (same_type_p (BINFO_TYPE (base_binfo), +                     BINFO_TYPE (BINFO_BASETYPE (derived, ix)))) +      return BINFO_BASETYPE (derived, ix); +  my_friendly_abort (20010223); +  return NULL;  }  /* Recursively build the VTT-initializer for BINFO (which is in the @@ -7347,6 +7349,7 @@ build_vtbl_initializer (binfo, orig_binfo, t, rtti_binfo, non_fn_entries_p)    memset (&vid, 0, sizeof (vid));    vid.binfo = binfo;    vid.derived = t; +  vid.rtti_binfo = rtti_binfo;    vid.last_init = &vid.inits;    vid.primary_vtbl_p = (binfo == TYPE_BINFO (t));    vid.ctor_vtbl_p = !same_type_p (BINFO_TYPE (rtti_binfo), t); @@ -7354,7 +7357,7 @@ build_vtbl_initializer (binfo, orig_binfo, t, rtti_binfo, non_fn_entries_p)    vid.index = ssize_int (-3);    /* Add entries to the vtable for RTTI.  */ -  build_rtti_vtbl_entries (binfo, rtti_binfo, &vid); +  build_rtti_vtbl_entries (binfo, &vid);    /* Create an array for keeping track of the functions we've       processed.  When we see multiple functions with the same @@ -7384,7 +7387,8 @@ build_vtbl_initializer (binfo, orig_binfo, t, rtti_binfo, non_fn_entries_p)        tree fn;        tree pfn;        tree init; - +      int generate_with_vtable_p = BV_GENERATE_THUNK_WITH_VTABLE_P (v); +              /* Pull the offset for `this', and the function to call, out of  	 the list.  */        delta = BV_DELTA (v); @@ -7394,8 +7398,17 @@ build_vtbl_initializer (binfo, orig_binfo, t, rtti_binfo, non_fn_entries_p)  	  vcall_index = BV_VCALL_INDEX (v);  	  my_friendly_assert (vcall_index != NULL_TREE, 20000621);  	} +      else if (vid.ctor_vtbl_p && BV_VCALL_INDEX (v)) +        { +          /* In the original, we did not need to use the vcall index, even +             though there was one, but in a ctor vtable things might be +             different (a primary virtual base might have moved). Be +             conservative and use a vcall adjusting thunk.  */ +	  vcall_index = BV_VCALL_INDEX (v); +          generate_with_vtable_p = 1; +        }        else -	vcall_index = NULL_TREE; +        vcall_index = NULL_TREE;        fn = BV_FN (v);        my_friendly_assert (TREE_CODE (delta) == INTEGER_CST, 19990727); @@ -7413,7 +7426,7 @@ build_vtbl_initializer (binfo, orig_binfo, t, rtti_binfo, non_fn_entries_p)        TREE_CONSTANT (pfn) = 1;        /* Enter it in the vtable.  */        init = build_vtable_entry (delta, vcall_index, pfn, -				 BV_GENERATE_THUNK_WITH_VTABLE_P (v)); +				 generate_with_vtable_p);        /* And add it to the chain of initializers.  */        vfun_inits = tree_cons (NULL_TREE, init, vfun_inits);      } @@ -7624,6 +7637,7 @@ add_vcall_offset_vtbl_entries_1 (binfo, vid)    tree base_virtuals;    tree orig_virtuals;    tree binfo_inits; +  int lost_primary = 0;    /* If BINFO is a primary base, this is the least derived class of       BINFO that is not a primary base.  */    tree non_primary_binfo; @@ -7645,6 +7659,21 @@ add_vcall_offset_vtbl_entries_1 (binfo, vid)  	 care about its vtable offsets.  */        if (TREE_VIA_VIRTUAL (non_primary_binfo))  	{ +	  if (vid->ctor_vtbl_p) +	    { +    	      tree probe; +	   +	      for (probe = vid->binfo; +	           probe != non_primary_binfo; +	           probe = get_primary_binfo (probe)) +	        { +                  if (BINFO_LOST_PRIMARY_P (probe)) +                    { +                      lost_primary = 1; +                      break; +                    } +	        } +            }  	  non_primary_binfo = vid->binfo;  	  break;  	} @@ -7655,6 +7684,12 @@ add_vcall_offset_vtbl_entries_1 (binfo, vid)        non_primary_binfo = b;      } +  if (vid->ctor_vtbl_p) +    /* For a ctor vtable we need the equivalent binfo within the hierarchy +       where rtti_binfo is the most derived type.  */ +    non_primary_binfo = get_original_base +          (non_primary_binfo, TYPE_BINFO (BINFO_TYPE (vid->rtti_binfo))); +    /* Make entries for the rest of the virtuals.  */    for (base_virtuals = BINFO_VIRTUALS (binfo),  	 derived_virtuals = BINFO_VIRTUALS (non_primary_binfo), @@ -7669,6 +7704,7 @@ add_vcall_offset_vtbl_entries_1 (binfo, vid)        tree base;        tree base_binfo;        size_t i; +      tree vcall_offset;        /* Find the declaration that originally caused this function to  	 be present.  */ @@ -7699,8 +7735,9 @@ add_vcall_offset_vtbl_entries_1 (binfo, vid)  	      || (DECL_DESTRUCTOR_P (BV_FN (derived_entry))  		  && DECL_DESTRUCTOR_P (fn)))  	    { -	      BV_VCALL_INDEX (derived_virtuals)  -		= BV_VCALL_INDEX (derived_entry); +	      if (!vid->ctor_vtbl_p) +  	        BV_VCALL_INDEX (derived_virtuals)  +		  = BV_VCALL_INDEX (derived_entry);  	      break;  	    }  	} @@ -7713,12 +7750,16 @@ add_vcall_offset_vtbl_entries_1 (binfo, vid)        base_binfo = get_binfo (base, vid->derived, /*protect=*/0);        /* Compute the vcall offset.  */ -      *vid->last_init  -	= (build_tree_list  -	   (NULL_TREE, -	    fold (build1 (NOP_EXPR, vtable_entry_type, -			  size_diffop (BINFO_OFFSET (base_binfo), -				       BINFO_OFFSET (vid->vbase)))))); +      vcall_offset = BINFO_OFFSET (vid->vbase); +      if (lost_primary) +        vcall_offset = size_binop (PLUS_EXPR, vcall_offset, +                                   BINFO_OFFSET (vid->binfo)); +      vcall_offset = size_diffop (BINFO_OFFSET (base_binfo), +		                  vcall_offset); +      vcall_offset = fold (build1 (NOP_EXPR, vtable_entry_type, +    			           vcall_offset)); +       +      *vid->last_init = build_tree_list (NULL_TREE, vcall_offset);        vid->last_init = &TREE_CHAIN (*vid->last_init);        /* Keep track of the vtable index where this vcall offset can be @@ -7738,12 +7779,11 @@ add_vcall_offset_vtbl_entries_1 (binfo, vid)  /* Return vtbl initializers for the RTTI entries coresponding to the     BINFO's vtable.  The RTTI entries should indicate the object given -   by RTTI_BINFO.  */ +   by VID->rtti_binfo.  */  static void -build_rtti_vtbl_entries (binfo, rtti_binfo, vid) +build_rtti_vtbl_entries (binfo, vid)       tree binfo; -     tree rtti_binfo;       vtbl_init_data *vid;  {    tree b; @@ -7754,7 +7794,7 @@ build_rtti_vtbl_entries (binfo, rtti_binfo, vid)    tree init;    basetype = BINFO_TYPE (binfo); -  t = BINFO_TYPE (rtti_binfo); +  t = BINFO_TYPE (vid->rtti_binfo);    /* For a COM object there is no RTTI entry.  */    if (CLASSTYPE_COM_INTERFACE (basetype)) @@ -7772,7 +7812,7 @@ build_rtti_vtbl_entries (binfo, rtti_binfo, vid)        my_friendly_assert (BINFO_PRIMARY_BASE_OF (primary_base) == b, 20010127);        b = primary_base;      } -  offset = size_diffop (BINFO_OFFSET (rtti_binfo), BINFO_OFFSET (b)); +  offset = size_diffop (BINFO_OFFSET (vid->rtti_binfo), BINFO_OFFSET (b));    /* The second entry is the address of the typeinfo object.  */    if (flag_rtti) @@ -7802,7 +7842,7 @@ build_rtti_vtbl_entries (binfo, rtti_binfo, vid)  /* Build an entry in the virtual function table.  DELTA is the offset     for the `this' pointer.  VCALL_INDEX is the vtable index containing -   the vcall offset; zero if none.  ENTRY is the virtual function +   the vcall offset; NULL_TREE if none.  ENTRY is the virtual function     table entry itself.  It's TREE_TYPE must be VFUNC_PTR_TYPE_NODE,     but it may not actually be a virtual function table pointer.  (For     example, it might be the address of the RTTI object, under the new diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 2aca7d1..7459c06 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -136,7 +136,7 @@ Boston, MA 02111-1307, USA.  */       does not have a BV_FN; it is just an offset.       The BV_OVERRIDING_BASE is the binfo for the final overrider for -     this function.  (This binfo's BINFO_TYPE will always be the same +     this function.  (That binfo's BINFO_TYPE will always be the same       as the DECL_CLASS_CONTEXT for the function.)     BINFO_VTABLE diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 26dbca4..9a6eaf7 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2001-02-27  Nathan Sidwell  <nathan@codesourcery.com> + +	* g++.old-deja/g++.abi/vtable3.h: Check vcall offsets too. +  2001-02-26  Will Cohen  <wcohen@redhat.com>  	* gcc.c-torture/execute/ieee/20010226-1.c: New test. diff --git a/gcc/testsuite/g++.old-deja/g++.abi/vtable3.h b/gcc/testsuite/g++.old-deja/g++.abi/vtable3.h index 327d346..4327b5f 100644 --- a/gcc/testsuite/g++.old-deja/g++.abi/vtable3.h +++ b/gcc/testsuite/g++.old-deja/g++.abi/vtable3.h @@ -7,11 +7,8 @@  #include <typeinfo>  #include <stdio.h> -// XXX. vcall offsets are still broken, remove this define to re-enable -// testing when fixed. -#define NO_VCALL_TEST -  int fail; +struct A;  template <typename BASE, typename DERIVED>  int Test (DERIVED *d, int expect) @@ -19,6 +16,7 @@ int Test (DERIVED *d, int expect)    BASE *b = static_cast <BASE *> (d);    void *full_b = dynamic_cast <void *> (b);    void *full_d = dynamic_cast <void *> (d); +  A *ap = static_cast <A *> (b);    if (full_b != full_d)      { @@ -37,8 +35,8 @@ int Test (DERIVED *d, int expect)                typeid (BASE).name (), typeid (DERIVED).name ());        return 1;      } -#ifndef NO_VCALL_TEST -  b->Baz (static_cast <void *> (b)); + +  b->Baz (static_cast <void *> (ap));    int res = b->Foo (static_cast <void *> (d)); @@ -49,7 +47,7 @@ int Test (DERIVED *d, int expect)                typeid (BASE).name (), res, expect);        return 1;      } -#endif +    return 0;  } | 
