/* 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.
You should have received a copy of the GNU General Public License
along with GNU CC; see the file COPYING. If not, write to
-the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
/* This file is part of the C front end.
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. */
-
- if (list_length (a1) < list_length (a2))
- attributes = a2, a2 = a1;
-
- for (; a2; a2 = TREE_CHAIN (a2))
- if (!value_member (attributes, a2))
- {
- 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. */
}
t1 = build_function_type (valtype, newargs);
- /* ... falls through ... */
+ /* ... falls through ... */
}
default:
return long_unsigned_type_node;
if (type1 == long_long_integer_type_node)
return long_long_unsigned_type_node;
- return type;
+ 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);
}
/* Return a signed type the same as TYPE in other respects. */
return long_integer_type_node;
if (type1 == long_long_unsigned_type_node)
return long_long_integer_type_node;
- return type;
+ 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);
}
/* Return a type the same as TYPE except unsigned or
int unsignedp;
tree type;
{
- if (! INTEGRAL_TYPE_P (type))
+ if (! INTEGRAL_TYPE_P (type)
+ || TREE_UNSIGNED (type) == unsignedp)
return type;
if (TYPE_PRECISION (type) == TYPE_PRECISION (signed_char_type_node))
return unsignedp ? unsigned_char_type_node : signed_char_type_node;
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);
else
return c_alignof (TREE_TYPE (expr));
}
+
/* Return either DECL or its known constant value (if it has one). */
static tree
decl_constant_value (decl)
tree decl;
{
- if (! TREE_PUBLIC (decl)
- /* Don't change a variable array bound or initial value to a constant
+ if (/* Don't change a variable array bound or initial value to a constant
in a place where a variable is invalid. */
- && current_function_decl != 0
+ current_function_decl != 0
&& ! pedantic
&& ! TREE_THIS_VOLATILE (decl)
&& TREE_READONLY (decl) && ! ITERATOR_P (decl)
return convert (type, exp);
}
+ if (TREE_CODE (exp) == COMPONENT_REF
+ && DECL_BIT_FIELD (TREE_OPERAND (exp, 1)))
+ {
+ tree width = DECL_SIZE (TREE_OPERAND (exp, 1));
+ HOST_WIDE_INT low = TREE_INT_CST_LOW (width);
+
+ /* If it's thinner than an int, promote it like a
+ C_PROMOTING_INTEGER_TYPE_P, otherwise leave it alone. */
+
+ 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))
{
/* Traditionally, unsignedness is preserved in default promotions.
top = TYPE_LANG_SPECIFIC (type)->len;
while (top - bot > 1)
{
- HOST_WIDE_INT cmp;
-
half = (top - bot + 1) >> 1;
field = field_array[bot+half];
continue;
}
- cmp = (HOST_WIDE_INT) DECL_NAME (field) - (HOST_WIDE_INT) component;
- if (cmp == 0)
+ if (DECL_NAME (field) == component)
break;
- if (cmp < 0)
+ if (DECL_NAME (field) < component)
bot += half;
else
top = bot + half;
error ("dereferencing pointer to incomplete type");
return error_mark_node;
}
- if (TREE_CODE (t) == VOID_TYPE)
+ if (TREE_CODE (t) == VOID_TYPE && skip_evaluation == 0)
warning ("dereferencing `void *' pointer");
/* We *must* set TREE_READONLY when dereferencing a pointer to const,
tree ar = default_conversion (array);
tree ind = default_conversion (index);
+ /* Do the same warning check as above, but only on the part that's
+ syntactically the index and only if it is also semantically
+ the 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'");
+
/* Put the integer in IND to simplify error checking. */
if (TREE_CODE (TREE_TYPE (ar)) == INTEGER_TYPE)
{
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;
}
parmval = convert_for_assignment (type, val,
- (char *)0, /* arg passing */
+ (char *) 0, /* arg passing */
fundecl, name, parmnum + 1);
#ifdef PROMOTE_PROTOTYPES
|| 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 &");
}
}
case RSHIFT_EXPR:
if (code0 == INTEGER_TYPE && code1 == INTEGER_TYPE)
{
- if (TREE_CODE (op1) == INTEGER_CST)
+ if (TREE_CODE (op1) == INTEGER_CST && skip_evaluation == 0)
{
if (tree_int_cst_sgn (op1) < 0)
warning ("right shift count is negative");
case LSHIFT_EXPR:
if (code0 == INTEGER_TYPE && code1 == INTEGER_TYPE)
{
- if (TREE_CODE (op1) == INTEGER_CST)
+ if (TREE_CODE (op1) == INTEGER_CST && skip_evaluation == 0)
{
if (tree_int_cst_sgn (op1) < 0)
warning ("left shift count is negative");
case LROTATE_EXPR:
if (code0 == INTEGER_TYPE && code1 == INTEGER_TYPE)
{
- if (TREE_CODE (op1) == INTEGER_CST)
+ if (TREE_CODE (op1) == INTEGER_CST && skip_evaluation == 0)
{
if (tree_int_cst_sgn (op1) < 0)
warning ("shift count is negative");
Otherwise, the targets must be compatible
and both must be object or both incomplete. */
if (comp_target_types (type0, type1))
- ;
+ result_type = common_type (type0, type1);
else if (TYPE_MAIN_VARIANT (tt0) == void_type_node)
{
/* op0 != orig_op0 detects the case of something
}
else
pedwarn ("comparison of distinct pointer types lacks a cast");
- result_type = common_type (type0, type1);
+
+ if (result_type == NULL_TREE)
+ result_type = ptr_type_node;
}
else if (code0 == POINTER_TYPE && TREE_CODE (op1) == INTEGER_CST
&& integer_zerop (op1))
shorten = 1;
else if (code0 == POINTER_TYPE && code1 == POINTER_TYPE)
{
- if (! comp_target_types (type0, type1))
- pedwarn ("comparison of distinct pointer types lacks a cast");
- else if (pedantic
- && TREE_CODE (TREE_TYPE (type0)) == FUNCTION_TYPE)
- pedwarn ("ANSI C forbids ordered comparisons of pointers to functions");
- result_type = common_type (type0, type1);
+ 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;
short_compare = 1;
else if (code0 == POINTER_TYPE && code1 == POINTER_TYPE)
{
- if (! comp_target_types (type0, type1))
- pedwarn ("comparison of distinct pointer types lacks a cast");
- else 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");
- result_type = common_type (type0, type1);
+ 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)
+ if (pedantic || extra_warnings)
pedwarn ("ordered comparison of pointer with integer zero");
}
else if (code1 == POINTER_TYPE && TREE_CODE (op0) == INTEGER_CST
converted = 1;
resultcode = xresultcode;
- if (extra_warnings)
+ if (warn_sign_compare && 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);
+
/* Avoid spurious warnings for comparison with enumerators. */
xop0 = orig_op0;
all the values of the unsigned type. */
if (! TREE_UNSIGNED (result_type))
/* OK */;
+ /* Do not warn if both operands are unsigned. */
+ else if (op0_signed == op1_signed)
+ /* OK */;
/* Do not warn if the signed quantity is an unsuffixed
integer literal (or some static constant expression
involving such literals) and it is non-negative. */
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");
+
+ /* Warn if two unsigned values are being compared in a size
+ larger than their original size, and one (and only one) is the
+ result of a `~' operator. This comparison will always fail.
+
+ Also warn if one operand is a constant, and the constant
+ does not have all bits set that are set in the ~ operand
+ when it is extended. */
+
+ 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");
+ }
}
}
}
&& 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)
+ || TREE_UNSIGNED (TREE_TYPE (intop)) != TREE_UNSIGNED (sizetype))
+ intop = convert (type_for_size (TYPE_PRECISION (sizetype),
+ TREE_UNSIGNED (sizetype)), intop);
/* Replace the integer argument with a suitable product by the object size.
Do this multiplication as signed, then convert to the appropriate
}
/* First do the subtraction as integers;
- then drop through to build the divide operator. */
+ then drop through to build the divide operator.
+ Do not do default conversions on the minus operator
+ in case restype is a short type. */
op0 = build_binary_op (MINUS_EXPR, convert (restype, op0),
- convert (restype, op1), 1);
+ convert (restype, op1), 0);
/* This generates an error if op1 is pointer to incomplete type. */
if (TYPE_SIZE (TREE_TYPE (TREE_TYPE (op1))) == 0)
error ("arithmetic on pointer to an incomplete type");
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:
register tree result_type = NULL;
tree orig_op1 = op1, orig_op2 = op2;
- /* If second operand is omitted, it is the same as the first one;
- make sure it is calculated only once. */
- if (op1 == 0)
- {
- if (pedantic)
- pedwarn ("ANSI C forbids omitting the middle term of a ?: expression");
- ifexp = op1 = save_expr (ifexp);
- }
-
ifexp = truthvalue_conversion (default_conversion (ifexp));
#if 0 /* Produces wrong result if within sizeof. */
&& 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);
}
}
warn_for_assignment ("pointer targets in %s differ in signedness",
get_spelling (errtype), funname, parmnum);
}
- else
+ else if (TREE_CODE (ttl) == FUNCTION_TYPE
+ && TREE_CODE (ttr) == FUNCTION_TYPE)
{
/* Because const and volatile on functions are restrictions
that say the function will not do certain things,
switch (TREE_CODE (value))
{
case CONSTRUCTOR:
- if (TREE_CODE (TREE_TYPE (value)) == UNION_TYPE
- && TREE_CONSTANT (value))
+ 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);
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;
static tree constructor_index;
/* For an ARRAY_TYPE, this is the end index of the range
- to intitialize with the next element, or NULL in the ordinary case
+ to initialize with the next element, or NULL in the ordinary case
where the element is used just once. */
static tree constructor_range_end;
static int constructor_depth;
/* 0 if implicitly pushing constructor levels is allowed. */
-int constructor_no_implicit = 0; /* 0 for C; 1 for some other languages. */
+int constructor_no_implicit = 0; /* 0 for C; 1 for some other languages. */
/* 1 if this constructor level was entered implicitly. */
static int constructor_implicit;
|| 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));
{
constructor_type = TREE_TYPE (constructor_fields);
push_member_name (constructor_fields);
+ constructor_depth++;
if (constructor_fields != constructor_unfilled_fields)
constructor_incremental = 0;
}
{
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;
|| 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)))
{
&& constructor_incremental)
{
constructor = digest_init (constructor_type, constructor,
- 0, 0);
+ require_constant_value,
+ require_constant_elements);
/* If initializing an array of unknown size,
determine the size now. */
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))
{
constructor_erroneous = 1;
else if (!TREE_CONSTANT (value))
constructor_constant = 0;
- else if (initializer_constant_valid_p (value, TREE_TYPE (value)) == 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))
constructor_index, which is modified in place. */
constructor_pending_elts
= tree_cons (copy_node (field),
- digest_init (type, value, 0, 0),
+ digest_init (type, value, require_constant_value,
+ require_constant_elements),
constructor_pending_elts);
}
else if (TREE_CODE (constructor_type) == RECORD_TYPE
if (!duplicate)
constructor_pending_elts
= tree_cons (field,
- digest_init (type, value, 0, 0),
+ digest_init (type, value, require_constant_value,
+ require_constant_elements),
constructor_pending_elts);
}
else
if (field && TREE_CODE (field) == INTEGER_CST)
field = copy_node (field);
constructor_elements
- = tree_cons (field, digest_init (type, value, 0, 0),
+ = tree_cons (field, digest_init (type, value,
+ require_constant_value,
+ require_constant_elements),
constructor_elements);
}
else
assemble_zeros (next - here);
}
}
- output_constant (digest_init (type, value, 0, 0),
+ output_constant (digest_init (type, value,
+ require_constant_value,
+ require_constant_elements),
int_size_in_bytes (type));
/* For a record or union,
}
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;
break;
}
- /* In the case of [LO .. HI] = VALUE, only evaluate VALUE once. */
+ /* In the case of [LO .. HI] = VALUE, only evaluate VALUE once. */
if (constructor_range_end)
value = save_expr (value);
/* If the (lexically) previous elments are not now saved,
we can discard the storage for them. */
- if (constructor_incremental && constructor_pending_elts == 0 && value != 0)
+ if (constructor_incremental && constructor_pending_elts == 0 && value != 0
+ && constructor_stack == 0)
clear_momentary ();
}
\f
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)))