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