/* Build expressions with type checking for C compiler.
- Copyright (C) 1987, 88, 91, 92, 93, 1994 Free Software Foundation, Inc.
+ Copyright (C) 1987, 88, 91-6, 1997 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.
#include "tree.h"
#include "c-tree.h"
#include "flags.h"
+#include "output.h"
/* Nonzero if we've already printed a "missing braces around initializer"
message within this initializer. */
extern char *index ();
extern char *rindex ();
-int mark_addressable ();
-static tree convert_for_assignment ();
-static void warn_for_assignment ();
-static int function_types_compatible_p ();
-static int type_lists_compatible_p ();
-int self_promoting_args_p ();
-static int self_promoting_type_p ();
-static int comp_target_types ();
-static tree pointer_int_sum ();
-static tree pointer_diff ();
-static tree convert_sequence ();
-static tree unary_complex_lvalue ();
-static tree process_init_constructor ();
-static tree convert_arguments ();
-static char *get_spelling ();
-static tree digest_init ();
-static void pedantic_lvalue_warning ();
-tree truthvalue_conversion ();
-void incomplete_type_error ();
-void readonly_warning ();
-static tree internal_build_compound_expr ();
-
-void process_init_element ();
+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, char *, tree,
+ tree, int));
+static void warn_for_assignment PROTO((char *, char *, tree, int));
+static tree valid_compound_expr_initializer PROTO((tree, tree));
+static void push_string PROTO((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 char *get_spelling PROTO((char *));
+static void warning_init PROTO((char *, char *,
+ 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));
\f
/* Do `exp = require_complete_type (exp);' to make sure exp
does not have an incomplete type. (That includes void types.) */
{
register enum tree_code code1;
register enum tree_code code2;
+ tree attributes;
/* Save time if the two types are the same. */
if (t2 == error_mark_node)
return t1;
+ /* Merge the attributes */
+ attributes = merge_attributes (TYPE_ATTRIBUTES (t1), TYPE_ATTRIBUTES (t2));
+
/* Treat an enum type as the unsigned integer type of the same width. */
if (TREE_CODE (t1) == ENUMERAL_TYPE)
tree subtype = common_type (subtype1, subtype2);
if (code1 == COMPLEX_TYPE && TREE_TYPE (t1) == subtype)
- return t1;
+ return build_type_attribute_variant (t1, attributes);
else if (code2 == COMPLEX_TYPE && TREE_TYPE (t2) == subtype)
- return t2;
+ return build_type_attribute_variant (t2, attributes);
else
- return build_complex_type (subtype);
+ return build_type_attribute_variant (build_complex_type (subtype),
+ attributes);
}
switch (code1)
/* If only one is real, use it as the result. */
if (code1 == REAL_TYPE && code2 != REAL_TYPE)
- return t1;
+ return build_type_attribute_variant (t1, attributes);
if (code2 == REAL_TYPE && code1 != REAL_TYPE)
- return t2;
+ return build_type_attribute_variant (t2, attributes);
/* Both real or both integers; use the one with greater precision. */
if (TYPE_PRECISION (t1) > TYPE_PRECISION (t2))
- return t1;
+ return build_type_attribute_variant (t1, attributes);
else if (TYPE_PRECISION (t2) > TYPE_PRECISION (t1))
- return t2;
+ return build_type_attribute_variant (t2, attributes);
/* Same precision. Prefer longs to ints even when same size. */
if (TYPE_MAIN_VARIANT (t1) == long_unsigned_type_node
|| TYPE_MAIN_VARIANT (t2) == long_unsigned_type_node)
- return 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)
/* But preserve unsignedness from the other type,
since long cannot hold all the values of an unsigned int. */
if (TREE_UNSIGNED (t1) || TREE_UNSIGNED (t2))
- return long_unsigned_type_node;
- return long_integer_type_node;
+ t1 = long_unsigned_type_node;
+ else
+ t1 = long_integer_type_node;
+ return build_type_attribute_variant (t1, attributes);
}
/* Otherwise prefer the unsigned one. */
if (TREE_UNSIGNED (t1))
- return t1;
- else return t2;
+ return build_type_attribute_variant (t1, attributes);
+ else
+ return build_type_attribute_variant (t2, attributes);
case POINTER_TYPE:
/* For two pointers, do this recursively on the target type,
= TYPE_READONLY (TREE_TYPE (t1)) || TYPE_READONLY (TREE_TYPE (t2));
int volatilep
= TYPE_VOLATILE (TREE_TYPE (t1)) || TYPE_VOLATILE (TREE_TYPE (t2));
- return build_pointer_type (c_build_type_variant (target, constp, volatilep));
+ t1 = build_pointer_type (c_build_type_variant (target, constp,
+ volatilep));
+ return build_type_attribute_variant (t1, attributes);
}
#if 0
- return build_pointer_type (common_type (TREE_TYPE (t1), TREE_TYPE (t2)));
+ 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));
/* Save space: see if the result is identical to one of the args. */
if (elt == TREE_TYPE (t1) && TYPE_DOMAIN (t1))
- return t1;
+ return build_type_attribute_variant (t1, attributes);
if (elt == TREE_TYPE (t2) && TYPE_DOMAIN (t2))
- return t2;
+ return build_type_attribute_variant (t2, attributes);
/* Merge the element types, and have a size if either arg has one. */
- return build_array_type (elt, TYPE_DOMAIN (TYPE_DOMAIN (t1) ? t1 : t2));
+ t1 = build_array_type (elt, TYPE_DOMAIN (TYPE_DOMAIN (t1) ? t1 : t2));
+ return build_type_attribute_variant (t1, attributes);
}
case FUNCTION_TYPE:
/* Save space: see if the result is identical to one of the args. */
if (valtype == TREE_TYPE (t1) && ! TYPE_ARG_TYPES (t2))
- return t1;
+ return build_type_attribute_variant (t1, attributes);
if (valtype == TREE_TYPE (t2) && ! TYPE_ARG_TYPES (t1))
- return t2;
+ return build_type_attribute_variant (t2, attributes);
/* Simple way if one arg fails to specify argument types. */
if (TYPE_ARG_TYPES (t1) == 0)
- return build_function_type (valtype, TYPE_ARG_TYPES (t2));
+ {
+ t1 = build_function_type (valtype, TYPE_ARG_TYPES (t2));
+ return build_type_attribute_variant (t1, attributes);
+ }
if (TYPE_ARG_TYPES (t2) == 0)
- return build_function_type (valtype, TYPE_ARG_TYPES (t1));
+ {
+ t1 = build_function_type (valtype, TYPE_ARG_TYPES (t1));
+ return build_type_attribute_variant (t1, attributes);
+ }
/* If both args specify argument types, we must merge the two
lists, argument by argument. */
parm_done: ;
}
- return build_function_type (valtype, newargs);
+ t1 = build_function_type (valtype, newargs);
+ /* ... falls through ... */
}
default:
- return t1;
+ return build_type_attribute_variant (t1, attributes);
}
}
{
register tree t1 = type1;
register tree t2 = type2;
+ int attrval, val;
/* Suppress errors caused by previously reported errors. */
if (t1 == t2 || TREE_CODE (t1) == ERROR_MARK || TREE_CODE (t2) == ERROR_MARK)
return 1;
- /* Treat an enum type as the unsigned integer type of the same width. */
+ /* Treat an enum type as the integer type of the same width and
+ signedness. */
if (TREE_CODE (t1) == ENUMERAL_TYPE)
- t1 = type_for_size (TYPE_PRECISION (t1), 1);
+ t1 = type_for_size (TYPE_PRECISION (t1), TREE_UNSIGNED (t1));
if (TREE_CODE (t2) == ENUMERAL_TYPE)
- t2 = type_for_size (TYPE_PRECISION (t2), 1);
+ t2 = type_for_size (TYPE_PRECISION (t2), TREE_UNSIGNED (t2));
if (t1 == t2)
return 1;
if (TYPE_MAIN_VARIANT (t1) == TYPE_MAIN_VARIANT (t2))
return 1;
+#ifndef COMP_TYPE_ATTRIBUTES
+#define COMP_TYPE_ATTRIBUTES(t1,t2) 1
+#endif
+
+ /* 1 if no need for warning yet, 2 if warning cause has been seen. */
+ if (! (attrval = COMP_TYPE_ATTRIBUTES (t1, t2)))
+ return 0;
+
+ /* 1 if no need for warning yet, 2 if warning cause has been seen. */
+ val = 0;
+
switch (TREE_CODE (t1))
{
case POINTER_TYPE:
- return (TREE_TYPE (t1) == TREE_TYPE (t2)
+ val = (TREE_TYPE (t1) == TREE_TYPE (t2)
? 1 : comptypes (TREE_TYPE (t1), TREE_TYPE (t2)));
+ break;
case FUNCTION_TYPE:
- return function_types_compatible_p (t1, t2);
+ val = function_types_compatible_p (t1, t2);
+ break;
case ARRAY_TYPE:
{
- /* 1 if no need for warning yet, 2 if warning cause has been seen. */
- int val = 1;
tree d1 = TYPE_DOMAIN (t1);
tree d2 = TYPE_DOMAIN (t2);
+ val = 1;
/* Target types must match incl. qualifiers. */
if (TREE_TYPE (t1) != TREE_TYPE (t2)
|| TREE_CODE (TYPE_MIN_VALUE (d2)) != INTEGER_CST
|| TREE_CODE (TYPE_MAX_VALUE (d1)) != INTEGER_CST
|| TREE_CODE (TYPE_MAX_VALUE (d2)) != INTEGER_CST)
- return val;
+ break;
- return (((TREE_INT_CST_LOW (TYPE_MIN_VALUE (d1))
+ 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);
+ == TREE_INT_CST_HIGH (TYPE_MAX_VALUE (d2)))))
+ val = 0;
+ break;
}
case RECORD_TYPE:
if (maybe_objc_comptypes (t1, t2, 0) == 1)
- return 1;
+ val = 1;
+ break;
}
- return 0;
+ return attrval == 2 && val == 1 ? 2 : val;
}
/* Return 1 if TTL and TTR are pointers to types that are equivalent,
{
/* 1 if no need for warning yet, 2 if warning cause has been seen. */
int val = 1;
- int newval;
+ int newval = 0;
while (1)
{
/* Allow wait (union {union wait *u; int *i} *)
and wait (union wait *) to be compatible. */
if (TREE_CODE (TREE_VALUE (args1)) == UNION_TYPE
- && TYPE_NAME (TREE_VALUE (args1)) == 0
+ && (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))))
return 0;
}
else if (TREE_CODE (TREE_VALUE (args2)) == UNION_TYPE
- && TYPE_NAME (TREE_VALUE (args2)) == 0
+ && (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))))
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 (TREE_CODE (type) != INTEGER_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)
&& DECL_INITIAL (decl) != 0
&& TREE_CODE (DECL_INITIAL (decl)) != ERROR_MARK
/* This is invalid if initial value is not constant.
/* Constants can be used directly unless they're not loadable. */
if (TREE_CODE (exp) == CONST_DECL)
exp = DECL_INITIAL (exp);
- /* Replace a nonvolatile const static variable with its value. */
- else if (optimize
- && TREE_CODE (exp) == VAR_DECL
- && TREE_READONLY (exp)
- /* But not for iterators! */
- && !ITERATOR_P (exp)
- && DECL_MODE (exp) != BLKmode)
+
+ /* Replace a nonvolatile const static variable with its value unless
+ it is an array, in which case we must be sure that taking the
+ address of the array produces consistent results. */
+ else if (optimize && TREE_CODE (exp) == VAR_DECL && code != ARRAY_TYPE)
{
exp = decl_constant_value (exp);
type = TREE_TYPE (exp);
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];
/* Step through all anon unions in linear fashion. */
while (DECL_NAME (field_array[bot]) == NULL_TREE)
{
- tree anon, junk;
+ tree anon = 0, junk;
field = field_array[bot++];
- anon = lookup_field (TREE_TYPE (field), component, &junk);
+ 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;
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;
if (DECL_NAME (field) == NULL_TREE)
{
tree junk;
- tree anon = lookup_field (TREE_TYPE (field), component, &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;
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;
}
else
{
- tree parmname;
- tree type0 = type;
-#ifdef PROMOTE_PROTOTYPES
- /* Rather than truncating and then reextending,
- convert directly to int, if that's the type we will want. */
- if (! flag_traditional
- && (TREE_CODE (type) == INTEGER_TYPE
- || TREE_CODE (type) == ENUMERAL_TYPE)
- && (TYPE_PRECISION (type) < TYPE_PRECISION (integer_type_node)))
- type = integer_type_node;
-#endif
-
-#if 0 /* This turns out not to win--there's no way to write a prototype
- for a function whose arg type is a union with no tag. */
- /* Nameless union automatically casts the types it contains. */
- if (TREE_CODE (type) == UNION_TYPE && TYPE_NAME (type) == 0)
- {
- tree field;
-
- for (field = TYPE_FIELDS (type); field;
- field = TREE_CHAIN (field))
- if (comptypes (TYPE_MAIN_VARIANT (TREE_TYPE (field)),
- TYPE_MAIN_VARIANT (TREE_TYPE (val))))
- break;
-
- if (field)
- val = build1 (CONVERT_EXPR, type, val);
- }
-#endif
-
/* Optionally warn about conversions that
differ from the default conversions. */
if (warn_conversion)
{
int formal_prec = TYPE_PRECISION (type);
- if (TREE_CODE (type) != REAL_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
- && TREE_CODE (TREE_TYPE (val)) != 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);
+ /* ??? At some point, messages should be written about
+ conversions between complex types, but that's too messy
+ to do now. */
+ else if (TREE_CODE (type) == REAL_TYPE
&& TREE_CODE (TREE_TYPE (val)) == REAL_TYPE)
{
/* Warn if any argument is passed as `float',
warn_for_assignment ("%s as `float' rather than `double' due to prototype", (char *) 0, name, parmnum + 1);
}
/* Detect integer changing in width or signedness. */
- else if ((TREE_CODE (type) == INTEGER_TYPE
- || TREE_CODE (type) == ENUMERAL_TYPE)
- && (TREE_CODE (TREE_TYPE (val)) == INTEGER_TYPE
- || TREE_CODE (TREE_TYPE (val)) == ENUMERAL_TYPE))
+ 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);
}
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 &");
}
}
Zero means they need to be converted to RESULT_TYPE. */
int converted = 0;
+ /* Nonzero means create the expression with this type, rather than
+ RESULT_TYPE. */
+ tree build_type = 0;
+
/* Nonzero means after finally constructing the expression
- give it this type. Otherwise, give it type RESULT_TYPE. */
+ convert it to this type. */
tree final_type = 0;
/* Nonzero if this is an operation like MIN or MAX which can
undefined if the quotient can't be represented in the
computation mode. We shorten only if unsigned or if
dividing by something we know != -1. */
- shorten = (TREE_UNSIGNED (orig_op0)
+ shorten = (TREE_UNSIGNED (TREE_TYPE (orig_op0))
|| (TREE_CODE (op1) == INTEGER_CST
&& (TREE_INT_CST_LOW (op1) != -1
|| TREE_INT_CST_HIGH (op1) != -1)));
on some targets, since the modulo instruction is undefined if the
quotient can't be represented in the computation mode. We shorten
only if unsigned or if dividing by something we know != -1. */
- shorten = (TREE_UNSIGNED (orig_op0)
+ shorten = (TREE_UNSIGNED (TREE_TYPE (orig_op0))
|| (TREE_CODE (op1) == INTEGER_CST
&& (TREE_INT_CST_LOW (op1) != -1
|| TREE_INT_CST_HIGH (op1) != -1)));
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_lt (op1, integer_zero_node))
+ if (tree_int_cst_sgn (op1) < 0)
warning ("right shift count is negative");
else
{
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_lt (op1, integer_zero_node))
+ 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)
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_lt (op1, integer_zero_node))
+ 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)
case NE_EXPR:
/* Result of comparison is always int,
but don't convert the args to int! */
- result_type = integer_type_node;
- converted = 1;
+ build_type = integer_type_node;
if ((code0 == INTEGER_TYPE || code0 == REAL_TYPE
|| code0 == COMPLEX_TYPE)
&& (code1 == INTEGER_TYPE || code1 == REAL_TYPE
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");
+
+ if (result_type == NULL_TREE)
+ result_type = ptr_type_node;
}
else if (code0 == POINTER_TYPE && TREE_CODE (op1) == INTEGER_CST
&& integer_zerop (op1))
- op1 = null_pointer_node;
+ result_type = type0;
else if (code1 == POINTER_TYPE && TREE_CODE (op0) == INTEGER_CST
&& integer_zerop (op0))
- op0 = null_pointer_node;
+ result_type = type1;
else if (code0 == POINTER_TYPE && code1 == INTEGER_TYPE)
{
+ result_type = type0;
if (! flag_traditional)
pedwarn ("comparison between pointer and integer");
- op1 = convert (TREE_TYPE (op0), op1);
}
else if (code0 == INTEGER_TYPE && code1 == POINTER_TYPE)
{
+ result_type = type1;
if (! flag_traditional)
pedwarn ("comparison between pointer and integer");
- op0 = convert (TREE_TYPE (op1), op0);
}
- else
- /* If args are not valid, clear out RESULT_TYPE
- to cause an error message later. */
- result_type = 0;
break;
case MAX_EXPR:
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;
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))
- 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 = integer_type_node;
+ 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 = integer_type_node;
- op1 = null_pointer_node;
- if (pedantic)
+ 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 = integer_type_node;
- op0 = null_pointer_node;
+ result_type = type1;
if (pedantic)
pedwarn ("ordered comparison of pointer with integer zero");
}
else if (code0 == POINTER_TYPE && code1 == INTEGER_TYPE)
{
- result_type = integer_type_node;
+ result_type = type0;
if (! flag_traditional)
pedwarn ("comparison between pointer and integer");
- op1 = convert (TREE_TYPE (op0), op1);
}
else if (code0 == INTEGER_TYPE && code1 == POINTER_TYPE)
{
- result_type = integer_type_node;
+ result_type = type1;
if (! flag_traditional)
pedwarn ("comparison between pointer and integer");
- op0 = convert (TREE_TYPE (op1), op0);
}
- converted = 1;
break;
}
unsigned_arg = TREE_UNSIGNED (TREE_TYPE (op0));
if (TYPE_PRECISION (TREE_TYPE (arg0)) < TYPE_PRECISION (result_type)
+ /* We can shorten only if the shift count is less than the
+ number of bits in the smaller type size. */
+ && TREE_INT_CST_HIGH (op1) == 0
+ && TYPE_PRECISION (TREE_TYPE (arg0)) > TREE_INT_CST_LOW (op1)
/* If arg is sign-extended and then unsigned-shifted,
we can simulate this with a signed shift in arg's type
only if the extended result is at least twice as wide
= shorten_compare (&xop0, &xop1, &xresult_type, &xresultcode);
if (val != 0)
return val;
- op0 = xop0, op1 = xop1, result_type = xresult_type;
+ op0 = xop0, op1 = xop1;
+ converted = 1;
resultcode = xresultcode;
- if (extra_warnings)
+ if (warn_sign_compare && skip_evaluation == 0)
{
- tree op0_type = TREE_TYPE (orig_op0);
- tree op1_type = TREE_TYPE (orig_op1);
- int op0_unsigned = TREE_UNSIGNED (op0_type);
- int op1_unsigned = TREE_UNSIGNED (op1_type);
+ 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;
+ xop1 = orig_op1;
+ STRIP_TYPE_NOPS (xop0);
+ STRIP_TYPE_NOPS (xop1);
+
/* Give warnings for comparisons between signed and unsigned
- quantities that will fail. Do not warn if the signed quantity
- is an unsuffixed integer literal (or some static constant
- expression involving such literals) and it is positive.
- Do not warn if the width of the unsigned quantity is less
- than that of the signed quantity, since in this case all
- values of the unsigned quantity fit in the signed quantity.
- Do not warn if the signed type is the same size as the
- result_type since sign extension does not cause trouble in
- this case. */
+ quantities that may fail. */
/* Do the checking based on the original operand trees, so that
casts will be considered, but default promotions won't be. */
- if (op0_unsigned != op1_unsigned
- && ((op0_unsigned
- && TYPE_PRECISION (op0_type) >= TYPE_PRECISION (op1_type)
- && TYPE_PRECISION (op0_type) < TYPE_PRECISION (result_type)
- && (TREE_CODE (op1) != INTEGER_CST
- || (TREE_CODE (op1) == INTEGER_CST
- && INT_CST_LT (op1, integer_zero_node))))
- ||
- (op1_unsigned
- && TYPE_PRECISION (op1_type) >= TYPE_PRECISION (op0_type)
- && TYPE_PRECISION (op1_type) < TYPE_PRECISION (result_type)
- && (TREE_CODE (op0) != INTEGER_CST
- || (TREE_CODE (op0) == INTEGER_CST
- && INT_CST_LT (op0, integer_zero_node))))))
+
+ /* Do not warn if the comparison is being done in a signed type,
+ since the signed type will only be chosen if it can represent
+ 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. */
+ 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))
+ /* OK */;
+ /* Do not warn if the comparison is an equality operation,
+ the unsigned quantity is an integral constant and it does
+ 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)))
+ || (op1_signed && TREE_CODE (xop0) == INTEGER_CST
+ && 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");
+ }
}
}
}
op1 = convert (result_type, op1);
}
+ if (build_type == NULL_TREE)
+ build_type = result_type;
+
{
- register tree result = build (resultcode, result_type, op0, op1);
+ register tree result = build (resultcode, build_type, op0, op1);
register tree folded;
folded = fold (result);
&& 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. */
+ /* Replace the integer argument with a suitable product by the object size.
+ Do this multiplication as signed, then convert to the appropriate
+ pointer type (actually unsigned integral). */
- intop = build_binary_op (MULT_EXPR, intop, size_exp, 1);
+ intop = convert (result_type,
+ build_binary_op (MULT_EXPR, intop,
+ convert (TREE_TYPE (intop), size_exp), 1));
/* Create the sum or difference. */
}
/* 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");
+
/* This generates an error if op0 is pointer to incomplete type. */
op1 = c_size_in_bytes (target_type);
/* Divide by the size, in easiest possible way. */
- result = build (EXACT_DIV_EXPR, restype, op0, op1);
+ result = build (EXACT_DIV_EXPR, restype, op0, convert (restype, op1));
folded = fold (result);
if (folded == result)
((code == PREINCREMENT_EXPR
|| code == POSTINCREMENT_EXPR)
? "increment" : "decrement"));
- inc = c_sizeof_nowarn (TREE_TYPE (result_type));
+ inc = c_size_in_bytes (TREE_TYPE (result_type));
}
else
inc = integer_one_node;
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:
IDENTIFIER_POINTER (DECL_NAME (x)));
return 0;
}
+
+ /* If we are making this addressable due to its having
+ volatile components, give a different error message. Also
+ handle the case of an unnamed parameter by not trying
+ to give the name. */
+
+ 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)));
}
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. */
rest = internal_build_compound_expr (TREE_CHAIN (list), FALSE);
- /* When pedantic, a compound expression can be neither an lvalue
- nor an integer constant expression. */
- if (! TREE_SIDE_EFFECTS (TREE_VALUE (list)) && ! pedantic)
- return rest;
+ if (! TREE_SIDE_EFFECTS (TREE_VALUE (list)))
+ {
+ /* The left-hand operand of a comma expression is like an expression
+ statement: with -W or -Wunused, we should warn if it doesn't have
+ any side-effects, unless it was explicitly cast to (void). */
+ if ((extra_warnings || warn_unused)
+ && ! (TREE_CODE (TREE_VALUE (list)) == CONVERT_EXPR
+ && TREE_TYPE (TREE_VALUE (list)) == void_type_node))
+ warning ("left-hand operand of comma expression has no effect");
+
+ /* When pedantic, a compound expression can be neither an lvalue
+ nor an integer constant expression. */
+ if (! pedantic)
+ return rest;
+ }
+
+ /* With -Wunused, we should also warn if the left-hand operand does have
+ side-effects, but computes a value which is not used. For example, in
+ `foo() + bar(), baz()' the result of the `+' operator is not used,
+ so we should issue a warning. */
+ else if (warn_unused)
+ warn_if_unused_value (TREE_VALUE (list));
return build (COMPOUND_EXPR, TREE_TYPE (rest), TREE_VALUE (list), rest);
}
&& 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");
&& !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 (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);
/* Arithmetic types all interconvert, and enum is treated like int. */
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))
+ && (coder == INTEGER_TYPE || coder == REAL_TYPE || coder == ENUMERAL_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);
- }
- else if (coder == POINTER_TYPE
- && TREE_CODE (TREE_TYPE (memb_types)) == POINTER_TYPE)
+ 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)
{
- tree memb_type = TREE_TYPE (memb_types);
register tree ttl = TREE_TYPE (memb_type);
register tree ttr = TREE_TYPE (rhstype);
/* Any non-function converts to a [const][volatile] void *
and vice versa; otherwise, targets must be the same.
- Meanwhile, the lhs target must have all the qualifiers of the rhs. */
+ Meanwhile, the lhs target must have all the qualifiers of
+ the rhs. */
if (TYPE_MAIN_VARIANT (ttl) == void_type_node
|| 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. */
+ 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);
}
}
+
/* Conversions among pointers */
else if (codel == POINTER_TYPE && coder == POINTER_TYPE)
{
/* Const and volatile mean something different for function types,
so the usual warnings are not appropriate. */
else if (TREE_CODE (ttr) != FUNCTION_TYPE
- || TREE_CODE (ttl) != FUNCTION_TYPE)
+ && TREE_CODE (ttl) != FUNCTION_TYPE)
{
if (! TYPE_READONLY (ttl) && TYPE_READONLY (ttr))
warn_for_assignment ("%s discards `const' from pointer target type",
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,
therefore, we do not need to check for such things as
arithmetic-combinations of integers. */
-static tree
+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_CONSTANT (value))
- return initializer_constant_valid_p (TREE_VALUE (CONSTRUCTOR_ELTS (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);
return TREE_STATIC (value) ? null_pointer_node : 0;
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);
+
/* Allow conversions between real types. */
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);
+
/* Allow length-preserving conversions between integer types. */
if (TREE_CODE (TREE_TYPE (value)) == INTEGER_TYPE
&& TREE_CODE (TREE_TYPE (TREE_OPERAND (value, 0))) == INTEGER_TYPE
- && tree_int_cst_equal (TYPE_SIZE (TREE_TYPE (value)),
- TYPE_SIZE (TREE_TYPE (TREE_OPERAND (value, 0)))))
+ && (TYPE_PRECISION (TREE_TYPE (value))
+ == TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (value, 0)))))
return initializer_constant_valid_p (TREE_OPERAND (value, 0), endtype);
- /* Allow conversions between integer types only if explicit value. */
+
+ /* Allow conversions between other integer types only if
+ explicit value. */
if (TREE_CODE (TREE_TYPE (value)) == INTEGER_TYPE
&& TREE_CODE (TREE_TYPE (TREE_OPERAND (value, 0))) == INTEGER_TYPE)
{
return null_pointer_node;
return 0;
}
+
/* Allow (int) &foo provided int is as wide as a pointer. */
if (TREE_CODE (TREE_TYPE (value)) == INTEGER_TYPE
&& TREE_CODE (TREE_TYPE (TREE_OPERAND (value, 0))) == POINTER_TYPE
- && ! tree_int_cst_lt (TYPE_SIZE (TREE_TYPE (value)),
- TYPE_SIZE (TREE_TYPE (TREE_OPERAND (value, 0)))))
+ && (TYPE_PRECISION (TREE_TYPE (value))
+ >= TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (value, 0)))))
return initializer_constant_valid_p (TREE_OPERAND (value, 0),
endtype);
+
+ /* Likewise conversions from int to pointers. */
+ if (TREE_CODE (TREE_TYPE (value)) == POINTER_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);
+
/* Allow conversions to union types if the value inside is okay. */
if (TREE_CODE (TREE_TYPE (value)) == UNION_TYPE)
return initializer_constant_valid_p (TREE_OPERAND (value, 0),
return error_mark_node;
}
- if (optimize && TREE_READONLY (inside_init)
- && TREE_CODE (inside_init) == VAR_DECL)
+ if (optimize && TREE_CODE (inside_init) == VAR_DECL)
inside_init = decl_constant_value (inside_init);
/* Compound expressions can only occur here if -pedantic or
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;
\f
/* Handle initializers that use braces. */
-static void output_init_element ();
-static void output_pending_init_elements ();
-static void check_init_type_bitfields ();
-
/* Type of object we are accumulating a constructor for.
This type is always a RECORD_TYPE, UNION_TYPE or ARRAY_TYPE. */
static tree constructor_type;
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;
p->unfilled_index = constructor_unfilled_index;
p->unfilled_fields = constructor_unfilled_fields;
p->bit_index = constructor_bit_index;
- p->elements = 0;
+ p->elements = constructor_elements;
p->constant = constructor_constant;
p->simple = constructor_simple;
p->erroneous = constructor_erroneous;
|| 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. */
- if (constructor_incremental && TREE_CODE (constructor_type) == RECORD_TYPE
- && constructor_fields)
+ /* 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
+ && 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;
}
}
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)
|| 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)))
{
int implicit;
{
struct constructor_stack *p;
- int size;
+ int size = 0;
tree constructor = 0;
if (implicit == 0)
&& 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. */
TYPE_DOMAIN (constructor_type) = build_index_type (maxindex);
TREE_TYPE (maxindex) = TYPE_DOMAIN (constructor_type);
+ /* TYPE_MAX_VALUE is always one less than the number of elements
+ in the array, because we start counting at zero. Therefore,
+ warn only if the value is less than zero. */
if (pedantic
- && tree_int_cst_lt (TYPE_MAX_VALUE (TYPE_DOMAIN (constructor_type)),
- integer_zero_node))
- error_with_decl (constructor_decl, "zero-size array `%s'");
+ && (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 ();
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_INT_CST_LOW (constructor_index)
- = TREE_INT_CST_LOW (first);
- TREE_INT_CST_HIGH (constructor_index)
- = TREE_INT_CST_HIGH (first);
+ 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%s", " for `%s'", NULL);
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
{
/* Advance to offset of this element. */
if (! tree_int_cst_equal (constructor_bit_index,
- DECL_FIELD_BITPOS (constructor_fields)))
+ DECL_FIELD_BITPOS (field)))
{
int next = (TREE_INT_CST_LOW (DECL_FIELD_BITPOS (field))
/ BITS_PER_UNIT);
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,
if (TREE_CODE (constructor_type) == RECORD_TYPE
|| TREE_CODE (constructor_type) == UNION_TYPE)
{
- tree temp = size_binop (PLUS_EXPR,
- DECL_FIELD_BITPOS (constructor_fields),
- DECL_SIZE (constructor_fields));
+ 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)
if (tree_int_cst_equal (TREE_PURPOSE (tail),
constructor_unfilled_index))
{
- output_init_element (TREE_VALUE (tail), TREE_TYPE (constructor_type),
+ output_init_element (TREE_VALUE (tail),
+ TREE_TYPE (constructor_type),
constructor_unfilled_index, 0);
goto retry;
}
constructor_unfilled_index))
;
else if (next == 0
- || tree_int_cst_lt (TREE_PURPOSE (tail),
- next))
+ || tree_int_cst_lt (TREE_PURPOSE (tail), next))
next = TREE_PURPOSE (tail);
}
else if (TREE_CODE (constructor_type) == RECORD_TYPE
if (constructor_incremental)
{
tree filled;
- tree nextpos_tree;
+ tree nextpos_tree = size_int (0);
if (TREE_CODE (constructor_type) == RECORD_TYPE
|| TREE_CODE (constructor_type) == UNION_TYPE)
{
- /* Find the last field written out. */
+ /* Find the last field written out, if any. */
for (tail = TYPE_FIELDS (constructor_type); tail;
tail = TREE_CHAIN (tail))
if (TREE_CHAIN (tail) == constructor_unfilled_fields)
break;
- /* Find the offset of the end of that field. */
- filled = size_binop (CEIL_DIV_EXPR,
- size_binop (PLUS_EXPR,
- DECL_FIELD_BITPOS (tail),
- DECL_SIZE (tail)),
- size_int (BITS_PER_UNIT));
+
+ if (tail)
+ /* Find the offset of the end of that field. */
+ 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)
/* Handle superfluous braces around string cst as in
char x[] = {"foo"}; */
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_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))
+ && (constructor_max_index == 0
+ || tree_int_cst_lt (constructor_max_index,
+ constructor_index)))
process_init_element (pop_init_level (1));
else
break;
break;
}
- fieldtype = TYPE_MAIN_VARIANT (TREE_TYPE (constructor_fields));
+ fieldtype = TREE_TYPE (constructor_fields);
+ if (fieldtype != error_mark_node)
+ fieldtype = TYPE_MAIN_VARIANT (fieldtype);
fieldcode = TREE_CODE (fieldtype);
/* Accept a string constant to initialize a subarray. */
/* Otherwise, if we have come to a subaggregate,
and we don't have an element of its type, push into it. */
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))
}
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;
}
- fieldtype = TYPE_MAIN_VARIANT (TREE_TYPE (constructor_fields));
+ fieldtype = TREE_TYPE (constructor_fields);
+ if (fieldtype != error_mark_node)
+ fieldtype = TYPE_MAIN_VARIANT (fieldtype);
fieldcode = TREE_CODE (fieldtype);
/* Accept a string constant to initialize a subarray. */
/* Otherwise, if we have come to a subaggregate,
and we don't have an element of its type, push into it. */
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))
/* Otherwise, if we have come to a subaggregate,
and we don't have an element of its type, push into it. */
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))
break;
}
+ /* In the case of [LO .. HI] = VALUE, only evaluate VALUE once. */
+ 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%s",
+ " after `%s'", NULL_PTR);
+ 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);
+ }
+
/* Now output the actual element.
Ordinarily, output once.
If there is a range, repeat it till we advance past the range. */
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);
+ TREE_INT_CST_LOW (constructor_index) = TREE_INT_CST_LOW (tem);
+ TREE_INT_CST_HIGH (constructor_index) = TREE_INT_CST_HIGH (tem);
if (!value)
/* If we are doing the bookkeeping for an element that was
/* 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)))
tree valtype = TREE_TYPE (TREE_TYPE (current_function_decl));
if (TREE_THIS_VOLATILE (current_function_decl))
- warning ("function declared `volatile' has a `return' statement");
+ warning ("function declared `noreturn' has a `return' statement");
if (!retval)
{
/* Strip any conversions, additions, and subtractions, and see if
we are returning the address of a local variable. Warn if so. */
- while (TREE_CODE (inner) == NOP_EXPR
- || TREE_CODE (inner) == NON_LVALUE_EXPR
- || TREE_CODE (inner) == CONVERT_EXPR
- || TREE_CODE (inner) == PLUS_EXPR
- || TREE_CODE (inner) == MINUS_EXPR)
- inner = TREE_OPERAND (inner, 0);
-
- if (TREE_CODE (inner) == ADDR_EXPR)
+ while (1)
{
- inner = TREE_OPERAND (inner, 0);
+ switch (TREE_CODE (inner))
+ {
+ case NOP_EXPR: case NON_LVALUE_EXPR: case CONVERT_EXPR:
+ case PLUS_EXPR:
+ inner = TREE_OPERAND (inner, 0);
+ continue;
- while (TREE_CODE_CLASS (TREE_CODE (inner)) == 'r')
- inner = TREE_OPERAND (inner, 0);
+ case MINUS_EXPR:
+ /* If the second operand of the MINUS_EXPR has a pointer
+ type (or is converted from it), this may be valid, so
+ don't give a warning. */
+ {
+ 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;
+ }
- if (TREE_CODE (inner) == VAR_DECL
- && ! TREE_STATIC (inner)
- && DECL_CONTEXT (inner) == current_function_decl)
- warning ("function returns address of local variable");
+ break;
}
t = build (MODIFY_EXPR, TREE_TYPE (res), res, t);