aboutsummaryrefslogtreecommitdiff
path: root/gcc/cp
diff options
context:
space:
mode:
authorMark Mitchell <mark@codesourcery.com>2003-07-22 23:30:22 +0000
committerMark Mitchell <mmitchel@gcc.gnu.org>2003-07-22 23:30:22 +0000
commita5ac359a6d661735a213b7b6b8436e615e768788 (patch)
tree74afcc9943903e84e906ee02eba4d464f77fe58b /gcc/cp
parent938d968ed373057812cd43a9b420399fb65f6c0b (diff)
downloadgcc-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/ChangeLog86
-rw-r--r--gcc/cp/call.c212
-rw-r--r--gcc/cp/class.c2
-rw-r--r--gcc/cp/cp-lang.c2
-rw-r--r--gcc/cp/cp-tree.h33
-rw-r--r--gcc/cp/cvt.c138
-rw-r--r--gcc/cp/decl.c33
-rw-r--r--gcc/cp/dump.c17
-rw-r--r--gcc/cp/error.c17
-rw-r--r--gcc/cp/expr.c7
-rw-r--r--gcc/cp/init.c163
-rw-r--r--gcc/cp/parser.c11
-rw-r--r--gcc/cp/pt.c114
-rw-r--r--gcc/cp/rtti.c30
-rw-r--r--gcc/cp/semantics.c13
-rw-r--r--gcc/cp/tree.c6
-rw-r--r--gcc/cp/typeck.c655
-rw-r--r--gcc/cp/typeck2.c15
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