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]
Other format: [Raw text]

Re: c++/4122: undefined reference to `non-virtual thunk to ...'



Hello,

I have generated a patch which fixes PR4122 in the 3.0 branch.
The problem is a regression from 2.95.x and present in all
releases of 3.0 and CVS head.  I have tested gcc with this
patch everywhere I could, and it apperars to work just fine.
The basic idea is to revert some changes checked in on June 6, 2001.
The changes apparently confused g++ when virtual inheritence was
used into thinking that a non-virtual thunk should be generated.
As far as I know, I have a copyright assignment form on file
with the FSF that covers gcc, but it may not be needed.
Could someone familiar with this code look it over,
and perhaps check it in? (assuming it's all good ;)
A patch for HEAD is in the works, I will post it tomorrow
if this one is OK'd.

Thanks!

ChangeLog entry:
2001-12-19  Robert Boehne  <rboehne@ricardo-us.com>
 
        PR c++/4122
        * method.c (make_thunk): Brought back from 2001-06-06.
        * class.c (build_vtable_entry): Re-add an int argument for
        generate_with_vtable_p.
        (get_vfield_offset, get_derived_offset): Re-add.
        (copy_virtuals): Resurect BV_GENERATE_THUNK_WITH_VTABLE_P.
        (update_vtable_entry_for_fn): Bring back local variable
        generate_thunk_with_vtable_p and use it.
        * semantics.c (emit_associated_thunks): Adjust arguments to
        make_thunk.
        * cp-tree.h: Modified make_thunk, added get_vfield_offset,
        BV_GENERATE_THUNK_WITH_VTABLE_P and THUNK_GENERATE_WITH_VTABLE_P
        * decl2.c (mark_vtable_entries): Use the macro
        THUNK_GENERATE_WITH_VTABLE_P as argument to use_thunk.
                                                                                                
http://gcc.gnu.org/cgi-bin/gnatsweb.pl?cmd=view%20audit-trail&database=gcc&pr=4122

-- 
Robert Boehne             Software Engineer
Ricardo Software   Chicago Technical Center
TEL: (630)789-0003 x. 238
FAX: (630)789-0127
email:  rboehne@ricardo-us.com
Index: gcc/cp/class.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/class.c,v
retrieving revision 1.358.2.38
diff -c -3 -p -r1.358.2.38 class.c
*** class.c	2001/12/03 02:38:50	1.358.2.38
--- class.c	2001/12/20 02:09:43
*************** varray_type local_classes;
*** 107,113 ****
  static tree get_vfield_name PARAMS ((tree));
  static void finish_struct_anon PARAMS ((tree));
  static tree build_vbase_pointer PARAMS ((tree, tree));
! static tree build_vtable_entry PARAMS ((tree, tree, tree));
  static tree get_vtable_name PARAMS ((tree));
  static tree get_basefndecls PARAMS ((tree, tree));
  static int build_primary_vtable PARAMS ((tree, tree));
--- 107,114 ----
  static tree get_vfield_name PARAMS ((tree));
  static void finish_struct_anon PARAMS ((tree));
  static tree build_vbase_pointer PARAMS ((tree, tree));
! static tree build_vtable_entry PARAMS ((tree, tree, tree, int));
! static tree get_derived_offset PARAMS ((tree, tree));
  static tree get_vtable_name PARAMS ((tree));
  static tree get_basefndecls PARAMS ((tree, tree));
  static int build_primary_vtable PARAMS ((tree, tree));
*************** get_vtt_name (type)
*** 693,698 ****
--- 694,730 ----
    return mangle_vtt_for_type (type);
  }
  
+ /* Return the offset to the main vtable for a given base BINFO.  */
+ 
+ tree
+ get_vfield_offset (binfo)
+      tree binfo;
+ {
+   return
+     size_binop (PLUS_EXPR, byte_position (TYPE_VFIELD (BINFO_TYPE (binfo))),
+ 		BINFO_OFFSET (binfo));
+ }
+ 
+ /* Get the offset to the start of the original binfo that we derived
+    this binfo from.  If we find TYPE first, return the offset only
+    that far.  The shortened search is useful because the this pointer
+    on method calling is expected to point to a DECL_CONTEXT (fndecl)
+    object, and not a baseclass of it.   */
+ 
+ static tree
+ get_derived_offset (binfo, type)
+      tree binfo, type;
+ {
+   tree offset1 = get_vfield_offset (TYPE_BINFO (BINFO_TYPE (binfo)));
+   tree offset2;
+ 
+   while (!same_type_p (BINFO_TYPE (binfo), type))
+     binfo = get_primary_binfo (binfo);
+ 
+   offset2 = get_vfield_offset (TYPE_BINFO (BINFO_TYPE (binfo)));
+   return size_binop (MINUS_EXPR, offset1, offset2);
+ }
+ 
  /* Create a VAR_DECL for a primary or secondary vtable for CLASS_TYPE.
     (For a secondary vtable for B-in-D, CLASS_TYPE should be D, not B.)
     Use NAME for the name of the vtable, and VTABLE_TYPE for its type.  */
*************** copy_virtuals (binfo)
*** 774,779 ****
--- 806,812 ----
      {
        BV_VCALL_INDEX (t) = NULL_TREE;
        BV_USE_VCALL_INDEX_P (t) = 0;
+       BV_GENERATE_THUNK_WITH_VTABLE_P (t) = 0;
      }
  
    return copies;
*************** update_vtable_entry_for_fn (t, binfo, fn
*** 2784,2789 ****
--- 2817,2823 ----
    tree overrider;
    tree delta;
    tree virtual_base;
+   int generate_thunk_with_vtable_p;
    tree first_defn;
  
    /* Find the nearest primary base (possibly binfo itself) which defines
*************** update_vtable_entry_for_fn (t, binfo, fn
*** 2801,2815 ****
--- 2835,2865 ----
    if (overrider == error_mark_node)
      return;
  
+   /* Compute the constant adjustment to the `this' pointer.  The
+      `this' pointer, when this function is called, will point at the
+      class whose vtable this is.  */
+   delta = size_binop (PLUS_EXPR,
+ 		      get_derived_offset (binfo,
+ 					  DECL_VIRTUAL_CONTEXT (fn)),
+ 		      BINFO_OFFSET (binfo));
+ 
    /* Assume that we will produce a thunk that convert all the way to
       the final overrider, and not to an intermediate virtual base.  */
    virtual_base = NULL_TREE;
  
+   /* Assume that we will always generate thunks with the vtables that
+      reference them.  */
+   generate_thunk_with_vtable_p = 1;
+ 
    /* Under the new ABI, we will convert to an intermediate virtual
       base first, and then use the vcall offset located there to finish
       the conversion.  */
    while (b)
      {
+       if (!virtual_base
+ 	  && same_type_p (BINFO_TYPE (b), BINFO_TYPE (binfo)))
+ 	generate_thunk_with_vtable_p = 0;
+ 
        /* If we find the final overrider, then we can stop
  	 walking.  */
        if (same_type_p (BINFO_TYPE (b), 
*************** update_vtable_entry_for_fn (t, binfo, fn
*** 2820,2826 ****
  	 overrider, then there is a virtual base between the
  	 declaring base (first_defn) and the final overrider.  */
        if (!virtual_base && TREE_VIA_VIRTUAL (b))
! 	virtual_base = b;
  
        b = BINFO_INHERITANCE_CHAIN (b);
      }
--- 2870,2879 ----
  	 overrider, then there is a virtual base between the
  	 declaring base (first_defn) and the final overrider.  */
        if (!virtual_base && TREE_VIA_VIRTUAL (b))
! 	{
! 	  generate_thunk_with_vtable_p = 1;
! 	  virtual_base = b;
! 	}
  
        b = BINFO_INHERITANCE_CHAIN (b);
      }
*************** update_vtable_entry_for_fn (t, binfo, fn
*** 2874,2879 ****
--- 2927,2934 ----
  
    if (virtual_base)
      BV_USE_VCALL_INDEX_P (*virtuals) = 1;
+   if (generate_thunk_with_vtable_p)
+     BV_GENERATE_THUNK_WITH_VTABLE_P (*virtuals) = 1;
  }
  
  /* Called from modify_all_vtables via dfs_walk.  */
*************** build_vtbl_initializer (binfo, orig_binf
*** 7838,7843 ****
--- 7893,7899 ----
        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.  */
*************** build_vtbl_initializer (binfo, orig_binf
*** 7848,7853 ****
--- 7904,7918 ----
  	  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;
  
*************** build_vtbl_initializer (binfo, orig_binf
*** 7867,7873 ****
        TREE_CONSTANT (pfn) = 1;
  
        /* Enter it in the vtable.  */
!       init = build_vtable_entry (delta, vcall_index, pfn);
  
        /* If the only definition of this function signature along our
  	 primary base chain is from a lost primary, this vtable slot will
--- 7932,7939 ----
        TREE_CONSTANT (pfn) = 1;
  
        /* Enter it in the vtable.  */
!       init = build_vtable_entry (delta, vcall_index, pfn,
! 				 generate_with_vtable_p);
  
        /* If the only definition of this function signature along our
  	 primary base chain is from a lost primary, this vtable slot will
*************** build_rtti_vtbl_entries (binfo, vid)
*** 8349,8358 ****
     ABI.)  */
  
  static tree
! build_vtable_entry (delta, vcall_index, entry)
       tree delta;
       tree vcall_index;
       tree entry;
  {
    if (flag_vtable_thunks)
      {
--- 8415,8425 ----
     ABI.)  */
  
  static tree
! build_vtable_entry (delta, vcall_index, entry, generate_with_vtable_p)
       tree delta;
       tree vcall_index;
       tree entry;
+      int generate_with_vtable_p;
  {
    if (flag_vtable_thunks)
      {
*************** build_vtable_entry (delta, vcall_index, 
*** 8363,8369 ****
  	  && fn != abort_fndecl
  	  && !DECL_TINFO_FN_P (fn))
  	{
! 	  entry = make_thunk (entry, delta, vcall_index);
  	  entry = build1 (ADDR_EXPR, vtable_entry_type, entry);
  	  TREE_READONLY (entry) = 1;
  	  TREE_CONSTANT (entry) = 1;
--- 8430,8437 ----
  	  && fn != abort_fndecl
  	  && !DECL_TINFO_FN_P (fn))
  	{
! 	  entry = make_thunk (entry, delta, vcall_index,
! 			      generate_with_vtable_p);
  	  entry = build1 (ADDR_EXPR, vtable_entry_type, entry);
  	  TREE_READONLY (entry) = 1;
  	  TREE_CONSTANT (entry) = 1;
Index: gcc/cp/cp-tree.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/cp-tree.h,v
retrieving revision 1.572.2.36
diff -c -3 -p -r1.572.2.36 cp-tree.h
*** cp-tree.h	2001/12/08 16:12:51	1.572.2.36
--- cp-tree.h	2001/12/20 02:09:43
*************** Boston, MA 02111-1307, USA.  */
*** 55,60 ****
--- 55,61 ----
        BASELINK_P (in TREE_LIST)
        ICS_ELLIPSIS_FLAG (in _CONV)
        BINFO_ACCESS (in BINFO)
+       BV_GENERATE_THUNK_WITH_VTABLE_P (in TREE_LIST)
     2: IDENTIFIER_OPNAME_P.
        TYPE_POLYMORHPIC_P (in _TYPE)
        ICS_THIS_FLAG (in _CONV)
*************** struct lang_type
*** 1764,1769 ****
--- 1765,1778 ----
  /* Nonzero if we should use a virtual thunk for this entry.  */
  #define BV_USE_VCALL_INDEX_P(NODE) \
     (TREE_LANG_FLAG_0 (NODE))
+ 
+ /* Nonzero if we should generate this thunk when the vtable that
+    references it is emitted, rather than with the final overrider.  */
+ #define BV_GENERATE_THUNK_WITH_VTABLE_P(NODE) \
+   (TREE_LANG_FLAG_1 (NODE))
+ 
+ /* The most derived class.  */
+ 
  
  /* Nonzero for TREE_LIST node means that this list of things
     is a list of parameters, as opposed to a list of expressions.  */
*************** struct lang_decl_flags
*** 1827,1832 ****
--- 1836,1842 ----
    unsigned tinfo_fn_p : 1;
    unsigned assignment_operator_p : 1;
    unsigned anticipated_p : 1;
+   unsigned generate_with_vtable_p : 1;
    /* Two unused bits.  */
  
    union {
*************** enum ptrmemfunc_vbit_where_t
*** 3067,3072 ****
--- 3077,3087 ----
  #define THUNK_VCALL_OFFSET(DECL) \
    (DECL_LANG_SPECIFIC (DECL)->decl_flags.u2.vcall_offset)
  
+ /* Nonzero if this thunk should be generated with the vtable that
+    references it.  */
+ #define THUNK_GENERATE_WITH_VTABLE_P(DECL) \
+   (DECL_LANG_SPECIFIC (DECL)->decl_flags.generate_with_vtable_p)
+ 
  /* These macros provide convenient access to the various _STMT nodes
     created when parsing template declarations.  */
  #define TRY_STMTS(NODE)         TREE_OPERAND (TRY_BLOCK_CHECK (NODE), 0)
*************** extern tree get_vtable_decl             
*** 3749,3754 ****
--- 3764,3770 ----
  extern void add_method				PARAMS ((tree, tree, int));
  extern int currently_open_class			PARAMS ((tree));
  extern tree currently_open_derived_class	PARAMS ((tree));
+ extern tree get_vfield_offset			PARAMS ((tree));
  extern void duplicate_tag_error			PARAMS ((tree));
  extern tree finish_struct			PARAMS ((tree, tree));
  extern void finish_struct_1			PARAMS ((tree));
*************** extern void init_method				PARAMS ((void
*** 4127,4133 ****
  extern void set_mangled_name_for_decl           PARAMS ((tree));
  extern tree build_opfncall			PARAMS ((enum tree_code, int, tree, tree, tree));
  extern tree hack_identifier			PARAMS ((tree, tree));
! extern tree make_thunk				PARAMS ((tree, tree, tree));
  extern void use_thunk				PARAMS ((tree, int));
  extern void synthesize_method			PARAMS ((tree));
  extern tree implicitly_declare_fn               PARAMS ((special_function_kind, tree, int));
--- 4143,4149 ----
  extern void set_mangled_name_for_decl           PARAMS ((tree));
  extern tree build_opfncall			PARAMS ((enum tree_code, int, tree, tree, tree));
  extern tree hack_identifier			PARAMS ((tree, tree));
! extern tree make_thunk				PARAMS ((tree, tree, tree, int));
  extern void use_thunk				PARAMS ((tree, int));
  extern void synthesize_method			PARAMS ((tree));
  extern tree implicitly_declare_fn               PARAMS ((special_function_kind, tree, int));
Index: gcc/cp/decl2.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/decl2.c,v
retrieving revision 1.437.2.29
diff -c -3 -p -r1.437.2.29 decl2.c
*** decl2.c	2001/11/30 03:12:42	1.437.2.29
--- decl2.c	2001/12/20 02:09:43
*************** mark_vtable_entries (decl)
*** 2281,2287 ****
  	 we know all the thunks we'll need when we emit a virtual
  	 function, so we emit the thunks there instead.  */
        if (DECL_THUNK_P (fn)) 
! 	use_thunk (fn, /*emit_p=*/0);
        mark_used (fn);
      }
  }
--- 2281,2287 ----
  	 we know all the thunks we'll need when we emit a virtual
  	 function, so we emit the thunks there instead.  */
        if (DECL_THUNK_P (fn)) 
! 	use_thunk (fn, THUNK_GENERATE_WITH_VTABLE_P (fn));
        mark_used (fn);
      }
  }
Index: gcc/cp/method.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/method.c,v
retrieving revision 1.190.2.14
diff -c -3 -p -r1.190.2.14 method.c
*** method.c	2001/07/25 09:32:46	1.190.2.14
--- method.c	2001/12/20 02:09:44
*************** request for member `%D' is ambiguous in 
*** 298,307 ****
     DELTA is the offset to this and VCALL_INDEX is NULL.  */
  
  tree
