aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJason Merrill <jason@yorick.cygnus.com>1999-07-28 00:45:12 +0000
committerJason Merrill <jason@gcc.gnu.org>1999-07-27 20:45:12 -0400
commit3927874dcd356a857dd2d35d121b4e88c514b635 (patch)
tree291d70577686f8a58a94575fb7ef5a4be75971b6
parent2401a452d83b88b0d2f441740ad159645ec131d6 (diff)
downloadgcc-3927874dcd356a857dd2d35d121b4e88c514b635.zip
gcc-3927874dcd356a857dd2d35d121b4e88c514b635.tar.gz
gcc-3927874dcd356a857dd2d35d121b4e88c514b635.tar.bz2
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
-rw-r--r--gcc/cp/ChangeLog4
-rw-r--r--gcc/cp/cp-tree.h12
-rw-r--r--gcc/cp/typeck.c55
3 files changed, 44 insertions, 27 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 27df6bc..63adc40 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,5 +1,9 @@
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.
+
* 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 4a47e9b..55d94bb 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 905b3e3..e62f7e3 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)));
}
}