/* 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.
#include "cp-tree.h"
#include "flags.h"
#include "output.h"
+#include "expr.h"
#ifdef HAVE_STRING_H
#include <string.h>
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));
+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));
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);
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:
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);
(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);
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;
}
}
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);
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, cp_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);
pedwarn ("ANSI C++ forbids comparison between pointer and integer");
}
break;
+
+ default:
+ break;
}
if ((code0 == INTEGER_TYPE || code0 == REAL_TYPE || code0 == COMPLEX_TYPE)
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)
{
/* & 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_NO_UNUSED_WARNING (compound) = 1;
return compound;
}
+
+ default:
+ break;
}
/* Complain about anything else that is not a true lvalue. */
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
return addr;
}
+
+ default:
+ break;
}
if (!errstring)
}
/* 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 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;
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);
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
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 ();
from warn_if_unused_value. */
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,
return result;
return cp_convert (TREE_TYPE (lhs), result);
}
+
+ default:
+ break;
}
/* Now we have handled acceptable kinds of LHS that are not truly lvalues.
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
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)
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
{
allconstant = TREE_CONSTANT (pfn);
allsimple = !! initializer_constant_valid_p (pfn, TREE_TYPE (pfn));
- u = tree_cons (pfn_field, pfn, NULL_TREE);
+ 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);
+ 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_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)
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.
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);
- }
- 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) == 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