#include "config.h"
#include "system.h"
#include "tree.h"
#include "c-tree.h"
#include "flags.h"
#include "output.h"
#include "rtl.h"
#include "expr.h"
#include "toplev.h"
#include "intl.h"
static int missing_braces_mentioned;
static tree qualify_type PROTO((tree, tree));
static int comp_target_types PROTO((tree, tree));
static int function_types_compatible_p PROTO((tree, tree));
static int type_lists_compatible_p PROTO((tree, tree));
static int self_promoting_type_p PROTO((tree));
static tree decl_constant_value PROTO((tree));
static tree lookup_field PROTO((tree, tree, tree *));
static tree convert_arguments PROTO((tree, tree, tree, tree));
static tree pointer_int_sum PROTO((enum tree_code, tree, tree));
static tree pointer_diff PROTO((tree, tree));
static tree unary_complex_lvalue PROTO((enum tree_code, tree));
static void pedantic_lvalue_warning PROTO((enum tree_code));
static tree internal_build_compound_expr PROTO((tree, int));
static tree convert_for_assignment PROTO((tree, tree, const char *, tree,
tree, int));
static void warn_for_assignment PROTO((const char *, const char *,
tree, int));
static tree valid_compound_expr_initializer PROTO((tree, tree));
static void push_string PROTO((const char *));
static void push_member_name PROTO((tree));
static void push_array_bounds PROTO((int));
static int spelling_length PROTO((void));
static char *print_spelling PROTO((char *));
static void warning_init PROTO((const char *));
static tree digest_init PROTO((tree, tree, int, int));
static void check_init_type_bitfields PROTO((tree));
static void output_init_element PROTO((tree, tree, tree, int));
static void output_pending_init_elements PROTO((int));
static void add_pending_init PROTO((tree, tree));
static int pending_init_member PROTO((tree));
tree
require_complete_type (value)
tree value;
{
tree type = TREE_TYPE (value);
if (TREE_CODE (value) == ERROR_MARK)
return error_mark_node;
if (TYPE_SIZE (type) != 0
&& type != void_type_node)
return value;
incomplete_type_error (value, type);
return error_mark_node;
}
void
incomplete_type_error (value, type)
tree value;
tree type;
{
const char *type_code_string;
if (TREE_CODE (type) == ERROR_MARK)
return;
if (value != 0 && (TREE_CODE (value) == VAR_DECL
|| TREE_CODE (value) == PARM_DECL))
error ("`%s' has an incomplete type",
IDENTIFIER_POINTER (DECL_NAME (value)));
else
{
retry:
switch (TREE_CODE (type))
{
case RECORD_TYPE:
type_code_string = "struct";
break;
case UNION_TYPE:
type_code_string = "union";
break;
case ENUMERAL_TYPE:
type_code_string = "enum";
break;
case VOID_TYPE:
error ("invalid use of void expression");
return;
case ARRAY_TYPE:
if (TYPE_DOMAIN (type))
{
type = TREE_TYPE (type);
goto retry;
}
error ("invalid use of array with unspecified bounds");
return;
default:
abort ();
}
if (TREE_CODE (TYPE_NAME (type)) == IDENTIFIER_NODE)
error ("invalid use of undefined type `%s %s'",
type_code_string, IDENTIFIER_POINTER (TYPE_NAME (type)));
else
error ("invalid use of incomplete typedef `%s'",
IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type))));
}
}
static tree
qualify_type (type, like)
tree type, like;
{
return c_build_qualified_type (type,
TYPE_QUALS (type) | TYPE_QUALS (like));
}
tree
common_type (t1, t2)
tree t1, t2;
{
register enum tree_code code1;
register enum tree_code code2;
tree attributes;
if (t1 == t2) return t1;
if (t1 == error_mark_node)
return t2;
if (t2 == error_mark_node)
return t1;
attributes = merge_machine_type_attributes (t1, t2);
if (TREE_CODE (t1) == ENUMERAL_TYPE)
t1 = type_for_size (TYPE_PRECISION (t1), 1);
if (TREE_CODE (t2) == ENUMERAL_TYPE)
t2 = type_for_size (TYPE_PRECISION (t2), 1);
code1 = TREE_CODE (t1);
code2 = TREE_CODE (t2);
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:
case REAL_TYPE:
if (code1 == REAL_TYPE && code2 != REAL_TYPE)
return build_type_attribute_variant (t1, attributes);
if (code2 == REAL_TYPE && code1 != REAL_TYPE)
return build_type_attribute_variant (t2, attributes);
if (TYPE_PRECISION (t1) > TYPE_PRECISION (t2))
return build_type_attribute_variant (t1, attributes);
else if (TYPE_PRECISION (t2) > TYPE_PRECISION (t1))
return build_type_attribute_variant (t2, attributes);
if (TYPE_MAIN_VARIANT (t1) == long_unsigned_type_node
|| TYPE_MAIN_VARIANT (t2) == long_unsigned_type_node)
return build_type_attribute_variant (long_unsigned_type_node,
attributes);
if (TYPE_MAIN_VARIANT (t1) == long_integer_type_node
|| TYPE_MAIN_VARIANT (t2) == long_integer_type_node)
{
if (TREE_UNSIGNED (t1) || TREE_UNSIGNED (t2))
t1 = long_unsigned_type_node;
else
t1 = long_integer_type_node;
return build_type_attribute_variant (t1, attributes);
}
if (TYPE_MAIN_VARIANT (t1) == long_double_type_node
|| TYPE_MAIN_VARIANT (t2) == long_double_type_node)
return build_type_attribute_variant (long_double_type_node,
attributes);
if (TREE_UNSIGNED (t1))
return build_type_attribute_variant (t1, attributes);
else
return build_type_attribute_variant (t2, attributes);
case POINTER_TYPE:
{
tree pointed_to_1 = TREE_TYPE (t1);
tree pointed_to_2 = TREE_TYPE (t2);
tree target = common_type (TYPE_MAIN_VARIANT (pointed_to_1),
TYPE_MAIN_VARIANT (pointed_to_2));
t1 = build_pointer_type (c_build_qualified_type
(target,
TYPE_QUALS (pointed_to_1) |
TYPE_QUALS (pointed_to_2)));
return build_type_attribute_variant (t1, attributes);
}
#if 0
t1 = build_pointer_type (common_type (TREE_TYPE (t1), TREE_TYPE (t2)));
return build_type_attribute_variant (t1, attributes);
#endif
case ARRAY_TYPE:
{
tree elt = common_type (TREE_TYPE (t1), TREE_TYPE (t2));
if (elt == TREE_TYPE (t1) && TYPE_DOMAIN (t1))
return build_type_attribute_variant (t1, attributes);
if (elt == TREE_TYPE (t2) && TYPE_DOMAIN (t2))
return build_type_attribute_variant (t2, attributes);
t1 = build_array_type (elt, TYPE_DOMAIN (TYPE_DOMAIN (t1) ? t1 : t2));
return build_type_attribute_variant (t1, attributes);
}
case FUNCTION_TYPE:
{
tree valtype = common_type (TREE_TYPE (t1), TREE_TYPE (t2));
tree p1 = TYPE_ARG_TYPES (t1);
tree p2 = TYPE_ARG_TYPES (t2);
int len;
tree newargs, n;
int i;
if (valtype == TREE_TYPE (t1) && ! TYPE_ARG_TYPES (t2))
return build_type_attribute_variant (t1, attributes);
if (valtype == TREE_TYPE (t2) && ! TYPE_ARG_TYPES (t1))
return build_type_attribute_variant (t2, attributes);
if (TYPE_ARG_TYPES (t1) == 0)
{
t1 = build_function_type (valtype, TYPE_ARG_TYPES (t2));
return build_type_attribute_variant (t1, attributes);
}
if (TYPE_ARG_TYPES (t2) == 0)
{
t1 = build_function_type (valtype, TYPE_ARG_TYPES (t1));
return build_type_attribute_variant (t1, attributes);
}
len = list_length (p1);
newargs = 0;
for (i = 0; i < len; i++)
newargs = tree_cons (NULL_TREE, NULL_TREE, newargs);
n = newargs;
for (; p1;
p1 = TREE_CHAIN (p1), p2 = TREE_CHAIN (p2), n = TREE_CHAIN (n))
{
if (TREE_VALUE (p1) == 0)
{
TREE_VALUE (n) = TREE_VALUE (p2);
goto parm_done;
}
if (TREE_VALUE (p2) == 0)
{
TREE_VALUE (n) = TREE_VALUE (p1);
goto parm_done;
}
if (TREE_CODE (TREE_VALUE (p1)) == UNION_TYPE
&& TREE_VALUE (p1) != TREE_VALUE (p2))
{
tree memb;
for (memb = TYPE_FIELDS (TREE_VALUE (p1));
memb; memb = TREE_CHAIN (memb))
if (comptypes (TREE_TYPE (memb), TREE_VALUE (p2)))
{
TREE_VALUE (n) = TREE_VALUE (p2);
if (pedantic)
pedwarn ("function types not truly compatible in ANSI C");
goto parm_done;
}
}
if (TREE_CODE (TREE_VALUE (p2)) == UNION_TYPE
&& TREE_VALUE (p2) != TREE_VALUE (p1))
{
tree memb;
for (memb = TYPE_FIELDS (TREE_VALUE (p2));
memb; memb = TREE_CHAIN (memb))
if (comptypes (TREE_TYPE (memb), TREE_VALUE (p1)))
{
TREE_VALUE (n) = TREE_VALUE (p1);
if (pedantic)
pedwarn ("function types not truly compatible in ANSI C");
goto parm_done;
}
}
TREE_VALUE (n) = common_type (TREE_VALUE (p1), TREE_VALUE (p2));
parm_done: ;
}
t1 = build_function_type (valtype, newargs);
}
default:
return build_type_attribute_variant (t1, attributes);
}
}
int
comptypes (type1, type2)
tree type1, type2;
{
register tree t1 = type1;
register tree t2 = type2;
int attrval, val;
if (t1 == t2 || !t1 || !t2
|| TREE_CODE (t1) == ERROR_MARK || TREE_CODE (t2) == ERROR_MARK)
return 1;
if (TREE_CODE (t1) == ENUMERAL_TYPE)
t1 = type_for_size (TYPE_PRECISION (t1), TREE_UNSIGNED (t1));
if (TREE_CODE (t2) == ENUMERAL_TYPE)
t2 = type_for_size (TYPE_PRECISION (t2), TREE_UNSIGNED (t2));
if (t1 == t2)
return 1;
if (TREE_CODE (t1) != TREE_CODE (t2)) return 0;
if (TYPE_QUALS (t1) != TYPE_QUALS (t2))
return 0;
if (TYPE_MAIN_VARIANT (t1) == TYPE_MAIN_VARIANT (t2))
return 1;
#ifndef COMP_TYPE_ATTRIBUTES
#define COMP_TYPE_ATTRIBUTES(t1,t2) 1
#endif
if (! (attrval = COMP_TYPE_ATTRIBUTES (t1, t2)))
return 0;
val = 0;
switch (TREE_CODE (t1))
{
case POINTER_TYPE:
val = (TREE_TYPE (t1) == TREE_TYPE (t2)
? 1 : comptypes (TREE_TYPE (t1), TREE_TYPE (t2)));
break;
case FUNCTION_TYPE:
val = function_types_compatible_p (t1, t2);
break;
case ARRAY_TYPE:
{
tree d1 = TYPE_DOMAIN (t1);
tree d2 = TYPE_DOMAIN (t2);
val = 1;
if (TREE_TYPE (t1) != TREE_TYPE (t2)
&& 0 == (val = comptypes (TREE_TYPE (t1), TREE_TYPE (t2))))
return 0;
if (d1 == 0 || d2 == 0 || d1 == d2
|| TREE_CODE (TYPE_MIN_VALUE (d1)) != INTEGER_CST
|| TREE_CODE (TYPE_MIN_VALUE (d2)) != INTEGER_CST
|| TREE_CODE (TYPE_MAX_VALUE (d1)) != INTEGER_CST
|| TREE_CODE (TYPE_MAX_VALUE (d2)) != INTEGER_CST)
break;
if (! ((TREE_INT_CST_LOW (TYPE_MIN_VALUE (d1))
== TREE_INT_CST_LOW (TYPE_MIN_VALUE (d2)))
&& (TREE_INT_CST_HIGH (TYPE_MIN_VALUE (d1))
== TREE_INT_CST_HIGH (TYPE_MIN_VALUE (d2)))
&& (TREE_INT_CST_LOW (TYPE_MAX_VALUE (d1))
== TREE_INT_CST_LOW (TYPE_MAX_VALUE (d2)))
&& (TREE_INT_CST_HIGH (TYPE_MAX_VALUE (d1))
== TREE_INT_CST_HIGH (TYPE_MAX_VALUE (d2)))))
val = 0;
break;
}
case RECORD_TYPE:
if (maybe_objc_comptypes (t1, t2, 0) == 1)
val = 1;
break;
default:
break;
}
return attrval == 2 && val == 1 ? 2 : val;
}
static int
comp_target_types (ttl, ttr)
tree ttl, ttr;
{
int val;
if ((val = maybe_objc_comptypes (ttl, ttr, 1)) >= 0)
return val;
#ifdef NEXT_SEMANTICS
if (! pedantic)
{
ttl = TYPE_MAIN_VARIANT (TREE_TYPE (ttl));
ttr = TYPE_MAIN_VARIANT (TREE_TYPE (ttr));
if (TREE_CODE (ttl) == POINTER_TYPE
&& TREE_CODE (ttr) == POINTER_TYPE)
return comp_target_types (ttl, ttr);
else
return comptypes (ttl, ttr);
}
#endif
val = comptypes (TYPE_MAIN_VARIANT (TREE_TYPE (ttl)),
TYPE_MAIN_VARIANT (TREE_TYPE (ttr)));
if (val == 2 && pedantic)
pedwarn ("types are not quite compatible");
return val;
}
static int
function_types_compatible_p (f1, f2)
tree f1, f2;
{
tree args1, args2;
int val = 1;
int val1;
if (!(TREE_TYPE (f1) == TREE_TYPE (f2)
|| (val = comptypes (TREE_TYPE (f1), TREE_TYPE (f2)))))
return 0;
args1 = TYPE_ARG_TYPES (f1);
args2 = TYPE_ARG_TYPES (f2);
if (args1 == 0)
{
if (!self_promoting_args_p (args2))
return 0;
if (TYPE_ACTUAL_ARG_TYPES (f1)
&& 1 != type_lists_compatible_p (args2, TYPE_ACTUAL_ARG_TYPES (f1)))
val = 2;
return val;
}
if (args2 == 0)
{
if (!self_promoting_args_p (args1))
return 0;
if (TYPE_ACTUAL_ARG_TYPES (f2)
&& 1 != type_lists_compatible_p (args1, TYPE_ACTUAL_ARG_TYPES (f2)))
val = 2;
return val;
}
val1 = type_lists_compatible_p (args1, args2);
return val1 != 1 ? val1 : val;
}
static int
type_lists_compatible_p (args1, args2)
tree args1, args2;
{
int val = 1;
int newval = 0;
while (1)
{
if (args1 == 0 && args2 == 0)
return val;
if (args1 == 0 || args2 == 0)
return 0;
if (TREE_VALUE (args1) == 0)
{
if (! self_promoting_type_p (TREE_VALUE (args2)))
return 0;
}
else if (TREE_VALUE (args2) == 0)
{
if (! self_promoting_type_p (TREE_VALUE (args1)))
return 0;
}
else if (! (newval = comptypes (TREE_VALUE (args1), TREE_VALUE (args2))))
{
if (TREE_CODE (TREE_VALUE (args1)) == UNION_TYPE
&& (TYPE_NAME (TREE_VALUE (args1)) == 0
|| TYPE_TRANSPARENT_UNION (TREE_VALUE (args1)))
&& TREE_CODE (TYPE_SIZE (TREE_VALUE (args1))) == INTEGER_CST
&& tree_int_cst_equal (TYPE_SIZE (TREE_VALUE (args1)),
TYPE_SIZE (TREE_VALUE (args2))))
{
tree memb;
for (memb = TYPE_FIELDS (TREE_VALUE (args1));
memb; memb = TREE_CHAIN (memb))
if (comptypes (TREE_TYPE (memb), TREE_VALUE (args2)))
break;
if (memb == 0)
return 0;
}
else if (TREE_CODE (TREE_VALUE (args2)) == UNION_TYPE
&& (TYPE_NAME (TREE_VALUE (args2)) == 0
|| TYPE_TRANSPARENT_UNION (TREE_VALUE (args2)))
&& TREE_CODE (TYPE_SIZE (TREE_VALUE (args2))) == INTEGER_CST
&& tree_int_cst_equal (TYPE_SIZE (TREE_VALUE (args2)),
TYPE_SIZE (TREE_VALUE (args1))))
{
tree memb;
for (memb = TYPE_FIELDS (TREE_VALUE (args2));
memb; memb = TREE_CHAIN (memb))
if (comptypes (TREE_TYPE (memb), TREE_VALUE (args1)))
break;
if (memb == 0)
return 0;
}
else
return 0;
}
if (newval > val)
val = newval;
args1 = TREE_CHAIN (args1);
args2 = TREE_CHAIN (args2);
}
}
int
self_promoting_args_p (parms)
tree parms;
{
register tree t;
for (t = parms; t; t = TREE_CHAIN (t))
{
register tree type = TREE_VALUE (t);
if (TREE_CHAIN (t) == 0 && type != void_type_node)
return 0;
if (type == 0)
return 0;
if (TYPE_MAIN_VARIANT (type) == float_type_node)
return 0;
if (C_PROMOTING_INTEGER_TYPE_P (type))
return 0;
}
return 1;
}
static int
self_promoting_type_p (type)
tree type;
{
if (TYPE_MAIN_VARIANT (type) == float_type_node)
return 0;
if (C_PROMOTING_INTEGER_TYPE_P (type))
return 0;
return 1;
}
tree
unsigned_type (type)
tree type;
{
tree type1 = TYPE_MAIN_VARIANT (type);
if (type1 == signed_char_type_node || type1 == char_type_node)
return unsigned_char_type_node;
if (type1 == integer_type_node)
return unsigned_type_node;
if (type1 == short_integer_type_node)
return short_unsigned_type_node;
if (type1 == long_integer_type_node)
return long_unsigned_type_node;
if (type1 == long_long_integer_type_node)
return long_long_unsigned_type_node;
if (type1 == intDI_type_node)
return unsigned_intDI_type_node;
if (type1 == intSI_type_node)
return unsigned_intSI_type_node;
if (type1 == intHI_type_node)
return unsigned_intHI_type_node;
if (type1 == intQI_type_node)
return unsigned_intQI_type_node;
return signed_or_unsigned_type (1, type);
}
tree
signed_type (type)
tree type;
{
tree type1 = TYPE_MAIN_VARIANT (type);
if (type1 == unsigned_char_type_node || type1 == char_type_node)
return signed_char_type_node;
if (type1 == unsigned_type_node)
return integer_type_node;
if (type1 == short_unsigned_type_node)
return short_integer_type_node;
if (type1 == long_unsigned_type_node)
return long_integer_type_node;
if (type1 == long_long_unsigned_type_node)
return long_long_integer_type_node;
if (type1 == unsigned_intDI_type_node)
return intDI_type_node;
if (type1 == unsigned_intSI_type_node)
return intSI_type_node;
if (type1 == unsigned_intHI_type_node)
return intHI_type_node;
if (type1 == unsigned_intQI_type_node)
return intQI_type_node;
return signed_or_unsigned_type (0, type);
}
tree
signed_or_unsigned_type (unsignedp, type)
int unsignedp;
tree type;
{
if ((! INTEGRAL_TYPE_P (type) && ! POINTER_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))
return unsignedp ? unsigned_type_node : integer_type_node;
if (TYPE_PRECISION (type) == TYPE_PRECISION (short_integer_type_node))
return unsignedp ? short_unsigned_type_node : short_integer_type_node;
if (TYPE_PRECISION (type) == TYPE_PRECISION (long_integer_type_node))
return unsignedp ? long_unsigned_type_node : long_integer_type_node;
if (TYPE_PRECISION (type) == TYPE_PRECISION (long_long_integer_type_node))
return (unsignedp ? long_long_unsigned_type_node
: long_long_integer_type_node);
return type;
}
tree
build_vector_constant (type, values)
tree type;
tree values;
{
tree vtype;
tree valarray[16], valtail;
int valnum, elements;
vtype = TREE_TYPE (type);
elements = (TREE_INT_CST_LOW (TYPE_SIZE (type))
/ TREE_INT_CST_LOW (TYPE_SIZE (vtype)));
for (valtail = values, valnum = 0;
valtail;
valtail = TREE_CHAIN (valtail), valnum++)
{
register tree val = TREE_VALUE (valtail);
STRIP_NOPS (val);
if (TREE_CODE (val) != INTEGER_CST && TREE_CODE (val) != REAL_CST)
{
error("expected a constant expression");
return error_mark_node;
}
valarray[valnum] = convert_for_assignment (vtype, val, "assignment",
NULL_TREE, NULL_TREE, 0);
}
if (valnum != 1 && valnum != elements)
{
error (valnum < elements
? "too few initializers" : "too many initializers");
return error_mark_node;
}
while (valnum < elements)
valarray[valnum++] = valarray[0];
while (elements > 4)
{
int i, j;
for (i = 2, j = 0; i <= elements; i += 2, j++)
{
unsigned HOST_WIDE_INT a = TREE_INT_CST_LOW (valarray[i-2]);
unsigned HOST_WIDE_INT b = TREE_INT_CST_LOW (valarray[i-1]);
int bits = 128 / elements;
valarray[j] = build_int_2 ((a << bits) | (b & ((1 << bits) - 1)),
0);
}
elements /= 2;
}
return build_vector (type, valarray[0], valarray[1],
valarray[2], valarray[3]);
}
tree
c_sizeof (type)
tree type;
{
enum tree_code code = TREE_CODE (type);
tree t;
if (code == FUNCTION_TYPE)
{
if (pedantic || warn_pointer_arith)
pedwarn ("sizeof applied to a function type");
return size_int (1);
}
if (code == VOID_TYPE)
{
if (pedantic || warn_pointer_arith)
pedwarn ("sizeof applied to a void type");
return size_int (1);
}
if (code == ERROR_MARK)
return size_int (1);
if (TYPE_SIZE (type) == 0)
{
error ("sizeof applied to an incomplete type");
return size_int (0);
}
t = size_binop (CEIL_DIV_EXPR, TYPE_SIZE (type),
size_int (TYPE_PRECISION (char_type_node)));
t = convert (sizetype, t);
if (TREE_CODE (t) == INTEGER_CST && force_fit_type (t, 0))
TREE_CONSTANT_OVERFLOW (t) = TREE_OVERFLOW (t) = 1;
return t;
}
tree
c_sizeof_nowarn (type)
tree type;
{
enum tree_code code = TREE_CODE (type);
tree t;
if (code == FUNCTION_TYPE
|| code == VOID_TYPE
|| code == ERROR_MARK)
return size_int (1);
if (TYPE_SIZE (type) == 0)
return size_int (0);
t = size_binop (CEIL_DIV_EXPR, TYPE_SIZE (type),
size_int (TYPE_PRECISION (char_type_node)));
t = convert (sizetype, t);
force_fit_type (t, 0);
return t;
}
tree
c_size_in_bytes (type)
tree type;
{
enum tree_code code = TREE_CODE (type);
tree t;
if (code == FUNCTION_TYPE)
return size_int (1);
if (code == VOID_TYPE)
return size_int (1);
if (code == ERROR_MARK)
return size_int (1);
if (TYPE_SIZE (type) == 0)
{
error ("arithmetic on pointer to an incomplete type");
return size_int (1);
}
t = size_binop (CEIL_DIV_EXPR, TYPE_SIZE (type),
size_int (BITS_PER_UNIT));
t = convert (sizetype, t);
force_fit_type (t, 0);
return t;
}
tree
c_alignof (type)
tree type;
{
enum tree_code code = TREE_CODE (type);
if (code == FUNCTION_TYPE)
return size_int (FUNCTION_BOUNDARY / BITS_PER_UNIT);
if (code == VOID_TYPE || code == ERROR_MARK)
return size_int (1);
if (TYPE_SIZE (type) == 0)
{
warning ("__alignof applied to an incomplete type");
return size_int (1);
}
return size_int (TYPE_ALIGN (type) / BITS_PER_UNIT);
}
tree
c_alignof_expr (expr)
tree expr;
{
if (TREE_CODE (expr) == VAR_DECL)
return size_int (DECL_ALIGN (expr) / BITS_PER_UNIT);
if (TREE_CODE (expr) == COMPONENT_REF
&& DECL_C_BIT_FIELD (TREE_OPERAND (expr, 1)))
{
error ("`__alignof' applied to a bit-field");
return size_int (1);
}
else if (TREE_CODE (expr) == COMPONENT_REF
&& TREE_CODE (TREE_OPERAND (expr, 1)) == FIELD_DECL)
return size_int (DECL_ALIGN (TREE_OPERAND (expr, 1)) / BITS_PER_UNIT);
if (TREE_CODE (expr) == INDIRECT_REF)
{
tree t = TREE_OPERAND (expr, 0);
tree best = t;
int bestalign = TYPE_ALIGN (TREE_TYPE (TREE_TYPE (t)));
while (TREE_CODE (t) == NOP_EXPR
&& TREE_CODE (TREE_TYPE (TREE_OPERAND (t, 0))) == POINTER_TYPE)
{
int thisalign;
t = TREE_OPERAND (t, 0);
thisalign = TYPE_ALIGN (TREE_TYPE (TREE_TYPE (t)));
if (thisalign > bestalign)
best = t, bestalign = thisalign;
}
return c_alignof (TREE_TYPE (TREE_TYPE (best)));
}
else
return c_alignof (TREE_TYPE (expr));
}
tree
c_vec_step (type)
tree type;
{
enum tree_code code = TREE_CODE (type);
if (code != VECTOR_TYPE)
{
error ("operand of `vec_step' must be a vector type");
return size_int (0);
}
return size_binop (CEIL_DIV_EXPR, size_int (16),
c_sizeof (TREE_TYPE (type)));
}
tree
c_vec_step_expr (expr)
tree expr;
{
return c_vec_step (TREE_TYPE (expr));
}
static tree
decl_constant_value (decl)
tree decl;
{
if (
current_function_decl != 0
&& ! pedantic
&& ! TREE_THIS_VOLATILE (decl)
&& TREE_READONLY (decl) && ! ITERATOR_P (decl)
&& DECL_INITIAL (decl) != 0
&& TREE_CODE (DECL_INITIAL (decl)) != ERROR_MARK
&& TREE_CONSTANT (DECL_INITIAL (decl))
&& TREE_CODE (DECL_INITIAL (decl)) != CONSTRUCTOR
&& DECL_MODE (decl) != BLKmode)
return DECL_INITIAL (decl);
return decl;
}
tree
default_conversion (exp)
tree exp;
{
register tree type = TREE_TYPE (exp);
register enum tree_code code = TREE_CODE (type);
if (TREE_CODE (exp) == CONST_DECL)
exp = DECL_INITIAL (exp);
else if (optimize && TREE_CODE (exp) == VAR_DECL && code != ARRAY_TYPE)
{
exp = decl_constant_value (exp);
type = TREE_TYPE (exp);
}
while (TREE_CODE (exp) == NON_LVALUE_EXPR
|| (TREE_CODE (exp) == NOP_EXPR
&& TREE_TYPE (TREE_OPERAND (exp, 0)) == TREE_TYPE (exp)))
exp = TREE_OPERAND (exp, 0);
if (code == ENUMERAL_TYPE)
{
type = type_for_size (MAX (TYPE_PRECISION (type),
TYPE_PRECISION (integer_type_node)),
((flag_traditional
|| (TYPE_PRECISION (type)
>= TYPE_PRECISION (integer_type_node)))
&& TREE_UNSIGNED (type)));
return convert (type, exp);
}
if (TREE_CODE (exp) == COMPONENT_REF
&& DECL_C_BIT_FIELD (TREE_OPERAND (exp, 1)))
{
tree width = DECL_SIZE (TREE_OPERAND (exp, 1));
HOST_WIDE_INT low = TREE_INT_CST_LOW (width);
if (low < TYPE_PRECISION (integer_type_node))
{
if (flag_traditional && TREE_UNSIGNED (type))
return convert (unsigned_type_node, exp);
else
return convert (integer_type_node, exp);
}
}
if (C_PROMOTING_INTEGER_TYPE_P (type))
{
if (TREE_UNSIGNED (type)
&& (flag_traditional
|| TYPE_PRECISION (type) == TYPE_PRECISION (integer_type_node)))
return convert (unsigned_type_node, exp);
return convert (integer_type_node, exp);
}
if (flag_traditional && !flag_allow_single_precision
&& TYPE_MAIN_VARIANT (type) == float_type_node)
return convert (double_type_node, exp);
if (code == VOID_TYPE)
{
error ("void value not ignored as it ought to be");
return error_mark_node;
}
if (code == FUNCTION_TYPE)
{
return build_unary_op (ADDR_EXPR, exp, 0);
}
if (code == ARRAY_TYPE)
{
register tree adr;
tree restype = TREE_TYPE (type);
tree ptrtype;
int constp = 0;
int volatilep = 0;
if (TREE_CODE_CLASS (TREE_CODE (exp)) == 'r'
|| TREE_CODE_CLASS (TREE_CODE (exp)) == 'd')
{
constp = TREE_READONLY (exp);
volatilep = TREE_THIS_VOLATILE (exp);
}
if (TYPE_QUALS (type) || constp || volatilep)
restype
= c_build_qualified_type (restype,
TYPE_QUALS (type)
| (constp * TYPE_QUAL_CONST)
| (volatilep * TYPE_QUAL_VOLATILE));
if (TREE_CODE (exp) == INDIRECT_REF)
return convert (TYPE_POINTER_TO (restype),
TREE_OPERAND (exp, 0));
if (TREE_CODE (exp) == COMPOUND_EXPR)
{
tree op1 = default_conversion (TREE_OPERAND (exp, 1));
return build (COMPOUND_EXPR, TREE_TYPE (op1),
TREE_OPERAND (exp, 0), op1);
}
if (! lvalue_p (exp)
&& ! (TREE_CODE (exp) == CONSTRUCTOR && TREE_STATIC (exp)))
{
error ("invalid use of non-lvalue array");
return error_mark_node;
}
ptrtype = build_pointer_type (restype);
if (TREE_CODE (exp) == VAR_DECL)
{
adr = build1 (ADDR_EXPR, ptrtype, exp);
if (mark_addressable (exp) == 0)
return error_mark_node;
TREE_CONSTANT (adr) = staticp (exp);
TREE_SIDE_EFFECTS (adr) = 0;
return adr;
}
adr = build_unary_op (ADDR_EXPR, exp, 1);
return convert (ptrtype, adr);
}
return exp;
}
static tree
lookup_field (type, component, indirect)
tree type, component;
tree *indirect;
{
tree field;
if (TYPE_LANG_SPECIFIC (type))
{
int bot, top, half;
tree *field_array = &TYPE_LANG_SPECIFIC (type)->elts[0];
field = TYPE_FIELDS (type);
bot = 0;
top = TYPE_LANG_SPECIFIC (type)->len;
while (top - bot > 1)
{
half = (top - bot + 1) >> 1;
field = field_array[bot+half];
if (DECL_NAME (field) == NULL_TREE)
{
while (DECL_NAME (field_array[bot]) == NULL_TREE)
{
tree anon = 0, junk;
field = field_array[bot++];
if (TREE_CODE (TREE_TYPE (field)) == RECORD_TYPE
|| TREE_CODE (TREE_TYPE (field)) == UNION_TYPE)
anon = lookup_field (TREE_TYPE (field), component, &junk);
if (anon != NULL_TREE)
{
*indirect = field;
return anon;
}
}
if (bot > top)
return NULL_TREE;
continue;
}
if (DECL_NAME (field) == component)
break;
if (DECL_NAME (field) < component)
bot += half;
else
top = bot + half;
}
if (DECL_NAME (field_array[bot]) == component)
field = field_array[bot];
else if (DECL_NAME (field) != component)
field = 0;
}
else
{
for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
{
if (DECL_NAME (field) == NULL_TREE)
{
tree junk;
tree anon = 0;
if (TREE_CODE (TREE_TYPE (field)) == RECORD_TYPE
|| TREE_CODE (TREE_TYPE (field)) == UNION_TYPE)
anon = lookup_field (TREE_TYPE (field), component, &junk);
if (anon != NULL_TREE)
{
*indirect = field;
return anon;
}
}
if (DECL_NAME (field) == component)
break;
}
}
*indirect = NULL_TREE;
return field;
}
tree
build_component_ref (datum, component)
tree datum, component;
{
register tree type = TREE_TYPE (datum);
register enum tree_code code = TREE_CODE (type);
register tree field = NULL;
register tree ref;
switch (TREE_CODE (datum))
{
case COMPOUND_EXPR:
{
tree value = build_component_ref (TREE_OPERAND (datum, 1), component);
return build (COMPOUND_EXPR, TREE_TYPE (value),
TREE_OPERAND (datum, 0), value);
}
case COND_EXPR:
return build_conditional_expr
(TREE_OPERAND (datum, 0),
build_component_ref (TREE_OPERAND (datum, 1), component),
build_component_ref (TREE_OPERAND (datum, 2), component));
default:
break;
}
if (code == RECORD_TYPE || code == UNION_TYPE)
{
tree indirect = 0;
if (TYPE_SIZE (type) == 0)
{
incomplete_type_error (NULL_TREE, type);
return error_mark_node;
}
field = lookup_field (type, component, &indirect);
if (!field)
{
error (code == RECORD_TYPE
? "structure has no member named `%s'"
: "union has no member named `%s'",
IDENTIFIER_POINTER (component));
return error_mark_node;
}
if (TREE_TYPE (field) == error_mark_node)
return error_mark_node;
if (indirect != 0)
{
ref = build (COMPONENT_REF, TREE_TYPE (indirect), datum, indirect);
if (TREE_READONLY (datum) || TREE_READONLY (indirect))
TREE_READONLY (ref) = 1;
if (TREE_THIS_VOLATILE (datum) || TREE_THIS_VOLATILE (indirect))
TREE_THIS_VOLATILE (ref) = 1;
datum = ref;
}
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;
return ref;
}
else if (code != ERROR_MARK)
error ("request for member `%s' in something not a structure or union",
IDENTIFIER_POINTER (component));
return error_mark_node;
}
tree
build_indirect_ref (ptr, errorstring)
tree ptr;
const char *errorstring;
{
register tree pointer = default_conversion (ptr);
register tree type = TREE_TYPE (pointer);
if (TREE_CODE (type) == POINTER_TYPE)
{
if (TREE_CODE (pointer) == ADDR_EXPR
&& !flag_volatile
&& (TREE_TYPE (TREE_OPERAND (pointer, 0))
== TREE_TYPE (type)))
return TREE_OPERAND (pointer, 0);
else
{
tree t = TREE_TYPE (type);
register tree ref = build1 (INDIRECT_REF,
TYPE_MAIN_VARIANT (t), pointer);
if (TYPE_SIZE (t) == 0 && TREE_CODE (t) != ARRAY_TYPE)
{
#ifdef NEXT_SEMANTICS
require_complete_type (type);
#endif
error ("dereferencing pointer to incomplete type");
return error_mark_node;
}
if (TREE_CODE (t) == VOID_TYPE && skip_evaluation == 0)
warning ("dereferencing `void *' pointer");
TREE_READONLY (ref) = TYPE_READONLY (t);
TREE_SIDE_EFFECTS (ref)
= TYPE_VOLATILE (t) || TREE_SIDE_EFFECTS (pointer) || flag_volatile;
TREE_THIS_VOLATILE (ref) = TYPE_VOLATILE (t);
return ref;
}
}
else if (TREE_CODE (pointer) != ERROR_MARK)
error ("invalid type argument of `%s'", errorstring);
return error_mark_node;
}
tree
build_array_ref (array, index)
tree array, index;
{
if (index == 0)
{
error ("subscript missing in array reference");
return error_mark_node;
}
if (TREE_TYPE (array) == error_mark_node
|| TREE_TYPE (index) == error_mark_node)
return error_mark_node;
if (TREE_CODE (TREE_TYPE (array)) == ARRAY_TYPE
&& TREE_CODE (array) != INDIRECT_REF)
{
tree rval, type;
if (warn_char_subscripts
&& TYPE_MAIN_VARIANT (TREE_TYPE (index)) == char_type_node)
warning ("array subscript has type `char'");
index = default_conversion (index);
if (TREE_CODE (TREE_TYPE (index)) != INTEGER_TYPE)
{
error ("array subscript is not an integer");
return error_mark_node;
}
if (TREE_CODE (index) != INTEGER_CST
|| (TYPE_SIZE (TREE_TYPE (TREE_TYPE (array))) != 0
&& TREE_CODE (TYPE_SIZE (TREE_TYPE (TREE_TYPE (array)))) != INTEGER_CST))
{
if (mark_addressable (array) == 0)
return error_mark_node;
}
if (TREE_CODE (index) == INTEGER_CST
&& TYPE_VALUES (TREE_TYPE (array))
&& ! int_fits_type_p (index, TYPE_VALUES (TREE_TYPE (array))))
{
if (mark_addressable (array) == 0)
return error_mark_node;
}
if (pedantic && !lvalue_p (array))
{
if (DECL_REGISTER (array))
pedwarn ("ANSI C forbids subscripting `register' array");
else
pedwarn ("ANSI C forbids subscripting non-lvalue array");
}
if (pedantic)
{
tree foo = array;
while (TREE_CODE (foo) == COMPONENT_REF)
foo = TREE_OPERAND (foo, 0);
if (TREE_CODE (foo) == VAR_DECL && DECL_REGISTER (foo))
pedwarn ("ANSI C forbids subscripting non-lvalue array");
}
type = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (array)));
rval = build (ARRAY_REF, type, array, index);
TREE_READONLY (rval)
|= (TYPE_READONLY (TREE_TYPE (TREE_TYPE (array)))
| TREE_READONLY (array));
TREE_SIDE_EFFECTS (rval)
|= (TYPE_VOLATILE (TREE_TYPE (TREE_TYPE (array)))
| TREE_SIDE_EFFECTS (array));
TREE_THIS_VOLATILE (rval)
|= (TYPE_VOLATILE (TREE_TYPE (TREE_TYPE (array)))
| TREE_THIS_VOLATILE (array));
return require_complete_type (fold (rval));
}
{
tree ar = default_conversion (array);
tree ind = default_conversion (index);
if (warn_char_subscripts
&& TREE_CODE (TREE_TYPE (index)) == INTEGER_TYPE
&& TYPE_MAIN_VARIANT (TREE_TYPE (index)) == char_type_node)
warning ("subscript has type `char'");
if (TREE_CODE (TREE_TYPE (ar)) == INTEGER_TYPE)
{
tree temp = ar;
ar = ind;
ind = temp;
}
if (ar == error_mark_node)
return ar;
if (TREE_CODE (TREE_TYPE (ar)) != POINTER_TYPE
|| TREE_CODE (TREE_TYPE (TREE_TYPE (ar))) == FUNCTION_TYPE)
{
error ("subscripted value is neither array nor pointer");
return error_mark_node;
}
if (TREE_CODE (TREE_TYPE (ind)) != INTEGER_TYPE)
{
error ("array subscript is not an integer");
return error_mark_node;
}
return build_indirect_ref (build_binary_op (PLUS_EXPR, ar, ind, 0),
"array indexing");
}
}
tree
build_function_call (function, params)
tree function, params;
{
register tree fntype, fundecl = 0;
register tree coerced_params;
tree name = NULL_TREE, assembler_name = NULL_TREE;
STRIP_TYPE_NOPS (function);
if (TREE_CODE (function) == FUNCTION_DECL
&& DECL_TARGET_OVERLOADED_INTRINSIC_P (function))
{
#ifdef SELECT_TARGET_OVERLOADED_INTRINSIC
function = SELECT_TARGET_OVERLOADED_INTRINSIC (function, params);
if (function == NULL_TREE)
#endif
return error_mark_node;
}
if (TREE_CODE (function) == FUNCTION_DECL)
{
name = DECL_NAME (function);
assembler_name = DECL_ASSEMBLER_NAME (function);
fntype = build_type_variant (TREE_TYPE (function),
TREE_READONLY (function),
TREE_THIS_VOLATILE (function));
fundecl = function;
function = build1 (ADDR_EXPR, build_pointer_type (fntype), function);
}
else
function = default_conversion (function);
fntype = TREE_TYPE (function);
if (TREE_CODE (fntype) == ERROR_MARK)
return error_mark_node;
if (!(TREE_CODE (fntype) == POINTER_TYPE
&& TREE_CODE (TREE_TYPE (fntype)) == FUNCTION_TYPE))
{
error ("called object is not a function");
return error_mark_node;
}
fntype = TREE_TYPE (fntype);
coerced_params
= convert_arguments (TYPE_ARG_TYPES (fntype), params, name, fundecl);
if (warn_format && (name || assembler_name))
check_function_format (name, assembler_name, coerced_params);
if (TREE_CODE (function) == ADDR_EXPR
&& TREE_CODE (TREE_OPERAND (function, 0)) == FUNCTION_DECL
&& DECL_BUILT_IN (TREE_OPERAND (function, 0)))
switch (DECL_FUNCTION_CODE (TREE_OPERAND (function, 0)))
{
case BUILT_IN_ABS:
case BUILT_IN_LABS:
case BUILT_IN_FABS:
if (coerced_params == 0)
return integer_zero_node;
return build_unary_op (ABS_EXPR, TREE_VALUE (coerced_params), 0);
default:
break;
}
{
register tree result
= build (CALL_EXPR, TREE_TYPE (fntype),
function, coerced_params, NULL_TREE);
TREE_SIDE_EFFECTS (result) = 1;
if (TREE_TYPE (result) == void_type_node)
return result;
return require_complete_type (result);
}
}
static tree
convert_arguments (typelist, values, name, fundecl)
tree typelist, values, name, fundecl;
{
register tree typetail, valtail;
register tree result = NULL;
int parmnum;
for (valtail = values, typetail = typelist, parmnum = 0;
valtail;
valtail = TREE_CHAIN (valtail), parmnum++)
{
register tree type = typetail ? TREE_VALUE (typetail) : 0;
register tree val = TREE_VALUE (valtail);
if (type == void_type_node)
{
if (name)
error ("too many arguments to function `%s'",
IDENTIFIER_POINTER (name));
else
error ("too many arguments to function");
break;
}
if (TREE_CODE (val) == NON_LVALUE_EXPR)
val = TREE_OPERAND (val, 0);
if (TREE_CODE (TREE_TYPE (val)) == ARRAY_TYPE
|| TREE_CODE (TREE_TYPE (val)) == FUNCTION_TYPE)
val = default_conversion (val);
val = require_complete_type (val);
if (typelist == 0
&& TREE_CODE (TREE_TYPE (val)) == VECTOR_TYPE
&& !(DECL_BUILT_IN (fundecl)
&& (DECL_FUNCTION_CODE (fundecl) == BUILT_IN_NEXT_ARG
|| DECL_FUNCTION_CODE (fundecl) == BUILT_IN_CLASSIFY_TYPE)))
error ("vector argument %d requires a prototype for `%s'",
parmnum + 1, IDENTIFIER_POINTER (name));
if (type != 0)
{
tree parmval;
if (TYPE_SIZE (type) == 0)
{
error ("type of formal parameter %d is incomplete", parmnum + 1);
parmval = val;
}
else
{
if (warn_conversion)
{
int formal_prec = TYPE_PRECISION (type);
if (INTEGRAL_TYPE_P (type)
&& TREE_CODE (TREE_TYPE (val)) == REAL_TYPE)
warn_for_assignment ("%s as integer rather than floating due to prototype", (char *) 0, name, parmnum + 1);
else if (TREE_CODE (type) == COMPLEX_TYPE
&& TREE_CODE (TREE_TYPE (val)) == REAL_TYPE)
warn_for_assignment ("%s as complex rather than floating due to prototype", (char *) 0, name, parmnum + 1);
else if (TREE_CODE (type) == REAL_TYPE
&& INTEGRAL_TYPE_P (TREE_TYPE (val)))
warn_for_assignment ("%s as floating rather than integer due to prototype", (char *) 0, name, parmnum + 1);
else if (TREE_CODE (type) == REAL_TYPE
&& TREE_CODE (TREE_TYPE (val)) == COMPLEX_TYPE)
warn_for_assignment ("%s as floating rather than complex due to prototype", (char *) 0, name, parmnum + 1);
else if (TREE_CODE (type) == REAL_TYPE
&& TREE_CODE (TREE_TYPE (val)) == REAL_TYPE)
{
if (formal_prec == TYPE_PRECISION (float_type_node))
warn_for_assignment ("%s as `float' rather than `double' due to prototype", (char *) 0, name, parmnum + 1);
}
else if (INTEGRAL_TYPE_P (type)
&& INTEGRAL_TYPE_P (TREE_TYPE (val)))
{
tree would_have_been = default_conversion (val);
tree type1 = TREE_TYPE (would_have_been);
if (TREE_CODE (type) == ENUMERAL_TYPE
&& type == TREE_TYPE (val))
;
else if (formal_prec != TYPE_PRECISION (type1))
warn_for_assignment ("%s with different width due to prototype", (char *) 0, name, parmnum + 1);
else if (TREE_UNSIGNED (type) == TREE_UNSIGNED (type1))
;
else if (TREE_CODE (type) == ENUMERAL_TYPE)
;
else if (TREE_CODE (val) == INTEGER_CST
&& int_fits_type_p (val, type))
;
else if (TREE_CODE (val) == NOP_EXPR
&& TREE_CODE (TREE_OPERAND (val, 0)) == INTEGER_CST
&& int_fits_type_p (TREE_OPERAND (val, 0), type))
;
#if 0
else if (TREE_CODE (TREE_TYPE (val)) == ENUMERAL_TYPE
&& int_fits_type_p (TYPE_MIN_VALUE (TREE_TYPE (val)), type)
&& int_fits_type_p (TYPE_MAX_VALUE (TREE_TYPE (val)), type))
;
#endif
else if (TYPE_PRECISION (TREE_TYPE (val)) < TYPE_PRECISION (type)
&& TREE_UNSIGNED (TREE_TYPE (val)))
;
else if (TREE_UNSIGNED (type))
warn_for_assignment ("%s as unsigned due to prototype", (char *) 0, name, parmnum + 1);
else
warn_for_assignment ("%s as signed due to prototype", (char *) 0, name, parmnum + 1);
}
}
parmval = convert_for_assignment (type, val,
(char *) 0,
fundecl, name, parmnum + 1);
#ifdef PROMOTE_PROTOTYPES
if ((TREE_CODE (type) == INTEGER_TYPE
|| TREE_CODE (type) == ENUMERAL_TYPE)
&& (TYPE_PRECISION (type) < TYPE_PRECISION (integer_type_node)))
parmval = default_conversion (parmval);
#endif
}
result = tree_cons (NULL_TREE, parmval, result);
}
else if (TREE_CODE (TREE_TYPE (val)) == REAL_TYPE
&& (TYPE_PRECISION (TREE_TYPE (val))
< TYPE_PRECISION (double_type_node)))
result = tree_cons (NULL_TREE, convert (double_type_node, val), result);
else
result = tree_cons (NULL_TREE, default_conversion (val), result);
if (typetail)
typetail = TREE_CHAIN (typetail);
}
if (typetail != 0 && TREE_VALUE (typetail) != void_type_node)
{
if (name)
error ("too few arguments to function `%s'",
IDENTIFIER_POINTER (name));
else
error ("too few arguments to function");
}
return nreverse (result);
}
tree
parser_build_binary_op (code, arg1, arg2)
enum tree_code code;
tree arg1, arg2;
{
tree result = build_binary_op (code, arg1, arg2, 1);
char class;
char class1 = TREE_CODE_CLASS (TREE_CODE (arg1));
char class2 = TREE_CODE_CLASS (TREE_CODE (arg2));
enum tree_code code1 = ERROR_MARK;
enum tree_code code2 = ERROR_MARK;
if (class1 == 'e' || class1 == '1'
|| class1 == '2' || class1 == '<')
code1 = C_EXP_ORIGINAL_CODE (arg1);
if (class2 == 'e' || class2 == '1'
|| class2 == '2' || class2 == '<')
code2 = C_EXP_ORIGINAL_CODE (arg2);
if (warn_parentheses)
{
if (code == LSHIFT_EXPR || code == RSHIFT_EXPR)
{
if (code1 == PLUS_EXPR || code1 == MINUS_EXPR
|| code2 == PLUS_EXPR || code2 == MINUS_EXPR)
warning ("suggest parentheses around + or - inside shift");
}
if (code == TRUTH_ORIF_EXPR)
{
if (code1 == TRUTH_ANDIF_EXPR
|| code2 == TRUTH_ANDIF_EXPR)
warning ("suggest parentheses around && within ||");
}
if (code == BIT_IOR_EXPR)
{
if (code1 == BIT_AND_EXPR || code1 == BIT_XOR_EXPR
|| code1 == PLUS_EXPR || code1 == MINUS_EXPR
|| code2 == BIT_AND_EXPR || code2 == BIT_XOR_EXPR
|| code2 == PLUS_EXPR || code2 == MINUS_EXPR)
warning ("suggest parentheses around arithmetic in operand of |");
if (TREE_CODE_CLASS (code1) == '<' || TREE_CODE_CLASS (code2) == '<')
warning ("suggest parentheses around comparison in operand of |");
}
if (code == BIT_XOR_EXPR)
{
if (code1 == BIT_AND_EXPR
|| code1 == PLUS_EXPR || code1 == MINUS_EXPR
|| code2 == BIT_AND_EXPR
|| code2 == PLUS_EXPR || code2 == MINUS_EXPR)
warning ("suggest parentheses around arithmetic in operand of ^");
if (TREE_CODE_CLASS (code1) == '<' || TREE_CODE_CLASS (code2) == '<')
warning ("suggest parentheses around comparison in operand of ^");
}
if (code == BIT_AND_EXPR)
{
if (code1 == PLUS_EXPR || code1 == MINUS_EXPR
|| code2 == PLUS_EXPR || code2 == MINUS_EXPR)
warning ("suggest parentheses around + or - in operand of &");
if (TREE_CODE_CLASS (code1) == '<' || TREE_CODE_CLASS (code2) == '<')
warning ("suggest parentheses around comparison in operand of &");
}
}
if (TREE_CODE_CLASS (code) == '<' && extra_warnings
&& (TREE_CODE_CLASS (code1) == '<' || TREE_CODE_CLASS (code2) == '<'))
warning ("comparisons like X<=Y<=Z do not have their mathematical meaning");
unsigned_conversion_warning (result, arg1);
unsigned_conversion_warning (result, arg2);
overflow_warning (result);
class = TREE_CODE_CLASS (TREE_CODE (result));
if (class == 'e' || class == '1'
|| class == '2' || class == '<')
C_SET_EXP_ORIGINAL_CODE (result, code);
else
{
int flag = TREE_CONSTANT (result);
result = build1 (NON_LVALUE_EXPR, TREE_TYPE (result), result);
C_SET_EXP_ORIGINAL_CODE (result, code);
TREE_CONSTANT (result) = flag;
}
return result;
}
tree
build_binary_op (code, orig_op0, orig_op1, convert_p)
enum tree_code code;
tree orig_op0, orig_op1;
int convert_p;
{
tree type0, type1;
register enum tree_code code0, code1;
tree op0, op1;
register enum tree_code resultcode = code;
register tree result_type = NULL;
int converted = 0;
tree build_type = 0;
tree final_type = 0;
int shorten = 0;
int short_compare = 0;
int short_shift = 0;
int common = 0;
if (convert_p)
{
op0 = default_conversion (orig_op0);
op1 = default_conversion (orig_op1);
}
else
{
op0 = orig_op0;
op1 = orig_op1;
}
type0 = TREE_TYPE (op0);
type1 = TREE_TYPE (op1);
code0 = TREE_CODE (type0);
code1 = TREE_CODE (type1);
STRIP_TYPE_NOPS (op0);
STRIP_TYPE_NOPS (op1);
if (code0 == ERROR_MARK || code1 == ERROR_MARK)
return error_mark_node;
switch (code)
{
case PLUS_EXPR:
if (code0 == POINTER_TYPE && code1 == INTEGER_TYPE)
return pointer_int_sum (PLUS_EXPR, op0, op1);
else if (code1 == POINTER_TYPE && code0 == INTEGER_TYPE)
return pointer_int_sum (PLUS_EXPR, op1, op0);
else
common = 1;
break;
case MINUS_EXPR:
if (code0 == POINTER_TYPE && code1 == POINTER_TYPE
&& comp_target_types (type0, type1))
return pointer_diff (op0, op1);
else if (code0 == POINTER_TYPE && code1 == INTEGER_TYPE)
return pointer_int_sum (MINUS_EXPR, op0, op1);
else
common = 1;
break;
case MULT_EXPR:
common = 1;
break;
case TRUNC_DIV_EXPR:
case CEIL_DIV_EXPR:
case FLOOR_DIV_EXPR:
case ROUND_DIV_EXPR:
case EXACT_DIV_EXPR:
if ((code0 == INTEGER_TYPE || code0 == REAL_TYPE
|| code0 == COMPLEX_TYPE)
&& (code1 == INTEGER_TYPE || code1 == REAL_TYPE
|| code1 == COMPLEX_TYPE))
{
if (!(code0 == INTEGER_TYPE && code1 == INTEGER_TYPE))
resultcode = RDIV_EXPR;
else
{
shorten = (TREE_UNSIGNED (TREE_TYPE (orig_op0))
|| (TREE_CODE (op1) == INTEGER_CST
&& (TREE_INT_CST_LOW (op1) != -1
|| TREE_INT_CST_HIGH (op1) != -1)));
}
common = 1;
}
break;
case BIT_AND_EXPR:
case BIT_ANDTC_EXPR:
case BIT_IOR_EXPR:
case BIT_XOR_EXPR:
if (code0 == INTEGER_TYPE && code1 == INTEGER_TYPE)
shorten = -1;
if (TREE_CODE (op0) == INTEGER_CST
&& TREE_CODE (op1) == NOP_EXPR
&& TYPE_PRECISION (type1) > TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (op1, 0)))
&& TREE_UNSIGNED (TREE_TYPE (TREE_OPERAND (op1, 0))))
{
final_type = result_type;
op1 = TREE_OPERAND (op1, 0);
result_type = TREE_TYPE (op1);
}
if (TREE_CODE (op1) == INTEGER_CST
&& TREE_CODE (op0) == NOP_EXPR
&& TYPE_PRECISION (type0) > TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (op0, 0)))
&& TREE_UNSIGNED (TREE_TYPE (TREE_OPERAND (op0, 0))))
{
final_type = result_type;
op0 = TREE_OPERAND (op0, 0);
result_type = TREE_TYPE (op0);
}
break;
case TRUNC_MOD_EXPR:
case FLOOR_MOD_EXPR:
if (code0 == INTEGER_TYPE && code1 == INTEGER_TYPE)
{
shorten = (TREE_UNSIGNED (TREE_TYPE (orig_op0))
|| (TREE_CODE (op1) == INTEGER_CST
&& (TREE_INT_CST_LOW (op1) != -1
|| TREE_INT_CST_HIGH (op1) != -1)));
common = 1;
}
break;
case TRUTH_ANDIF_EXPR:
case TRUTH_ORIF_EXPR:
case TRUTH_AND_EXPR:
case TRUTH_OR_EXPR:
case TRUTH_XOR_EXPR:
if ((code0 == INTEGER_TYPE || code0 == POINTER_TYPE
|| code0 == REAL_TYPE || code0 == COMPLEX_TYPE)
&& (code1 == INTEGER_TYPE || code1 == POINTER_TYPE
|| code1 == REAL_TYPE || code1 == COMPLEX_TYPE))
{
result_type = integer_type_node;
op0 = truthvalue_conversion (op0);
op1 = truthvalue_conversion (op1);
converted = 1;
}
break;
case RSHIFT_EXPR:
if (code0 == INTEGER_TYPE && code1 == INTEGER_TYPE)
{
if (TREE_CODE (op1) == INTEGER_CST && skip_evaluation == 0)
{
if (tree_int_cst_sgn (op1) < 0)
warning ("right shift count is negative");
else
{
if (TREE_INT_CST_LOW (op1) | TREE_INT_CST_HIGH (op1))
short_shift = 1;
if (TREE_INT_CST_HIGH (op1) != 0
|| ((unsigned HOST_WIDE_INT) TREE_INT_CST_LOW (op1)
>= TYPE_PRECISION (type0)))
warning ("right shift count >= width of type");
}
}
result_type = type0;
if (! flag_traditional)
{
if (TYPE_MAIN_VARIANT (TREE_TYPE (op1)) != integer_type_node)
op1 = convert (integer_type_node, op1);
converted = 1;
}
}
break;
case LSHIFT_EXPR:
if (code0 == INTEGER_TYPE && code1 == INTEGER_TYPE)
{
if (TREE_CODE (op1) == INTEGER_CST && skip_evaluation == 0)
{
if (tree_int_cst_sgn (op1) < 0)
warning ("left shift count is negative");
else if (TREE_INT_CST_HIGH (op1) != 0
|| ((unsigned HOST_WIDE_INT) TREE_INT_CST_LOW (op1)
>= TYPE_PRECISION (type0)))
warning ("left shift count >= width of type");
}
result_type = type0;
if (! flag_traditional)
{
if (TYPE_MAIN_VARIANT (TREE_TYPE (op1)) != integer_type_node)
op1 = convert (integer_type_node, op1);
converted = 1;
}
}
break;
case RROTATE_EXPR:
case LROTATE_EXPR:
if (code0 == INTEGER_TYPE && code1 == INTEGER_TYPE)
{
if (TREE_CODE (op1) == INTEGER_CST && skip_evaluation == 0)
{
if (tree_int_cst_sgn (op1) < 0)
warning ("shift count is negative");
else if (TREE_INT_CST_HIGH (op1) != 0
|| ((unsigned HOST_WIDE_INT) TREE_INT_CST_LOW (op1)
>= TYPE_PRECISION (type0)))
warning ("shift count >= width of type");
}
result_type = type0;
if (! flag_traditional)
{
if (TYPE_MAIN_VARIANT (TREE_TYPE (op1)) != integer_type_node)
op1 = convert (integer_type_node, op1);
converted = 1;
}
}
break;
case EQ_EXPR:
case NE_EXPR:
build_type = integer_type_node;
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)
{
register tree tt0 = TREE_TYPE (type0);
register tree tt1 = TREE_TYPE (type1);
if (comp_target_types (type0, type1))
result_type = common_type (type0, type1);
else if (TYPE_MAIN_VARIANT (tt0) == void_type_node)
{
if (pedantic && (!integer_zerop (op0) || op0 != orig_op0)
&& TREE_CODE (tt1) == FUNCTION_TYPE)
pedwarn ("ANSI C forbids comparison of `void *' with function pointer");
}
else if (TYPE_MAIN_VARIANT (tt1) == void_type_node)
{
if (pedantic && (!integer_zerop (op1) || op1 != orig_op1)
&& TREE_CODE (tt0) == FUNCTION_TYPE)
pedwarn ("ANSI C forbids comparison of `void *' with function pointer");
}
else
pedwarn ("comparison of distinct pointer types lacks a cast");
if (result_type == NULL_TREE)
result_type = ptr_type_node;
}
else if (code0 == POINTER_TYPE && TREE_CODE (op1) == INTEGER_CST
&& integer_zerop (op1))
result_type = type0;
else if (code1 == POINTER_TYPE && TREE_CODE (op0) == INTEGER_CST
&& integer_zerop (op0))
result_type = type1;
else if (code0 == POINTER_TYPE && code1 == INTEGER_TYPE)
{
result_type = type0;
if (! flag_traditional)
pedwarn ("comparison between pointer and integer");
}
else if (code0 == INTEGER_TYPE && code1 == POINTER_TYPE)
{
result_type = type1;
if (! flag_traditional)
pedwarn ("comparison between pointer and integer");
}
break;
case MAX_EXPR:
case MIN_EXPR:
if ((code0 == INTEGER_TYPE || code0 == REAL_TYPE)
&& (code1 == INTEGER_TYPE || code1 == REAL_TYPE))
shorten = 1;
else if (code0 == POINTER_TYPE && code1 == POINTER_TYPE)
{
if (comp_target_types (type0, type1))
{
result_type = common_type (type0, type1);
if (pedantic
&& TREE_CODE (TREE_TYPE (type0)) == FUNCTION_TYPE)
pedwarn ("ANSI C forbids ordered comparisons of pointers to functions");
}
else
{
result_type = ptr_type_node;
pedwarn ("comparison of distinct pointer types lacks a cast");
}
}
break;
case LE_EXPR:
case GE_EXPR:
case LT_EXPR:
case GT_EXPR:
build_type = integer_type_node;
if ((code0 == INTEGER_TYPE || code0 == REAL_TYPE)
&& (code1 == INTEGER_TYPE || code1 == REAL_TYPE))
short_compare = 1;
else if (code0 == POINTER_TYPE && code1 == POINTER_TYPE)
{
if (comp_target_types (type0, type1))
{
result_type = common_type (type0, type1);
if ((TYPE_SIZE (TREE_TYPE (type0)) != 0)
!= (TYPE_SIZE (TREE_TYPE (type1)) != 0))
pedwarn ("comparison of complete and incomplete pointers");
else if (pedantic
&& TREE_CODE (TREE_TYPE (type0)) == FUNCTION_TYPE)
pedwarn ("ANSI C forbids ordered comparisons of pointers to functions");
}
else
{
result_type = ptr_type_node;
pedwarn ("comparison of distinct pointer types lacks a cast");
}
}
else if (code0 == POINTER_TYPE && TREE_CODE (op1) == INTEGER_CST
&& integer_zerop (op1))
{
result_type = type0;
if (pedantic || extra_warnings)
pedwarn ("ordered comparison of pointer with integer zero");
}
else if (code1 == POINTER_TYPE && TREE_CODE (op0) == INTEGER_CST
&& integer_zerop (op0))
{
result_type = type1;
if (pedantic)
pedwarn ("ordered comparison of pointer with integer zero");
}
else if (code0 == POINTER_TYPE && code1 == INTEGER_TYPE)
{
result_type = type0;
if (! flag_traditional)
pedwarn ("comparison between pointer and integer");
}
else if (code0 == INTEGER_TYPE && code1 == POINTER_TYPE)
{
result_type = type1;
if (! flag_traditional)
pedwarn ("comparison between pointer and integer");
}
break;
default:
break;
}
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);
if (shorten && none_complex)
{
int unsigned0, unsigned1;
tree arg0 = get_narrower (op0, &unsigned0);
tree arg1 = get_narrower (op1, &unsigned1);
int uns = TREE_UNSIGNED (result_type);
tree type;
final_type = result_type;
if ((TYPE_PRECISION (TREE_TYPE (op0))
== TYPE_PRECISION (TREE_TYPE (arg0)))
&& TREE_TYPE (op0) != final_type)
unsigned0 = TREE_UNSIGNED (TREE_TYPE (op0));
if ((TYPE_PRECISION (TREE_TYPE (op1))
== TYPE_PRECISION (TREE_TYPE (arg1)))
&& TREE_TYPE (op1) != final_type)
unsigned1 = TREE_UNSIGNED (TREE_TYPE (op1));
if (shorten == -1)
uns = unsigned0;
if ((TYPE_PRECISION (TREE_TYPE (arg0))
< TYPE_PRECISION (result_type))
&& (TYPE_PRECISION (TREE_TYPE (arg1))
== TYPE_PRECISION (TREE_TYPE (arg0)))
&& unsigned0 == unsigned1
&& (unsigned0 || !uns))
result_type
= signed_or_unsigned_type (unsigned0,
common_type (TREE_TYPE (arg0), TREE_TYPE (arg1)));
else if (TREE_CODE (arg0) == INTEGER_CST
&& (unsigned1 || !uns)
&& (TYPE_PRECISION (TREE_TYPE (arg1))
< TYPE_PRECISION (result_type))
&& (type = signed_or_unsigned_type (unsigned1,
TREE_TYPE (arg1)),
int_fits_type_p (arg0, type)))
result_type = type;
else if (TREE_CODE (arg1) == INTEGER_CST
&& (unsigned0 || !uns)
&& (TYPE_PRECISION (TREE_TYPE (arg0))
< TYPE_PRECISION (result_type))
&& (type = signed_or_unsigned_type (unsigned0,
TREE_TYPE (arg0)),
int_fits_type_p (arg1, type)))
result_type = type;
}
if (short_shift)
{
int unsigned_arg;
tree arg0 = get_narrower (op0, &unsigned_arg);
final_type = result_type;
if (arg0 == op0 && final_type == TREE_TYPE (op0))
unsigned_arg = TREE_UNSIGNED (TREE_TYPE (op0));
if (TYPE_PRECISION (TREE_TYPE (arg0)) < TYPE_PRECISION (result_type)
&& TREE_INT_CST_HIGH (op1) == 0
&& TYPE_PRECISION (TREE_TYPE (arg0)) > TREE_INT_CST_LOW (op1)
&& (!TREE_UNSIGNED (final_type)
|| unsigned_arg
|| 2 * TYPE_PRECISION (TREE_TYPE (arg0)) <= TYPE_PRECISION (result_type)))
{
result_type
= signed_or_unsigned_type (unsigned_arg,
TREE_TYPE (arg0));
if (TREE_TYPE (op0) != result_type)
op0 = convert (result_type, op0);
converted = 1;
}
}
if (short_compare)
{
tree xop0 = op0, xop1 = op1, xresult_type = result_type;
enum tree_code xresultcode = resultcode;
tree val
= shorten_compare (&xop0, &xop1, &xresult_type, &xresultcode);
if (val != 0)
return val;
op0 = xop0, op1 = xop1;
converted = 1;
resultcode = xresultcode;
if ((warn_sign_compare < 0 ? extra_warnings : warn_sign_compare != 0)
&& skip_evaluation == 0)
{
int op0_signed = ! TREE_UNSIGNED (TREE_TYPE (orig_op0));
int op1_signed = ! TREE_UNSIGNED (TREE_TYPE (orig_op1));
int unsignedp0, unsignedp1;
tree primop0 = get_narrower (op0, &unsignedp0);
tree primop1 = get_narrower (op1, &unsignedp1);
xop0 = orig_op0;
xop1 = orig_op1;
STRIP_TYPE_NOPS (xop0);
STRIP_TYPE_NOPS (xop1);
if (! TREE_UNSIGNED (result_type))
;
else if (op0_signed == op1_signed)
;
else if ((op0_signed && TREE_CODE (xop0) == INTEGER_CST
&& tree_int_cst_sgn (xop0) >= 0)
|| (op1_signed && TREE_CODE (xop1) == INTEGER_CST
&& tree_int_cst_sgn (xop1) >= 0))
;
else if ((resultcode == EQ_EXPR || resultcode == NE_EXPR)
&& ((op0_signed && TREE_CODE (xop1) == INTEGER_CST
&& int_fits_type_p (xop1, signed_type (result_type)))
|| (op1_signed && TREE_CODE (xop0) == INTEGER_CST
&& int_fits_type_p (xop0, signed_type (result_type)))))
;
else
warning ("comparison between signed and unsigned");
if ((TREE_CODE (primop0) == BIT_NOT_EXPR)
!= (TREE_CODE (primop1) == BIT_NOT_EXPR))
{
if (TREE_CODE (primop0) == BIT_NOT_EXPR)
primop0 = get_narrower (TREE_OPERAND (primop0, 0),
&unsignedp0);
else
primop1 = get_narrower (TREE_OPERAND (primop1, 0),
&unsignedp1);
if (TREE_CODE (primop0) == INTEGER_CST
|| TREE_CODE (primop1) == INTEGER_CST)
{
tree primop;
long constant, mask;
int unsignedp, bits;
if (TREE_CODE (primop0) == INTEGER_CST)
{
primop = primop1;
unsignedp = unsignedp1;
constant = TREE_INT_CST_LOW (primop0);
}
else
{
primop = primop0;
unsignedp = unsignedp0;
constant = TREE_INT_CST_LOW (primop1);
}
bits = TYPE_PRECISION (TREE_TYPE (primop));
if (bits < TYPE_PRECISION (result_type)
&& bits < HOST_BITS_PER_LONG && unsignedp)
{
mask = (~0L) << bits;
if ((mask & constant) != mask)
warning ("comparison of promoted ~unsigned with constant");
}
}
else if (unsignedp0 && unsignedp1
&& (TYPE_PRECISION (TREE_TYPE (primop0))
< TYPE_PRECISION (result_type))
&& (TYPE_PRECISION (TREE_TYPE (primop1))
< TYPE_PRECISION (result_type)))
warning ("comparison of promoted ~unsigned with unsigned");
}
}
}
}
if (!result_type)
{
binary_op_error (code);
return error_mark_node;
}
if (! converted)
{
if (TREE_TYPE (op0) != result_type)
op0 = convert (result_type, op0);
if (TREE_TYPE (op1) != result_type)
op1 = convert (result_type, op1);
}
if (build_type == NULL_TREE)
build_type = result_type;
{
register tree result = build (resultcode, build_type, op0, op1);
register tree folded;
folded = fold (result);
if (folded == result)
TREE_CONSTANT (folded) = TREE_CONSTANT (op0) & TREE_CONSTANT (op1);
if (final_type != 0)
return convert (final_type, folded);
return folded;
}
}
static tree
pointer_int_sum (resultcode, ptrop, intop)
enum tree_code resultcode;
register tree ptrop, intop;
{
tree size_exp;
register tree result;
register tree folded;
register tree result_type = TREE_TYPE (ptrop);
if (TREE_CODE (TREE_TYPE (result_type)) == VOID_TYPE)
{
if (pedantic || warn_pointer_arith)
pedwarn ("pointer of type `void *' used in arithmetic");
size_exp = integer_one_node;
}
else if (TREE_CODE (TREE_TYPE (result_type)) == FUNCTION_TYPE)
{
if (pedantic || warn_pointer_arith)
pedwarn ("pointer to a function used in arithmetic");
size_exp = integer_one_node;
}
else
size_exp = c_size_in_bytes (TREE_TYPE (result_type));
if ((TREE_CODE (intop) == PLUS_EXPR || TREE_CODE (intop) == MINUS_EXPR)
&& ! TREE_CONSTANT (intop)
&& TREE_CONSTANT (TREE_OPERAND (intop, 1))
&& TREE_CONSTANT (size_exp)
&& TREE_CODE (TREE_TYPE (TREE_OPERAND (intop, 0))) == INTEGER_TYPE
&& (! TREE_UNSIGNED (TREE_TYPE (intop))
|| (TYPE_PRECISION (TREE_TYPE (intop))
== TYPE_PRECISION (TREE_TYPE (ptrop)))))
{
enum tree_code subcode = resultcode;
tree int_type = TREE_TYPE (intop);
if (TREE_CODE (intop) == MINUS_EXPR)
subcode = (subcode == PLUS_EXPR ? MINUS_EXPR : PLUS_EXPR);
ptrop = build_binary_op (subcode, ptrop,
convert (int_type, TREE_OPERAND (intop, 1)), 1);
intop = convert (int_type, TREE_OPERAND (intop, 0));
}
if (TYPE_PRECISION (TREE_TYPE (intop)) != TYPE_PRECISION (sizetype)
|| TREE_UNSIGNED (TREE_TYPE (intop)) != TREE_UNSIGNED (sizetype))
intop = convert (type_for_size (TYPE_PRECISION (sizetype),
TREE_UNSIGNED (sizetype)), intop);
intop = convert (result_type,
build_binary_op (MULT_EXPR, intop,
convert (TREE_TYPE (intop), size_exp), 1));
result = build (resultcode, result_type, ptrop, intop);
folded = fold (result);
if (folded == result)
TREE_CONSTANT (folded) = TREE_CONSTANT (ptrop) & TREE_CONSTANT (intop);
return folded;
}
static tree
pointer_diff (op0, op1)
register tree op0, op1;
{
register tree result, folded;
tree restype = ptrdiff_type_node;
tree target_type = TREE_TYPE (TREE_TYPE (op0));
if (pedantic || warn_pointer_arith)
{
if (TREE_CODE (target_type) == VOID_TYPE)
pedwarn ("pointer of type `void *' used in subtraction");
if (TREE_CODE (target_type) == FUNCTION_TYPE)
pedwarn ("pointer to a function used in subtraction");
}
op0 = build_binary_op (MINUS_EXPR, convert (restype, op0),
convert (restype, op1), 0);
if (TYPE_SIZE (TREE_TYPE (TREE_TYPE (op1))) == 0)
error ("arithmetic on pointer to an incomplete type");
op1 = c_size_in_bytes (target_type);
result = build (EXACT_DIV_EXPR, restype, op0, convert (restype, op1));
folded = fold (result);
if (folded == result)
TREE_CONSTANT (folded) = TREE_CONSTANT (op0) & TREE_CONSTANT (op1);
return folded;
}
tree
build_unary_op (code, xarg, noconvert)
enum tree_code code;
tree xarg;
int noconvert;
{
register tree arg = xarg;
register tree argtype = 0;
register enum tree_code typecode = TREE_CODE (TREE_TYPE (arg));
tree val;
if (typecode == ERROR_MARK)
return error_mark_node;
if (typecode == ENUMERAL_TYPE)
typecode = INTEGER_TYPE;
switch (code)
{
case CONVERT_EXPR:
if (!(typecode == INTEGER_TYPE || typecode == REAL_TYPE
|| typecode == COMPLEX_TYPE))
{
error ("wrong type argument to unary plus");
return error_mark_node;
}
else if (!noconvert)
arg = default_conversion (arg);
break;
case NEGATE_EXPR:
if (!(typecode == INTEGER_TYPE || typecode == REAL_TYPE
|| typecode == COMPLEX_TYPE))
{
error ("wrong type argument to unary minus");
return error_mark_node;
}
else if (!noconvert)
arg = default_conversion (arg);
break;
case BIT_NOT_EXPR:
if (typecode == COMPLEX_TYPE)
{
code = CONJ_EXPR;
if (!noconvert)
arg = default_conversion (arg);
}
else if (typecode != INTEGER_TYPE)
{
error ("wrong type argument to bit-complement");
return error_mark_node;
}
else if (!noconvert)
arg = default_conversion (arg);
break;
case ABS_EXPR:
if (!(typecode == INTEGER_TYPE || typecode == REAL_TYPE
|| typecode == COMPLEX_TYPE))
{
error ("wrong type argument to abs");
return error_mark_node;
}
else if (!noconvert)
arg = default_conversion (arg);
break;
case CONJ_EXPR:
if (!(typecode == INTEGER_TYPE || typecode == REAL_TYPE
|| typecode == COMPLEX_TYPE))
{
error ("wrong type argument to conjugation");
return error_mark_node;
}
else if (!noconvert)
arg = default_conversion (arg);
break;
case TRUTH_NOT_EXPR:
if (typecode != INTEGER_TYPE
&& typecode != REAL_TYPE && typecode != POINTER_TYPE
&& typecode != COMPLEX_TYPE
&& typecode != ARRAY_TYPE && typecode != FUNCTION_TYPE)
{
error ("wrong type argument to unary exclamation mark");
return error_mark_node;
}
arg = truthvalue_conversion (arg);
return invert_truthvalue (arg);
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 convert (TREE_TYPE (arg), integer_zero_node);
case PREINCREMENT_EXPR:
case POSTINCREMENT_EXPR:
case PREDECREMENT_EXPR:
case POSTDECREMENT_EXPR:
val = unary_complex_lvalue (code, arg);
if (val != 0)
return val;
if (typecode == 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);
}
if (typecode != POINTER_TYPE
&& typecode != INTEGER_TYPE && typecode != REAL_TYPE)
{
error (code == PREINCREMENT_EXPR || code == POSTINCREMENT_EXPR
? "wrong type argument to increment"
: "wrong type argument to decrement");
return error_mark_node;
}
{
register tree inc;
tree result_type = TREE_TYPE (arg);
arg = get_unwidened (arg, 0);
argtype = TREE_TYPE (arg);
if (typecode == POINTER_TYPE)
{
if (TYPE_SIZE (TREE_TYPE (result_type)) == 0)
error (code == PREINCREMENT_EXPR || code == POSTINCREMENT_EXPR
? "increment of pointer to unknown structure"
: "decrement of pointer to unknown structure");
else if ((pedantic || warn_pointer_arith)
&& (TREE_CODE (TREE_TYPE (result_type)) == FUNCTION_TYPE
|| TREE_CODE (TREE_TYPE (result_type)) == VOID_TYPE))
pedwarn (code == PREINCREMENT_EXPR || code == POSTINCREMENT_EXPR
? "wrong type argument to increment"
: "wrong type argument to decrement");
inc = c_size_in_bytes (TREE_TYPE (result_type));
}
else
inc = integer_one_node;
inc = convert (argtype, inc);
while (1)
switch (TREE_CODE (arg))
{
case NOP_EXPR:
case CONVERT_EXPR:
case FLOAT_EXPR:
case FIX_TRUNC_EXPR:
case FIX_FLOOR_EXPR:
case FIX_ROUND_EXPR:
case FIX_CEIL_EXPR:
pedantic_lvalue_warning (CONVERT_EXPR);
if ((TREE_CODE (TREE_TYPE (arg))
== TREE_CODE (TREE_TYPE (TREE_OPERAND (arg, 0))))
&& (TYPE_MODE (TREE_TYPE (arg))
== TYPE_MODE (TREE_TYPE (TREE_OPERAND (arg, 0)))))
arg = TREE_OPERAND (arg, 0);
else
{
tree incremented, modify, value;
arg = stabilize_reference (arg);
if (code == PREINCREMENT_EXPR || code == PREDECREMENT_EXPR)
value = arg;
else
value = save_expr (arg);
incremented = build (((code == PREINCREMENT_EXPR
|| code == POSTINCREMENT_EXPR)
? PLUS_EXPR : MINUS_EXPR),
argtype, value, inc);
TREE_SIDE_EFFECTS (incremented) = 1;
modify = build_modify_expr (arg, NOP_EXPR, incremented);
value = build (COMPOUND_EXPR, TREE_TYPE (arg), modify, value);
TREE_USED (value) = 1;
return value;
}
break;
default:
goto give_up;
}
give_up:
if (!lvalue_or_else (arg, ((code == PREINCREMENT_EXPR
|| code == POSTINCREMENT_EXPR)
? "invalid lvalue in increment"
: "invalid lvalue in decrement")))
return error_mark_node;
if (TREE_READONLY (arg))
readonly_warning (arg,
((code == PREINCREMENT_EXPR
|| code == POSTINCREMENT_EXPR)
? "increment" : "decrement"));
val = build (code, TREE_TYPE (arg), arg, inc);
TREE_SIDE_EFFECTS (val) = 1;
val = convert (result_type, val);
if (TREE_CODE (val) != code)
TREE_NO_UNUSED_WARNING (val) = 1;
return val;
}
case ADDR_EXPR:
if (TREE_CODE (arg) == INDIRECT_REF)
{
if (lvalue_p (TREE_OPERAND (arg, 0)))
return non_lvalue (TREE_OPERAND (arg, 0));
return TREE_OPERAND (arg, 0);
}
if (TREE_CODE (arg) == ARRAY_REF)
{
if (mark_addressable (TREE_OPERAND (arg, 0)) == 0)
return error_mark_node;
return build_binary_op (PLUS_EXPR, TREE_OPERAND (arg, 0),
TREE_OPERAND (arg, 1), 1);
}
val = unary_complex_lvalue (code, arg);
if (val != 0)
return val;
#if 0
switch (TREE_CODE (arg))
{
case NOP_EXPR:
case CONVERT_EXPR:
case FLOAT_EXPR:
case FIX_TRUNC_EXPR:
case FIX_FLOOR_EXPR:
case FIX_ROUND_EXPR:
case FIX_CEIL_EXPR:
if (pedantic)
pedwarn ("ANSI C forbids the address of a cast expression");
return convert (build_pointer_type (TREE_TYPE (arg)),
build_unary_op (ADDR_EXPR, TREE_OPERAND (arg, 0),
0));
}
#endif
if (TREE_CODE (arg) == CONSTRUCTOR && TREE_CONSTANT (arg))
;
else if (typecode != FUNCTION_TYPE
&& !lvalue_or_else (arg, "invalid lvalue in unary `&'"))
return error_mark_node;
argtype = TREE_TYPE (arg);
if (TREE_CODE_CLASS (TREE_CODE (arg)) == 'd'
|| TREE_CODE_CLASS (TREE_CODE (arg)) == 'r')
{
if (TREE_READONLY (arg) || TREE_THIS_VOLATILE (arg))
argtype = c_build_type_variant (argtype,
TREE_READONLY (arg),
TREE_THIS_VOLATILE (arg));
}
argtype = build_pointer_type (argtype);
if (mark_addressable (arg) == 0)
return error_mark_node;
{
tree addr;
if (TREE_CODE (arg) == COMPONENT_REF)
{
tree field = TREE_OPERAND (arg, 1);
addr = build_unary_op (ADDR_EXPR, TREE_OPERAND (arg, 0), 0);
if (DECL_C_BIT_FIELD (field))
{
error ("attempt to take address of bit-field structure member `%s'",
IDENTIFIER_POINTER (DECL_NAME (field)));
return error_mark_node;
}
addr = convert (argtype, addr);
if (! integer_zerop (DECL_FIELD_BITPOS (field)))
{
tree offset
= size_binop (EASY_DIV_EXPR, DECL_FIELD_BITPOS (field),
size_int (BITS_PER_UNIT));
int flag = TREE_CONSTANT (addr);
addr = fold (build (PLUS_EXPR, argtype,
addr, convert (argtype, offset)));
TREE_CONSTANT (addr) = flag;
}
}
else
addr = build1 (code, argtype, arg);
if (staticp (arg)
&& ! (TREE_CODE (arg) == FUNCTION_DECL
&& DECL_CONTEXT (arg) != 0))
TREE_CONSTANT (addr) = 1;
return addr;
}
default:
break;
}
if (argtype == 0)
argtype = TREE_TYPE (arg);
return fold (build1 (code, argtype, arg));
}
#if 0
static tree
convert_sequence (conversions, arg)
tree conversions;
tree arg;
{
switch (TREE_CODE (conversions))
{
case NOP_EXPR:
case CONVERT_EXPR:
case FLOAT_EXPR:
case FIX_TRUNC_EXPR:
case FIX_FLOOR_EXPR:
case FIX_ROUND_EXPR:
case FIX_CEIL_EXPR:
return convert (TREE_TYPE (conversions),
convert_sequence (TREE_OPERAND (conversions, 0),
arg));
default:
return arg;
}
}
#endif
int
lvalue_p (ref)
tree ref;
{
register enum tree_code code = TREE_CODE (ref);
switch (code)
{
case REALPART_EXPR:
case IMAGPART_EXPR:
case COMPONENT_REF:
return lvalue_p (TREE_OPERAND (ref, 0));
case STRING_CST:
return 1;
case INDIRECT_REF:
case ARRAY_REF:
case VAR_DECL:
case PARM_DECL:
case RESULT_DECL:
case ERROR_MARK:
return (TREE_CODE (TREE_TYPE (ref)) != FUNCTION_TYPE
&& TREE_CODE (TREE_TYPE (ref)) != METHOD_TYPE);
case BIND_EXPR:
case RTL_EXPR:
return TREE_CODE (TREE_TYPE (ref)) == ARRAY_TYPE;
default:
return 0;
}
}
int
lvalue_or_else (ref, msgid)
tree ref;
const char *msgid;
{
int win = lvalue_p (ref);
if (! win)
error (msgid);
return win;
}
static tree
unary_complex_lvalue (code, arg)
enum tree_code code;
tree arg;
{
if (TREE_CODE (arg) == COMPOUND_EXPR)
{
tree real_result = build_unary_op (code, TREE_OPERAND (arg, 1), 0);
if (TREE_CODE (TREE_TYPE (arg)) != FUNCTION_TYPE)
pedantic_lvalue_warning (COMPOUND_EXPR);
return build (COMPOUND_EXPR, TREE_TYPE (real_result),
TREE_OPERAND (arg, 0), real_result);
}
if (TREE_CODE (arg) == COND_EXPR)
{
pedantic_lvalue_warning (COND_EXPR);
if (TREE_CODE (TREE_TYPE (arg)) != FUNCTION_TYPE)
pedantic_lvalue_warning (COMPOUND_EXPR);
return (build_conditional_expr
(TREE_OPERAND (arg, 0),
build_unary_op (code, TREE_OPERAND (arg, 1), 0),
build_unary_op (code, TREE_OPERAND (arg, 2), 0)));
}
return 0;
}
static void
pedantic_lvalue_warning (code)
enum tree_code code;
{
if (pedantic)
pedwarn (code == COND_EXPR
? "ANSI C forbids use of conditional expressions as lvalues"
: code == COMPOUND_EXPR
? "ANSI C forbids use of compound expressions as lvalues"
: "ANSI C forbids use of cast expressions as lvalues");
}
void
readonly_warning (arg, msgid)
tree arg;
const char *msgid;
{
if (TREE_CODE (arg) == VAR_DECL && ITERATOR_P (arg))
pedwarn ("%s of iterator `%s'", _(msgid),
IDENTIFIER_POINTER (DECL_NAME (arg)));
if (TREE_CODE (arg) == COMPONENT_REF)
{
if (TYPE_READONLY (TREE_TYPE (TREE_OPERAND (arg, 0))))
readonly_warning (TREE_OPERAND (arg, 0), msgid);
else
pedwarn ("%s of read-only member `%s'", _(msgid),
IDENTIFIER_POINTER (DECL_NAME (TREE_OPERAND (arg, 1))));
}
else if (TREE_CODE (arg) == VAR_DECL)
pedwarn ("%s of read-only variable `%s'", _(msgid),
IDENTIFIER_POINTER (DECL_NAME (arg)));
else
pedwarn ("%s of read-only location", _(msgid));
}
int
mark_addressable (exp)
tree exp;
{
register tree x = exp;
while (1)
switch (TREE_CODE (x))
{
case COMPONENT_REF:
if (DECL_C_BIT_FIELD (TREE_OPERAND (x, 1)))
{
error ("cannot take address of bitfield `%s'",
IDENTIFIER_POINTER (DECL_NAME (TREE_OPERAND (x, 1))));
return 0;
}
case ADDR_EXPR:
case ARRAY_REF:
case REALPART_EXPR:
case IMAGPART_EXPR:
x = TREE_OPERAND (x, 0);
break;
case CONSTRUCTOR:
TREE_ADDRESSABLE (x) = 1;
return 1;
case VAR_DECL:
case CONST_DECL:
case PARM_DECL:
case RESULT_DECL:
if (DECL_REGISTER (x) && !TREE_ADDRESSABLE (x)
&& DECL_NONLOCAL (x))
{
if (TREE_PUBLIC (x))
{
error ("global register variable `%s' used in nested function",
IDENTIFIER_POINTER (DECL_NAME (x)));
return 0;
}
pedwarn ("register variable `%s' used in nested function",
IDENTIFIER_POINTER (DECL_NAME (x)));
}
else if (DECL_REGISTER (x) && !TREE_ADDRESSABLE (x))
{
if (TREE_PUBLIC (x))
{
error ("address of global register variable `%s' requested",
IDENTIFIER_POINTER (DECL_NAME (x)));
return 0;
}
else if (C_TYPE_FIELDS_VOLATILE (TREE_TYPE (x)))
{
error ("cannot put object with volatile field into register");
return 0;
}
pedwarn ("address of register variable `%s' requested",
IDENTIFIER_POINTER (DECL_NAME (x)));
}
put_var_into_stack (x);
case FUNCTION_DECL:
TREE_ADDRESSABLE (x) = 1;
#if 0
if (DECL_CONTEXT (x) == 0)
TREE_ADDRESSABLE (DECL_ASSEMBLER_NAME (x)) = 1;
#endif
default:
return 1;
}
}
tree
build_conditional_expr (ifexp, op1, op2)
tree ifexp, op1, op2;
{
register tree type1;
register tree type2;
register enum tree_code code1;
register enum tree_code code2;
register tree result_type = NULL;
tree orig_op1 = op1, orig_op2 = op2;
ifexp = truthvalue_conversion (default_conversion (ifexp));
#if 0
if (TREE_TYPE (op1) == TREE_TYPE (op2)
&& TREE_CODE (TREE_TYPE (op1)) != ARRAY_TYPE
&& TREE_CODE (TREE_TYPE (op1)) != ENUMERAL_TYPE
&& TREE_CODE (TREE_TYPE (op1)) != FUNCTION_TYPE)
{
if (TREE_CODE (ifexp) == INTEGER_CST)
return pedantic_non_lvalue (integer_zerop (ifexp) ? op2 : op1);
return fold (build (COND_EXPR, TREE_TYPE (op1), ifexp, op1, op2));
}
#endif
if (TREE_CODE (TREE_TYPE (op1)) != VOID_TYPE)
op1 = default_conversion (op1);
if (TREE_CODE (TREE_TYPE (op2)) != VOID_TYPE)
op2 = default_conversion (op2);
if (TREE_CODE (ifexp) == ERROR_MARK
|| TREE_CODE (TREE_TYPE (op1)) == ERROR_MARK
|| TREE_CODE (TREE_TYPE (op2)) == ERROR_MARK)
return error_mark_node;
type1 = TREE_TYPE (op1);
code1 = TREE_CODE (type1);
type2 = TREE_TYPE (op2);
code2 = TREE_CODE (type2);
if (TYPE_MAIN_VARIANT (type1) == TYPE_MAIN_VARIANT (type2))
{
if (type1 == type2)
result_type = type1;
else
result_type = TYPE_MAIN_VARIANT (type1);
}
else if ((code1 == INTEGER_TYPE || code1 == REAL_TYPE)
&& (code2 == INTEGER_TYPE || code2 == REAL_TYPE))
{
result_type = common_type (type1, type2);
}
else if (code1 == VOID_TYPE || code2 == VOID_TYPE)
{
if (pedantic && (code1 != VOID_TYPE || code2 != VOID_TYPE))
pedwarn ("ANSI C forbids conditional expr with only one void side");
result_type = void_type_node;
}
else if (code1 == POINTER_TYPE && code2 == POINTER_TYPE)
{
if (comp_target_types (type1, type2))
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 (TREE_TYPE (type2)) == FUNCTION_TYPE)
pedwarn ("ANSI C forbids conditional expr between `void *' and function pointer");
result_type = qualify_type (type1, type2);
}
else if (TYPE_MAIN_VARIANT (TREE_TYPE (type2)) == void_type_node)
{
if (pedantic && TREE_CODE (TREE_TYPE (type1)) == FUNCTION_TYPE)
pedwarn ("ANSI C forbids conditional expr between `void *' and function pointer");
result_type = qualify_type (type2, type1);
}
else
{
pedwarn ("pointer type mismatch in conditional expression");
result_type = build_pointer_type (void_type_node);
}
}
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;
#if 0
if (pedantic && TREE_CODE (type1) == FUNCTION_TYPE)
pedwarn ("ANSI C forbids conditional expr between 0 and function pointer");
#endif
}
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;
#if 0
if (pedantic && TREE_CODE (type2) == FUNCTION_TYPE)
pedwarn ("ANSI C forbids conditional expr between 0 and function pointer");
#endif
}
result_type = type2;
}
if (!result_type)
{
if (flag_cond_mismatch)
result_type = void_type_node;
else
{
error ("type mismatch in conditional expression");
return error_mark_node;
}
}
result_type
= build_type_variant (result_type,
TREE_READONLY (op1) || TREE_READONLY (op2),
TREE_THIS_VOLATILE (op1) || TREE_THIS_VOLATILE (op2));
if (result_type != TREE_TYPE (op1))
op1 = convert_and_check (result_type, op1);
if (result_type != TREE_TYPE (op2))
op2 = convert_and_check (result_type, op2);
#if 0
if (code1 == RECORD_TYPE || code1 == UNION_TYPE)
{
result_type = TREE_TYPE (op1);
if (TREE_CONSTANT (ifexp))
return pedantic_non_lvalue (integer_zerop (ifexp) ? op2 : op1);
if (TYPE_MODE (result_type) == BLKmode)
{
register tree tempvar
= build_decl (VAR_DECL, NULL_TREE, result_type);
register tree xop1 = build_modify_expr (tempvar, op1);
register tree xop2 = build_modify_expr (tempvar, op2);
register tree result = fold (build (COND_EXPR, result_type,
ifexp, xop1, xop2));
layout_decl (tempvar, TYPE_ALIGN (result_type));
if (TREE_CODE (DECL_SIZE (tempvar)) != INTEGER_CST)
abort ();
DECL_RTL (tempvar)
= assign_stack_local (DECL_MODE (tempvar),
(TREE_INT_CST_LOW (DECL_SIZE (tempvar))
+ BITS_PER_UNIT - 1)
/ BITS_PER_UNIT,
0);
TREE_SIDE_EFFECTS (result)
= TREE_SIDE_EFFECTS (ifexp) | TREE_SIDE_EFFECTS (op1)
| TREE_SIDE_EFFECTS (op2);
return build (COMPOUND_EXPR, result_type, result, tempvar);
}
}
#endif
if (TREE_CODE (ifexp) == INTEGER_CST)
return pedantic_non_lvalue (integer_zerop (ifexp) ? op2 : op1);
return fold (build (COND_EXPR, result_type, ifexp, op1, op2));
}
tree
build_compound_expr (list)
tree list;
{
return internal_build_compound_expr (list, TRUE);
}
static tree
internal_build_compound_expr (list, first_p)
tree list;
int first_p;
{
register tree rest;
if (TREE_CHAIN (list) == 0)
{
#if 0
if (TREE_CODE (list) == NON_LVALUE_EXPR)
list = TREE_OPERAND (list, 0);
#endif
if (!first_p && integer_zerop (TREE_VALUE (list)))
return non_lvalue (TREE_VALUE (list));
return TREE_VALUE (list);
}
if (TREE_CHAIN (list) != 0 && TREE_CHAIN (TREE_CHAIN (list)) == 0)
{
if (TREE_CODE (TREE_TYPE (TREE_VALUE (TREE_CHAIN (list)))) == ARRAY_TYPE)
TREE_VALUE (TREE_CHAIN (list))
= default_conversion (TREE_VALUE (TREE_CHAIN (list)));
}
rest = internal_build_compound_expr (TREE_CHAIN (list), FALSE);
if (! TREE_SIDE_EFFECTS (TREE_VALUE (list)))
{
if ((extra_warnings || warn_unused)
&& ! (TREE_CODE (TREE_VALUE (list)) == CONVERT_EXPR
&& TREE_TYPE (TREE_VALUE (list)) == void_type_node))
#ifdef NEXT_SEMANTICS
if (!(flag_altivec && !extra_warnings))
#endif
warning ("left-hand operand of comma expression has no effect");
if (! pedantic)
return rest;
}
else if (warn_unused)
warn_if_unused_value (TREE_VALUE (list));
return build (COMPOUND_EXPR, TREE_TYPE (rest), TREE_VALUE (list), rest);
}
tree
build_c_cast (type, expr)
register tree type;
tree expr;
{
register tree value = expr;
if (type == error_mark_node || expr == error_mark_node)
return error_mark_node;
if (TREE_CODE (type) != POINTER_TYPE
|| !is_protocol_qualified_id (type))
type = TYPE_MAIN_VARIANT (type);
#if 0
if (TREE_CODE (value) == NON_LVALUE_EXPR)
value = TREE_OPERAND (value, 0);
#endif
if (TREE_CODE (type) == ARRAY_TYPE)
{
error ("cast specifies array type");
return error_mark_node;
}
if (TREE_CODE (type) == FUNCTION_TYPE)
{
error ("cast specifies function type");
return error_mark_node;
}
if (type == TREE_TYPE (value))
{
if (pedantic)
{
if (TREE_CODE (type) == RECORD_TYPE
|| TREE_CODE (type) == UNION_TYPE)
pedwarn ("ANSI C forbids casting nonscalar to the same type");
}
}
else if (TREE_CODE (type) == UNION_TYPE)
{
tree field;
if (TREE_CODE (TREE_TYPE (value)) == ARRAY_TYPE
|| TREE_CODE (TREE_TYPE (value)) == FUNCTION_TYPE)
value = default_conversion (value);
for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
if (comptypes (TYPE_MAIN_VARIANT (TREE_TYPE (field)),
TYPE_MAIN_VARIANT (TREE_TYPE (value))))
break;
if (field)
{
const char *name;
tree t;
if (pedantic)
pedwarn ("ANSI C forbids casts to union type");
if (TYPE_NAME (type) != 0)
{
if (TREE_CODE (TYPE_NAME (type)) == IDENTIFIER_NODE)
name = IDENTIFIER_POINTER (TYPE_NAME (type));
else
name = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type)));
}
else
name = "";
t = digest_init (type, build (CONSTRUCTOR, type, NULL_TREE,
build_tree_list (field, value)),
0, 0);
TREE_CONSTANT (t) = TREE_CONSTANT (value);
return t;
}
error ("cast to union type from type not present in union");
return error_mark_node;
}
else if (TREE_CODE (type) == VECTOR_TYPE && TREE_CODE (expr) == VECTOR_CST
&& TREE_TYPE (expr) != type)
{
TREE_TYPE (expr) = type;
return expr;
}
else
{
tree otype, ovalue;
if (type == void_type_node)
return build1 (CONVERT_EXPR, type, value);
if (TREE_CODE (TREE_TYPE (value)) == FUNCTION_TYPE
|| TREE_CODE (TREE_TYPE (value)) == ARRAY_TYPE)
value = default_conversion (value);
otype = TREE_TYPE (value);
if (warn_cast_qual
&& TREE_CODE (type) == POINTER_TYPE
&& TREE_CODE (otype) == POINTER_TYPE)
{
tree in_type = type;
tree in_otype = otype;
while (TREE_CODE (in_type) == POINTER_TYPE)
in_type = TREE_TYPE (in_type);
while (TREE_CODE (in_otype) == POINTER_TYPE)
in_otype = TREE_TYPE (in_otype);
if (TYPE_QUALS (in_otype) & ~TYPE_QUALS (in_type))
pedwarn ("cast discards qualifiers from pointer target type");
}
if (STRICT_ALIGNMENT && warn_cast_align
&& TREE_CODE (type) == POINTER_TYPE
&& TREE_CODE (otype) == POINTER_TYPE
&& TREE_CODE (TREE_TYPE (otype)) != VOID_TYPE
&& TREE_CODE (TREE_TYPE (otype)) != FUNCTION_TYPE
&& !((TREE_CODE (TREE_TYPE (otype)) == UNION_TYPE
|| TREE_CODE (TREE_TYPE (otype)) == RECORD_TYPE)
&& TYPE_MODE (TREE_TYPE (otype)) == VOIDmode)
&& TYPE_ALIGN (TREE_TYPE (type)) > TYPE_ALIGN (TREE_TYPE (otype)))
warning ("cast increases required alignment of target type");
if (TREE_CODE (type) == INTEGER_TYPE
&& TREE_CODE (otype) == POINTER_TYPE
&& TYPE_PRECISION (type) != TYPE_PRECISION (otype)
&& !TREE_CONSTANT (value))
warning ("cast from pointer to integer of different size");
if (warn_bad_function_cast
&& TREE_CODE (value) == CALL_EXPR
&& TREE_CODE (type) != TREE_CODE (otype))
warning ("cast does not match function type");
if (TREE_CODE (type) == POINTER_TYPE
&& TREE_CODE (otype) == INTEGER_TYPE
&& TYPE_PRECISION (type) != TYPE_PRECISION (otype)
#if 0
&& !(TREE_CODE (value) == INTEGER_CST && integer_zerop (value))
#endif
&& !TREE_CONSTANT (value))
warning ("cast to pointer from integer of different size");
ovalue = value;
value = convert (type, value);
if (TREE_CODE (value) == INTEGER_CST)
{
TREE_OVERFLOW (value) = TREE_OVERFLOW (ovalue);
TREE_CONSTANT_OVERFLOW (value) = TREE_CONSTANT_OVERFLOW (ovalue);
}
}
if (pedantic && TREE_CODE (value) == INTEGER_CST
&& TREE_CODE (expr) == INTEGER_CST
&& TREE_CODE (TREE_TYPE (expr)) != INTEGER_TYPE)
value = non_lvalue (value);
if (value == expr && pedantic)
value = non_lvalue (value);
return value;
}
tree
build_modify_expr (lhs, modifycode, rhs)
tree lhs, rhs;
enum tree_code modifycode;
{
register tree result;
tree newrhs;
tree lhstype = TREE_TYPE (lhs);
tree olhstype = lhstype;
lhs = require_complete_type (lhs);
if (TREE_CODE (lhs) == ERROR_MARK || TREE_CODE (rhs) == ERROR_MARK)
return error_mark_node;
if (TREE_CODE (rhs) == NON_LVALUE_EXPR)
rhs = TREE_OPERAND (rhs, 0);
newrhs = rhs;
switch (TREE_CODE (lhs))
{
case COMPOUND_EXPR:
pedantic_lvalue_warning (COMPOUND_EXPR);
newrhs = build_modify_expr (TREE_OPERAND (lhs, 1),
modifycode, rhs);
if (TREE_CODE (newrhs) == ERROR_MARK)
return error_mark_node;
return build (COMPOUND_EXPR, lhstype,
TREE_OPERAND (lhs, 0), newrhs);
case COND_EXPR:
pedantic_lvalue_warning (COND_EXPR);
rhs = save_expr (rhs);
{
tree cond
= build_conditional_expr (TREE_OPERAND (lhs, 0),
build_modify_expr (TREE_OPERAND (lhs, 1),
modifycode, rhs),
build_modify_expr (TREE_OPERAND (lhs, 2),
modifycode, rhs));
if (TREE_CODE (cond) == ERROR_MARK)
return cond;
return build (COMPOUND_EXPR, TREE_TYPE (lhs),
convert (void_type_node, rhs), cond);
}
default:
break;
}
if (modifycode != NOP_EXPR)
{
lhs = stabilize_reference (lhs);
newrhs = build_binary_op (modifycode, lhs, rhs, 1);
}
switch (TREE_CODE (lhs))
{
case NOP_EXPR:
case CONVERT_EXPR:
case FLOAT_EXPR:
case FIX_TRUNC_EXPR:
case FIX_FLOOR_EXPR:
case FIX_ROUND_EXPR:
case FIX_CEIL_EXPR:
if (TREE_CODE (TREE_TYPE (newrhs)) == ARRAY_TYPE
|| TREE_CODE (TREE_TYPE (newrhs)) == FUNCTION_TYPE)
newrhs = default_conversion (newrhs);
{
tree inner_lhs = TREE_OPERAND (lhs, 0);
tree result;
result = build_modify_expr (inner_lhs, NOP_EXPR,
convert (TREE_TYPE (inner_lhs),
convert (lhstype, newrhs)));
if (TREE_CODE (result) == ERROR_MARK)
return result;
pedantic_lvalue_warning (CONVERT_EXPR);
return convert (TREE_TYPE (lhs), result);
}
default:
break;
}
if (!lvalue_or_else (lhs, "invalid lvalue in assignment"))
return error_mark_node;
if (TREE_READONLY (lhs) || TYPE_READONLY (lhstype)
|| ((TREE_CODE (lhstype) == RECORD_TYPE
|| TREE_CODE (lhstype) == UNION_TYPE)
&& C_TYPE_FIELDS_READONLY (lhstype)))
readonly_warning (lhs, "assignment");
if (TREE_CODE (lhs) == COMPONENT_REF
&& (TREE_CODE (lhstype) == INTEGER_TYPE
|| TREE_CODE (lhstype) == REAL_TYPE
|| TREE_CODE (lhstype) == ENUMERAL_TYPE))
lhstype = TREE_TYPE (get_unwidened (lhs, 0));
if (lhstype != TREE_TYPE (lhs))
{
lhs = copy_node (lhs);
TREE_TYPE (lhs) = lhstype;
}
newrhs = convert_for_assignment (lhstype, newrhs, _("assignment"),
NULL_TREE, NULL_TREE, 0);
if (TREE_CODE (newrhs) == ERROR_MARK)
return error_mark_node;
result = build (MODIFY_EXPR, lhstype, lhs, newrhs);
TREE_SIDE_EFFECTS (result) = 1;
if (olhstype == TREE_TYPE (result))
return result;
return convert_for_assignment (olhstype, result, _("assignment"),
NULL_TREE, NULL_TREE, 0);
}
static tree
convert_for_assignment (type, rhs, errtype, fundecl, funname, parmnum)
tree type, rhs;
const char *errtype;
tree fundecl, funname;
int parmnum;
{
register enum tree_code codel = TREE_CODE (type);
register tree rhstype;
register enum tree_code coder;
if (TREE_CODE (rhs) == NON_LVALUE_EXPR)
rhs = TREE_OPERAND (rhs, 0);
if (TREE_CODE (TREE_TYPE (rhs)) == ARRAY_TYPE
|| TREE_CODE (TREE_TYPE (rhs)) == FUNCTION_TYPE)
rhs = default_conversion (rhs);
else if (optimize && TREE_CODE (rhs) == VAR_DECL)
rhs = decl_constant_value (rhs);
rhstype = TREE_TYPE (rhs);
coder = TREE_CODE (rhstype);
if (coder == ERROR_MARK)
return error_mark_node;
if (TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (rhstype))
{
overflow_warning (rhs);
maybe_objc_comptypes (type, rhstype, 0);
return rhs;
}
if (coder == VOID_TYPE)
{
error ("void value not ignored as it ought to be");
return error_mark_node;
}
if ((codel == INTEGER_TYPE || codel == REAL_TYPE || codel == ENUMERAL_TYPE
|| codel == COMPLEX_TYPE)
&& (coder == INTEGER_TYPE || coder == REAL_TYPE || coder == ENUMERAL_TYPE
|| coder == COMPLEX_TYPE))
return convert_and_check (type, rhs);
else if (codel == UNION_TYPE && TYPE_TRANSPARENT_UNION (type) && ! errtype)
{
tree memb_types;
tree marginal_memb_type = 0;
for (memb_types = TYPE_FIELDS (type); memb_types;
memb_types = TREE_CHAIN (memb_types))
{
tree memb_type = TREE_TYPE (memb_types);
if (comptypes (TYPE_MAIN_VARIANT (memb_type),
TYPE_MAIN_VARIANT (rhstype)))
break;
if (TREE_CODE (memb_type) != POINTER_TYPE)
continue;
if (coder == POINTER_TYPE)
{
register tree ttl = TREE_TYPE (memb_type);
register tree ttr = TREE_TYPE (rhstype);
if (TYPE_MAIN_VARIANT (ttl) == void_type_node
|| TYPE_MAIN_VARIANT (ttr) == void_type_node
|| comp_target_types (memb_type, rhstype))
{
if (TYPE_QUALS (ttl) == TYPE_QUALS (ttr)
|| ((TREE_CODE (ttr) == FUNCTION_TYPE
&& TREE_CODE (ttl) == FUNCTION_TYPE)
? ((TYPE_QUALS (ttl) | TYPE_QUALS (ttr))
== TYPE_QUALS (ttr))
: ((TYPE_QUALS (ttl) | TYPE_QUALS (ttr))
== TYPE_QUALS (ttl))))
break;
if (! marginal_memb_type)
marginal_memb_type = memb_type;
}
}
if (integer_zerop (rhs)
|| (TREE_CODE (rhs) == NOP_EXPR
&& integer_zerop (TREE_OPERAND (rhs, 0))))
{
rhs = null_pointer_node;
break;
}
}
if (memb_types || marginal_memb_type)
{
if (! memb_types)
{
register tree ttl = TREE_TYPE (marginal_memb_type);
register tree ttr = TREE_TYPE (rhstype);
if (TREE_CODE (ttr) == FUNCTION_TYPE
&& TREE_CODE (ttl) == FUNCTION_TYPE)
{
if (TYPE_QUALS (ttl) & ~TYPE_QUALS (ttr))
warn_for_assignment ("%s makes qualified function pointer from unqualified",
errtype, funname, parmnum);
}
else if (TYPE_QUALS (ttr) & ~TYPE_QUALS (ttl))
warn_for_assignment ("%s discards qualifiers from pointer target type",
errtype, funname,
parmnum);
}
if (pedantic && ! DECL_IN_SYSTEM_HEADER (fundecl))
pedwarn ("ANSI C prohibits argument conversion to union type");
return build1 (NOP_EXPR, type, rhs);
}
}
else if (codel == POINTER_TYPE && coder == POINTER_TYPE)
{
register tree ttl = TREE_TYPE (type);
register tree ttr = TREE_TYPE (rhstype);
if (TYPE_MAIN_VARIANT (ttl) == void_type_node
|| TYPE_MAIN_VARIANT (ttr) == void_type_node
|| comp_target_types (type, rhstype)
|| (unsigned_type (TYPE_MAIN_VARIANT (ttl))
== unsigned_type (TYPE_MAIN_VARIANT (ttr))))
{
if (pedantic
&& ((TYPE_MAIN_VARIANT (ttl) == void_type_node
&& TREE_CODE (ttr) == FUNCTION_TYPE)
||
(TYPE_MAIN_VARIANT (ttr) == void_type_node
&& (!integer_zerop (rhs) || TREE_CODE (rhs) == NOP_EXPR)
&& TREE_CODE (ttl) == FUNCTION_TYPE)))
warn_for_assignment ("ANSI forbids %s between function pointer and `void *'",
errtype, funname, parmnum);
else if (TREE_CODE (ttr) != FUNCTION_TYPE
&& TREE_CODE (ttl) != FUNCTION_TYPE)
{
if (TYPE_QUALS (ttr) & ~TYPE_QUALS (ttl))
{
if (!(fundecl
&& TREE_CODE (fundecl) == FUNCTION_DECL
&& DECL_TARGET_INTRINSIC_P (fundecl)))
warn_for_assignment ("%s discards qualifiers from pointer target type",
errtype, funname, parmnum);
}
else if (TYPE_MAIN_VARIANT (ttl) == void_type_node
|| TYPE_MAIN_VARIANT (ttr) == void_type_node
|| comp_target_types (type, rhstype))
;
else if (pedantic)
warn_for_assignment ("pointer targets in %s differ in signedness",
errtype, funname, parmnum);
}
else if (TREE_CODE (ttl) == FUNCTION_TYPE
&& TREE_CODE (ttr) == FUNCTION_TYPE)
{
if (TYPE_QUALS (ttl) & ~TYPE_QUALS (ttr))
warn_for_assignment ("%s makes qualified function pointer from unqualified",
errtype, funname, parmnum);
}
}
else
warn_for_assignment ("%s from incompatible pointer type",
errtype, funname, parmnum);
return convert (type, rhs);
}
else if (codel == POINTER_TYPE && coder == INTEGER_TYPE)
{
if (! (TREE_CODE (rhs) == INTEGER_CST && integer_zerop (rhs))
&&
! (TREE_CODE (rhs) == NOP_EXPR
&& TREE_CODE (TREE_TYPE (rhs)) == INTEGER_TYPE
&& TREE_CODE (TREE_OPERAND (rhs, 0)) == INTEGER_CST
&& integer_zerop (TREE_OPERAND (rhs, 0))))
{
warn_for_assignment ("%s makes pointer from integer without a cast",
errtype, funname, parmnum);
return convert (type, rhs);
}
return null_pointer_node;
}
else if (codel == INTEGER_TYPE && coder == POINTER_TYPE)
{
warn_for_assignment ("%s makes integer from pointer without a cast",
errtype, funname, parmnum);
return convert (type, rhs);
}
if (!errtype)
{
if (funname)
{
tree selector = maybe_building_objc_message_expr ();
if (selector && parmnum > 2)
error ("incompatible type for argument %d of `%s'",
parmnum - 2, IDENTIFIER_POINTER (selector));
else
error ("incompatible type for argument %d of `%s'",
parmnum, IDENTIFIER_POINTER (funname));
}
else
error ("incompatible type for argument %d of indirect function call",
parmnum);
}
else
error ("incompatible types in %s", errtype);
return error_mark_node;
}
int flag_next_runtime;
static void
warn_for_assignment (msgid, opname, function, argnum)
const char *msgid;
const char *opname;
tree function;
int argnum;
{
if (opname == 0)
{
tree selector = maybe_building_objc_message_expr ();
char * new_opname;
if (selector && argnum > (flag_next_runtime ? 2 : 3))
{
function = selector;
argnum -= (flag_next_runtime ? 2 : 3);
}
if (function)
{
const char *argstring = _("passing arg %d of `%s'");
new_opname = (char *) alloca (IDENTIFIER_LENGTH (function)
+ strlen (argstring) + 1 + 25
+ 1);
sprintf (new_opname, argstring, argnum,
IDENTIFIER_POINTER (function));
}
else
{
const char *argnofun = _("passing arg %d of pointer to function");
new_opname = (char *) alloca (strlen (argnofun) + 1 + 25 + 1);
sprintf (new_opname, argnofun, argnum);
}
opname = new_opname;
}
pedwarn (msgid, opname);
}
tree
initializer_constant_valid_p (value, endtype)
tree value;
tree endtype;
{
switch (TREE_CODE (value))
{
case CONSTRUCTOR:
if ((TREE_CODE (TREE_TYPE (value)) == UNION_TYPE
|| TREE_CODE (TREE_TYPE (value)) == RECORD_TYPE)
&& TREE_CONSTANT (value)
&& CONSTRUCTOR_ELTS (value))
return
initializer_constant_valid_p (TREE_VALUE (CONSTRUCTOR_ELTS (value)),
endtype);
return TREE_STATIC (value) ? null_pointer_node : 0;
case INTEGER_CST:
case REAL_CST:
case STRING_CST:
case COMPLEX_CST:
case VECTOR_CST:
return null_pointer_node;
case ADDR_EXPR:
return TREE_OPERAND (value, 0);
case NON_LVALUE_EXPR:
return initializer_constant_valid_p (TREE_OPERAND (value, 0), endtype);
case CONVERT_EXPR:
case NOP_EXPR:
#ifdef NEXT_SEMANTICS
if (TREE_CODE (TREE_TYPE (value)) == POINTER_TYPE
&& TREE_CODE (TREE_TYPE (TREE_OPERAND (value, 0))) == INTEGER_TYPE)
return initializer_constant_valid_p (TREE_OPERAND (value, 0), endtype);
#endif
if (TREE_CODE (TREE_TYPE (value)) == POINTER_TYPE
&& TREE_CODE (TREE_TYPE (TREE_OPERAND (value, 0))) == POINTER_TYPE)
return initializer_constant_valid_p (TREE_OPERAND (value, 0), endtype);
if (TREE_CODE (TREE_TYPE (value)) == REAL_TYPE
&& TREE_CODE (TREE_TYPE (TREE_OPERAND (value, 0))) == REAL_TYPE)
return initializer_constant_valid_p (TREE_OPERAND (value, 0), endtype);
if (TREE_CODE (TREE_TYPE (value)) == INTEGER_TYPE
&& TREE_CODE (TREE_TYPE (TREE_OPERAND (value, 0))) == INTEGER_TYPE
&& (TYPE_PRECISION (TREE_TYPE (value))
== TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (value, 0)))))
return initializer_constant_valid_p (TREE_OPERAND (value, 0), endtype);
if (TREE_CODE (TREE_TYPE (value)) == INTEGER_TYPE
&& TREE_CODE (TREE_TYPE (TREE_OPERAND (value, 0))) == INTEGER_TYPE)
{
tree inner = initializer_constant_valid_p (TREE_OPERAND (value, 0),
endtype);
if (inner == null_pointer_node)
return null_pointer_node;
return 0;
}
if (TREE_CODE (TREE_TYPE (value)) == INTEGER_TYPE
&& TREE_CODE (TREE_TYPE (TREE_OPERAND (value, 0))) == POINTER_TYPE
&& (TYPE_PRECISION (TREE_TYPE (value))
>= TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (value, 0)))))
return initializer_constant_valid_p (TREE_OPERAND (value, 0),
endtype);
if (TREE_CODE (TREE_TYPE (value)) == POINTER_TYPE
&& TREE_CODE (TREE_TYPE (TREE_OPERAND (value, 0))) == INTEGER_TYPE)
{
if (integer_zerop (TREE_OPERAND (value, 0)))
return null_pointer_node;
else if (TYPE_PRECISION (TREE_TYPE (value))
<= TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (value, 0))))
return initializer_constant_valid_p (TREE_OPERAND (value, 0),
endtype);
}
if (TREE_CODE (TREE_TYPE (value)) == UNION_TYPE)
return initializer_constant_valid_p (TREE_OPERAND (value, 0),
endtype);
return 0;
case PLUS_EXPR:
if (TREE_CODE (endtype) == INTEGER_TYPE
&& TYPE_PRECISION (endtype) < POINTER_SIZE)
return 0;
{
tree valid0 = initializer_constant_valid_p (TREE_OPERAND (value, 0),
endtype);
tree valid1 = initializer_constant_valid_p (TREE_OPERAND (value, 1),
endtype);
if (valid0 == null_pointer_node)
return valid1;
if (valid1 == null_pointer_node)
return valid0;
return 0;
}
case MINUS_EXPR:
if (TREE_CODE (endtype) == INTEGER_TYPE
&& TYPE_PRECISION (endtype) < POINTER_SIZE)
return 0;
{
tree valid0 = initializer_constant_valid_p (TREE_OPERAND (value, 0),
endtype);
tree valid1 = initializer_constant_valid_p (TREE_OPERAND (value, 1),
endtype);
if (valid1 == null_pointer_node)
return valid0;
if (valid0 == valid1)
return null_pointer_node;
return 0;
}
default:
return 0;
}
}
static tree
valid_compound_expr_initializer (value, endtype)
tree value;
tree endtype;
{
if (TREE_CODE (value) == COMPOUND_EXPR)
{
if (valid_compound_expr_initializer (TREE_OPERAND (value, 0), endtype)
== error_mark_node)
return error_mark_node;
return valid_compound_expr_initializer (TREE_OPERAND (value, 1),
endtype);
}
else if (! TREE_CONSTANT (value)
&& ! initializer_constant_valid_p (value, endtype))
return error_mark_node;
else
return value;
}
void
store_init_value (decl, init)
tree decl, init;
{
register tree value, type;
type = TREE_TYPE (decl);
if (TREE_CODE (type) == ERROR_MARK)
return;
value = digest_init (type, init, TREE_STATIC (decl),
TREE_STATIC (decl) || pedantic);
#if 0
if (value == error_mark_node)
;
else if (TREE_STATIC (decl) && ! TREE_CONSTANT (value))
{
error ("initializer for static variable is not constant");
value = error_mark_node;
}
else if (TREE_STATIC (decl)
&& initializer_constant_valid_p (value, TREE_TYPE (value)) == 0)
{
error ("initializer for static variable uses complicated arithmetic");
value = error_mark_node;
}
else
{
if (pedantic && TREE_CODE (value) == CONSTRUCTOR)
{
if (! TREE_CONSTANT (value))
pedwarn ("aggregate initializer is not constant");
else if (! TREE_STATIC (value))
pedwarn ("aggregate initializer uses complicated arithmetic");
}
}
#endif
DECL_INITIAL (decl) = value;
STRIP_TYPE_NOPS (value);
constant_expression_warning (value);
}
struct spelling
{
int kind;
union
{
int i;
const char *s;
} u;
};
#define SPELLING_STRING 1
#define SPELLING_MEMBER 2
#define SPELLING_BOUNDS 3
static struct spelling *spelling;
static struct spelling *spelling_base;
static int spelling_size;
#define SPELLING_DEPTH() (spelling - spelling_base)
#define RESTORE_SPELLING_DEPTH(depth) (spelling = spelling_base + depth)
#define SAVE_SPELLING_DEPTH(code) \
{ \
int __depth = SPELLING_DEPTH (); \
code; \
RESTORE_SPELLING_DEPTH (__depth); \
}
#define PUSH_SPELLING(KIND, VALUE, MEMBER) \
{ \
int depth = SPELLING_DEPTH (); \
\
if (depth >= spelling_size) \
{ \
spelling_size += 10; \
if (spelling_base == 0) \
spelling_base \
= (struct spelling *) xmalloc (spelling_size * sizeof (struct spelling)); \
else \
spelling_base \
= (struct spelling *) xrealloc (spelling_base, \
spelling_size * sizeof (struct spelling)); \
RESTORE_SPELLING_DEPTH (depth); \
} \
\
spelling->kind = (KIND); \
spelling->MEMBER = (VALUE); \
spelling++; \
}
static void
push_string (string)
const char *string;
{
PUSH_SPELLING (SPELLING_STRING, string, u.s);
}
static void
push_member_name (decl)
tree decl;
{
const char *string
= DECL_NAME (decl) ? IDENTIFIER_POINTER (DECL_NAME (decl)) : "<anonymous>";
PUSH_SPELLING (SPELLING_MEMBER, string, u.s);
}
static void
push_array_bounds (bounds)
int bounds;
{
PUSH_SPELLING (SPELLING_BOUNDS, bounds, u.i);
}
static int
spelling_length ()
{
register int size = 0;
register struct spelling *p;
for (p = spelling_base; p < spelling; p++)
{
if (p->kind == SPELLING_BOUNDS)
size += 25;
else
size += strlen (p->u.s) + 1;
}
return size;
}
static char *
print_spelling (buffer)
register char *buffer;
{
register char *d = buffer;
register struct spelling *p;
for (p = spelling_base; p < spelling; p++)
if (p->kind == SPELLING_BOUNDS)
{
sprintf (d, "[%d]", p->u.i);
d += strlen (d);
}
else
{
register const char *s;
if (p->kind == SPELLING_MEMBER)
*d++ = '.';
for (s = p->u.s; (*d = *s++); d++)
;
}
*d++ = '\0';
return buffer;
}
void
error_init (msgid)
const char *msgid;
{
char *ofwhat;
error (msgid);
ofwhat = print_spelling ((char *) alloca (spelling_length () + 1));
if (*ofwhat)
error ("(near initialization for `%s')", ofwhat);
}
void
pedwarn_init (msgid)
const char *msgid;
{
char *ofwhat;
pedwarn (msgid);
ofwhat = print_spelling ((char *) alloca (spelling_length () + 1));
if (*ofwhat)
pedwarn ("(near initialization for `%s')", ofwhat);
}
static void
warning_init (msgid)
const char *msgid;
{
char *ofwhat;
warning (msgid);
ofwhat = print_spelling ((char *) alloca (spelling_length () + 1));
if (*ofwhat)
warning ("(near initialization for `%s')", ofwhat);
}
static tree
digest_init (type, init, require_constant, constructor_constant)
tree type, init;
int require_constant, constructor_constant;
{
enum tree_code code = TREE_CODE (type);
tree inside_init = init;
if (init == error_mark_node)
return init;
if (TREE_CODE (init) == NON_LVALUE_EXPR)
inside_init = TREE_OPERAND (init, 0);
if (code == ARRAY_TYPE)
{
tree typ1 = TYPE_MAIN_VARIANT (TREE_TYPE (type));
if ((typ1 == char_type_node
|| typ1 == signed_char_type_node
|| typ1 == unsigned_char_type_node
|| typ1 == unsigned_wchar_type_node
|| typ1 == signed_wchar_type_node)
&& ((inside_init && TREE_CODE (inside_init) == STRING_CST)))
{
if (comptypes (TYPE_MAIN_VARIANT (TREE_TYPE (inside_init)),
TYPE_MAIN_VARIANT (type)))
return inside_init;
if ((TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (inside_init)))
!= char_type_node)
#ifdef PASCAL_STRINGS
&& (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (inside_init)))
!= unsigned_char_type_node)
#endif
&& TYPE_PRECISION (typ1) == TYPE_PRECISION (char_type_node))
{
error_init ("char-array initialized from wide string");
return error_mark_node;
}
if ((TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (inside_init)))
== char_type_node)
&& TYPE_PRECISION (typ1) != TYPE_PRECISION (char_type_node))
{
error_init ("int-array initialized from non-wide string");
return error_mark_node;
}
TREE_TYPE (inside_init) = type;
if (TYPE_DOMAIN (type) != 0
&& TREE_CODE (TYPE_SIZE (type)) == INTEGER_CST)
{
register int size = TREE_INT_CST_LOW (TYPE_SIZE (type));
size = (size + BITS_PER_UNIT - 1) / BITS_PER_UNIT;
if (size < TREE_STRING_LENGTH (inside_init)
- (TYPE_PRECISION (typ1) != TYPE_PRECISION (char_type_node)
? TYPE_PRECISION (wchar_type_node) / BITS_PER_UNIT
: 1))
pedwarn_init ("initializer-string for array of chars is too long");
}
return inside_init;
}
}
if (inside_init && TREE_TYPE (inside_init) != 0
&& (comptypes (TYPE_MAIN_VARIANT (TREE_TYPE (inside_init)),
TYPE_MAIN_VARIANT (type))
|| (code == ARRAY_TYPE
&& comptypes (TREE_TYPE (inside_init), type))
|| (code == POINTER_TYPE
&& (TREE_CODE (TREE_TYPE (inside_init)) == ARRAY_TYPE
|| TREE_CODE (TREE_TYPE (inside_init)) == FUNCTION_TYPE)
&& comptypes (TREE_TYPE (TREE_TYPE (inside_init)),
TREE_TYPE (type)))))
{
if (code == POINTER_TYPE
&& (TREE_CODE (TREE_TYPE (inside_init)) == ARRAY_TYPE
|| TREE_CODE (TREE_TYPE (inside_init)) == FUNCTION_TYPE))
inside_init = default_conversion (inside_init);
else if (code == ARRAY_TYPE && TREE_CODE (inside_init) != STRING_CST
&& TREE_CODE (inside_init) != CONSTRUCTOR)
{
error_init ("array initialized from non-constant array expression");
return error_mark_node;
}
if (optimize && TREE_CODE (inside_init) == VAR_DECL)
inside_init = decl_constant_value (inside_init);
if (require_constant && pedantic
&& TREE_CODE (inside_init) == COMPOUND_EXPR)
{
inside_init
= valid_compound_expr_initializer (inside_init,
TREE_TYPE (inside_init));
if (inside_init == error_mark_node)
error_init ("initializer element is not constant");
else
pedwarn_init ("initializer element is not constant");
if (flag_pedantic_errors)
inside_init = error_mark_node;
}
else if (require_constant && ! TREE_CONSTANT (inside_init))
{
error_init ("initializer element is not constant");
inside_init = error_mark_node;
}
else if (require_constant
&& initializer_constant_valid_p (inside_init, TREE_TYPE (inside_init)) == 0)
{
error_init ("initializer element is not computable at load time");
inside_init = error_mark_node;
}
return inside_init;
}
if (code == INTEGER_TYPE || code == REAL_TYPE || code == POINTER_TYPE
|| code == ENUMERAL_TYPE || code == COMPLEX_TYPE || code == VECTOR_TYPE)
{
inside_init
= convert_for_assignment (type, init, _("initialization"),
NULL_TREE, NULL_TREE, 0);
if (require_constant && ! TREE_CONSTANT (inside_init))
{
error_init ("initializer element is not constant");
inside_init = error_mark_node;
}
else if (require_constant
&& initializer_constant_valid_p (inside_init, TREE_TYPE (inside_init)) == 0)
{
error_init ("initializer element is not computable at load time");
inside_init = error_mark_node;
}
return inside_init;
}
if (TYPE_SIZE (type) && TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST)
{
error_init ("variable-sized object may not be initialized");
return error_mark_node;
}
if (flag_traditional)
{
tree top = 0, prev = 0, otype = type;
while (TREE_CODE (type) == RECORD_TYPE
|| TREE_CODE (type) == ARRAY_TYPE
|| TREE_CODE (type) == QUAL_UNION_TYPE
|| TREE_CODE (type) == UNION_TYPE)
{
tree temp = build (CONSTRUCTOR, type, NULL_TREE, NULL_TREE);
if (prev == 0)
top = temp;
else
TREE_OPERAND (prev, 1) = build_tree_list (NULL_TREE, temp);
prev = temp;
if (TREE_CODE (type) == ARRAY_TYPE)
type = TREE_TYPE (type);
else if (TYPE_FIELDS (type))
type = TREE_TYPE (TYPE_FIELDS (type));
else
{
error_init ("invalid initializer");
return error_mark_node;
}
}
if (otype != type)
{
TREE_OPERAND (prev, 1)
= build_tree_list (NULL_TREE,
digest_init (type, init, require_constant,
constructor_constant));
return top;
}
else
return error_mark_node;
}
error_init ("invalid initializer");
return error_mark_node;
}
static tree constructor_type;
static tree constructor_fields;
static tree constructor_index;
static tree constructor_range_end;
static tree constructor_max_index;
static tree constructor_unfilled_fields;
static tree constructor_unfilled_index;
static tree constructor_bit_index;
static tree constructor_elements;
static int constructor_constant;
static int constructor_simple;
static int constructor_erroneous;
static int constructor_subconstants_deferred;
struct init_node
{
struct init_node *left, *right;
struct init_node *parent;
int balance;
tree purpose;
tree value;
};
static struct init_node *constructor_pending_elts;
static int constructor_depth;
int constructor_no_implicit = 0;
static int require_constant_value;
static int require_constant_elements;
static int constructor_incremental;
static tree constructor_decl;
static char *constructor_asmspec;
static int constructor_top_level;
struct constructor_stack
{
struct constructor_stack *next;
tree type;
tree fields;
tree index;
tree range_end;
tree max_index;
tree unfilled_index;
tree unfilled_fields;
tree bit_index;
tree elements;
int offset;
struct init_node *pending_elts;
int depth;
tree replacement_value;
char constant;
char simple;
char implicit;
char incremental;
char erroneous;
char outer;
};
struct constructor_stack *constructor_stack;
struct initializer_stack
{
struct initializer_stack *next;
tree decl;
char *asmspec;
struct constructor_stack *constructor_stack;
tree elements;
struct spelling *spelling;
struct spelling *spelling_base;
int spelling_size;
char top_level;
char incremental;
char require_constant_value;
char require_constant_elements;
char deferred;
};
struct initializer_stack *initializer_stack;
void
start_init (decl, asmspec_tree, top_level)
tree decl;
tree asmspec_tree;
int top_level;
{
const char *locus;
struct initializer_stack *p
= (struct initializer_stack *) xmalloc (sizeof (struct initializer_stack));
char *asmspec = 0;
if (asmspec_tree)
asmspec = TREE_STRING_POINTER (asmspec_tree);
p->decl = constructor_decl;
p->asmspec = constructor_asmspec;
p->incremental = constructor_incremental;
p->require_constant_value = require_constant_value;
p->require_constant_elements = require_constant_elements;
p->constructor_stack = constructor_stack;
p->elements = constructor_elements;
p->spelling = spelling;
p->spelling_base = spelling_base;
p->spelling_size = spelling_size;
p->deferred = constructor_subconstants_deferred;
p->top_level = constructor_top_level;
p->next = initializer_stack;
initializer_stack = p;
constructor_decl = decl;
constructor_incremental = top_level;
constructor_asmspec = asmspec;
constructor_subconstants_deferred = 0;
constructor_top_level = top_level;
if (decl != 0)
{
require_constant_value = TREE_STATIC (decl);
require_constant_elements
= ((TREE_STATIC (decl) || pedantic)
&& (TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE
|| TREE_CODE (TREE_TYPE (decl)) == RECORD_TYPE
|| TREE_CODE (TREE_TYPE (decl)) == UNION_TYPE
|| TREE_CODE (TREE_TYPE (decl)) == QUAL_UNION_TYPE));
locus = IDENTIFIER_POINTER (DECL_NAME (decl));
constructor_incremental |= TREE_STATIC (decl);
}
else
{
require_constant_value = 0;
require_constant_elements = 0;
locus = "(anonymous)";
}
constructor_stack = 0;
missing_braces_mentioned = 0;
spelling_base = 0;
spelling_size = 0;
RESTORE_SPELLING_DEPTH (0);
if (locus)
push_string (locus);
}
void
finish_init ()
{
struct initializer_stack *p = initializer_stack;
if (constructor_subconstants_deferred)
output_deferred_addressed_constants ();
while (constructor_stack)
{
struct constructor_stack *q = constructor_stack;
constructor_stack = q->next;
free (q);
}
constructor_decl = p->decl;
constructor_asmspec = p->asmspec;
constructor_incremental = p->incremental;
require_constant_value = p->require_constant_value;
require_constant_elements = p->require_constant_elements;
constructor_stack = p->constructor_stack;
constructor_elements = p->elements;
spelling = p->spelling;
spelling_base = p->spelling_base;
spelling_size = p->spelling_size;
constructor_subconstants_deferred = p->deferred;
constructor_top_level = p->top_level;
initializer_stack = p->next;
free (p);
}
void
really_start_incremental_init (type)
tree type;
{
struct constructor_stack *p
= (struct constructor_stack *) xmalloc (sizeof (struct constructor_stack));
if (type == 0)
type = TREE_TYPE (constructor_decl);
check_init_type_bitfields (type);
p->type = constructor_type;
p->fields = constructor_fields;
p->index = constructor_index;
p->range_end = constructor_range_end;
p->max_index = constructor_max_index;
p->unfilled_index = constructor_unfilled_index;
p->unfilled_fields = constructor_unfilled_fields;
p->bit_index = constructor_bit_index;
p->elements = constructor_elements;
p->constant = constructor_constant;
p->simple = constructor_simple;
p->erroneous = constructor_erroneous;
p->pending_elts = constructor_pending_elts;
p->depth = constructor_depth;
p->replacement_value = 0;
p->implicit = 0;
p->incremental = constructor_incremental;
p->outer = 0;
p->next = 0;
constructor_stack = p;
constructor_constant = 1;
constructor_simple = 1;
constructor_depth = SPELLING_DEPTH ();
constructor_elements = 0;
constructor_pending_elts = 0;
constructor_type = type;
if (TREE_CODE (constructor_type) == RECORD_TYPE
|| TREE_CODE (constructor_type) == UNION_TYPE)
{
constructor_fields = TYPE_FIELDS (constructor_type);
while (constructor_fields != 0 && DECL_C_BIT_FIELD (constructor_fields)
&& DECL_NAME (constructor_fields) == 0)
constructor_fields = TREE_CHAIN (constructor_fields);
constructor_unfilled_fields = constructor_fields;
constructor_bit_index = copy_node (integer_zero_node);
TREE_TYPE (constructor_bit_index) = sbitsizetype;
}
else if (TREE_CODE (constructor_type) == ARRAY_TYPE)
{
constructor_range_end = 0;
if (TYPE_DOMAIN (constructor_type))
{
constructor_max_index
= TYPE_MAX_VALUE (TYPE_DOMAIN (constructor_type));
constructor_index
= copy_node (TYPE_MIN_VALUE (TYPE_DOMAIN (constructor_type)));
}
else
constructor_index = copy_node (integer_zero_node);
constructor_unfilled_index = copy_node (constructor_index);
}
else
{
constructor_fields = constructor_type;
constructor_unfilled_fields = constructor_type;
}
if (constructor_incremental)
{
int momentary = suspend_momentary ();
push_obstacks_nochange ();
if (TREE_PERMANENT (constructor_decl))
end_temporary_allocation ();
make_decl_rtl (constructor_decl, constructor_asmspec,
constructor_top_level);
assemble_variable (constructor_decl, constructor_top_level, 0, 1);
pop_obstacks ();
resume_momentary (momentary);
}
if (constructor_incremental)
{
defer_addressed_constants ();
constructor_subconstants_deferred = 1;
}
}
void
push_init_level (implicit)
int implicit;
{
struct constructor_stack *p;
while (constructor_stack->implicit)
{
if ((TREE_CODE (constructor_type) == RECORD_TYPE
|| TREE_CODE (constructor_type) == UNION_TYPE)
&& constructor_fields == 0)
process_init_element (pop_init_level (1));
else if (TREE_CODE (constructor_type) == ARRAY_TYPE
&& tree_int_cst_lt (constructor_max_index, constructor_index))
process_init_element (pop_init_level (1));
else
break;
}
if (constructor_incremental && constructor_type != 0
&& TREE_CODE (constructor_type) == RECORD_TYPE && constructor_fields
&& constructor_fields == constructor_unfilled_fields)
{
if (! tree_int_cst_equal (constructor_bit_index,
DECL_FIELD_BITPOS (constructor_fields)))
{
unsigned next = (TREE_INT_CST_LOW
(DECL_FIELD_BITPOS (constructor_fields))
/ (unsigned)BITS_PER_UNIT);
unsigned here = (TREE_INT_CST_LOW (constructor_bit_index)
/ (unsigned)BITS_PER_UNIT);
assemble_zeros ((next - here)
* (unsigned)BITS_PER_UNIT
/ (unsigned)BITS_PER_UNIT);
}
constructor_unfilled_fields = constructor_fields;
}
p = (struct constructor_stack *) xmalloc (sizeof (struct constructor_stack));
p->type = constructor_type;
p->fields = constructor_fields;
p->index = constructor_index;
p->range_end = constructor_range_end;
p->max_index = constructor_max_index;
p->unfilled_index = constructor_unfilled_index;
p->unfilled_fields = constructor_unfilled_fields;
p->bit_index = constructor_bit_index;
p->elements = constructor_elements;
p->constant = constructor_constant;
p->simple = constructor_simple;
p->erroneous = constructor_erroneous;
p->pending_elts = constructor_pending_elts;
p->depth = constructor_depth;
p->replacement_value = 0;
p->implicit = implicit;
p->incremental = constructor_incremental;
p->outer = 0;
p->next = constructor_stack;
constructor_stack = p;
constructor_constant = 1;
constructor_simple = 1;
constructor_depth = SPELLING_DEPTH ();
constructor_elements = 0;
constructor_pending_elts = 0;
if (constructor_type == 0)
;
else if (TREE_CODE (constructor_type) == RECORD_TYPE
|| TREE_CODE (constructor_type) == UNION_TYPE)
{
if (constructor_fields == 0)
constructor_type = 0;
else
{
constructor_type = TREE_TYPE (constructor_fields);
push_member_name (constructor_fields);
constructor_depth++;
if (constructor_fields != constructor_unfilled_fields)
constructor_incremental = 0;
}
}
else if (TREE_CODE (constructor_type) == ARRAY_TYPE)
{
constructor_type = TREE_TYPE (constructor_type);
push_array_bounds (TREE_INT_CST_LOW (constructor_index));
constructor_depth++;
if (! tree_int_cst_equal (constructor_index, constructor_unfilled_index)
|| constructor_range_end != 0)
constructor_incremental = 0;
}
if (constructor_type == 0)
{
error_init ("extra brace group at end of initializer");
constructor_fields = 0;
constructor_unfilled_fields = 0;
return;
}
check_init_type_bitfields (constructor_type);
if (implicit && warn_missing_braces && !missing_braces_mentioned)
{
missing_braces_mentioned = 1;
warning_init ("missing braces around initializer");
}
if (TREE_CODE (constructor_type) == RECORD_TYPE
|| TREE_CODE (constructor_type) == UNION_TYPE)
{
constructor_fields = TYPE_FIELDS (constructor_type);
while (constructor_fields != 0 && DECL_C_BIT_FIELD (constructor_fields)
&& DECL_NAME (constructor_fields) == 0)
constructor_fields = TREE_CHAIN (constructor_fields);
constructor_unfilled_fields = constructor_fields;
constructor_bit_index = copy_node (integer_zero_node);
TREE_TYPE (constructor_bit_index) = sbitsizetype;
}
else if (TREE_CODE (constructor_type) == ARRAY_TYPE)
{
constructor_range_end = 0;
if (TYPE_DOMAIN (constructor_type))
{
constructor_max_index
= TYPE_MAX_VALUE (TYPE_DOMAIN (constructor_type));
constructor_index
= copy_node (TYPE_MIN_VALUE (TYPE_DOMAIN (constructor_type)));
}
else
constructor_index = copy_node (integer_zero_node);
constructor_unfilled_index = copy_node (constructor_index);
}
else
{
warning_init ("braces around scalar initializer");
constructor_fields = constructor_type;
constructor_unfilled_fields = constructor_type;
}
}
static void
check_init_type_bitfields (type)
tree type;
{
if (TREE_CODE (type) == RECORD_TYPE)
{
tree tail;
for (tail = TYPE_FIELDS (type); tail;
tail = TREE_CHAIN (tail))
{
if (DECL_C_BIT_FIELD (tail))
{
constructor_incremental = 0;
break;
}
check_init_type_bitfields (TREE_TYPE (tail));
}
}
else if (TREE_CODE (type) == UNION_TYPE)
{
tree tail = TYPE_FIELDS (type);
if (tail && DECL_C_BIT_FIELD (tail))
constructor_incremental = 0;
}
else if (TREE_CODE (type) == ARRAY_TYPE)
check_init_type_bitfields (TREE_TYPE (type));
}
tree
pop_init_level (implicit)
int implicit;
{
struct constructor_stack *p;
int size = 0;
tree constructor = 0;
if (implicit == 0)
{
while (constructor_stack->implicit)
process_init_element (pop_init_level (1));
}
p = constructor_stack;
if (constructor_type != 0)
size = int_size_in_bytes (constructor_type);
if (extra_warnings
&& constructor_type
&& TREE_CODE (constructor_type) == RECORD_TYPE
&& constructor_unfilled_fields)
{
push_member_name (constructor_unfilled_fields);
warning_init ("missing initializer");
RESTORE_SPELLING_DEPTH (constructor_depth);
}
output_pending_init_elements (1);
#if 0
if (! implicit && pedantic
&& (TREE_CODE (constructor_type) == ARRAY_TYPE
? integer_zerop (constructor_unfilled_index)
: constructor_unfilled_fields == TYPE_FIELDS (constructor_type)))
pedwarn_init ("empty braces in initializer");
#endif
if (p->replacement_value)
{
constructor = p->replacement_value;
if (p->next == 0 && constructor_decl != 0
&& constructor_incremental)
{
constructor = digest_init (constructor_type, constructor,
require_constant_value,
require_constant_elements);
if (TREE_CODE (constructor_type) == ARRAY_TYPE
&& TYPE_DOMAIN (constructor_type) == 0)
{
int failure;
int momentary_p;
push_obstacks_nochange ();
if (TREE_PERMANENT (constructor_type))
end_temporary_allocation ();
momentary_p = suspend_momentary ();
if (constructor_stack->next)
abort ();
failure
= complete_array_type (constructor_type,
constructor, 0);
if (failure)
abort ();
size = int_size_in_bytes (constructor_type);
resume_momentary (momentary_p);
pop_obstacks ();
}
output_constant (constructor, size);
}
}
else if (constructor_type == 0)
;
else if (TREE_CODE (constructor_type) != RECORD_TYPE
&& TREE_CODE (constructor_type) != UNION_TYPE
&& TREE_CODE (constructor_type) != ARRAY_TYPE
&& ! constructor_incremental)
{
if (constructor_elements == 0)
{
error_init ("empty scalar initializer");
constructor = error_mark_node;
}
else if (TREE_CHAIN (constructor_elements) != 0)
{
error_init ("extra elements in scalar initializer");
constructor = TREE_VALUE (constructor_elements);
}
else
constructor = TREE_VALUE (constructor_elements);
}
else if (! constructor_incremental)
{
if (constructor_erroneous)
constructor = error_mark_node;
else
{
int momentary = suspend_momentary ();
constructor = build (CONSTRUCTOR, constructor_type, NULL_TREE,
nreverse (constructor_elements));
if (constructor_constant)
TREE_CONSTANT (constructor) = 1;
if (constructor_constant && constructor_simple)
TREE_STATIC (constructor) = 1;
resume_momentary (momentary);
}
}
else
{
tree filled;
int momentary = suspend_momentary ();
if (TREE_CODE (constructor_type) == RECORD_TYPE
|| TREE_CODE (constructor_type) == UNION_TYPE)
{
filled = size_binop (CEIL_DIV_EXPR,
constructor_bit_index,
size_int (BITS_PER_UNIT));
}
else if (TREE_CODE (constructor_type) == ARRAY_TYPE)
{
if (TREE_CODE (constructor_type) == ARRAY_TYPE
&& TYPE_DOMAIN (constructor_type) == 0)
{
tree maxindex
= size_binop (MINUS_EXPR,
constructor_unfilled_index,
integer_one_node);
push_obstacks_nochange ();
if (TREE_PERMANENT (constructor_type))
end_temporary_allocation ();
maxindex = copy_node (maxindex);
TYPE_DOMAIN (constructor_type) = build_index_type (maxindex);
TREE_TYPE (maxindex) = TYPE_DOMAIN (constructor_type);
if (pedantic
&& (tree_int_cst_sgn (TYPE_MAX_VALUE (TYPE_DOMAIN (constructor_type)))
< 0))
error_with_decl (constructor_decl,
"zero or negative array size `%s'");
layout_type (constructor_type);
size = int_size_in_bytes (constructor_type);
pop_obstacks ();
}
filled = size_binop (MULT_EXPR, constructor_unfilled_index,
size_in_bytes (TREE_TYPE (constructor_type)));
}
else
filled = 0;
if (filled != 0)
assemble_zeros (size - TREE_INT_CST_LOW (filled));
resume_momentary (momentary);
}
constructor_type = p->type;
constructor_fields = p->fields;
constructor_index = p->index;
constructor_range_end = p->range_end;
constructor_max_index = p->max_index;
constructor_unfilled_index = p->unfilled_index;
constructor_unfilled_fields = p->unfilled_fields;
constructor_bit_index = p->bit_index;
constructor_elements = p->elements;
constructor_constant = p->constant;
constructor_simple = p->simple;
constructor_erroneous = p->erroneous;
constructor_pending_elts = p->pending_elts;
constructor_depth = p->depth;
constructor_incremental = p->incremental;
RESTORE_SPELLING_DEPTH (constructor_depth);
constructor_stack = p->next;
free (p);
if (constructor == 0)
{
if (constructor_stack == 0)
return error_mark_node;
return NULL_TREE;
}
return constructor;
}
void
set_init_index (first, last)
tree first, last;
{
while ((TREE_CODE (first) == NOP_EXPR
|| TREE_CODE (first) == CONVERT_EXPR
|| TREE_CODE (first) == NON_LVALUE_EXPR)
&& (TYPE_MODE (TREE_TYPE (first))
== TYPE_MODE (TREE_TYPE (TREE_OPERAND (first, 0)))))
(first) = TREE_OPERAND (first, 0);
if (last)
while ((TREE_CODE (last) == NOP_EXPR
|| TREE_CODE (last) == CONVERT_EXPR
|| TREE_CODE (last) == NON_LVALUE_EXPR)
&& (TYPE_MODE (TREE_TYPE (last))
== TYPE_MODE (TREE_TYPE (TREE_OPERAND (last, 0)))))
(last) = TREE_OPERAND (last, 0);
if (TREE_CODE (first) != INTEGER_CST)
error_init ("nonconstant array index in initializer");
else if (last != 0 && TREE_CODE (last) != INTEGER_CST)
error_init ("nonconstant array index in initializer");
else if (! constructor_unfilled_index)
error_init ("array index in non-array initializer");
else if (tree_int_cst_lt (first, constructor_unfilled_index))
error_init ("duplicate array index in initializer");
else
{
TREE_INT_CST_LOW (constructor_index) = TREE_INT_CST_LOW (first);
TREE_INT_CST_HIGH (constructor_index) = TREE_INT_CST_HIGH (first);
if (last != 0 && tree_int_cst_lt (last, first))
error_init ("empty index range in initializer");
else
{
if (pedantic)
pedwarn ("ANSI C forbids specifying element to initialize");
constructor_range_end = last;
}
}
}
void
set_init_label (fieldname)
tree fieldname;
{
tree tail;
int passed = 0;
if (constructor_type == 0)
return;
for (tail = TYPE_FIELDS (constructor_type); tail;
tail = TREE_CHAIN (tail))
{
if (tail == constructor_unfilled_fields)
passed = 1;
if (DECL_NAME (tail) == fieldname)
break;
}
if (tail == 0)
error ("unknown field `%s' specified in initializer",
IDENTIFIER_POINTER (fieldname));
else if (!passed)
error ("field `%s' already initialized",
IDENTIFIER_POINTER (fieldname));
else
{
constructor_fields = tail;
if (pedantic)
pedwarn ("ANSI C forbids specifying structure member to initialize");
}
}
static void
add_pending_init (purpose, value)
tree purpose, value;
{
struct init_node *p, **q, *r;
q = &constructor_pending_elts;
p = 0;
if (TREE_CODE (constructor_type) == ARRAY_TYPE)
{
while (*q != 0)
{
p = *q;
if (tree_int_cst_lt (purpose, p->purpose))
q = &p->left;
else if (tree_int_cst_lt (p->purpose, purpose))
q = &p->right;
else
abort ();
}
}
else
{
while (*q != NULL)
{
p = *q;
if (tree_int_cst_lt (DECL_FIELD_BITPOS (purpose),
DECL_FIELD_BITPOS (p->purpose)))
q = &p->left;
else if (tree_int_cst_lt (DECL_FIELD_BITPOS (p->purpose),
DECL_FIELD_BITPOS (purpose)))
q = &p->right;
else
abort ();
}
}
r = (struct init_node *) oballoc (sizeof (struct init_node));
r->purpose = purpose;
r->value = value;
*q = r;
r->parent = p;
r->left = 0;
r->right = 0;
r->balance = 0;
while (p)
{
struct init_node *s;
if (r == p->left)
{
if (p->balance == 0)
p->balance = -1;
else if (p->balance < 0)
{
if (r->balance < 0)
{
p->left = r->right;
if (p->left)
p->left->parent = p;
r->right = p;
p->balance = 0;
r->balance = 0;
s = p->parent;
p->parent = r;
r->parent = s;
if (s)
{
if (s->left == p)
s->left = r;
else
s->right = r;
}
else
constructor_pending_elts = r;
}
else
{
struct init_node *t = r->right;
r->right = t->left;
if (r->right)
r->right->parent = r;
t->left = r;
p->left = t->right;
if (p->left)
p->left->parent = p;
t->right = p;
p->balance = t->balance < 0;
r->balance = -(t->balance > 0);
t->balance = 0;
s = p->parent;
p->parent = t;
r->parent = t;
t->parent = s;
if (s)
{
if (s->left == p)
s->left = t;
else
s->right = t;
}
else
constructor_pending_elts = t;
}
break;
}
else
{
p->balance = 0;
break;
}
}
else
{
if (p->balance == 0)
p->balance++;
else if (p->balance > 0)
{
if (r->balance > 0)
{
p->right = r->left;
if (p->right)
p->right->parent = p;
r->left = p;
p->balance = 0;
r->balance = 0;
s = p->parent;
p->parent = r;
r->parent = s;
if (s)
{
if (s->left == p)
s->left = r;
else
s->right = r;
}
else
constructor_pending_elts = r;
}
else
{
struct init_node *t = r->left;
r->left = t->right;
if (r->left)
r->left->parent = r;
t->right = r;
p->right = t->left;
if (p->right)
p->right->parent = p;
t->left = p;
r->balance = (t->balance < 0);
p->balance = -(t->balance > 0);
t->balance = 0;
s = p->parent;
p->parent = t;
r->parent = t;
t->parent = s;
if (s)
{
if (s->left == p)
s->left = t;
else
s->right = t;
}
else
constructor_pending_elts = t;
}
break;
}
else
{
p->balance = 0;
break;
}
}
r = p;
p = p->parent;
}
}
static int
pending_init_member (field)
tree field;
{
struct init_node *p;
p = constructor_pending_elts;
if (TREE_CODE (constructor_type) == ARRAY_TYPE)
{
while (p)
{
if (tree_int_cst_equal (field, p->purpose))
return 1;
else if (tree_int_cst_lt (field, p->purpose))
p = p->left;
else
p = p->right;
}
}
else
{
while (p)
{
if (field == p->purpose)
return 1;
else if (tree_int_cst_lt (DECL_FIELD_BITPOS (field),
DECL_FIELD_BITPOS (p->purpose)))
p = p->left;
else
p = p->right;
}
}
return 0;
}
static void
output_init_element (value, type, field, pending)
tree value, type, field;
int pending;
{
int duplicate = 0;
if (TREE_CODE (TREE_TYPE (value)) == FUNCTION_TYPE
|| (TREE_CODE (TREE_TYPE (value)) == ARRAY_TYPE
&& !(TREE_CODE (value) == STRING_CST
&& TREE_CODE (type) == ARRAY_TYPE
&& TREE_CODE (TREE_TYPE (type)) == INTEGER_TYPE)
&& !comptypes (TYPE_MAIN_VARIANT (TREE_TYPE (value)),
TYPE_MAIN_VARIANT (type))))
value = default_conversion (value);
if (value == error_mark_node)
constructor_erroneous = 1;
else if (!TREE_CONSTANT (value))
constructor_constant = 0;
else if (initializer_constant_valid_p (value, TREE_TYPE (value)) == 0
|| ((TREE_CODE (constructor_type) == RECORD_TYPE
|| TREE_CODE (constructor_type) == UNION_TYPE)
&& DECL_C_BIT_FIELD (field)
&& TREE_CODE (value) != INTEGER_CST))
constructor_simple = 0;
if (require_constant_value && ! TREE_CONSTANT (value))
{
error_init ("initializer element is not constant");
value = error_mark_node;
}
else if (require_constant_elements
&& initializer_constant_valid_p (value, TREE_TYPE (value)) == 0)
{
error_init ("initializer element is not computable at load time");
value = error_mark_node;
}
if (pending)
{
if (TREE_CODE (constructor_type) == RECORD_TYPE
|| TREE_CODE (constructor_type) == UNION_TYPE
|| TREE_CODE (constructor_type) == ARRAY_TYPE)
{
if (pending_init_member (field))
{
error_init ("duplicate initializer");
duplicate = 1;
}
}
}
if (TREE_CODE (constructor_type) == ARRAY_TYPE
&& !tree_int_cst_equal (field, constructor_unfilled_index))
{
if (! duplicate)
add_pending_init (copy_node (field),
digest_init (type, value, require_constant_value,
require_constant_elements));
}
else if (TREE_CODE (constructor_type) == RECORD_TYPE
&& field != constructor_unfilled_fields)
{
if (!duplicate)
add_pending_init (field,
digest_init (type, value, require_constant_value,
require_constant_elements));
}
else
{
if (!duplicate)
{
if (! constructor_incremental)
{
if (field && TREE_CODE (field) == INTEGER_CST)
field = copy_node (field);
constructor_elements
= tree_cons (field, digest_init (type, value,
require_constant_value,
require_constant_elements),
constructor_elements);
}
else
{
if (TREE_CODE (constructor_type) == RECORD_TYPE)
{
if (! tree_int_cst_equal (constructor_bit_index,
DECL_FIELD_BITPOS (field)))
{
unsigned next = (TREE_INT_CST_LOW
(DECL_FIELD_BITPOS (field))
/ (unsigned)BITS_PER_UNIT);
unsigned here = (TREE_INT_CST_LOW
(constructor_bit_index)
/ (unsigned)BITS_PER_UNIT);
assemble_zeros ((next - here)
* (unsigned)BITS_PER_UNIT
/ (unsigned)BITS_PER_UNIT);
}
}
output_constant (digest_init (type, value,
require_constant_value,
require_constant_elements),
int_size_in_bytes (type));
if (TREE_CODE (constructor_type) == RECORD_TYPE
|| TREE_CODE (constructor_type) == UNION_TYPE)
{
tree temp = size_binop (PLUS_EXPR, DECL_FIELD_BITPOS (field),
DECL_SIZE (field));
TREE_INT_CST_LOW (constructor_bit_index)
= TREE_INT_CST_LOW (temp);
TREE_INT_CST_HIGH (constructor_bit_index)
= TREE_INT_CST_HIGH (temp);
}
}
}
if (TREE_CODE (constructor_type) == ARRAY_TYPE)
{
tree tem = size_binop (PLUS_EXPR, constructor_unfilled_index,
integer_one_node);
TREE_INT_CST_LOW (constructor_unfilled_index)
= TREE_INT_CST_LOW (tem);
TREE_INT_CST_HIGH (constructor_unfilled_index)
= TREE_INT_CST_HIGH (tem);
}
else if (TREE_CODE (constructor_type) == RECORD_TYPE)
constructor_unfilled_fields = TREE_CHAIN (constructor_unfilled_fields);
else if (TREE_CODE (constructor_type) == UNION_TYPE)
constructor_unfilled_fields = 0;
if (pending)
output_pending_init_elements (0);
}
}
static void
output_pending_init_elements (all)
int all;
{
struct init_node *elt = constructor_pending_elts;
tree next;
retry:
next = 0;
while (elt)
{
if (TREE_CODE (constructor_type) == ARRAY_TYPE)
{
if (tree_int_cst_equal (elt->purpose,
constructor_unfilled_index))
output_init_element (elt->value,
TREE_TYPE (constructor_type),
constructor_unfilled_index, 0);
else if (tree_int_cst_lt (constructor_unfilled_index,
elt->purpose))
{
if (elt->left)
elt = elt->left;
else
{
next = elt->purpose;
break;
}
}
else
{
if (elt->right)
elt = elt->right;
else
{
while (elt->parent && elt->parent->right == elt)
elt = elt->parent;
elt = elt->parent;
if (elt && tree_int_cst_lt (constructor_unfilled_index,
elt->purpose))
{
next = elt->purpose;
break;
}
}
}
}
else if (TREE_CODE (constructor_type) == RECORD_TYPE
|| TREE_CODE (constructor_type) == UNION_TYPE)
{
if (constructor_unfilled_fields == 0)
break;
if (elt->purpose == constructor_unfilled_fields)
{
output_init_element (elt->value,
TREE_TYPE (constructor_unfilled_fields),
constructor_unfilled_fields,
0);
}
else if (tree_int_cst_lt (DECL_FIELD_BITPOS (constructor_unfilled_fields),
DECL_FIELD_BITPOS (elt->purpose)))
{
if (elt->left)
elt = elt->left;
else
{
next = elt->purpose;
break;
}
}
else
{
if (elt->right)
elt = elt->right;
else
{
while (elt->parent && elt->parent->right == elt)
elt = elt->parent;
elt = elt->parent;
if (elt
&& tree_int_cst_lt (DECL_FIELD_BITPOS (constructor_unfilled_fields),
DECL_FIELD_BITPOS (elt->purpose)))
{
next = elt->purpose;
break;
}
}
}
}
}
if (! (all && next != 0))
return;
if (constructor_incremental)
{
tree filled;
tree nextpos_tree = size_int (0);
if (TREE_CODE (constructor_type) == RECORD_TYPE
|| TREE_CODE (constructor_type) == UNION_TYPE)
{
tree tail;
for (tail = TYPE_FIELDS (constructor_type); tail;
tail = TREE_CHAIN (tail))
if (TREE_CHAIN (tail) == constructor_unfilled_fields)
break;
if (tail)
filled = size_binop (CEIL_DIV_EXPR,
size_binop (PLUS_EXPR,
DECL_FIELD_BITPOS (tail),
DECL_SIZE (tail)),
size_int (BITS_PER_UNIT));
else
filled = size_int (0);
nextpos_tree = size_binop (CEIL_DIV_EXPR,
DECL_FIELD_BITPOS (next),
size_int (BITS_PER_UNIT));
TREE_INT_CST_HIGH (constructor_bit_index)
= TREE_INT_CST_HIGH (DECL_FIELD_BITPOS (next));
TREE_INT_CST_LOW (constructor_bit_index)
= TREE_INT_CST_LOW (DECL_FIELD_BITPOS (next));
constructor_unfilled_fields = next;
}
else if (TREE_CODE (constructor_type) == ARRAY_TYPE)
{
filled = size_binop (MULT_EXPR, constructor_unfilled_index,
size_in_bytes (TREE_TYPE (constructor_type)));
nextpos_tree
= size_binop (MULT_EXPR, next,
size_in_bytes (TREE_TYPE (constructor_type)));
TREE_INT_CST_LOW (constructor_unfilled_index)
= TREE_INT_CST_LOW (next);
TREE_INT_CST_HIGH (constructor_unfilled_index)
= TREE_INT_CST_HIGH (next);
}
else
filled = 0;
if (filled)
{
int nextpos = TREE_INT_CST_LOW (nextpos_tree);
assemble_zeros (nextpos - TREE_INT_CST_LOW (filled));
}
}
else
{
if (TREE_CODE (constructor_type) == RECORD_TYPE
|| TREE_CODE (constructor_type) == UNION_TYPE)
constructor_unfilled_fields = next;
else if (TREE_CODE (constructor_type) == ARRAY_TYPE)
{
TREE_INT_CST_LOW (constructor_unfilled_index)
= TREE_INT_CST_LOW (next);
TREE_INT_CST_HIGH (constructor_unfilled_index)
= TREE_INT_CST_HIGH (next);
}
}
goto retry;
}
void
process_init_element (value)
tree value;
{
extern int errorcount;
tree orig_value = value;
int string_flag = value != 0 && TREE_CODE (value) == STRING_CST;
if (string_flag
&& constructor_type
&& TREE_CODE (constructor_type) == ARRAY_TYPE
&& TREE_CODE (TREE_TYPE (constructor_type)) == INTEGER_TYPE
&& integer_zerop (constructor_unfilled_index))
{
constructor_stack->replacement_value = value;
return;
}
if (constructor_stack->replacement_value != 0)
{
error_init ("excess elements in struct initializer");
return;
}
if (value && TREE_CODE (value) == ERROR_MARK && errorcount)
{
fatal ("too many errors, bailing out");
}
if (constructor_type == 0)
return;
while (constructor_stack->implicit)
{
if ((TREE_CODE (constructor_type) == RECORD_TYPE
|| TREE_CODE (constructor_type) == UNION_TYPE)
&& constructor_fields == 0)
process_init_element (pop_init_level (1));
else if (TREE_CODE (constructor_type) == ARRAY_TYPE
&& (constructor_max_index == 0
|| tree_int_cst_lt (constructor_max_index,
constructor_index)))
process_init_element (pop_init_level (1));
else
break;
}
while (1)
{
if (TREE_CODE (constructor_type) == RECORD_TYPE)
{
tree fieldtype;
enum tree_code fieldcode;
if (constructor_fields == 0)
{
pedwarn_init ("excess elements in struct initializer");
break;
}
fieldtype = TREE_TYPE (constructor_fields);
if (fieldtype != error_mark_node)
fieldtype = TYPE_MAIN_VARIANT (fieldtype);
fieldcode = TREE_CODE (fieldtype);
if (value != 0
&& fieldcode == ARRAY_TYPE
&& TREE_CODE (TREE_TYPE (fieldtype)) == INTEGER_TYPE
&& string_flag)
value = orig_value;
else if (value != 0 && !constructor_no_implicit
&& value != error_mark_node
&& TYPE_MAIN_VARIANT (TREE_TYPE (value)) != fieldtype
&& (fieldcode == RECORD_TYPE || fieldcode == ARRAY_TYPE
|| fieldcode == UNION_TYPE))
{
push_init_level (1);
continue;
}
if (value)
{
push_member_name (constructor_fields);
output_init_element (value, fieldtype, constructor_fields, 1);
RESTORE_SPELLING_DEPTH (constructor_depth);
}
else
{
tree temp = size_binop (PLUS_EXPR,
DECL_FIELD_BITPOS (constructor_fields),
DECL_SIZE (constructor_fields));
TREE_INT_CST_LOW (constructor_bit_index)
= TREE_INT_CST_LOW (temp);
TREE_INT_CST_HIGH (constructor_bit_index)
= TREE_INT_CST_HIGH (temp);
constructor_unfilled_fields = TREE_CHAIN (constructor_fields);
}
constructor_fields = TREE_CHAIN (constructor_fields);
while (constructor_fields != 0
&& DECL_C_BIT_FIELD (constructor_fields)
&& DECL_NAME (constructor_fields) == 0)
constructor_fields = TREE_CHAIN (constructor_fields);
break;
}
if (TREE_CODE (constructor_type) == UNION_TYPE)
{
tree fieldtype;
enum tree_code fieldcode;
if (constructor_fields == 0)
{
pedwarn_init ("excess elements in union initializer");
break;
}
fieldtype = TREE_TYPE (constructor_fields);
if (fieldtype != error_mark_node)
fieldtype = TYPE_MAIN_VARIANT (fieldtype);
fieldcode = TREE_CODE (fieldtype);
if (value != 0
&& fieldcode == ARRAY_TYPE
&& TREE_CODE (TREE_TYPE (fieldtype)) == INTEGER_TYPE
&& string_flag)
value = orig_value;
else if (value != 0 && !constructor_no_implicit
&& value != error_mark_node
&& TYPE_MAIN_VARIANT (TREE_TYPE (value)) != fieldtype
&& (fieldcode == RECORD_TYPE || fieldcode == ARRAY_TYPE
|| fieldcode == UNION_TYPE))
{
push_init_level (1);
continue;
}
if (value)
{
push_member_name (constructor_fields);
output_init_element (value, fieldtype, constructor_fields, 1);
RESTORE_SPELLING_DEPTH (constructor_depth);
}
else
{
TREE_INT_CST_LOW (constructor_bit_index)
= TREE_INT_CST_LOW (DECL_SIZE (constructor_fields));
TREE_INT_CST_HIGH (constructor_bit_index)
= TREE_INT_CST_HIGH (DECL_SIZE (constructor_fields));
constructor_unfilled_fields = TREE_CHAIN (constructor_fields);
}
constructor_fields = 0;
break;
}
if (TREE_CODE (constructor_type) == ARRAY_TYPE)
{
tree elttype = TYPE_MAIN_VARIANT (TREE_TYPE (constructor_type));
enum tree_code eltcode = TREE_CODE (elttype);
if (value != 0
&& eltcode == ARRAY_TYPE
&& TREE_CODE (TREE_TYPE (elttype)) == INTEGER_TYPE
&& string_flag)
value = orig_value;
else if (value != 0 && !constructor_no_implicit
&& value != error_mark_node
&& TYPE_MAIN_VARIANT (TREE_TYPE (value)) != elttype
&& (eltcode == RECORD_TYPE || eltcode == ARRAY_TYPE
|| eltcode == UNION_TYPE))
{
push_init_level (1);
continue;
}
if (constructor_max_index != 0
&& tree_int_cst_lt (constructor_max_index, constructor_index))
{
pedwarn_init ("excess elements in array initializer");
break;
}
if (constructor_range_end)
{
if (constructor_max_index != 0
&& tree_int_cst_lt (constructor_max_index,
constructor_range_end))
{
pedwarn_init ("excess elements in array initializer");
TREE_INT_CST_HIGH (constructor_range_end)
= TREE_INT_CST_HIGH (constructor_max_index);
TREE_INT_CST_LOW (constructor_range_end)
= TREE_INT_CST_LOW (constructor_max_index);
}
value = save_expr (value);
}
do
{
tree tem;
if (value)
{
push_array_bounds (TREE_INT_CST_LOW (constructor_index));
output_init_element (value, elttype, constructor_index, 1);
RESTORE_SPELLING_DEPTH (constructor_depth);
}
tem = size_binop (PLUS_EXPR, constructor_index,
integer_one_node);
TREE_INT_CST_LOW (constructor_index) = TREE_INT_CST_LOW (tem);
TREE_INT_CST_HIGH (constructor_index) = TREE_INT_CST_HIGH (tem);
if (!value)
{
TREE_INT_CST_LOW (constructor_unfilled_index)
= TREE_INT_CST_LOW (constructor_index);
TREE_INT_CST_HIGH (constructor_unfilled_index)
= TREE_INT_CST_HIGH (constructor_index);
}
}
while (! (constructor_range_end == 0
|| tree_int_cst_lt (constructor_range_end,
constructor_index)));
break;
}
if (constructor_fields == 0)
{
pedwarn_init ("excess elements in scalar initializer");
break;
}
if (value)
output_init_element (value, constructor_type, NULL_TREE, 1);
constructor_fields = 0;
break;
}
if (constructor_incremental && constructor_pending_elts == 0 && value != 0
&& constructor_stack == 0)
clear_momentary ();
}
void
c_expand_asm_operands (string, outputs, inputs, clobbers, vol, filename, line)
tree string, outputs, inputs, clobbers;
int vol;
char *filename;
int line;
{
int noutputs = list_length (outputs);
register int i;
register tree *o = (tree *) alloca (noutputs * sizeof (tree));
register tree tail;
if (TREE_CODE (string) == ADDR_EXPR)
string = TREE_OPERAND (string, 0);
if (TREE_CODE (string) != STRING_CST)
{
error ("asm template is not a string constant");
return;
}
for (i = 0, tail = outputs; tail; tail = TREE_CHAIN (tail), i++)
o[i] = TREE_VALUE (tail);
for (i = 0, tail = inputs; tail; tail = TREE_CHAIN (tail), i++)
if (TREE_CODE (TREE_TYPE (TREE_VALUE (tail))) == ARRAY_TYPE
|| TREE_CODE (TREE_TYPE (TREE_VALUE (tail))) == FUNCTION_TYPE)
TREE_VALUE (tail) = default_conversion (TREE_VALUE (tail));
expand_asm_operands (string, outputs, inputs, clobbers, vol, filename, line);
for (i = 0, tail = outputs; tail; tail = TREE_CHAIN (tail), i++)
{
if (o[i] != TREE_VALUE (tail))
{
expand_expr (build_modify_expr (o[i], NOP_EXPR, TREE_VALUE (tail)),
NULL_RTX, VOIDmode, EXPAND_NORMAL);
free_temp_slots ();
}
else
{
tree type = TREE_TYPE (o[i]);
if (TREE_READONLY (o[i])
|| TYPE_READONLY (type)
|| ((TREE_CODE (type) == RECORD_TYPE
|| TREE_CODE (type) == UNION_TYPE)
&& C_TYPE_FIELDS_READONLY (type)))
readonly_warning (o[i], "modification by `asm'");
}
}
emit_queue ();
}
void
c_expand_return (retval)
tree retval;
{
tree valtype = TREE_TYPE (TREE_TYPE (current_function_decl));
if (TREE_THIS_VOLATILE (current_function_decl))
warning ("function declared `noreturn' has a `return' statement");
if (!retval)
{
current_function_returns_null = 1;
if (warn_return_type && valtype != 0 && TREE_CODE (valtype) != VOID_TYPE)
warning ("`return' with no value, in function returning non-void");
expand_null_return ();
}
else if (valtype == 0 || TREE_CODE (valtype) == VOID_TYPE)
{
current_function_returns_null = 1;
if (pedantic || TREE_CODE (TREE_TYPE (retval)) != VOID_TYPE)
pedwarn ("`return' with a value, in function returning void");
expand_return (retval);
}
else
{
tree t = convert_for_assignment (valtype, retval, _("return"),
NULL_TREE, NULL_TREE, 0);
tree res = DECL_RESULT (current_function_decl);
tree inner;
if (t == error_mark_node)
return;
inner = t = convert (TREE_TYPE (res), t);
while (1)
{
switch (TREE_CODE (inner))
{
case NOP_EXPR: case NON_LVALUE_EXPR: case CONVERT_EXPR:
case PLUS_EXPR:
inner = TREE_OPERAND (inner, 0);
continue;
case MINUS_EXPR:
{
tree op1 = TREE_OPERAND (inner, 1);
while (! POINTER_TYPE_P (TREE_TYPE (op1))
&& (TREE_CODE (op1) == NOP_EXPR
|| TREE_CODE (op1) == NON_LVALUE_EXPR
|| TREE_CODE (op1) == CONVERT_EXPR))
op1 = TREE_OPERAND (op1, 0);
if (POINTER_TYPE_P (TREE_TYPE (op1)))
break;
inner = TREE_OPERAND (inner, 0);
continue;
}
case ADDR_EXPR:
inner = TREE_OPERAND (inner, 0);
while (TREE_CODE_CLASS (TREE_CODE (inner)) == 'r')
inner = TREE_OPERAND (inner, 0);
if (TREE_CODE (inner) == VAR_DECL
&& ! DECL_EXTERNAL (inner)
&& ! TREE_STATIC (inner)
&& DECL_CONTEXT (inner) == current_function_decl)
warning ("function returns address of local variable");
break;
default:
break;
}
break;
}
t = build (MODIFY_EXPR, TREE_TYPE (res), res, t);
TREE_SIDE_EFFECTS (t) = 1;
expand_return (t);
current_function_returns_value = 1;
}
}
tree
c_expand_start_case (exp)
tree exp;
{
register enum tree_code code = TREE_CODE (TREE_TYPE (exp));
tree type = TREE_TYPE (exp);
if (code != INTEGER_TYPE && code != ENUMERAL_TYPE && code != ERROR_MARK)
{
error ("switch quantity not an integer");
exp = error_mark_node;
}
else
{
tree index;
type = TYPE_MAIN_VARIANT (TREE_TYPE (exp));
if (warn_traditional
&& (type == long_integer_type_node
|| type == long_unsigned_type_node))
pedwarn ("`long' switch expression not converted to `int' in ANSI C");
exp = default_conversion (exp);
type = TREE_TYPE (exp);
index = get_unwidened (exp, NULL_TREE);
if (TREE_UNSIGNED (TREE_TYPE (exp))
== TREE_UNSIGNED (TREE_TYPE (index)))
exp = index;
}
expand_start_case (1, exp, type, "switch statement");
return exp;
}