/* Build expressions with type checking for C compiler.
- Copyright (C) 1987, 88, 91, 92, 93, 94, 1995 Free Software Foundation, Inc.
+ Copyright (C) 1987, 88, 91, 92-5, 1996 Free Software Foundation, Inc.
This file is part of GNU CC.
extern char *index ();
extern char *rindex ();
-static tree quality_type PROTO((tree, tree));
+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));
return t1;
/* Merge the attributes */
-
- { register tree a1, a2;
- a1 = TYPE_ATTRIBUTES (t1);
- a2 = TYPE_ATTRIBUTES (t2);
-
- /* Either one unset? Take the set one. */
-
- if (!(attributes = a1))
- attributes = a2;
-
- /* One that completely contains the other? Take it. */
-
- else if (a2 && !attribute_list_contained (a1, a2))
- if (attribute_list_contained (a2, a1))
- attributes = a2;
- else
- {
- /* Pick the longest list, and hang on the other list. */
- /* ??? For the moment we punt on the issue of attrs with args. */
-
- if (list_length (a1) < list_length (a2))
- attributes = a2, a2 = a1;
-
- for (; a2; a2 = TREE_CHAIN (a2))
- if (lookup_attribute (IDENTIFIER_POINTER (TREE_PURPOSE (a2)),
- attributes) == NULL_TREE)
- {
- a1 = copy_node (a2);
- TREE_CHAIN (a1) = attributes;
- attributes = a1;
- }
- }
- }
+ attributes = merge_attributes (TYPE_ATTRIBUTES (t1), TYPE_ATTRIBUTES (t2));
/* Treat an enum type as the unsigned integer type of the same width. */
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 type;
}
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 type;
}
return size_int (DECL_ALIGN (expr) / BITS_PER_UNIT);
if (TREE_CODE (expr) == COMPONENT_REF
- && DECL_BIT_FIELD (TREE_OPERAND (expr, 1)))
+ && DECL_C_BIT_FIELD (TREE_OPERAND (expr, 1)))
{
error ("`__alignof' applied to a bit-field");
return size_int (1);
if (ar == error_mark_node)
return ar;
- if (TREE_CODE (TREE_TYPE (ar)) != POINTER_TYPE)
+ 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;
|| code2 == BIT_AND_EXPR || code2 == BIT_XOR_EXPR
|| code2 == PLUS_EXPR || code2 == MINUS_EXPR)
warning ("suggest parentheses around arithmetic in operand of |");
+ /* Check cases like x|y==z */
+ if (TREE_CODE_CLASS (code1) == '<' || TREE_CODE_CLASS (code2) == '<')
+ warning ("suggest parentheses around comparison in operand of |");
}
if (code == BIT_XOR_EXPR)
|| code2 == BIT_AND_EXPR
|| code2 == PLUS_EXPR || code2 == MINUS_EXPR)
warning ("suggest parentheses around arithmetic in operand of ^");
+ /* Check cases like x^y==z */
+ 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 &");
+ /* Check cases like x&y==z */
+ if (TREE_CODE_CLASS (code1) == '<' || TREE_CODE_CLASS (code2) == '<')
+ warning ("suggest parentheses around comparison in operand of &");
}
}
converted = 1;
resultcode = xresultcode;
- if (extra_warnings)
+ if (warn_sign_compare)
{
int op0_signed = ! TREE_UNSIGNED (TREE_TYPE (orig_op0));
int op1_signed = ! TREE_UNSIGNED (TREE_TYPE (orig_op1));
not use the most significant bit of result_type. */
else if ((resultcode == EQ_EXPR || resultcode == NE_EXPR)
&& ((op0_signed && TREE_CODE (xop1) == INTEGER_CST
- && int_fits_type_p (xop1, signed_type (result_type))
+ && 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))))))
+ && int_fits_type_p (xop0, signed_type (result_type)))))
/* OK */;
else
warning ("comparison between signed and unsigned");
&& TREE_CONSTANT (size_exp)
/* If the constant comes from pointer subtraction,
skip this optimization--it would cause an error. */
- && TREE_CODE (TREE_TYPE (TREE_OPERAND (intop, 0))) == INTEGER_TYPE)
+ && TREE_CODE (TREE_TYPE (TREE_OPERAND (intop, 0))) == INTEGER_TYPE
+ /* If the constant is unsigned, and smaller than the pointer size,
+ then we must skip this optimization. This is because it could cause
+ an overflow error if the constant is negative but INTOP is not. */
+ && (! 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);
intop = convert (int_type, TREE_OPERAND (intop, 0));
}
- /* Convert the integer argument to a type the same size as a pointer
+ /* Convert the integer argument to a type the same size as sizetype
so the multiply won't overflow spuriously. */
- if (TYPE_PRECISION (TREE_TYPE (intop)) != POINTER_SIZE)
- intop = convert (type_for_size (POINTER_SIZE, 0), intop);
+ if (TYPE_PRECISION (TREE_TYPE (intop)) != TYPE_PRECISION (sizetype))
+ intop = convert (type_for_size (TYPE_PRECISION (sizetype), 0), intop);
/* Replace the integer argument with a suitable product by the object size.
Do this multiplication as signed, then convert to the appropriate
addr = build_unary_op (ADDR_EXPR, TREE_OPERAND (arg, 0), 0);
- if (DECL_BIT_FIELD (field))
+ if (DECL_C_BIT_FIELD (field))
{
error ("attempt to take address of bit-field structure member `%s'",
IDENTIFIER_POINTER (DECL_NAME (field)));
while (1)
switch (TREE_CODE (x))
{
- case ADDR_EXPR:
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;
+ }
+
+ /* ... fall through ... */
+
+ case ADDR_EXPR:
case ARRAY_REF:
case REALPART_EXPR:
case IMAGPART_EXPR:
{
if (pedantic)
pedwarn ("ANSI C forbids omitting the middle term of a ?: expression");
- ifexp = op1 = save_expr (ifexp);
+ ifexp = orig_op1 = op1 = save_expr (ifexp);
}
ifexp = truthvalue_conversion (default_conversion (ifexp));
&& TREE_CODE (otype) == POINTER_TYPE
&& TREE_CODE (TREE_TYPE (otype)) != VOID_TYPE
&& TREE_CODE (TREE_TYPE (otype)) != FUNCTION_TYPE
+ /* Don't warn about opaque types, where the actual alignment
+ restriction is unknown. */
+ && !((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");
|| coder == COMPLEX_TYPE))
return convert_and_check (type, rhs);
- /* Conversion to a union from its member types. */
- else if (codel == UNION_TYPE)
+ /* Conversion to a transparent union from its member types.
+ This applies only to function arguments. */
+ 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))
{
- if (comptypes (TREE_TYPE (memb_types), TREE_TYPE (rhs)))
- {
- if (pedantic
- && !(fundecl != 0 && DECL_IN_SYSTEM_HEADER (fundecl)))
- pedwarn ("ANSI C prohibits argument conversion to union type");
- return build1 (NOP_EXPR, type, rhs);
- }
+ tree memb_type = TREE_TYPE (memb_types);
- else if (coder == POINTER_TYPE
- && TREE_CODE (TREE_TYPE (memb_types)) == POINTER_TYPE)
+ if (comptypes (TYPE_MAIN_VARIANT (memb_type),
+ TYPE_MAIN_VARIANT (rhstype)))
+ break;
+
+ if (TREE_CODE (memb_type) != POINTER_TYPE)
+ continue;
+
+ if (coder == POINTER_TYPE)
{
- tree memb_type = TREE_TYPE (memb_types);
register tree ttl = TREE_TYPE (memb_type);
register tree ttr = TREE_TYPE (rhstype);
|| TYPE_MAIN_VARIANT (ttr) == void_type_node
|| comp_target_types (memb_type, rhstype))
{
- /* Const and volatile mean something different for function
- types, so the usual warnings are not appropriate. */
- if (TREE_CODE (ttr) != FUNCTION_TYPE
- || TREE_CODE (ttl) != FUNCTION_TYPE)
- {
- if (! TYPE_READONLY (ttl) && TYPE_READONLY (ttr))
- warn_for_assignment ("%s discards `const' from pointer target type",
- get_spelling (errtype), funname,
- parmnum);
- if (! TYPE_VOLATILE (ttl) && TYPE_VOLATILE (ttr))
- warn_for_assignment ("%s discards `volatile' from pointer target type",
- get_spelling (errtype), funname,
- parmnum);
- }
- else
- {
- /* Because const and volatile on functions are
- restrictions that say the function will not do
- certain things, it is okay to use a const or volatile
- function where an ordinary one is wanted, but not
- vice-versa. */
- if (TYPE_READONLY (ttl) && ! TYPE_READONLY (ttr))
- warn_for_assignment ("%s makes `const *' function pointer from non-const",
- get_spelling (errtype), funname,
- parmnum);
- if (TYPE_VOLATILE (ttl) && ! TYPE_VOLATILE (ttr))
- warn_for_assignment ("%s makes `volatile *' function pointer from non-volatile",
- get_spelling (errtype), funname,
- parmnum);
- }
-
- if (pedantic
- && !(fundecl != 0 && DECL_IN_SYSTEM_HEADER (fundecl)))
- pedwarn ("ANSI C prohibits argument conversion to union type");
- return build1 (NOP_EXPR, type, rhs);
+ /* If this type won't generate any warnings, use it. */
+ if ((TREE_CODE (ttr) == FUNCTION_TYPE
+ && TREE_CODE (ttl) == FUNCTION_TYPE)
+ ? ((! TYPE_READONLY (ttl) | TYPE_READONLY (ttr))
+ & (! TYPE_VOLATILE (ttl) | TYPE_VOLATILE (ttr)))
+ : ((TYPE_READONLY (ttl) | ! TYPE_READONLY (ttr))
+ & (TYPE_VOLATILE (ttl) | ! TYPE_VOLATILE (ttr))))
+ break;
+
+ /* Keep looking for a better type, but remember this one. */
+ if (! marginal_memb_type)
+ marginal_memb_type = memb_type;
}
}
/* Can convert integer zero to any pointer type. */
- else if (TREE_CODE (TREE_TYPE (memb_types)) == POINTER_TYPE
- && (integer_zerop (rhs)
- || (TREE_CODE (rhs) == NOP_EXPR
- && integer_zerop (TREE_OPERAND (rhs, 0)))))
- return build1 (NOP_EXPR, type, null_pointer_node);
+ 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)
+ {
+ /* We have only a marginally acceptable member type;
+ it needs a warning. */
+ register tree ttl = TREE_TYPE (marginal_memb_type);
+ register tree ttr = TREE_TYPE (rhstype);
+
+ /* Const and volatile mean something different for function
+ types, so the usual warnings are not appropriate. */
+ if (TREE_CODE (ttr) == FUNCTION_TYPE
+ && TREE_CODE (ttl) == FUNCTION_TYPE)
+ {
+ /* Because const and volatile on functions are
+ restrictions that say the function will not do
+ certain things, it is okay to use a const or volatile
+ function where an ordinary one is wanted, but not
+ vice-versa. */
+ if (TYPE_READONLY (ttl) && ! TYPE_READONLY (ttr))
+ warn_for_assignment ("%s makes `const *' function pointer from non-const",
+ get_spelling (errtype), funname,
+ parmnum);
+ if (TYPE_VOLATILE (ttl) && ! TYPE_VOLATILE (ttr))
+ warn_for_assignment ("%s makes `volatile *' function pointer from non-volatile",
+ get_spelling (errtype), funname,
+ parmnum);
+ }
+ else
+ {
+ if (! TYPE_READONLY (ttl) && TYPE_READONLY (ttr))
+ warn_for_assignment ("%s discards `const' from pointer target type",
+ get_spelling (errtype), funname,
+ parmnum);
+ if (! TYPE_VOLATILE (ttl) && TYPE_VOLATILE (ttr))
+ warn_for_assignment ("%s discards `volatile' from pointer target type",
+ get_spelling (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);
}
}
case CONSTRUCTOR:
if ((TREE_CODE (TREE_TYPE (value)) == UNION_TYPE
|| TREE_CODE (TREE_TYPE (value)) == RECORD_TYPE)
- && TREE_CONSTANT (value))
+ && TREE_CONSTANT (value)
+ && CONSTRUCTOR_ELTS (value))
return
initializer_constant_valid_p (TREE_VALUE (CONSTRUCTOR_ELTS (value)),
endtype);
and it initializes the first element of x to 0. */
if (flag_traditional)
{
- tree top = 0, prev = 0;
+ tree top = 0, prev = 0, otype = type;
while (TREE_CODE (type) == RECORD_TYPE
|| TREE_CODE (type) == ARRAY_TYPE
|| TREE_CODE (type) == QUAL_UNION_TYPE
return error_mark_node;
}
}
- TREE_OPERAND (prev, 1)
- = build_tree_list (NULL_TREE,
- digest_init (type, init, require_constant,
- constructor_constant));
- return top;
+
+ 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%s", " for `%s'", NULL);
return error_mark_node;
|| TREE_CODE (constructor_type) == UNION_TYPE)
{
constructor_fields = TYPE_FIELDS (constructor_type);
- /* Skip any nameless bit fields atthe beginning. */
- while (constructor_fields != 0 && DECL_BIT_FIELD (constructor_fields)
+ /* Skip any nameless bit fields at the beginning. */
+ 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;
break;
}
- /* Structure elements may require alignment. Do this now
- if necessary for the subaggregate. */
+ /* Structure elements may require alignment. Do this now if necessary
+ for the subaggregate, and if it comes next in sequence. Don't do
+ this for subaggregates that will go on the pending list. */
if (constructor_incremental && constructor_type != 0
- && TREE_CODE (constructor_type) == RECORD_TYPE && constructor_fields)
+ && TREE_CODE (constructor_type) == RECORD_TYPE && constructor_fields
+ && constructor_fields == constructor_unfilled_fields)
{
/* Advance to offset of this element. */
if (! tree_int_cst_equal (constructor_bit_index,
assemble_zeros (next - here);
}
+ /* Indicate that we have now filled the structure up to the current
+ field. */
+ constructor_unfilled_fields = constructor_fields;
}
p = (struct constructor_stack *) xmalloc (sizeof (struct constructor_stack));
|| TREE_CODE (constructor_type) == UNION_TYPE)
{
constructor_fields = TYPE_FIELDS (constructor_type);
- /* Skip any nameless bit fields atthe beginning. */
- while (constructor_fields != 0 && DECL_BIT_FIELD (constructor_fields)
+ /* Skip any nameless bit fields at the beginning. */
+ 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;
for (tail = TYPE_FIELDS (type); tail;
tail = TREE_CHAIN (tail))
{
- if (DECL_BIT_FIELD (tail)
+ if (DECL_C_BIT_FIELD (tail)
/* This catches cases like `int foo : 8;'. */
|| DECL_MODE (tail) != TYPE_MODE (TREE_TYPE (tail)))
{
error_init ("nonconstant array index in initializer%s", " for `%s'", NULL);
else if (last != 0 && TREE_CODE (last) != INTEGER_CST)
error_init ("nonconstant array index in initializer%s", " for `%s'", NULL);
+ else if (! constructor_unfilled_index)
+ error_init ("array index in non-array initializer%s", " for `%s'", NULL);
else if (tree_int_cst_lt (first, constructor_unfilled_index))
error_init ("duplicate array index in initializer%s", " for `%s'", NULL);
else
tree tail;
int passed = 0;
+ /* Don't die if an entire brace-pair level is superfluous
+ in the containing level. */
+ if (constructor_type == 0)
+ return;
+
for (tail = TYPE_FIELDS (constructor_type); tail;
tail = TREE_CHAIN (tail))
{
else if (initializer_constant_valid_p (value, TREE_TYPE (value)) == 0
|| ((TREE_CODE (constructor_type) == RECORD_TYPE
|| TREE_CODE (constructor_type) == UNION_TYPE)
- && DECL_BIT_FIELD (field) && TREE_CODE (value) != INTEGER_CST))
+ && DECL_C_BIT_FIELD (field)
+ && TREE_CODE (value) != INTEGER_CST))
constructor_simple = 0;
if (require_constant_value && ! TREE_CONSTANT (value))
}
constructor_fields = TREE_CHAIN (constructor_fields);
- /* Skip any nameless bit fields atthe beginning. */
- while (constructor_fields != 0 && DECL_BIT_FIELD (constructor_fields)
+ /* Skip any nameless bit fields at the beginning. */
+ while (constructor_fields != 0
+ && DECL_C_BIT_FIELD (constructor_fields)
&& DECL_NAME (constructor_fields) == 0)
constructor_fields = TREE_CHAIN (constructor_fields);
break;
else
{
tree type = TREE_TYPE (o[i]);
- if (TYPE_READONLY (type)
+ if (TREE_READONLY (o[i])
+ || TYPE_READONLY (type)
|| ((TREE_CODE (type) == RECORD_TYPE
|| TREE_CODE (type) == UNION_TYPE)
&& C_TYPE_FIELDS_READONLY (type)))