From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 30238 invoked by alias); 20 Dec 2001 02:56:03 -0000 Mailing-List: contact gcc-prs-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Archive: List-Post: List-Help: Sender: gcc-prs-owner@gcc.gnu.org Received: (qmail 30215 invoked by uid 71); 20 Dec 2001 02:56:01 -0000 Date: Wed, 19 Dec 2001 18:56:00 -0000 Message-ID: <20011220025601.30214.qmail@sources.redhat.com> To: nobody@gcc.gnu.org Cc: gcc-prs@gcc.gnu.org, From: Robert Boehne Subject: Re: c++/4122: undefined reference to `non-virtual thunk to ...' Reply-To: Robert Boehne X-SW-Source: 2001-12/txt/msg00998.txt.bz2 List-Id: The following reply was made to PR c++/4122; it has been noted by GNATS. From: Robert Boehne To: gcc-gnats@gcc.gnu.org, gcc-prs@gcc.gnu.org, juergen@monocerus.demon.co.uk, boehme@informatik.hu-berlin.de, loewis@informatik.hu-berlin.de, rboehne@ricardo-us.com, gcc-bugs@gcc.gnu.org, nobody@gcc.gnu.org, michael@ritzert.de, gcc-patches@gcc.gnu.org Cc: Subject: Re: c++/4122: undefined reference to `non-virtual thunk to ...' Date: Wed, 19 Dec 2001 20:48:29 -0600 This is a multi-part message in MIME format. --------------DD1B5602DBA2066186AA77FC Content-Type: text/plain; charset=us-ascii Content-Transfer-Encoding: 7bit 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 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 --------------DD1B5602DBA2066186AA77FC Content-Type: text/plain; charset=us-ascii; name="branch30patch.diff" Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename="branch30patch.diff" 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); } } --------------DD1B5602DBA2066186AA77FC--