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


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

PATCH for virtual functions/templates



When handling the following test-case, we generated a bad virtual
function table for C<int*>.  This bug only triggers when the vtables
are processed in a particularly nasty order.

The underlying reason for this bug is that BINFO_VIRTUALS was a
less-than-ideal data structure.  We were trying to share tree
structure between virtual function tables and BINFO_VIRTUALS, and then
copy it when necessary.  That was error prone (this is not the first
bug we've seen in this area), and besides it's just plain ugly to
figure out what your virtual functions are by peeking inside your
vtable initializer and deciphering a bunch of gunk.

This patch cleans up the data structure issues (thereby fixing the
test-case), and adds some asserts to catch problems at compile-time.

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

Index: testsuite/g++.old-deja/g++.pt/virtual4.C
===================================================================
RCS file: virtual4.C
diff -N virtual4.C
*** /dev/null	Sat Dec  5 20:30:03 1998
--- virtual4.C	Tue Jul 27 11:06:50 1999
***************
*** 0 ****
--- 1,40 ----
+ // Origin: Mark Mitchell <mark@codesourcery.com>
+ 
+ struct B 
+ {
+   B ();
+   virtual void f () = 0;
+ };
+ 
+ B::B () 
+ {
+ }
+ 
+ extern B* bp;
+ 
+ template <class T>
+ struct C : public B
+ {
+   virtual void f () 
+     {
+     }
+ };
+ 
+ template <class T>
+ struct D : public B
+ {
+   virtual void f () 
+     {
+       bp = new C<T*>;
+     }
+ };
+ 
+ B* bp = new D<int>;
+ 
+ int main ()
+ {
+   bp->f ();
+   bp->f ();
+ }
+ 
+ 
Index: cp/class.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/class.c,v
retrieving revision 1.167
diff -c -p -r1.167 class.c
*** class.c	1999/07/26 08:18:12	1.167
--- class.c	1999/07/27 18:07:06
*************** static void mark_overriders PROTO((tree,
*** 121,132 ****
  static void check_for_override PROTO((tree, tree));
  static tree get_class_offset_1 PROTO((tree, tree, tree, tree, tree));
  static tree get_class_offset PROTO((tree, tree, tree, tree));
! static void modify_one_vtable PROTO((tree, tree, tree, tree));
! static void modify_all_vtables PROTO((tree, tree, tree));
! static void modify_all_direct_vtables PROTO((tree, int, tree, tree,
! 					     tree));
! static void modify_all_indirect_vtables PROTO((tree, int, int, tree,
! 					       tree, tree));
  static int finish_base_struct PROTO((tree, struct base_info *));
  static void finish_struct_methods PROTO((tree));
  static void maybe_warn_about_overly_private_class PROTO ((tree));
--- 121,130 ----
  static void check_for_override PROTO((tree, tree));
  static tree get_class_offset_1 PROTO((tree, tree, tree, tree, tree));
  static tree get_class_offset PROTO((tree, tree, tree, tree));
! static void modify_one_vtable PROTO((tree, tree, tree));
! static void modify_all_vtables PROTO((tree, tree));
! static void modify_all_direct_vtables PROTO((tree, int, tree, tree));
! static void modify_all_indirect_vtables PROTO((tree, int, int, tree, tree));
  static int finish_base_struct PROTO((tree, struct base_info *));
  static void finish_struct_methods PROTO((tree));
  static void maybe_warn_about_overly_private_class PROTO ((tree));
*************** static tree fixed_type_or_null PROTO((tr
*** 139,144 ****
--- 137,144 ----
  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));
  
  /* Way of stacking language names.  */
  tree *current_lang_base, *current_lang_stack;
*************** build_vtable_entry (delta, pfn)
*** 466,471 ****
--- 466,490 ----
      }
  }
  
+ /* Build a vtable entry for FNDECL.  DELTA is the amount by which we
+    must adjust the this pointer when calling F.  */
+ 
+ static tree
+ build_vtable_entry_for_fn (delta, fndecl)
+      tree delta;
+      tree fndecl;
+ {
+   tree pfn;
+ 
+   /* Take the address of the function, considering it to be of an
+      appropriate generic type.  */
+   pfn = build1 (ADDR_EXPR, vfunc_ptr_type_node, fndecl);
+   /* The address of a function can't change.  */
+   TREE_CONSTANT (pfn) = 1;
+   /* Now build the vtable entry itself.  */
+   return build_vtable_entry (delta, pfn);
+ }
+ 
  /* We want to give the assembler the vtable identifier as well as
     the offset to the function pointer.  So we generate
  
*************** static void
*** 669,698 ****
  set_rtti_entry (virtuals, offset, type)
       tree virtuals, offset, type;
  {
!   tree vfn;
  
    if (CLASSTYPE_COM_INTERFACE (type))
      return;
  
    if (flag_rtti)
!     vfn = build1 (ADDR_EXPR, vfunc_ptr_type_node, get_tinfo_fn (type));
    else
!     vfn = build1 (NOP_EXPR, vfunc_ptr_type_node, size_zero_node);
!   TREE_CONSTANT (vfn) = 1;
  
!   if (! flag_vtable_thunks)
!     TREE_VALUE (virtuals) = build_vtable_entry (offset, vfn);
!   else
      {
!       tree voff = build1 (NOP_EXPR, vfunc_ptr_type_node, offset);
!       TREE_CONSTANT (voff) = 1;
! 
!       TREE_VALUE (virtuals) = build_vtable_entry (integer_zero_node, voff);
  
!       /* The second slot is for the tdesc pointer when thunks are used.  */
!       TREE_VALUE (TREE_CHAIN (virtuals))
! 	= build_vtable_entry (integer_zero_node, vfn);
      }
  }
  
  /* Build a virtual function for type TYPE.
--- 688,721 ----
  set_rtti_entry (virtuals, offset, type)
       tree virtuals, offset, type;
  {
!   tree fn;
  
    if (CLASSTYPE_COM_INTERFACE (type))
      return;
  
    if (flag_rtti)
!     fn = get_tinfo_fn (type);
    else
!     /* If someone tries to get RTTI information for a type compiled
!        without RTTI, they're out of luck.  By calling __pure_virtual
!        in this case, we give a small clue as to what went wrong.  We
!        could consider having a __no_typeinfo function as well, for a
!        more specific hint.  */
!     fn = abort_fndecl;
  
