{
tree type;
- if (current_template_parms)
+ if (processing_template_decl)
return value;
type = TREE_TYPE (value);
else if (TREE_CODE (type) == ARRAY_TYPE && TYPE_DOMAIN (type))
{
tree t = complete_type (TREE_TYPE (type));
- if (TYPE_SIZE (t) != NULL_TREE)
- type = build_cplus_array_type (t, TYPE_DOMAIN (type));
+ if (TYPE_SIZE (t) != NULL_TREE && ! processing_template_decl)
+ layout_type (type);
+ TYPE_NEEDS_CONSTRUCTING (type)
+ = TYPE_NEEDS_CONSTRUCTING (TYPE_MAIN_VARIANT (t));
+ TYPE_NEEDS_DESTRUCTOR (type)
+ = TYPE_NEEDS_DESTRUCTOR (TYPE_MAIN_VARIANT (t));
}
else if (IS_AGGR_TYPE (type) && CLASSTYPE_TEMPLATE_INSTANTIATION (type))
instantiate_class_template (TYPE_MAIN_VARIANT (type));
{
int rval;
look_hard:
- rval = t1 == t2 || UNIQUELY_DERIVED_FROM_P (t1, t2);
+ rval = t1 == t2 || DERIVED_FROM_P (t1, t2);
if (rval)
{
}
if (strict < 0)
{
- val = UNIQUELY_DERIVED_FROM_P (t2, t1);
+ val = DERIVED_FROM_P (t2, t1);
break;
}
}
enum tree_code code = TREE_CODE (type);
tree t;
- if (current_template_parms)
+ if (processing_template_decl)
return build_min (SIZEOF_EXPR, sizetype, type);
if (code == FUNCTION_TYPE)
expr_sizeof (e)
tree e;
{
- if (current_template_parms)
+ if (processing_template_decl)
return build_min (SIZEOF_EXPR, sizetype, e);
if (TREE_CODE (e) == COMPONENT_REF
if (t != type)
return convert (t, exp);
}
- if (flag_traditional
- && TYPE_MAIN_VARIANT (type) == float_type_node)
- return convert (double_type_node, exp);
return exp;
}
{
tree binfo = binfo_or_else (basetype, dtype);
if (binfo)
- return build_component_ref (build_scoped_ref (datum, basetype),
- field, binfo, 1);
+ return build_x_component_ref (build_scoped_ref (datum, basetype),
+ field, binfo, 1);
}
return error_mark_node;
}
tree datum, field;
int protect;
{
- register tree basetype = TREE_TYPE (datum);
- register enum tree_code code = TREE_CODE (basetype);
- register tree ref;
-
- if (code == REFERENCE_TYPE)
- {
- datum = convert_from_reference (datum);
- basetype = TREE_TYPE (datum);
- code = TREE_CODE (basetype);
- }
-
- if (! IS_AGGR_TYPE_CODE (code))
- {
- if (code != ERROR_MARK)
- cp_error ("request for member `%D' in `%E', which is of non-aggregate type `%T'",
- field, datum, basetype);
- return error_mark_node;
- }
-
- if (TYPE_SIZE (basetype) == 0)
- {
- incomplete_type_error (0, basetype);
- return error_mark_node;
- }
-
- /* Look up component name in the structure type definition. */
-
- if (field == error_mark_node)
- my_friendly_abort (115);
-
- if (TREE_STATIC (field))
- return field;
-
- if (datum == current_class_ref)
- {
- tree access = compute_access (TYPE_BINFO (current_class_type), field);
-
- if (access == access_private_node)
- {
- cp_error ("field `%D' is private", field);
- return error_mark_node;
- }
- else if (access == access_protected_node)
- {
- cp_error ("field `%D' is protected", field);
- return error_mark_node;
- }
- }
-
- ref = build (COMPONENT_REF, TREE_TYPE (field), datum, field);
-
- if (TREE_READONLY (datum) || TREE_READONLY (field))
- TREE_READONLY (ref) = 1;
- if (TREE_THIS_VOLATILE (datum) || TREE_THIS_VOLATILE (field))
- TREE_THIS_VOLATILE (ref) = 1;
- if (DECL_MUTABLE_P (field))
- TREE_READONLY (ref) = 0;
-
- return ref;
+ return build_component_ref (datum, field, NULL_TREE, protect);
}
/* Given a COND_EXPR in T, return it in a form that we can, for
register tree field = NULL;
register tree ref;
- if (current_template_parms)
+ if (processing_template_decl)
return build_min_nt (COMPONENT_REF, datum, component);
/* If DATUM is a COMPOUND_EXPR or COND_EXPR, move our reference
hierarchy, the compiler will abort (because vptr lookups are
not supposed to be ambiguous. */
field = CLASSTYPE_VFIELD (basetype);
- else if (TREE_CODE (component) == FIELD_DECL)
+ else if (TREE_CODE (component) == FIELD_DECL
+ || TREE_CODE (component) == TYPE_DECL)
{
field = component;
}
fndecl = build_vfn_ref (&addr, datum, DECL_VINDEX (fndecl));
}
mark_used (fndecl);
- return fndecl;
+ return build (OFFSET_REF, TREE_TYPE (fndecl), datum, fndecl);
}
if (access == access_protected_node)
cp_error ("member function `%D' is protected", fndecl);
return ref;
}
+
+/* Variant of build_component_ref for use in expressions, which should
+ never have REFERENCE_TYPE. */
+
+tree
+build_x_component_ref (datum, component, basetype_path, protect)
+ tree datum, component, basetype_path;
+ int protect;
+{
+ tree t = build_component_ref (datum, component, basetype_path, protect);
+
+ if (! processing_template_decl)
+ t = convert_from_reference (t);
+
+ return t;
+}
\f
/* Given an expression PTR for a pointer, return an expression
for the value pointed to.
{
tree rval;
- if (current_template_parms)
+ if (processing_template_decl)
return build_min_nt (INDIRECT_REF, ptr);
rval = build_opfncall (INDIRECT_REF, LOOKUP_NORMAL, ptr, NULL_TREE, NULL_TREE);
tree ptr;
char *errorstring;
{
- register tree pointer = (TREE_CODE (TREE_TYPE (ptr)) == REFERENCE_TYPE ?
- ptr : default_conversion (ptr));
- register tree type = TREE_TYPE (pointer);
+ register tree pointer, type;
+
+ if (ptr == error_mark_node)
+ return error_mark_node;
+
+ pointer = (TREE_CODE (TREE_TYPE (ptr)) == REFERENCE_TYPE
+ ? ptr : default_conversion (ptr));
+ type = TREE_TYPE (pointer);
if (ptr == current_class_ptr)
return current_class_ref;
if (function == error_mark_node)
return error_mark_node;
- if (current_template_parms)
+ if (processing_template_decl)
return build_min_nt (CALL_EXPR, function, params, NULL_TREE);
type = TREE_TYPE (function);
/* Handle methods, friends, and overloaded functions, respectively. */
if (is_method)
{
+ tree basetype = NULL_TREE;
+
if (TREE_CODE (function) == FUNCTION_DECL)
{
+ basetype = DECL_CLASS_CONTEXT (function);
+
if (DECL_NAME (function))
function = DECL_NAME (function);
else
else if (TREE_CODE (function) == TREE_LIST)
{
my_friendly_assert (TREE_CODE (TREE_VALUE (function)) == FUNCTION_DECL, 312);
+ basetype = DECL_CLASS_CONTEXT (TREE_VALUE (function));
function = TREE_PURPOSE (function);
}
else if (TREE_CODE (function) != IDENTIFIER_NODE)
must go through here in case it is a virtual function.
@@ Perhaps this could be optimized. */
+ if (basetype && (! current_class_type
+ || ! DERIVED_FROM_P (basetype, current_class_type)))
+ return build_member_call (basetype, function, params);
+
if (decl == NULL_TREE)
{
if (current_class_type == NULL_TREE)
{
tree val = TREE_VALUE (function);
+ if (flag_ansi_overloading)
+ return build_new_function_call (function, params, NULL_TREE);
+
if (TREE_CODE (val) == TEMPLATE_DECL)
return build_overload_call_real
(function, params, LOOKUP_COMPLAIN, (struct candidate *)0, 0);
if (TREE_CODE (type) == REFERENCE_TYPE)
type = TREE_TYPE (type);
- if (TYPE_LANG_SPECIFIC (type)
- && TYPE_OVERLOADS_CALL_EXPR (complete_type (type)))
+ if (IS_AGGR_TYPE (type))
return build_opfncall (CALL_EXPR, LOOKUP_NORMAL, function, params, NULL_TREE);
}
needs to be separately compiled). */
if (DECL_INLINE (function))
- {
- /* Is it a synthesized method that needs to be synthesized? */
- if (DECL_ARTIFICIAL (function) && ! DECL_INITIAL (function)
- /* Kludge: don't synthesize for default args. */
- && current_function_decl)
- synthesize_method (function);
-
- function = inline_conversion (function);
- }
+ function = inline_conversion (function);
else
function = build_addr_func (function);
}
return result;
result = require_complete_type (result);
}
+ if (IS_AGGR_TYPE (value_type))
+ result = build_cplus_new (value_type, result);
return convert_from_reference (result);
}
}
{
tree rval;
- if (current_template_parms)
+ if (processing_template_decl)
return build_min_nt (code, arg1, arg2);
+ if (flag_ansi_overloading)
+ return build_new_op (code, LOOKUP_NORMAL, arg1, arg2, NULL_TREE);
+
rval = build_opfncall (code, LOOKUP_SPECULATIVELY,
arg1, arg2, NULL_TREE);
if (rval)
else if (code0 == POINTER_TYPE && code1 == INTEGER_TYPE)
{
result_type = type0;
- if (pedantic)
- pedwarn ("ANSI C++ forbids comparison between pointer and integer");
- else if (! flag_traditional)
- warning ("comparison between pointer and integer");
+ pedwarn ("ANSI C++ forbids comparison between pointer and integer");
}
else if (code0 == INTEGER_TYPE && code1 == POINTER_TYPE)
{
result_type = type1;
- if (pedantic)
- pedwarn ("ANSI C++ forbids comparison between pointer and integer");
- else if (! flag_traditional)
- warning ("comparison between pointer and integer");
+ pedwarn ("ANSI C++ forbids comparison between pointer and integer");
}
break;
}
enum tree_code code;
tree xarg;
{
- if (current_template_parms)
+ if (processing_template_decl)
return build_min_nt (code, xarg, NULL_TREE);
/* & rec, on incomplete RECORD_TYPEs is the simple opr &, not an
/* don't look for a function */;
else
{
- tree rval = build_opfncall (code, LOOKUP_SPECULATIVELY, xarg,
- NULL_TREE, NULL_TREE);
- if (rval)
- return build_opfncall (code, LOOKUP_NORMAL, xarg,
+ tree rval;
+
+ if (flag_ansi_overloading)
+ {
+ rval = build_new_op (code, LOOKUP_NORMAL, xarg,
NULL_TREE, NULL_TREE);
+ if (rval || code != ADDR_EXPR)
+ return rval;
+ }
+ else
+ {
+ rval = build_opfncall (code, LOOKUP_SPECULATIVELY, xarg,
+ NULL_TREE, NULL_TREE);
+ if (rval)
+ return build_opfncall (code, LOOKUP_NORMAL, xarg,
+ NULL_TREE, NULL_TREE);
+ }
}
if (code == ADDR_EXPR)
tree expr;
{
tree t;
- if (current_template_parms)
+ if (processing_template_decl)
return expr;
t = convert (boolean_type_node, expr);
t = fold (build1 (CLEANUP_POINT_EXPR, boolean_type_node, t));
is really the representation of a pointer to it.
Here give the representation its true type. */
tree t;
- tree offset;
my_friendly_assert (TREE_CODE (arg) != SCOPE_REF, 313);
return build_unary_op (ADDR_EXPR, t, 0);
else
{
+ tree type;
+ tree offset = integer_zero_node;
+
if (TREE_OPERAND (arg, 0)
&& (TREE_CODE (TREE_OPERAND (arg, 0)) != NOP_EXPR
|| TREE_OPERAND (TREE_OPERAND (arg, 0), 0) != error_mark_node))
return error_mark_node;
}
- /* Add in the offset to the right subobject. */
- offset = get_delta_difference (DECL_FIELD_CONTEXT (t),
- TREE_TYPE (TREE_OPERAND (arg, 0)),
- 0);
+ type = TREE_TYPE (TREE_OPERAND (arg, 0));
+
+ if (TREE_CODE (TREE_TYPE (arg)) == OFFSET_TYPE)
+ {
+ /* Add in the offset to the intermediate subobject, if any. */
+ offset = get_delta_difference (TYPE_OFFSET_BASETYPE (TREE_TYPE (arg)),
+ type,
+ 0);
+ type = TYPE_OFFSET_BASETYPE (TREE_TYPE (arg));
+ }
+
+ /* Now in the offset to the final subobject. */
+ offset = size_binop (PLUS_EXPR,
+ offset,
+ get_delta_difference (DECL_FIELD_CONTEXT (t),
+ type,
+ 0));
/* Add in the offset to the field. */
offset = size_binop (PLUS_EXPR, offset,
{
tree rval = NULL_TREE;
- if (current_template_parms)
+ if (processing_template_decl)
return build_min_nt (COND_EXPR, ifexp, op1, op2);
+ if (flag_ansi_overloading)
+ return build_new_op (COND_EXPR, LOOKUP_NORMAL, ifexp, op1, op2);
+
/* See comments in `build_x_binary_op'. */
if (op1 != 0)
rval = build_opfncall (COND_EXPR, LOOKUP_SPECULATIVELY, ifexp, op1, op2);
result = fold (build (COND_EXPR, type1, ifexp, op1, op2));
if (TREE_TYPE (result) != type1)
result = build1 (NOP_EXPR, type1, result);
+ /* Expand both sides into the same slot,
+ hopefully the target of the ?: expression. */
+ if (TREE_CODE (op1) == TARGET_EXPR && TREE_CODE (op2) == TARGET_EXPR)
+ {
+ tree slot = build (VAR_DECL, TREE_TYPE (result));
+ layout_decl (slot, 0);
+ result = build (TARGET_EXPR, TREE_TYPE (result),
+ slot, result, NULL_TREE, NULL_TREE);
+ }
return result;
}
pedwarn ("ANSI C++ forbids conditional expr with only one void side");
result_type = void_type_node;
}
+ else if (code1 == POINTER_TYPE && null_ptr_cst_p (op2))
+ result_type = qualify_type (type1, type2);
+ else if (code2 == POINTER_TYPE && null_ptr_cst_p (op1))
+ result_type = qualify_type (type2, type1);
else if (code1 == POINTER_TYPE && code2 == POINTER_TYPE)
{
if (comp_target_types (type1, type2, 1))
result_type = common_type (type1, type2);
- else if (integer_zerop (op1) && TREE_TYPE (type1) == void_type_node
- && TREE_CODE (orig_op1) != NOP_EXPR)
- result_type = qualify_type (type2, type1);
- else if (integer_zerop (op2) && TREE_TYPE (type2) == void_type_node
- && TREE_CODE (orig_op2) != NOP_EXPR)
- result_type = qualify_type (type1, type2);
else if (TYPE_MAIN_VARIANT (TREE_TYPE (type1)) == void_type_node)
{
if (pedantic && TREE_CODE (type2) == FUNCTION_TYPE)
}
else if (code1 == POINTER_TYPE && code2 == INTEGER_TYPE)
{
- if (!integer_zerop (op2))
- pedwarn ("pointer/integer type mismatch in conditional expression");
- else
- op2 = null_pointer_node;
-
+ pedwarn ("pointer/integer type mismatch in conditional expression");
result_type = type1;
}
else if (code2 == POINTER_TYPE && code1 == INTEGER_TYPE)
{
- if (!integer_zerop (op1))
- pedwarn ("pointer/integer type mismatch in conditional expression");
- else
- op1 = null_pointer_node;
-
+ pedwarn ("pointer/integer type mismatch in conditional expression");
result_type = type2;
}
tree rest = TREE_CHAIN (list);
tree result;
- if (current_template_parms)
+ if (processing_template_decl)
return build_min_nt (COMPOUND_EXPR, list, NULL_TREE);
if (rest == NULL_TREE)
build_static_cast (type, expr)
tree type, expr;
{
- if (current_template_parms)
+ tree intype, binfo;
+ int ok;
+
+ if (type == error_mark_node || expr == error_mark_node)
+ return error_mark_node;
+
+ if (TREE_CODE (expr) == OFFSET_REF)
+ expr = resolve_offset_ref (expr);
+
+ if (processing_template_decl)
{
tree t = build_min (STATIC_CAST_EXPR, type, expr);
return t;
}
- return build_c_cast (type, expr, 0);
+ /* build_c_cast puts on a NOP_EXPR to make the result not an lvalue.
+ Strip such NOP_EXPRs if VALUE is being used in non-lvalue context. */
+ if (TREE_CODE (type) != REFERENCE_TYPE
+ && TREE_CODE (expr) == NOP_EXPR
+ && TREE_TYPE (expr) == TREE_TYPE (TREE_OPERAND (expr, 0)))
+ expr = TREE_OPERAND (expr, 0);
+
+ if (TREE_CODE (type) == VOID_TYPE)
+ return build1 (CONVERT_EXPR, type, expr);
+
+ if (type_unknown_p (expr))
+ {
+ expr = instantiate_type (type, expr, 1);
+ if (expr == error_mark_node)
+ return error_mark_node;
+ }
+
+ if (TREE_CODE (type) == REFERENCE_TYPE)
+ return (convert_from_reference
+ (convert_to_reference (type, expr, CONV_STATIC|CONV_IMPLICIT,
+ LOOKUP_COMPLAIN, NULL_TREE)));
+
+ if (IS_AGGR_TYPE (type))
+ return build_cplus_new
+ (type, (build_method_call
+ (NULL_TREE, ctor_identifier, build_tree_list (NULL_TREE, expr),
+ TYPE_BINFO (type), LOOKUP_NORMAL)));
+
+ expr = decay_conversion (expr);
+ intype = TREE_TYPE (expr);
+
+ /* FIXME handle casting to array type. */
+
+ ok = 0;
+ if (can_convert_arg (type, intype, expr))
+ ok = 1;
+ else if (TYPE_PTROB_P (type) && TYPE_PTROB_P (intype))
+ {
+ tree binfo;
+ if (IS_AGGR_TYPE (TREE_TYPE (type)) && IS_AGGR_TYPE (TREE_TYPE (intype))
+ && (TYPE_READONLY (TREE_TYPE (type))
+ >= TYPE_READONLY (TREE_TYPE (intype)))
+ && (TYPE_VOLATILE (TREE_TYPE (type))
+ >= TYPE_VOLATILE (TREE_TYPE (intype)))
+ && (binfo = get_binfo (TREE_TYPE (intype), TREE_TYPE (type), 0))
+ && ! TREE_VIA_VIRTUAL (binfo))
+ ok = 1;
+ }
+ else if (TYPE_PTRMEM_P (type) && TYPE_PTRMEM_P (intype))
+ {
+ if (comptypes (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (type))),
+ TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (intype))), 1)
+ && (TYPE_READONLY (TREE_TYPE (TREE_TYPE (type)))
+ >= TYPE_READONLY (TREE_TYPE (TREE_TYPE (intype))))
+ && (TYPE_VOLATILE (TREE_TYPE (TREE_TYPE (type)))
+ >= TYPE_VOLATILE (TREE_TYPE (TREE_TYPE (intype))))
+ && (binfo = get_binfo (TYPE_OFFSET_BASETYPE (intype),
+ TYPE_OFFSET_BASETYPE (type), 0))
+ && ! TREE_VIA_VIRTUAL (binfo))
+ ok = 1;
+ }
+ else if (TREE_CODE (intype) != BOOLEAN_TYPE
+ && TREE_CODE (type) != ARRAY_TYPE
+ && TREE_CODE (type) != FUNCTION_TYPE
+ && can_convert (intype, type))
+ ok = 1;
+
+ if (ok)
+ return build_c_cast (type, expr, 0);
+
+ cp_error ("static_cast from `%T' to `%T'", intype, type);
+ return error_mark_node;
}
tree
build_reinterpret_cast (type, expr)
tree type, expr;
{
- tree intype = TREE_TYPE (expr);
+ tree intype;
- if (current_template_parms)
+ if (type == error_mark_node || expr == error_mark_node)
+ return error_mark_node;
+
+ if (TREE_CODE (expr) == OFFSET_REF)
+ expr = resolve_offset_ref (expr);
+
+ if (processing_template_decl)
{
tree t = build_min (REINTERPRET_CAST_EXPR, type, expr);
return t;
}
- if (TYPE_PTRMEMFUNC_P (type))
- if (TYPE_PTRMEMFUNC_P (intype))
- return build1 (NOP_EXPR, type, expr);
+ if (TREE_CODE (type) != REFERENCE_TYPE)
+ {
+ expr = decay_conversion (expr);
- if (TYPE_PTRMEMFUNC_P (type))
- type = TYPE_PTRMEMFUNC_FN_TYPE (type);
+ /* build_c_cast puts on a NOP_EXPR to make the result not an lvalue.
+ Strip such NOP_EXPRs if VALUE is being used in non-lvalue context. */
+ if (TREE_CODE (expr) == NOP_EXPR
+ && TREE_TYPE (expr) == TREE_TYPE (TREE_OPERAND (expr, 0)))
+ expr = TREE_OPERAND (expr, 0);
+ }
+
+ if (type_unknown_p (expr))
+ {
+ expr = instantiate_type (type, expr, 1);
+ if (expr == error_mark_node)
+ return error_mark_node;
+ }
- if (TYPE_PTRMEMFUNC_P (intype))
- intype = TYPE_PTRMEMFUNC_FN_TYPE (intype);
+ intype = TREE_TYPE (expr);
- if (! POINTER_TYPE_P (type) && ! TREE_CODE (type) == INTEGER_TYPE)
+ if (TREE_CODE (type) == REFERENCE_TYPE)
{
- cp_error ("reinterpret_cast cannot convert to type `%T'", type);
- return error_mark_node;
+ if (! real_lvalue_p (expr))
+ {
+ cp_error ("reinterpret_cast from `%T' rvalue to `%T'", intype, type);
+ return error_mark_node;
+ }
+ expr = build_unary_op (ADDR_EXPR, expr, 0);
+ if (expr != error_mark_node)
+ expr = build_reinterpret_cast
+ (build_pointer_type (TREE_TYPE (type)), expr);
+ if (expr != error_mark_node)
+ expr = build_indirect_ref (expr, 0);
+ return expr;
}
- if (! POINTER_TYPE_P (intype) && ! TREE_CODE (intype) == INTEGER_TYPE)
+ else if (comptypes (TYPE_MAIN_VARIANT (intype), TYPE_MAIN_VARIANT (type), 1))
+ return build_static_cast (type, expr);
+
+ if (TYPE_PTR_P (type) && (TREE_CODE (intype) == INTEGER_TYPE
+ || TREE_CODE (intype) == ENUMERAL_TYPE))
+ /* OK */;
+ else if (TREE_CODE (type) == INTEGER_TYPE && TYPE_PTR_P (intype))
{
- cp_error ("reinterpret_cast cannot convert from type `%T'", type);
- return error_mark_node;
+ if (TYPE_PRECISION (type) < TYPE_PRECISION (intype))
+ cp_pedwarn ("reinterpret_cast from `%T' to `%T' loses precision",
+ intype, type);
}
- if (TREE_CODE (type) == INTEGER_TYPE && TREE_CODE (intype) != POINTER_TYPE)
+ else if ((TYPE_PTRFN_P (type) && TYPE_PTRFN_P (intype))
+ || (TYPE_PTRMEMFUNC_P (type) && TYPE_PTRMEMFUNC_P (intype)))
{
- cp_error ("reinterpret_cast cannot convert non-pointer type `%T' to `%T'",
- intype, type);
- return error_mark_node;
+ if (TREE_READONLY_DECL_P (expr))
+ expr = decl_constant_value (expr);
+ return fold (build1 (NOP_EXPR, type, expr));
}
- if (TREE_CODE (intype) == INTEGER_TYPE && TREE_CODE (type) != POINTER_TYPE)
+ else if ((TYPE_PTRMEM_P (type) && TYPE_PTRMEM_P (intype))
+ || (TYPE_PTROBV_P (type) && TYPE_PTROBV_P (intype)))
+ {
+ if (! comp_ptr_ttypes_reinterpret (TREE_TYPE (type), TREE_TYPE (intype)))
+ cp_pedwarn ("reinterpret_cast from `%T' to `%T' casts away const (or volatile)",
+ intype, type);
+
+ if (TREE_READONLY_DECL_P (expr))
+ expr = decl_constant_value (expr);
+ return fold (build1 (NOP_EXPR, type, expr));
+ }
+ else
{
- cp_error ("reinterpret_cast cannot convert `%T' to non-pointer type `%T'",
- intype, type);
+ cp_error ("reinterpret_cast from `%T' to `%T'", intype, type);
return error_mark_node;
}
-
- if (TREE_CODE (type) == POINTER_TYPE && TREE_CODE (intype) == POINTER_TYPE)
- expr = convert (ptr_type_node, expr);
-
- return build_c_cast (type, expr, 0);
+
+ return convert (type, expr);
}
tree
build_const_cast (type, expr)
tree type, expr;
{
- tree intype = TREE_TYPE (expr);
- tree t1, t2;
+ tree intype;
if (type == error_mark_node || expr == error_mark_node)
return error_mark_node;
- if (current_template_parms)
+ if (TREE_CODE (expr) == OFFSET_REF)
+ expr = resolve_offset_ref (expr);
+
+ if (processing_template_decl)
{
tree t = build_min (CONST_CAST_EXPR, type, expr);
return t;
}
- if (TYPE_PTRMEMFUNC_P (type))
- type = TYPE_PTRMEMFUNC_FN_TYPE (type);
- if (TYPE_PTRMEMFUNC_P (intype))
- intype = TYPE_PTRMEMFUNC_FN_TYPE (intype);
-
- if (! POINTER_TYPE_P (type))
- {
- cp_error ("const_cast cannot convert to non-pointer type `%T'", type);
- return error_mark_node;
- }
- if (TREE_CODE (type) == REFERENCE_TYPE && ! real_lvalue_p (expr))
+ if (TREE_CODE (type) != REFERENCE_TYPE)
{
- cp_error ("const_cast cannot convert rvalue to type `%T'", type);
- return error_mark_node;
- }
- if (TREE_CODE (type) == POINTER_TYPE && TREE_CODE (intype) != POINTER_TYPE)
- {
- cp_error ("const_cast cannot convert non-pointer type `%T' to type `%T'",
- intype, type);
- return error_mark_node;
+ expr = decay_conversion (expr);
+
+ /* build_c_cast puts on a NOP_EXPR to make the result not an lvalue.
+ Strip such NOP_EXPRs if VALUE is being used in non-lvalue context. */
+ if (TREE_CODE (expr) == NOP_EXPR
+ && TREE_TYPE (expr) == TREE_TYPE (TREE_OPERAND (expr, 0)))
+ expr = TREE_OPERAND (expr, 0);
}
- if (TREE_CODE (type) == REFERENCE_TYPE)
+ if (type_unknown_p (expr))
{
- t1 = TREE_TYPE (type);
- t2 = intype;
+ expr = instantiate_type (type, expr, 1);
+ if (expr == error_mark_node)
+ return error_mark_node;
}
- else
- {
- t1 = TREE_TYPE (type);
- t2 = TREE_TYPE (intype);
- for (; TREE_CODE (t1) == POINTER_TYPE && TREE_CODE (t2) == POINTER_TYPE;
- t1 = TREE_TYPE (t1), t2 = TREE_TYPE (t2))
- ;
- }
+ intype = TREE_TYPE (expr);
- if (TREE_CODE (t1) == OFFSET_TYPE && TREE_CODE (t2) == OFFSET_TYPE)
+ if (comptypes (TYPE_MAIN_VARIANT (intype), TYPE_MAIN_VARIANT (type), 1))
+ return build_static_cast (type, expr);
+ else if (TREE_CODE (type) == REFERENCE_TYPE)
{
- if (TYPE_OFFSET_BASETYPE (t1) != TYPE_OFFSET_BASETYPE (t2))
+ if (! real_lvalue_p (expr))
{
- cp_error ("const_cast cannot convert between pointers to members of different types `%T' and `%T'",
- TYPE_OFFSET_BASETYPE (t2), TYPE_OFFSET_BASETYPE (t1));
+ cp_error ("const_cast from `%T' rvalue to `%T'", intype, type);
return error_mark_node;
}
- t1 = TREE_TYPE (t1);
- t2 = TREE_TYPE (t2);
- }
- if (TYPE_MAIN_VARIANT (t1) != TYPE_MAIN_VARIANT (t2))
- {
- cp_error ("const_cast cannot convert unrelated type `%T' to `%T'",
- t2, t1);
- return error_mark_node;
+ if (comp_ptr_ttypes_const (TREE_TYPE (type), intype))
+ return (convert_from_reference
+ (convert_to_reference (type, expr, CONV_CONST|CONV_IMPLICIT,
+ LOOKUP_COMPLAIN, NULL_TREE)));
}
+ else if (TREE_CODE (type) == POINTER_TYPE
+ && TREE_CODE (intype) == POINTER_TYPE
+ && comp_ptr_ttypes_const (TREE_TYPE (type), TREE_TYPE (intype)))
+ return convert (type, expr);
- return build_c_cast (type, expr, 0);
+ cp_error ("const_cast from `%T' to `%T'", intype, type);
+ return error_mark_node;
}
/* Build an expression representing a cast to type TYPE of expression EXPR.
return error_mark_node;
}
- if (current_template_parms)
+ if (processing_template_decl)
{
tree t = build_min (CAST_EXPR, type,
min_tree_cons (NULL_TREE, value, NULL_TREE));
}
/* Always produce some operator for an explicit cast,
- so we can tell (for -pedantic) that the cast is no lvalue.
- Also, pedantically, don't let (void *) (FOO *) 0 be a null
- pointer constant. */
- if (TREE_CODE (type) != REFERENCE_TYPE
- && (value == expr
- || (pedantic
- && TREE_CODE (value) == INTEGER_CST
- && TREE_CODE (expr) == INTEGER_CST
- && TREE_CODE (TREE_TYPE (expr)) != INTEGER_TYPE)))
+ so we can tell (for -pedantic) that the cast is no lvalue. */
+ if (TREE_CODE (type) != REFERENCE_TYPE && value == expr
+ && real_lvalue_p (value))
value = non_lvalue (value);
return value;
else if (TYPE_HAS_TRIVIAL_ASSIGN_REF (lhstype)
&& TYPE_MAIN_VARIANT (lhstype) == TYPE_MAIN_VARIANT (TREE_TYPE (newrhs)))
{
- if (warn_synth)
- /* If we care about this, do overload resolution. */
- build_opfncall (MODIFY_EXPR, LOOKUP_NORMAL,
- lhs, rhs, make_node (NOP_EXPR));
+ build_opfncall (MODIFY_EXPR, LOOKUP_NORMAL,
+ lhs, rhs, make_node (NOP_EXPR));
/* Do the default thing */;
}
enum tree_code modifycode;
tree rhs;
{
- if (current_template_parms)
+ if (processing_template_decl)
return build_min_nt (MODOP_EXPR, lhs,
build_min_nt (modifycode, NULL_TREE, NULL_TREE), rhs);
if (!force)
{
error_not_base_type (from, to);
- error (" in pointer to member function conversion");
+ error (" in pointer to member conversion");
return delta;
}
binfo = get_binfo (to, from, 1);
if (binfo == error_mark_node)
{
- error (" in pointer to member function conversion");
+ error (" in pointer to member conversion");
return delta;
}
if (binfo == 0)
return BINFO_OFFSET (binfo);
}
+static tree
+build_ptrmemfunc1 (type, delta, idx, pfn, delta2)
+ tree type, delta, idx, pfn, delta2;
+{
+ tree u;
+
+#if 0
+ /* This is the old way we did it. We want to avoid calling
+ digest_init, so that it can give an error if we use { } when
+ initializing a pointer to member function. */
+
+ if (pfn)
+ {
+ u = build_nt (CONSTRUCTOR, NULL_TREE,
+ tree_cons (pfn_identifier, pfn, NULL_TREE));
+ }
+ else
+ {
+ u = build_nt (CONSTRUCTOR, NULL_TREE,
+ tree_cons (delta2_identifier, delta2, NULL_TREE));
+ }
+
+ u = build_nt (CONSTRUCTOR, NULL_TREE,
+ tree_cons (NULL_TREE, delta,
+ tree_cons (NULL_TREE, idx,
+ tree_cons (NULL_TREE, u, NULL_TREE))));
+
+ return digest_init (type, u, (tree*)0);
+#else
+ tree delta_field, idx_field, pfn_or_delta2_field, pfn_field, delta2_field;
+ tree subtype;
+ int allconstant, allsimple;
+
+ delta_field = TYPE_FIELDS (type);
+ idx_field = TREE_CHAIN (delta_field);
+ pfn_or_delta2_field = TREE_CHAIN (idx_field);
+ subtype = TREE_TYPE (pfn_or_delta2_field);
+ pfn_field = TYPE_FIELDS (subtype);
+ delta2_field = TREE_CHAIN (pfn_field);
+
+ if (pfn)
+ {
+ allconstant = TREE_CONSTANT (pfn);
+ allsimple = initializer_constant_valid_p (pfn, TREE_TYPE (pfn));
+ u = tree_cons (pfn_field, pfn, NULL_TREE);
+ }
+ else
+ {
+ delta2 = convert_and_check (delta_type_node, delta2);
+ allconstant = TREE_CONSTANT (delta2);
+ allsimple = initializer_constant_valid_p (delta2, TREE_TYPE (delta2));
+ u = tree_cons (delta2_field, delta2, NULL_TREE);
+ }
+
+ delta = convert_and_check (delta_type_node, delta);
+ idx = convert_and_check (delta_type_node, idx);
+
+ allconstant = allconstant && TREE_CONSTANT (delta) && TREE_CONSTANT (idx);
+ allsimple = allsimple
+ && initializer_constant_valid_p (delta, TREE_TYPE (delta))
+ && initializer_constant_valid_p (idx, TREE_TYPE (idx));
+
+ u = build (CONSTRUCTOR, subtype, NULL_TREE, u);
+ u = tree_cons (delta_field, delta,
+ tree_cons (idx_field, idx,
+ tree_cons (pfn_or_delta2_field, u, NULL_TREE)));
+ u = build (CONSTRUCTOR, type, NULL_TREE, u);
+ TREE_CONSTANT (u) = allconstant;
+ TREE_STATIC (u) = allconstant && allsimple;
+ return u;
+#endif
+}
+
/* Build a constructor for a pointer to member function. It can be
used to initialize global variables, local variable, or used
as a value in expressions. TYPE is the POINTER to METHOD_TYPE we
tree delta = integer_zero_node;
tree delta2 = integer_zero_node;
tree vfield_offset;
- tree npfn;
+ tree npfn = NULL_TREE;
tree u;
/* Handle multiple conversions of pointer to member functions. */
if (TYPE_PTRMEMFUNC_P (TREE_TYPE (pfn)))
{
tree ndelta, ndelta2, nindex;
+ tree e1, e2, e3, n;
+
/* Is is already the right type? */
if (type == TYPE_PTRMEMFUNC_FN_TYPE (TREE_TYPE (pfn)))
return pfn;
- if (TREE_CODE (pfn) != CONSTRUCTOR)
- {
- tree e1, e2, e3;
- ndelta = convert (ptrdiff_type_node, build_component_ref (pfn, delta_identifier, NULL_TREE, 0));
- ndelta2 = convert (ptrdiff_type_node, DELTA2_FROM_PTRMEMFUNC (pfn));
- idx = build_component_ref (pfn, index_identifier, NULL_TREE, 0);
- delta = get_delta_difference (TYPE_METHOD_BASETYPE (TREE_TYPE (TYPE_PTRMEMFUNC_FN_TYPE (TREE_TYPE (pfn)))),
- TYPE_METHOD_BASETYPE (TREE_TYPE (type)),
- force);
- delta = build_binary_op (PLUS_EXPR, delta, ndelta, 1);
- delta2 = build_binary_op (PLUS_EXPR, ndelta2, delta2, 1);
- e1 = fold (build (GT_EXPR, boolean_type_node, idx, integer_zero_node));
+ ndelta = convert (ptrdiff_type_node, build_component_ref (pfn, delta_identifier, NULL_TREE, 0));
+ ndelta2 = convert (ptrdiff_type_node, DELTA2_FROM_PTRMEMFUNC (pfn));
+ idx = build_component_ref (pfn, index_identifier, NULL_TREE, 0);
+
+ n = get_delta_difference (TYPE_METHOD_BASETYPE (TREE_TYPE (TYPE_PTRMEMFUNC_FN_TYPE (TREE_TYPE (pfn)))),
+ TYPE_METHOD_BASETYPE (TREE_TYPE (type)),
+ force);
+
+ delta = build_binary_op (PLUS_EXPR, ndelta, n, 1);
+ delta2 = build_binary_op (PLUS_EXPR, ndelta2, n, 1);
+ e1 = fold (build (GT_EXPR, boolean_type_node, idx, integer_zero_node));
- u = build_nt (CONSTRUCTOR, NULL_TREE, tree_cons (delta2_identifier, delta2, NULL_TREE));
- u = build_nt (CONSTRUCTOR, NULL_TREE, tree_cons (NULL_TREE, delta,
- tree_cons (NULL_TREE, idx,
- tree_cons (NULL_TREE, u, NULL_TREE))));
- e2 = digest_init (TYPE_GET_PTRMEMFUNC_TYPE (type), u, (tree*)0);
+ e2 = build_ptrmemfunc1 (TYPE_GET_PTRMEMFUNC_TYPE (type), delta, idx,
+ NULL_TREE, delta2);
- pfn = PFN_FROM_PTRMEMFUNC (pfn);
- npfn = build1 (NOP_EXPR, type, pfn);
- TREE_CONSTANT (npfn) = TREE_CONSTANT (pfn);
+ pfn = PFN_FROM_PTRMEMFUNC (pfn);
+ npfn = build1 (NOP_EXPR, type, pfn);
+ TREE_CONSTANT (npfn) = TREE_CONSTANT (pfn);
- u = build_nt (CONSTRUCTOR, NULL_TREE, tree_cons (pfn_identifier, npfn, NULL_TREE));
- u = build_nt (CONSTRUCTOR, NULL_TREE, tree_cons (NULL_TREE, delta,
- tree_cons (NULL_TREE, idx,
- tree_cons (NULL_TREE, u, NULL_TREE))));
- e3 = digest_init (TYPE_GET_PTRMEMFUNC_TYPE (type), u, (tree*)0);
- return build_conditional_expr (e1, e2, e3);
- }
-
- ndelta = TREE_VALUE (CONSTRUCTOR_ELTS (pfn));
- nindex = TREE_VALUE (TREE_CHAIN (CONSTRUCTOR_ELTS (pfn)));
- npfn = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (CONSTRUCTOR_ELTS (pfn))));
- npfn = TREE_VALUE (CONSTRUCTOR_ELTS (npfn));
- if (integer_zerop (nindex))
- pfn = integer_zero_node;
- else if (integer_zerop (fold (size_binop (PLUS_EXPR, nindex, integer_one_node))))
- {
- tree e3;
- delta = get_delta_difference (TYPE_METHOD_BASETYPE (TREE_TYPE (TYPE_PTRMEMFUNC_FN_TYPE (TREE_TYPE (pfn)))),
- TYPE_METHOD_BASETYPE (TREE_TYPE (type)),
- force);
- delta = build_binary_op (PLUS_EXPR, delta, ndelta, 1);
- pfn = build1 (NOP_EXPR, type, npfn);
- TREE_CONSTANT (pfn) = TREE_CONSTANT (npfn);
-
- u = build_nt (CONSTRUCTOR, NULL_TREE, tree_cons (pfn_identifier, pfn, NULL_TREE));
- u = build_nt (CONSTRUCTOR, NULL_TREE, tree_cons (NULL_TREE, delta,
- tree_cons (NULL_TREE, nindex,
- tree_cons (NULL_TREE, u, NULL_TREE))));
- e3 = digest_init (TYPE_GET_PTRMEMFUNC_TYPE (type), u, (tree*)0);
- return e3;
- }
- else
- {
- sorry ("value casting of variable nonnull pointer to member functions not supported");
- return error_mark_node;
- }
+ e3 = build_ptrmemfunc1 (TYPE_GET_PTRMEMFUNC_TYPE (type), delta, idx, npfn,
+ NULL_TREE);
+ return build_conditional_expr (e1, e2, e3);
}
/* Handle null pointer to member function conversions. */
if (integer_zerop (pfn))
{
pfn = build_c_cast (type, integer_zero_node, 0);
- u = build_nt (CONSTRUCTOR, NULL_TREE, tree_cons (pfn_identifier, pfn, NULL_TREE));
- u = build_nt (CONSTRUCTOR, NULL_TREE, tree_cons (NULL_TREE, integer_zero_node,
- tree_cons (NULL_TREE, integer_zero_node,
- tree_cons (NULL_TREE, u, NULL_TREE))));
- return digest_init (TYPE_GET_PTRMEMFUNC_TYPE (type), u, (tree*)0);
+ return build_ptrmemfunc1 (TYPE_GET_PTRMEMFUNC_TYPE (type),
+ integer_zero_node, integer_zero_node,
+ pfn, NULL_TREE);
}
if (TREE_CODE (pfn) == TREE_LIST
|| (TREE_CODE (pfn) == ADDR_EXPR
&& TREE_CODE (TREE_OPERAND (pfn, 0)) == TREE_LIST))
- {
- pfn = instantiate_type (type, pfn, 1);
- if (pfn == error_mark_node)
- return error_mark_node;
- pfn = build_addr_func (pfn);
- }
+ return instantiate_type (type, pfn, 1);
/* Allow pointer to member conversions here. */
delta = get_delta_difference (TYPE_METHOD_BASETYPE (TREE_TYPE (TREE_TYPE (pfn))),
idx = size_binop (PLUS_EXPR,
DECL_VINDEX (TREE_OPERAND (pfn, 0)),
integer_one_node);
- u = build_nt (CONSTRUCTOR, NULL_TREE, tree_cons (delta2_identifier, delta2, NULL_TREE));
}
else
{
npfn = build1 (NOP_EXPR, type, pfn);
TREE_CONSTANT (npfn) = TREE_CONSTANT (pfn);
}
-
- u = build_nt (CONSTRUCTOR, NULL_TREE, tree_cons (pfn_identifier, npfn, NULL_TREE));
}
- u = build_nt (CONSTRUCTOR, NULL_TREE, tree_cons (NULL_TREE, delta,
- tree_cons (NULL_TREE, idx,
- tree_cons (NULL_TREE, u, NULL_TREE))));
- return digest_init (TYPE_GET_PTRMEMFUNC_TYPE (type), u, (tree*)0);
+ return build_ptrmemfunc1 (TYPE_GET_PTRMEMFUNC_TYPE (type), delta, idx, npfn, delta2);
}
/* Convert value RHS to type TYPE as preparation for an assignment
return error_mark_node;
}
- if (ctt < 0)
+ if (ctt < 0 && TYPE_MAIN_VARIANT (ttl) != TYPE_MAIN_VARIANT (ttr))
cp_pedwarn ("converting `%T' to `%T' is a contravariance violation",
rhstype, type);
if (TYPE_MAIN_VARIANT (ttl) != void_type_node
&& TYPE_MAIN_VARIANT (ttr) == void_type_node
- && rhs != null_pointer_node)
+ && ! null_ptr_cst_p (rhs))
{
if (coder == RECORD_TYPE)
cp_pedwarn ("implicit conversion of signature pointer to type `%T'",
}
}
}
- else if (TREE_CODE (ttr) == OFFSET_TYPE
- && TREE_CODE (ttl) != OFFSET_TYPE)
- {
- /* Normally, pointers to different type codes (other
- than void) are not compatible, but we perform
- some type instantiation if that resolves the
- ambiguity of (X Y::*) and (X *). */
-
- if (current_class_ptr)
- {
- if (TREE_CODE (rhs) == INTEGER_CST)
- {
- rhs = build (PLUS_EXPR, build_pointer_type (TREE_TYPE (ttr)),
- current_class_ptr, rhs);
- return convert_for_assignment (type, rhs,
- errtype, fndecl, parmnum);
- }
- }
- if (TREE_CODE (ttl) == METHOD_TYPE)
- error ("%s between pointer-to-method and pointer-to-member types",
- errtype);
- else
- error ("%s between pointer and pointer-to-member types", errtype);
- return error_mark_node;
- }
else
{
int add_quals = 0, const_parity = 0, volatile_parity = 0;
else
cp_pedwarn ("%s to `%T' from `%T' lacks a cast",
errtype, type, rhstype);
- return convert (type, rhs);
}
- return null_pointer_node;
+ return convert (type, rhs);
}
else if (codel == INTEGER_TYPE
&& (coder == POINTER_TYPE
if (TREE_CODE (rhstype) == REFERENCE_TYPE)
rhstype = TREE_TYPE (rhstype);
+ type = complete_type (type);
+
if (TYPE_LANG_SPECIFIC (type)
&& (IS_SIGNATURE_POINTER (type) || IS_SIGNATURE_REFERENCE (type)))
return build_signature_pointer_constructor (type, rhs);
return;
}
- if (current_template_parms)
+ if (processing_template_decl)
{
add_tree (build_min_nt (RETURN_STMT, retval));
return;
if (TREE_CODE (to) != TREE_CODE (from))
return 0;
+ if (TREE_CODE (from) == OFFSET_TYPE
+ && comptypes (TYPE_OFFSET_BASETYPE (from),
+ TYPE_OFFSET_BASETYPE (to), 1))
+ continue;
+
/* Const and volatile mean something different for function types,
so the usual checks are not appropriate. */
if (TREE_CODE (to) != FUNCTION_TYPE && TREE_CODE (to) != METHOD_TYPE)
{
return comp_ptr_ttypes_real (to, from, 1);
}
+
+/* Returns 1 if to and from are (possibly multi-level) pointers to the same
+ type or inheritance-related types, regardless of cv-quals. */
+
+int
+ptr_reasonably_similar (to, from)
+ tree to, from;
+{
+ for (; ; to = TREE_TYPE (to), from = TREE_TYPE (from))
+ {
+ if (TREE_CODE (to) != TREE_CODE (from))
+ return 0;
+
+ if (TREE_CODE (from) == OFFSET_TYPE
+ && comptypes (TYPE_OFFSET_BASETYPE (to),
+ TYPE_OFFSET_BASETYPE (from), -1))
+ continue;
+
+ if (TREE_CODE (to) != POINTER_TYPE)
+ return comptypes
+ (TYPE_MAIN_VARIANT (to), TYPE_MAIN_VARIANT (from), -1);
+ }
+}
+
+/* Like comp_ptr_ttypes, for const_cast. */
+
+int
+comp_ptr_ttypes_const (to, from)
+ tree to, from;
+{
+ for (; ; to = TREE_TYPE (to), from = TREE_TYPE (from))
+ {
+ if (TREE_CODE (to) != TREE_CODE (from))
+ return 0;
+
+ if (TREE_CODE (from) == OFFSET_TYPE
+ && comptypes (TYPE_OFFSET_BASETYPE (from),
+ TYPE_OFFSET_BASETYPE (to), 1))
+ continue;
+
+ if (TREE_CODE (to) != POINTER_TYPE)
+ return comptypes (TYPE_MAIN_VARIANT (to), TYPE_MAIN_VARIANT (from), 1);
+ }
+}
+
+/* Like comp_ptr_ttypes, for reinterpret_cast. */
+
+int
+comp_ptr_ttypes_reinterpret (to, from)
+ tree to, 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);
+
+ if (TREE_CODE (to) != TREE_CODE (from))
+ return 1;
+
+ /* Const and volatile mean something different for function types,
+ so the usual checks are not appropriate. */
+ if (TREE_CODE (to) != FUNCTION_TYPE && TREE_CODE (to) != METHOD_TYPE)
+ {
+ if (TYPE_READONLY (from) > TYPE_READONLY (to)
+ || TYPE_VOLATILE (from) > TYPE_VOLATILE (to))
+ return 0;
+
+ if (! constp
+ && (TYPE_READONLY (to) > TYPE_READONLY (from)
+ || TYPE_VOLATILE (to) > TYPE_READONLY (from)))
+ return 0;
+ constp &= TYPE_READONLY (to);
+ }
+
+ if (TREE_CODE (to) != POINTER_TYPE)
+ return 1;
+ }
+}