! make_thunk (function, delta, vcall_index)
       tree function;
       tree delta;
       tree vcall_index;
  {
    tree thunk_id;
    tree thunk;
--- 298,308 ----
     DELTA is the offset to this and VCALL_INDEX is NULL.  */
  
  tree
! make_thunk (function, delta, vcall_index, generate_with_vtable_p)
       tree function;
       tree delta;
       tree vcall_index;
+      int generate_with_vtable_p;
  {
    tree thunk_id;
    tree thunk;
*************** make_thunk (function, delta, vcall_index
*** 350,355 ****
--- 351,357 ----
        DECL_INITIAL (thunk) = function;
        THUNK_DELTA (thunk) = d;
        THUNK_VCALL_OFFSET (thunk) = vcall_offset;
+       THUNK_GENERATE_WITH_VTABLE_P (thunk) = generate_with_vtable_p;
        /* The thunk itself is not a constructor or destructor, even if
           the thing it is thunking to is.  */
        DECL_INTERFACE_KNOWN (thunk) = 1;
Index: gcc/cp/semantics.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/semantics.c,v
retrieving revision 1.189.2.18
diff -c -3 -p -r1.189.2.18 semantics.c
*** semantics.c	2001/12/12 19:05:20	1.189.2.18
--- semantics.c	2001/12/20 02:09:44
*************** emit_associated_thunks (fn)
*** 2372,2378 ****
  					  vfunc_ptr_type_node,
  					  fn),
  				  BV_DELTA (v),
! 				  vcall_index);
  	      use_thunk (thunk, /*emit_p=*/1);
  	    }
      }
--- 2372,2379 ----
  					  vfunc_ptr_type_node,
  					  fn),
  				  BV_DELTA (v),
! 				  vcall_index,
! 				  /*generate_with_vtable_p=*/0);
  	      use_thunk (thunk, /*emit_p=*/1);
  	    }
      }

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