!   if (flag_vtable_thunks)
      {
!       /* The first slot holds the offset.  */
!       TREE_PURPOSE (virtuals) = offset;
  
!       /* The next node holds the function.  */
!       virtuals = TREE_CHAIN (virtuals);
!       offset = integer_zero_node;
      }
+ 
+   /* This slot holds the function to call.  */
+   TREE_PURPOSE (virtuals) = offset;
+   TREE_VALUE (virtuals) = fn;
  }
  
  /* Build a virtual function for type TYPE.
*************** get_vtable_entry (virtuals, base_fndecl)
*** 951,976 ****
    return virtuals;
  }
  #endif
- 
- /* Put new entry ENTRY into virtual function table initializer
-    VIRTUALS.
  
!    Also update DECL_VINDEX (FNDECL).  */
  
  static void
! modify_vtable_entry (old_entry_in_list, new_entry, fndecl)
!      tree old_entry_in_list, new_entry, fndecl;
  {
!   tree base_fndecl = TREE_OPERAND (FNADDR_FROM_VTABLE_ENTRY (TREE_VALUE (old_entry_in_list)), 0);
  
! #ifdef NOTQUITE
!   cp_warning ("replaced %D with %D", DECL_ASSEMBLER_NAME (base_fndecl),
! 	      DECL_ASSEMBLER_NAME (fndecl));
! #endif
!   TREE_VALUE (old_entry_in_list) = new_entry;
  
!   /* Now assign virtual dispatch information, if unset.  */
!   /* We can dispatch this, through any overridden base function.  */
    if (TREE_CODE (DECL_VINDEX (fndecl)) != INTEGER_CST)
      {
        DECL_VINDEX (fndecl) = DECL_VINDEX (base_fndecl);
--- 974,995 ----
    return virtuals;
  }
  #endif
  
! /* Change the offset for the FNDECL entry to NEW_OFFSET.  Also update
!    DECL_VINDEX (FNDECL).  */
  
  static void
! modify_vtable_entry (old_entry_in_list, new_offset, fndecl)
!      tree old_entry_in_list, new_offset, fndecl;
  {
!   tree base_fndecl = TREE_VALUE (old_entry_in_list);
  
!   /* Update the entry.  */
!   TREE_PURPOSE (old_entry_in_list) = new_offset;
!   TREE_VALUE (old_entry_in_list) = fndecl;
  
!   /* Now assign virtual dispatch information, if unset.  We can
!      dispatch this, through any overridden base function.  */
    if (TREE_CODE (DECL_VINDEX (fndecl)) != INTEGER_CST)
      {
        DECL_VINDEX (fndecl) = DECL_VINDEX (base_fndecl);
*************** add_virtual_function (pv, phv, has_virtu
*** 1012,1022 ****
    tree pending_virtuals = *pv;
    tree pending_hard_virtuals = *phv;
  
-   /* FUNCTION_TYPEs and OFFSET_TYPEs no longer freely
-      convert to void *.  Make such a conversion here.  */
-   tree vfn = build1 (ADDR_EXPR, vfunc_ptr_type_node, fndecl);
-   TREE_CONSTANT (vfn) = 1;
- 
  #ifndef DUMB_USER
    if (current_class_type == 0)
      cp_warning ("internal problem, current_class_type is zero when adding `%D', please report",
--- 1031,1036 ----
*************** add_virtual_function (pv, phv, has_virtu
*** 1032,1039 ****
       to hold that entry.  */
    if (DECL_VINDEX (fndecl) == error_mark_node)
      {
-       tree entry;
- 
        /* We remember that this was the base sub-object for rtti.  */
        CLASSTYPE_RTTI (t) = t;
  
--- 1046,1051 ----
*************** add_virtual_function (pv, phv, has_virtu
*** 1068,1075 ****
  	DECL_VINDEX (fndecl) = idx;
  	DECL_CONTEXT (fndecl) = t;
        }
!       entry = build_vtable_entry (integer_zero_node, vfn);
!       pending_virtuals = tree_cons (DECL_VINDEX (fndecl), entry, pending_virtuals);
      }
    /* Might already be INTEGER_CST if declared twice in class.  We will
       give error later or we've already given it.  */
--- 1080,1089 ----
  	DECL_VINDEX (fndecl) = idx;
  	DECL_CONTEXT (fndecl) = t;
        }
!       /* Save the state we've computed on the PENDING_VIRTUALS list.  */
!       pending_virtuals = tree_cons (integer_zero_node,
! 				    fndecl,
! 				    pending_virtuals);
      }
    /* Might already be INTEGER_CST if declared twice in class.  We will
       give error later or we've already given it.  */
*************** add_virtual_function (pv, phv, has_virtu
*** 1077,1083 ****
      {
        /* Need an entry in some other virtual function table.
           Deal with this after we have laid out our virtual base classes.  */
!       pending_hard_virtuals = temp_tree_cons (fndecl, vfn, pending_hard_virtuals);
      }
    *pv = pending_virtuals;
    *phv = pending_hard_virtuals;
--- 1091,1099 ----
      {
        /* Need an entry in some other virtual function table.
           Deal with this after we have laid out our virtual base classes.  */
!       pending_hard_virtuals = temp_tree_cons (NULL_TREE, 
! 					      fndecl, 
! 					      pending_hard_virtuals);
      }
    *pv = pending_virtuals;
    *phv = pending_hard_virtuals;
*************** duplicate_tag_error (t)
*** 2207,2212 ****
--- 2223,2300 ----
    TYPE_NONCOPIED_PARTS (t) = NULL_TREE;
  }
  
+ /* Construct the initializer for BINFOs virtual function table.  */
+ 
+ static tree
+ build_vtbl_initializer (binfo)
+      tree binfo;
+ {
+   tree v = BINFO_VIRTUALS (binfo);
+   tree inits = NULL_TREE;
+ 
+   /* 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
+      function, and we can process it just like the other virtual
+      function entries.  */
+   if (!CLASSTYPE_COM_INTERFACE (BINFO_TYPE (binfo))
+       && flag_vtable_thunks)
+     {
+       tree offset;
+       tree init;
+ 
+       /* The first entry is an offset.  */
+       offset = TREE_PURPOSE (v);
+       my_friendly_assert (TREE_CODE (offset) == INTEGER_CST,
+ 			  19990727);
+ 
+       /* Convert the offset to look like a function pointer, so that
+ 	 we can put it in the vtable.  */
+       init = build1 (NOP_EXPR, vfunc_ptr_type_node, offset);
+       TREE_CONSTANT (init) = 1;
+       init = build_vtable_entry (integer_zero_node, init);
+       inits = tree_cons (NULL_TREE, init, inits);
+ 
+       /* Even in this case, the second entry (the tdesc pointer) is
+ 	 just an ordinary function.  */
+       v = TREE_CHAIN (v);
+     }
+ 
+   /* Go through all the ordinary virtual functions, building up
+      initializers.  */
+   while (v)
+     {
+       tree delta;
+       tree fn;
+       tree init;
+ 
+       /* Pull the offset for `this', and the function to call, out of
+ 	 the list.  */
+       delta = TREE_PURPOSE (v);
+       fn = TREE_VALUE (v);
+       my_friendly_assert (TREE_CODE (delta) == INTEGER_CST, 19990727);
+       my_friendly_assert (TREE_CODE (fn) == FUNCTION_DECL, 19990727);
+ 
+       /* You can't call an abstract virtual function; it's abstract.
+ 	 So, we replace these functions with __pure_virtual.  */
+       if (DECL_ABSTRACT_VIRTUAL_P (fn))
+ 	fn = abort_fndecl;
+ 
+       /* Package up that information for the vtable.  */
+       init = build_vtable_entry_for_fn (delta, fn);
+       /* And add it to the chain of initializers.  */
+       inits = tree_cons (NULL_TREE, init, inits);
+ 
+       /* Keep going.  */
+       v = TREE_CHAIN (v);
+     }
+ 
+   /* The initializers were built up in reverse order; straighten them
+      out now.  */
+   inits = nreverse (inits);
+   /* Package all the initializers up as an array initializer.  */
+   return build_nt (CONSTRUCTOR, NULL_TREE, inits);
+ }
+ 
  /* finish up all new vtables.  */
  
  static void
*************** finish_vtbls (binfo, do_self, t)
*** 2228,2241 ****
  	  decl = BINFO_VTABLE (binfo);
  	  context = DECL_CONTEXT (decl);
  	  DECL_CONTEXT (decl) = 0;
! 
! 	  /* We make a copy here in case we need to replace pure
! 	     virtual functions with __pure_virtual.  We don't want to
! 	     mess up BINFO_VIRTUALS when we do this.  */
! 	  DECL_INITIAL (decl) = copy_list (BINFO_VIRTUALS (binfo));
! 	  DECL_INITIAL (decl) = build_nt (CONSTRUCTOR, NULL_TREE,
! 					  DECL_INITIAL (decl));
! 
  	  cp_finish_decl (decl, DECL_INITIAL (decl), NULL_TREE, 0, 0);
  	  DECL_CONTEXT (decl) = context;
  	}
--- 2316,2322 ----
  	  decl = BINFO_VTABLE (binfo);
  	  context = DECL_CONTEXT (decl);
  	  DECL_CONTEXT (decl) = 0;
! 	  DECL_INITIAL (decl) = build_vtbl_initializer (binfo);
  	  cp_finish_decl (decl, DECL_INITIAL (decl), NULL_TREE, 0, 0);
  	  DECL_CONTEXT (decl) = context;
  	}
*************** finish_vtbls (binfo, do_self, t)
*** 2248,2256 ****
        int is_not_base_vtable
  	= i != CLASSTYPE_VFIELD_PARENT (BINFO_TYPE (binfo));
        if (TREE_VIA_VIRTUAL (base_binfo))
! 	{
! 	  base_binfo = binfo_member (BINFO_TYPE (base_binfo), CLASSTYPE_VBASECLASSES (t));
! 	}
        finish_vtbls (base_binfo, is_not_base_vtable, t);
      }
  }
