{
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
- && current_template_parms == NULL_TREE)
+ if (TYPE_SIZE (t) != NULL_TREE && ! processing_template_decl)
layout_type (type);
TYPE_NEEDS_CONSTRUCTING (type)
= TYPE_NEEDS_CONSTRUCTING (TYPE_MAIN_VARIANT (t));
return unsigned_intHI_type_node;
if (type1 == intQI_type_node)
return unsigned_intQI_type_node;
- return type;
+
+ return signed_or_unsigned_type (1, type);
}
/* Return a signed type the same as TYPE in other respects. */
return intHI_type_node;
if (type1 == unsigned_intQI_type_node)
return intQI_type_node;
- return type;
+
+ return signed_or_unsigned_type (0, type);
}
/* Return a type the same as TYPE except unsigned or
int unsignedp;
tree type;
{
- if (! INTEGRAL_TYPE_P (type))
+ if (! INTEGRAL_TYPE_P (type)
+ || TREE_UNSIGNED (type) == unsignedp)
return type;
+
if (TYPE_PRECISION (type) == TYPE_PRECISION (signed_char_type_node))
return unsignedp ? unsigned_char_type_node : signed_char_type_node;
if (TYPE_PRECISION (type) == TYPE_PRECISION (integer_type_node))
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
type = TREE_TYPE (type);
code = TREE_CODE (type);
+
+ if (type == unknown_type_node)
+ {
+ cp_pedwarn ("assuming & on overloaded member function");
+ return build_unary_op (ADDR_EXPR, exp, 0);
+ }
}
if (code == REFERENCE_TYPE)
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;
}
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;
}
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);
idx = save_expr (build_component_ref (function,
index_identifier,
NULL_TREE, 0));
- e1 = build (GT_EXPR, boolean_type_node, idx,
- convert (delta_type_node, integer_zero_node));
+ e1 = fold (build (GT_EXPR, boolean_type_node, idx,
+ convert (delta_type_node, integer_zero_node)));
delta = convert (ptrdiff_type_node,
build_component_ref (function, delta_identifier, NULL_TREE, 0));
delta2 = DELTA2_FROM_PTRMEMFUNC (function);
instance
= convert_pointer_to_real (TYPE_METHOD_BASETYPE (TREE_TYPE (fntype)),
instance_ptr);
- if (instance == error_mark_node)
+ if (instance == error_mark_node && instance_ptr != error_mark_node)
return instance;
vtbl = convert_pointer_to (ptr_type_node, instance);
e3 = PFN_FROM_PTRMEMFUNC (function);
TREE_TYPE (e2) = TREE_TYPE (e3);
- function = build_conditional_expr (e1, e2, e3);
+ e1 = build_conditional_expr (e1, e2, e3);
+
+ if (instance_ptr == error_mark_node
+ && TREE_CODE (e1) != ADDR_EXPR
+ && TREE_CODE (TREE_OPERAND (e1, 0)) != FUNCTION_DECL)
+ cp_error ("object missing in `%E'", function);
+
+ function = e1;
/* Make sure this doesn't get evaluated first inside one of the
branches of the COND_EXPR. */
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);
}
}
else
{
- parmval = convert_for_initialization (return_loc, type, val,
- flags|INDIRECT_BIND,
- "argument passing", fndecl, i);
+ parmval = convert_for_initialization
+ (return_loc, type, val, flags,
+ "argument passing", fndecl, i);
#ifdef PROMOTE_PROTOTYPES
if ((TREE_CODE (type) == INTEGER_TYPE
|| TREE_CODE (type) == ENUMERAL_TYPE)
{
tree rval;
- if (current_template_parms)
+ if (processing_template_decl)
return build_min_nt (code, arg1, arg2);
if (flag_ansi_overloading)
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
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,
case PARM_DECL:
if (x == current_class_ptr)
{
- error ("address of `this' not available");
+ if (! flag_this_is_variable)
+ error ("address of `this' not available");
TREE_ADDRESSABLE (x) = 1; /* so compiler doesn't die later */
put_var_into_stack (x);
return 1;
case CONST_DECL:
case RESULT_DECL:
- /* For C++, we don't warn about taking the address of a register
- variable for CONST_DECLs; ARM p97 explicitly says it's okay. */
+ if (DECL_REGISTER (x) && !TREE_ADDRESSABLE (x)
+ && !DECL_ARTIFICIAL (x) && extra_warnings)
+ cp_warning ("address requested for `%D', which is declared `register'",
+ x);
put_var_into_stack (x);
TREE_ADDRESSABLE (x) = 1;
return 1;
TREE_ADDRESSABLE (x) = 1;
return 1;
+ case TARGET_EXPR:
+ TREE_ADDRESSABLE (x) = 1;
+ mark_addressable (TREE_OPERAND (x, 0));
+ return 1;
+
default:
return 1;
}
{
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)
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 (type == error_mark_node || expr == error_mark_node)
+ return error_mark_node;
+
+ if (TREE_CODE (expr) == OFFSET_REF)
+ expr = resolve_offset_ref (expr);
- if (current_template_parms)
+ 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);
+
+ /* 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 (type))
- type = TYPE_PTRMEMFUNC_FN_TYPE (type);
+ intype = TREE_TYPE (expr);
- if (TYPE_PTRMEMFUNC_P (intype))
- intype = TYPE_PTRMEMFUNC_FN_TYPE (intype);
+ if (TREE_CODE (type) == REFERENCE_TYPE)
+ {
+ 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;
+ }
+ else if (comptypes (TYPE_MAIN_VARIANT (intype), TYPE_MAIN_VARIANT (type), 1))
+ return build_static_cast (type, expr);
- if (! POINTER_TYPE_P (type) && ! TREE_CODE (type) == INTEGER_TYPE)
+ 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 to 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 (! POINTER_TYPE_P (intype) && ! TREE_CODE (intype) == INTEGER_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 from type `%T'", 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 (type) == INTEGER_TYPE && TREE_CODE (intype) != POINTER_TYPE)
+ else if ((TYPE_PTRMEM_P (type) && TYPE_PTRMEM_P (intype))
+ || (TYPE_PTROBV_P (type) && TYPE_PTROBV_P (intype)))
{
- cp_error ("reinterpret_cast cannot convert non-pointer type `%T' to `%T'",
- intype, type);
- return error_mark_node;
+ 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));
}
- if (TREE_CODE (intype) == INTEGER_TYPE && TREE_CODE (type) != POINTER_TYPE)
+ 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))
- {
- 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)
+ if (TREE_CODE (type) != REFERENCE_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));
convert references to their expanded types,
but don't convert any other types. */
if (TREE_CODE (TREE_TYPE (value)) == FUNCTION_TYPE
- || TREE_CODE (TREE_TYPE (value)) == METHOD_TYPE
+ || (TREE_CODE (TREE_TYPE (value)) == METHOD_TYPE
+ /* Don't do the default conversion if we want a
+ pointer to a function. */
+ && TREE_CODE (type) != POINTER_TYPE
+ && TREE_CODE (TREE_TYPE (type)) != FUNCTION_TYPE)
|| TREE_CODE (TREE_TYPE (value)) == ARRAY_TYPE
|| TREE_CODE (TREE_TYPE (value)) == REFERENCE_TYPE)
value = default_conversion (value);
}
/* 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;
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);
binfo = get_binfo (from, to, 1);
if (binfo == error_mark_node)
{
- error (" in pointer to member function conversion");
+ error (" in pointer to member function conversiona");
return delta;
}
if (binfo == 0)
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");
+ if (!force)
+ error (" in pointer to member conversion");
return delta;
}
if (binfo == 0)
{
- cp_error ("cannot convert pointer to member of type %T to unrelated pointer to member of type %T", from, to);
+ if (!force)
+ cp_error ("cannot convert pointer to member of type %T to unrelated pointer to member of type %T", from, to);
return delta;
}
if (TREE_VIA_VIRTUAL (binfo))
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);
}
}
}
- 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 if (TYPE_HAS_CONSTRUCTOR (type) || IS_AGGR_TYPE (TREE_TYPE (rhs)))
return convert (type, rhs);
+ /* Handle anachronistic conversions from (::*)() to void* or (*)(). */
+ else if (TREE_CODE (type) == POINTER_TYPE
+ && (TREE_CODE (TREE_TYPE (type)) == FUNCTION_TYPE
+ || TREE_TYPE (type) == void_type_node)
+ && TREE_TYPE (rhs)
+ && TYPE_PTRMEMFUNC_P (TREE_TYPE (rhs)))
+ return convert (type, rhs);
cp_error ("%s to `%T' from `%T'", errtype, type, rhstype);
return error_mark_node;
extern tree dtor_label, ctor_label;
tree result = DECL_RESULT (current_function_decl);
tree valtype = TREE_TYPE (result);
- int returns_value = 1;
if (TREE_THIS_VOLATILE (current_function_decl))
warning ("function declared `noreturn' has a `return' statement");
return;
}
- if (current_template_parms)
+ if (processing_template_decl)
{
add_tree (build_min_nt (RETURN_STMT, retval));
return;
else if (DECL_CONSTRUCTOR_P (current_function_decl)
&& retval != current_class_ptr)
{
- error ("return from a constructor: use `this = ...' instead");
+ if (flag_this_is_variable)
+ error ("return from a constructor: use `this = ...' instead");
+ else
+ error ("return from a constructor");
retval = current_class_ptr;
}
if (valtype == NULL_TREE || TREE_CODE (valtype) == VOID_TYPE)
{
current_function_returns_null = 1;
- /* We do this here so we'll avoid a warning about how the function
- "may or may not return a value" in finish_function. */
- returns_value = 0;
-
- if (retval)
+ if (pedantic || TREE_CODE (TREE_TYPE (retval)) != VOID_TYPE)
pedwarn ("`return' with a value, in function returning void");
expand_return (retval);
+ return;
}
/* Add some useful error checking for C++. */
else if (TREE_CODE (valtype) == REFERENCE_TYPE)
(3) If an X(X&) constructor is defined, the return
value must be returned via that. */
- /* If we're returning in a register, we can't initialize the
- return value from a TARGET_EXPR. */
- if (TREE_CODE (retval) == TARGET_EXPR
- && TYPE_MAIN_VARIANT (TREE_TYPE (retval)) == TYPE_MAIN_VARIANT (valtype)
- && ! current_function_returns_struct)
- retval = expand_target_expr (retval);
-
if (retval == result
- /* Watch out for constructors, which "return" aggregates
- via initialization, but which otherwise "return" a pointer. */
|| DECL_CONSTRUCTOR_P (current_function_decl))
+ /* It's already done for us. */;
+ else if (TREE_TYPE (retval) == void_type_node)
{
- /* This is just an error--it's already been reported. */
- if (TYPE_SIZE (valtype) == NULL_TREE)
- return;
-
- if (TYPE_MODE (valtype) != BLKmode
- && any_pending_cleanups (1))
- retval = get_temp_regvar (valtype, retval);
- }
- else if (IS_AGGR_TYPE (valtype) && current_function_returns_struct)
- {
- expand_aggr_init (result, retval, 0, LOOKUP_ONLYCONVERTING);
- expand_cleanups_to (NULL_TREE);
- DECL_INITIAL (result) = NULL_TREE;
+ pedwarn ("return of void value in function returning non-void");
+ expand_expr_stmt (retval);
retval = 0;
}
else
{
- if (TYPE_MODE (valtype) == VOIDmode)
- {
- if (TYPE_MODE (TREE_TYPE (result)) != VOIDmode
- && warn_return_type)
- warning ("return of void value in function returning non-void");
- expand_expr_stmt (retval);
- retval = 0;
- result = 0;
- }
- else if (TYPE_MODE (valtype) != BLKmode
- && any_pending_cleanups (1))
- {
- retval = get_temp_regvar (valtype, retval);
- expand_cleanups_to (NULL_TREE);
- result = 0;
- }
- else
+ /* We already did this above for refs, don't do it again. */
+ if (TREE_CODE (valtype) != REFERENCE_TYPE)
+ retval = convert_for_initialization (NULL_TREE, valtype, retval,
+ LOOKUP_NORMAL,
+ "return", NULL_TREE, 0);
+
+ /* We can't initialize a register from a NEW_EXPR. */
+ if (! current_function_returns_struct
+ && TREE_CODE (retval) == TARGET_EXPR
+ && TREE_CODE (TREE_OPERAND (retval, 0)) == NEW_EXPR)
+ retval = build (COMPOUND_EXPR, TREE_TYPE (retval), retval,
+ TREE_OPERAND (retval, 0));
+
+ if (retval == error_mark_node)
{
- /* We already did this above, don't do it again. */
- if (TREE_CODE (valtype) != REFERENCE_TYPE)
- retval = convert_for_initialization (result, valtype, retval,
- LOOKUP_NORMAL,
- "return", NULL_TREE, 0);
- DECL_INITIAL (result) = NULL_TREE;
+ /* Avoid warning about control reaching end of function. */
+ expand_null_return ();
+ return;
}
- if (retval == error_mark_node)
- return;
}
- emit_queue ();
-
if (retval != NULL_TREE
&& TREE_CODE_CLASS (TREE_CODE (retval)) == 'd'
&& cond_stack == 0 && loop_stack == 0 && case_stack == 0)
current_function_return_value = retval;
- if (result)
+ if (ctor_label && TREE_CODE (ctor_label) != ERROR_MARK)
{
- /* Everything's great--RETVAL is in RESULT. */
- if (original_result_rtx)
- {
- store_expr (result, original_result_rtx, 0);
- expand_cleanups_to (NULL_TREE);
- use_variable (DECL_RTL (result));
- if (ctor_label && TREE_CODE (ctor_label) != ERROR_MARK)
- expand_goto (ctor_label);
- else
- expand_null_return ();
- }
- else if (retval && retval != result)
- {
- /* Clear this out so the later call to decl_function_context
- won't end up bombing on us. */
- if (DECL_CONTEXT (result) == error_mark_node)
- DECL_CONTEXT (result) = NULL_TREE;
- /* Here is where we finally get RETVAL into RESULT.
- `expand_return' does the magic of protecting
- RESULT from cleanups. */
- retval = fold (build1 (CLEANUP_POINT_EXPR, TREE_TYPE (result),
- retval));
- /* This part _must_ come second, because expand_return looks for
- the INIT_EXPR as the toplevel node only. :-( */
- retval = build (INIT_EXPR, TREE_TYPE (result), result, retval);
- TREE_SIDE_EFFECTS (retval) = 1;
- expand_return (retval);
- }
- else
- expand_return (result);
+ /* Here RETVAL is CURRENT_CLASS_PTR, so there's nothing to do. */
+ expand_goto (ctor_label);
}
- else
+
+ if (retval && retval != result)
{
- /* We may still need to put RETVAL into RESULT. */
- result = DECL_RESULT (current_function_decl);
- if (original_result_rtx)
- {
- /* Here we have a named return value that went
- into memory. We can compute RETVAL into that. */
- if (retval)
- expand_assignment (result, retval, 0, 0);
- else
- store_expr (result, original_result_rtx, 0);
- result = make_tree (TREE_TYPE (result), original_result_rtx);
- }
- else if (ctor_label && TREE_CODE (ctor_label) != ERROR_MARK)
- {
- /* Here RETVAL is CURRENT_CLASS_PTR, so there's nothing to do. */
- expand_goto (ctor_label);
- }
- else if (retval)
- {
- /* Here is where we finally get RETVAL into RESULT.
- `expand_return' does the magic of protecting
- RESULT from cleanups. */
- result = build (INIT_EXPR, TREE_TYPE (result), result, retval);
- TREE_SIDE_EFFECTS (result) = 1;
- expand_return (result);
- }
- else if (TYPE_MODE (TREE_TYPE (result)) != VOIDmode)
- expand_return (result);
+ result = build (INIT_EXPR, TREE_TYPE (result), result, retval);
+ TREE_SIDE_EFFECTS (result) = 1;
}
-
- current_function_returns_value = returns_value;
-
- /* One way to clear out cleanups that EXPR might
- generate. Note that this code will really be
- dead code, but that is ok--cleanups that were
- needed were handled by the magic of `return'. */
- expand_cleanups_to (NULL_TREE);
+ expand_return (result);
+ current_function_returns_value = 1;
}
\f
/* Start a C switch statement, testing expression EXP.
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;
+ }
+}