static tree convert_for_assignment PROTO((tree, tree, char*, tree, int));
/* static */ tree convert_for_initialization PROTO((tree, tree, tree, int, char*, tree, int));
extern tree shorten_compare ();
-extern void binary_op_error ();
static tree pointer_int_sum PROTO((enum tree_code, register tree, register tree));
static tree pointer_diff PROTO((register tree, register tree));
+static int comp_target_parms PROTO((tree, tree, int));
+static int comp_ptr_ttypes_const PROTO((tree, tree));
+static int comp_ptr_ttypes_reinterpret PROTO((tree, tree));
#if 0
static tree convert_sequence ();
#endif
/* static */ tree unary_complex_lvalue PROTO((enum tree_code, tree));
static tree get_delta_difference PROTO((tree, tree, int));
-extern rtx original_result_rtx;
-extern int warn_synth;
-
/* Return the target type of TYPE, which meas return T for:
T*, T&, T[], T (...), and otherwise, just T. */
{
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;
}
}
If there is not a unique most-derived base type, this function
returns ERROR_MARK_NODE. */
-tree
+static tree
common_base_type (tt1, tt2)
tree tt1, tt2;
{
/* This really wants return whether or not parameter type lists
would make their owning functions assignment compatible or not. */
-int
+static int
comp_target_parms (parms1, parms2, strict)
tree parms1, parms2;
int strict;
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)
inner = build1 (CONVERT_EXPR,
build_pointer_type (TREE_TYPE (TREE_TYPE (inner))),
inner);
- TREE_REFERENCE_EXPR (inner) = 1;
+ TREE_CONSTANT (inner) = TREE_CONSTANT (TREE_OPERAND (inner, 0));
}
return convert (build_pointer_type (TREE_TYPE (type)), inner);
}
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;
}
else
{
+ tree name = component;
+ if (TREE_CODE (component) == VAR_DECL)
+ name = DECL_NAME (component);
if (basetype_path == NULL_TREE)
basetype_path = TYPE_BINFO (basetype);
- field = lookup_field (basetype_path, component,
- protect && ! VFIELD_NAME_P (component), 0);
+ field = lookup_field (basetype_path, name,
+ protect && !VFIELD_NAME_P (name), 0);
if (field == error_mark_node)
return error_mark_node;
/* Not found as a data field, look for it as a method. If found,
then if this is the only possible one, return it, else
report ambiguity error. */
- tree fndecls = lookup_fnfields (basetype_path, component, 1);
+ tree fndecls = lookup_fnfields (basetype_path, name, 1);
if (fndecls == error_mark_node)
return error_mark_node;
if (fndecls)
&& ! resolves_to_fixed_type_p (datum, 0))
{
tree addr = build_unary_op (ADDR_EXPR, datum, 0);
+ tree fntype = TREE_TYPE (fndecl);
+
addr = convert_pointer_to (DECL_CONTEXT (fndecl), addr);
datum = build_indirect_ref (addr, NULL_PTR);
my_friendly_assert (datum != error_mark_node, 310);
fndecl = build_vfn_ref (&addr, datum, DECL_VINDEX (fndecl));
+ TREE_TYPE (fndecl) = build_pointer_type (fntype);
}
mark_used (fndecl);
return build (OFFSET_REF, TREE_TYPE (fndecl), datum, fndecl);
}
}
- cp_error ("`%#T' has no member named `%D'", basetype, component);
+ cp_error ("`%#T' has no member named `%D'", basetype, name);
return error_mark_node;
}
else if (TREE_TYPE (field) == error_mark_node)
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;
will inherit the type of the array, which will be some pointer type. */
tree
-build_x_array_ref (array, idx)
- tree array, idx;
-{
- tree rval = build_opfncall (ARRAY_REF, LOOKUP_NORMAL, array, idx, NULL_TREE);
- if (rval)
- return rval;
- return build_array_ref (array, idx);
-}
-
-tree
build_array_ref (array, idx)
tree array, idx;
{
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)
}
else
{
-#ifdef NEW_OVER
- return build_new_function_call (function, params, NULL_TREE);
-#else
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);
(function, params, LOOKUP_COMPLAIN);
else
my_friendly_abort (360);
-#endif
}
}
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);
}
decl = convert_pointer_to (TREE_TYPE (ctypeptr), decl);
}
else
- decl = build_c_cast (ctypeptr, decl, 0);
+ decl = build_c_cast (ctypeptr, decl);
params = tree_cons (NULL_TREE, decl, params);
}
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);
}
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);
}
}
if (! flag_elide_constructors)
return_loc = 0;
+ /* Argument passing is always copy-initialization. */
+ flags |= LOOKUP_ONLYCONVERTING;
+
if (fndecl)
{
if (TREE_CODE (TREE_TYPE (fndecl)) == METHOD_TYPE)
}
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)
+ 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));
argtype = TREE_TYPE (arg);
if (TREE_CODE (argtype) == REFERENCE_TYPE)
{
- arg = build1 (CONVERT_EXPR, build_pointer_type (TREE_TYPE (TREE_TYPE (arg))), arg);
- TREE_REFERENCE_EXPR (arg) = 1;
+ arg = build1
+ (CONVERT_EXPR,
+ build_pointer_type (TREE_TYPE (TREE_TYPE (arg))), arg);
+ TREE_CONSTANT (arg) = TREE_CONSTANT (TREE_OPERAND (arg, 0));
return arg;
}
else if (pedantic
if (arg == current_class_ref)
return current_class_ptr;
- /* Keep `default_conversion' from converting if
- ARG is of REFERENCE_TYPE. */
arg = TREE_OPERAND (arg, 0);
if (TREE_CODE (TREE_TYPE (arg)) == REFERENCE_TYPE)
{
- if (TREE_CODE (arg) == VAR_DECL && DECL_INITIAL (arg)
- && !TREE_SIDE_EFFECTS (DECL_INITIAL (arg)))
- arg = DECL_INITIAL (arg);
- arg = build1 (CONVERT_EXPR, build_pointer_type (TREE_TYPE (TREE_TYPE (arg))), arg);
- TREE_REFERENCE_EXPR (arg) = 1;
+ arg = build1
+ (CONVERT_EXPR,
+ build_pointer_type (TREE_TYPE (TREE_TYPE (arg))), arg);
TREE_CONSTANT (arg) = TREE_CONSTANT (TREE_OPERAND (arg, 0));
}
else if (lvalue_p (arg))
|| TREE_CODE (arg) == INIT_EXPR)
{
tree real_result = build_unary_op (code, TREE_OPERAND (arg, 0), 0);
- return build (COMPOUND_EXPR, TREE_TYPE (real_result), arg, real_result);
+ arg = build (COMPOUND_EXPR, TREE_TYPE (real_result), arg, real_result);
+ TREE_NO_UNUSED_WARNING (arg) = 1;
+ return arg;
}
if (TREE_CODE (TREE_TYPE (arg)) == FUNCTION_TYPE
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)
+ 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);
register enum tree_code code1;
register enum tree_code code2;
register tree result_type = NULL_TREE;
- tree orig_op1 = op1, orig_op2 = op2;
/* If second operand is omitted, it is the same as the first one;
make sure it is calculated only once. */
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);
+
+ 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_PTRMEMFUNC_P (intype))
- intype = TYPE_PTRMEMFUNC_FN_TYPE (intype);
+ if (type_unknown_p (expr))
+ {
+ expr = instantiate_type (type, expr, 1);
+ if (expr == error_mark_node)
+ return error_mark_node;
+ }
- if (! POINTER_TYPE_P (type) && ! TREE_CODE (type) == INTEGER_TYPE)
+ intype = TREE_TYPE (expr);
+
+ 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)))
{
- cp_error ("reinterpret_cast cannot convert `%T' to non-pointer type `%T'",
- intype, type);
+ 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 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.
when doing the cast. */
tree
-build_c_cast (type, expr, allow_nonconverting)
- register tree type;
- tree expr;
- int allow_nonconverting;
+build_c_cast (type, expr)
+ tree type, expr;
{
register tree value = 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));
else
{
tree otype;
- int flag;
/* Convert functions and arrays to pointers and
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);
warning ("cast to pointer from integer of different size");
#endif
- flag = allow_nonconverting ? CONV_NONCONVERTING : 0;
-
if (TREE_CODE (type) == REFERENCE_TYPE)
value = (convert_from_reference
- (convert_to_reference (type, value, CONV_OLD_CONVERT|flag,
+ (convert_to_reference (type, value, CONV_C_CAST,
LOOKUP_COMPLAIN, NULL_TREE)));
else
{
value = decl_constant_value (value);
ovalue = value;
- value = convert_force (type, value, flag);
+ value = convert_force (type, value, CONV_C_CAST);
/* Ignore any integer overflow caused by the cast. */
if (TREE_CODE (value) == INTEGER_CST)
}
/* 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;
tree olhs = lhs;
/* Avoid duplicate error messages from operands that had errors. */
- if (TREE_CODE (lhs) == ERROR_MARK || TREE_CODE (rhs) == ERROR_MARK)
+ if (lhs == error_mark_node || rhs == error_mark_node)
return error_mark_node;
/* Types that aren't fully specified cannot be used in assignments. */
case COMPOUND_EXPR:
newrhs = build_modify_expr (TREE_OPERAND (lhs, 1),
modifycode, rhs);
- if (TREE_CODE (newrhs) == ERROR_MARK)
+ if (newrhs == error_mark_node)
return error_mark_node;
return build (COMPOUND_EXPR, lhstype,
TREE_OPERAND (lhs, 0), newrhs);
case MODIFY_EXPR:
newrhs = build_modify_expr (TREE_OPERAND (lhs, 0), modifycode, rhs);
- if (TREE_CODE (newrhs) == ERROR_MARK)
+ if (newrhs == error_mark_node)
return error_mark_node;
return build (COMPOUND_EXPR, lhstype, lhs, newrhs);
modifycode, rhs),
build_modify_expr (convert (TREE_TYPE (lhs), TREE_OPERAND (lhs, 2)),
modifycode, rhs));
- if (TREE_CODE (cond) == ERROR_MARK)
+ if (cond == error_mark_node)
return cond;
/* Make sure the code to compute the rhs comes out
before the split. */
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 */;
}
{
tree inner_lhs = TREE_OPERAND (lhs, 0);
tree result;
- if (! lvalue_p (lhs) && pedantic)
- pedwarn ("cast to non-reference type used as lvalue");
+
+ /* WP 5.4.1: The result is an lvalue if T is a reference type,
+ otherwise the result is an rvalue. */
+ if (! lvalue_p (lhs))
+ pedwarn ("ANSI C++ forbids cast to non-reference type used as lvalue");
result = build_modify_expr (inner_lhs, NOP_EXPR,
convert (TREE_TYPE (inner_lhs),
convert (lhstype, newrhs)));
- if (TREE_CODE (result) == ERROR_MARK)
+ if (result == error_mark_node)
return result;
return convert (TREE_TYPE (lhs), result);
}
TREE_OPERAND (newrhs, 0));
}
- if (TREE_CODE (newrhs) == ERROR_MARK)
+ if (newrhs == error_mark_node)
return error_mark_node;
if (TREE_CODE (newrhs) == COND_EXPR)
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))
tree delta2 = integer_zero_node;
tree vfield_offset;
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 ndelta, ndelta2;
tree e1, e2, e3, n;
/* Is is already the right type? */
/* Handle null pointer to member function conversions. */
if (integer_zerop (pfn))
{
- pfn = build_c_cast (type, integer_zero_node, 0);
+ pfn = build_c_cast (type, integer_zero_node);
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))),
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
}
else if (TYPE_HAS_CONSTRUCTOR (type) || IS_AGGR_TYPE (TREE_TYPE (rhs)))
return convert (type, rhs);
+ /* Handle anachronistic conversions from (::*)() to cv void* or (*)(). */
+ else if (TREE_CODE (type) == POINTER_TYPE
+ && (TREE_CODE (TREE_TYPE (type)) == FUNCTION_TYPE
+ || TYPE_MAIN_VARIANT (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;
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);
if (IS_AGGR_TYPE (type)
&& (TYPE_NEEDS_CONSTRUCTING (type) || TREE_HAS_CONSTRUCTOR (rhs)))
{
+ if (flag_ansi_overloading)
+ return cp_convert (type, rhs, CONV_IMPLICIT|CONV_FORCE_TEMP, flags);
+
if (TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (rhstype))
{
/* This is sufficient to perform initialization. No need,
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;
}
+ /* Effective C++ rule 15. See also start_function. */
+ if (warn_ecpp
+ && DECL_NAME (current_function_decl) == ansi_opname[(int) MODIFY_EXPR]
+ && retval != current_class_ref)
+ cp_warning ("`operator=' should return a reference to `*this'");
+
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 && ! DECL_ARTIFICIAL (current_function_decl))
+ || 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)
/* convert to reference now, so we can give error if we
return an reference to a non-lvalue. */
- retval = convert_for_initialization (tmp_result, valtype, retval,
- LOOKUP_NORMAL, "return",
- NULL_TREE, 0);
+ retval = convert_for_initialization
+ (tmp_result, valtype, retval, LOOKUP_NORMAL|LOOKUP_ONLYCONVERTING,
+ "return", NULL_TREE, 0);
/* Sort through common things to see what it is
we are returning. */
if (TREE_CODE (whats_returned) == ADDR_EXPR)
whats_returned = TREE_OPERAND (whats_returned, 0);
}
+ if (TREE_CODE (whats_returned) == CONVERT_EXPR)
+ whats_returned = TREE_OPERAND (whats_returned, 0);
if (TREE_CODE (whats_returned) == ADDR_EXPR)
{
whats_returned = TREE_OPERAND (whats_returned, 0);
(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|LOOKUP_ONLYCONVERTING,
+ "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, 1)) == 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.
/* CONSTP remembers whether or not all the intervening pointers in the `to'
type have been const. */
-int
+static int
comp_ptr_ttypes_real (to, from, constp)
tree to, from;
int constp;
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. */
+
+static 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. */
+
+static 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;
+ }
+}