--- 2329,2336 ----
        int is_not_base_vtable
  	= i != CLASSTYPE_VFIELD_PARENT (BINFO_TYPE (binfo));
        if (TREE_VIA_VIRTUAL (base_binfo))
! 	base_binfo = binfo_member (BINFO_TYPE (base_binfo), 
! 				   CLASSTYPE_VBASECLASSES (t));
        finish_vtbls (base_binfo, is_not_base_vtable, t);
      }
  }
*************** skip_rtti_stuff (virtuals, t)
*** 2396,2403 ****
  }
  
  static void
! modify_one_vtable (binfo, t, fndecl, pfn)
!      tree binfo, t, fndecl, pfn;
  {
    tree virtuals = BINFO_VIRTUALS (binfo);
    unsigned HOST_WIDE_INT n;
--- 2476,2483 ----
  }
  
  static void
! modify_one_vtable (binfo, t, fndecl)
!      tree binfo, t, fndecl;
  {
    tree virtuals = BINFO_VIRTUALS (binfo);
    unsigned HOST_WIDE_INT n;
*************** modify_one_vtable (binfo, t, fndecl, pfn
*** 2424,2431 ****
    while (virtuals)
      {
        tree current_fndecl = TREE_VALUE (virtuals);
!       current_fndecl = FNADDR_FROM_VTABLE_ENTRY (current_fndecl);
!       current_fndecl = TREE_OPERAND (current_fndecl, 0);
        if (current_fndecl && overrides (fndecl, current_fndecl))
  	{
  	  tree base_offset, offset;
--- 2504,2517 ----
    while (virtuals)
      {
        tree current_fndecl = TREE_VALUE (virtuals);
! 
!       /* We should never have an instance of __pure_virtual on the
! 	 BINFO_VIRTUALS list.  If we do, then we will never notice
! 	 that the function that should have been there instead has
! 	 been overridden.  */
!       my_friendly_assert (current_fndecl != abort_fndecl,
! 			  19990727);
! 
        if (current_fndecl && overrides (fndecl, current_fndecl))
  	{
  	  tree base_offset, offset;
*************** modify_one_vtable (binfo, t, fndecl, pfn
*** 2469,2475 ****
  	  cp_warning ("in %D", DECL_NAME (BINFO_VTABLE (binfo)));
  #endif
  	  modify_vtable_entry (get_vtable_entry_n (BINFO_VIRTUALS (binfo), n),
! 			       build_vtable_entry (this_offset, pfn),
  			       fndecl);
  	}
        ++n;
--- 2555,2561 ----
  	  cp_warning ("in %D", DECL_NAME (BINFO_VTABLE (binfo)));
  #endif
  	  modify_vtable_entry (get_vtable_entry_n (BINFO_VIRTUALS (binfo), n),
! 			       this_offset,
  			       fndecl);
  	}
        ++n;
*************** modify_one_vtable (binfo, t, fndecl, pfn
*** 2480,2498 ****
  /* These are the ones that are not through virtual base classes.  */
  
  static void
! modify_all_direct_vtables (binfo, do_self, t, fndecl, pfn)
       tree binfo;
       int do_self;
!      tree t, fndecl, pfn;
  {
    tree binfos = BINFO_BASETYPES (binfo);
    int i, n_baselinks = binfos ? TREE_VEC_LENGTH (binfos) : 0;
  
    /* Should we use something besides CLASSTYPE_VFIELDS? */
    if (do_self && CLASSTYPE_VFIELDS (BINFO_TYPE (binfo)))
!     {
!       modify_one_vtable (binfo, t, fndecl, pfn);
!     }
  
    for (i = 0; i < n_baselinks; i++)
      {
--- 2566,2582 ----
  /* These are the ones that are not through virtual base classes.  */
  
  static void
! modify_all_direct_vtables (binfo, do_self, t, fndecl)
       tree binfo;
       int do_self;
!      tree t, fndecl;
  {
    tree binfos = BINFO_BASETYPES (binfo);
    int i, n_baselinks = binfos ? TREE_VEC_LENGTH (binfos) : 0;
  
    /* Should we use something besides CLASSTYPE_VFIELDS? */
    if (do_self && CLASSTYPE_VFIELDS (BINFO_TYPE (binfo)))
!     modify_one_vtable (binfo, t, fndecl);
  
    for (i = 0; i < n_baselinks; i++)
      {
*************** modify_all_direct_vtables (binfo, do_sel
*** 2500,2506 ****
        int is_not_base_vtable
  	= i != CLASSTYPE_VFIELD_PARENT (BINFO_TYPE (binfo));
        if (! TREE_VIA_VIRTUAL (base_binfo))
! 	modify_all_direct_vtables (base_binfo, is_not_base_vtable, t, fndecl, pfn);
      }
  }
  
--- 2584,2590 ----
        int is_not_base_vtable
  	= i != CLASSTYPE_VFIELD_PARENT (BINFO_TYPE (binfo));
        if (! TREE_VIA_VIRTUAL (base_binfo))
! 	modify_all_direct_vtables (base_binfo, is_not_base_vtable, t, fndecl);
      }
  }
  
*************** fixup_vtable_deltas1 (binfo, t)
*** 2518,2526 ****
    while (virtuals)
      {
        tree fndecl = TREE_VALUE (virtuals);
!       tree pfn = FNADDR_FROM_VTABLE_ENTRY (fndecl);
!       tree delta = DELTA_FROM_VTABLE_ENTRY (fndecl);
!       fndecl = TREE_OPERAND (pfn, 0);
        if (fndecl)
  	{
  	  tree base_offset, offset;
--- 2602,2609 ----
    while (virtuals)
      {
        tree fndecl = TREE_VALUE (virtuals);
!       tree delta = TREE_PURPOSE (virtuals);
! 
        if (fndecl)
  	{
  	  tree base_offset, offset;
*************** fixup_vtable_deltas1 (binfo, t)
*** 2565,2571 ****
  		}
  
  	      modify_vtable_entry (get_vtable_entry_n (BINFO_VIRTUALS (binfo), n),
! 				   build_vtable_entry (this_offset, pfn),
  				   fndecl);
  	    }
  	}
--- 2648,2654 ----
  		}
  
  	      modify_vtable_entry (get_vtable_entry_n (BINFO_VIRTUALS (binfo), n),
! 				   this_offset,
  				   fndecl);
  	    }
  	}
*************** fixup_vtable_deltas (binfo, init_self, t
*** 2598,2624 ****
      }
    /* Should we use something besides CLASSTYPE_VFIELDS? */
    if (init_self && CLASSTYPE_VFIELDS (BINFO_TYPE (binfo)))
!     {
!       fixup_vtable_deltas1 (binfo, t);
!     }
  }
  
  /* These are the ones that are through virtual base classes.  */
  
  static void
! modify_all_indirect_vtables (binfo, do_self, via_virtual, t, fndecl, pfn)
       tree binfo;
       int do_self, via_virtual;
!      tree t, fndecl, pfn;
  {
    tree binfos = BINFO_BASETYPES (binfo);
    int i, n_baselinks = binfos ? TREE_VEC_LENGTH (binfos) : 0;
  
    /* Should we use something besides CLASSTYPE_VFIELDS? */
    if (do_self && via_virtual && CLASSTYPE_VFIELDS (BINFO_TYPE (binfo)))
!     {
!       modify_one_vtable (binfo, t, fndecl, pfn);
!     }
  
    for (i = 0; i < n_baselinks; i++)
      {
--- 2681,2703 ----
      }
    /* Should we use something besides CLASSTYPE_VFIELDS? */
    if (init_self && CLASSTYPE_VFIELDS (BINFO_TYPE (binfo)))
!     fixup_vtable_deltas1 (binfo, t);
  }
  
  /* These are the ones that are through virtual base classes.  */
  
  static void
! modify_all_indirect_vtables (binfo, do_self, via_virtual, t, fndecl)
       tree binfo;
       int do_self, via_virtual;
!      tree t, fndecl;
  {
    tree binfos = BINFO_BASETYPES (binfo);
    int i, n_baselinks = binfos ? TREE_VEC_LENGTH (binfos) : 0;
  
    /* Should we use something besides CLASSTYPE_VFIELDS? */
    if (do_self && via_virtual && CLASSTYPE_VFIELDS (BINFO_TYPE (binfo)))
!     modify_one_vtable (binfo, t, fndecl);
  
    for (i = 0; i < n_baselinks; i++)
      {
*************** modify_all_indirect_vtables (binfo, do_s
*** 2630,2648 ****
  	  via_virtual = 1;
  	  base_binfo = binfo_member (BINFO_TYPE (base_binfo), CLASSTYPE_VBASECLASSES (t));
  	}
!       modify_all_indirect_vtables (base_binfo, is_not_base_vtable, via_virtual, t, fndecl, pfn);
      }
  }
  
  static void
! modify_all_vtables (t, fndecl, vfn)
!      tree t, fndecl, vfn;
  {
    /* Do these first, so that we will make use of any non-virtual class's
       vtable, over a virtual classes vtable.  */
!   modify_all_direct_vtables (TYPE_BINFO (t), 1, t, fndecl, vfn);
    if (TYPE_USES_VIRTUAL_BASECLASSES (t))
!     modify_all_indirect_vtables (TYPE_BINFO (t), 1, 0, t, fndecl, vfn);
  }
  
  /* Here, we already know that they match in every respect.
--- 2709,2728 ----
  	  via_virtual = 1;
  	  base_binfo = binfo_member (BINFO_TYPE (base_binfo), CLASSTYPE_VBASECLASSES (t));
  	}
!       modify_all_indirect_vtables (base_binfo, is_not_base_vtable, via_virtual, t, fndecl);
      }
  }
  
  static void
! modify_all_vtables (t, fndecl)
!      tree t;
!      tree fndecl;
  {
    /* Do these first, so that we will make use of any non-virtual class's
       vtable, over a virtual classes vtable.  */
!   modify_all_direct_vtables (TYPE_BINFO (t), 1, t, fndecl);
    if (TYPE_USES_VIRTUAL_BASECLASSES (t))
!     modify_all_indirect_vtables (TYPE_BINFO (t), 1, 0, t, fndecl);
  }
  
  /* Here, we already know that they match in every respect.
*************** override_one_vtable (binfo, old, t)
*** 2693,2702 ****
      {
        tree fndecl = TREE_VALUE (virtuals);
        tree old_fndecl = TREE_VALUE (old_virtuals);
!       fndecl = FNADDR_FROM_VTABLE_ENTRY (fndecl);
!       old_fndecl = FNADDR_FROM_VTABLE_ENTRY (old_fndecl);
!       fndecl = TREE_OPERAND (fndecl, 0);
!       old_fndecl = TREE_OPERAND (old_fndecl, 0);
        /* First check to see if they are the same.  */
        if (DECL_ASSEMBLER_NAME (fndecl) == DECL_ASSEMBLER_NAME (old_fndecl))
  	{
--- 2773,2779 ----
      {
        tree fndecl = TREE_VALUE (virtuals);
        tree old_fndecl = TREE_VALUE (old_virtuals);
! 
        /* First check to see if they are the same.  */
        if (DECL_ASSEMBLER_NAME (fndecl) == DECL_ASSEMBLER_NAME (old_fndecl))
  	{
*************** override_one_vtable (binfo, old, t)
*** 2748,2755 ****
  	    }
  	  {
  	    /* This MUST be overridden, or the class is ill-formed.  */
! 	    tree fndecl = TREE_OPERAND (FNADDR_FROM_VTABLE_ENTRY (TREE_VALUE (virtuals)), 0);
! 	    tree vfn;
  
  	    fndecl = copy_node (fndecl);
  	    copy_lang_decl (fndecl);
--- 2825,2831 ----
  	    }
  	  {
  	    /* This MUST be overridden, or the class is ill-formed.  */
! 	    tree fndecl = TREE_VALUE (virtuals);
  
  	    fndecl = copy_node (fndecl);
  	    copy_lang_decl (fndecl);
*************** override_one_vtable (binfo, old, t)
*** 2758,2769 ****
  	    if (! CLASSTYPE_ABSTRACT_VIRTUALS (t))
  	      CLASSTYPE_ABSTRACT_VIRTUALS (t) = error_mark_node;
  
- 	    vfn = build1 (ADDR_EXPR, vfunc_ptr_type_node, fndecl);
- 	    TREE_CONSTANT (vfn) = 1;
- 	    
  	    /* We can use integer_zero_node, as we will core dump
  	       if this is used anyway.  */
! 	    TREE_VALUE (virtuals) = build_vtable_entry (integer_zero_node, vfn);
  	  }
  	}
        virtuals = TREE_CHAIN (virtuals);
--- 2834,2843 ----
  	    if (! CLASSTYPE_ABSTRACT_VIRTUALS (t))
  	      CLASSTYPE_ABSTRACT_VIRTUALS (t) = error_mark_node;
  
  	    /* We can use integer_zero_node, as we will core dump
  	       if this is used anyway.  */
! 	    TREE_VALUE (virtuals) = build_vtable_entry (integer_zero_node, 
! 							fndecl);
  	  }
  	}
        virtuals = TREE_CHAIN (virtuals);
*************** finish_struct_1 (t)
*** 3960,3971 ****
      TYPE_VIRTUAL_P (t) = 1;
  
    if (flag_rtti && TYPE_VIRTUAL_P (t) && !pending_hard_virtuals)
!     modify_all_vtables (t, NULL_TREE, NULL_TREE);
  
    while (pending_hard_virtuals)
      {
        modify_all_vtables (t,
- 			  TREE_PURPOSE (pending_hard_virtuals),
  			  TREE_VALUE (pending_hard_virtuals));
        pending_hard_virtuals = TREE_CHAIN (pending_hard_virtuals);
      }
--- 4034,4044 ----
      TYPE_VIRTUAL_P (t) = 1;
  
    if (flag_rtti && TYPE_VIRTUAL_P (t) && !pending_hard_virtuals)
!     modify_all_vtables (t, NULL_TREE);
  
    while (pending_hard_virtuals)
      {
        modify_all_vtables (t,
  			  TREE_VALUE (pending_hard_virtuals));
        pending_hard_virtuals = TREE_CHAIN (pending_hard_virtuals);
      }
*************** finish_struct_1 (t)
*** 4146,4171 ****
  
    if (CLASSTYPE_VSIZE (t) != 0)
      {
- #if 0
-       /* This is now done above.  */
-       if (DECL_FIELD_CONTEXT (vfield) != t)
- 	{
- 	  tree binfo = get_binfo (DECL_FIELD_CONTEXT (vfield), t, 0);
- 	  tree offset = BINFO_OFFSET (binfo);
- 
- 	  vfield = copy_node (vfield);
- 	  copy_lang_decl (vfield);
- 
- 	  if (! integer_zerop (offset))
- 	    offset = size_binop (MULT_EXPR, offset, size_int (BITS_PER_UNIT));
- 	  DECL_FIELD_CONTEXT (vfield) = t;
- 	  DECL_CLASS_CONTEXT (vfield) = t;
- 	  DECL_FIELD_BITPOS (vfield)
- 	    = size_binop (PLUS_EXPR, offset, DECL_FIELD_BITPOS (vfield));
- 	  CLASSTYPE_VFIELD (t) = vfield;
- 	}
- #endif
- 
        /* In addition to this one, all the other vfields should be listed.  */
        /* Before that can be done, we have to have FIELD_DECLs for them, and
  	 a place to find them.  */
--- 4219,4224 ----
Index: cp/cp-tree.h
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/cp-tree.h,v
retrieving revision 1.248
diff -c -p -r1.248 cp-tree.h
*** cp-tree.h	1999/07/26 18:12:14	1.248
--- cp-tree.h	1999/07/27 18:07:08
*************** Boston, MA 02111-1307, USA.  */
*** 98,104 ****
  
     DECL_SAVED_INSNS/DECL_FIELD_SIZE
       For a static VAR_DECL, this is DECL_INIT_PRIORITY.
! */
  
  /* Language-dependent contents of an identifier.  */
  
--- 98,111 ----
  
     DECL_SAVED_INSNS/DECL_FIELD_SIZE
       For a static VAR_DECL, this is DECL_INIT_PRIORITY.
! 
!    BINFO_VIRTUALS
!      For a binfo, this is a TREE_LIST.  The TREE_PURPOSE of each node
!      gives the amount by which to adjust the `this' pointer when
!      calling the function.  The TREE_VALUE is the declaration for the 
!      virtual function itself.  When CLASSTYPE_COM_INTERFACE_P does not
!      hold, the first entry does not have a TREE_VALUE; it is just an
!      offset.  */ 
  
  /* Language-dependent contents of an identifier.  */
  
Index: cp/decl2.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/decl2.c,v
retrieving revision 1.224
diff -c -p -r1.224 decl2.c
*** decl2.c	1999/07/20 10:40:47	1.224
--- decl2.c	1999/07/27 18:07:11
*************** mark_vtable_entries (decl)
*** 2414,2424 ****
  
        fn = TREE_OPERAND (fnaddr, 0);
        TREE_ADDRESSABLE (fn) = 1;
-       if (DECL_LANG_SPECIFIC (fn) && DECL_ABSTRACT_VIRTUAL_P (fn))
- 	{
- 	  TREE_OPERAND (fnaddr, 0) = abort_fndecl;
- 	  mark_used (abort_fndecl);
- 	}
        if (TREE_CODE (fn) == THUNK_DECL && DECL_EXTERNAL (fn))
  	{
  	  DECL_EXTERNAL (fn) = 0;
--- 2414,2419 ----
Index: cp/error.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/error.c,v
retrieving revision 1.79
diff -c -p -r1.79 error.c
*** error.c	1999/07/23 01:01:15	1.79
--- error.c	1999/07/27 18:07:12
*************** dump_expr (t, nop)
*** 1670,1676 ****
  
  	      t = TREE_TYPE (TYPE_PTRMEMFUNC_FN_TYPE (TREE_TYPE (t)));
  	      t = TYPE_METHOD_BASETYPE (t);
! 	      virtuals = BINFO_VIRTUALS (TYPE_BINFO (TYPE_MAIN_VARIANT (t)));
  	      
  	      n = TREE_INT_CST_LOW (idx);
  
--- 1670,1676 ----
  
  	      t = TREE_TYPE (TYPE_PTRMEMFUNC_FN_TYPE (TREE_TYPE (t)));
  	      t = TYPE_METHOD_BASETYPE (t);
! 	      virtuals = TYPE_BINFO_VIRTUALS (TYPE_MAIN_VARIANT (t));
  	      
  	      n = TREE_INT_CST_LOW (idx);
  
*************** dump_expr (t, nop)
*** 1685,1691 ****
  		}
  	      if (virtuals)
  		{
! 		  dump_expr (FNADDR_FROM_VTABLE_ENTRY (TREE_VALUE (virtuals)), 0);
  		  break;
  		}
  	    }
--- 1685,1691 ----
  		}
  	      if (virtuals)
  		{
! 		  dump_expr (TREE_VALUE (virtuals), 0);
  		  break;
  		}
  	    }
Index: cp/search.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/search.c,v
retrieving revision 1.112
diff -c -p -r1.112 search.c
*** search.c	1999/07/26 08:18:19	1.112
--- search.c	1999/07/27 18:07:19
*************** get_abstract_virtuals_1 (binfo, do_self,
*** 2032,2041 ****
  
        while (virtuals)
  	{
! 	  tree base_pfn = FNADDR_FROM_VTABLE_ENTRY (TREE_VALUE (virtuals));
! 	  tree base_fndecl = TREE_OPERAND (base_pfn, 0);
  	  if (DECL_ABSTRACT_VIRTUAL_P (base_fndecl))
! 	    abstract_virtuals = tree_cons (NULL_TREE, base_fndecl, abstract_virtuals);
  	  virtuals = TREE_CHAIN (virtuals);
  	}
      }
--- 2032,2041 ----
  
        while (virtuals)
  	{
! 	  tree base_fndecl = TREE_VALUE (virtuals);
  	  if (DECL_ABSTRACT_VIRTUAL_P (base_fndecl))
! 	    abstract_virtuals = tree_cons (NULL_TREE, base_fndecl, 
! 					   abstract_virtuals);
  	  virtuals = TREE_CHAIN (virtuals);
  	}
      }
*************** get_abstract_virtuals (type)
*** 2065,2076 ****
  
        while (virtuals)
  	{
! 	  tree base_pfn = FNADDR_FROM_VTABLE_ENTRY (TREE_VALUE (virtuals));
! 	  tree base_fndecl = TREE_OPERAND (base_pfn, 0);
  	  if (DECL_NEEDS_FINAL_OVERRIDER_P (base_fndecl))
  	    cp_error ("`%#D' needs a final overrider", base_fndecl);
  	  else if (DECL_ABSTRACT_VIRTUAL_P (base_fndecl))
! 	    abstract_virtuals = tree_cons (NULL_TREE, base_fndecl, abstract_virtuals);
  	  virtuals = TREE_CHAIN (virtuals);
  	}
      }
--- 2065,2076 ----
  
        while (virtuals)
  	{
! 	  tree base_fndecl = TREE_VALUE (virtuals);
  	  if (DECL_NEEDS_FINAL_OVERRIDER_P (base_fndecl))
  	    cp_error ("`%#D' needs a final overrider", base_fndecl);
  	  else if (DECL_ABSTRACT_VIRTUAL_P (base_fndecl))
! 	    abstract_virtuals = tree_cons (NULL_TREE, base_fndecl, 
! 					   abstract_virtuals);
  	  virtuals = TREE_CHAIN (virtuals);
  	}
      }
