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
This commit is contained in:
Mark Mitchell 2003-07-22 23:30:22 +00:00 committed by Mark Mitchell
parent 938d968ed3
commit a5ac359a6d
21 changed files with 612 additions and 947 deletions

View File

@ -1,3 +1,8 @@
2003-07-22 Mark Mitchell <mark@codesourcery.com>
* fold-const.c (force_fit_type): Handle OFFSET_TYPE.
* varasam.c (output_constant): Likewise.
2003-07-22 Kazu Hirata <kazu@cs.umass.edu> 2003-07-22 Kazu Hirata <kazu@cs.umass.edu>
* alias.c: Fix comment formatting. * alias.c: Fix comment formatting.

View File

@ -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> 2003-07-22 Wolfgang Bangerth <bangerth@dealii.org>
* lex.c (unqualified_fn_lookup_error): Mention that the error * lex.c (unqualified_fn_lookup_error): Mention that the error

View File

@ -642,11 +642,9 @@ standard_conversion (tree to, tree from, tree expr)
if (same_type_p (from, to)) if (same_type_p (from, to))
return conv; 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)) && 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) else if ((tcode == INTEGER_TYPE && fcode == POINTER_TYPE)
|| (tcode == POINTER_TYPE && fcode == INTEGER_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); conv = build_conv (STD_CONV, to, conv);
ICS_BAD_FLAG (conv) = 1; 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)); tree to_pointee;
enum tree_code utcode = TREE_CODE (TREE_TYPE (to)); tree from_pointee;
if (same_type_ignoring_top_level_qualifiers_p (TREE_TYPE (from), if (tcode == POINTER_TYPE
TREE_TYPE (to))) && same_type_ignoring_top_level_qualifiers_p (TREE_TYPE (from),
TREE_TYPE (to)))
; ;
else if (utcode == VOID_TYPE && ufcode != OFFSET_TYPE else if (VOID_TYPE_P (TREE_TYPE (to))
&& ufcode != FUNCTION_TYPE) && !TYPE_PTRMEM_P (from)
&& TREE_CODE (TREE_TYPE (from)) != FUNCTION_TYPE)
{ {
from = build_pointer_type from = build_pointer_type
(cp_build_qualified_type (void_type_node, (cp_build_qualified_type (void_type_node,
cp_type_quals (TREE_TYPE (from)))); cp_type_quals (TREE_TYPE (from))));
conv = build_conv (PTR_CONV, from, conv); 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 fbase = TYPE_PTRMEM_CLASS_TYPE (from);
tree tbase = TYPE_OFFSET_BASETYPE (TREE_TYPE (to)); tree tbase = TYPE_PTRMEM_CLASS_TYPE (to);
if (DERIVED_FROM_P (fbase, tbase) if (DERIVED_FROM_P (fbase, tbase)
&& (same_type_ignoring_top_level_qualifiers_p && (same_type_ignoring_top_level_qualifiers_p
(TREE_TYPE (TREE_TYPE (from)), (TYPE_PTRMEM_POINTED_TO_TYPE (from),
TREE_TYPE (TREE_TYPE (to))))) 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); 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)) if (same_type_p (from, to))
/* OK */; /* 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); conv = build_conv (QUAL_CONV, to, conv);
else if (expr && string_conv_p (to, expr, 0)) else if (expr && string_conv_p (to, expr, 0))
/* converting from string constant to char *. */ /* converting from string constant to char *. */
conv = build_conv (QUAL_CONV, to, conv); 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); conv = build_conv (PTR_CONV, to, conv);
ICS_BAD_FLAG (conv) = 1; ICS_BAD_FLAG (conv) = 1;
@ -745,14 +758,25 @@ standard_conversion (tree to, tree from, tree expr)
} }
else if (tcode == BOOLEAN_TYPE) else if (tcode == BOOLEAN_TYPE)
{ {
if (! (INTEGRAL_CODE_P (fcode) || fcode == REAL_TYPE /* [conv.bool]
|| fcode == POINTER_TYPE || TYPE_PTRMEMFUNC_P (from)))
return 0;
conv = build_conv (STD_CONV, to, conv); An rvalue of arithmetic, enumeration, pointer, or pointer to
if (fcode == POINTER_TYPE member type can be converted to an rvalue of type bool. */
|| (TYPE_PTRMEMFUNC_P (from) && ICS_STD_RANK (conv) < PBOOL_RANK)) if (ARITHMETIC_TYPE_P (from)
ICS_STD_RANK (conv) = PBOOL_RANK; || 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 /* We don't check for ENUMERAL_TYPE here because there are no standard
conversions to enum type. */ conversions to enum type. */
@ -1592,8 +1616,7 @@ add_builtin_candidate (struct z_candidate **candidates, enum tree_code code,
T operator-(T); */ T operator-(T); */
case CONVERT_EXPR: /* unary + */ case CONVERT_EXPR: /* unary + */
if (TREE_CODE (type1) == POINTER_TYPE if (TREE_CODE (type1) == POINTER_TYPE)
&& TREE_CODE (TREE_TYPE (type1)) != OFFSET_TYPE)
break; break;
case NEGATE_EXPR: case NEGATE_EXPR:
if (ARITHMETIC_TYPE_P (type1)) if (ARITHMETIC_TYPE_P (type1))
@ -1618,12 +1641,10 @@ add_builtin_candidate (struct z_candidate **candidates, enum tree_code code,
case MEMBER_REF: case MEMBER_REF:
if (TREE_CODE (type1) == POINTER_TYPE 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 c1 = TREE_TYPE (type1);
tree c2 = (TYPE_PTRMEMFUNC_P (type2) tree c2 = TYPE_PTRMEM_CLASS_TYPE (type2);
? TYPE_METHOD_BASETYPE (TREE_TYPE (TYPE_PTRMEMFUNC_FN_TYPE (type2)))
: TYPE_OFFSET_BASETYPE (TREE_TYPE (type2)));
if (IS_AGGR_TYPE (c1) && DERIVED_FROM_P (c2, c1) if (IS_AGGR_TYPE (c1) && DERIVED_FROM_P (c2, c1)
&& (TYPE_PTRMEMFUNC_P (type2) && (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)) if ((TYPE_PTRMEMFUNC_P (type1) && TYPE_PTRMEMFUNC_P (type2))
|| (TYPE_PTRMEM_P (type1) && TYPE_PTRMEM_P (type2))) || (TYPE_PTRMEM_P (type1) && TYPE_PTRMEM_P (type2)))
break; break;
if ((TYPE_PTRMEMFUNC_P (type1) || TYPE_PTRMEM_P (type1)) if (TYPE_PTR_TO_MEMBER_P (type1) && null_ptr_cst_p (args[1]))
&& null_ptr_cst_p (args[1]))
{ {
type2 = type1; type2 = type1;
break; break;
} }
if ((TYPE_PTRMEMFUNC_P (type2) || TYPE_PTRMEM_P (type2)) if (TYPE_PTR_TO_MEMBER_P (type2) && null_ptr_cst_p (args[0]))
&& null_ptr_cst_p (args[0]))
{ {
type1 = type2; type1 = type2;
break; break;
@ -1871,12 +1890,8 @@ add_builtin_candidate (struct z_candidate **candidates, enum tree_code code,
break; break;
/* Otherwise, the types should be pointers. */ /* Otherwise, the types should be pointers. */
if (!(TREE_CODE (type1) == POINTER_TYPE if (!(TYPE_PTR_P (type1) || TYPE_PTR_TO_MEMBER_P (type1))
|| TYPE_PTRMEM_P (type1) || !(TYPE_PTR_P (type2) || TYPE_PTR_TO_MEMBER_P (type2)))
|| TYPE_PTRMEMFUNC_P (type1))
|| !(TREE_CODE (type2) == POINTER_TYPE
|| TYPE_PTRMEM_P (type2)
|| TYPE_PTRMEMFUNC_P (type2)))
return; return;
/* We don't check that the two types are the same; the logic /* 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) if (type2 && !same_type_p (type1, type2)
&& TREE_CODE (type1) == TREE_CODE (type2) && TREE_CODE (type1) == TREE_CODE (type2)
&& (TREE_CODE (type1) == REFERENCE_TYPE && (TREE_CODE (type1) == REFERENCE_TYPE
|| (TREE_CODE (type1) == POINTER_TYPE || (TYPE_PTR_P (type1) && TYPE_PTR_P (type2))
&& TYPE_PTRMEM_P (type1) == TYPE_PTRMEM_P (type2)) || (TYPE_PTRMEM_P (type1) && TYPE_PTRMEM_P (type2))
|| TYPE_PTRMEMFUNC_P (type1) || TYPE_PTRMEMFUNC_P (type1)
|| IS_AGGR_TYPE (type1) || IS_AGGR_TYPE (type1)
|| TREE_CODE (type1) == ENUMERAL_TYPE)) || TREE_CODE (type1) == ENUMERAL_TYPE))
@ -2605,76 +2620,6 @@ build_user_type_conversion (tree totype, tree expr, int flags)
return NULL_TREE; 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. */ /* Do any initial processing on the arguments to a function call. */
static tree 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. cv-qualification of either the second or the third operand.
The result is of the common type. */ The result is of the common type. */
else if ((null_ptr_cst_p (arg2) else if ((null_ptr_cst_p (arg2)
&& (TYPE_PTR_P (arg3_type) || TYPE_PTRMEM_P (arg3_type) && (TYPE_PTR_P (arg3_type) || TYPE_PTR_TO_MEMBER_P (arg3_type)))
|| TYPE_PTRMEMFUNC_P (arg3_type)))
|| (null_ptr_cst_p (arg3) || (null_ptr_cst_p (arg3)
&& (TYPE_PTR_P (arg2_type) || TYPE_PTRMEM_P (arg2_type) && (TYPE_PTR_P (arg2_type) || TYPE_PTR_TO_MEMBER_P (arg2_type)))
|| TYPE_PTRMEMFUNC_P (arg2_type)))
|| (TYPE_PTR_P (arg2_type) && TYPE_PTR_P (arg3_type)) || (TYPE_PTR_P (arg2_type) && TYPE_PTR_P (arg3_type))
|| (TYPE_PTRMEM_P (arg2_type) && TYPE_PTRMEM_P (arg3_type)) || (TYPE_PTRMEM_P (arg2_type) && TYPE_PTRMEM_P (arg3_type))
|| (TYPE_PTRMEMFUNC_P (arg2_type) || (TYPE_PTRMEMFUNC_P (arg2_type) && TYPE_PTRMEMFUNC_P (arg3_type)))
&& TYPE_PTRMEMFUNC_P (arg3_type)))
{ {
result_type = composite_pointer_type (arg2_type, arg3_type, arg2, result_type = composite_pointer_type (arg2_type, arg3_type, arg2,
arg3, "conditional expression"); 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 for pointers A*, except opposite: if B is derived from A then
A::* converts to B::*, not vice versa. For that reason, we A::* converts to B::*, not vice versa. For that reason, we
switch the from_ and to_ variables here. */ switch the from_ and to_ variables here. */
else if (TYPE_PTRMEM_P (from_type1) else if ((TYPE_PTRMEM_P (from_type1) && TYPE_PTRMEM_P (from_type2)
&& TYPE_PTRMEM_P (from_type2) && TYPE_PTRMEM_P (to_type1) && TYPE_PTRMEM_P (to_type2))
&& TYPE_PTRMEM_P (to_type1) || (TYPE_PTRMEMFUNC_P (from_type1)
&& TYPE_PTRMEM_P (to_type2)) && TYPE_PTRMEMFUNC_P (from_type2)
&& TYPE_PTRMEMFUNC_P (to_type1)
&& TYPE_PTRMEMFUNC_P (to_type2)))
{ {
deref_to_type1 = TYPE_OFFSET_BASETYPE (TREE_TYPE (from_type1)); deref_to_type1 = TYPE_PTRMEM_CLASS_TYPE (from_type1);
deref_to_type2 = TYPE_OFFSET_BASETYPE (TREE_TYPE (from_type2)); deref_to_type2 = TYPE_PTRMEM_CLASS_TYPE (from_type2);
deref_from_type1 = TYPE_OFFSET_BASETYPE (TREE_TYPE (to_type1)); deref_from_type1 = TYPE_PTRMEM_CLASS_TYPE (to_type1);
deref_from_type2 = TYPE_OFFSET_BASETYPE (TREE_TYPE (to_type2)); deref_from_type2 = TYPE_PTRMEM_CLASS_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);
} }
if (deref_from_type1 != NULL_TREE if (deref_from_type1 != NULL_TREE

View File

@ -3078,7 +3078,7 @@ check_field_decls (tree t, tree *access_decls,
type = strip_array_types (type); type = strip_array_types (type);
if (TREE_CODE (type) == POINTER_TYPE) if (TYPE_PTR_P (type))
has_pointers = 1; has_pointers = 1;
if (DECL_MUTABLE_P (x) || TYPE_HAS_MUTABLE_P (type)) if (DECL_MUTABLE_P (x) || TYPE_HAS_MUTABLE_P (type))

View File

@ -364,7 +364,7 @@ cp_var_mod_type_p (tree type)
{ {
/* If TYPE is a pointer-to-member, it is variably modified if either /* If TYPE is a pointer-to-member, it is variably modified if either
the class or the member are variably modified. */ 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)) return (variably_modified_type_p (TYPE_PTRMEM_CLASS_TYPE (type))
|| variably_modified_type_p (TYPE_PTRMEM_POINTED_TO_TYPE (type))); || variably_modified_type_p (TYPE_PTRMEM_POINTED_TO_TYPE (type)));

View File

@ -2421,8 +2421,7 @@ struct lang_decl GTY(())
(ARITHMETIC_TYPE_P (TYPE) \ (ARITHMETIC_TYPE_P (TYPE) \
|| TREE_CODE (TYPE) == ENUMERAL_TYPE \ || TREE_CODE (TYPE) == ENUMERAL_TYPE \
|| TYPE_PTR_P (TYPE) \ || TYPE_PTR_P (TYPE) \
|| TYPE_PTRMEM_P (TYPE) \ || TYPE_PTR_TO_MEMBER_P (TYPE))
|| TYPE_PTRMEMFUNC_P (TYPE))
/* [dcl.init.aggr] /* [dcl.init.aggr]
@ -2508,14 +2507,15 @@ struct lang_decl GTY(())
#define TYPE_HAS_TRIVIAL_ASSIGN_REF(NODE) \ #define TYPE_HAS_TRIVIAL_ASSIGN_REF(NODE) \
(TYPE_HAS_ASSIGN_REF (NODE) && ! TYPE_HAS_COMPLEX_ASSIGN_REF (NODE)) (TYPE_HAS_ASSIGN_REF (NODE) && ! TYPE_HAS_COMPLEX_ASSIGN_REF (NODE))
#define TYPE_PTRMEM_P(NODE) \ /* Returns true if NODE is a pointer-to-data-member. */
(TREE_CODE (NODE) == POINTER_TYPE \ #define TYPE_PTRMEM_P(NODE) \
&& TREE_CODE (TREE_TYPE (NODE)) == OFFSET_TYPE) (TREE_CODE (NODE) == OFFSET_TYPE)
#define TYPE_PTR_P(NODE) \ #define TYPE_PTR_P(NODE) \
(TREE_CODE (NODE) == POINTER_TYPE \ (TREE_CODE (NODE) == POINTER_TYPE)
&& TREE_CODE (TREE_TYPE (NODE)) != OFFSET_TYPE) #define TYPE_PTROB_P(NODE) \
#define TYPE_PTROB_P(NODE) \ (TYPE_PTR_P (NODE) \
(TYPE_PTR_P (NODE) && TREE_CODE (TREE_TYPE (NODE)) != FUNCTION_TYPE \ && TREE_CODE (TREE_TYPE (NODE)) != FUNCTION_TYPE \
&& TREE_CODE (TREE_TYPE (NODE)) != METHOD_TYPE \
&& TREE_CODE (TREE_TYPE (NODE)) != VOID_TYPE) && TREE_CODE (TREE_TYPE (NODE)) != VOID_TYPE)
#define TYPE_PTROBV_P(NODE) \ #define TYPE_PTROBV_P(NODE) \
(TYPE_PTR_P (NODE) && TREE_CODE (TREE_TYPE (NODE)) != FUNCTION_TYPE) (TYPE_PTR_P (NODE) && TREE_CODE (TREE_TYPE (NODE)) != FUNCTION_TYPE)
@ -2536,6 +2536,10 @@ struct lang_decl GTY(())
#define TYPE_PTRMEMFUNC_FLAG(NODE) \ #define TYPE_PTRMEMFUNC_FLAG(NODE) \
(LANG_TYPE_CLASS_CHECK (NODE)->ptrmemfunc_flag) (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 /* Indicates when overload resolution may resolve to a pointer to
member function. [expr.unary.op]/3 */ member function. [expr.unary.op]/3 */
#define PTRMEM_OK_P(NODE) TREE_LANG_FLAG_0 (NODE) #define PTRMEM_OK_P(NODE) TREE_LANG_FLAG_0 (NODE)
@ -2574,13 +2578,13 @@ struct lang_decl GTY(())
type `const X*'. */ type `const X*'. */
#define TYPE_PTRMEM_CLASS_TYPE(NODE) \ #define TYPE_PTRMEM_CLASS_TYPE(NODE) \
(TYPE_PTRMEM_P (NODE) \ (TYPE_PTRMEM_P (NODE) \
? TYPE_OFFSET_BASETYPE (TREE_TYPE (NODE)) \ ? TYPE_OFFSET_BASETYPE (NODE) \
: TYPE_PTRMEMFUNC_OBJECT_TYPE (NODE)) : TYPE_PTRMEMFUNC_OBJECT_TYPE (NODE))
/* For a pointer-to-member type of the form `T X::*', this is `T'. */ /* For a pointer-to-member type of the form `T X::*', this is `T'. */
#define TYPE_PTRMEM_POINTED_TO_TYPE(NODE) \ #define TYPE_PTRMEM_POINTED_TO_TYPE(NODE) \
(TYPE_PTRMEM_P (NODE) \ (TYPE_PTRMEM_P (NODE) \
? TREE_TYPE (TREE_TYPE (NODE)) \ ? TREE_TYPE (NODE) \
: TREE_TYPE (TYPE_PTRMEMFUNC_FN_TYPE (NODE))) : TREE_TYPE (TYPE_PTRMEMFUNC_FN_TYPE (NODE)))
/* For a pointer-to-member constant `X::Y' this is the RECORD_TYPE for /* 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 null_ptr_cst_p (tree);
extern bool sufficient_parms_p (tree); extern bool sufficient_parms_p (tree);
extern tree type_decays_to (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_user_type_conversion (tree, tree, int);
extern tree build_new_function_call (tree, tree); extern tree build_new_function_call (tree, tree);
extern tree build_operator_new_call (tree, tree, 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_aggr_from_typedef (tree, int);
extern tree get_type_value (tree); extern tree get_type_value (tree);
extern tree build_zero_init (tree, tree, bool); extern tree build_zero_init (tree, tree, bool);
extern tree build_offset_ref (tree, tree); extern tree build_offset_ref (tree, tree, bool);
extern tree resolve_offset_ref (tree);
extern tree build_new (tree, tree, tree, int); extern tree build_new (tree, tree, tree, int);
extern tree build_vec_init (tree, tree, tree, int); extern tree build_vec_init (tree, tree, tree, int);
extern tree build_x_delete (tree, int, tree); extern tree build_x_delete (tree, int, tree);
@ -4272,7 +4274,6 @@ extern tree commonparms (tree, tree);
extern tree original_type (tree); extern tree original_type (tree);
extern bool comp_except_specs (tree, tree, bool); extern bool comp_except_specs (tree, tree, bool);
extern bool comptypes (tree, tree, int); extern bool comptypes (tree, tree, int);
extern int comp_target_types (tree, tree, int);
extern bool compparms (tree, tree); extern bool compparms (tree, tree);
extern int comp_cv_qualification (tree, tree); extern int comp_cv_qualification (tree, tree);
extern int comp_cv_qual_signature (tree, tree); extern int comp_cv_qual_signature (tree, tree);

View File

@ -180,49 +180,7 @@ 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;
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;
if (bk == bk_via_virtual)
{
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);
}
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'", error ("cannot convert `%E' from type `%T' to type `%T'",
expr, intype, type); expr, intype, type);
@ -231,6 +189,50 @@ cp_convert_to_pointer (tree type, tree expr, bool force)
return build_nop (type, expr); 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 (force)
warning ("pointer to member cast from `%T' to `%T' is via virtual base",
intype, type);
else
{
error ("pointer to member cast from `%T' to `%T' is via virtual base",
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)) else if (TYPE_PTRMEMFUNC_P (type) && TYPE_PTRMEMFUNC_P (intype))
return build_ptrmemfunc (TYPE_PTRMEMFUNC_FN_TYPE (type), expr, 0); return build_ptrmemfunc (TYPE_PTRMEMFUNC_FN_TYPE (type), expr, 0);
else if (TYPE_PTRMEMFUNC_P (intype)) else if (TYPE_PTRMEMFUNC_P (intype))
@ -253,8 +255,6 @@ cp_convert_to_pointer (tree type, tree expr, bool force)
return error_mark_node; return error_mark_node;
} }
my_friendly_assert (form != OFFSET_TYPE, 186);
if (integer_zerop (expr)) if (integer_zerop (expr))
{ {
if (TYPE_PTRMEMFUNC_P (type)) if (TYPE_PTRMEMFUNC_P (type))
@ -271,8 +271,7 @@ cp_convert_to_pointer (tree type, tree expr, bool force)
force_fit_type (expr, 0); force_fit_type (expr, 0);
return expr; return expr;
} }
else if ((TYPE_PTRMEM_P (type) || TYPE_PTRMEMFUNC_P (type)) else if (TYPE_PTR_TO_MEMBER_P (type) && INTEGRAL_CODE_P (form))
&& INTEGRAL_CODE_P (form))
{ {
error ("invalid conversion from '%T' to '%T'", intype, type); error ("invalid conversion from '%T' to '%T'", intype, type);
return error_mark_node; return error_mark_node;
@ -454,7 +453,7 @@ convert_to_reference (tree reftype, tree expr, int convtype,
register tree intype; register tree intype;
tree rval = NULL_TREE; tree rval = NULL_TREE;
tree rval_as_conversion = NULL_TREE; tree rval_as_conversion = NULL_TREE;
int i; bool can_convert_intype_to_type;
if (TREE_CODE (type) == FUNCTION_TYPE if (TREE_CODE (type) == FUNCTION_TYPE
&& TREE_TYPE (expr) == unknown_type_node) && TREE_TYPE (expr) == unknown_type_node)
@ -473,9 +472,9 @@ convert_to_reference (tree reftype, tree expr, int convtype,
intype = TYPE_MAIN_VARIANT (intype); intype = TYPE_MAIN_VARIANT (intype);
i = comp_target_types (type, intype, 0); can_convert_intype_to_type = can_convert (type, intype);
if (!can_convert_intype_to_type
if (i <= 0 && (convtype & CONV_IMPLICIT) && IS_AGGR_TYPE (intype) && (convtype & CONV_IMPLICIT) && IS_AGGR_TYPE (intype)
&& ! (flags & LOOKUP_NO_CONVERSION)) && ! (flags & LOOKUP_NO_CONVERSION))
{ {
/* Look for a user-defined conversion to lvalue that we can use. */ /* 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; expr = rval_as_conversion;
rval_as_conversion = NULL_TREE; rval_as_conversion = NULL_TREE;
intype = type; intype = type;
i = 1; can_convert_intype_to_type = 1;
} }
} }
if (((convtype & CONV_STATIC) && i == -1) if (((convtype & CONV_STATIC) && can_convert (intype, type))
|| ((convtype & CONV_IMPLICIT) && i == 1)) || ((convtype & CONV_IMPLICIT) && can_convert_intype_to_type))
{ {
if (flags & LOOKUP_COMPLAIN) if (flags & LOOKUP_COMPLAIN)
{ {
@ -550,8 +549,6 @@ convert_to_reference (tree reftype, tree expr, int convtype,
return rval; return rval;
} }
my_friendly_assert (TREE_CODE (intype) != OFFSET_TYPE, 189);
if (flags & LOOKUP_COMPLAIN) if (flags & LOOKUP_COMPLAIN)
error ("cannot convert type `%T' to type `%T'", intype, reftype); 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 tree e = expr;
register enum tree_code code = TREE_CODE (type); register enum tree_code code = TREE_CODE (type);
if (e == error_mark_node if (error_operand_p (e) || type == error_mark_node)
|| TREE_TYPE (e) == error_mark_node)
return error_mark_node; return error_mark_node;
complete_type (type); complete_type (type);
@ -671,13 +667,6 @@ ocp_convert (tree type, tree expr, int convtype, int flags)
return e; 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)) if (INTEGRAL_CODE_P (code))
{ {
tree intype = TREE_TYPE (e); 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)); return fold (convert_to_integer (type, e));
} }
if (code == POINTER_TYPE || code == REFERENCE_TYPE if (POINTER_TYPE_P (type) || TYPE_PTR_TO_MEMBER_P (type))
|| TYPE_PTRMEMFUNC_P (type))
return fold (cp_convert_to_pointer (type, e, false)); return fold (cp_convert_to_pointer (type, e, false));
if (code == VECTOR_TYPE) if (code == VECTOR_TYPE)
return fold (convert_to_vector (type, e)); return fold (convert_to_vector (type, e));
@ -1178,10 +1166,20 @@ type_promotes_to (tree type)
tree tree
perform_qualification_conversions (tree type, tree expr) perform_qualification_conversions (tree type, tree expr)
{ {
if (TREE_CODE (type) == POINTER_TYPE tree expr_type;
&& TREE_CODE (TREE_TYPE (expr)) == POINTER_TYPE
&& comp_ptr_ttypes (TREE_TYPE (type), TREE_TYPE (TREE_TYPE (expr)))) expr_type = TREE_TYPE (expr);
return build1 (NOP_EXPR, 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 else
return error_mark_node; return error_mark_node;
} }

View File

@ -9284,7 +9284,26 @@ build_ptrmemfunc_type (tree type)
tree tree
build_ptrmem_type (tree class_type, tree member_type) 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. /* 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"; error_msg = "array of references";
break; break;
case OFFSET_TYPE:
error_msg = "array of data members";
break;
case METHOD_TYPE: case METHOD_TYPE:
error_msg = "array of function members"; error_msg = "array of function members";
break; break;
@ -11360,8 +11375,6 @@ grokdeclarator (tree declarator,
} }
else if (TREE_CODE (type) == FUNCTION_TYPE) else if (TREE_CODE (type) == FUNCTION_TYPE)
type = build_pointer_type (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); type = build_pointer_type (type);
TREE_TYPE (decl) = 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)) else if (abstract_virtuals_error (decl, type))
any_error = 1; /* Seems like a good idea. */ any_error = 1; /* Seems like a good idea. */
else if (POINTER_TYPE_P (type)) else if (POINTER_TYPE_P (type))

View File

@ -237,18 +237,13 @@ cp_dump_tree (void* dump_info, tree t)
} }
break; break;
case POINTER_TYPE: case OFFSET_TYPE:
if (TYPE_PTRMEM_P (t)) dump_string (di, "ptrmem");
{ dump_child ("ptd", TYPE_PTRMEM_POINTED_TO_TYPE (t));
dump_string (di, "ptrmem"); dump_child ("cls", TYPE_PTRMEM_CLASS_TYPE (t));
dump_child ("ptd", TYPE_PTRMEM_POINTED_TO_TYPE (t)); return true;
dump_child ("cls", TYPE_PTRMEM_CLASS_TYPE (t));
return true;
}
break;
case RECORD_TYPE: case RECORD_TYPE:
case UNION_TYPE:
if (TYPE_PTRMEMFUNC_P (t)) if (TYPE_PTRMEMFUNC_P (t))
{ {
dump_string (di, "ptrmem"); dump_string (di, "ptrmem");
@ -256,7 +251,9 @@ cp_dump_tree (void* dump_info, tree t)
dump_child ("cls", TYPE_PTRMEM_CLASS_TYPE (t)); dump_child ("cls", TYPE_PTRMEM_CLASS_TYPE (t));
return true; return true;
} }
/* Fall through. */
case UNION_TYPE:
/* Is it a type used as a base? */ /* Is it a type used as a base? */
if (TYPE_CONTEXT (t) && TREE_CODE (TYPE_CONTEXT (t)) == TREE_CODE (t) if (TYPE_CONTEXT (t) && TREE_CODE (TYPE_CONTEXT (t)) == TREE_CODE (t)
&& CLASSTYPE_AS_BASE (TYPE_CONTEXT (t)) == t) && CLASSTYPE_AS_BASE (TYPE_CONTEXT (t)) == t)

View File

@ -587,19 +587,14 @@ dump_type_prefix (tree t, int flags)
tree sub = TREE_TYPE (t); tree sub = TREE_TYPE (t);
padding = dump_type_prefix (sub, flags); padding = dump_type_prefix (sub, flags);
/* A tree for a member pointer looks like pointer to offset, if (TREE_CODE (sub) == ARRAY_TYPE)
so let the OFFSET_TYPE case handle it. */
if (!TYPE_PTRMEM_P (t))
{ {
if (TREE_CODE (sub) == ARRAY_TYPE) output_add_space (scratch_buffer);
{ print_left_paren (scratch_buffer);
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_character
(scratch_buffer, "&*"[TREE_CODE (t) == POINTER_TYPE]);
padding = dump_qualifiers (t, before);
} }
break; break;

View File

@ -51,11 +51,8 @@ cplus_expand_constant (tree cst)
member = PTRMEM_CST_MEMBER (cst); member = PTRMEM_CST_MEMBER (cst);
if (TREE_CODE (member) == FIELD_DECL) if (TREE_CODE (member) == FIELD_DECL)
{ /* Find the offset for the field. */
/* Find the offset for the field. */ cst = fold (build_nop (type, byte_position (member)));
tree offset = byte_position (member);
cst = fold (build1 (NOP_EXPR, type, offset));
}
else else
{ {
tree delta; tree delta;

View File

@ -1337,10 +1337,11 @@ get_type_value (tree name)
return NULL_TREE; return NULL_TREE;
} }
/* Build a reference to a member of an aggregate. This is not a /* Build a reference to a member of an aggregate. This is not a C++
C++ `&', but really something which can have its address taken, `&', but really something which can have its address taken, and
and then act as a pointer to member, for example TYPE :: FIELD then act as a pointer to member, for example TYPE :: FIELD can have
can have its address taken by saying & TYPE :: FIELD. 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> @@ Prints out lousy diagnostics for operator <typename>
@@ fields. @@ fields.
@ -1348,7 +1349,7 @@ get_type_value (tree name)
@@ This function should be rewritten and placed in search.c. */ @@ This function should be rewritten and placed in search.c. */
tree tree
build_offset_ref (tree type, tree name) build_offset_ref (tree type, tree name, bool address_p)
{ {
tree decl; tree decl;
tree member; tree member;
@ -1435,8 +1436,33 @@ build_offset_ref (tree type, tree name)
return error_mark_node; 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. */ /* 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. */ /* Go from the TREE_BASELINK to the member function info. */
tree fnfields = member; tree fnfields = member;
@ -1475,104 +1501,63 @@ build_offset_ref (tree type, tree name)
mark_used (t); mark_used (t);
if (DECL_STATIC_FUNCTION_P (t)) if (DECL_STATIC_FUNCTION_P (t))
return t; return t;
t = build (OFFSET_REF, TREE_TYPE (t), decl, t); member = t;
PTRMEM_OK_P (t) = 1; }
return 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); /* If MEMBER is non-static, then the program has fallen afoul of
return error_mark_node; [expr.prim]:
}
if (TREE_CODE (member) == TYPE_DECL) An id-expression that denotes a nonstatic data member or
{ nonstatic member function of a class can only be used:
TREE_USED (member) = 1;
-- 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)
{
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; 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;
}
/* static class functions too. */
if (TREE_CODE (member) == FUNCTION_DECL
&& TREE_CODE (TREE_TYPE (member)) == FUNCTION_TYPE)
abort ();
/* In member functions, the form `type::name' is no longer /* In member functions, the form `type::name' is no longer
equivalent to `this->type::name', at least not until equivalent to `this->type::name', at least not until
resolve_offset_ref. */ resolve_offset_ref. */
member = build (OFFSET_REF, build_offset_type (type, TREE_TYPE (member)), member = build (OFFSET_REF, TREE_TYPE (member), decl, member);
decl, member);
PTRMEM_OK_P (member) = 1; PTRMEM_OK_P (member) = 1;
return member; 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 /* If DECL is a `const' declaration, and its value is a known
constant, then return that value. */ constant, then return that value. */

View File

@ -3581,17 +3581,6 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p)
it does not. Therefore, we have to manually obtain it does not. Therefore, we have to manually obtain
the underlying type here. */ the underlying type here. */
scope = non_reference (scope); 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 /* The type of the POSTFIX_EXPRESSION must be
complete. */ complete. */
scope = complete_type_or_else (scope, NULL_TREE); scope = complete_type_or_else (scope, NULL_TREE);

View File

@ -3004,8 +3004,7 @@ convert_nontype_argument (tree type, tree expr)
Check this first since if expr_type is the unknown_type_node Check this first since if expr_type is the unknown_type_node
we would otherwise complain below. */ we would otherwise complain below. */
; ;
else if (TYPE_PTRMEM_P (expr_type) else if (TYPE_PTR_TO_MEMBER_P (expr_type))
|| TYPE_PTRMEMFUNC_P (expr_type))
{ {
if (TREE_CODE (expr) != PTRMEM_CST) if (TREE_CODE (expr) != PTRMEM_CST)
goto bad_argument; goto bad_argument;
@ -3038,8 +3037,7 @@ convert_nontype_argument (tree type, tree expr)
else else
error ("it must be the address of an object with external linkage"); error ("it must be the address of an object with external linkage");
} }
else if (TYPE_PTRMEM_P (expr_type) else if (TYPE_PTR_TO_MEMBER_P (expr_type))
|| TYPE_PTRMEMFUNC_P (expr_type))
error ("it must be a pointer-to-member of the form `&X::Y'"); error ("it must be a pointer-to-member of the form `&X::Y'");
return NULL_TREE; return NULL_TREE;
@ -3070,9 +3068,7 @@ convert_nontype_argument (tree type, tree expr)
return error_mark_node; return error_mark_node;
} }
} }
else if (INTEGRAL_TYPE_P (expr_type) else if (INTEGRAL_TYPE_P (expr_type) || TYPE_PTR_TO_MEMBER_P (expr_type))
|| TYPE_PTRMEM_P (expr_type)
|| TYPE_PTRMEMFUNC_P (expr_type))
{ {
if (! TREE_CONSTANT (expr)) if (! TREE_CONSTANT (expr))
{ {
@ -3117,31 +3113,32 @@ convert_nontype_argument (tree type, tree expr)
goto non_constant; goto non_constant;
return expr; 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: case POINTER_TYPE:
{ {
tree type_pointed_to = TREE_TYPE (type); tree type_pointed_to = TREE_TYPE (type);
if (TYPE_PTRMEM_P (type)) if (TREE_CODE (type_pointed_to) == FUNCTION_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)
{ {
/* For a non-type template-parameter of type pointer to /* For a non-type template-parameter of type pointer to
function, only the function-to-pointer conversion function, only the function-to-pointer conversion
@ -3421,8 +3418,7 @@ convert_template_argument (tree parm,
inner_args = INNERMOST_TEMPLATE_ARGS (args); inner_args = INNERMOST_TEMPLATE_ARGS (args);
if (TREE_CODE (arg) == TREE_LIST if (TREE_CODE (arg) == TREE_LIST
&& TREE_TYPE (arg) != NULL_TREE && TREE_CODE (TREE_VALUE (arg)) == OFFSET_REF)
&& TREE_CODE (TREE_TYPE (arg)) == OFFSET_TYPE)
{ {
/* The template argument was the name of some /* The template argument was the name of some
member function. That's usually 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); my_friendly_assert (TREE_CODE (type) != METHOD_TYPE, 20011231);
if (TREE_CODE (type) == FUNCTION_TYPE) 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 /* This is really a method type. The cv qualifiers of the
qualifiers of the class type. They should be held this pointer should _not_ be determined by the cv
somewhere in the FUNCTION_TYPE, but we don't do that at qualifiers of the class type. They should be held
the moment. Consider somewhere in the FUNCTION_TYPE, but we don't do that at
typedef void (Func) () const; the moment. Consider
typedef void (Func) () const;
template <typename T1> void Foo (Func T1::*); template <typename T1> void Foo (Func T1::*);
*/ */
return build_cplus_method_type (TYPE_MAIN_VARIANT (r), tree method_type;
TREE_TYPE (type),
TYPE_ARG_TYPES (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 else
return build_offset_type (r, type); return build_ptrmem_type (r, type);
} }
case FUNCTION_TYPE: case FUNCTION_TYPE:
case METHOD_TYPE: case METHOD_TYPE:
@ -9511,12 +9512,6 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict)
} }
else 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 /* If PARM is `const T' and ARG is only `int', we don't have
a match unless we are allowing additional qualification. a match unless we are allowing additional qualification.
If ARG is `const int' and PARM is just `T' that's OK; 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. */ level of pointers. */
strict |= (strict_in & UNIFY_ALLOW_DERIVED); 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), return unify (tparms, targs, TREE_TYPE (parm),
TREE_TYPE (arg), strict); TREE_TYPE (arg), strict);
} }
@ -9782,7 +9765,6 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict)
DEDUCE_EXACT, 0, -1); DEDUCE_EXACT, 0, -1);
case OFFSET_TYPE: case OFFSET_TYPE:
offset:
if (TREE_CODE (arg) != OFFSET_TYPE) if (TREE_CODE (arg) != OFFSET_TYPE)
return 1; return 1;
if (unify (tparms, targs, TYPE_OFFSET_BASETYPE (parm), 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; return 0;
else if (POINTER_TYPE_P (type)) else if (POINTER_TYPE_P (type))
return 0; return 0;
else if (TYPE_PTRMEM_P (type)) else if (TYPE_PTR_TO_MEMBER_P (type))
return 0;
else if (TYPE_PTRMEMFUNC_P (type))
return 0; return 0;
else if (TREE_CODE (type) == TEMPLATE_TYPE_PARM) else if (TREE_CODE (type) == TEMPLATE_TYPE_PARM)
return 0; return 0;
@ -11325,7 +11305,7 @@ dependent_type_p_r (tree type)
dependent. */ dependent. */
type = TYPE_MAIN_VARIANT (type); type = TYPE_MAIN_VARIANT (type);
/* -- a compound type constructed from any dependent 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)) return (dependent_type_p (TYPE_PTRMEM_CLASS_TYPE (type))
|| dependent_type_p (TYPE_PTRMEM_POINTED_TO_TYPE || dependent_type_p (TYPE_PTRMEM_POINTED_TO_TYPE
(type))); (type)));

View File

@ -331,8 +331,6 @@ get_tinfo_decl (tree type)
return error_mark_node; return error_mark_node;
} }
if (TREE_CODE (type) == OFFSET_TYPE)
type = TREE_TYPE (type);
if (TREE_CODE (type) == METHOD_TYPE) if (TREE_CODE (type) == METHOD_TYPE)
type = build_function_type (TREE_TYPE (type), type = build_function_type (TREE_TYPE (type),
TREE_CHAIN (TYPE_ARG_TYPES (type))); TREE_CHAIN (TYPE_ARG_TYPES (type)));
@ -715,19 +713,17 @@ qualifier_flags (tree type)
static bool static bool
target_incomplete_p (tree type) target_incomplete_p (tree type)
{ {
while (TREE_CODE (type) == POINTER_TYPE) while (true)
if (TYPE_PTRMEM_P (type)) if (TYPE_PTRMEM_P (type))
{ {
if (!COMPLETE_TYPE_P (TYPE_PTRMEM_CLASS_TYPE (type))) if (!COMPLETE_TYPE_P (TYPE_PTRMEM_CLASS_TYPE (type)))
return true; return true;
type = TYPE_PTRMEM_POINTED_TO_TYPE (type); type = TYPE_PTRMEM_POINTED_TO_TYPE (type);
} }
else else if (TREE_CODE (type) == POINTER_TYPE)
type = TREE_TYPE (type); type = TREE_TYPE (type);
if (!COMPLETE_OR_VOID_TYPE_P (type)) else
return true; return !COMPLETE_OR_VOID_TYPE_P (type);
return false;
} }
/* Return a CONSTRUCTOR for the common part of the type_info objects. This /* 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); my_friendly_assert (at_eof, 20021120);
switch (TREE_CODE (type)) switch (TREE_CODE (type))
{ {
case OFFSET_TYPE:
return ptm_initializer (var_desc, type, non_public_p);
case POINTER_TYPE: case POINTER_TYPE:
if (TYPE_PTRMEM_P (type)) return ptr_initializer (var_desc, type, non_public_p);
return ptm_initializer (var_desc, type, non_public_p);
else
return ptr_initializer (var_desc, type, non_public_p);
break;
case ENUMERAL_TYPE: case ENUMERAL_TYPE:
return generic_initializer (var_desc, type); return generic_initializer (var_desc, type);
break; break;
@ -1164,8 +1158,10 @@ get_pseudo_ti_desc (tree type)
{ {
switch (TREE_CODE (type)) switch (TREE_CODE (type))
{ {
case OFFSET_TYPE:
return ptm_desc_type_node;
case POINTER_TYPE: case POINTER_TYPE:
return TYPE_PTRMEM_P (type) ? ptm_desc_type_node : ptr_desc_type_node; return ptr_desc_type_node;
case ENUMERAL_TYPE: case ENUMERAL_TYPE:
return enum_desc_type_node; return enum_desc_type_node;
case FUNCTION_TYPE: case FUNCTION_TYPE:

View File

@ -1367,7 +1367,8 @@ finish_qualified_id_expr (tree qualifying_class, tree expr, bool done,
{ {
if (TREE_CODE (expr) == SCOPE_REF) if (TREE_CODE (expr) == SCOPE_REF)
expr = TREE_OPERAND (expr, 1); expr = TREE_OPERAND (expr, 1);
expr = build_offset_ref (qualifying_class, expr); expr = build_offset_ref (qualifying_class, expr,
/*address_p=*/true);
return expr; return expr;
} }
@ -1396,13 +1397,9 @@ finish_qualified_id_expr (tree qualifying_class, tree expr, bool done,
BASELINK_ACCESS_BINFO (expr), BASELINK_ACCESS_BINFO (expr),
/*preserve_reference=*/false)); /*preserve_reference=*/false));
else if (done) else if (done)
{ /* The expression is a qualified name whose address is not
/* The expression is a qualified name whose address is not being taken. */
being taken. */ expr = build_offset_ref (qualifying_class, expr, /*address_p=*/false);
expr = build_offset_ref (qualifying_class, expr);
if (TREE_CODE (expr) == OFFSET_REF)
expr = resolve_offset_ref (expr);
}
} }
return expr; return expr;

View File

@ -1775,10 +1775,8 @@ pod_type_p (tree t)
return 1; return 1;
if (TYPE_PTR_P (t)) if (TYPE_PTR_P (t))
return 1; /* pointer to non-member */ return 1; /* pointer to non-member */
if (TYPE_PTRMEM_P (t)) if (TYPE_PTR_TO_MEMBER_P (t))
return 1; /* pointer to member object */ return 1; /* pointer to member */
if (TYPE_PTRMEMFUNC_P (t))
return 1; /* pointer to member function */
if (! CLASS_TYPE_P (t)) if (! CLASS_TYPE_P (t))
return 0; /* other non-class type (reference or function) */ return 0; /* other non-class type (reference or function) */

View File

@ -48,22 +48,17 @@ Boston, MA 02111-1307, USA. */
static tree convert_for_assignment (tree, tree, const char *, tree, int); static tree convert_for_assignment (tree, tree, const char *, tree, int);
static tree cp_pointer_int_sum (enum tree_code, tree, tree); static tree cp_pointer_int_sum (enum tree_code, tree, tree);
static tree rationalize_conditional_expr (enum tree_code, 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_real (tree, tree, int);
static int comp_ptr_ttypes_const (tree, tree); 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_except_types (tree, tree, bool);
static bool comp_array_types (tree, tree, bool); static bool comp_array_types (tree, tree, bool);
static tree common_base_type (tree, tree); static tree common_base_type (tree, tree);
static tree lookup_anon_field (tree, tree); static tree lookup_anon_field (tree, tree);
static tree pointer_diff (tree, 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 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 void casts_away_constness_r (tree *, tree *);
static bool casts_away_constness (tree, tree); static bool casts_away_constness (tree, tree);
static void maybe_warn_about_returning_address_of_local (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); static tree lookup_destructor (tree, tree, tree);
/* Return the target type of TYPE, which means return T for: /* 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) == ARRAY_TYPE
|| TREE_CODE (type) == FUNCTION_TYPE || TREE_CODE (type) == FUNCTION_TYPE
|| TREE_CODE (type) == METHOD_TYPE || TREE_CODE (type) == METHOD_TYPE
|| TREE_CODE (type) == OFFSET_TYPE) || TYPE_PTRMEM_P (type))
type = TREE_TYPE (type); type = TREE_TYPE (type);
return type; return type;
} }
@ -169,56 +164,9 @@ type_unknown_p (tree exp)
{ {
return (TREE_CODE (exp) == OVERLOAD return (TREE_CODE (exp) == OVERLOAD
|| TREE_CODE (exp) == TREE_LIST || TREE_CODE (exp) == TREE_LIST
|| TREE_TYPE (exp) == unknown_type_node || 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));
} }
/* 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. /* Return the common type of two parameter lists.
We assume that comptypes has already been done and returned 1; 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. /* 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 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 tree
composite_pointer_type (tree t1, tree t2, tree arg1, tree arg2, composite_pointer_type (tree t1, tree t2, tree arg1, tree arg2,
const char* location) const char* location)
{ {
tree result_type; tree class1;
tree attributes; tree class2;
/* [expr.rel] /* [expr.rel]
@ -467,16 +484,6 @@ composite_pointer_type (tree t1, tree t2, tree arg1, tree arg2,
if (null_ptr_cst_p (arg2)) if (null_ptr_cst_p (arg2))
return t1; 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: /* We have:
[expr.rel] [expr.rel]
@ -487,45 +494,78 @@ composite_pointer_type (tree t1, tree t2, tree arg1, tree arg2,
and cv2. and cv2.
If either type is a pointer to void, make sure it is T1. */ 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; tree t;
t = t1; t = t1;
t1 = t2; t1 = t2;
t2 = t; t2 = t;
} }
/* Now, if T1 is a pointer to void, merge the qualifiers. */ /* 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)) if (pedantic && TYPE_PTRFN_P (t2))
pedwarn ("ISO C++ forbids %s between pointer of type `void *' and pointer-to-function", location); pedwarn ("ISO C++ forbids %s between pointer of type `void *' and pointer-to-function", location);
t1 = TREE_TYPE (t1); result_type
t2 = TREE_TYPE (t2); = cp_build_qualified_type (void_type_node,
result_type = cp_build_qualified_type (void_type_node, (cp_type_quals (TREE_TYPE (t1))
(cp_type_quals (t1) | cp_type_quals (TREE_TYPE (t2))));
| cp_type_quals (t2)));
result_type = build_pointer_type (result_type); 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);
} }
else
/* [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)))
{ {
tree full1 = qualify_type_recursive (t1, t2); class1 = TREE_TYPE (t1);
tree full2 = qualify_type_recursive (t2, t1); class2 = TREE_TYPE (t2);
int val = comp_target_types (full1, full2, 1); if (DERIVED_FROM_P (class1, class2))
t2 = (build_pointer_type
if (val > 0) (cp_build_qualified_type (class1, TYPE_QUALS (class2))));
result_type = full1; else if (DERIVED_FROM_P (class2, class1))
else if (val < 0) t1 = (build_pointer_type
result_type = full2; (cp_build_qualified_type (class2, TYPE_QUALS (class1))));
else else
{ {
pedwarn ("%s between distinct pointer types `%T' and `%T' lacks a cast", error ("%s between distinct pointer types `%T' and `%T' "
location, t1, t2); "lacks a cast", location, t1, t2);
result_type = ptr_type_node; return error_mark_node;
}
}
/* [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)))
{
class1 = TYPE_PTRMEM_CLASS_TYPE (t1);
class2 = TYPE_PTRMEM_CLASS_TYPE (t2);
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
{
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. /* Return the merged type of two types.
@ -557,8 +597,6 @@ merge_types (tree t1, tree t2)
/* Merge the attributes. */ /* Merge the attributes. */
attributes = (*targetm.merge_type_attributes) (t1, t2); 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)) if (TYPE_PTRMEMFUNC_P (t1))
t1 = TYPE_PTRMEMFUNC_FN_TYPE (t1); t1 = TYPE_PTRMEMFUNC_FN_TYPE (t1);
if (TYPE_PTRMEMFUNC_P (t2)) if (TYPE_PTRMEMFUNC_P (t2))
@ -706,7 +744,6 @@ common_type (tree t1, tree t2)
|| (TYPE_PTRMEMFUNC_P (t1) && TYPE_PTRMEMFUNC_P (t2))) || (TYPE_PTRMEMFUNC_P (t1) && TYPE_PTRMEMFUNC_P (t2)))
return composite_pointer_type (t1, t2, error_mark_node, error_mark_node, return composite_pointer_type (t1, t2, error_mark_node, error_mark_node,
"conversion"); "conversion");
else else
abort (); abort ();
} }
@ -995,206 +1032,6 @@ comptypes (tree t1, tree t2, int strict)
return false; 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. */ /* Returns 1 if TYPE1 is at least as qualified as TYPE2. */
bool bool
@ -1333,80 +1170,6 @@ compparms (tree parms1, tree parms2)
return true; 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 tree
cxx_sizeof_or_alignof_type (tree type, enum tree_code op, int complain) 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); pedwarn ("invalid application of `%s' to a member function", op_name);
value = size_one_node; 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 else
value = c_sizeof_or_alignof_type (complete_type (type), op, complain); 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' won't be an error_mark_node if we were given a
pointer to member, so it's cool to check for this here. */ 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); error ("invalid use of `%s' on pointer to member", errorstring);
else if (pointer != error_mark_node) 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. /* Subtraction of two similar pointers.
We must subtract them as integers, then divide by object size. */ We must subtract them as integers, then divide by object size. */
if (code0 == POINTER_TYPE && code1 == POINTER_TYPE 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)); return pointer_diff (op0, op1, common_type (type0, type1));
/* Handle pointer minus int. Just like pointer plus int. */ /* Handle pointer minus int. Just like pointer plus int. */
else if (code0 == POINTER_TYPE && code1 == INTEGER_TYPE) 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 == INTEGER_TYPE || code1 == REAL_TYPE
|| code1 == COMPLEX_TYPE)) || code1 == COMPLEX_TYPE))
short_compare = 1; 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, result_type = composite_pointer_type (type0, type1, op0, op1,
"comparison"); "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; 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; result_type = type1;
else if (code0 == POINTER_TYPE && code1 == INTEGER_TYPE) 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"); pedwarn ("ISO C++ forbids using pointer to a function in subtraction");
if (TREE_CODE (target_type) == METHOD_TYPE) if (TREE_CODE (target_type) == METHOD_TYPE)
pedwarn ("ISO C++ forbids using pointer to a method in subtraction"); 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; /* 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)))) if (!COMPLETE_TYPE_P (TREE_TYPE (TREE_TYPE (op1))))
error ("invalid use of a pointer to an incomplete type in pointer arithmetic"); error ("invalid use of a pointer to an incomplete type in pointer arithmetic");
op1 = ((TREE_CODE (target_type) == VOID_TYPE op1 = (TYPE_PTROB_P (ptrtype)
|| TREE_CODE (target_type) == FUNCTION_TYPE ? size_in_bytes (target_type)
|| TREE_CODE (target_type) == METHOD_TYPE : integer_one_node);
|| TREE_CODE (target_type) == OFFSET_TYPE)
? integer_one_node
: size_in_bytes (target_type));
/* Do the division. */ /* Do the division. */
@ -3999,7 +3755,6 @@ build_unary_op (enum tree_code code, tree xarg, int noconvert)
if (TREE_CODE (argtype) == POINTER_TYPE) if (TREE_CODE (argtype) == POINTER_TYPE)
{ {
enum tree_code tmp = TREE_CODE (TREE_TYPE (argtype));
tree type = complete_type (TREE_TYPE (argtype)); tree type = complete_type (TREE_TYPE (argtype));
if (!COMPLETE_OR_VOID_TYPE_P (type)) 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) || code == POSTINCREMENT_EXPR)
? "increment" : "decrement"), TREE_TYPE (argtype)); ? "increment" : "decrement"), TREE_TYPE (argtype));
else if ((pedantic || warn_pointer_arith) else if ((pedantic || warn_pointer_arith)
&& (tmp == FUNCTION_TYPE || tmp == METHOD_TYPE && !TYPE_PTROB_P (argtype))
|| tmp == VOID_TYPE || tmp == OFFSET_TYPE))
pedwarn ("ISO C++ forbids %sing a pointer of type `%T'", pedwarn ("ISO C++ forbids %sing a pointer of type `%T'",
((code == PREINCREMENT_EXPR ((code == PREINCREMENT_EXPR
|| code == POSTINCREMENT_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); error ("invalid use of `--' on bool variable `%D'", arg);
return error_mark_node; 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); val = boolean_increment (code, arg);
#endif
} }
else else
val = build (code, TREE_TYPE (arg), arg, inc); 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. */ regardless of NOCONVERT. */
argtype = lvalue_type (arg); argtype = lvalue_type (arg);
if (TREE_CODE (arg) == OFFSET_REF)
goto offset_ref;
if (TREE_CODE (argtype) == REFERENCE_TYPE) if (TREE_CODE (argtype) == REFERENCE_TYPE)
{ {
arg = build1 arg = build1
@ -4183,9 +3935,10 @@ build_unary_op (enum tree_code code, tree xarg, int noconvert)
" Say `&%T::%D'", " Say `&%T::%D'",
base, name); base, name);
} }
arg = build_offset_ref (base, name); arg = build_offset_ref (base, name, /*address_p=*/true);
} }
offset_ref:
if (type_unknown_p (arg)) if (type_unknown_p (arg))
return build1 (ADDR_EXPR, unknown_type_node, 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 if (TREE_CODE (TREE_TYPE (arg)) == FUNCTION_TYPE
|| TREE_CODE (TREE_TYPE (arg)) == METHOD_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; tree t;
my_friendly_assert (TREE_CODE (arg) != SCOPE_REF, 313); 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 /* 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 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)) if (casts_away_constness (src_type, dest_type))
error ("static_cast from type `%T' to type `%T' casts away constness", error ("%s from type `%T' to type `%T' casts away constness",
src_type, dest_type); description, src_type, dest_type);
} }
/* Return an expression representing static_cast<TYPE>(EXPR). */ /* Return an expression representing static_cast<TYPE>(EXPR). */
@ -4726,7 +4478,7 @@ build_static_cast (tree type, tree expr)
{ {
tree base; 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), base = lookup_base (TREE_TYPE (type), TREE_TYPE (intype),
ba_check | ba_quiet, NULL); ba_check | ba_quiet, NULL);
return build_base_path (MINUS_EXPR, expr, base, /*nonnull=*/false); 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)) 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)) if (TYPE_PTRMEM_P (type))
{ {
tree delta;
if (TREE_CODE (expr) == PTRMEM_CST) if (TREE_CODE (expr) == PTRMEM_CST)
expr = cplus_expand_constant (expr); expr = cplus_expand_constant (expr);
expr = cp_build_binary_op (PLUS_EXPR, delta = get_delta_difference (c1, c2, /*force=*/1);
cp_convert (ptrdiff_type_node, expr), if (!integer_zerop (delta))
get_delta_difference (c1, c2, expr = cp_build_binary_op (PLUS_EXPR,
/*force=*/1)); build_nop (ptrdiff_type_node, expr),
delta);
return build_nop (type, expr); return build_nop (type, expr);
} }
else else
@ -4785,7 +4540,7 @@ build_static_cast (tree type, tree expr)
&& VOID_TYPE_P (TREE_TYPE (intype)) && VOID_TYPE_P (TREE_TYPE (intype))
&& TYPE_PTROB_P (type)) && 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); 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)) else if ((TYPE_PTRMEM_P (type) && TYPE_PTRMEM_P (intype))
|| (TYPE_PTROBV_P (type) && TYPE_PTROBV_P (intype))) || (TYPE_PTROBV_P (type) && TYPE_PTROBV_P (intype)))
{ {
if (! comp_ptr_ttypes_reinterpret (TREE_TYPE (type), TREE_TYPE (intype))) check_for_casting_away_constness (intype, type, "reinterpret_cast");
pedwarn ("reinterpret_cast from `%T' to `%T' casts away const (or volatile)",
intype, type);
expr = decl_constant_value (expr); expr = decl_constant_value (expr);
return fold (build1 (NOP_EXPR, type, expr)); return fold (build1 (NOP_EXPR, type, expr));
} }
@ -4932,8 +4684,9 @@ build_const_cast (tree type, tree expr)
return convert_from_reference (expr); return convert_from_reference (expr);
} }
} }
else if (TREE_CODE (type) == POINTER_TYPE else if (((TREE_CODE (type) == POINTER_TYPE
&& TREE_CODE (intype) == 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))) && comp_ptr_ttypes_const (TREE_TYPE (type), TREE_TYPE (intype)))
return cp_convert (type, expr); return cp_convert (type, expr);
@ -5048,11 +4801,11 @@ build_c_cast (tree type, tree expr)
otype, type); otype, type);
if (TREE_CODE (type) == INTEGER_TYPE if (TREE_CODE (type) == INTEGER_TYPE
&& TREE_CODE (otype) == POINTER_TYPE && TYPE_PTR_P (otype)
&& TYPE_PRECISION (type) != TYPE_PRECISION (otype)) && TYPE_PRECISION (type) != TYPE_PRECISION (otype))
warning ("cast from pointer to integer of different size"); 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 && TREE_CODE (otype) == INTEGER_TYPE
&& TYPE_PRECISION (type) != TYPE_PRECISION (otype) && TYPE_PRECISION (type) != TYPE_PRECISION (otype)
/* Don't warn about converting any constant. */ /* Don't warn about converting any constant. */
@ -5785,13 +5538,9 @@ static tree
convert_for_assignment (tree type, tree rhs, convert_for_assignment (tree type, tree rhs,
const char *errtype, tree fndecl, int parmnum) const char *errtype, tree fndecl, int parmnum)
{ {
register enum tree_code codel = TREE_CODE (type);
register tree rhstype; register tree rhstype;
register enum tree_code coder; register enum tree_code coder;
if (codel == OFFSET_TYPE)
abort ();
/* Strip NON_LVALUE_EXPRs since we aren't using as an lvalue. */ /* Strip NON_LVALUE_EXPRs since we aren't using as an lvalue. */
if (TREE_CODE (rhs) == NON_LVALUE_EXPR) if (TREE_CODE (rhs) == NON_LVALUE_EXPR)
rhs = TREE_OPERAND (rhs, 0); rhs = TREE_OPERAND (rhs, 0);
@ -6266,7 +6015,7 @@ check_return_expr (tree retval)
static int static int
comp_ptr_ttypes_real (tree to, tree from, int constp) 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)) 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) if (constp == 0)
return 0; return 0;
else to_more_cv_qualified = true;
++to_more_cv_qualified;
} }
if (constp > 0) 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 /* Returns the type qualifiers for this type, including the qualifiers on the
elements for an array type. */ 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 pointer to member level is ignored when determining if a const
cv-qualifier has been cast away. */ cv-qualifier has been cast away. */
if (TYPE_PTRMEM_P (*t1)) 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)) 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] /* [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 "pointer to T1" to the type "pointer to T2" casts away
constness. */ constness. */
return casts_away_constness return casts_away_constness
(build_pointer_type (TREE_TYPE (TREE_TYPE (t1))), (build_pointer_type (TYPE_PTRMEM_POINTED_TO_TYPE (t1)),
build_pointer_type (TREE_TYPE (TREE_TYPE (t2)))); build_pointer_type (TYPE_PTRMEM_POINTED_TO_TYPE (t2)));
/* Casting away constness is only something that makes sense for /* Casting away constness is only something that makes sense for
pointer or reference types. */ pointer or reference types. */
@ -6532,23 +6246,6 @@ casts_away_constness (tree t1, tree t2)
return false; 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. /* If T is a REFERENCE_TYPE return the type to which T refers.
Otherwise, return T itself. */ Otherwise, return T itself. */

