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