From 63a6a42300a163dd3967ec5df8d537aa11475065 Mon Sep 17 00:00:00 2001 From: mmitchel Date: Tue, 22 Feb 2000 02:30:54 +0000 Subject: [PATCH] * cp-tree.h (CPTI_VTABLE_INDEX_TYPE): New macro. (CPTI_CLASS_STAR_TYPE): Remove. (vtable_index_type): Likewise. (class_star_type_node): Remove. (TYPE_PTRMEMFUNC_FN_TYPE): Adjust for the new ABI. (build_binary_op_nodefault): Remove. * call.c (build_new_op): Use build_binary_op instead of build_binary_op_nodefault. * decl.c (init_decl_processing): Remove class_star_type_node initialization. Make delta_type_node ptrdiff_type_node under the new ABI. Initialize vtable_index_type. (build_ptrmemfunc_type): Build different structures for the new ABI. (build_enumerator): Use build_binary_op instead of build_binary_op_nodefault. * method.c (build_overload_value): Mangle pointers-to-members appropriately under the new ABI. * typeck.c (build_array_ref): Use build_binary_op instead of build_binary_op_nodefault. (get_member_function_from_ptrfunc): Adjust for the new ABI. (build_binary_op_nodefault): Rename to ... (build_binary_op): ... this. Remove old version. Adjust for pointer-to-member comparisons under the new ABI. (build_ptrmemfunc1): Remove dead code. Adjust for the new ABI. (build_ptrmemfunc): Adjust for the new ABI. (expand_ptrmemfunc_cst): Likewise. (delta2_from_ptrmemfunc): Assert that we're not using the new ABI. (pfn_from_ptrmemfunc): Adjust for the new ABI. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@32099 138bc75d-0d04-0410-961f-82ee72b054a4 --- gcc/cp/ChangeLog | 31 ++++ gcc/cp/call.c | 2 +- gcc/cp/cp-tree.h | 28 +++- gcc/cp/decl.c | 60 ++++---- gcc/cp/method.c | 22 ++- gcc/cp/typeck.c | 424 +++++++++++++++++++++++++++++++------------------------ 6 files changed, 345 insertions(+), 222 deletions(-) diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 045902c..346123d 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,34 @@ +2000-02-21 Mark Mitchell + + * cp-tree.h (CPTI_VTABLE_INDEX_TYPE): New macro. + (CPTI_CLASS_STAR_TYPE): Remove. + (vtable_index_type): Likewise. + (class_star_type_node): Remove. + (TYPE_PTRMEMFUNC_FN_TYPE): Adjust for the new ABI. + (build_binary_op_nodefault): Remove. + * call.c (build_new_op): Use build_binary_op instead of + build_binary_op_nodefault. + * decl.c (init_decl_processing): Remove class_star_type_node + initialization. Make delta_type_node ptrdiff_type_node under the + new ABI. Initialize vtable_index_type. + (build_ptrmemfunc_type): Build different structures for the new + ABI. + (build_enumerator): Use build_binary_op instead of + build_binary_op_nodefault. + * method.c (build_overload_value): Mangle pointers-to-members + appropriately under the new ABI. + * typeck.c (build_array_ref): Use build_binary_op instead of + build_binary_op_nodefault. + (get_member_function_from_ptrfunc): Adjust for the new ABI. + (build_binary_op_nodefault): Rename to ... + (build_binary_op): ... this. Remove old version. Adjust for + pointer-to-member comparisons under the new ABI. + (build_ptrmemfunc1): Remove dead code. Adjust for the new ABI. + (build_ptrmemfunc): Adjust for the new ABI. + (expand_ptrmemfunc_cst): Likewise. + (delta2_from_ptrmemfunc): Assert that we're not using the new ABI. + (pfn_from_ptrmemfunc): Adjust for the new ABI. + 2000-02-21 Gabriel Dos Reis * call.c (build_object_call): Compress consecutive calls to diff --git a/gcc/cp/call.c b/gcc/cp/call.c index e996b59..887e2df 100644 --- a/gcc/cp/call.c +++ b/gcc/cp/call.c @@ -3407,7 +3407,7 @@ builtin: case BIT_XOR_EXPR: case TRUTH_ANDIF_EXPR: case TRUTH_ORIF_EXPR: - return build_binary_op_nodefault (code, arg1, arg2, code); + return build_binary_op (code, arg1, arg2); case CONVERT_EXPR: case NEGATE_EXPR: diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 500937b..5337ed3 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -517,6 +517,7 @@ enum cp_tree_index CPTI_WCHAR_DECL, CPTI_VTABLE_ENTRY_TYPE, CPTI_DELTA_TYPE, + CPTI_VTABLE_INDEX_TYPE, CPTI_CLEANUP_TYPE, CPTI_TI_DESC_TYPE, @@ -532,7 +533,6 @@ enum cp_tree_index CPTI_PTMD_DESC_TYPE, CPTI_BASE_DESC_TYPE, - CPTI_CLASS_STAR_TYPE, CPTI_CLASS_TYPE, CPTI_RECORD_TYPE, CPTI_UNION_TYPE, @@ -601,7 +601,12 @@ extern tree cp_global_trees[CPTI_MAX]; #define void_zero_node cp_global_trees[CPTI_VOID_ZERO] #define wchar_decl_node cp_global_trees[CPTI_WCHAR_DECL] #define vtable_entry_type cp_global_trees[CPTI_VTABLE_ENTRY_TYPE] +/* The type used to represent an offset by which to adjust the `this' + pointer in pointer-to-member types and, when not using vtable + thunks, in vtables. */ #define delta_type_node cp_global_trees[CPTI_DELTA_TYPE] +/* The type used to represent an index into the vtable. */ +#define vtable_index_type cp_global_trees[CPTI_VTABLE_INDEX_TYPE] #define ti_desc_type_node cp_global_trees[CPTI_TI_DESC_TYPE] #define bltn_desc_type_node cp_global_trees[CPTI_BLTN_DESC_TYPE] @@ -616,7 +621,6 @@ extern tree cp_global_trees[CPTI_MAX]; #define ptmd_desc_type_node cp_global_trees[CPTI_PTMD_DESC_TYPE] #define base_desc_type_node cp_global_trees[CPTI_BASE_DESC_TYPE] -#define class_star_type_node cp_global_trees[CPTI_CLASS_STAR_TYPE] #define class_type_node cp_global_trees[CPTI_CLASS_TYPE] #define record_type_node cp_global_trees[CPTI_RECORD_TYPE] #define union_type_node cp_global_trees[CPTI_UNION_TYPE] @@ -2498,12 +2502,27 @@ extern int flag_new_for_scope; function. (Of course, the exact values may differ depending on the mangling - scheme, sizes of types, and such.). */ + scheme, sizes of types, and such.). + + Under the new ABI, we do: + + struct { + __P __pfn; + ptrdiff_t __delta; + }; + + (We don't need DELTA2, because the vtable is always the first thing + in the object.) If the function is virtual, then PFN is one plus + twice the index into the vtable; otherwise, it is just a pointer to + the function. */ /* Get the POINTER_TYPE to the METHOD_TYPE associated with this pointer to member function. TYPE_PTRMEMFUNC_P _must_ be true, before using this macro. */ -#define TYPE_PTRMEMFUNC_FN_TYPE(NODE) (TREE_TYPE (TYPE_FIELDS (TREE_TYPE (TREE_CHAIN (TREE_CHAIN (TYPE_FIELDS (NODE))))))) +#define TYPE_PTRMEMFUNC_FN_TYPE(NODE) \ + (flag_new_abi \ + ? (TREE_TYPE (TYPE_FIELDS (NODE))) \ + : (TREE_TYPE (TYPE_FIELDS (TREE_TYPE (TREE_CHAIN (TREE_CHAIN (TYPE_FIELDS (NODE)))))))) /* Returns `A' for a type like `int (A::*)(double)' */ #define TYPE_PTRMEMFUNC_OBJECT_TYPE(NODE) \ @@ -4341,7 +4360,6 @@ extern tree build_function_call_maybe PARAMS ((tree, tree)); extern tree convert_arguments PARAMS ((tree, tree, tree, int)); extern tree build_x_binary_op PARAMS ((enum tree_code, tree, tree)); extern tree build_binary_op PARAMS ((enum tree_code, tree, tree)); -extern tree build_binary_op_nodefault PARAMS ((enum tree_code, tree, tree, enum tree_code)); extern tree build_x_unary_op PARAMS ((enum tree_code, tree)); extern tree build_unary_op PARAMS ((enum tree_code, tree, int)); extern tree unary_complex_lvalue PARAMS ((enum tree_code, tree)); diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index 4551509..cb9ec29 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -222,7 +222,6 @@ tree error_mark_list; tree __ptmf_desc_array_type, __ptmd_desc_array_type; #endif - tree class_star_type_node; tree class_type_node, record_type_node, union_type_node, enum_type_node; tree unknown_type_node; @@ -6207,15 +6206,18 @@ init_decl_processing () int_array_type_node = build_array_type (integer_type_node, array_domain_type); - /* This is just some anonymous class type. Nobody should ever - need to look inside this envelope. */ - class_star_type_node = build_pointer_type (make_aggr_type (RECORD_TYPE)); - - if (flag_huge_objects) + if (flag_new_abi) + delta_type_node = ptrdiff_type_node; + else if (flag_huge_objects) delta_type_node = long_integer_type_node; else delta_type_node = short_integer_type_node; + if (flag_new_abi) + vtable_index_type = ptrdiff_type_node; + else + vtable_index_type = delta_type_node; + default_function_type = build_function_type (integer_type_node, NULL_TREE); @@ -8804,27 +8806,36 @@ build_ptrmemfunc_type (type) unqualified_variant = build_ptrmemfunc_type (TYPE_MAIN_VARIANT (type)); - u = make_aggr_type (UNION_TYPE); - SET_IS_AGGR_TYPE (u, 0); - fields[0] = build_lang_decl (FIELD_DECL, pfn_identifier, type); - fields[1] = build_lang_decl (FIELD_DECL, delta2_identifier, - delta_type_node); - finish_builtin_type (u, "__ptrmemfunc_type", fields, 1, ptr_type_node); - TYPE_NAME (u) = NULL_TREE; - t = make_aggr_type (RECORD_TYPE); - /* Let the front-end know this is a pointer to member function... */ TYPE_PTRMEMFUNC_FLAG (t) = 1; /* ... and not really an aggregate. */ SET_IS_AGGR_TYPE (t, 0); - fields[0] = build_lang_decl (FIELD_DECL, delta_identifier, - delta_type_node); - fields[1] = build_lang_decl (FIELD_DECL, index_identifier, - delta_type_node); - fields[2] = build_lang_decl (FIELD_DECL, pfn_or_delta2_identifier, u); - finish_builtin_type (t, "__ptrmemfunc_type", fields, 2, ptr_type_node); + if (!flag_new_abi) + { + u = make_aggr_type (UNION_TYPE); + SET_IS_AGGR_TYPE (u, 0); + fields[0] = build_lang_decl (FIELD_DECL, pfn_identifier, type); + fields[1] = build_lang_decl (FIELD_DECL, delta2_identifier, + delta_type_node); + finish_builtin_type (u, "__ptrmemfunc_type", fields, 1, ptr_type_node); + TYPE_NAME (u) = NULL_TREE; + + fields[0] = build_lang_decl (FIELD_DECL, delta_identifier, + delta_type_node); + fields[1] = build_lang_decl (FIELD_DECL, index_identifier, + delta_type_node); + fields[2] = build_lang_decl (FIELD_DECL, pfn_or_delta2_identifier, u); + finish_builtin_type (t, "__ptrmemfunc_type", fields, 2, ptr_type_node); + } + else + { + fields[0] = build_lang_decl (FIELD_DECL, pfn_identifier, type); + fields[1] = build_lang_decl (FIELD_DECL, delta_identifier, + delta_type_node); + finish_builtin_type (t, "__ptrmemfunc_type", fields, 1, ptr_type_node); + } /* Zap out the name so that the back-end will give us the debugging information for this anonymous RECORD_TYPE. */ @@ -12777,10 +12788,9 @@ build_enumerator (name, value, enumtype) /* The next value is the previous value ... */ prev_value = DECL_INITIAL (TREE_VALUE (TYPE_VALUES (enumtype))); /* ... plus one. */ - value = build_binary_op_nodefault (PLUS_EXPR, - prev_value, - integer_one_node, - PLUS_EXPR); + value = build_binary_op (PLUS_EXPR, + prev_value, + integer_one_node); if (tree_int_cst_lt (value, prev_value)) cp_error ("overflow in enumeration values at `%D'", name); diff --git a/gcc/cp/method.c b/gcc/cp/method.c index b48e80e..6a12868 100644 --- a/gcc/cp/method.c +++ b/gcc/cp/method.c @@ -851,6 +851,7 @@ build_overload_value (type, value, flags) tree idx; tree pfn; tree delta2; + tree fn; my_friendly_assert (TYPE_PTRMEMFUNC_P (type), 0); @@ -872,17 +873,26 @@ build_overload_value (type, value, flags) my_friendly_assert (TREE_CODE (value) == PTRMEM_CST, 0); expand_ptrmemfunc_cst (value, &delta, &idx, &pfn, &delta2); + fn = PTRMEM_CST_MEMBER (value); build_overload_int (delta, flags); OB_PUTC ('_'); - build_overload_int (idx, flags); - OB_PUTC ('_'); - if (pfn) + if (!flag_new_abi) + { + build_overload_int (idx, flags); + OB_PUTC ('_'); + } + else if (DECL_VIRTUAL_P (fn)) + { + build_overload_int (DECL_VINDEX (fn), flags); + OB_PUTC ('_'); + } + + if (!DECL_VIRTUAL_P (fn)) { numeric_output_need_bar = 0; - build_overload_identifier (DECL_ASSEMBLER_NAME - (PTRMEM_CST_MEMBER (value))); + build_overload_identifier (DECL_ASSEMBLER_NAME (fn)); } - else + else if (!flag_new_abi) { OB_PUTC ('i'); build_overload_int (delta2, flags); diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c index 8264ede..346eb83 100644 --- a/gcc/cp/typeck.c +++ b/gcc/cp/typeck.c @@ -2509,8 +2509,7 @@ build_array_ref (array, idx) return error_mark_node; } - return build_indirect_ref (build_binary_op_nodefault (PLUS_EXPR, ar, - ind, PLUS_EXPR), + return build_indirect_ref (build_binary_op (PLUS_EXPR, ar, ind), "array indexing"); } } @@ -2836,9 +2835,11 @@ get_member_function_from_ptrfunc (instance_ptrptr, function) fntype = TYPE_PTRMEMFUNC_FN_TYPE (TREE_TYPE (function)); basetype = TYPE_METHOD_BASETYPE (TREE_TYPE (fntype)); - delta = cp_convert (ptrdiff_type_node, - build_component_ref (function, delta_identifier, - NULL_TREE, 0)); + /* 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; + e3 = PFN_FROM_PTRMEMFUNC (function); /* This used to avoid checking for virtual functions if basetype @@ -2853,27 +2854,42 @@ get_member_function_from_ptrfunc (instance_ptrptr, function) 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 + if (flag_new_abi) + { + idx = build_binary_op (TRUNC_DIV_EXPR, + build1 (NOP_EXPR, vtable_index_type, e3), + integer_two_node); + e1 = build_binary_op (BIT_AND_EXPR, + build1 (NOP_EXPR, vtable_index_type, e3), + integer_one_node); + } + else + { + 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; + e1 = build_binary_op (GE_EXPR, idx, integer_zero_node); + idx = build_binary_op (MINUS_EXPR, idx, integer_one_node); + } vtbl = convert_pointer_to (ptr_type_node, instance); - delta2 = DELTA2_FROM_PTRMEMFUNC (function); + delta = cp_convert (ptrdiff_type_node, + build_component_ref (function, delta_identifier, + NULL_TREE, 0)); + if (flag_new_abi) + /* DELTA2 is the amount by which to adjust the `this' pointer + to find the vtbl. */ + delta2 = delta; + else + 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)); + aref = build_array_ref (vtbl, idx); + if (! flag_vtable_thunks) { aref = save_expr (aref); @@ -3237,14 +3253,6 @@ build_x_binary_op (code, arg1, arg2) return build_new_op (code, LOOKUP_NORMAL, arg1, arg2, NULL_TREE); } -tree -build_binary_op (code, arg1, arg2) - enum tree_code code; - tree arg1, arg2; -{ - return build_binary_op_nodefault (code, arg1, arg2, code); -} - /* Build a binary-operation expression without default conversions. CODE is the kind of expression to build. This function differs from `build' in several ways: @@ -3255,9 +3263,6 @@ build_binary_op (code, arg1, arg2) are done in the narrower type when that gives the same result). Constant folding is also done before the result is returned. - ERROR_CODE is the code that determines what to say in error messages. - It is usually, but not always, the same as CODE. - Note that the operands will never have enumeral types because either they have just had the default conversions performed or they have both just been converted to some other type in which @@ -3267,10 +3272,9 @@ build_binary_op (code, arg1, arg2) multiple inheritance, and deal with pointer to member functions. */ tree -build_binary_op_nodefault (code, orig_op0, orig_op1, error_code) +build_binary_op (code, orig_op0, orig_op1) enum tree_code code; tree orig_op0, orig_op1; - enum tree_code error_code; { tree op0, op1; register enum tree_code code0, code1; @@ -3626,102 +3630,98 @@ build_binary_op_nodefault (code, orig_op0, orig_op1, error_code) } else if (TYPE_PTRMEMFUNC_P (type0) && null_ptr_cst_p (op1)) { - op0 = build_component_ref (op0, index_identifier, NULL_TREE, 0); - op1 = integer_zero_node; + if (flag_new_abi) + { + op0 = build_component_ref (op0, pfn_identifier, NULL_TREE, 0); + op1 = cp_convert (TREE_TYPE (op0), integer_zero_node); + } + else + { + op0 = build_component_ref (op0, index_identifier, NULL_TREE, 0); + op1 = integer_zero_node; + } result_type = TREE_TYPE (op0); } else if (TYPE_PTRMEMFUNC_P (type1) && null_ptr_cst_p (op0)) - { - op0 = build_component_ref (op1, index_identifier, NULL_TREE, 0); - op1 = integer_zero_node; - result_type = TREE_TYPE (op0); - } + return build_binary_op (code, op1, op0); else if (TYPE_PTRMEMFUNC_P (type0) && TYPE_PTRMEMFUNC_P (type1) && same_type_p (type0, type1)) { - /* The code we generate for the test is: - - (op0.index == op1.index - && ((op1.index != -1 && op0.delta2 == op1.delta2) - || op0.pfn == op1.pfn)) */ - - tree index0 = build_component_ref (op0, index_identifier, - NULL_TREE, 0); - tree index1 = save_expr (build_component_ref (op1, index_identifier, - NULL_TREE, 0)); - tree pfn0 = PFN_FROM_PTRMEMFUNC (op0); - tree pfn1 = PFN_FROM_PTRMEMFUNC (op1); - tree delta20 = DELTA2_FROM_PTRMEMFUNC (op0); - tree delta21 = DELTA2_FROM_PTRMEMFUNC (op1); - tree e1, e2, e3; - tree integer_neg_one_node - = build_binary_op (MINUS_EXPR, integer_zero_node, - integer_one_node); - e1 = build_binary_op (EQ_EXPR, index0, index1); - e2 = build_binary_op (NE_EXPR, index1, integer_neg_one_node); - e2 = build_binary_op (TRUTH_ANDIF_EXPR, e2, - build_binary_op (EQ_EXPR, delta20, delta21)); - /* We can't use build_binary_op for this cmp because it would get - confused by the ptr to method types and think we want pmfs. */ - e3 = build (EQ_EXPR, boolean_type_node, pfn0, pfn1); - e2 = build_binary_op (TRUTH_ORIF_EXPR, e2, e3); - e2 = build_binary_op (TRUTH_ANDIF_EXPR, e1, e2); - if (code == EQ_EXPR) - return e2; - return build_binary_op (EQ_EXPR, e2, integer_zero_node); - } - else if (TYPE_PTRMEMFUNC_P (type0) - && same_type_p (TYPE_PTRMEMFUNC_FN_TYPE (type0), type1)) - { - tree index0 = build_component_ref (op0, index_identifier, - NULL_TREE, 0); - tree index1; - tree pfn0 = PFN_FROM_PTRMEMFUNC (op0); - tree delta20 = DELTA2_FROM_PTRMEMFUNC (op0); - tree delta21 = integer_zero_node; - tree e1, e2, e3; - tree integer_neg_one_node - = build_binary_op (MINUS_EXPR, integer_zero_node, integer_one_node); - if (TREE_CODE (TREE_OPERAND (op1, 0)) == FUNCTION_DECL - && DECL_VINDEX (TREE_OPERAND (op1, 0))) + /* E will be the final comparison. */ + tree e; + /* E1 and E2 are for scratch. */ + tree e1; + tree e2; + + if (flag_new_abi) { - /* Map everything down one to make room for - the null pointer to member. */ - index1 = size_binop (PLUS_EXPR, - DECL_VINDEX (TREE_OPERAND (op1, 0)), - integer_one_node); - op1 = integer_zero_node; - delta21 = TYPE_VFIELD (TYPE_METHOD_BASETYPE - (TREE_TYPE (type1))); - delta21 = DECL_FIELD_BITPOS (delta21); - delta21 = size_binop (FLOOR_DIV_EXPR, delta21, - size_int (BITS_PER_UNIT)); - delta21 = convert (sizetype, delta21); + /* We generate: + + (op0.pfn == op1.pfn + && (!op0.pfn || op0.delta == op1.delta)) + + The reason for the `!op0.pfn' bit is that a NULL + pointer-to-member is any member with a zero PFN; the + DELTA field is unspecified. */ + tree pfn0; + tree pfn1; + tree delta0; + tree delta1; + + pfn0 = pfn_from_ptrmemfunc (op0); + pfn1 = pfn_from_ptrmemfunc (op1); + delta0 = build_component_ref (op0, delta_identifier, + NULL_TREE, 0); + delta1 = build_component_ref (op1, delta_identifier, + NULL_TREE, 0); + e1 = build_binary_op (EQ_EXPR, delta0, delta1); + e2 = build_binary_op (NE_EXPR, + pfn0, + cp_convert (TREE_TYPE (pfn0), + integer_zero_node)); + e1 = build_binary_op (TRUTH_ORIF_EXPR, e1, e2); + e2 = build (EQ_EXPR, boolean_type_node, pfn0, pfn1); + e = build_binary_op (TRUTH_ANDIF_EXPR, e2, e1); } else - index1 = integer_neg_one_node; - { - tree nop1 = build1 (NOP_EXPR, TYPE_PTRMEMFUNC_FN_TYPE (type0), - op1); - TREE_CONSTANT (nop1) = TREE_CONSTANT (op1); - op1 = nop1; - } - e1 = build_binary_op (EQ_EXPR, index0, index1); - e2 = build_binary_op (NE_EXPR, index1, integer_neg_one_node); - e2 = build_binary_op (TRUTH_ANDIF_EXPR, e2, - build_binary_op (EQ_EXPR, delta20, delta21)); - /* We can't use build_binary_op for this cmp because it would get + { + /* The code we generate for the test is: + + (op0.index == op1.index + && ((op1.index != -1 && op0.delta2 == op1.delta2) + || op0.pfn == op1.pfn)) */ + + tree index0 = build_component_ref (op0, index_identifier, + NULL_TREE, 0); + tree index1 = save_expr (build_component_ref (op1, index_identifier, + NULL_TREE, 0)); + tree pfn0 = PFN_FROM_PTRMEMFUNC (op0); + tree pfn1 = PFN_FROM_PTRMEMFUNC (op1); + tree delta20 = DELTA2_FROM_PTRMEMFUNC (op0); + tree delta21 = DELTA2_FROM_PTRMEMFUNC (op1); + tree e3; + tree integer_neg_one_node + = build_binary_op (MINUS_EXPR, integer_zero_node, + integer_one_node); + e1 = build_binary_op (EQ_EXPR, index0, index1); + e2 = build_binary_op (NE_EXPR, index1, integer_neg_one_node); + e2 = build_binary_op (TRUTH_ANDIF_EXPR, e2, + build_binary_op (EQ_EXPR, delta20, delta21)); + /* We can't use build_binary_op for this cmp because it would get confused by the ptr to method types and think we want pmfs. */ - e3 = build (EQ_EXPR, boolean_type_node, pfn0, op1); - e2 = build_binary_op (TRUTH_ORIF_EXPR, e2, e3); - e2 = build_binary_op (TRUTH_ANDIF_EXPR, e1, e2); + e3 = build (EQ_EXPR, boolean_type_node, pfn0, pfn1); + e2 = build_binary_op (TRUTH_ORIF_EXPR, e2, e3); + e = build_binary_op (TRUTH_ANDIF_EXPR, e1, e2); + } if (code == EQ_EXPR) - return e2; - return build_binary_op (EQ_EXPR, e2, integer_zero_node); - } - else if (TYPE_PTRMEMFUNC_P (type1) - && same_type_p (TYPE_PTRMEMFUNC_FN_TYPE (type1), type0)) - return build_binary_op (code, op1, op0); + return e; + return build_binary_op (EQ_EXPR, e, integer_zero_node); + } + else if ((TYPE_PTRMEMFUNC_P (type0) + && same_type_p (TYPE_PTRMEMFUNC_FN_TYPE (type0), type1)) + || (TYPE_PTRMEMFUNC_P (type1) + && same_type_p (TYPE_PTRMEMFUNC_FN_TYPE (type1), type0))) + my_friendly_abort (20000221); break; case MAX_EXPR: @@ -4059,7 +4059,7 @@ build_binary_op_nodefault (code, orig_op0, orig_op1, error_code) if (!result_type) { cp_error ("invalid operands of types `%T' and `%T' to binary `%O'", - TREE_TYPE (orig_op0), TREE_TYPE (orig_op1), error_code); + TREE_TYPE (orig_op0), TREE_TYPE (orig_op1), code); return error_mark_node; } @@ -6071,77 +6071,101 @@ get_delta_difference (from, to, force) return BINFO_OFFSET (binfo); } +/* Return a constructor for the pointer-to-member-function TYPE using + the other components as specified. */ + tree build_ptrmemfunc1 (type, delta, idx, pfn, delta2) tree type, delta, idx, pfn, delta2; { tree u; + tree delta_field; + tree idx_field; + tree pfn_or_delta2_field; + tree pfn_field; + tree delta2_field; + tree subtype; + int allconstant, allsimple; -#if 0 - /* This is the old way we did it. We want to avoid calling - digest_init, so that it can give an error if we use { } when - initializing a pointer to member function. */ - - if (pfn) + /* Pull the FIELD_DECLs out of the type. */ + if (flag_new_abi) { - u = build_nt (CONSTRUCTOR, NULL_TREE, - tree_cons (pfn_identifier, pfn, NULL_TREE)); + pfn_field = TYPE_FIELDS (type); + delta_field = TREE_CHAIN (pfn_field); + idx_field = NULL_TREE; + pfn_or_delta2_field = NULL_TREE; + delta2_field = NULL_TREE; + subtype = NULL_TREE; } else { - u = build_nt (CONSTRUCTOR, NULL_TREE, - tree_cons (delta2_identifier, delta2, NULL_TREE)); + delta_field = TYPE_FIELDS (type); + idx_field = TREE_CHAIN (delta_field); + pfn_or_delta2_field = TREE_CHAIN (idx_field); + subtype = TREE_TYPE (pfn_or_delta2_field); + pfn_field = TYPE_FIELDS (subtype); + delta2_field = TREE_CHAIN (pfn_field); } - u = build_nt (CONSTRUCTOR, NULL_TREE, - tree_cons (NULL_TREE, delta, - tree_cons (NULL_TREE, idx, - tree_cons (NULL_TREE, u, NULL_TREE)))); - - return digest_init (type, u, (tree*)0); -#else - tree delta_field, idx_field, pfn_or_delta2_field, pfn_field, delta2_field; - tree subtype; - int allconstant, allsimple; + /* Make sure DELTA has the type we want. */ + delta = convert_and_check (delta_type_node, delta); - delta_field = TYPE_FIELDS (type); - idx_field = TREE_CHAIN (delta_field); - pfn_or_delta2_field = TREE_CHAIN (idx_field); - subtype = TREE_TYPE (pfn_or_delta2_field); - pfn_field = TYPE_FIELDS (subtype); - delta2_field = TREE_CHAIN (pfn_field); + /* Keep track of whether the initializer is a) constant, and b) can + be done statically. */ + allconstant = TREE_CONSTANT (delta); + allsimple = (initializer_constant_valid_p (delta, TREE_TYPE (delta)) + != NULL_TREE); if (pfn) { - allconstant = TREE_CONSTANT (pfn); - allsimple = !! initializer_constant_valid_p (pfn, TREE_TYPE (pfn)); - u = tree_cons (pfn_field, pfn, NULL_TREE); + /* A non-virtual function. */ + if (!flag_new_abi) + u = build_tree_list (pfn_field, pfn); + + allconstant &= TREE_CONSTANT (pfn); + allsimple &= (initializer_constant_valid_p (pfn, TREE_TYPE (pfn)) + != NULL_TREE); } else { - delta2 = convert_and_check (delta_type_node, delta2); - allconstant = TREE_CONSTANT (delta2); - allsimple = !! initializer_constant_valid_p (delta2, TREE_TYPE (delta2)); - u = tree_cons (delta2_field, delta2, NULL_TREE); - } - - delta = convert_and_check (delta_type_node, delta); - idx = convert_and_check (delta_type_node, idx); + /* A virtual function. */ + if (flag_new_abi) + { + allconstant &= TREE_CONSTANT (pfn); + allsimple &= (initializer_constant_valid_p (pfn, TREE_TYPE (pfn)) + != NULL_TREE); + } + else + { + idx = convert_and_check (delta_type_node, idx); + u = build_tree_list (delta2_field, delta2); - allconstant = allconstant && TREE_CONSTANT (delta) && TREE_CONSTANT (idx); - allsimple = allsimple - && initializer_constant_valid_p (delta, TREE_TYPE (delta)) - && initializer_constant_valid_p (idx, TREE_TYPE (idx)); + allconstant &= TREE_CONSTANT (idx) && TREE_CONSTANT (delta2); + allsimple &= ((initializer_constant_valid_p (idx, TREE_TYPE (idx)) + != NULL_TREE) + && (initializer_constant_valid_p (delta2, + TREE_TYPE (delta2)) + != NULL_TREE)); + } + } - u = build (CONSTRUCTOR, subtype, NULL_TREE, u); - u = tree_cons (delta_field, delta, - tree_cons (idx_field, idx, - tree_cons (pfn_or_delta2_field, u, NULL_TREE))); + /* Finish creating the initializer. */ + if (flag_new_abi) + u = tree_cons (pfn_field, pfn, + build_tree_list (delta_field, delta)); + else + { + u = build (CONSTRUCTOR, subtype, NULL_TREE, u); + u = tree_cons (delta_field, delta, + tree_cons (idx_field, + idx, + build_tree_list (pfn_or_delta2_field, + u))); + } u = build (CONSTRUCTOR, type, NULL_TREE, u); TREE_CONSTANT (u) = allconstant; TREE_STATIC (u) = allconstant && allsimple; return u; -#endif } /* Build a constructor for a pointer to member function. It can be @@ -6179,15 +6203,33 @@ build_ptrmemfunc (type, pfn, force) cp_error ("invalid conversion to type `%T' from type `%T'", to_type, pfn_type); + /* We don't have to do any conversion to convert a + pointer-to-member to its own type. But, we don't want to + just return a PTRMEM_CST if there's an explicit cast; that + cast should make the expression an invalid template argument. */ + if (TREE_CODE (pfn) != PTRMEM_CST && same_type_p (to_type, pfn_type)) + return pfn; + + if (flag_new_abi) + { + /* Under the new ABI, the conversion is easy. Just adjust + the DELTA field. */ + npfn = build_component_ref (pfn, pfn_identifier, NULL_TREE, 0); + delta = build_component_ref (pfn, delta_identifier, NULL_TREE, 0); + delta = cp_convert (ptrdiff_type_node, delta); + n = get_delta_difference (TYPE_PTRMEMFUNC_OBJECT_TYPE (pfn_type), + TYPE_PTRMEMFUNC_OBJECT_TYPE (to_type), + force); + delta = build_binary_op (PLUS_EXPR, delta, n); + return build_ptrmemfunc1 (to_type, delta, NULL_TREE, npfn, + NULL_TREE); + } + if (TREE_CODE (pfn) == PTRMEM_CST) { /* We could just build the resulting CONSTRUCTOR now, but we don't, relying on the general machinery below, together - with constant-folding, to do the right thing. We don't - want to return a PTRMEM_CST here, since a - pointer-to-member constant is no longer a valid template - argument once it is cast to any type, including its - original type. */ + with constant-folding, to do the right thing. */ expand_ptrmemfunc_cst (pfn, &ndelta, &idx, &npfn, &ndelta2); if (npfn) /* This constant points to a non-virtual function. @@ -6195,12 +6237,6 @@ build_ptrmemfunc (type, pfn, force) matter since we won't use it anyhow. */ ndelta2 = integer_zero_node; } - else if (same_type_p (to_type, pfn_type)) - /* We don't have to do any conversion. Note that we do this - after checking for a PTRMEM_CST so that a PTRMEM_CST, cast - to its own type, will not be considered a legal non-type - template argument. */ - return pfn; else { ndelta = cp_convert (ptrdiff_type_node, @@ -6220,8 +6256,7 @@ build_ptrmemfunc (type, pfn, force) e1 = fold (build (GT_EXPR, boolean_type_node, idx, integer_zero_node)); /* If it's a virtual function, this is what we want. */ - e2 = build_ptrmemfunc1 (to_type, delta, idx, - NULL_TREE, delta2); + e2 = build_ptrmemfunc1 (to_type, delta, idx, NULL_TREE, delta2); pfn = PFN_FROM_PTRMEMFUNC (pfn); npfn = build1 (NOP_EXPR, type, pfn); @@ -6229,8 +6264,7 @@ build_ptrmemfunc (type, pfn, force) /* But if it's a non-virtual function, or NULL, we use this instead. */ - e3 = build_ptrmemfunc1 (to_type, delta, - idx, npfn, NULL_TREE); + e3 = build_ptrmemfunc1 (to_type, delta, idx, npfn, NULL_TREE); return build_conditional_expr (e1, e2, e3); } @@ -6279,7 +6313,10 @@ expand_ptrmemfunc_cst (cst, delta, idx, pfn, delta2) if (!DECL_VIRTUAL_P (fn)) { - *idx = size_binop (MINUS_EXPR, integer_zero_node, integer_one_node); + if (!flag_new_abi) + *idx = size_binop (MINUS_EXPR, integer_zero_node, integer_one_node); + else + *idx = NULL_TREE; *pfn = convert (TYPE_PTRMEMFUNC_FN_TYPE (type), build_addr_func (fn)); *delta2 = NULL_TREE; } @@ -6292,9 +6329,21 @@ expand_ptrmemfunc_cst (cst, delta, idx, pfn, delta2) 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; + if (!flag_new_abi) + { + /* 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; + } + else + { + /* Under the new ABI, we set PFN to twice the index, plus + one. */ + *idx = NULL_TREE; + *pfn = size_binop (MULT_EXPR, DECL_VINDEX (fn), integer_two_node); + *pfn = size_binop (PLUS_EXPR, *pfn, integer_one_node); + *pfn = build1 (NOP_EXPR, TYPE_PTRMEMFUNC_FN_TYPE (type), *pfn); + } /* Offset from an object of PTR_CLASS to the vptr for ORIG_CLASS. */ *delta2 = size_binop (PLUS_EXPR, *delta, @@ -6309,6 +6358,8 @@ tree delta2_from_ptrmemfunc (t) tree t; { + my_friendly_assert (!flag_new_abi, 20000221); + if (TREE_CODE (t) == PTRMEM_CST) { tree delta; @@ -6347,11 +6398,14 @@ pfn_from_ptrmemfunc (t) return pfn; } - return (build_component_ref - (build_component_ref (t, - pfn_or_delta2_identifier, NULL_TREE, - 0), - pfn_identifier, NULL_TREE, 0)); + if (flag_new_abi) + return build_component_ref (t, pfn_identifier, NULL_TREE, 0); + else + return (build_component_ref + (build_component_ref (t, + pfn_or_delta2_identifier, NULL_TREE, + 0), + pfn_identifier, NULL_TREE, 0)); } /* Convert value RHS to type TYPE as preparation for an assignment to -- 2.7.4