diff options
author | Mark Mitchell <mark@codesourcery.com> | 2003-07-22 23:30:22 +0000 |
---|---|---|
committer | Mark Mitchell <mmitchel@gcc.gnu.org> | 2003-07-22 23:30:22 +0000 |
commit | a5ac359a6d661735a213b7b6b8436e615e768788 (patch) | |
tree | 74afcc9943903e84e906ee02eba4d464f77fe58b /gcc/cp | |
parent | 938d968ed373057812cd43a9b420399fb65f6c0b (diff) | |
download | gcc-a5ac359a6d661735a213b7b6b8436e615e768788.zip gcc-a5ac359a6d661735a213b7b6b8436e615e768788.tar.gz gcc-a5ac359a6d661735a213b7b6b8436e615e768788.tar.bz2 |
fold-const.c (force_fit_type): Handle OFFSET_TYPE.
* fold-const.c (force_fit_type): Handle OFFSET_TYPE.
* varasam.c (output_constant): Likewise.
2003-07-22 Mark Mitchell <mark@codesourcery.com>
Eliminate use of POINTER_TYPE for pointers-to-members.
* call.c (standard_conversion): Rework pointer-to-member handling.
Add comments.
(add_builtin_candidate): Likewise.
(resolve_scoped_fn_name): Remove.
(build_conditional_expr): Rework pointer-to-member handling.
(compare_ics): Likewise.
* class.c (check_field_decls): Use TYPE_PTR_P.
* cp-lang.c (cp_var_mod_type_p): Rework pointer-to-member
handling.
* cp-tree.h (SCALAR_TYPE_P): Use TYPE_PTR_TO_MEMBER_P.
(TYPE_PTRMEM_P): Add comment.
(TYPE_PTR_P): Simplify.
(TYPE_PTROB_P): Correct definition.
(TYPE_PTR_TO_MEMBER_P): New macro.
(TYPE_PTRMEM_CLASS_TYPE): Adjust.
(TYPE_PTRMEM_POINTED_TO_TYPE): Likewise.
(resolved_scoped_fn_name): Remove declaration.
(build_offset_ref): Change prototype.
(resolve_offset_ref): Remove.
(comp_target_types): Remove.
* cvt.c (cp_convert_to_pointer): Rework pointer-to-member
handling.
(convert_to_reference): Use can_convert.
(ocp_convert): Improve error handling. Rework pointer-to-member
handling.
(perform_qualification_conversions): Rework pointer-to-member
handling.
* decl.c (build_ptrmem_type): Handle functions too.
(create_array_type_for_decl): Remove OFFSET_TYPE error message.
(grokdeclarator): Use OFFSET_TYPE for pointers to data members.
(grokparms): Remove OFFSET_TYPE error message.
* dump.c (cp_dump_tree): Rework pointer-to-member handling.
* error.c (dump_type_prefix): Likewise.
* expr.c (cplus_expand_constant): Use build_nop.
* init.c (build_offset_ref): Add address_p parameter. Fold in
necessary bits from resolve_offset_ref.
(resolve_offset_ref): Remove.
* parser.c (cp_parser_postfix_expression): Remove special case
code for OFFSET_TYPE.
* pt.c (convert_nontype_argument): Rework pointer-to-member
handling.
(convert_template_argument): Likewise.
(unify): Likewise.
(invalid_nontype_parm_type_p): Likewise.
(dependent_type_p_r): Likewise.
* rtti.c (get_tinfo_decl): Remove OFFSET_TYPE special case.
(target_incomplete_p_): Rework pointer-to-member
handling.
(get_pseudo_ti_init): Likewise.
(get_pseudo_ti_desc): Likewise.
* semantics.c (finish_qualified_id_expr): Adjust call to
build_offset_ref. Remove use of resolve_offset_ref.
* tree.c (pod_type_p): Use TYPE_PTR_TO_MEMBER_P.
* typeck.c (target_type): Use TYPE_PTRMEM_P.
(type_unknown_p): Remove obsolete code about the time before
non-dependent expressions were handled correctly.
(qualify_type_recursive): Remove.
(composite_pointer_type_r): New function.
(composite_pointer_type): Use it.
(merge_types): Remove dead comments.
(comp_cv_target_types): Remove.
(comp_target_types): Likewise.
(comp_target_parms): Likewise.
(cxx_sizeof_or_alignof_type): Remove OFFSET_TYPE error.
(build_indirect_ref): Use TYPE_PTR_TO_MEMBER_P.
(build_binary_op): Do not use of comp_target_types.
(pointer_diff): Remove OFFSET_TYPE case.
(build_unary_op): Adjust pointer-to-member handling.
(unary_complex_lvalue): Likewise.
(check_for_casting_away_constness): Add description parameter.
(build_static_cast): Pass it.
(build_reinterpret_cast): Use check_for_casting_away_constness.
(build_const_cast): Adjust pointer-to-member handling.
(build_c_cast): Likewise.
(convert_for_assignment): Remove OFFSET_TYPE error message.
(comp_ptr_ttypes_real): Adjust pointer-to-member handling.
(comp_ptr_ttypes_reinterpret): Remove.
(casts_away_constness_r): Adjust pointer-to-member handling.
(casts_away_constness): Liekwise.
(strip_all_pointer_quals): Remove.
* typeck2.c (digest_init): Adjust pointer-to-member handling.
(build_m_component_ref): Likewise.
From-SVN: r69691
Diffstat (limited to 'gcc/cp')
-rw-r--r-- | gcc/cp/ChangeLog | 86 | ||||
-rw-r--r-- | gcc/cp/call.c | 212 | ||||
-rw-r--r-- | gcc/cp/class.c | 2 | ||||
-rw-r--r-- | gcc/cp/cp-lang.c | 2 | ||||
-rw-r--r-- | gcc/cp/cp-tree.h | 33 | ||||
-rw-r--r-- | gcc/cp/cvt.c | 138 | ||||
-rw-r--r-- | gcc/cp/decl.c | 33 | ||||
-rw-r--r-- | gcc/cp/dump.c | 17 | ||||
-rw-r--r-- | gcc/cp/error.c | 17 | ||||
-rw-r--r-- | gcc/cp/expr.c | 7 | ||||
-rw-r--r-- | gcc/cp/init.c | 163 | ||||
-rw-r--r-- | gcc/cp/parser.c | 11 | ||||
-rw-r--r-- | gcc/cp/pt.c | 114 | ||||
-rw-r--r-- | gcc/cp/rtti.c | 30 | ||||
-rw-r--r-- | gcc/cp/semantics.c | 13 | ||||
-rw-r--r-- | gcc/cp/tree.c | 6 | ||||
-rw-r--r-- | gcc/cp/typeck.c | 655 | ||||
-rw-r--r-- | gcc/cp/typeck2.c | 15 |
18 files changed, 606 insertions, 948 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 55e3127..9827991 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,89 @@ +2003-07-22 Mark Mitchell <mark@codesourcery.com> + + Eliminate use of POINTER_TYPE for pointers-to-members. + * call.c (standard_conversion): Rework pointer-to-member handling. + Add comments. + (add_builtin_candidate): Likewise. + (resolve_scoped_fn_name): Remove. + (build_conditional_expr): Rework pointer-to-member handling. + (compare_ics): Likewise. + * class.c (check_field_decls): Use TYPE_PTR_P. + * cp-lang.c (cp_var_mod_type_p): Rework pointer-to-member + handling. + * cp-tree.h (SCALAR_TYPE_P): Use TYPE_PTR_TO_MEMBER_P. + (TYPE_PTRMEM_P): Add comment. + (TYPE_PTR_P): Simplify. + (TYPE_PTROB_P): Correct definition. + (TYPE_PTR_TO_MEMBER_P): New macro. + (TYPE_PTRMEM_CLASS_TYPE): Adjust. + (TYPE_PTRMEM_POINTED_TO_TYPE): Likewise. + (resolved_scoped_fn_name): Remove declaration. + (build_offset_ref): Change prototype. + (resolve_offset_ref): Remove. + (comp_target_types): Remove. + * cvt.c (cp_convert_to_pointer): Rework pointer-to-member + handling. + (convert_to_reference): Use can_convert. + (ocp_convert): Improve error handling. Rework pointer-to-member + handling. + (perform_qualification_conversions): Rework pointer-to-member + handling. + * decl.c (build_ptrmem_type): Handle functions too. + (create_array_type_for_decl): Remove OFFSET_TYPE error message. + (grokdeclarator): Use OFFSET_TYPE for pointers to data members. + (grokparms): Remove OFFSET_TYPE error message. + * dump.c (cp_dump_tree): Rework pointer-to-member handling. + * error.c (dump_type_prefix): Likewise. + * expr.c (cplus_expand_constant): Use build_nop. + * init.c (build_offset_ref): Add address_p parameter. Fold in + necessary bits from resolve_offset_ref. + (resolve_offset_ref): Remove. + * parser.c (cp_parser_postfix_expression): Remove special case + code for OFFSET_TYPE. + * pt.c (convert_nontype_argument): Rework pointer-to-member + handling. + (convert_template_argument): Likewise. + (unify): Likewise. + (invalid_nontype_parm_type_p): Likewise. + (dependent_type_p_r): Likewise. + * rtti.c (get_tinfo_decl): Remove OFFSET_TYPE special case. + (target_incomplete_p_): Rework pointer-to-member + handling. + (get_pseudo_ti_init): Likewise. + (get_pseudo_ti_desc): Likewise. + * semantics.c (finish_qualified_id_expr): Adjust call to + build_offset_ref. Remove use of resolve_offset_ref. + * tree.c (pod_type_p): Use TYPE_PTR_TO_MEMBER_P. + * typeck.c (target_type): Use TYPE_PTRMEM_P. + (type_unknown_p): Remove obsolete code about the time before + non-dependent expressions were handled correctly. + (qualify_type_recursive): Remove. + (composite_pointer_type_r): New function. + (composite_pointer_type): Use it. + (merge_types): Remove dead comments. + (comp_cv_target_types): Remove. + (comp_target_types): Likewise. + (comp_target_parms): Likewise. + (cxx_sizeof_or_alignof_type): Remove OFFSET_TYPE error. + (build_indirect_ref): Use TYPE_PTR_TO_MEMBER_P. + (build_binary_op): Do not use of comp_target_types. + (pointer_diff): Remove OFFSET_TYPE case. + (build_unary_op): Adjust pointer-to-member handling. + (unary_complex_lvalue): Likewise. + (check_for_casting_away_constness): Add description parameter. + (build_static_cast): Pass it. + (build_reinterpret_cast): Use check_for_casting_away_constness. + (build_const_cast): Adjust pointer-to-member handling. + (build_c_cast): Likewise. + (convert_for_assignment): Remove OFFSET_TYPE error message. + (comp_ptr_ttypes_real): Adjust pointer-to-member handling. + (comp_ptr_ttypes_reinterpret): Remove. + (casts_away_constness_r): Adjust pointer-to-member handling. + (casts_away_constness): Liekwise. + (strip_all_pointer_quals): Remove. + * typeck2.c (digest_init): Adjust pointer-to-member handling. + (build_m_component_ref): Likewise. + 2003-07-22 Wolfgang Bangerth <bangerth@dealii.org> * lex.c (unqualified_fn_lookup_error): Mention that the error diff --git a/gcc/cp/call.c b/gcc/cp/call.c index 022ac78..cbfc5c3 100644 --- a/gcc/cp/call.c +++ b/gcc/cp/call.c @@ -642,11 +642,9 @@ standard_conversion (tree to, tree from, tree expr) if (same_type_p (from, to)) return conv; - if ((tcode == POINTER_TYPE || TYPE_PTRMEMFUNC_P (to)) + if ((tcode == POINTER_TYPE || TYPE_PTR_TO_MEMBER_P (to)) && expr && null_ptr_cst_p (expr)) - { - conv = build_conv (STD_CONV, to, conv); - } + conv = build_conv (STD_CONV, to, conv); else if ((tcode == INTEGER_TYPE && fcode == POINTER_TYPE) || (tcode == POINTER_TYPE && fcode == INTEGER_TYPE)) { @@ -663,33 +661,37 @@ standard_conversion (tree to, tree from, tree expr) conv = build_conv (STD_CONV, to, conv); ICS_BAD_FLAG (conv) = 1; } - else if (tcode == POINTER_TYPE && fcode == POINTER_TYPE) + else if ((tcode == POINTER_TYPE && fcode == POINTER_TYPE) + || (TYPE_PTRMEM_P (to) && TYPE_PTRMEM_P (from))) { - enum tree_code ufcode = TREE_CODE (TREE_TYPE (from)); - enum tree_code utcode = TREE_CODE (TREE_TYPE (to)); + tree to_pointee; + tree from_pointee; - if (same_type_ignoring_top_level_qualifiers_p (TREE_TYPE (from), - TREE_TYPE (to))) + if (tcode == POINTER_TYPE + && same_type_ignoring_top_level_qualifiers_p (TREE_TYPE (from), + TREE_TYPE (to))) ; - else if (utcode == VOID_TYPE && ufcode != OFFSET_TYPE - && ufcode != FUNCTION_TYPE) + else if (VOID_TYPE_P (TREE_TYPE (to)) + && !TYPE_PTRMEM_P (from) + && TREE_CODE (TREE_TYPE (from)) != FUNCTION_TYPE) { from = build_pointer_type (cp_build_qualified_type (void_type_node, cp_type_quals (TREE_TYPE (from)))); conv = build_conv (PTR_CONV, from, conv); } - else if (ufcode == OFFSET_TYPE && utcode == OFFSET_TYPE) + else if (TYPE_PTRMEM_P (from)) { - tree fbase = TYPE_OFFSET_BASETYPE (TREE_TYPE (from)); - tree tbase = TYPE_OFFSET_BASETYPE (TREE_TYPE (to)); + tree fbase = TYPE_PTRMEM_CLASS_TYPE (from); + tree tbase = TYPE_PTRMEM_CLASS_TYPE (to); if (DERIVED_FROM_P (fbase, tbase) && (same_type_ignoring_top_level_qualifiers_p - (TREE_TYPE (TREE_TYPE (from)), - TREE_TYPE (TREE_TYPE (to))))) + (TYPE_PTRMEM_POINTED_TO_TYPE (from), + TYPE_PTRMEM_POINTED_TO_TYPE (to)))) { - from = build_ptrmem_type (tbase, TREE_TYPE (TREE_TYPE (from))); + from = build_ptrmem_type (tbase, + TYPE_PTRMEM_POINTED_TO_TYPE (from)); conv = build_conv (PMEM_CONV, from, conv); } } @@ -706,14 +708,25 @@ standard_conversion (tree to, tree from, tree expr) } } + if (tcode == POINTER_TYPE) + { + to_pointee = TREE_TYPE (to); + from_pointee = TREE_TYPE (from); + } + else + { + to_pointee = to; + from_pointee = from; + } + if (same_type_p (from, to)) /* OK */; - else if (comp_ptr_ttypes (TREE_TYPE (to), TREE_TYPE (from))) + else if (comp_ptr_ttypes (to_pointee, from_pointee)) conv = build_conv (QUAL_CONV, to, conv); else if (expr && string_conv_p (to, expr, 0)) /* converting from string constant to char *. */ conv = build_conv (QUAL_CONV, to, conv); - else if (ptr_reasonably_similar (TREE_TYPE (to), TREE_TYPE (from))) + else if (ptr_reasonably_similar (to_pointee, from_pointee)) { conv = build_conv (PTR_CONV, to, conv); ICS_BAD_FLAG (conv) = 1; @@ -745,14 +758,25 @@ standard_conversion (tree to, tree from, tree expr) } else if (tcode == BOOLEAN_TYPE) { - if (! (INTEGRAL_CODE_P (fcode) || fcode == REAL_TYPE - || fcode == POINTER_TYPE || TYPE_PTRMEMFUNC_P (from))) - return 0; + /* [conv.bool] - conv = build_conv (STD_CONV, to, conv); - if (fcode == POINTER_TYPE - || (TYPE_PTRMEMFUNC_P (from) && ICS_STD_RANK (conv) < PBOOL_RANK)) - ICS_STD_RANK (conv) = PBOOL_RANK; + An rvalue of arithmetic, enumeration, pointer, or pointer to + member type can be converted to an rvalue of type bool. */ + if (ARITHMETIC_TYPE_P (from) + || fcode == ENUMERAL_TYPE + || fcode == POINTER_TYPE + || TYPE_PTR_TO_MEMBER_P (from)) + { + conv = build_conv (STD_CONV, to, conv); + if (fcode == POINTER_TYPE + || TYPE_PTRMEM_P (from) + || (TYPE_PTRMEMFUNC_P (from) + && ICS_STD_RANK (conv) < PBOOL_RANK)) + ICS_STD_RANK (conv) = PBOOL_RANK; + return conv; + } + + return NULL_TREE; } /* We don't check for ENUMERAL_TYPE here because there are no standard conversions to enum type. */ @@ -1592,8 +1616,7 @@ add_builtin_candidate (struct z_candidate **candidates, enum tree_code code, T operator-(T); */ case CONVERT_EXPR: /* unary + */ - if (TREE_CODE (type1) == POINTER_TYPE - && TREE_CODE (TREE_TYPE (type1)) != OFFSET_TYPE) + if (TREE_CODE (type1) == POINTER_TYPE) break; case NEGATE_EXPR: if (ARITHMETIC_TYPE_P (type1)) @@ -1618,12 +1641,10 @@ add_builtin_candidate (struct z_candidate **candidates, enum tree_code code, case MEMBER_REF: if (TREE_CODE (type1) == POINTER_TYPE - && (TYPE_PTRMEMFUNC_P (type2) || TYPE_PTRMEM_P (type2))) + && TYPE_PTR_TO_MEMBER_P (type2)) { tree c1 = TREE_TYPE (type1); - tree c2 = (TYPE_PTRMEMFUNC_P (type2) - ? TYPE_METHOD_BASETYPE (TREE_TYPE (TYPE_PTRMEMFUNC_FN_TYPE (type2))) - : TYPE_OFFSET_BASETYPE (TREE_TYPE (type2))); + tree c2 = TYPE_PTRMEM_CLASS_TYPE (type2); if (IS_AGGR_TYPE (c1) && DERIVED_FROM_P (c2, c1) && (TYPE_PTRMEMFUNC_P (type2) @@ -1693,14 +1714,12 @@ add_builtin_candidate (struct z_candidate **candidates, enum tree_code code, if ((TYPE_PTRMEMFUNC_P (type1) && TYPE_PTRMEMFUNC_P (type2)) || (TYPE_PTRMEM_P (type1) && TYPE_PTRMEM_P (type2))) break; - if ((TYPE_PTRMEMFUNC_P (type1) || TYPE_PTRMEM_P (type1)) - && null_ptr_cst_p (args[1])) + if (TYPE_PTR_TO_MEMBER_P (type1) && null_ptr_cst_p (args[1])) { type2 = type1; break; } - if ((TYPE_PTRMEMFUNC_P (type2) || TYPE_PTRMEM_P (type2)) - && null_ptr_cst_p (args[0])) + if (TYPE_PTR_TO_MEMBER_P (type2) && null_ptr_cst_p (args[0])) { type1 = type2; break; @@ -1871,12 +1890,8 @@ add_builtin_candidate (struct z_candidate **candidates, enum tree_code code, break; /* Otherwise, the types should be pointers. */ - if (!(TREE_CODE (type1) == POINTER_TYPE - || TYPE_PTRMEM_P (type1) - || TYPE_PTRMEMFUNC_P (type1)) - || !(TREE_CODE (type2) == POINTER_TYPE - || TYPE_PTRMEM_P (type2) - || TYPE_PTRMEMFUNC_P (type2))) + if (!(TYPE_PTR_P (type1) || TYPE_PTR_TO_MEMBER_P (type1)) + || !(TYPE_PTR_P (type2) || TYPE_PTR_TO_MEMBER_P (type2))) return; /* We don't check that the two types are the same; the logic @@ -1894,8 +1909,8 @@ add_builtin_candidate (struct z_candidate **candidates, enum tree_code code, if (type2 && !same_type_p (type1, type2) && TREE_CODE (type1) == TREE_CODE (type2) && (TREE_CODE (type1) == REFERENCE_TYPE - || (TREE_CODE (type1) == POINTER_TYPE - && TYPE_PTRMEM_P (type1) == TYPE_PTRMEM_P (type2)) + || (TYPE_PTR_P (type1) && TYPE_PTR_P (type2)) + || (TYPE_PTRMEM_P (type1) && TYPE_PTRMEM_P (type2)) || TYPE_PTRMEMFUNC_P (type1) || IS_AGGR_TYPE (type1) || TREE_CODE (type1) == ENUMERAL_TYPE)) @@ -2605,76 +2620,6 @@ build_user_type_conversion (tree totype, tree expr, int flags) return NULL_TREE; } -/* Find the possibly overloaded set of functions corresponding to a - call of the form SCOPE::NAME (...). NAME might be a - TEMPLATE_ID_EXPR, OVERLOAD, _DECL, or IDENTIFIER_NODE. */ - -tree -resolve_scoped_fn_name (tree scope, tree name) -{ - tree fn = NULL_TREE; - tree template_args = NULL_TREE; - bool is_template_id = TREE_CODE (name) == TEMPLATE_ID_EXPR; - - if (is_template_id) - { - template_args = TREE_OPERAND (name, 1); - name = TREE_OPERAND (name, 0); - } - if (TREE_CODE (name) == OVERLOAD) - name = DECL_NAME (get_first_fn (name)); - - if (TREE_CODE (scope) == NAMESPACE_DECL) - fn = lookup_namespace_name (scope, name); - else if (!CLASS_TYPE_P (scope)) - { - error ("`%T' is not a class type", scope); - return error_mark_node; - } - else - { - if (!TYPE_BEING_DEFINED (scope) - && !COMPLETE_TYPE_P (complete_type (scope))) - { - error ("incomplete type '%T' cannot be used to name a scope", - scope); - return error_mark_node; - } - - if (BASELINK_P (name)) - fn = name; - else - fn = lookup_member (scope, name, /*protect=*/1, /*want_type=*/false); - if (fn && current_class_type) - fn = (adjust_result_of_qualified_name_lookup - (fn, scope, current_class_type)); - - /* It might be the name of a function pointer member. */ - if (fn && TREE_CODE (fn) == FIELD_DECL) - fn = finish_non_static_data_member (fn, current_class_ref, scope); - } - - if (!fn) - { - error ("'%D' has no member named '%E'", scope, name); - return error_mark_node; - } - if (is_template_id) - { - tree fns = fn; - - if (BASELINK_P (fn)) - fns = BASELINK_FUNCTIONS (fns); - fns = build_nt (TEMPLATE_ID_EXPR, fns, template_args); - if (BASELINK_P (fn)) - BASELINK_FUNCTIONS (fn) = fns; - else - fn = fns; - } - - return fn; -} - /* Do any initial processing on the arguments to a function call. */ static tree @@ -3379,15 +3324,12 @@ build_conditional_expr (tree arg1, tree arg2, tree arg3) cv-qualification of either the second or the third operand. The result is of the common type. */ else if ((null_ptr_cst_p (arg2) - && (TYPE_PTR_P (arg3_type) || TYPE_PTRMEM_P (arg3_type) - || TYPE_PTRMEMFUNC_P (arg3_type))) + && (TYPE_PTR_P (arg3_type) || TYPE_PTR_TO_MEMBER_P (arg3_type))) || (null_ptr_cst_p (arg3) - && (TYPE_PTR_P (arg2_type) || TYPE_PTRMEM_P (arg2_type) - || TYPE_PTRMEMFUNC_P (arg2_type))) + && (TYPE_PTR_P (arg2_type) || TYPE_PTR_TO_MEMBER_P (arg2_type))) || (TYPE_PTR_P (arg2_type) && TYPE_PTR_P (arg3_type)) || (TYPE_PTRMEM_P (arg2_type) && TYPE_PTRMEM_P (arg3_type)) - || (TYPE_PTRMEMFUNC_P (arg2_type) - && TYPE_PTRMEMFUNC_P (arg3_type))) + || (TYPE_PTRMEMFUNC_P (arg2_type) && TYPE_PTRMEMFUNC_P (arg3_type))) { result_type = composite_pointer_type (arg2_type, arg3_type, arg2, arg3, "conditional expression"); @@ -5401,25 +5343,17 @@ compare_ics (tree ics1, tree ics2) for pointers A*, except opposite: if B is derived from A then A::* converts to B::*, not vice versa. For that reason, we switch the from_ and to_ variables here. */ - else if (TYPE_PTRMEM_P (from_type1) - && TYPE_PTRMEM_P (from_type2) - && TYPE_PTRMEM_P (to_type1) - && TYPE_PTRMEM_P (to_type2)) - { - deref_to_type1 = TYPE_OFFSET_BASETYPE (TREE_TYPE (from_type1)); - deref_to_type2 = TYPE_OFFSET_BASETYPE (TREE_TYPE (from_type2)); - deref_from_type1 = TYPE_OFFSET_BASETYPE (TREE_TYPE (to_type1)); - deref_from_type2 = TYPE_OFFSET_BASETYPE (TREE_TYPE (to_type2)); - } - else if (TYPE_PTRMEMFUNC_P (from_type1) - && TYPE_PTRMEMFUNC_P (from_type2) - && TYPE_PTRMEMFUNC_P (to_type1) - && TYPE_PTRMEMFUNC_P (to_type2)) - { - deref_to_type1 = TYPE_PTRMEMFUNC_OBJECT_TYPE (from_type1); - deref_to_type2 = TYPE_PTRMEMFUNC_OBJECT_TYPE (from_type2); - deref_from_type1 = TYPE_PTRMEMFUNC_OBJECT_TYPE (to_type1); - deref_from_type2 = TYPE_PTRMEMFUNC_OBJECT_TYPE (to_type2); + else if ((TYPE_PTRMEM_P (from_type1) && TYPE_PTRMEM_P (from_type2) + && TYPE_PTRMEM_P (to_type1) && TYPE_PTRMEM_P (to_type2)) + || (TYPE_PTRMEMFUNC_P (from_type1) + && TYPE_PTRMEMFUNC_P (from_type2) + && TYPE_PTRMEMFUNC_P (to_type1) + && TYPE_PTRMEMFUNC_P (to_type2))) + { + deref_to_type1 = TYPE_PTRMEM_CLASS_TYPE (from_type1); + deref_to_type2 = TYPE_PTRMEM_CLASS_TYPE (from_type2); + deref_from_type1 = TYPE_PTRMEM_CLASS_TYPE (to_type1); + deref_from_type2 = TYPE_PTRMEM_CLASS_TYPE (to_type2); } if (deref_from_type1 != NULL_TREE diff --git a/gcc/cp/class.c b/gcc/cp/class.c index 06cb635..4c46d1c 100644 --- a/gcc/cp/class.c +++ b/gcc/cp/class.c @@ -3078,7 +3078,7 @@ check_field_decls (tree t, tree *access_decls, type = strip_array_types (type); - if (TREE_CODE (type) == POINTER_TYPE) + if (TYPE_PTR_P (type)) has_pointers = 1; if (DECL_MUTABLE_P (x) || TYPE_HAS_MUTABLE_P (type)) diff --git a/gcc/cp/cp-lang.c b/gcc/cp/cp-lang.c index 3c68711..adf6705 100644 --- a/gcc/cp/cp-lang.c +++ b/gcc/cp/cp-lang.c @@ -364,7 +364,7 @@ cp_var_mod_type_p (tree type) { /* If TYPE is a pointer-to-member, it is variably modified if either the class or the member are variably modified. */ - if (TYPE_PTRMEM_P (type) || TYPE_PTRMEMFUNC_P (type)) + if (TYPE_PTR_TO_MEMBER_P (type)) return (variably_modified_type_p (TYPE_PTRMEM_CLASS_TYPE (type)) || variably_modified_type_p (TYPE_PTRMEM_POINTED_TO_TYPE (type))); diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 8fef2de..b466752 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -2421,8 +2421,7 @@ struct lang_decl GTY(()) (ARITHMETIC_TYPE_P (TYPE) \ || TREE_CODE (TYPE) == ENUMERAL_TYPE \ || TYPE_PTR_P (TYPE) \ - || TYPE_PTRMEM_P (TYPE) \ - || TYPE_PTRMEMFUNC_P (TYPE)) + || TYPE_PTR_TO_MEMBER_P (TYPE)) /* [dcl.init.aggr] @@ -2508,14 +2507,15 @@ struct lang_decl GTY(()) #define TYPE_HAS_TRIVIAL_ASSIGN_REF(NODE) \ (TYPE_HAS_ASSIGN_REF (NODE) && ! TYPE_HAS_COMPLEX_ASSIGN_REF (NODE)) -#define TYPE_PTRMEM_P(NODE) \ - (TREE_CODE (NODE) == POINTER_TYPE \ - && TREE_CODE (TREE_TYPE (NODE)) == OFFSET_TYPE) -#define TYPE_PTR_P(NODE) \ - (TREE_CODE (NODE) == POINTER_TYPE \ - && TREE_CODE (TREE_TYPE (NODE)) != OFFSET_TYPE) -#define TYPE_PTROB_P(NODE) \ - (TYPE_PTR_P (NODE) && TREE_CODE (TREE_TYPE (NODE)) != FUNCTION_TYPE \ +/* Returns true if NODE is a pointer-to-data-member. */ +#define TYPE_PTRMEM_P(NODE) \ + (TREE_CODE (NODE) == OFFSET_TYPE) +#define TYPE_PTR_P(NODE) \ + (TREE_CODE (NODE) == POINTER_TYPE) +#define TYPE_PTROB_P(NODE) \ + (TYPE_PTR_P (NODE) \ + && TREE_CODE (TREE_TYPE (NODE)) != FUNCTION_TYPE \ + && TREE_CODE (TREE_TYPE (NODE)) != METHOD_TYPE \ && TREE_CODE (TREE_TYPE (NODE)) != VOID_TYPE) #define TYPE_PTROBV_P(NODE) \ (TYPE_PTR_P (NODE) && TREE_CODE (TREE_TYPE (NODE)) != FUNCTION_TYPE) @@ -2536,6 +2536,10 @@ struct lang_decl GTY(()) #define TYPE_PTRMEMFUNC_FLAG(NODE) \ (LANG_TYPE_CLASS_CHECK (NODE)->ptrmemfunc_flag) +/* Returns true if NODE is a pointer-to-member. */ +#define TYPE_PTR_TO_MEMBER_P(NODE) \ + (TYPE_PTRMEM_P (NODE) || TYPE_PTRMEMFUNC_P (NODE)) + /* Indicates when overload resolution may resolve to a pointer to member function. [expr.unary.op]/3 */ #define PTRMEM_OK_P(NODE) TREE_LANG_FLAG_0 (NODE) @@ -2574,13 +2578,13 @@ struct lang_decl GTY(()) type `const X*'. */ #define TYPE_PTRMEM_CLASS_TYPE(NODE) \ (TYPE_PTRMEM_P (NODE) \ - ? TYPE_OFFSET_BASETYPE (TREE_TYPE (NODE)) \ + ? TYPE_OFFSET_BASETYPE (NODE) \ : TYPE_PTRMEMFUNC_OBJECT_TYPE (NODE)) /* For a pointer-to-member type of the form `T X::*', this is `T'. */ #define TYPE_PTRMEM_POINTED_TO_TYPE(NODE) \ (TYPE_PTRMEM_P (NODE) \ - ? TREE_TYPE (TREE_TYPE (NODE)) \ + ? TREE_TYPE (NODE) \ : TREE_TYPE (TYPE_PTRMEMFUNC_FN_TYPE (NODE))) /* For a pointer-to-member constant `X::Y' this is the RECORD_TYPE for @@ -3527,7 +3531,6 @@ extern tree build_method_call (tree, tree, tree, tree, int); extern bool null_ptr_cst_p (tree); extern bool sufficient_parms_p (tree); extern tree type_decays_to (tree); -extern tree resolve_scoped_fn_name (tree, tree); extern tree build_user_type_conversion (tree, tree, int); extern tree build_new_function_call (tree, tree); extern tree build_operator_new_call (tree, tree, tree *, tree *); @@ -3876,8 +3879,7 @@ extern int is_aggr_type (tree, int); extern tree get_aggr_from_typedef (tree, int); extern tree get_type_value (tree); extern tree build_zero_init (tree, tree, bool); -extern tree build_offset_ref (tree, tree); -extern tree resolve_offset_ref (tree); +extern tree build_offset_ref (tree, tree, bool); extern tree build_new (tree, tree, tree, int); extern tree build_vec_init (tree, tree, tree, int); extern tree build_x_delete (tree, int, tree); @@ -4272,7 +4274,6 @@ extern tree commonparms (tree, tree); extern tree original_type (tree); extern bool comp_except_specs (tree, tree, bool); extern bool comptypes (tree, tree, int); -extern int comp_target_types (tree, tree, int); extern bool compparms (tree, tree); extern int comp_cv_qualification (tree, tree); extern int comp_cv_qual_signature (tree, tree); diff --git a/gcc/cp/cvt.c b/gcc/cp/cvt.c index bc9b309..2cdf395 100644 --- a/gcc/cp/cvt.c +++ b/gcc/cp/cvt.c @@ -180,55 +180,57 @@ cp_convert_to_pointer (tree type, tree expr, bool force) } } - if (TYPE_PTRMEM_P (type) && TYPE_PTRMEM_P (intype)) + if (TYPE_PTRMEMFUNC_P (type)) { - tree b1; - tree b2; - tree binfo; - enum tree_code code = PLUS_EXPR; - base_kind bk; + error ("cannot convert `%E' from type `%T' to type `%T'", + expr, intype, type); + return error_mark_node; + } - b1 = TYPE_OFFSET_BASETYPE (TREE_TYPE (type)); - b2 = TYPE_OFFSET_BASETYPE (TREE_TYPE (intype)); - binfo = lookup_base (b1, b2, ba_check, &bk); - if (!binfo) - { - binfo = lookup_base (b2, b1, ba_check, &bk); - code = MINUS_EXPR; - } - if (binfo == error_mark_node) - return error_mark_node; + return build_nop (type, expr); + } + else if (TYPE_PTRMEM_P (type) && TYPE_PTRMEM_P (intype)) + { + tree b1; + tree b2; + tree binfo; + enum tree_code code = PLUS_EXPR; + base_kind bk; + + b1 = TYPE_PTRMEM_CLASS_TYPE (type); + b2 = TYPE_PTRMEM_CLASS_TYPE (intype); + binfo = lookup_base (b1, b2, ba_check, &bk); + if (!binfo) + { + binfo = lookup_base (b2, b1, ba_check, &bk); + code = MINUS_EXPR; + } + if (binfo == error_mark_node) + return error_mark_node; - if (bk == bk_via_virtual) + if (bk == bk_via_virtual) + { + if (force) + warning ("pointer to member cast from `%T' to `%T' is via virtual base", + intype, type); + else { - if (force) - warning ("pointer to member cast from `%T' to `%T' is via virtual base", - TREE_TYPE (intype), TREE_TYPE (type)); - else - { - error ("pointer to member cast from `%T' to `%T' is via virtual base", - TREE_TYPE (intype), TREE_TYPE (type)); - return error_mark_node; - } - /* This is a reinterpret cast, whose result is unspecified. - We choose to do nothing. */ - return build1 (NOP_EXPR, type, expr); + error ("pointer to member cast from `%T' to `%T' is via virtual base", + intype, type); + return error_mark_node; } - - if (TREE_CODE (expr) == PTRMEM_CST) - expr = cplus_expand_constant (expr); - - if (binfo) - expr = size_binop (code, convert (sizetype, expr), - BINFO_OFFSET (binfo)); - } - else if (TYPE_PTRMEMFUNC_P (type)) - { - error ("cannot convert `%E' from type `%T' to type `%T'", - expr, intype, type); - return error_mark_node; + /* This is a reinterpret cast, whose result is unspecified. + We choose to do nothing. */ + return build1 (NOP_EXPR, type, expr); } + if (TREE_CODE (expr) == PTRMEM_CST) + expr = cplus_expand_constant (expr); + + if (binfo && !integer_zerop (BINFO_OFFSET (binfo))) + expr = size_binop (code, + build_nop (sizetype, expr), + BINFO_OFFSET (binfo)); return build_nop (type, expr); } else if (TYPE_PTRMEMFUNC_P (type) && TYPE_PTRMEMFUNC_P (intype)) @@ -253,8 +255,6 @@ cp_convert_to_pointer (tree type, tree expr, bool force) return error_mark_node; } - my_friendly_assert (form != OFFSET_TYPE, 186); - if (integer_zerop (expr)) { if (TYPE_PTRMEMFUNC_P (type)) @@ -271,8 +271,7 @@ cp_convert_to_pointer (tree type, tree expr, bool force) force_fit_type (expr, 0); return expr; } - else if ((TYPE_PTRMEM_P (type) || TYPE_PTRMEMFUNC_P (type)) - && INTEGRAL_CODE_P (form)) + else if (TYPE_PTR_TO_MEMBER_P (type) && INTEGRAL_CODE_P (form)) { error ("invalid conversion from '%T' to '%T'", intype, type); return error_mark_node; @@ -454,7 +453,7 @@ convert_to_reference (tree reftype, tree expr, int convtype, register tree intype; tree rval = NULL_TREE; tree rval_as_conversion = NULL_TREE; - int i; + bool can_convert_intype_to_type; if (TREE_CODE (type) == FUNCTION_TYPE && TREE_TYPE (expr) == unknown_type_node) @@ -473,9 +472,9 @@ convert_to_reference (tree reftype, tree expr, int convtype, intype = TYPE_MAIN_VARIANT (intype); - i = comp_target_types (type, intype, 0); - - if (i <= 0 && (convtype & CONV_IMPLICIT) && IS_AGGR_TYPE (intype) + can_convert_intype_to_type = can_convert (type, intype); + if (!can_convert_intype_to_type + && (convtype & CONV_IMPLICIT) && IS_AGGR_TYPE (intype) && ! (flags & LOOKUP_NO_CONVERSION)) { /* Look for a user-defined conversion to lvalue that we can use. */ @@ -489,12 +488,12 @@ convert_to_reference (tree reftype, tree expr, int convtype, expr = rval_as_conversion; rval_as_conversion = NULL_TREE; intype = type; - i = 1; + can_convert_intype_to_type = 1; } } - if (((convtype & CONV_STATIC) && i == -1) - || ((convtype & CONV_IMPLICIT) && i == 1)) + if (((convtype & CONV_STATIC) && can_convert (intype, type)) + || ((convtype & CONV_IMPLICIT) && can_convert_intype_to_type)) { if (flags & LOOKUP_COMPLAIN) { @@ -550,8 +549,6 @@ convert_to_reference (tree reftype, tree expr, int convtype, return rval; } - my_friendly_assert (TREE_CODE (intype) != OFFSET_TYPE, 189); - if (flags & LOOKUP_COMPLAIN) error ("cannot convert type `%T' to type `%T'", intype, reftype); @@ -618,8 +615,7 @@ ocp_convert (tree type, tree expr, int convtype, int flags) register tree e = expr; register enum tree_code code = TREE_CODE (type); - if (e == error_mark_node - || TREE_TYPE (e) == error_mark_node) + if (error_operand_p (e) || type == error_mark_node) return error_mark_node; complete_type (type); @@ -671,13 +667,6 @@ ocp_convert (tree type, tree expr, int convtype, int flags) return e; } - /* Just convert to the type of the member. */ - if (code == OFFSET_TYPE) - { - type = TREE_TYPE (type); - code = TREE_CODE (type); - } - if (INTEGRAL_CODE_P (code)) { tree intype = TREE_TYPE (e); @@ -721,8 +710,7 @@ ocp_convert (tree type, tree expr, int convtype, int flags) } return fold (convert_to_integer (type, e)); } - if (code == POINTER_TYPE || code == REFERENCE_TYPE - || TYPE_PTRMEMFUNC_P (type)) + if (POINTER_TYPE_P (type) || TYPE_PTR_TO_MEMBER_P (type)) return fold (cp_convert_to_pointer (type, e, false)); if (code == VECTOR_TYPE) return fold (convert_to_vector (type, e)); @@ -1178,10 +1166,20 @@ type_promotes_to (tree type) tree perform_qualification_conversions (tree type, tree expr) { - if (TREE_CODE (type) == POINTER_TYPE - && TREE_CODE (TREE_TYPE (expr)) == POINTER_TYPE - && comp_ptr_ttypes (TREE_TYPE (type), TREE_TYPE (TREE_TYPE (expr)))) - return build1 (NOP_EXPR, type, expr); + tree expr_type; + + expr_type = TREE_TYPE (expr); + + if (TYPE_PTR_P (type) && TYPE_PTR_P (expr_type) + && comp_ptr_ttypes (TREE_TYPE (type), TREE_TYPE (expr_type))) + return build_nop (type, expr); + else if (TYPE_PTR_TO_MEMBER_P (type) + && TYPE_PTR_TO_MEMBER_P (expr_type) + && same_type_p (TYPE_PTRMEM_CLASS_TYPE (type), + TYPE_PTRMEM_CLASS_TYPE (expr_type)) + && comp_ptr_ttypes (TYPE_PTRMEM_POINTED_TO_TYPE (type), + TYPE_PTRMEM_POINTED_TO_TYPE (expr_type))) + return build_nop (type, expr); else return error_mark_node; } diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index 22137be..7f36c99 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -9284,7 +9284,26 @@ build_ptrmemfunc_type (tree type) tree build_ptrmem_type (tree class_type, tree member_type) { - return build_pointer_type (build_offset_type (class_type, member_type)); + if (TREE_CODE (member_type) == METHOD_TYPE) + { + tree arg_types; + + arg_types = TYPE_ARG_TYPES (member_type); + class_type = (cp_build_qualified_type + (class_type, + cp_type_quals (TREE_TYPE (TREE_VALUE (arg_types))))); + member_type + = build_cplus_method_type (class_type, + TREE_TYPE (member_type), + TREE_CHAIN (arg_types)); + return build_ptrmemfunc_type (build_pointer_type (member_type)); + } + else + { + my_friendly_assert (TREE_CODE (member_type) != FUNCTION_TYPE, + 20030716); + return build_offset_type (class_type, member_type); + } } /* DECL is a VAR_DECL defined in-class, whose TYPE is also given. @@ -9521,10 +9540,6 @@ create_array_type_for_decl (tree name, tree type, tree size) error_msg = "array of references"; break; - case OFFSET_TYPE: - error_msg = "array of data members"; - break; - case METHOD_TYPE: error_msg = "array of function members"; break; @@ -11360,8 +11375,6 @@ grokdeclarator (tree declarator, } else if (TREE_CODE (type) == FUNCTION_TYPE) type = build_pointer_type (type); - else if (TREE_CODE (type) == OFFSET_TYPE) - type = build_pointer_type (type); } { @@ -11991,12 +12004,6 @@ grokparms (tree first_parm) type = build_pointer_type (type); TREE_TYPE (decl) = type; } - else if (TREE_CODE (type) == OFFSET_TYPE) - { - error ("parameter `%D' invalidly declared offset type", decl); - type = build_pointer_type (type); - TREE_TYPE (decl) = type; - } else if (abstract_virtuals_error (decl, type)) any_error = 1; /* Seems like a good idea. */ else if (POINTER_TYPE_P (type)) diff --git a/gcc/cp/dump.c b/gcc/cp/dump.c index c809189..b48f25b 100644 --- a/gcc/cp/dump.c +++ b/gcc/cp/dump.c @@ -237,18 +237,13 @@ cp_dump_tree (void* dump_info, tree t) } break; - case POINTER_TYPE: - if (TYPE_PTRMEM_P (t)) - { - dump_string (di, "ptrmem"); - dump_child ("ptd", TYPE_PTRMEM_POINTED_TO_TYPE (t)); - dump_child ("cls", TYPE_PTRMEM_CLASS_TYPE (t)); - return true; - } - break; + case OFFSET_TYPE: + dump_string (di, "ptrmem"); + dump_child ("ptd", TYPE_PTRMEM_POINTED_TO_TYPE (t)); + dump_child ("cls", TYPE_PTRMEM_CLASS_TYPE (t)); + return true; case RECORD_TYPE: - case UNION_TYPE: if (TYPE_PTRMEMFUNC_P (t)) { dump_string (di, "ptrmem"); @@ -256,7 +251,9 @@ cp_dump_tree (void* dump_info, tree t) dump_child ("cls", TYPE_PTRMEM_CLASS_TYPE (t)); return true; } + /* Fall through. */ + case UNION_TYPE: /* Is it a type used as a base? */ if (TYPE_CONTEXT (t) && TREE_CODE (TYPE_CONTEXT (t)) == TREE_CODE (t) && CLASSTYPE_AS_BASE (TYPE_CONTEXT (t)) == t) diff --git a/gcc/cp/error.c b/gcc/cp/error.c index c547d67..11a548b 100644 --- a/gcc/cp/error.c +++ b/gcc/cp/error.c @@ -587,19 +587,14 @@ dump_type_prefix (tree t, int flags) tree sub = TREE_TYPE (t); padding = dump_type_prefix (sub, flags); - /* A tree for a member pointer looks like pointer to offset, - so let the OFFSET_TYPE case handle it. */ - if (!TYPE_PTRMEM_P (t)) + if (TREE_CODE (sub) == ARRAY_TYPE) { - if (TREE_CODE (sub) == ARRAY_TYPE) - { - output_add_space (scratch_buffer); - print_left_paren (scratch_buffer); - } - output_add_character - (scratch_buffer, "&*"[TREE_CODE (t) == POINTER_TYPE]); - padding = dump_qualifiers (t, before); + output_add_space (scratch_buffer); + print_left_paren (scratch_buffer); } + output_add_character + (scratch_buffer, "&*"[TREE_CODE (t) == POINTER_TYPE]); + padding = dump_qualifiers (t, before); } break; diff --git a/gcc/cp/expr.c b/gcc/cp/expr.c index 160a946..630f078 100644 --- a/gcc/cp/expr.c +++ b/gcc/cp/expr.c @@ -51,11 +51,8 @@ cplus_expand_constant (tree cst) member = PTRMEM_CST_MEMBER (cst); if (TREE_CODE (member) == FIELD_DECL) - { - /* Find the offset for the field. */ - tree offset = byte_position (member); - cst = fold (build1 (NOP_EXPR, type, offset)); - } + /* Find the offset for the field. */ + cst = fold (build_nop (type, byte_position (member))); else { tree delta; diff --git a/gcc/cp/init.c b/gcc/cp/init.c index dad5228..fc10a24 100644 --- a/gcc/cp/init.c +++ b/gcc/cp/init.c @@ -1337,10 +1337,11 @@ get_type_value (tree name) return NULL_TREE; } -/* Build a reference to a member of an aggregate. This is not a - C++ `&', but really something which can have its address taken, - and then act as a pointer to member, for example TYPE :: FIELD - can have its address taken by saying & TYPE :: FIELD. +/* Build a reference to a member of an aggregate. This is not a C++ + `&', but really something which can have its address taken, and + then act as a pointer to member, for example TYPE :: FIELD can have + its address taken by saying & TYPE :: FIELD. ADDRESS_P is true if + this expression is the operand of "&". @@ Prints out lousy diagnostics for operator <typename> @@ fields. @@ -1348,7 +1349,7 @@ get_type_value (tree name) @@ This function should be rewritten and placed in search.c. */ tree -build_offset_ref (tree type, tree name) +build_offset_ref (tree type, tree name, bool address_p) { tree decl; tree member; @@ -1435,8 +1436,33 @@ build_offset_ref (tree type, tree name) return error_mark_node; } + if (!member) + { + error ("`%D' is not a member of type `%T'", name, type); + return error_mark_node; + } + + if (TREE_CODE (member) == TYPE_DECL) + { + TREE_USED (member) = 1; + return member; + } + /* static class members and class-specific enum + values can be returned without further ado. */ + if (TREE_CODE (member) == VAR_DECL || TREE_CODE (member) == CONST_DECL) + { + mark_used (member); + return convert_from_reference (member); + } + + if (TREE_CODE (member) == FIELD_DECL && DECL_C_BIT_FIELD (member)) + { + error ("invalid pointer to bit-field `%D'", member); + return error_mark_node; + } + /* A lot of this logic is now handled in lookup_member. */ - if (member && BASELINK_P (member)) + if (BASELINK_P (member)) { /* Go from the TREE_BASELINK to the member function info. */ tree fnfields = member; @@ -1475,104 +1501,63 @@ build_offset_ref (tree type, tree name) mark_used (t); if (DECL_STATIC_FUNCTION_P (t)) return t; - t = build (OFFSET_REF, TREE_TYPE (t), decl, t); - PTRMEM_OK_P (t) = 1; - return t; + member = t; + } + else + { + TREE_TYPE (fnfields) = unknown_type_node; + member = fnfields; } - - TREE_TYPE (fnfields) = unknown_type_node; - - t = build (OFFSET_REF, unknown_type_node, decl, fnfields); - PTRMEM_OK_P (t) = 1; - return t; } - if (member == NULL_TREE) + if (!address_p) { - error ("`%D' is not a member of type `%T'", name, type); - return error_mark_node; - } + /* If MEMBER is non-static, then the program has fallen afoul of + [expr.prim]: - if (TREE_CODE (member) == TYPE_DECL) - { - TREE_USED (member) = 1; - return member; - } - /* static class members and class-specific enum - values can be returned without further ado. */ - if (TREE_CODE (member) == VAR_DECL || TREE_CODE (member) == CONST_DECL) - { - mark_used (member); - return convert_from_reference (member); - } + An id-expression that denotes a nonstatic data member or + nonstatic member function of a class can only be used: - if (TREE_CODE (member) == FIELD_DECL && DECL_C_BIT_FIELD (member)) - { - error ("invalid pointer to bit-field `%D'", member); - return error_mark_node; - } + -- as part of a class member access (_expr.ref_) in which the + object-expression refers to the member's class or a class + derived from that class, or - /* static class functions too. */ - if (TREE_CODE (member) == FUNCTION_DECL - && TREE_CODE (TREE_TYPE (member)) == FUNCTION_TYPE) - abort (); + -- to form a pointer to member (_expr.unary.op_), or + + -- in the body of a nonstatic member function of that class or + of a class derived from that class (_class.mfct.nonstatic_), or + + -- in a mem-initializer for a constructor for that class or for + a class derived from that class (_class.base.init_). */ + if (DECL_NONSTATIC_MEMBER_FUNCTION_P (member)) + { + /* In Microsoft mode, treat a non-static member function as if + it were a pointer-to-member. */ + if (flag_ms_extensions) + { + member = build (OFFSET_REF, TREE_TYPE (member), decl, member); + PTRMEM_OK_P (member) = 1; + return build_unary_op (ADDR_EXPR, member, 0); + } + error ("invalid use of non-static member function `%D'", member); + return error_mark_node; + } + else if (TREE_CODE (member) == FIELD_DECL) + { + error ("invalid use of non-static data member `%D'", member); + return error_mark_node; + } + return member; + } /* In member functions, the form `type::name' is no longer equivalent to `this->type::name', at least not until resolve_offset_ref. */ - member = build (OFFSET_REF, build_offset_type (type, TREE_TYPE (member)), - decl, member); + member = build (OFFSET_REF, TREE_TYPE (member), decl, member); PTRMEM_OK_P (member) = 1; return member; } -/* If a OFFSET_REF made it through to here, then it did - not have its address taken. */ - -tree -resolve_offset_ref (tree exp) -{ - tree member; - - my_friendly_assert (TREE_CODE (exp) == OFFSET_REF, 20030703); - - member = TREE_OPERAND (exp, 1); - - /* If MEMBER is non-static, then the program has fallen afoul of - [expr.prim]: - - An id-expression that denotes a nonstatic data member or - nonstatic member function of a class can only be used: - - -- as part of a class member access (_expr.ref_) in which the - object-expression refers to the member's class or a class - derived from that class, or - - -- to form a pointer to member (_expr.unary.op_), or - - -- in the body of a nonstatic member function of that class or - of a class derived from that class (_class.mfct.nonstatic_), or - - -- in a mem-initializer for a constructor for that class or for - a class derived from that class (_class.base.init_). */ - if (DECL_NONSTATIC_MEMBER_FUNCTION_P (member)) - { - /* In Microsoft mode, treat a non-static member function as if - it were a pointer-to-member. */ - if (flag_ms_extensions) - return build_unary_op (ADDR_EXPR, exp, 0); - error ("invalid use of non-static member function `%D'", member); - return error_mark_node; - } - else if (TREE_CODE (member) == FIELD_DECL) - { - error ("invalid use of non-static data member `%D'", member); - return error_mark_node; - } - - return member; -} - /* If DECL is a `const' declaration, and its value is a known constant, then return that value. */ diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index df45bb6..3cef2e2 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -3581,17 +3581,6 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p) it does not. Therefore, we have to manually obtain the underlying type here. */ scope = non_reference (scope); - /* If the SCOPE is an OFFSET_TYPE, then we grab the - type of the field. We get an OFFSET_TYPE for - something like: - - S::T.a ... - - Probably, we should not get an OFFSET_TYPE here; - that transformation should be made only if `&S::T' - is written. */ - if (TREE_CODE (scope) == OFFSET_TYPE) - scope = TREE_TYPE (scope); /* The type of the POSTFIX_EXPRESSION must be complete. */ scope = complete_type_or_else (scope, NULL_TREE); diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 774d6d9..61d54b9 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -3004,8 +3004,7 @@ convert_nontype_argument (tree type, tree expr) Check this first since if expr_type is the unknown_type_node we would otherwise complain below. */ ; - else if (TYPE_PTRMEM_P (expr_type) - || TYPE_PTRMEMFUNC_P (expr_type)) + else if (TYPE_PTR_TO_MEMBER_P (expr_type)) { if (TREE_CODE (expr) != PTRMEM_CST) goto bad_argument; @@ -3038,8 +3037,7 @@ convert_nontype_argument (tree type, tree expr) else error ("it must be the address of an object with external linkage"); } - else if (TYPE_PTRMEM_P (expr_type) - || TYPE_PTRMEMFUNC_P (expr_type)) + else if (TYPE_PTR_TO_MEMBER_P (expr_type)) error ("it must be a pointer-to-member of the form `&X::Y'"); return NULL_TREE; @@ -3070,9 +3068,7 @@ convert_nontype_argument (tree type, tree expr) return error_mark_node; } } - else if (INTEGRAL_TYPE_P (expr_type) - || TYPE_PTRMEM_P (expr_type) - || TYPE_PTRMEMFUNC_P (expr_type)) + else if (INTEGRAL_TYPE_P (expr_type) || TYPE_PTR_TO_MEMBER_P (expr_type)) { if (! TREE_CONSTANT (expr)) { @@ -3117,31 +3113,32 @@ convert_nontype_argument (tree type, tree expr) goto non_constant; return expr; - + + case OFFSET_TYPE: + { + tree e; + + /* For a non-type template-parameter of type pointer to data + member, qualification conversions (_conv.qual_) are + applied. */ + e = perform_qualification_conversions (type, expr); + if (TREE_CODE (e) == NOP_EXPR) + /* The call to perform_qualification_conversions will + insert a NOP_EXPR over EXPR to do express conversion, + if necessary. But, that will confuse us if we use + this (converted) template parameter to instantiate + another template; then the thing will not look like a + valid template argument. So, just make a new + constant, of the appropriate type. */ + e = make_ptrmem_cst (type, PTRMEM_CST_MEMBER (expr)); + return e; + } + case POINTER_TYPE: { tree type_pointed_to = TREE_TYPE (type); - if (TYPE_PTRMEM_P (type)) - { - tree e; - - /* For a non-type template-parameter of type pointer to data - member, qualification conversions (_conv.qual_) are - applied. */ - e = perform_qualification_conversions (type, expr); - if (TREE_CODE (e) == NOP_EXPR) - /* The call to perform_qualification_conversions will - insert a NOP_EXPR over EXPR to do express conversion, - if necessary. But, that will confuse us if we use - this (converted) template parameter to instantiate - another template; then the thing will not look like a - valid template argument. So, just make a new - constant, of the appropriate type. */ - e = make_ptrmem_cst (type, PTRMEM_CST_MEMBER (expr)); - return e; - } - else if (TREE_CODE (type_pointed_to) == FUNCTION_TYPE) + if (TREE_CODE (type_pointed_to) == FUNCTION_TYPE) { /* For a non-type template-parameter of type pointer to function, only the function-to-pointer conversion @@ -3421,8 +3418,7 @@ convert_template_argument (tree parm, inner_args = INNERMOST_TEMPLATE_ARGS (args); if (TREE_CODE (arg) == TREE_LIST - && TREE_TYPE (arg) != NULL_TREE - && TREE_CODE (TREE_TYPE (arg)) == OFFSET_TYPE) + && TREE_CODE (TREE_VALUE (arg)) == OFFSET_REF) { /* The template argument was the name of some member function. That's usually @@ -6815,21 +6811,26 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl) } my_friendly_assert (TREE_CODE (type) != METHOD_TYPE, 20011231); if (TREE_CODE (type) == FUNCTION_TYPE) - /* This is really a method type. The cv qualifiers of the - this pointer should _not_ be determined by the cv - qualifiers of the class type. They should be held - somewhere in the FUNCTION_TYPE, but we don't do that at - the moment. Consider - typedef void (Func) () const; - - template <typename T1> void Foo (Func T1::*); - - */ - return build_cplus_method_type (TYPE_MAIN_VARIANT (r), - TREE_TYPE (type), - TYPE_ARG_TYPES (type)); + { + /* This is really a method type. The cv qualifiers of the + this pointer should _not_ be determined by the cv + qualifiers of the class type. They should be held + somewhere in the FUNCTION_TYPE, but we don't do that at + the moment. Consider + typedef void (Func) () const; + + template <typename T1> void Foo (Func T1::*); + + */ + tree method_type; + + method_type = build_cplus_method_type (TYPE_MAIN_VARIANT (r), + TREE_TYPE (type), + TYPE_ARG_TYPES (type)); + return build_ptrmemfunc_type (build_pointer_type (method_type)); + } else - return build_offset_type (r, type); + return build_ptrmem_type (r, type); } case FUNCTION_TYPE: case METHOD_TYPE: @@ -9511,12 +9512,6 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict) } else { - /* If ARG is an offset type, we're trying to unify '*T' with - 'U C::*', which is ill-formed. See the comment in the - POINTER_TYPE case about this ugliness. */ - if (TREE_CODE (arg) == OFFSET_TYPE) - return 1; - /* If PARM is `const T' and ARG is only `int', we don't have a match unless we are allowing additional qualification. If ARG is `const int' and PARM is just `T' that's OK; @@ -9617,18 +9612,6 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict) level of pointers. */ strict |= (strict_in & UNIFY_ALLOW_DERIVED); - if (TREE_CODE (TREE_TYPE (parm)) == OFFSET_TYPE - && TREE_CODE (TREE_TYPE (arg)) == OFFSET_TYPE) - { - /* Avoid getting confused about cv-quals; don't recurse here. - Pointers to members should really be just OFFSET_TYPE, not - this two-level nonsense... */ - - parm = TREE_TYPE (parm); - arg = TREE_TYPE (arg); - goto offset; - } - return unify (tparms, targs, TREE_TYPE (parm), TREE_TYPE (arg), strict); } @@ -9782,7 +9765,6 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict) DEDUCE_EXACT, 0, -1); case OFFSET_TYPE: - offset: if (TREE_CODE (arg) != OFFSET_TYPE) return 1; if (unify (tparms, targs, TYPE_OFFSET_BASETYPE (parm), @@ -11286,9 +11268,7 @@ invalid_nontype_parm_type_p (tree type, tsubst_flags_t complain) return 0; else if (POINTER_TYPE_P (type)) return 0; - else if (TYPE_PTRMEM_P (type)) - return 0; - else if (TYPE_PTRMEMFUNC_P (type)) + else if (TYPE_PTR_TO_MEMBER_P (type)) return 0; else if (TREE_CODE (type) == TEMPLATE_TYPE_PARM) return 0; @@ -11325,7 +11305,7 @@ dependent_type_p_r (tree type) dependent. */ type = TYPE_MAIN_VARIANT (type); /* -- a compound type constructed from any dependent type. */ - if (TYPE_PTRMEM_P (type) || TYPE_PTRMEMFUNC_P (type)) + if (TYPE_PTR_TO_MEMBER_P (type)) return (dependent_type_p (TYPE_PTRMEM_CLASS_TYPE (type)) || dependent_type_p (TYPE_PTRMEM_POINTED_TO_TYPE (type))); diff --git a/gcc/cp/rtti.c b/gcc/cp/rtti.c index 067ddee..fdad47d 100644 --- a/gcc/cp/rtti.c +++ b/gcc/cp/rtti.c @@ -331,8 +331,6 @@ get_tinfo_decl (tree type) return error_mark_node; } - if (TREE_CODE (type) == OFFSET_TYPE) - type = TREE_TYPE (type); if (TREE_CODE (type) == METHOD_TYPE) type = build_function_type (TREE_TYPE (type), TREE_CHAIN (TYPE_ARG_TYPES (type))); @@ -715,19 +713,17 @@ qualifier_flags (tree type) static bool target_incomplete_p (tree type) { - while (TREE_CODE (type) == POINTER_TYPE) + while (true) if (TYPE_PTRMEM_P (type)) { - if (!COMPLETE_TYPE_P (TYPE_PTRMEM_CLASS_TYPE (type))) - return true; - type = TYPE_PTRMEM_POINTED_TO_TYPE (type); + if (!COMPLETE_TYPE_P (TYPE_PTRMEM_CLASS_TYPE (type))) + return true; + type = TYPE_PTRMEM_POINTED_TO_TYPE (type); } - else + else if (TREE_CODE (type) == POINTER_TYPE) type = TREE_TYPE (type); - if (!COMPLETE_OR_VOID_TYPE_P (type)) - return true; - - return false; + else + return !COMPLETE_OR_VOID_TYPE_P (type); } /* Return a CONSTRUCTOR for the common part of the type_info objects. This @@ -999,12 +995,10 @@ get_pseudo_ti_init (tree type, tree var_desc, bool *non_public_p) my_friendly_assert (at_eof, 20021120); switch (TREE_CODE (type)) { + case OFFSET_TYPE: + return ptm_initializer (var_desc, type, non_public_p); case POINTER_TYPE: - if (TYPE_PTRMEM_P (type)) - return ptm_initializer (var_desc, type, non_public_p); - else - return ptr_initializer (var_desc, type, non_public_p); - break; + return ptr_initializer (var_desc, type, non_public_p); case ENUMERAL_TYPE: return generic_initializer (var_desc, type); break; @@ -1164,8 +1158,10 @@ get_pseudo_ti_desc (tree type) { switch (TREE_CODE (type)) { + case OFFSET_TYPE: + return ptm_desc_type_node; case POINTER_TYPE: - return TYPE_PTRMEM_P (type) ? ptm_desc_type_node : ptr_desc_type_node; + return ptr_desc_type_node; case ENUMERAL_TYPE: return enum_desc_type_node; case FUNCTION_TYPE: diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c index c490ab8..102653a 100644 --- a/gcc/cp/semantics.c +++ b/gcc/cp/semantics.c @@ -1367,7 +1367,8 @@ finish_qualified_id_expr (tree qualifying_class, tree expr, bool done, { if (TREE_CODE (expr) == SCOPE_REF) expr = TREE_OPERAND (expr, 1); - expr = build_offset_ref (qualifying_class, expr); + expr = build_offset_ref (qualifying_class, expr, + /*address_p=*/true); return expr; } @@ -1396,13 +1397,9 @@ finish_qualified_id_expr (tree qualifying_class, tree expr, bool done, BASELINK_ACCESS_BINFO (expr), /*preserve_reference=*/false)); else if (done) - { - /* The expression is a qualified name whose address is not - being taken. */ - expr = build_offset_ref (qualifying_class, expr); - if (TREE_CODE (expr) == OFFSET_REF) - expr = resolve_offset_ref (expr); - } + /* The expression is a qualified name whose address is not + being taken. */ + expr = build_offset_ref (qualifying_class, expr, /*address_p=*/false); } return expr; diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c index 59722ac..0fcba63 100644 --- a/gcc/cp/tree.c +++ b/gcc/cp/tree.c @@ -1775,10 +1775,8 @@ pod_type_p (tree t) return 1; if (TYPE_PTR_P (t)) return 1; /* pointer to non-member */ - if (TYPE_PTRMEM_P (t)) - return 1; /* pointer to member object */ - if (TYPE_PTRMEMFUNC_P (t)) - return 1; /* pointer to member function */ + if (TYPE_PTR_TO_MEMBER_P (t)) + return 1; /* pointer to member */ if (! CLASS_TYPE_P (t)) return 0; /* other non-class type (reference or function) */ diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c index 0f1011e..0356cb7aa 100644 --- a/gcc/cp/typeck.c +++ b/gcc/cp/typeck.c @@ -48,22 +48,17 @@ Boston, MA 02111-1307, USA. */ static tree convert_for_assignment (tree, tree, const char *, tree, int); static tree cp_pointer_int_sum (enum tree_code, tree, tree); static tree rationalize_conditional_expr (enum tree_code, tree); -static int comp_target_parms (tree, tree); static int comp_ptr_ttypes_real (tree, tree, int); static int comp_ptr_ttypes_const (tree, tree); -static int comp_ptr_ttypes_reinterpret (tree, tree); static bool comp_except_types (tree, tree, bool); static bool comp_array_types (tree, tree, bool); static tree common_base_type (tree, tree); static tree lookup_anon_field (tree, tree); static tree pointer_diff (tree, tree, tree); -static tree qualify_type_recursive (tree, tree); static tree get_delta_difference (tree, tree, int); -static int comp_cv_target_types (tree, tree, int); static void casts_away_constness_r (tree *, tree *); static bool casts_away_constness (tree, tree); static void maybe_warn_about_returning_address_of_local (tree); -static tree strip_all_pointer_quals (tree); static tree lookup_destructor (tree, tree, tree); /* Return the target type of TYPE, which means return T for: @@ -77,7 +72,7 @@ target_type (tree type) || TREE_CODE (type) == ARRAY_TYPE || TREE_CODE (type) == FUNCTION_TYPE || TREE_CODE (type) == METHOD_TYPE - || TREE_CODE (type) == OFFSET_TYPE) + || TYPE_PTRMEM_P (type)) type = TREE_TYPE (type); return type; } @@ -169,56 +164,9 @@ type_unknown_p (tree exp) { return (TREE_CODE (exp) == OVERLOAD || TREE_CODE (exp) == TREE_LIST - || TREE_TYPE (exp) == unknown_type_node - /* Until we get the type of non type-dependent expressions - correct, we can have non-type dependent expressions with - no type. */ - || (TREE_TYPE (exp) - && TREE_CODE (TREE_TYPE (exp)) == OFFSET_TYPE - && TREE_TYPE (TREE_TYPE (exp)) == unknown_type_node)); + || TREE_TYPE (exp) == unknown_type_node); } -/* Return a pointer or pointer to member type similar to T1, with a - cv-qualification signature that is the union of the cv-qualification - signatures of T1 and T2: [expr.rel], [expr.eq]. */ - -static tree -qualify_type_recursive (tree t1, tree t2) -{ - if ((TYPE_PTR_P (t1) && TYPE_PTR_P (t2)) - || (TYPE_PTRMEM_P (t1) && TYPE_PTRMEM_P (t2))) - { - tree tt1; - tree tt2; - tree b1; - int type_quals; - tree tgt; - tree attributes = (*targetm.merge_type_attributes) (t1, t2); - - if (TYPE_PTRMEM_P (t1)) - { - b1 = TYPE_PTRMEM_CLASS_TYPE (t1); - tt1 = TYPE_PTRMEM_POINTED_TO_TYPE (t1); - tt2 = TYPE_PTRMEM_POINTED_TO_TYPE (t2); - } - else - { - b1 = NULL_TREE; - tt1 = TREE_TYPE (t1); - tt2 = TREE_TYPE (t2); - } - - type_quals = (cp_type_quals (tt1) | cp_type_quals (tt2)); - tgt = qualify_type_recursive (tt1, tt2); - tgt = cp_build_qualified_type (tgt, type_quals); - if (b1) - t1 = build_ptrmem_type (b1, tgt); - else - t1 = build_pointer_type (tgt); - t1 = build_type_attribute_variant (t1, attributes); - } - return t1; -} /* Return the common type of two parameter lists. We assume that comptypes has already been done and returned 1; @@ -447,16 +395,85 @@ type_after_usual_arithmetic_conversions (tree t1, tree t2) } } +/* Subroutine of composite_pointer_type to implement the recursive + case. See that function for documentation fo the parameters. */ + +static tree +composite_pointer_type_r (tree t1, tree t2, const char* location) +{ + tree pointee1; + tree pointee2; + tree result_type; + tree attributes; + + /* Determine the types pointed to by T1 and T2. */ + if (TREE_CODE (t1) == POINTER_TYPE) + { + pointee1 = TREE_TYPE (t1); + pointee2 = TREE_TYPE (t2); + } + else + { + pointee1 = TYPE_PTRMEM_POINTED_TO_TYPE (t1); + pointee2 = TYPE_PTRMEM_POINTED_TO_TYPE (t2); + } + + /* [expr.rel] + + Otherwise, the composite pointer type is a pointer type + similar (_conv.qual_) to the type of one of the operands, + with a cv-qualification signature (_conv.qual_) that is the + union of the cv-qualification signatures of the operand + types. */ + if (same_type_ignoring_top_level_qualifiers_p (pointee1, pointee2)) + result_type = pointee1; + else if ((TREE_CODE (pointee1) == POINTER_TYPE + && TREE_CODE (pointee2) == POINTER_TYPE) + || (TYPE_PTR_TO_MEMBER_P (pointee1) + && TYPE_PTR_TO_MEMBER_P (pointee2))) + result_type = composite_pointer_type_r (pointee1, pointee2, location); + else + { + pedwarn ("%s between distinct pointer types `%T' and `%T' " + "lacks a cast", + location, t1, t2); + result_type = void_type_node; + } + result_type = cp_build_qualified_type (result_type, + (cp_type_quals (pointee1) + | cp_type_quals (pointee2))); + result_type = build_pointer_type (result_type); + /* If the original types were pointers to members, so is the + result. */ + if (TYPE_PTR_TO_MEMBER_P (t1)) + { + if (!same_type_p (TYPE_PTRMEM_CLASS_TYPE (t1), + TYPE_PTRMEM_CLASS_TYPE (t2))) + pedwarn ("%s between distinct pointer types `%T' and `%T' " + "lacks a cast", + location, t1, t2); + result_type = build_ptrmem_type (TYPE_PTRMEM_CLASS_TYPE (t1), + result_type); + } + + /* Merge the attributes. */ + attributes = (*targetm.merge_type_attributes) (t1, t2); + return build_type_attribute_variant (result_type, attributes); +} + /* Return the composite pointer type (see [expr.rel]) for T1 and T2. ARG1 and ARG2 are the values with those types. The LOCATION is a - string describing the current location, in case an error occurs. */ + string describing the current location, in case an error occurs. + + This routine also implements the computation of a common type for + pointers-to-members as per [expr.eq]. */ tree composite_pointer_type (tree t1, tree t2, tree arg1, tree arg2, const char* location) { - tree result_type; - tree attributes; + tree class1; + tree class2; /* [expr.rel] @@ -467,16 +484,6 @@ composite_pointer_type (tree t1, tree t2, tree arg1, tree arg2, if (null_ptr_cst_p (arg2)) return t1; - /* Deal with pointer-to-member functions in the same way as we deal - with pointers to functions. */ - if (TYPE_PTRMEMFUNC_P (t1)) - t1 = TYPE_PTRMEMFUNC_FN_TYPE (t1); - if (TYPE_PTRMEMFUNC_P (t2)) - t2 = TYPE_PTRMEMFUNC_FN_TYPE (t2); - - /* Merge the attributes. */ - attributes = (*targetm.merge_type_attributes) (t1, t2); - /* We have: [expr.rel] @@ -487,45 +494,78 @@ composite_pointer_type (tree t1, tree t2, tree arg1, tree arg2, and cv2. If either type is a pointer to void, make sure it is T1. */ - if (VOID_TYPE_P (TREE_TYPE (t2))) + if (TREE_CODE (t2) == POINTER_TYPE && VOID_TYPE_P (TREE_TYPE (t2))) { tree t; t = t1; t1 = t2; t2 = t; } + /* Now, if T1 is a pointer to void, merge the qualifiers. */ - if (VOID_TYPE_P (TREE_TYPE (t1))) + if (TREE_CODE (t1) == POINTER_TYPE && VOID_TYPE_P (TREE_TYPE (t1))) { + tree attributes; + tree result_type; + if (pedantic && TYPE_PTRFN_P (t2)) pedwarn ("ISO C++ forbids %s between pointer of type `void *' and pointer-to-function", location); - t1 = TREE_TYPE (t1); - t2 = TREE_TYPE (t2); - result_type = cp_build_qualified_type (void_type_node, - (cp_type_quals (t1) - | cp_type_quals (t2))); + result_type + = cp_build_qualified_type (void_type_node, + (cp_type_quals (TREE_TYPE (t1)) + | cp_type_quals (TREE_TYPE (t2)))); result_type = build_pointer_type (result_type); + /* Merge the attributes. */ + attributes = (*targetm.merge_type_attributes) (t1, t2); + return build_type_attribute_variant (result_type, attributes); + } + + /* [expr.eq] permits the application of a pointer conversion to + bring the pointers to a common type. */ + if (TREE_CODE (t1) == POINTER_TYPE && TREE_CODE (t2) == POINTER_TYPE + && CLASS_TYPE_P (TREE_TYPE (t1)) + && CLASS_TYPE_P (TREE_TYPE (t2)) + && !same_type_ignoring_top_level_qualifiers_p (TREE_TYPE (t1), + TREE_TYPE (t2))) + { + class1 = TREE_TYPE (t1); + class2 = TREE_TYPE (t2); + + if (DERIVED_FROM_P (class1, class2)) + t2 = (build_pointer_type + (cp_build_qualified_type (class1, TYPE_QUALS (class2)))); + else if (DERIVED_FROM_P (class2, class1)) + t1 = (build_pointer_type + (cp_build_qualified_type (class2, TYPE_QUALS (class1)))); + else + { + error ("%s between distinct pointer types `%T' and `%T' " + "lacks a cast", location, t1, t2); + return error_mark_node; + } } - else + /* [expr.eq] permits the application of a pointer-to-member + conversion to change the class type of one of the types. */ + else if (TYPE_PTR_TO_MEMBER_P (t1) + && !same_type_p (TYPE_PTRMEM_CLASS_TYPE (t1), + TYPE_PTRMEM_CLASS_TYPE (t2))) { - tree full1 = qualify_type_recursive (t1, t2); - tree full2 = qualify_type_recursive (t2, t1); + class1 = TYPE_PTRMEM_CLASS_TYPE (t1); + class2 = TYPE_PTRMEM_CLASS_TYPE (t2); - int val = comp_target_types (full1, full2, 1); - - if (val > 0) - result_type = full1; - else if (val < 0) - result_type = full2; + if (DERIVED_FROM_P (class1, class2)) + t1 = build_ptrmem_type (class2, TYPE_PTRMEM_POINTED_TO_TYPE (t1)); + else if (DERIVED_FROM_P (class2, class1)) + t2 = build_ptrmem_type (class1, TYPE_PTRMEM_POINTED_TO_TYPE (t2)); else { - pedwarn ("%s between distinct pointer types `%T' and `%T' lacks a cast", - location, t1, t2); - result_type = ptr_type_node; + error ("%s between distinct pointer-to-member types `%T' and `%T' " + "lacks a cast", location, t1, t2); + return error_mark_node; } } - return build_type_attribute_variant (result_type, attributes); + return composite_pointer_type_r (t1, t2, location); } /* Return the merged type of two types. @@ -557,8 +597,6 @@ merge_types (tree t1, tree t2) /* Merge the attributes. */ attributes = (*targetm.merge_type_attributes) (t1, t2); - /* Treat an enum type as the unsigned integer type of the same width. */ - if (TYPE_PTRMEMFUNC_P (t1)) t1 = TYPE_PTRMEMFUNC_FN_TYPE (t1); if (TYPE_PTRMEMFUNC_P (t2)) @@ -706,7 +744,6 @@ common_type (tree t1, tree t2) || (TYPE_PTRMEMFUNC_P (t1) && TYPE_PTRMEMFUNC_P (t2))) return composite_pointer_type (t1, t2, error_mark_node, error_mark_node, "conversion"); - else abort (); } @@ -995,206 +1032,6 @@ comptypes (tree t1, tree t2, int strict) return false; } -/* Subroutine of comp_target-types. Make sure that the cv-quals change - only in the same direction as the target type. */ - -static int -comp_cv_target_types (tree ttl, tree ttr, int nptrs) -{ - int t; - - if (!at_least_as_qualified_p (ttl, ttr) - && !at_least_as_qualified_p (ttr, ttl)) - /* The qualifications are incomparable. */ - return 0; - - if (TYPE_MAIN_VARIANT (ttl) == TYPE_MAIN_VARIANT (ttr)) - return more_qualified_p (ttr, ttl) ? -1 : 1; - - t = comp_target_types (ttl, ttr, nptrs); - if ((t == 1 && at_least_as_qualified_p (ttl, ttr)) - || (t == -1 && at_least_as_qualified_p (ttr, ttl))) - return t; - - return 0; -} - -/* Return 1 or -1 if TTL and TTR are pointers to types that are equivalent, - ignoring their qualifiers, 0 if not. Return 1 means that TTR can be - converted to TTL. Return -1 means that TTL can be converted to TTR but - not vice versa. - - NPTRS is the number of pointers we can strip off and keep cool. - This is used to permit (for aggr A, aggr B) A, B* to convert to A*, - but to not permit B** to convert to A**. - - This should go away. Callers should use can_convert or something - similar instead. (jason 17 Apr 1997) */ - -int -comp_target_types (tree ttl, tree ttr, int nptrs) -{ - ttl = TYPE_MAIN_VARIANT (ttl); - ttr = TYPE_MAIN_VARIANT (ttr); - if (same_type_p (ttl, ttr)) - return 1; - - if (TREE_CODE (ttr) != TREE_CODE (ttl)) - return 0; - - if ((TREE_CODE (ttr) == POINTER_TYPE - || TREE_CODE (ttr) == REFERENCE_TYPE) - /* If we get a pointer with nptrs == 0, we don't allow any tweaking - of the type pointed to. This is necessary for reference init - semantics. We won't get here from a previous call with nptrs == 1; - for multi-level pointers we end up in comp_ptr_ttypes. */ - && nptrs > 0) - { - int is_ptr = TREE_CODE (ttr) == POINTER_TYPE; - - ttl = TREE_TYPE (ttl); - ttr = TREE_TYPE (ttr); - - if (is_ptr) - { - if (TREE_CODE (ttl) == UNKNOWN_TYPE - || TREE_CODE (ttr) == UNKNOWN_TYPE) - return 1; - else if (TREE_CODE (ttl) == VOID_TYPE - && TREE_CODE (ttr) != FUNCTION_TYPE - && TREE_CODE (ttr) != METHOD_TYPE - && TREE_CODE (ttr) != OFFSET_TYPE) - return 1; - else if (TREE_CODE (ttr) == VOID_TYPE - && TREE_CODE (ttl) != FUNCTION_TYPE - && TREE_CODE (ttl) != METHOD_TYPE - && TREE_CODE (ttl) != OFFSET_TYPE) - return -1; - else if (TREE_CODE (ttl) == POINTER_TYPE - || TREE_CODE (ttl) == ARRAY_TYPE) - { - if (comp_ptr_ttypes (ttl, ttr)) - return 1; - else if (comp_ptr_ttypes (ttr, ttl)) - return -1; - return 0; - } - } - - /* Const and volatile mean something different for function types, - so the usual checks are not appropriate. */ - if (TREE_CODE (ttl) == FUNCTION_TYPE || TREE_CODE (ttl) == METHOD_TYPE) - return comp_target_types (ttl, ttr, nptrs - 1); - - return comp_cv_target_types (ttl, ttr, nptrs - 1); - } - - my_friendly_assert (TREE_CODE (ttr) != ARRAY_TYPE, 20030617); - if (TREE_CODE (ttr) == FUNCTION_TYPE || TREE_CODE (ttr) == METHOD_TYPE) - { - tree argsl, argsr; - int saw_contra = 0; - - if (pedantic) - { - if (!same_type_p (TREE_TYPE (ttl), TREE_TYPE (ttr))) - return 0; - } - else - { - switch (comp_target_types (TREE_TYPE (ttl), TREE_TYPE (ttr), -1)) - { - case 0: - return 0; - case -1: - saw_contra = 1; - } - } - - argsl = TYPE_ARG_TYPES (ttl); - argsr = TYPE_ARG_TYPES (ttr); - - /* Compare 'this' here, not in comp_target_parms. */ - if (TREE_CODE (ttr) == METHOD_TYPE) - { - tree tl = TYPE_METHOD_BASETYPE (ttl); - tree tr = TYPE_METHOD_BASETYPE (ttr); - - if (!same_or_base_type_p (tr, tl)) - { - if (same_or_base_type_p (tl, tr)) - saw_contra = 1; - else - return 0; - } - - argsl = TREE_CHAIN (argsl); - argsr = TREE_CHAIN (argsr); - } - - switch (comp_target_parms (argsl, argsr)) - { - case 0: - return 0; - case -1: - saw_contra = 1; - } - - return saw_contra ? -1 : 1; - } - /* for C++ */ - else if (TREE_CODE (ttr) == OFFSET_TYPE) - { - int base; - - /* Contravariance: we can assign a pointer to base member to a pointer - to derived member. Note difference from simple pointer case, where - we can pass a pointer to derived to a pointer to base. */ - if (same_or_base_type_p (TYPE_OFFSET_BASETYPE (ttr), - TYPE_OFFSET_BASETYPE (ttl))) - base = 1; - else if (same_or_base_type_p (TYPE_OFFSET_BASETYPE (ttl), - TYPE_OFFSET_BASETYPE (ttr))) - { - tree tmp = ttl; - ttl = ttr; - ttr = tmp; - base = -1; - } - else - return 0; - - ttl = TREE_TYPE (ttl); - ttr = TREE_TYPE (ttr); - - if (TREE_CODE (ttl) == POINTER_TYPE - || TREE_CODE (ttl) == ARRAY_TYPE) - { - if (comp_ptr_ttypes (ttl, ttr)) - return base; - return 0; - } - else - { - if (comp_cv_target_types (ttl, ttr, nptrs) == 1) - return base; - return 0; - } - } - else if (IS_AGGR_TYPE (ttl)) - { - if (nptrs < 0) - return 0; - if (same_or_base_type_p (ttl, ttr)) - return 1; - if (same_or_base_type_p (ttr, ttl)) - return -1; - return 0; - } - - return 0; -} - /* Returns 1 if TYPE1 is at least as qualified as TYPE2. */ bool @@ -1333,80 +1170,6 @@ compparms (tree parms1, tree parms2) return true; } -/* This really wants return whether or not parameter type lists - would make their owning functions assignment compatible or not. - - The return value is like for comp_target_types. - - This should go away, possibly with the exception of the empty parmlist - conversion; there are no conversions between function types in C++. - (jason 17 Apr 1997) */ - -static int -comp_target_parms (tree parms1, tree parms2) -{ - register tree t1 = parms1, t2 = parms2; - int warn_contravariance = 0; - - /* In C, an unspecified parmlist matches any specified parmlist - whose argument types don't need default promotions. This is not - true for C++, but let's do it anyway for unfixed headers. */ - - if (t1 == 0 && t2 != 0) - { - pedwarn ("ISO C++ prohibits conversion from `%#T' to `(...)'", - parms2); - return self_promoting_args_p (t2); - } - if (t2 == 0) - return self_promoting_args_p (t1); - - for (; t1 || t2; t1 = TREE_CHAIN (t1), t2 = TREE_CHAIN (t2)) - { - tree p1, p2; - - /* If one parmlist is shorter than the other, they fail to match. */ - if (!t1 || !t2) - return 0; - p1 = TREE_VALUE (t1); - p2 = TREE_VALUE (t2); - if (same_type_p (p1, p2)) - continue; - - if (pedantic) - return 0; - - if ((TREE_CODE (p1) == POINTER_TYPE && TREE_CODE (p2) == POINTER_TYPE) - || (TREE_CODE (p1) == REFERENCE_TYPE - && TREE_CODE (p2) == REFERENCE_TYPE)) - { - /* The following is wrong for contravariance, - but many programs depend on it. */ - if (TREE_TYPE (p1) == void_type_node) - continue; - if (TREE_TYPE (p2) == void_type_node) - { - warn_contravariance = 1; - continue; - } - if (IS_AGGR_TYPE (TREE_TYPE (p1)) - && !same_type_ignoring_top_level_qualifiers_p (TREE_TYPE (p1), - TREE_TYPE (p2))) - return 0; - } - /* Note backwards order due to contravariance. */ - if (comp_target_types (p2, p1, 1) <= 0) - { - if (comp_target_types (p1, p2, 1) > 0) - { - warn_contravariance = 1; - continue; - } - return 0; - } - } - return warn_contravariance ? -1 : 1; -} tree cxx_sizeof_or_alignof_type (tree type, enum tree_code op, int complain) @@ -1430,12 +1193,6 @@ cxx_sizeof_or_alignof_type (tree type, enum tree_code op, int complain) pedwarn ("invalid application of `%s' to a member function", op_name); value = size_one_node; } - else if (type_code == OFFSET_TYPE) - { - if (complain) - error ("invalid application of `%s' to non-static member", op_name); - value = size_zero_node; - } else value = c_sizeof_or_alignof_type (complete_type (type), op, complain); @@ -2277,7 +2034,7 @@ build_indirect_ref (tree ptr, const char *errorstring) } /* `pointer' won't be an error_mark_node if we were given a pointer to member, so it's cool to check for this here. */ - else if (TYPE_PTRMEM_P (type) || TYPE_PTRMEMFUNC_P (type)) + else if (TYPE_PTR_TO_MEMBER_P (type)) error ("invalid use of `%s' on pointer to member", errorstring); else if (pointer != error_mark_node) { @@ -3010,7 +2767,8 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1, /* Subtraction of two similar pointers. We must subtract them as integers, then divide by object size. */ if (code0 == POINTER_TYPE && code1 == POINTER_TYPE - && comp_target_types (type0, type1, 1)) + && same_type_ignoring_top_level_qualifiers_p (TREE_TYPE (type0), + TREE_TYPE (type1))) return pointer_diff (op0, op1, common_type (type0, type1)); /* Handle pointer minus int. Just like pointer plus int. */ else if (code0 == POINTER_TYPE && code1 == INTEGER_TYPE) @@ -3172,12 +2930,15 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1, && (code1 == INTEGER_TYPE || code1 == REAL_TYPE || code1 == COMPLEX_TYPE)) short_compare = 1; - else if (code0 == POINTER_TYPE && code1 == POINTER_TYPE) + else if ((code0 == POINTER_TYPE && code1 == POINTER_TYPE) + || (TYPE_PTRMEM_P (type0) && TYPE_PTRMEM_P (type1))) result_type = composite_pointer_type (type0, type1, op0, op1, "comparison"); - else if (code0 == POINTER_TYPE && null_ptr_cst_p (op1)) + else if ((code0 == POINTER_TYPE || TYPE_PTRMEM_P (type0)) + && null_ptr_cst_p (op1)) result_type = type0; - else if (code1 == POINTER_TYPE && null_ptr_cst_p (op0)) + else if ((code1 == POINTER_TYPE || TYPE_PTRMEM_P (type1)) + && null_ptr_cst_p (op0)) result_type = type1; else if (code0 == POINTER_TYPE && code1 == INTEGER_TYPE) { @@ -3656,8 +3417,6 @@ pointer_diff (register tree op0, register tree op1, register tree ptrtype) pedwarn ("ISO C++ forbids using pointer to a function in subtraction"); if (TREE_CODE (target_type) == METHOD_TYPE) pedwarn ("ISO C++ forbids using pointer to a method in subtraction"); - if (TREE_CODE (target_type) == OFFSET_TYPE) - pedwarn ("ISO C++ forbids using pointer to a member in subtraction"); } /* First do the subtraction as integers; @@ -3671,12 +3430,9 @@ pointer_diff (register tree op0, register tree op1, register tree ptrtype) if (!COMPLETE_TYPE_P (TREE_TYPE (TREE_TYPE (op1)))) error ("invalid use of a pointer to an incomplete type in pointer arithmetic"); - op1 = ((TREE_CODE (target_type) == VOID_TYPE - || TREE_CODE (target_type) == FUNCTION_TYPE - || TREE_CODE (target_type) == METHOD_TYPE - || TREE_CODE (target_type) == OFFSET_TYPE) - ? integer_one_node - : size_in_bytes (target_type)); + op1 = (TYPE_PTROB_P (ptrtype) + ? size_in_bytes (target_type) + : integer_one_node); /* Do the division. */ @@ -3999,7 +3755,6 @@ build_unary_op (enum tree_code code, tree xarg, int noconvert) if (TREE_CODE (argtype) == POINTER_TYPE) { - enum tree_code tmp = TREE_CODE (TREE_TYPE (argtype)); tree type = complete_type (TREE_TYPE (argtype)); if (!COMPLETE_OR_VOID_TYPE_P (type)) @@ -4008,8 +3763,7 @@ build_unary_op (enum tree_code code, tree xarg, int noconvert) || code == POSTINCREMENT_EXPR) ? "increment" : "decrement"), TREE_TYPE (argtype)); else if ((pedantic || warn_pointer_arith) - && (tmp == FUNCTION_TYPE || tmp == METHOD_TYPE - || tmp == VOID_TYPE || tmp == OFFSET_TYPE)) + && !TYPE_PTROB_P (argtype)) pedwarn ("ISO C++ forbids %sing a pointer of type `%T'", ((code == PREINCREMENT_EXPR || code == POSTINCREMENT_EXPR) @@ -4072,13 +3826,7 @@ build_unary_op (enum tree_code code, tree xarg, int noconvert) error ("invalid use of `--' on bool variable `%D'", arg); return error_mark_node; } -#if 0 - /* This will only work if someone can convince Kenner to accept - my patch to expand_increment. (jason) */ - val = build (code, TREE_TYPE (arg), arg, inc); -#else val = boolean_increment (code, arg); -#endif } else val = build (code, TREE_TYPE (arg), arg, inc); @@ -4092,6 +3840,10 @@ build_unary_op (enum tree_code code, tree xarg, int noconvert) regardless of NOCONVERT. */ argtype = lvalue_type (arg); + + if (TREE_CODE (arg) == OFFSET_REF) + goto offset_ref; + if (TREE_CODE (argtype) == REFERENCE_TYPE) { arg = build1 @@ -4183,9 +3935,10 @@ build_unary_op (enum tree_code code, tree xarg, int noconvert) " Say `&%T::%D'", base, name); } - arg = build_offset_ref (base, name); + arg = build_offset_ref (base, name, /*address_p=*/true); } - + + offset_ref: if (type_unknown_p (arg)) return build1 (ADDR_EXPR, unknown_type_node, arg); @@ -4338,11 +4091,8 @@ unary_complex_lvalue (enum tree_code code, tree arg) if (TREE_CODE (TREE_TYPE (arg)) == FUNCTION_TYPE || TREE_CODE (TREE_TYPE (arg)) == METHOD_TYPE - || TREE_CODE (TREE_TYPE (arg)) == OFFSET_TYPE) + || TREE_CODE (arg) == OFFSET_REF) { - /* The representation of something of type OFFSET_TYPE - is really the representation of a pointer to it. - Here give the representation its true type. */ tree t; my_friendly_assert (TREE_CODE (arg) != SCOPE_REF, 313); @@ -4599,14 +4349,16 @@ build_compound_expr (tree list) } /* Issue an error message if casting from SRC_TYPE to DEST_TYPE casts - away constness. */ + away constness. DESCRIPTION explains what operation is taking + place. */ static void -check_for_casting_away_constness (tree src_type, tree dest_type) +check_for_casting_away_constness (tree src_type, tree dest_type, + const char *description) { if (casts_away_constness (src_type, dest_type)) - error ("static_cast from type `%T' to type `%T' casts away constness", - src_type, dest_type); + error ("%s from type `%T' to type `%T' casts away constness", + description, src_type, dest_type); } /* Return an expression representing static_cast<TYPE>(EXPR). */ @@ -4726,7 +4478,7 @@ build_static_cast (tree type, tree expr) { tree base; - check_for_casting_away_constness (intype, type); + check_for_casting_away_constness (intype, type, "static_cast"); base = lookup_base (TREE_TYPE (type), TREE_TYPE (intype), ba_check | ba_quiet, NULL); return build_base_path (MINUS_EXPR, expr, base, /*nonnull=*/false); @@ -4758,15 +4510,18 @@ build_static_cast (tree type, tree expr) } if (can_convert (t1, t2)) { - check_for_casting_away_constness (intype, type); + check_for_casting_away_constness (intype, type, "static_cast"); if (TYPE_PTRMEM_P (type)) { + tree delta; + if (TREE_CODE (expr) == PTRMEM_CST) expr = cplus_expand_constant (expr); - expr = cp_build_binary_op (PLUS_EXPR, - cp_convert (ptrdiff_type_node, expr), - get_delta_difference (c1, c2, - /*force=*/1)); + delta = get_delta_difference (c1, c2, /*force=*/1); + if (!integer_zerop (delta)) + expr = cp_build_binary_op (PLUS_EXPR, + build_nop (ptrdiff_type_node, expr), + delta); return build_nop (type, expr); } else @@ -4785,7 +4540,7 @@ build_static_cast (tree type, tree expr) && VOID_TYPE_P (TREE_TYPE (intype)) && TYPE_PTROB_P (type)) { - check_for_casting_away_constness (intype, type); + check_for_casting_away_constness (intype, type, "static_cast"); return build_nop (type, expr); } @@ -4856,10 +4611,7 @@ build_reinterpret_cast (tree type, tree expr) else if ((TYPE_PTRMEM_P (type) && TYPE_PTRMEM_P (intype)) || (TYPE_PTROBV_P (type) && TYPE_PTROBV_P (intype))) { - if (! comp_ptr_ttypes_reinterpret (TREE_TYPE (type), TREE_TYPE (intype))) - pedwarn ("reinterpret_cast from `%T' to `%T' casts away const (or volatile)", - intype, type); - + check_for_casting_away_constness (intype, type, "reinterpret_cast"); expr = decl_constant_value (expr); return fold (build1 (NOP_EXPR, type, expr)); } @@ -4932,8 +4684,9 @@ build_const_cast (tree type, tree expr) return convert_from_reference (expr); } } - else if (TREE_CODE (type) == POINTER_TYPE - && TREE_CODE (intype) == POINTER_TYPE + else if (((TREE_CODE (type) == POINTER_TYPE + && TREE_CODE (intype) == POINTER_TYPE) + || (TYPE_PTRMEM_P (type) && TYPE_PTRMEM_P (intype))) && comp_ptr_ttypes_const (TREE_TYPE (type), TREE_TYPE (intype))) return cp_convert (type, expr); @@ -5048,11 +4801,11 @@ build_c_cast (tree type, tree expr) otype, type); if (TREE_CODE (type) == INTEGER_TYPE - && TREE_CODE (otype) == POINTER_TYPE + && TYPE_PTR_P (otype) && TYPE_PRECISION (type) != TYPE_PRECISION (otype)) warning ("cast from pointer to integer of different size"); - if (TREE_CODE (type) == POINTER_TYPE + if (TYPE_PTR_P (type) && TREE_CODE (otype) == INTEGER_TYPE && TYPE_PRECISION (type) != TYPE_PRECISION (otype) /* Don't warn about converting any constant. */ @@ -5785,13 +5538,9 @@ static tree convert_for_assignment (tree type, tree rhs, const char *errtype, tree fndecl, int parmnum) { - register enum tree_code codel = TREE_CODE (type); register tree rhstype; register enum tree_code coder; - if (codel == OFFSET_TYPE) - abort (); - /* Strip NON_LVALUE_EXPRs since we aren't using as an lvalue. */ if (TREE_CODE (rhs) == NON_LVALUE_EXPR) rhs = TREE_OPERAND (rhs, 0); @@ -6266,7 +6015,7 @@ check_return_expr (tree retval) static int comp_ptr_ttypes_real (tree to, tree from, int constp) { - int to_more_cv_qualified = 0; + bool to_more_cv_qualified = false; for (; ; to = TREE_TYPE (to), from = TREE_TYPE (from)) { @@ -6289,8 +6038,7 @@ comp_ptr_ttypes_real (tree to, tree from, int constp) { if (constp == 0) return 0; - else - ++to_more_cv_qualified; + to_more_cv_qualified = true; } if (constp > 0) @@ -6369,40 +6117,6 @@ comp_ptr_ttypes_const (tree to, tree from) } } -/* Like comp_ptr_ttypes, for reinterpret_cast. */ - -static int -comp_ptr_ttypes_reinterpret (tree to, tree from) -{ - int constp = 1; - - for (; ; to = TREE_TYPE (to), from = TREE_TYPE (from)) - { - if (TREE_CODE (from) == OFFSET_TYPE) - from = TREE_TYPE (from); - if (TREE_CODE (to) == OFFSET_TYPE) - to = TREE_TYPE (to); - - /* Const and volatile mean something different for function types, - so the usual checks are not appropriate. */ - if (TREE_CODE (from) != FUNCTION_TYPE && TREE_CODE (from) != METHOD_TYPE - && TREE_CODE (to) != FUNCTION_TYPE && TREE_CODE (to) != METHOD_TYPE) - { - if (!at_least_as_qualified_p (to, from)) - return 0; - - if (! constp - && !at_least_as_qualified_p (from, to)) - return 0; - constp &= TYPE_READONLY (to); - } - - if (TREE_CODE (from) != POINTER_TYPE - || TREE_CODE (to) != POINTER_TYPE) - return 1; - } -} - /* Returns the type qualifiers for this type, including the qualifiers on the elements for an array type. */ @@ -6442,9 +6156,9 @@ casts_away_constness_r (tree *t1, tree *t2) pointer to member level is ignored when determining if a const cv-qualifier has been cast away. */ if (TYPE_PTRMEM_P (*t1)) - *t1 = build_pointer_type (TREE_TYPE (TREE_TYPE (*t1))); + *t1 = build_pointer_type (TYPE_PTRMEM_POINTED_TO_TYPE (*t1)); if (TYPE_PTRMEM_P (*t2)) - *t2 = build_pointer_type (TREE_TYPE (TREE_TYPE (*t2))); + *t2 = build_pointer_type (TYPE_PTRMEM_POINTED_TO_TYPE (*t2)); /* [expr.const.cast] @@ -6513,8 +6227,8 @@ casts_away_constness (tree t1, tree t2) "pointer to T1" to the type "pointer to T2" casts away constness. */ return casts_away_constness - (build_pointer_type (TREE_TYPE (TREE_TYPE (t1))), - build_pointer_type (TREE_TYPE (TREE_TYPE (t2)))); + (build_pointer_type (TYPE_PTRMEM_POINTED_TO_TYPE (t1)), + build_pointer_type (TYPE_PTRMEM_POINTED_TO_TYPE (t2))); /* Casting away constness is only something that makes sense for pointer or reference types. */ @@ -6532,23 +6246,6 @@ casts_away_constness (tree t1, tree t2) return false; } -/* Returns TYPE with its cv qualifiers removed - TYPE is T cv* .. *cv where T is not a pointer type, - returns T * .. *. (If T is an array type, then the cv qualifiers - above are those of the array members.) */ - -static tree -strip_all_pointer_quals (tree type) -{ - if (TREE_CODE (type) == POINTER_TYPE) - return build_pointer_type (strip_all_pointer_quals (TREE_TYPE (type))); - else if (TREE_CODE (type) == OFFSET_TYPE) - return build_offset_type (TYPE_OFFSET_BASETYPE (type), - strip_all_pointer_quals (TREE_TYPE (type))); - else - return TYPE_MAIN_VARIANT (type); -} - /* If T is a REFERENCE_TYPE return the type to which T refers. Otherwise, return T itself. */ diff --git a/gcc/cp/typeck2.c b/gcc/cp/typeck2.c index 6a14fec..8d1209c 100644 --- a/gcc/cp/typeck2.c +++ b/gcc/cp/typeck2.c @@ -506,7 +506,7 @@ digest_init (tree type, tree init, tree* tail) if (code == INTEGER_TYPE || code == REAL_TYPE || code == POINTER_TYPE || code == ENUMERAL_TYPE || code == REFERENCE_TYPE || code == BOOLEAN_TYPE || code == COMPLEX_TYPE - || TYPE_PTRMEMFUNC_P (type)) + || TYPE_PTR_TO_MEMBER_P (type)) { if (raw_constructor) { @@ -1070,8 +1070,7 @@ build_m_component_ref (tree datum, tree component) return error_mark_node; ptrmem_type = TREE_TYPE (component); - if (!TYPE_PTRMEM_P (ptrmem_type) - && !TYPE_PTRMEMFUNC_P (ptrmem_type)) + if (!TYPE_PTR_TO_MEMBER_P (ptrmem_type)) { error ("`%E' cannot be used as a member pointer, since it is of type `%T'", component, ptrmem_type); @@ -1107,10 +1106,12 @@ build_m_component_ref (tree datum, tree component) type = cp_build_qualified_type (type, (cp_type_quals (type) | cp_type_quals (TREE_TYPE (datum)))); - - datum = build_base_path (PLUS_EXPR, build_address (datum), binfo, 1); - component = cp_convert (ptrdiff_type_node, component); - datum = build (PLUS_EXPR, build_pointer_type (type), datum, component); + /* Build an expression for "object + offset" where offset is the + value stored in the pointer-to-data-member. */ + datum = build (PLUS_EXPR, build_pointer_type (type), + build_base_path (PLUS_EXPR, build_address (datum), + binfo, 1), + build_nop (ptrdiff_type_node, component)); return build_indirect_ref (datum, 0); } else |