/* Build expressions with type checking for C++ compiler.
- Copyright (C) 1987, 88, 89, 92, 93, 94, 95, 1996 Free Software Foundation, Inc.
+ Copyright (C) 1987, 88, 89, 92-96, 1997 Free Software Foundation, Inc.
Hacked by Michael Tiemann (tiemann@cygnus.com)
This file is part of GNU CC.
and to process initializations in declarations (since they work
like a strange sort of assignment). */
-extern void error ();
-extern void warning ();
-
#include "config.h"
#include <stdio.h>
#include "tree.h"
#include "cp-tree.h"
#include "flags.h"
#include "output.h"
+#include "expr.h"
-int mark_addressable PROTO((tree));
-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));
-#if 0
-static tree convert_sequence ();
+#ifdef HAVE_STRING_H
+#include <string.h>
#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;
+extern void compiler_error ();
+
+static tree convert_for_assignment PROTO((tree, tree, char*, tree,
+ int));
+static tree pointer_int_sum PROTO((enum tree_code, tree, tree));
+static tree rationalize_conditional_expr PROTO((enum tree_code, tree));
+static int comp_target_parms PROTO((tree, tree, int));
+static int comp_ptr_ttypes_real PROTO((tree, tree, int));
+static int comp_ptr_ttypes_const PROTO((tree, tree));
+static int comp_ptr_ttypes_reinterpret PROTO((tree, tree));
+static int comp_array_types PROTO((int (*) (tree, tree, int), tree,
+ tree, int));
+static tree build_ptrmemfunc1 PROTO((tree, tree, tree, tree, tree));
+static tree common_base_type PROTO((tree, tree));
+static tree convert_sequence PROTO((tree, tree));
+static tree lookup_anon_field PROTO((tree, tree));
+static tree pointer_diff PROTO((tree, tree, tree));
+static tree qualify_type PROTO((tree, tree));
+static tree expand_target_expr PROTO((tree));
+static tree get_delta_difference PROTO((tree, tree, int));
/* Return the target type of TYPE, which meas return T for:
T*, T&, T[], T (...), and otherwise, just T. */
code1 = TREE_CODE (t1);
code2 = TREE_CODE (t2);
+ /* If one type is complex, form the common type of the non-complex
+ components, then make that complex. Use T1 or T2 if it is the
+ required type. */
+ if (code1 == COMPLEX_TYPE || code2 == COMPLEX_TYPE)
+ {
+ tree subtype1 = code1 == COMPLEX_TYPE ? TREE_TYPE (t1) : t1;
+ tree subtype2 = code2 == COMPLEX_TYPE ? TREE_TYPE (t2) : t2;
+ tree subtype = common_type (subtype1, subtype2);
+
+ if (code1 == COMPLEX_TYPE && TREE_TYPE (t1) == subtype)
+ return build_type_attribute_variant (t1, attributes);
+ else if (code2 == COMPLEX_TYPE && TREE_TYPE (t2) == subtype)
+ return build_type_attribute_variant (t2, attributes);
+ else
+ return build_type_attribute_variant (build_complex_type (subtype),
+ attributes);
+ }
+
switch (code1)
{
case INTEGER_TYPE:
target = tt1;
else if (tt1 == void_type_node || tt2 == void_type_node)
target = void_type_node;
+ else if (tt1 == unknown_type_node)
+ target = tt2;
+ else if (tt2 == unknown_type_node)
+ target = tt1;
else
target = common_type (tt1, tt2);
static int
comp_array_types (cmp, t1, t2, strict)
- register int (*cmp)();
+ register int (*cmp) PROTO((tree, tree, int));
tree t1, t2;
int strict;
{
0 : <= (compared according to C++)
-1: <= or >= (relaxed)
- Otherwise, pointers involving base classes and derived classes
- can be mixed as valid: i.e. a pointer to a base class may be assigned
- to a pointer to one of its derived classes, as per C++. A pointer to
+ Otherwise, pointers involving base classes and derived classes can
+ be mixed as valid: i.e. a pointer to a derived class may be converted
+ to a pointer to one of its base classes, as per C++. A pointer to
a derived class may be passed as a parameter to a function expecting a
pointer to a base classes. These allowances do not commute. In this
case, TYPE1 is assumed to be the base class, and TYPE2 is assumed to
val = comp_array_types (comptypes, t1, t2, strict);
break;
+ case TEMPLATE_TEMPLATE_PARM:
+ if (TEMPLATE_TYPE_IDX (t1) != TEMPLATE_TYPE_IDX (t2)
+ || TEMPLATE_TYPE_LEVEL (t1) != TEMPLATE_TYPE_LEVEL (t2))
+ return 0;
+
+ if (CLASSTYPE_TEMPLATE_INFO (t1) && CLASSTYPE_TEMPLATE_INFO (t2))
+ {
+ int i = TREE_VEC_LENGTH (CLASSTYPE_TI_ARGS (t1));
+ tree *p1 = &TREE_VEC_ELT (CLASSTYPE_TI_ARGS (t1), 0);
+ tree *p2 = &TREE_VEC_ELT (CLASSTYPE_TI_ARGS (t2), 0);
+
+ while (i--)
+ {
+ if (TREE_CODE_CLASS (TREE_CODE (p1[i])) == 't')
+ {
+ if (! comptypes (p1[i], p2[i], 1))
+ return 0;
+ }
+ else
+ {
+ if (simple_cst_equal (p1[i], p2[i]) <= 0)
+ return 0;
+ }
+ }
+ return 1;
+ }
+ else if (CLASSTYPE_TEMPLATE_INFO (t1) || CLASSTYPE_TEMPLATE_INFO (t2))
+ return 0;
+ else
+ return 1;
+
case TEMPLATE_TYPE_PARM:
- return TEMPLATE_TYPE_IDX (t1) == TEMPLATE_TYPE_IDX (t2);
+ return TEMPLATE_TYPE_IDX (t1) == TEMPLATE_TYPE_IDX (t2)
+ && TEMPLATE_TYPE_LEVEL (t1) == TEMPLATE_TYPE_LEVEL (t2);
case TYPENAME_TYPE:
if (TYPE_IDENTIFIER (t1) != TYPE_IDENTIFIER (t2))
return 0;
return comptypes (TYPE_CONTEXT (t1), TYPE_CONTEXT (t2), 1);
+
+ default:
+ break;
}
return attrval == 2 && val == 1 ? 2 : val;
}
-/* Return 1 if TTL and TTR are pointers to types that are equivalent,
- ignoring their qualifiers.
+/* Return 1 or -1 if TTL and TTR are pointers to types that are equivalent,
+ ignoring their qualifiers, 0 if not. Return 1 means that TTR can be
+ converted to TTL. Return -1 means that TTL can be converted to TTR but
+ not vice versa.
NPTRS is the number of pointers we can strip off and keep cool.
This is used to permit (for aggr A, aggr B) A, B* to convert to A*,
if (nptrs > 0)
{
- if (TREE_CODE (ttl) == VOID_TYPE
+ if (TREE_CODE (ttl) == UNKNOWN_TYPE
+ || TREE_CODE (ttr) == UNKNOWN_TYPE)
+ return 1;
+ else if (TREE_CODE (ttl) == VOID_TYPE
&& TREE_CODE (ttr) != FUNCTION_TYPE
&& TREE_CODE (ttr) != METHOD_TYPE
&& TREE_CODE (ttr) != OFFSET_TYPE)
if (TREE_CODE (ttr) == ARRAY_TYPE)
return comp_array_types (comp_target_types, ttl, ttr, 0);
else if (TREE_CODE (ttr) == FUNCTION_TYPE || TREE_CODE (ttr) == METHOD_TYPE)
- if (comp_target_types (TREE_TYPE (ttl), TREE_TYPE (ttr), nptrs))
+ if (comp_target_types (TREE_TYPE (ttl), TREE_TYPE (ttr), -1))
switch (comp_target_parms (TYPE_ARG_TYPES (ttl), TYPE_ARG_TYPES (ttr), 1))
{
case 0:
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;
enum tree_code code = TREE_CODE (type);
tree t;
+ if (processing_template_decl)
+ return build_min (ALIGNOF_EXPR, sizetype, type);
+
if (code == FUNCTION_TYPE || code == METHOD_TYPE)
return size_int (FUNCTION_BOUNDARY / BITS_PER_UNIT);
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);
+ return cp_convert (build_pointer_type (TREE_TYPE (type)), inner);
}
if (TREE_CODE (exp) == COMPOUND_EXPR)
/* This way is better for a COMPONENT_REF since it can
simplify the offset for a component. */
adr = build_unary_op (ADDR_EXPR, exp, 1);
- return convert (ptrtype, adr);
+ return cp_convert (ptrtype, adr);
}
return exp;
{
tree t = type_promotes_to (type);
if (t != type)
- return convert (t, exp);
+ return cp_convert (t, exp);
}
return exp;
return error_mark_node;
}
-/* Like `build_component_ref, but uses an already found field.
- Must compute access for current_class_ref. Otherwise, ok. */
+/* Like `build_component_ref, but uses an already found field, and converts
+ from a reference. Must compute access for current_class_ref.
+ Otherwise, ok. */
tree
build_component_ref_1 (datum, field, protect)
tree datum, field;
int protect;
{
- return build_component_ref (datum, field, NULL_TREE, protect);
+ return convert_from_reference
+ (build_component_ref (datum, field, NULL_TREE, protect));
}
-/* Given a COND_EXPR in T, return it in a form that we can, for
- example, use as an lvalue. This code used to be in unary_complex_lvalue,
- but we needed it to deal with `a = (d == c) ? b : c' expressions, where
- we're dealing with aggregates. So, we now call this in unary_complex_lvalue,
- and in build_modify_expr. The case (in particular) that led to this was
- with CODE == ADDR_EXPR, since it's not an lvalue when we'd get it there. */
+/* Given a COND_EXPR, MIN_EXPR, or MAX_EXPR in T, return it in a form that we
+ can, for example, use as an lvalue. This code used to be in
+ unary_complex_lvalue, but we needed it to deal with `a = (d == c) ? b : c'
+ expressions, where we're dealing with aggregates. But now it's again only
+ called from unary_complex_lvalue. The case (in particular) that led to
+ this was with CODE == ADDR_EXPR, since it's not an lvalue when we'd
+ get it there. */
static tree
rationalize_conditional_expr (code, t)
enum tree_code code;
tree t;
{
+ /* For MIN_EXPR or MAX_EXPR, fold-const.c has arranged things so that
+ the first operand is always the one to be used if both operands
+ are equal, so we know what conditional expression this used to be. */
+ if (TREE_CODE (t) == MIN_EXPR || TREE_CODE (t) == MAX_EXPR)
+ {
+ return
+ build_conditional_expr (build_x_binary_op ((TREE_CODE (t) == MIN_EXPR
+ ? LE_EXPR : GE_EXPR),
+ TREE_OPERAND (t, 0),
+ TREE_OPERAND (t, 1)),
+ build_unary_op (code, TREE_OPERAND (t, 0), 0),
+ build_unary_op (code, TREE_OPERAND (t, 1), 0));
+ }
+
return
build_conditional_expr (TREE_OPERAND (t, 0),
build_unary_op (code, TREE_OPERAND (t, 1), 0),
basetype_path, protect),
build_component_ref (TREE_OPERAND (datum, 2), component,
basetype_path, protect));
+
+ case TEMPLATE_DECL:
+ cp_error ("invalid use of %D", datum);
+ datum = error_mark_node;
+ break;
+
+ default:
+ break;
}
code = TREE_CODE (basetype);
fndecl = build_vfn_ref (&addr, datum, DECL_VINDEX (fndecl));
TREE_TYPE (fndecl) = build_pointer_type (fntype);
}
- mark_used (fndecl);
+ else
+ mark_used (fndecl);
return build (OFFSET_REF, TREE_TYPE (fndecl), datum, fndecl);
}
if (access == access_protected_node)
if (TREE_CODE (type) == POINTER_TYPE || TREE_CODE (type) == REFERENCE_TYPE)
{
if (TREE_CODE (pointer) == ADDR_EXPR
+ && !flag_volatile
&& (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_OPERAND (pointer, 0)))
== TYPE_MAIN_VARIANT (TREE_TYPE (type)))
&& (TREE_READONLY (TREE_OPERAND (pointer, 0))
register tree ref = build1 (INDIRECT_REF,
TYPE_MAIN_VARIANT (t), pointer);
+ /* We *must* set TREE_READONLY when dereferencing a pointer to const,
+ so that we get the proper error message if the result is used
+ to assign to. Also, &* is supposed to be a no-op. */
TREE_READONLY (ref) = TYPE_READONLY (t);
- TREE_THIS_VOLATILE (ref) = TYPE_VOLATILE (t);
TREE_SIDE_EFFECTS (ref)
- = TYPE_VOLATILE (t) || TREE_SIDE_EFFECTS (pointer);
+ = TYPE_VOLATILE (t) || TREE_SIDE_EFFECTS (pointer) || flag_volatile;
+ TREE_THIS_VOLATILE (ref) = TYPE_VOLATILE (t);
return ref;
}
}
integer type. Otherwise, to make a compatible PLUS_EXPR, it
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;
tree function, params, decl;
{
tree type;
+ tree template_id = NULL_TREE;
int is_method;
if (function == error_mark_node)
if (processing_template_decl)
return build_min_nt (CALL_EXPR, function, params, NULL_TREE);
+ /* Save explicit template arguments if found */
+ if (TREE_CODE (function) == TEMPLATE_ID_EXPR)
+ {
+ template_id = function;
+ function = TREE_OPERAND (function, 0);
+ }
+
type = TREE_TYPE (function);
if (TREE_CODE (type) == OFFSET_TYPE
{
tree basetype = NULL_TREE;
- if (TREE_CODE (function) == FUNCTION_DECL)
+ if (TREE_CODE (function) == FUNCTION_DECL
+ || DECL_FUNCTION_TEMPLATE_P (function))
{
basetype = DECL_CLASS_CONTEXT (function);
decl = build_indirect_ref (decl, NULL_PTR);
}
+ /* Put back explicit template arguments, if any. */
+ if (template_id)
+ function = template_id;
return build_method_call (decl, function, params,
NULL_TREE, LOOKUP_NORMAL);
}
return build_method_call (decl, function, params,
NULL_TREE, LOOKUP_NORMAL);
}
- else if (TREE_CODE (function) == TREE_LIST)
+ else if (really_overloaded_fn (function))
{
if (TREE_VALUE (function) == NULL_TREE)
{
tree val = TREE_VALUE (function);
if (flag_ansi_overloading)
- return build_new_function_call (function, params, NULL_TREE);
+ {
+ /* Put back explicit template arguments, if any. */
+ if (template_id)
+ function = template_id;
+ return build_new_function_call (function, params);
+ }
if (TREE_CODE (val) == TEMPLATE_DECL)
return build_overload_call_real
decl_addr = build_unary_op (ADDR_EXPR, decl, 0);
function = get_member_function_from_ptrfunc (&decl_addr,
TREE_OPERAND (function, 1));
- params = tree_cons (NULL_TREE, decl_addr, params);
+ params = expr_tree_cons (NULL_TREE, decl_addr, params);
return build_function_call (function, params);
}
}
else
decl = build_c_cast (ctypeptr, decl);
- params = tree_cons (NULL_TREE, decl, params);
+ params = expr_tree_cons (NULL_TREE, decl, params);
}
return build_function_call (function, params);
function = save_expr (function);
fntype = TYPE_PTRMEMFUNC_FN_TYPE (TREE_TYPE (function));
- idx = save_expr (build_component_ref (function,
- index_identifier,
- NULL_TREE, 0));
- 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));
+
+ /* Promoting idx before saving it improves performance on RISC
+ targets. Without promoting, the first compare used
+ load-with-sign-extend, while the second used normal load then
+ shift to sign-extend. An optimizer flaw, perhaps, but it's easier
+ to make this change. */
+ idx = save_expr (default_conversion
+ (build_component_ref (function,
+ index_identifier,
+ NULL_TREE, 0)));
+ e1 = build_binary_op (GT_EXPR, idx, integer_zero_node, 1);
+ delta = cp_convert (ptrdiff_type_node,
+ build_component_ref (function, delta_identifier, NULL_TREE, 0));
delta2 = DELTA2_FROM_PTRMEMFUNC (function);
- /* convert down to the right base, before using the instance. */
+ /* Convert down to the right base, before using the instance. */
instance
= convert_pointer_to_real (TYPE_METHOD_BASETYPE (TREE_TYPE (fntype)),
instance_ptr);
vtbl
= build (PLUS_EXPR,
build_pointer_type (build_pointer_type (vtable_entry_type)),
- vtbl, convert (ptrdiff_type_node, delta2));
+ vtbl, cp_convert (ptrdiff_type_node, delta2));
vtbl = build_indirect_ref (vtbl, NULL_PTR);
aref = build_array_ref (vtbl, build_binary_op (MINUS_EXPR,
idx,
pedwarn ("ANSI C++ forbids calling `main' from within program");
}
- if (pedantic && DECL_THIS_INLINE (function) && ! DECL_INITIAL (function)
- && ! DECL_ARTIFICIAL (function)
- && ! DECL_PENDING_INLINE_INFO (function))
- cp_pedwarn ("inline function `%#D' called before definition",
- function);
-
/* Differs from default_conversion by not setting TREE_ADDRESSABLE
(because calling an inline function does not mean the function
needs to be separately compiled). */
if (!((TREE_CODE (fntype) == POINTER_TYPE
&& TREE_CODE (TREE_TYPE (fntype)) == FUNCTION_TYPE)
- || is_method))
+ || is_method
+ || TREE_CODE (function) == TEMPLATE_ID_EXPR))
{
cp_error ("`%E' cannot be used as a function", function);
return error_mark_node;
if (coerced_params == 0)
return integer_zero_node;
return build_unary_op (ABS_EXPR, TREE_VALUE (coerced_params), 0);
+
+ default:
+ break;
}
/* C++ */
/* Strip the `&' from an overloaded FUNCTION_DECL. */
if (TREE_CODE (val) == ADDR_EXPR)
val = TREE_OPERAND (val, 0);
- if (TREE_CODE (val) == TREE_LIST
- && TREE_CHAIN (val) == NULL_TREE
- && TREE_TYPE (TREE_VALUE (val)) != NULL_TREE
- && (TREE_TYPE (val) == unknown_type_node
- || DECL_CHAIN (TREE_VALUE (val)) == NULL_TREE))
- /* Instantiates automatically. */
- val = TREE_VALUE (val);
+ if (really_overloaded_fn (val))
+ cp_error ("insufficient type information to resolve address of overloaded function `%D'",
+ DECL_NAME (get_first_fn (val)));
else
- {
- error ("insufficient type information in parameter list");
- val = integer_zero_node;
- }
+ error ("insufficient type information in parameter list");
+ val = integer_zero_node;
}
else if (TREE_CODE (val) == OFFSET_REF
&& TREE_CODE (TREE_TYPE (val)) == METHOD_TYPE)
if (parmval == error_mark_node)
return error_mark_node;
- result = tree_cons (NULL_TREE, parmval, result);
+ result = expr_tree_cons (NULL_TREE, parmval, result);
}
else
{
&& (TYPE_PRECISION (TREE_TYPE (val))
< TYPE_PRECISION (double_type_node)))
/* Convert `float' to `double'. */
- result = tree_cons (NULL_TREE, convert (double_type_node, val), result);
+ result = expr_tree_cons (NULL_TREE, cp_convert (double_type_node, val), result);
else if (TYPE_LANG_SPECIFIC (TREE_TYPE (val))
&& ! TYPE_HAS_TRIVIAL_INIT_REF (TREE_TYPE (val)))
{
cp_warning ("cannot pass objects of type `%T' through `...'",
TREE_TYPE (val));
- result = tree_cons (NULL_TREE, val, result);
+ result = expr_tree_cons (NULL_TREE, val, result);
}
else
/* Convert `short' and `char' to full-size `int'. */
- result = tree_cons (NULL_TREE, default_conversion (val), result);
+ result = expr_tree_cons (NULL_TREE, default_conversion (val), result);
}
if (typetail)
if (parmval == error_mark_node)
return error_mark_node;
- result = tree_cons (0, parmval, result);
+ result = expr_tree_cons (0, parmval, result);
typetail = TREE_CHAIN (typetail);
/* ends with `...'. */
if (typetail == NULL_TREE)
We must subtract them as integers, then divide by object size. */
if (code0 == POINTER_TYPE && code1 == POINTER_TYPE
&& comp_target_types (type0, type1, 1))
- return pointer_diff (op0, op1);
+ return pointer_diff (op0, op1, common_type (type0, type1));
/* Handle pointer minus int. Just like pointer plus int. */
else if (code0 == POINTER_TYPE && code1 == INTEGER_TYPE)
return pointer_int_sum (MINUS_EXPR, op0, op1);
case FLOOR_DIV_EXPR:
case ROUND_DIV_EXPR:
case EXACT_DIV_EXPR:
- if ((code0 == INTEGER_TYPE || code0 == REAL_TYPE)
- && (code1 == INTEGER_TYPE || code1 == REAL_TYPE))
+ if ((code0 == INTEGER_TYPE || code0 == REAL_TYPE
+ || code0 == COMPLEX_TYPE)
+ && (code1 == INTEGER_TYPE || code1 == REAL_TYPE
+ || code1 == COMPLEX_TYPE))
{
if (TREE_CODE (op1) == INTEGER_CST && integer_zerop (op1))
cp_warning ("division by zero in `%E / 0'", op0);
/* Convert the shift-count to an integer, regardless of
size of value being shifted. */
if (TYPE_MAIN_VARIANT (TREE_TYPE (op1)) != integer_type_node)
- op1 = convert (integer_type_node, op1);
+ op1 = cp_convert (integer_type_node, op1);
/* Avoid converting op1 to result_type later. */
converted = 1;
}
/* Convert the shift-count to an integer, regardless of
size of value being shifted. */
if (TYPE_MAIN_VARIANT (TREE_TYPE (op1)) != integer_type_node)
- op1 = convert (integer_type_node, op1);
+ op1 = cp_convert (integer_type_node, op1);
/* Avoid converting op1 to result_type later. */
converted = 1;
}
/* Convert the shift-count to an integer, regardless of
size of value being shifted. */
if (TYPE_MAIN_VARIANT (TREE_TYPE (op1)) != integer_type_node)
- op1 = convert (integer_type_node, op1);
+ op1 = cp_convert (integer_type_node, op1);
}
break;
case EQ_EXPR:
case NE_EXPR:
build_type = boolean_type_node;
- if ((code0 == INTEGER_TYPE || code0 == REAL_TYPE)
- && (code1 == INTEGER_TYPE || code1 == REAL_TYPE))
+ if ((code0 == INTEGER_TYPE || code0 == REAL_TYPE
+ || code0 == COMPLEX_TYPE)
+ && (code1 == INTEGER_TYPE || code1 == REAL_TYPE
+ || code1 == COMPLEX_TYPE))
short_compare = 1;
else if (code0 == POINTER_TYPE && code1 == POINTER_TYPE)
{
pedwarn ("ANSI C++ forbids comparison between pointer and integer");
}
break;
+
+ default:
+ break;
}
- if ((code0 == INTEGER_TYPE || code0 == REAL_TYPE)
- && (code1 == INTEGER_TYPE || code1 == REAL_TYPE))
+ if ((code0 == INTEGER_TYPE || code0 == REAL_TYPE || code0 == COMPLEX_TYPE)
+ &&
+ (code1 == INTEGER_TYPE || code1 == REAL_TYPE || code1 == COMPLEX_TYPE))
{
+ int none_complex = (code0 != COMPLEX_TYPE && code1 != COMPLEX_TYPE);
+
if (shorten || common || short_compare)
result_type = common_type (type0, type1);
Eg, (short)-1 | (unsigned short)-1 is (int)-1
but calculated in (unsigned short) it would be (unsigned short)-1. */
- if (shorten)
+ if (shorten && none_complex)
{
int unsigned0, unsigned1;
tree arg0 = get_narrower (op0, &unsigned0);
TREE_TYPE (arg0));
/* Convert value-to-be-shifted to that type. */
if (TREE_TYPE (op0) != result_type)
- op0 = convert (result_type, op0);
+ op0 = cp_convert (result_type, op0);
converted = 1;
}
}
tree val
= shorten_compare (&xop0, &xop1, &xresult_type, &xresultcode);
if (val != 0)
- return convert (boolean_type_node, val);
+ return cp_convert (boolean_type_node, val);
op0 = xop0, op1 = xop1;
converted = 1;
resultcode = xresultcode;
if (! converted)
{
if (TREE_TYPE (op0) != result_type)
- op0 = convert (result_type, op0);
+ op0 = cp_convert (result_type, op0);
if (TREE_TYPE (op1) != result_type)
- op1 = convert (result_type, op1);
+ op1 = cp_convert (result_type, op1);
}
if (build_type == NULL_TREE)
if (folded == result)
TREE_CONSTANT (folded) = TREE_CONSTANT (op0) & TREE_CONSTANT (op1);
if (final_type != 0)
- return convert (final_type, folded);
+ return cp_convert (final_type, folded);
return folded;
}
}
so the multiply won't overflow spuriously. */
if (TYPE_PRECISION (TREE_TYPE (intop)) != TYPE_PRECISION (sizetype))
- intop = convert (type_for_size (TYPE_PRECISION (sizetype), 0), intop);
+ intop = cp_convert (type_for_size (TYPE_PRECISION (sizetype), 0), intop);
/* Replace the integer argument with a suitable product by the object size.
Do this multiplication as signed, then convert to the appropriate
pointer type (actually unsigned integral). */
- intop = convert (result_type,
- build_binary_op (MULT_EXPR, intop,
- convert (TREE_TYPE (intop), size_exp), 1));
+ intop = cp_convert (result_type,
+ build_binary_op (MULT_EXPR, intop,
+ cp_convert (TREE_TYPE (intop), size_exp), 1));
/* Create the sum or difference. */
The resulting tree has type int. */
static tree
-pointer_diff (op0, op1)
+pointer_diff (op0, op1, ptrtype)
register tree op0, op1;
+ register tree ptrtype;
{
register tree result, folded;
tree restype = ptrdiff_type_node;
- tree target_type = TREE_TYPE (TREE_TYPE (op0));
+ tree target_type = TREE_TYPE (ptrtype);
if (pedantic || warn_pointer_arith)
{
then drop through to build the divide operator. */
op0 = build_binary_op (MINUS_EXPR,
- convert (restype, op0), convert (restype, op1), 1);
+ cp_convert (restype, op0), cp_convert (restype, op1), 1);
/* This generates an error if op1 is a pointer to an incomplete type. */
if (TYPE_SIZE (TREE_TYPE (TREE_TYPE (op1))) == 0)
/* Do the division. */
- result = build (EXACT_DIV_EXPR, restype, op0, convert (restype, op1));
+ result = build (EXACT_DIV_EXPR, restype, op0, cp_convert (restype, op1));
folded = fold (result);
if (folded == result)
size_int (BITS_PER_UNIT));
int flag = TREE_CONSTANT (rval);
rval = fold (build (PLUS_EXPR, argtype,
- rval, convert (argtype, offset)));
+ rval, cp_convert (argtype, offset)));
TREE_CONSTANT (rval) = flag;
}
return rval;
/* & rec, on incomplete RECORD_TYPEs is the simple opr &, not an
error message. */
if (code == ADDR_EXPR
+ && TREE_CODE (xarg) != TEMPLATE_ID_EXPR
&& ((IS_AGGR_TYPE_CODE (TREE_CODE (TREE_TYPE (xarg)))
&& TYPE_SIZE (TREE_TYPE (xarg)) == NULL_TREE)
|| (TREE_CODE (xarg) == OFFSET_REF)))
tree t;
if (processing_template_decl)
return expr;
- t = convert (boolean_type_node, expr);
+ t = cp_convert (boolean_type_node, expr);
t = fold (build1 (CLEANUP_POINT_EXPR, boolean_type_node, t));
return t;
}
break;
case BIT_NOT_EXPR:
- if (!(arg = build_expr_type_conversion (WANT_INT | WANT_ENUM, arg, 1)))
+ if (TREE_CODE (TREE_TYPE (arg)) == COMPLEX_TYPE)
+ {
+ code = CONJ_EXPR;
+ if (!noconvert)
+ arg = default_conversion (arg);
+ }
+ else if (!(arg = build_expr_type_conversion (WANT_INT | WANT_ENUM,
+ arg, 1)))
errstring = "wrong type argument to bit-complement";
else if (!noconvert)
arg = default_conversion (arg);
arg = default_conversion (arg);
break;
+ case CONJ_EXPR:
+ /* Conjugating a real value is a no-op, but allow it anyway. */
+ if (!(arg = build_expr_type_conversion (WANT_ARITH | WANT_ENUM, arg, 1)))
+ errstring = "wrong type argument to conjugation";
+ else if (!noconvert)
+ arg = default_conversion (arg);
+ break;
+
case TRUTH_NOT_EXPR:
- arg = convert (boolean_type_node, arg);
+ arg = cp_convert (boolean_type_node, arg);
val = invert_truthvalue (arg);
if (arg != error_mark_node)
return val;
case NOP_EXPR:
break;
+ case REALPART_EXPR:
+ if (TREE_CODE (arg) == COMPLEX_CST)
+ return TREE_REALPART (arg);
+ else if (TREE_CODE (TREE_TYPE (arg)) == COMPLEX_TYPE)
+ return fold (build1 (REALPART_EXPR, TREE_TYPE (TREE_TYPE (arg)), arg));
+ else
+ return arg;
+
+ case IMAGPART_EXPR:
+ if (TREE_CODE (arg) == COMPLEX_CST)
+ return TREE_IMAGPART (arg);
+ else if (TREE_CODE (TREE_TYPE (arg)) == COMPLEX_TYPE)
+ return fold (build1 (IMAGPART_EXPR, TREE_TYPE (TREE_TYPE (arg)), arg));
+ else
+ return cp_convert (TREE_TYPE (arg), integer_zero_node);
+
case PREINCREMENT_EXPR:
case POSTINCREMENT_EXPR:
case PREDECREMENT_EXPR:
if (val != 0)
return val;
+ /* Increment or decrement the real part of the value,
+ and don't change the imaginary part. */
+ if (TREE_CODE (TREE_TYPE (arg)) == COMPLEX_TYPE)
+ {
+ tree real, imag;
+
+ arg = stabilize_reference (arg);
+ real = build_unary_op (REALPART_EXPR, arg, 1);
+ imag = build_unary_op (IMAGPART_EXPR, arg, 1);
+ return build (COMPLEX_EXPR, TREE_TYPE (arg),
+ build_unary_op (code, real, 1), imag);
+ }
+
/* Report invalid types. */
if (!(arg = build_expr_type_conversion (WANT_ARITH | WANT_POINTER,
else
inc = integer_one_node;
- inc = convert (argtype, inc);
+ inc = cp_convert (argtype, inc);
/* Handle incrementing a cast-expression. */
TREE_NO_UNUSED_WARNING (compound) = 1;
return compound;
}
+
+ default:
+ break;
}
/* Complain about anything else that is not a true lvalue. */
val = build (code, TREE_TYPE (arg), arg, inc);
TREE_SIDE_EFFECTS (val) = 1;
- return convert (result_type, val);
+ return cp_convert (result_type, val);
}
case ADDR_EXPR:
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))
0);
return build1 (ADDR_EXPR, unknown_type_node, arg);
}
+ else if (TREE_CODE (arg) == TEMPLATE_ID_EXPR)
+ {
+ tree targs;
+ tree fn;
+
+ /* We don't require a match here; it's possible that the
+ context (like a cast to a particular type) will resolve
+ the particular choice of template. */
+ fn = determine_specialization (arg,
+ NULL_TREE,
+ &targs,
+ 0,
+ 0);
+
+ if (fn)
+ {
+ fn = instantiate_template (fn, targs);
+ mark_addressable (fn);
+ return build_unary_op (ADDR_EXPR, fn, 0);
+ }
+
+ return build1 (ADDR_EXPR, unknown_type_node, arg);
+ }
/* Handle complex lvalues (when permitted)
by reduction to simpler cases. */
case FIX_CEIL_EXPR:
if (! lvalue_p (arg) && pedantic)
pedwarn ("taking the address of a cast to non-reference type");
+ break;
+
+ default:
+ break;
}
/* Allow the address of a constructor if all the elements
if (staticp (arg))
TREE_CONSTANT (addr) = 1;
- if (TREE_CODE (argtype) == POINTER_TYPE &&
- TREE_CODE (TREE_TYPE (argtype)) == METHOD_TYPE)
+ if (TREE_CODE (argtype) == POINTER_TYPE
+ && TREE_CODE (TREE_TYPE (argtype)) == METHOD_TYPE)
{
build_ptrmemfunc_type (argtype);
addr = build_ptrmemfunc (argtype, addr, 0);
return addr;
}
+
+ default:
+ break;
}
if (!errstring)
case FIX_FLOOR_EXPR:
case FIX_ROUND_EXPR:
case FIX_CEIL_EXPR:
- return convert (TREE_TYPE (conversions),
- convert_sequence (TREE_OPERAND (conversions, 0),
- arg));
+ return cp_convert (TREE_TYPE (conversions),
+ convert_sequence (TREE_OPERAND (conversions, 0),
+ arg));
default:
return arg;
}
/* Handle (a ? b : c) used as an "lvalue". */
- if (TREE_CODE (arg) == COND_EXPR)
+ if (TREE_CODE (arg) == COND_EXPR
+ || TREE_CODE (arg) == MIN_EXPR || TREE_CODE (arg) == MAX_EXPR)
return rationalize_conditional_expr (code, arg);
if (TREE_CODE (arg) == MODIFY_EXPR
return error_mark_node;
}
- 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));
- }
+ type = TYPE_OFFSET_BASETYPE (TREE_TYPE (arg));
/* Now in the offset to the final subobject. */
offset = size_binop (PLUS_EXPR,
DECL_FIELD_BITPOS (t),
size_int (BITS_PER_UNIT)));
- /* We offset all pointer to data memebers by 1 so that we can
+ /* We offset all pointer to data members by 1 so that we can
distinguish between a null pointer to data member and the first
data member of a structure. */
offset = size_binop (PLUS_EXPR, offset, size_int (1));
- return convert (build_pointer_type (TREE_TYPE (arg)), offset);
+ return cp_convert (build_pointer_type (TREE_TYPE (arg)), offset);
}
}
case ADDR_EXPR:
case COMPONENT_REF:
case ARRAY_REF:
+ case REALPART_EXPR:
+ case IMAGPART_EXPR:
x = TREE_OPERAND (x, 0);
break;
return 1;
case FUNCTION_DECL:
- /* We have to test both conditions here. The first may
- be non-zero in the case of processing a default function.
- The second may be non-zero in the case of a template function. */
- x = DECL_MAIN_VARIANT (x);
- if ((DECL_THIS_INLINE (x) || DECL_PENDING_INLINE_INFO (x))
- && (DECL_CONTEXT (x) == NULL_TREE
- || TREE_CODE_CLASS (TREE_CODE (DECL_CONTEXT (x))) != 't'
- || ! CLASSTYPE_INTERFACE_ONLY (DECL_CONTEXT (x))))
+ if (DECL_LANG_SPECIFIC (x) != 0)
{
- mark_inline_for_output (x);
- if (x == current_function_decl)
- DECL_EXTERNAL (x) = 0;
+ x = DECL_MAIN_VARIANT (x);
+ /* We have to test both conditions here. The first may be
+ non-zero in the case of processing a default function. The
+ second may be non-zero in the case of a template function. */
+ if (DECL_TEMPLATE_INFO (x) && !DECL_TEMPLATE_SPECIALIZATION (x))
+ mark_used (x);
}
TREE_ADDRESSABLE (x) = 1;
TREE_USED (x) = 1;
ifexp = op1 = save_expr (ifexp);
}
- ifexp = convert (boolean_type_node, ifexp);
+ ifexp = cp_convert (boolean_type_node, ifexp);
if (TREE_CODE (ifexp) == ERROR_MARK)
return error_mark_node;
result_type = build_ptrmemfunc_type (result_type);
if (result_type != TREE_TYPE (op1))
- op1 = convert_and_check (result_type, op1);
+ op1 = convert_for_initialization
+ (NULL_TREE, result_type, op1, LOOKUP_NORMAL, "converting", NULL_TREE, 0);
if (result_type != TREE_TYPE (op2))
- op2 = convert_and_check (result_type, op2);
+ op2 = convert_for_initialization
+ (NULL_TREE, result_type, op2, LOOKUP_NORMAL, "converting", NULL_TREE, 0);
if (TREE_CONSTANT (ifexp))
return integer_zerop (ifexp) ? op2 : op1;
result = build_opfncall (COMPOUND_EXPR, LOOKUP_NORMAL,
TREE_VALUE (list), TREE_VALUE (rest), NULL_TREE);
if (result)
- return build_x_compound_expr (tree_cons (NULL_TREE, result, TREE_CHAIN (rest)));
+ return build_x_compound_expr (expr_tree_cons (NULL_TREE, result, TREE_CHAIN (rest)));
if (! TREE_SIDE_EFFECTS (TREE_VALUE (list)))
{
warn_if_unused_value (TREE_VALUE(list));
#endif
- return build_compound_expr (tree_cons (NULL_TREE, TREE_VALUE (list),
- build_tree_list (NULL_TREE, build_x_compound_expr (rest))));
+ return build_compound_expr (expr_tree_cons (NULL_TREE, TREE_VALUE (list),
+ build_expr_list (NULL_TREE, build_x_compound_expr (rest))));
}
/* Given a list of expressions, return a compound expression
if (processing_template_decl)
{
- tree t = build_min (STATIC_CAST_EXPR, type, expr);
+ tree t = build_min (STATIC_CAST_EXPR, copy_to_permanent (type),
+ expr);
return t;
}
if (IS_AGGR_TYPE (type))
return build_cplus_new
(type, (build_method_call
- (NULL_TREE, ctor_identifier, build_tree_list (NULL_TREE, expr),
+ (NULL_TREE, ctor_identifier, build_expr_list (NULL_TREE, expr),
TYPE_BINFO (type), LOOKUP_NORMAL)));
expr = decay_conversion (expr);
if (processing_template_decl)
{
- tree t = build_min (REINTERPRET_CAST_EXPR, type, expr);
+ tree t = build_min (REINTERPRET_CAST_EXPR,
+ copy_to_permanent (type), expr);
return t;
}
expr = decl_constant_value (expr);
return fold (build1 (NOP_EXPR, type, expr));
}
+ else if ((TYPE_PTRFN_P (type) && TYPE_PTROBV_P (intype))
+ || (TYPE_PTRFN_P (type) && TYPE_PTROBV_P (intype)))
+ {
+ pedwarn ("ANSI C++ forbids casting between pointers to functions and objects");
+ 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;
}
- return convert (type, expr);
+ return cp_convert (type, expr);
}
tree
if (processing_template_decl)
{
- tree t = build_min (CONST_CAST_EXPR, type, expr);
+ tree t = build_min (CONST_CAST_EXPR, copy_to_permanent (type),
+ expr);
return t;
}
}
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)));
+ {
+ expr = build_unary_op (ADDR_EXPR, expr, 0);
+ expr = build1 (NOP_EXPR, type, expr);
+ return convert_from_reference (expr);
+ }
}
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 cp_convert (type, expr);
cp_error ("const_cast from `%T' to `%T'", intype, type);
return error_mark_node;
tree
build_c_cast (type, expr)
- register tree type;
- tree expr;
+ tree type, expr;
{
register tree value = expr;
else
{
tree otype;
- int flag;
/* Convert functions and arrays to pointers and
convert references to their expanded types,
|| (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 (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);
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)
return value;
}
\f
-tree
+static tree
expand_target_expr (t)
tree t;
{
do_pending_stack_adjust ();
start_sequence_for_rtl_expr (xval);
emit_note (0, -1);
- rtxval = expand_expr (t, NULL_RTX, VOIDmode, 0);
+ rtxval = expand_expr (t, NULL_RTX, VOIDmode, EXPAND_NORMAL);
do_pending_stack_adjust ();
TREE_SIDE_EFFECTS (xval) = 1;
RTL_EXPR_SEQUENCE (xval) = get_insns ();
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. */
/* Handle assignment to signature pointers/refs. */
- if (TYPE_LANG_SPECIFIC (lhstype) &&
- (IS_SIGNATURE_POINTER (lhstype) || IS_SIGNATURE_REFERENCE (lhstype)))
+ if (TYPE_LANG_SPECIFIC (lhstype)
+ && (IS_SIGNATURE_POINTER (lhstype) || IS_SIGNATURE_REFERENCE (lhstype)))
{
return build_signature_pointer_constructor (lhs, rhs);
}
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);
so the code to compute it is only emitted once. */
tree cond
= build_conditional_expr (TREE_OPERAND (lhs, 0),
- build_modify_expr (convert (TREE_TYPE (lhs), TREE_OPERAND (lhs, 1)),
+ build_modify_expr (cp_convert (TREE_TYPE (lhs), TREE_OPERAND (lhs, 1)),
modifycode, rhs),
- build_modify_expr (convert (TREE_TYPE (lhs), TREE_OPERAND (lhs, 2)),
+ build_modify_expr (cp_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. */
return build (COMPOUND_EXPR, TREE_TYPE (lhs),
/* Case to void to suppress warning
from warn_if_unused_value. */
- convert (void_type_node, rhs), cond);
+ cp_convert (void_type_node, rhs), cond);
}
+
+ default:
+ break;
}
if (TREE_CODE (lhs) == OFFSET_REF)
{
if (! IS_AGGR_TYPE (lhstype))
/* Do the default thing */;
- else if (! TYPE_HAS_CONSTRUCTOR (lhstype))
- {
- cp_error ("`%T' has no constructors", lhstype);
- return error_mark_node;
- }
- else if (TYPE_HAS_TRIVIAL_INIT_REF (lhstype)
- && TYPE_MAIN_VARIANT (lhstype) == TYPE_MAIN_VARIANT (TREE_TYPE (newrhs)))
- /* Do the default thing */;
else
{
result = build_method_call (lhs, ctor_identifier,
- build_tree_list (NULL_TREE, rhs),
+ build_expr_list (NULL_TREE, rhs),
TYPE_BINFO (lhstype), LOOKUP_NORMAL);
if (result == NULL_TREE)
return error_mark_node;
/* `operator=' is not an inheritable operator. */
if (! IS_AGGR_TYPE (lhstype))
/* Do the default thing */;
- else if (! TYPE_HAS_ASSIGNMENT (lhstype))
- {
- cp_error ("`%T' does not define operator=", lhstype);
- return error_mark_node;
- }
- else if (TYPE_HAS_TRIVIAL_ASSIGN_REF (lhstype)
- && TYPE_MAIN_VARIANT (lhstype) == TYPE_MAIN_VARIANT (TREE_TYPE (newrhs)))
- {
- build_opfncall (MODIFY_EXPR, LOOKUP_NORMAL,
- lhs, rhs, make_node (NOP_EXPR));
-
- /* Do the default thing */;
- }
else
{
result = build_opfncall (MODIFY_EXPR, LOOKUP_NORMAL,
{
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)
+ cp_convert (TREE_TYPE (inner_lhs),
+ cp_convert (lhstype, newrhs)));
+ if (result == error_mark_node)
return result;
- return convert (TREE_TYPE (lhs), result);
+ return cp_convert (TREE_TYPE (lhs), result);
}
+
+ default:
+ break;
}
/* Now we have handled acceptable kinds of LHS that are not truly lvalues.
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)
if (TREE_SIDE_EFFECTS (lhs))
cond = build_compound_expr (tree_cons
(NULL_TREE, lhs,
- build_tree_list (NULL_TREE, cond)));
+ build_expr_list (NULL_TREE, cond)));
/* Cannot have two identical lhs on this one tree (result) as preexpand
calls will rip them out and fill in RTL for them, but when the
result
= build (COND_EXPR, result_type, cond,
build_modify_expr (lhs, modifycode,
- convert (result_type,
- TREE_OPERAND (newrhs, 1))),
+ cp_convert (result_type,
+ TREE_OPERAND (newrhs, 1))),
build_modify_expr (lhs1, modifycode,
- convert (result_type,
- TREE_OPERAND (newrhs, 2))));
+ cp_convert (result_type,
+ TREE_OPERAND (newrhs, 2))));
}
}
else
binfo = get_binfo (from, to, 1);
if (binfo == error_mark_node)
{
- error (" in pointer to member function conversiona");
+ error (" in pointer to member function conversion");
return delta;
}
if (binfo == 0)
warning ("pointer to member conversion to virtual base class will only work if you are very careful");
}
delta = BINFO_OFFSET (binfo);
- delta = convert (ptrdiff_type_node, delta);
+ delta = cp_convert (ptrdiff_type_node, delta);
return build_binary_op (MINUS_EXPR,
integer_zero_node,
if (pfn)
{
u = build_nt (CONSTRUCTOR, NULL_TREE,
- tree_cons (pfn_identifier, pfn, NULL_TREE));
+ expr_tree_cons (pfn_identifier, pfn, NULL_TREE));
}
else
{
u = build_nt (CONSTRUCTOR, NULL_TREE,
- tree_cons (delta2_identifier, delta2, NULL_TREE));
+ expr_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))));
+ expr_tree_cons (NULL_TREE, delta,
+ expr_tree_cons (NULL_TREE, idx,
+ expr_tree_cons (NULL_TREE, u, NULL_TREE))));
return digest_init (type, u, (tree*)0);
#else
if (pfn)
{
allconstant = TREE_CONSTANT (pfn);
- allsimple = initializer_constant_valid_p (pfn, TREE_TYPE (pfn));
- u = tree_cons (pfn_field, pfn, NULL_TREE);
+ allsimple = !! initializer_constant_valid_p (pfn, TREE_TYPE (pfn));
+ u = expr_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);
+ allsimple = !! initializer_constant_valid_p (delta2, TREE_TYPE (delta2));
+ u = expr_tree_cons (delta2_field, delta2, NULL_TREE);
}
delta = convert_and_check (delta_type_node, 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 = expr_tree_cons (delta_field, delta,
+ expr_tree_cons (idx_field, idx,
+ expr_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;
if (type == TYPE_PTRMEMFUNC_FN_TYPE (TREE_TYPE (pfn)))
return pfn;
- ndelta = convert (ptrdiff_type_node, build_component_ref (pfn, delta_identifier, NULL_TREE, 0));
- ndelta2 = convert (ptrdiff_type_node, DELTA2_FROM_PTRMEMFUNC (pfn));
+ ndelta = cp_convert (ptrdiff_type_node, build_component_ref (pfn, delta_identifier, NULL_TREE, 0));
+ ndelta2 = cp_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)))),
return error_mark_node;
}
/* Arithmetic types all interconvert. */
- if ((codel == INTEGER_TYPE || codel == REAL_TYPE || codel == BOOLEAN_TYPE)
- && (coder == INTEGER_TYPE || coder == REAL_TYPE || coder == BOOLEAN_TYPE))
+ if ((codel == INTEGER_TYPE || codel == REAL_TYPE || codel == BOOLEAN_TYPE
+ || codel == COMPLEX_TYPE)
+ && (coder == INTEGER_TYPE || coder == REAL_TYPE || coder == BOOLEAN_TYPE
+ || coder == COMPLEX_TYPE))
{
/* But we should warn if assigning REAL_TYPE to INTEGER_TYPE. */
if (coder == REAL_TYPE && codel == INTEGER_TYPE)
|| (coder == ENUMERAL_TYPE
&& (INTEGRAL_CODE_P (codel) || codel == REAL_TYPE)))
{
- return cp_convert (type, rhs, CONV_IMPLICIT, LOOKUP_NORMAL);
+ return ocp_convert (type, rhs, CONV_IMPLICIT, LOOKUP_NORMAL);
}
/* Conversions among pointers */
else if (codel == POINTER_TYPE
return error_mark_node;
}
}
- return convert (type, rhs);
+ return cp_convert (type, rhs);
}
else if (codel == POINTER_TYPE && coder == INTEGER_TYPE)
{
cp_pedwarn ("%s to `%T' from `%T' lacks a cast",
errtype, type, rhstype);
}
- return convert (type, rhs);
+ return cp_convert (type, rhs);
}
else if (codel == INTEGER_TYPE
&& (coder == POINTER_TYPE
else
cp_pedwarn ("%s to `%T' from `%T' lacks a cast",
errtype, type, rhstype);
- return convert (type, rhs);
+ return cp_convert (type, rhs);
}
else if (codel == BOOLEAN_TYPE
&& (coder == POINTER_TYPE
&& (IS_SIGNATURE_POINTER (rhstype)
|| TYPE_PTRMEMFUNC_FLAG (rhstype)
|| IS_SIGNATURE_REFERENCE (rhstype)))))
- return convert (type, rhs);
+ return cp_convert (type, rhs);
/* C++ */
else if (((coder == POINTER_TYPE
return nrhs;
}
else if (TYPE_HAS_CONSTRUCTOR (type) || IS_AGGR_TYPE (TREE_TYPE (rhs)))
- return convert (type, rhs);
+ return cp_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);
+ return cp_convert (type, rhs);
cp_error ("%s to `%T' from `%T'", errtype, type, rhstype);
return error_mark_node;
&& (TYPE_NEEDS_CONSTRUCTING (type) || TREE_HAS_CONSTRUCTOR (rhs)))
{
if (flag_ansi_overloading)
- return cp_convert (type, rhs, CONV_IMPLICIT|CONV_FORCE_TEMP, flags);
+ return ocp_convert (type, rhs, CONV_IMPLICIT|CONV_FORCE_TEMP, flags);
if (TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (rhstype))
{
if (TYPE_HAS_INIT_REF (type))
{
tree init = build_method_call (exp, ctor_identifier,
- build_tree_list (NULL_TREE, rhs),
+ build_expr_list (NULL_TREE, rhs),
TYPE_BINFO (type), LOOKUP_NORMAL);
if (init == error_mark_node)
return rhs;
}
- return cp_convert (type, rhs, CONV_OLD_CONVERT,
- flags | LOOKUP_NO_CONVERSION);
+ return ocp_convert (type, rhs, CONV_OLD_CONVERT,
+ flags | LOOKUP_NO_CONVERSION);
}
if (type == TREE_TYPE (rhs))
if (o[i] != TREE_VALUE (tail))
{
expand_expr (build_modify_expr (o[i], NOP_EXPR, TREE_VALUE (tail)),
- const0_rtx, VOIDmode, 0);
+ const0_rtx, VOIDmode, EXPAND_NORMAL);
free_temp_slots ();
}
/* Detect modification of read-only values.
}
/* Effective C++ rule 15. See also start_function. */
- if (extra_warnings
+ 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;
- if (pedantic || TREE_CODE (TREE_TYPE (retval)) != VOID_TYPE)
+ 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)
- {
- tree whats_returned;
- tree tmp_result = result;
-
- /* Don't initialize directly into a non-BLKmode retval, since that
- could lose when being inlined by another caller. (GCC can't
- read the function return register in an inline function when
- the return value is being ignored). */
- if (result && TYPE_MODE (TREE_TYPE (tmp_result)) != BLKmode)
- tmp_result = 0;
-
- /* 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|LOOKUP_ONLYCONVERTING,
- "return", NULL_TREE, 0);
-
- /* Sort through common things to see what it is
- we are returning. */
- whats_returned = retval;
- if (TREE_CODE (whats_returned) == COMPOUND_EXPR)
- {
- whats_returned = TREE_OPERAND (whats_returned, 1);
- if (TREE_CODE (whats_returned) == ADDR_EXPR)
- whats_returned = TREE_OPERAND (whats_returned, 0);
- }
- if (TREE_CODE (whats_returned) == ADDR_EXPR)
- {
- whats_returned = TREE_OPERAND (whats_returned, 0);
- while (TREE_CODE (whats_returned) == NEW_EXPR
- || TREE_CODE (whats_returned) == TARGET_EXPR)
- {
- /* Get the target. */
- whats_returned = TREE_OPERAND (whats_returned, 0);
- warning ("returning reference to temporary");
- }
- }
-
- if (TREE_CODE (whats_returned) == VAR_DECL && DECL_NAME (whats_returned))
- {
- if (TEMP_NAME_P (DECL_NAME (whats_returned)))
- warning ("reference to non-lvalue returned");
- else if (! TREE_STATIC (whats_returned)
- && IDENTIFIER_LOCAL_VALUE (DECL_NAME (whats_returned))
- && !TREE_PUBLIC (whats_returned))
- cp_warning_at ("reference to local variable `%D' returned", whats_returned);
- }
- }
- else if (TREE_CODE (retval) == ADDR_EXPR)
- {
- tree whats_returned = TREE_OPERAND (retval, 0);
-
- if (TREE_CODE (whats_returned) == VAR_DECL
- && DECL_NAME (whats_returned)
- && IDENTIFIER_LOCAL_VALUE (DECL_NAME (whats_returned))
- && !TREE_STATIC (whats_returned)
- && !TREE_PUBLIC (whats_returned))
- cp_warning_at ("address of local variable `%D' returned", whats_returned);
- }
- else if (TREE_CODE (retval) == VAR_DECL)
- {
- if (TREE_CODE (TREE_TYPE (retval)) == ARRAY_TYPE
- && DECL_NAME (retval)
- && IDENTIFIER_LOCAL_VALUE (DECL_NAME (retval))
- && !TREE_STATIC (retval)
- && !TREE_PUBLIC (retval))
- cp_warning_at ("address of local array `%D' returned", retval);
- }
/* Now deal with possible C++ hair:
(1) Compute the return value.
}
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));
+ retval = convert_for_initialization
+ (NULL_TREE, valtype, retval, LOOKUP_NORMAL|LOOKUP_ONLYCONVERTING,
+ "return", NULL_TREE, 0);
if (retval == error_mark_node)
{
expand_null_return ();
return;
}
+
+ /* We can't initialize a register from a AGGR_INIT_EXPR. */
+ else if (! current_function_returns_struct
+ && TREE_CODE (retval) == TARGET_EXPR
+ && TREE_CODE (TREE_OPERAND (retval, 1)) == AGGR_INIT_EXPR)
+ retval = build (COMPOUND_EXPR, TREE_TYPE (retval), retval,
+ TREE_OPERAND (retval, 0));
+
+ /* Add some useful error checking for C++. */
+ else if (TREE_CODE (valtype) == REFERENCE_TYPE)
+ {
+ tree whats_returned;
+
+ /* Sort through common things to see what it is
+ we are returning. */
+ whats_returned = retval;
+ if (TREE_CODE (whats_returned) == COMPOUND_EXPR)
+ {
+ whats_returned = TREE_OPERAND (whats_returned, 1);
+ if (TREE_CODE (whats_returned) == ADDR_EXPR)
+ whats_returned = TREE_OPERAND (whats_returned, 0);
+ }
+ while (TREE_CODE (whats_returned) == CONVERT_EXPR
+ || TREE_CODE (whats_returned) == NOP_EXPR)
+ whats_returned = TREE_OPERAND (whats_returned, 0);
+ if (TREE_CODE (whats_returned) == ADDR_EXPR)
+ {
+ whats_returned = TREE_OPERAND (whats_returned, 0);
+ while (TREE_CODE (whats_returned) == AGGR_INIT_EXPR
+ || TREE_CODE (whats_returned) == TARGET_EXPR)
+ {
+ /* Get the target. */
+ whats_returned = TREE_OPERAND (whats_returned, 0);
+ warning ("returning reference to temporary");
+ }
+ }
+
+ if (TREE_CODE (whats_returned) == VAR_DECL && DECL_NAME (whats_returned))
+ {
+ if (TEMP_NAME_P (DECL_NAME (whats_returned)))
+ warning ("reference to non-lvalue returned");
+ else if (TREE_CODE (TREE_TYPE (whats_returned)) != REFERENCE_TYPE
+ && ! TREE_STATIC (whats_returned)
+ && IDENTIFIER_LOCAL_VALUE (DECL_NAME (whats_returned))
+ && !TREE_PUBLIC (whats_returned))
+ cp_warning_at ("reference to local variable `%D' returned", whats_returned);
+ }
+ }
+ else if (TREE_CODE (retval) == ADDR_EXPR)
+ {
+ tree whats_returned = TREE_OPERAND (retval, 0);
+
+ if (TREE_CODE (whats_returned) == VAR_DECL
+ && DECL_NAME (whats_returned)
+ && IDENTIFIER_LOCAL_VALUE (DECL_NAME (whats_returned))
+ && !TREE_STATIC (whats_returned)
+ && !TREE_PUBLIC (whats_returned))
+ cp_warning_at ("address of local variable `%D' returned", whats_returned);
+ }
}
if (retval != NULL_TREE
result = build (INIT_EXPR, TREE_TYPE (result), result, retval);
TREE_SIDE_EFFECTS (result) = 1;
}
+
+ expand_start_target_temps ();
+
expand_return (result);
+
+ expand_end_target_temps ();
+
current_function_returns_value = 1;
}
\f
/* 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;
/* Like comp_ptr_ttypes, for const_cast. */
-int
+static int
comp_ptr_ttypes_const (to, from)
tree to, from;
{
/* Like comp_ptr_ttypes, for reinterpret_cast. */
-int
+static int
comp_ptr_ttypes_reinterpret (to, from)
tree to, from;
{