}
/* Resolve a pointer to member function. INSTANCE is the object
- instance to use, if the member points to a virtual member. */
+ instance to use, if the member points to a virtual member.
+
+ This used to avoid checking for virtual functions if basetype
+ has no virtual functions, according to an earlier ANSI draft.
+ With the final ISO C++ rules, such an optimization is
+ incorrect: A pointer to a derived member can be static_cast
+ to pointer-to-base-member, as long as the dynamic object
+ later has the right member. */
tree
get_member_function_from_ptrfunc (instance_ptrptr, function)
if (TYPE_PTRMEMFUNC_P (TREE_TYPE (function)))
{
- tree fntype, idx, e1, delta, delta2, e2, e3, vtbl;
- tree instance, basetype;
- tree mask;
+ tree idx, delta, e1, e2, e3, vtbl, basetype;
+ tree fntype = TYPE_PTRMEMFUNC_FN_TYPE (TREE_TYPE (function));
tree instance_ptr = *instance_ptrptr;
-
- if (instance_ptr == error_mark_node
- && TREE_CODE (function) == PTRMEM_CST)
+ if (instance_ptr == error_mark_node)
{
- /* Extracting the function address from a pmf is only
- allowed with -Wno-pmf-conversions. It only works for
- pmf constants. */
- e1 = build_addr_func (PTRMEM_CST_MEMBER (function));
- e1 = convert (TYPE_PTRMEMFUNC_FN_TYPE (TREE_TYPE (function)), e1);
- return e1;
+ if (TREE_CODE (function) == PTRMEM_CST)
+ {
+ /* Extracting the function address from a pmf is only
+ allowed with -Wno-pmf-conversions. It only works for
+ pmf constants. */
+ e1 = build_addr_func (PTRMEM_CST_MEMBER (function));
+ e1 = convert (fntype, e1);
+ return e1;
+ }
+ else
+ {
+ error ("object missing in use of `%E'", function);
+ return error_mark_node;
+ }
}
if (TREE_SIDE_EFFECTS (instance_ptr))
if (TREE_SIDE_EFFECTS (function))
function = save_expr (function);
- fntype = TYPE_PTRMEMFUNC_FN_TYPE (TREE_TYPE (function));
- basetype = TYPE_METHOD_BASETYPE (TREE_TYPE (fntype));
-
- /* Convert down to the right base, before using the instance. */
- instance = lookup_base (TREE_TYPE (TREE_TYPE (instance_ptr)), basetype,
- ba_check, NULL);
- instance = build_base_path (PLUS_EXPR, instance_ptr, instance, 1);
- if (instance == error_mark_node && instance_ptr != error_mark_node)
- return instance;
-
+ /* Start by extracting all the information from the PMF itself. */
e3 = PFN_FROM_PTRMEMFUNC (function);
-
- vtbl = build1 (NOP_EXPR, build_pointer_type (ptr_type_node), instance);
- TREE_CONSTANT (vtbl) = TREE_CONSTANT (instance);
-
- delta = cp_convert (ptrdiff_type_node,
- build_component_ref (function, delta_identifier,
- NULL_TREE, 0));
-
- /* This used to avoid checking for virtual functions if basetype
- has no virtual functions, according to an earlier ANSI draft.
- With the final ISO C++ rules, such an optimization is
- incorrect: A pointer to a derived member can be static_cast
- to pointer-to-base-member, as long as the dynamic object
- later has the right member. */
-
+ delta = build_component_ref (function, delta_identifier, NULL_TREE, 0);
idx = build1 (NOP_EXPR, vtable_index_type, e3);
switch (TARGET_PTRMEMFUNC_VBIT_LOCATION)
{
case ptrmemfunc_vbit_in_pfn:
- /* Mask out the virtual bit from the index. */
e1 = cp_build_binary_op (BIT_AND_EXPR, idx, integer_one_node);
- mask = build1 (NOP_EXPR, vtable_index_type, build_int_2 (~1, ~0));
- idx = cp_build_binary_op (BIT_AND_EXPR, idx, mask);
+ idx = cp_build_binary_op (MINUS_EXPR, idx, integer_one_node);
break;
case ptrmemfunc_vbit_in_delta:
- e1 = cp_build_binary_op (BIT_AND_EXPR,
- delta, integer_one_node);
- delta = cp_build_binary_op (RSHIFT_EXPR,
- build1 (NOP_EXPR, vtable_index_type,
- delta),
- integer_one_node);
+ e1 = cp_build_binary_op (BIT_AND_EXPR, delta, integer_one_node);
+ delta = cp_build_binary_op (RSHIFT_EXPR, delta, integer_one_node);
break;
default:
abort ();
}
- /* DELTA2 is the amount by which to adjust the `this' pointer
- to find the vtbl. */
- delta2 = delta;
- vtbl = build
- (PLUS_EXPR,
- build_pointer_type (build_pointer_type (vtable_entry_type)),
- vtbl, cp_convert (ptrdiff_type_node, delta2));
+ /* Convert down to the right base before using the instance. First
+ use the type... */
+ basetype = TYPE_METHOD_BASETYPE (TREE_TYPE (fntype));
+ basetype = lookup_base (TREE_TYPE (TREE_TYPE (instance_ptr)),
+ basetype, ba_check, NULL);
+ instance_ptr = build_base_path (PLUS_EXPR, instance_ptr, basetype, 1);
+ if (instance_ptr == error_mark_node)
+ return error_mark_node;
+ /* ...and then the delta in the PMF. */
+ instance_ptr = build (PLUS_EXPR, TREE_TYPE (instance_ptr),
+ instance_ptr, delta);
+
+ /* Hand back the adjusted 'this' argument to our caller. */
+ *instance_ptrptr = instance_ptr;
+
+ /* Next extract the vtable pointer from the object. */
+ vtbl = build1 (NOP_EXPR, build_pointer_type (vtbl_ptr_type_node),
+ instance_ptr);
vtbl = build_indirect_ref (vtbl, NULL);
+ /* Finally, extract the function pointer from the vtable. */
e2 = fold (build (PLUS_EXPR, TREE_TYPE (vtbl), vtbl, idx));
e2 = build_indirect_ref (e2, NULL);
e1 = build (COMPOUND_EXPR, TREE_TYPE (e1),
instance_ptr, e1);
- *instance_ptrptr = build (PLUS_EXPR, TREE_TYPE (instance_ptr),
- instance_ptr, delta);
-
- if (instance_ptr == error_mark_node
- && TREE_CODE (e1) != ADDR_EXPR
- && TREE_CODE (TREE_OPERAND (e1, 0)) != FUNCTION_DECL)
- error ("object missing in `%E'", function);
-
function = e1;
}
return function;