This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the EGCS project.
(C++) fix pmfs and MI
- To: gcc-patches@gcc.gnu.org
- Subject: (C++) fix pmfs and MI
- From: Jason Merrill <jason@cygnus.com>
- Date: Tue, 27 Jul 1999 17:44:37 -0700
We were failing to compensate for the vtable adjustment when calculating
delta for a PMF. Fixes g++.other/pmf4.C.
I added a macro DECL_VIRTUAL_CONTEXT to make it explicit when that's what
we want, since we're planning to fix DECL_CONTEXT to mean the real context.
1999-07-27 Jason Merrill <jason@yorick.cygnus.com>
* cp-tree.h (DECL_VIRTUAL_CONTEXT): New macro.
* typeck.c (expand_ptrmemfunc_cst): Calculate delta correctly for
virtual functions and MI. Simplify.
Index: cp-tree.h
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/cp-tree.h,v
retrieving revision 1.249
diff -c -p -r1.249 cp-tree.h
*** cp-tree.h 1999/07/27 18:15:20 1.249
--- cp-tree.h 1999/07/28 00:11:00
*************** struct lang_decl
*** 1403,1408 ****
--- 1403,1412 ----
#define CP_DECL_CONTEXT(NODE) \
(DECL_CONTEXT (NODE) ? DECL_CONTEXT (NODE) : global_namespace)
#define FROB_CONTEXT(NODE) ((NODE) == global_namespace ? NULL_TREE : (NODE))
+
+ /* For a virtual function, the base where we find its vtable entry.
+ For a non-virtual function, the base where it is defined. */
+ #define DECL_VIRTUAL_CONTEXT(NODE) DECL_CONTEXT (NODE)
/* 1 iff NODE has namespace scope, including the global namespace. */
#define DECL_NAMESPACE_SCOPE_P(NODE) \
Index: typeck.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/typeck.c,v
retrieving revision 1.178
diff -c -p -r1.178 typeck.c
*** typeck.c 1999/07/27 01:35:35 1.178
--- typeck.c 1999/07/28 00:11:00
*************** build_x_modify_expr (lhs, modifycode, rh
*** 6078,6085 ****
/* Get difference in deltas for different pointer to member function
types. Return integer_zero_node, if FROM cannot be converted to a
! TO type. If FORCE is true, then allow reverse conversions as well. */
static tree
get_delta_difference (from, to, force)
tree from, to;
--- 6078,6090 ----
/* Get difference in deltas for different pointer to member function
types. Return integer_zero_node, if FROM cannot be converted to a
! TO type. If FORCE is true, then allow reverse conversions as well.
+ Note that the naming of FROM and TO is kind of backwards; the return
+ value is what we add to a TO in order to get a FROM. They are named
+ this way because we call this function to find out how to convert from
+ a pointer to member of FROM to a pointer to member of TO. */
+
static tree
get_delta_difference (from, to, force)
tree from, to;
*************** expand_ptrmemfunc_cst (cst, delta, idx,
*** 6338,6374 ****
{
tree type = TREE_TYPE (cst);
tree fn = PTRMEM_CST_MEMBER (cst);
my_friendly_assert (TREE_CODE (fn) == FUNCTION_DECL, 0);
!
! *delta
! = get_delta_difference (TYPE_METHOD_BASETYPE (TREE_TYPE (fn)),
! TYPE_PTRMEMFUNC_OBJECT_TYPE (type),
! /*force=*/0);
if (!DECL_VIRTUAL_P (fn))
{
! *idx = size_binop (MINUS_EXPR, integer_zero_node,
! integer_one_node);
! *pfn = build_addr_func (fn);
! if (!same_type_p (TYPE_METHOD_BASETYPE (TREE_TYPE (fn)),
! TYPE_PTRMEMFUNC_OBJECT_TYPE (type)))
! *pfn = build1 (NOP_EXPR, TYPE_PTRMEMFUNC_FN_TYPE (type),
! *pfn);
*delta2 = NULL_TREE;
}
else
{
! *idx = size_binop (PLUS_EXPR, DECL_VINDEX (fn),
! integer_one_node);
*pfn = NULL_TREE;
! *delta2 = get_binfo (DECL_CONTEXT (fn),
! DECL_CLASS_CONTEXT (fn),
! 0);
! *delta2 = get_vfield_offset (*delta2);
! *delta2 = size_binop (PLUS_EXPR, *delta2,
! build_binary_op (PLUS_EXPR,
! *delta,
! integer_zero_node));
}
}
--- 6343,6383 ----
{
tree type = TREE_TYPE (cst);
tree fn = PTRMEM_CST_MEMBER (cst);
+ tree ptr_class, fn_class;
my_friendly_assert (TREE_CODE (fn) == FUNCTION_DECL, 0);
!
! /* The class that the function belongs to. */
! fn_class = DECL_CLASS_CONTEXT (fn);
!
! /* The class that we're creating a pointer to member of. */
! ptr_class = TYPE_PTRMEMFUNC_OBJECT_TYPE (type);
!
! /* First, calculate the adjustment to the function's class. */
! *delta = get_delta_difference (fn_class, ptr_class, /*force=*/0);
!
if (!DECL_VIRTUAL_P (fn))
{
! *idx = size_binop (MINUS_EXPR, integer_zero_node, integer_one_node);
! *pfn = convert (TYPE_PTRMEMFUNC_FN_TYPE (type), build_addr_func (fn));
*delta2 = NULL_TREE;
}
else
{
! /* If we're dealing with a virtual function, we have to adjust 'this'
! again, to point to the base which provides the vtable entry for
! fn; the call will do the opposite adjustment. */
! tree orig_class = DECL_VIRTUAL_CONTEXT (fn);
! tree binfo = binfo_or_else (orig_class, fn_class);
! *delta = size_binop (PLUS_EXPR, *delta, BINFO_OFFSET (binfo));
!
! /* Map everything down one to make room for the null PMF. */
! *idx = size_binop (PLUS_EXPR, DECL_VINDEX (fn), integer_one_node);
*pfn = NULL_TREE;
!
! /* Offset from an object of PTR_CLASS to the vptr for ORIG_CLASS. */
! *delta2 = size_binop (PLUS_EXPR, *delta,
! get_vfield_offset (TYPE_BINFO (orig_class)));
}
}