*************** expand_upcast_fixups (binfo, addr, orig_
*** 2541,2548 ****
    while (virtuals)
      {
        tree current_fndecl = TREE_VALUE (virtuals);
!       current_fndecl = FNADDR_FROM_VTABLE_ENTRY (current_fndecl);
!       current_fndecl = TREE_OPERAND (current_fndecl, 0);
        if (current_fndecl
  	  && current_fndecl != abort_fndecl
  	  && (vc=virtual_context (current_fndecl, t, vbase)) != vbase)
--- 2541,2547 ----
    while (virtuals)
      {
        tree current_fndecl = TREE_VALUE (virtuals);
! 
        if (current_fndecl
  	  && current_fndecl != abort_fndecl
  	  && (vc=virtual_context (current_fndecl, t, vbase)) != vbase)
Index: cp/tree.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/tree.c,v
retrieving revision 1.119
diff -c -p -r1.119 tree.c
*** tree.c	1999/07/27 01:35:35	1.119
--- tree.c	1999/07/27 18:07:21
*************** debug_binfo (elem)
*** 1245,1251 ****
  
    while (virtuals)
      {
!       tree fndecl = TREE_OPERAND (FNADDR_FROM_VTABLE_ENTRY (TREE_VALUE (virtuals)), 0);
        fprintf (stderr, "%s [%ld =? %ld]\n",
  	       IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (fndecl)),
  	       (long) n, (long) TREE_INT_CST_LOW (DECL_VINDEX (fndecl)));
--- 1245,1251 ----
  
    while (virtuals)
      {
!       tree fndecl = TREE_VALUE (virtuals);
        fprintf (stderr, "%s [%ld =? %ld]\n",
  	       IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (fndecl)),
  	       (long) n, (long) TREE_INT_CST_LOW (DECL_VINDEX (fndecl)));

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