diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 6102f843731..aa6dff611da 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,11 @@ +2002-05-09 Jason Merrill + + * typeck.c (get_member_function_from_ptrfunc): Reorganize. + Use subtraction rather than a bitmask to get the index. + * cvt.c (cp_convert_to_pointer): Bail on an error_mark_node. + + * pt.c (tsubst_expr) [ASM_STMT]: Copy ASM_INPUT_P. + 2002-05-07 Neil Booth * Make-lang.in (decl2.o): Update. diff --git a/gcc/cp/cvt.c b/gcc/cp/cvt.c index b5306c1738f..fc57dd3d744 100644 --- a/gcc/cp/cvt.c +++ b/gcc/cp/cvt.c @@ -130,6 +130,9 @@ cp_convert_to_pointer (type, expr, force) intype = TREE_TYPE (expr); } + if (expr == error_mark_node) + return error_mark_node; + form = TREE_CODE (intype); if (POINTER_TYPE_P (intype)) diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 7551df7b14e..c4e119e10cb 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -7541,12 +7541,13 @@ tsubst_expr (t, args, complain, in_decl) case ASM_STMT: prep_stmt (t); - finish_asm_stmt (ASM_CV_QUAL (t), - tsubst_expr (ASM_STRING (t), args, complain, in_decl), - tsubst_expr (ASM_OUTPUTS (t), args, complain, in_decl), - tsubst_expr (ASM_INPUTS (t), args, complain, in_decl), - tsubst_expr (ASM_CLOBBERS (t), args, complain, - in_decl)); + tmp = finish_asm_stmt + (ASM_CV_QUAL (t), + tsubst_expr (ASM_STRING (t), args, complain, in_decl), + tsubst_expr (ASM_OUTPUTS (t), args, complain, in_decl), + tsubst_expr (ASM_INPUTS (t), args, complain, in_decl), + tsubst_expr (ASM_CLOBBERS (t), args, complain, in_decl)); + ASM_INPUT_P (tmp) = ASM_INPUT_P (t); break; case TRY_BLOCK: diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c index a1050bb7596..329bc3300ca 100644 --- a/gcc/cp/typeck.c +++ b/gcc/cp/typeck.c @@ -2821,7 +2821,14 @@ build_x_function_call (function, params, decl) } /* 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) @@ -2833,21 +2840,26 @@ 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)) @@ -2856,64 +2868,47 @@ get_member_function_from_ptrfunc (instance_ptrptr, function) 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); @@ -2932,14 +2927,6 @@ get_member_function_from_ptrfunc (instance_ptrptr, function) 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;