/* Build expressions with type checking for C compiler.
- Copyright (C) 1987, 1988, 1989, 1992, 1993 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.
#include "tree.h"
#include "c-tree.h"
#include "flags.h"
+#include "output.h"
-/* Nonzero if we've already printed a "partly bracketed initializer"
+/* Nonzero if we've already printed a "missing braces around initializer"
message within this initializer. */
-static int partial_bracket_mentioned = 0;
+static int missing_braces_mentioned;
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)
code1 = TREE_CODE (t1);
code2 = TREE_CODE (t2);
- /* If one type is complex, form the common type
- of the non-complex components,
- then make that complex. */
+ /* If one type is complex, form the common type of the non-complex
+ components, then make that complex. Use T1 or T2 if it is the
+ required type. */
if (code1 == COMPLEX_TYPE || code2 == COMPLEX_TYPE)
{
- tree subtype1, subtype2, subtype;
- if (code1 == COMPLEX_TYPE)
- subtype1 = TREE_TYPE (t1);
- else
- subtype1 = t1;
- if (code2 == COMPLEX_TYPE)
- subtype2 = TREE_TYPE (t2);
+ tree subtype1 = code1 == COMPLEX_TYPE ? TREE_TYPE (t1) : t1;
+ tree subtype2 = code2 == COMPLEX_TYPE ? TREE_TYPE (t2) : t2;
+ tree subtype = common_type (subtype1, subtype2);
+
+ if (code1 == COMPLEX_TYPE && TREE_TYPE (t1) == subtype)
+ return build_type_attribute_variant (t1, attributes);
+ else if (code2 == COMPLEX_TYPE && TREE_TYPE (t2) == subtype)
+ return build_type_attribute_variant (t2, attributes);
else
- subtype2 = t2;
- subtype = common_type (subtype1, subtype2);
- 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];
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;
}
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
if (!(code0 == INTEGER_TYPE && code1 == INTEGER_TYPE))
resultcode = RDIV_EXPR;
else
- /* When dividing two signed integers, you have to promote to int.
- E.g. (short) -32868 / (short) -1 doesn't fit in a short. */
- shorten = TREE_UNSIGNED (orig_op0);
+ {
+ /* Although it would be tempting to shorten always here, that
+ loses 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 (TREE_TYPE (orig_op0))
+ || (TREE_CODE (op1) == INTEGER_CST
+ && (TREE_INT_CST_LOW (op1) != -1
+ || TREE_INT_CST_HIGH (op1) != -1)));
+ }
common = 1;
}
break;
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
/* Comparison operations are shortened too but differently.
They identify themselves by setting short_compare = 1. */
- if (short_compare && none_complex)
+ if (short_compare)
{
/* Don't write &op0, etc., because that would prevent op0
from being kept in a register.
= 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),
pedwarn (format, buffer);
}
+
+/* Issue a warning for a bad initializer component.
+ FORMAT describes the message. OFWHAT is the name for the component.
+ LOCAL is a format string for formatting the insertion of the name
+ into the message.
+
+ If OFWHAT is null, the component name is stored on the spelling stack.
+ If the component name is a null string, then LOCAL is omitted entirely. */
+
+static void
+warning_init (format, local, ofwhat)
+ char *format, *local, *ofwhat;
+{
+ char *buffer;
+
+ if (ofwhat == 0)
+ ofwhat = print_spelling ((char *) alloca (spelling_length () + 1));
+ buffer = (char *) alloca (strlen (local) + strlen (ofwhat) + 2);
+
+ if (*ofwhat)
+ sprintf (buffer, local, ofwhat);
+ else
+ buffer[0] = 0;
+
+ warning (format, buffer);
+}
\f
/* Digest the parser output INIT as an initializer for type TYPE.
Return a C expression of type TYPE to represent the initial value.
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;
tree decl;
char *asmspec;
struct constructor_stack *constructor_stack;
+ tree elements;
struct spelling *spelling;
struct spelling *spelling_base;
int spelling_size;
p->require_constant_value = require_constant_value;
p->require_constant_elements = require_constant_elements;
p->constructor_stack = constructor_stack;
+ p->elements = constructor_elements;
p->spelling = spelling;
p->spelling_base = spelling_base;
p->spelling_size = spelling_size;
constructor_stack = 0;
+ missing_braces_mentioned = 0;
+
spelling_base = 0;
spelling_size = 0;
RESTORE_SPELLING_DEPTH (0);
require_constant_value = p->require_constant_value;
require_constant_elements = p->require_constant_elements;
constructor_stack = p->constructor_stack;
+ constructor_elements = p->elements;
spelling = p->spelling;
spelling_base = p->spelling_base;
spelling_size = p->spelling_size;
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;
}
- /* Turn off constructor_incremental if type is a struct with bitfields. */
- if (constructor_type != 0)
- check_init_type_bitfields (constructor_type);
-
if (constructor_type == 0)
{
error_init ("extra brace group at end of initializer%s",
" for `%s'", NULL);
constructor_fields = 0;
constructor_unfilled_fields = 0;
+ return;
}
- else if (TREE_CODE (constructor_type) == RECORD_TYPE
+
+ /* Turn off constructor_incremental if type is a struct with bitfields. */
+ check_init_type_bitfields (constructor_type);
+
+ if (implicit && warn_missing_braces && !missing_braces_mentioned)
+ {
+ missing_braces_mentioned = 1;
+ warning_init ("missing braces around initializer%s", " for `%s'", NULL);
+ }
+
+ if (TREE_CODE (constructor_type) == RECORD_TYPE
|| 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;
}
else
{
- warning ("braces around scalar initializer");
+ warning_init ("braces around scalar initializer%s", " for `%s'", NULL);
constructor_fields = constructor_type;
constructor_unfilled_fields = constructor_type;
}
tree tail;
for (tail = TYPE_FIELDS (type); tail;
tail = TREE_CHAIN (tail))
- if (DECL_BIT_FIELD (tail)
- /* This catches cases like `int foo : 8;'. */
- || DECL_MODE (tail) != TYPE_MODE (TREE_TYPE (tail)))
- {
- constructor_incremental = 0;
- break;
- }
+ {
+ if (DECL_C_BIT_FIELD (tail)
+ /* This catches cases like `int foo : 8;'. */
+ || DECL_MODE (tail) != TYPE_MODE (TREE_TYPE (tail)))
+ {
+ constructor_incremental = 0;
+ break;
+ }
+
+ check_init_type_bitfields (TREE_TYPE (tail));
+ }
}
+
+ else if (TREE_CODE (type) == ARRAY_TYPE)
+ check_init_type_bitfields (TREE_TYPE (type));
}
/* At the end of an implicit or explicit brace level,
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) == 0)
{
int failure;
+ int momentary_p;
push_obstacks_nochange ();
if (TREE_PERMANENT (constructor_type))
end_temporary_allocation ();
+ momentary_p = suspend_momentary ();
+
/* We shouldn't have an incomplete array type within
some other type. */
if (constructor_stack->next)
abort ();
size = int_size_in_bytes (constructor_type);
+ resume_momentary (momentary_p);
pop_obstacks ();
}
TYPE_DOMAIN (constructor_type) = build_index_type (maxindex);
TREE_TYPE (maxindex) = TYPE_DOMAIN (constructor_type);
- /* We shouldn't have an incomplete array type within
- some other type. */
- if (constructor_stack->next)
- abort ();
-
+ /* 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 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))
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)
+ 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. */
/* 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)
{
tree t = convert_for_assignment (valtype, retval, "return",
NULL_TREE, NULL_TREE, 0);
tree res = DECL_RESULT (current_function_decl);
- t = build (MODIFY_EXPR, TREE_TYPE (res),
- res, convert (TREE_TYPE (res), t));
+ tree inner;
+
+ if (t == error_mark_node)
+ return;
+
+ inner = t = convert (TREE_TYPE (res), t);
+
+ /* Strip any conversions, additions, and subtractions, and see if
+ we are returning the address of a local variable. Warn if so. */
+ while (1)
+ {
+ switch (TREE_CODE (inner))
+ {
+ case NOP_EXPR: case NON_LVALUE_EXPR: case CONVERT_EXPR:
+ case PLUS_EXPR:
+ inner = TREE_OPERAND (inner, 0);
+ continue;
+
+ case MINUS_EXPR:
+ /* 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;
+ }
+
+ break;
+ }
+
+ t = build (MODIFY_EXPR, TREE_TYPE (res), res, t);
TREE_SIDE_EFFECTS (t) = 1;
expand_return (t);
current_function_returns_value = 1;