C++ Patch (Was: Virtual Mem Func Ptr Call Fails When Base Class Has No Vtable)
Martin v. Loewis
martinATmira.isdn.cs.tu-berlin.de
Wed Sep 15 01:12:00 GMT 1999
> Yes, sounds like the right fix to me. Please do up the fix and submit
> it.
Attached below. Because of re-indentation, it looks larger than it
actually is.
> `if that function is virtual the function actually called will be the
> final overrider'
Ok. Since that distinguishes between qualified and non-qualified
calls, a word about pointer-to-member calls would have done good.
Regards,
Martin
1999-09-15 Martin v. Loewis <martin@mira.isdn.cs.tu-berlin.de>
* typeck.c (get_member_function_from_ptrfunc): Always consider
virtuality inside member pointer.
// Based on a test case by Andrew Bell <andrew.bell@bigfoot.com>
// Check for pointer-to-virtual-function calls on
// bases without virtual functions.
struct B{};
struct D:B{
virtual void foo();
};
void D::foo(){}
int main()
{
B *b = new D;
void (B::*f)() = static_cast<void (B::*)()>(&D::foo);
(b->*f)();
}
Index: typeck.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/typeck.c,v
retrieving revision 1.209
diff -c -3 -p -r1.209 typeck.c
*** typeck.c 1999/09/13 13:41:30 1.209
--- typeck.c 1999/09/15 08:02:28
*************** get_member_function_from_ptrfunc (instan
*** 2818,2883 ****
NULL_TREE, 0));
e3 = PFN_FROM_PTRMEMFUNC (function);
! if (TYPE_SIZE (basetype) != NULL_TREE
! && ! TYPE_VIRTUAL_P (basetype))
! /* If basetype doesn't have virtual functions, don't emit code to
! handle that case. */
! e1 = e3;
! else
! {
! /* Promoting idx before saving it improves performance on RISC
! targets. Without promoting, the first compare used
! load-with-sign-extend, while the second used normal load then
! shift to sign-extend. An optimizer flaw, perhaps, but it's
! easier to make this change. */
! idx = save_expr (default_conversion
! (build_component_ref (function,
! index_identifier,
! NULL_TREE, 0)));
! e1 = build_binary_op (GE_EXPR, idx, integer_zero_node);
!
! /* Convert down to the right base, before using the instance. */
! instance = convert_pointer_to_real (basetype, instance_ptr);
! if (instance == error_mark_node && instance_ptr != error_mark_node)
! return instance;
!
! vtbl = convert_pointer_to (ptr_type_node, instance);
! delta2 = DELTA2_FROM_PTRMEMFUNC (function);
! vtbl = build
! (PLUS_EXPR,
! build_pointer_type (build_pointer_type (vtable_entry_type)),
! vtbl, cp_convert (ptrdiff_type_node, delta2));
! vtbl = build_indirect_ref (vtbl, NULL_PTR);
! aref = build_array_ref (vtbl, build_binary_op (MINUS_EXPR,
! idx,
! integer_one_node));
! if (! flag_vtable_thunks)
! {
! aref = save_expr (aref);
! delta = build_binary_op
! (PLUS_EXPR,
! build_conditional_expr (e1,
! build_component_ref (aref,
! delta_identifier,
! NULL_TREE, 0),
! integer_zero_node),
! delta);
! }
! if (flag_vtable_thunks)
! e2 = aref;
! else
! e2 = build_component_ref (aref, pfn_identifier, NULL_TREE, 0);
! TREE_TYPE (e2) = TREE_TYPE (e3);
! e1 = build_conditional_expr (e1, e2, e3);
! /* Make sure this doesn't get evaluated first inside one of the
! branches of the COND_EXPR. */
! if (TREE_CODE (instance_ptr) == SAVE_EXPR)
! e1 = build (COMPOUND_EXPR, TREE_TYPE (e1),
! instance_ptr, e1);
}
*instance_ptrptr = build (PLUS_EXPR, TREE_TYPE (instance_ptr),
instance_ptr, delta);
--- 2818,2880 ----
NULL_TREE, 0));
e3 = PFN_FROM_PTRMEMFUNC (function);
! /* This used 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. */
! /* Promoting idx before saving it improves performance on RISC
! targets. Without promoting, the first compare used
! load-with-sign-extend, while the second used normal load then
! shift to sign-extend. An optimizer flaw, perhaps, but it's
! easier to make this change. */
! idx = save_expr (default_conversion
! (build_component_ref (function,
! index_identifier,
! NULL_TREE, 0)));
! e1 = build_binary_op (GE_EXPR, idx, integer_zero_node);
! /* Convert down to the right base, before using the instance. */
! instance = convert_pointer_to_real (basetype, instance_ptr);
! if (instance == error_mark_node && instance_ptr != error_mark_node)
! return instance;
! vtbl = convert_pointer_to (ptr_type_node, instance);
! delta2 = DELTA2_FROM_PTRMEMFUNC (function);
! vtbl = build
! (PLUS_EXPR,
! build_pointer_type (build_pointer_type (vtable_entry_type)),
! vtbl, cp_convert (ptrdiff_type_node, delta2));
! vtbl = build_indirect_ref (vtbl, NULL_PTR);
! aref = build_array_ref (vtbl, build_binary_op (MINUS_EXPR,
! idx,
! integer_one_node));
! if (! flag_vtable_thunks)
! {
! aref = save_expr (aref);
!
! delta = build_binary_op
! (PLUS_EXPR,
! build_conditional_expr (e1,
! build_component_ref (aref,
! delta_identifier,
! NULL_TREE, 0),
! integer_zero_node),
! delta);
}
+
+ if (flag_vtable_thunks)
+ e2 = aref;
+ else
+ e2 = build_component_ref (aref, pfn_identifier, NULL_TREE, 0);
+ TREE_TYPE (e2) = TREE_TYPE (e3);
+ e1 = build_conditional_expr (e1, e2, e3);
+
+ /* Make sure this doesn't get evaluated first inside one of the
+ branches of the COND_EXPR. */
+ if (TREE_CODE (instance_ptr) == SAVE_EXPR)
+ e1 = build (COMPOUND_EXPR, TREE_TYPE (e1),
+ instance_ptr, e1);
*instance_ptrptr = build (PLUS_EXPR, TREE_TYPE (instance_ptr),
instance_ptr, delta);
More information about the Gcc-bugs
mailing list