From 3927874dcd356a857dd2d35d121b4e88c514b635 Mon Sep 17 00:00:00 2001 From: Jason Merrill Date: Wed, 28 Jul 1999 00:45:12 +0000 Subject: [PATCH] cp-tree.h (DECL_VIRTUAL_CONTEXT): New macro. * cp-tree.h (DECL_VIRTUAL_CONTEXT): New macro. * typeck.c (expand_ptrmemfunc_cst): Calculate delta correctly for virtual functions and MI. Simplify. From-SVN: r28304 --- gcc/cp/ChangeLog | 4 ++++ gcc/cp/cp-tree.h | 12 +++++++---- gcc/cp/typeck.c | 55 ++++++++++++++++++++++++++++-------------------- 3 files changed, 44 insertions(+), 27 deletions(-) diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 27df6bc4d20..63adc40f37c 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,5 +1,9 @@ 1999-07-27 Jason Merrill + * cp-tree.h (DECL_VIRTUAL_CONTEXT): New macro. + * typeck.c (expand_ptrmemfunc_cst): Calculate delta correctly for + virtual functions and MI. Simplify. + * method.c: Remove prototype for largest_union_member. * pt.c (determine_specialization): Fix uninitialized warning. * lex.c (real_yylex): Likewise. diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 4a47e9bcd33..55d94bb36a3 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -212,12 +212,12 @@ struct tree_overload indicating a particular base class, and whose TREE_VALUE is a (possibly overloaded) function from that base class. */ #define BASELINK_P(NODE) \ - (TREE_CODE ((NODE)) == TREE_LIST && TREE_LANG_FLAG_1 ((NODE))) + (TREE_CODE (NODE) == TREE_LIST && TREE_LANG_FLAG_1 (NODE)) #define SET_BASELINK_P(NODE) \ - (TREE_LANG_FLAG_1 ((NODE)) = 1) + (TREE_LANG_FLAG_1 (NODE) = 1) -#define WRAPPER_PTR(NODE) (((struct tree_wrapper*)NODE)->u.ptr) -#define WRAPPER_INT(NODE) (((struct tree_wrapper*)NODE)->u.i) +#define WRAPPER_PTR(NODE) (((struct tree_wrapper*)(NODE))->u.ptr) +#define WRAPPER_INT(NODE) (((struct tree_wrapper*)(NODE))->u.i) struct tree_wrapper { @@ -1404,6 +1404,10 @@ struct lang_decl (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) \ (DECL_CONTEXT (NODE) == NULL_TREE \ diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c index 905b3e3a1b2..e62f7e34e3f 100644 --- a/gcc/cp/typeck.c +++ b/gcc/cp/typeck.c @@ -6078,7 +6078,12 @@ build_x_modify_expr (lhs, modifycode, rhs) /* 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. */ + 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) @@ -6338,37 +6343,41 @@ expand_ptrmemfunc_cst (cst, delta, idx, pfn, delta2) { 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); - - *delta - = get_delta_difference (TYPE_METHOD_BASETYPE (TREE_TYPE (fn)), - TYPE_PTRMEMFUNC_OBJECT_TYPE (type), - /*force=*/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 = 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); + *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 { - *idx = size_binop (PLUS_EXPR, DECL_VINDEX (fn), - integer_one_node); + /* 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; - *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)); + + /* 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))); } } -- 2.30.2