View File

@ -506,7 +506,7 @@ digest_init (tree type, tree init, tree* tail)
if (code == INTEGER_TYPE || code == REAL_TYPE || code == POINTER_TYPE if (code == INTEGER_TYPE || code == REAL_TYPE || code == POINTER_TYPE
|| code == ENUMERAL_TYPE || code == REFERENCE_TYPE || code == ENUMERAL_TYPE || code == REFERENCE_TYPE
|| code == BOOLEAN_TYPE || code == COMPLEX_TYPE || code == BOOLEAN_TYPE || code == COMPLEX_TYPE
|| TYPE_PTRMEMFUNC_P (type)) || TYPE_PTR_TO_MEMBER_P (type))
{ {
if (raw_constructor) if (raw_constructor)
{ {
@ -1070,8 +1070,7 @@ build_m_component_ref (tree datum, tree component)
return error_mark_node; return error_mark_node;
ptrmem_type = TREE_TYPE (component); ptrmem_type = TREE_TYPE (component);
if (!TYPE_PTRMEM_P (ptrmem_type) if (!TYPE_PTR_TO_MEMBER_P (ptrmem_type))
&& !TYPE_PTRMEMFUNC_P (ptrmem_type))
{ {
error ("`%E' cannot be used as a member pointer, since it is of type `%T'", error ("`%E' cannot be used as a member pointer, since it is of type `%T'",
component, ptrmem_type); component, ptrmem_type);
@ -1107,10 +1106,12 @@ build_m_component_ref (tree datum, tree component)
type = cp_build_qualified_type (type, type = cp_build_qualified_type (type,
(cp_type_quals (type) (cp_type_quals (type)
| cp_type_quals (TREE_TYPE (datum)))); | cp_type_quals (TREE_TYPE (datum))));
/* Build an expression for "object + offset" where offset is the
datum = build_base_path (PLUS_EXPR, build_address (datum), binfo, 1); value stored in the pointer-to-data-member. */
component = cp_convert (ptrdiff_type_node, component); datum = build (PLUS_EXPR, build_pointer_type (type),
datum = build (PLUS_EXPR, build_pointer_type (type), datum, component); build_base_path (PLUS_EXPR, build_address (datum),
binfo, 1),
build_nop (ptrdiff_type_node, component));
return build_indirect_ref (datum, 0); return build_indirect_ref (datum, 0);
} }
else else

View File

@ -193,7 +193,8 @@ force_fit_type (tree t, int overflow)
low = TREE_INT_CST_LOW (t); low = TREE_INT_CST_LOW (t);
high = TREE_INT_CST_HIGH (t); high = TREE_INT_CST_HIGH (t);
if (POINTER_TYPE_P (TREE_TYPE (t))) if (POINTER_TYPE_P (TREE_TYPE (t))
|| TREE_CODE (TREE_TYPE (t)) == OFFSET_TYPE)
prec = POINTER_SIZE; prec = POINTER_SIZE;
else else
prec = TYPE_PRECISION (TREE_TYPE (t)); prec = TYPE_PRECISION (TREE_TYPE (t));

View File

@ -3695,6 +3695,7 @@ output_constant (tree exp, unsigned HOST_WIDE_INT size, unsigned int align)
case ENUMERAL_TYPE: case ENUMERAL_TYPE:
case POINTER_TYPE: case POINTER_TYPE:
case REFERENCE_TYPE: case REFERENCE_TYPE:
case OFFSET_TYPE:
if (! assemble_integer (expand_expr (exp, NULL_RTX, VOIDmode, if (! assemble_integer (expand_expr (exp, NULL_RTX, VOIDmode,
EXPAND_INITIALIZER), EXPAND_INITIALIZER),
size, align, 0)) size, align, 0))