/* Build expressions with type checking for C compiler.
- Copyright (C) 1987, 1988, 1989, 1992 Free Software Foundation, Inc.
+ Copyright (C) 1987, 1988, 1989, 1992, 1993 Free Software Foundation, Inc.
This file is part of GNU CC.
#include "c-tree.h"
#include "flags.h"
+/* Nonzero if we've already printed a "missing braces around initializer"
+ message within this initializer. */
+static int missing_braces_mentioned;
+
extern char *index ();
extern char *rindex ();
static tree process_init_constructor ();
static tree convert_arguments ();
static char *get_spelling ();
-tree digest_init ();
+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 ();
\f
/* Do `exp = require_complete_type (exp);' to make sure exp
does not have an incomplete type. (That includes void types.) */
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 (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);
+ else
+ subtype2 = t2;
+ subtype = common_type (subtype1, subtype2);
+ return build_complex_type (subtype);
+ }
+
switch (code1)
{
case INTEGER_TYPE:
/* Same precision. Prefer longs to ints even when same size. */
- if (t1 == long_unsigned_type_node
- || t2 == long_unsigned_type_node)
+ if (TYPE_MAIN_VARIANT (t1) == long_unsigned_type_node
+ || TYPE_MAIN_VARIANT (t2) == long_unsigned_type_node)
return long_unsigned_type_node;
- if (t1 == long_integer_type_node
- || t2 == long_integer_type_node)
+ 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 (TYPE_VOLATILE (t1) != TYPE_VOLATILE (t2))
return 0;
- /* If generating auxiliary info, allow for two different type nodes which
- have essentially the same definition. */
+ /* Allow for two different type nodes which have essentially the same
+ definition. Note that we already checked for equality of the type
+ type qualifiers (just above). */
if (TYPE_MAIN_VARIANT (t1) == TYPE_MAIN_VARIANT (t2))
return 1;
}
case RECORD_TYPE:
- return maybe_objc_comptypes (t1, t2);
+ if (maybe_objc_comptypes (t1, t2, 0) == 1)
+ return 1;
}
return 0;
}
comp_target_types (ttl, ttr)
tree ttl, ttr;
{
- int val = comptypes (TYPE_MAIN_VARIANT (TREE_TYPE (ttl)),
- TYPE_MAIN_VARIANT (TREE_TYPE (ttr)));
+ int val;
+
+ /* Give maybe_objc_comptypes a crack at letting these types through. */
+ if (val = maybe_objc_comptypes (ttl, ttr, 1) >= 0)
+ return val;
+
+ val = comptypes (TYPE_MAIN_VARIANT (TREE_TYPE (ttl)),
+ TYPE_MAIN_VARIANT (TREE_TYPE (ttr)));
+
if (val == 2 && pedantic)
pedwarn ("types are not quite compatible");
return val;
t = size_binop (CEIL_DIV_EXPR, TYPE_SIZE (type),
size_int (TYPE_PRECISION (char_type_node)));
/* size_binop does not put the constant in range, so do it now. */
- if (TREE_CODE (t) == INTEGER_CST)
- TREE_CONSTANT_OVERFLOW (t) |= force_fit_type (t, 0);
+ if (TREE_CODE (t) == INTEGER_CST && force_fit_type (t, 0))
+ TREE_CONSTANT_OVERFLOW (t) = TREE_OVERFLOW (t) = 1;
return t;
}
else if (optimize
&& TREE_CODE (exp) == VAR_DECL
&& TREE_READONLY (exp)
+ /* But not for iterators! */
+ && !ITERATOR_P (exp)
&& DECL_MODE (exp) != BLKmode)
{
exp = decl_constant_value (exp);
{
type = type_for_size (MAX (TYPE_PRECISION (type),
TYPE_PRECISION (integer_type_node)),
- (flag_traditional && TREE_UNSIGNED (type)));
+ ((flag_traditional
+ || TYPE_PRECISION (type) >= TYPE_PRECISION (integer_type_node))
+ && TREE_UNSIGNED (type)));
return convert (type, exp);
}
return convert (unsigned_type_node, exp);
return convert (integer_type_node, exp);
}
- if (flag_traditional && TYPE_MAIN_VARIANT (type) == float_type_node)
+ if (flag_traditional && !flag_allow_single_precision
+ && TYPE_MAIN_VARIANT (type) == float_type_node)
return convert (double_type_node, exp);
if (code == VOID_TYPE)
{
register tree adr;
tree restype = TREE_TYPE (type);
tree ptrtype;
+ int constp = 0;
+ int volatilep = 0;
+
+ if (TREE_CODE_CLASS (TREE_CODE (exp)) == 'r'
+ || TREE_CODE_CLASS (TREE_CODE (exp)) == 'd')
+ {
+ constp = TREE_READONLY (exp);
+ volatilep = TREE_THIS_VOLATILE (exp);
+ }
+
+ if (TYPE_READONLY (type) || TYPE_VOLATILE (type)
+ || constp || volatilep)
+ restype = c_build_type_variant (restype,
+ TYPE_READONLY (type) || constp,
+ TYPE_VOLATILE (type) || volatilep);
if (TREE_CODE (exp) == INDIRECT_REF)
return convert (TYPE_POINTER_TO (restype),
return error_mark_node;
}
- if (TYPE_READONLY (type) || TYPE_VOLATILE (type))
- restype = c_build_type_variant (restype, TYPE_READONLY (type),
- TYPE_VOLATILE (type));
-
ptrtype = build_pointer_type (restype);
if (TREE_CODE (exp) == VAR_DECL)
return exp;
}
\f
+/* Look up component name in the structure type definition.
+
+ If this component name is found indirectly within an anonymous union,
+ store in *INDIRECT the component which directly contains
+ that anonymous union. Otherwise, set *INDIRECT to 0. */
+
+static tree
+lookup_field (type, component, indirect)
+ tree type, component;
+ tree *indirect;
+{
+ tree field;
+
+ /* If TYPE_LANG_SPECIFIC is set, then it is a sorted array of pointers
+ to the field elements. Use a binary search on this array to quickly
+ find the element. Otherwise, do a linear search. TYPE_LANG_SPECIFIC
+ will always be set for structures which have many elements. */
+
+ if (TYPE_LANG_SPECIFIC (type))
+ {
+ int bot, top, half;
+ tree *field_array = &TYPE_LANG_SPECIFIC (type)->elts[0];
+
+ field = TYPE_FIELDS (type);
+ bot = 0;
+ top = TYPE_LANG_SPECIFIC (type)->len;
+ while (top - bot > 1)
+ {
+ HOST_WIDE_INT cmp;
+
+ half = (top - bot + 1) >> 1;
+ field = field_array[bot+half];
+
+ if (DECL_NAME (field) == NULL_TREE)
+ {
+ /* Step through all anon unions in linear fashion. */
+ while (DECL_NAME (field_array[bot]) == NULL_TREE)
+ {
+ tree anon, junk;
+
+ field = field_array[bot++];
+ anon = lookup_field (TREE_TYPE (field), component, &junk);
+ if (anon != NULL_TREE)
+ {
+ *indirect = field;
+ return anon;
+ }
+ }
+
+ /* Entire record is only anon unions. */
+ if (bot > top)
+ return NULL_TREE;
+
+ /* Restart the binary search, with new lower bound. */
+ continue;
+ }
+
+ cmp = (HOST_WIDE_INT) DECL_NAME (field) - (HOST_WIDE_INT) component;
+ if (cmp == 0)
+ break;
+ if (cmp < 0)
+ bot += half;
+ else
+ top = bot + half;
+ }
+
+ if (DECL_NAME (field_array[bot]) == component)
+ field = field_array[bot];
+ else if (DECL_NAME (field) != component)
+ field = 0;
+ }
+ else
+ {
+ for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
+ {
+ if (DECL_NAME (field) == NULL_TREE)
+ {
+ tree junk;
+ tree anon = lookup_field (TREE_TYPE (field), component, &junk);
+ if (anon != NULL_TREE)
+ {
+ *indirect = field;
+ return anon;
+ }
+ }
+
+ if (DECL_NAME (field) == component)
+ break;
+ }
+ }
+
+ *indirect = NULL_TREE;
+ return field;
+}
+
/* Make an expression to refer to the COMPONENT field of
structure or union value DATUM. COMPONENT is an IDENTIFIER_NODE. */
if (code == RECORD_TYPE || code == UNION_TYPE)
{
+ tree indirect = 0;
+
if (TYPE_SIZE (type) == 0)
{
incomplete_type_error (NULL_TREE, type);
return error_mark_node;
}
- /* Look up component name in the structure type definition.
-
- If TYPE_LANG_SPECIFIC is set, then it is a sorted array of pointers
- to the field elements. Use a binary search on this array to quickly
- find the element. Otherwise, do a linear search. TYPE_LANG_SPECIFIC
- will always be set for structures which have many elements. */
-
- if (TYPE_LANG_SPECIFIC (type))
- {
- int bot, top, half;
- tree *field_array = &TYPE_LANG_SPECIFIC (type)->elts[0];
-
- field = TYPE_FIELDS (type);
- bot = 0;
- top = TYPE_LANG_SPECIFIC (type)->len;
- while (top - bot > 1)
- {
- int cmp;
-
- half = (top - bot + 1) >> 1;
- field = field_array[bot+half];
- cmp = (long)DECL_NAME (field) - (long)component;
- if (cmp == 0)
- break;
- if (cmp < 0)
- bot += half;
- else
- top = bot + half;
- }
-
- if (DECL_NAME (field_array[bot]) == component)
- field = field_array[bot];
- else if (DECL_NAME (field) != component)
- field = 0;
- }
- else
- {
- for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
- {
- if (DECL_NAME (field) == component)
- break;
- }
- }
+ field = lookup_field (type, component, &indirect);
if (!field)
{
if (TREE_TYPE (field) == error_mark_node)
return error_mark_node;
+ /* If FIELD was found buried within an anonymous union,
+ make one COMPONENT_REF to get that anonymous union,
+ then fall thru to make a second COMPONENT_REF to get FIELD. */
+ if (indirect != 0)
+ {
+ ref = build (COMPONENT_REF, TREE_TYPE (indirect), datum, indirect);
+ if (TREE_READONLY (datum) || TREE_READONLY (indirect))
+ TREE_READONLY (ref) = 1;
+ if (TREE_THIS_VOLATILE (datum) || TREE_THIS_VOLATILE (indirect))
+ TREE_THIS_VOLATILE (ref) = 1;
+ datum = ref;
+ }
+
ref = build (COMPONENT_REF, TREE_TYPE (field), datum, field);
if (TREE_READONLY (datum) || TREE_READONLY (field))
TREE_READONLY (ref) = TYPE_READONLY (t);
TREE_SIDE_EFFECTS (ref)
= TYPE_VOLATILE (t) || TREE_SIDE_EFFECTS (pointer) || flag_volatile;
- TREE_THIS_VOLATILE (ref) = TYPE_VOLATILE (t) || flag_volatile;
+ TREE_THIS_VOLATILE (ref) = TYPE_VOLATILE (t);
return ref;
}
}
if (mark_addressable (array) == 0)
return error_mark_node;
}
+ /* An array that is indexed by a constant value which is not within
+ the array bounds cannot be stored in a register either; because we
+ would get a crash in store_bit_field/extract_bit_field when trying
+ to access a non-existent part of the register. */
+ if (TREE_CODE (index) == INTEGER_CST
+ && TYPE_VALUES (TREE_TYPE (array))
+ && ! int_fits_type_p (index, TYPE_VALUES (TREE_TYPE (array))))
+ {
+ if (mark_addressable (array) == 0)
+ return error_mark_node;
+ }
if (pedantic && !lvalue_p (array))
{
}
}
\f
-/* Check a printf/fprintf/sprintf/scanf/fscanf/sscanf format against PARAMS. */
-
-#define ISDIGIT(c) ((c) >= '0' && (c) <= '9')
-
-#define T_I &integer_type_node
-#define T_L &long_integer_type_node
-#define T_S &short_integer_type_node
-#define T_UI &unsigned_type_node
-#define T_UL &long_unsigned_type_node
-#define T_US &short_unsigned_type_node
-#define T_F &float_type_node
-#define T_D &double_type_node
-#define T_LD &long_double_type_node
-#define T_C &char_type_node
-#define T_V &void_type_node
-#define T_W &wchar_type_node
-
-typedef struct
-{
- char *format_chars;
- int pointer_count;
- /* Type of argument if no length modifier is used. */
- tree *nolen;
- /* Type of argument if length modifier for shortening is used.
- If NULL, then this modifier is not allowed. */
- tree *hlen;
- /* Type of argument if length modifier `l' is used.
- If NULL, then this modifier is not allowed. */
- tree *llen;
- /* Type of argument if length modifier `L' is used.
- If NULL, then this modifier is not allowed. */
- tree *bigllen;
- /* List of other modifier characters allowed with these options. */
- char *flag_chars;
-} format_char_info;
-
-static format_char_info print_table[]
- = {
- { "di", 0, T_I, T_I, T_L, NULL, "-wp0 +" },
- { "oxX", 0, T_UI, T_UI, T_UL, NULL, "-wp0#" },
- { "u", 0, T_UI, T_UI, T_UL, NULL, "-wp0" },
- { "feEgG", 0, T_D, NULL, NULL, T_LD, "-wp0 +#" },
- { "c", 0, T_I, NULL, T_W, NULL, "-w" },
- { "C", 0, T_W, NULL, NULL, NULL, "-w" },
- { "s", 1, T_C, NULL, T_W, NULL, "-wp" },
- { "S", 1, T_W, NULL, NULL, NULL, "-wp" },
- { "p", 1, T_V, NULL, NULL, NULL, "-" },
- { "n", 1, T_I, T_S, T_L, NULL, "" },
- { NULL }
- };
-
-static format_char_info scan_table[]
- = {
- { "di", 1, T_I, T_S, T_L, NULL, "*" },
- { "ouxX", 1, T_UI, T_US, T_UL, NULL, "*" },
- { "efgEG", 1, T_F, NULL, T_D, T_LD, "*" },
- { "sc", 1, T_C, NULL, T_W, NULL, "*" },
- { "[", 1, T_C, NULL, NULL, NULL, "*" },
- { "C", 1, T_W, NULL, NULL, NULL, "*" },
- { "S", 1, T_W, NULL, NULL, NULL, "*" },
- { "p", 2, T_V, NULL, NULL, NULL, "*" },
- { "n", 1, T_I, T_S, T_L, NULL, "" },
- { NULL }
- };
-
-typedef struct
-{
- tree function_ident; /* identifier such as "printf" */
- int is_scan; /* TRUE if *scanf */
- int format_num; /* number of format argument */
- int first_arg_num; /* number of first arg (zero for varargs) */
-} function_info;
-
-static unsigned int function_info_entries = 0;
-static function_info *function_info_table = NULL;
-
-/* Record information for argument format checking. FUNCTION_IDENT is
- the identifier node for the name of the function to check (its decl
- need not exist yet). IS_SCAN is true for scanf-type format checking;
- false indicates printf-style format checking. FORMAT_NUM is the number
- of the argument which is the format control string (starting from 1).
- FIRST_ARG_NUM is the number of the first actual argument to check
- against teh format string, or zero if no checking is not be done
- (e.g. for varargs such as vfprintf). */
-
-void
-record_format_info (function_ident, is_scan, format_num, first_arg_num)
- tree function_ident;
- int is_scan;
- int format_num;
- int first_arg_num;
-{
- function_info *info;
-
- function_info_entries++;
- if (function_info_table)
- function_info_table
- = (function_info *) xrealloc (function_info_table,
- function_info_entries * sizeof (function_info));
- else
- function_info_table = (function_info *) xmalloc (sizeof (function_info));
-
- info = &function_info_table[function_info_entries - 1];
-
- info->function_ident = function_ident;
- info->is_scan = is_scan;
- info->format_num = format_num;
- info->first_arg_num = first_arg_num;
-}
-
-/* Initialize the table of functions to perform format checking on.
- The ANSI functions are always checked (whether <stdio.h> is
- included or not), since it is common to call printf without
- including <stdio.h>. There shouldn't be a problem with this,
- since ANSI reserves these function names whether you include the
- header file or not. In any case, the checking is harmless. */
-
-void
-init_format_info_table ()
-{
- record_format_info (get_identifier ("printf"), 0, 1, 2);
- record_format_info (get_identifier ("fprintf"), 0, 2, 3);
- record_format_info (get_identifier ("sprintf"), 0, 2, 3);
- record_format_info (get_identifier ("scanf"), 1, 1, 2);
- record_format_info (get_identifier ("fscanf"), 1, 2, 3);
- record_format_info (get_identifier ("sscanf"), 1, 2, 3);
- record_format_info (get_identifier ("vprintf"), 0, 1, 0);
- record_format_info (get_identifier ("vfprintf"), 0, 2, 0);
- record_format_info (get_identifier ("vsprintf"), 0, 2, 0);
-}
-
-static char tfaff[] = "too few arguments for format";
-\f
-/* Check the argument list of a call to printf, scanf, etc.
- INFO points to the element of function_info_table.
- PARAMS is the list of argument values. */
-
-static void
-check_format (info, params)
- function_info *info;
- tree params;
-{
- int i;
- int arg_num;
- int suppressed, wide, precise;
- int length_char;
- int format_char;
- int format_length;
- tree format_tree;
- tree cur_param;
- tree cur_type;
- tree wanted_type;
- char *format_chars;
- format_char_info *fci;
- static char message[132];
- char flag_chars[8];
-
- /* Skip to format argument. If the argument isn't available, there's
- no work for us to do; prototype checking will catch the problem. */
- for (arg_num = 1; ; ++arg_num)
- {
- if (params == 0)
- return;
- if (arg_num == info->format_num)
- break;
- params = TREE_CHAIN (params);
- }
- format_tree = TREE_VALUE (params);
- params = TREE_CHAIN (params);
- if (format_tree == 0)
- return;
- /* We can only check the format if it's a string constant. */
- while (TREE_CODE (format_tree) == NOP_EXPR)
- format_tree = TREE_OPERAND (format_tree, 0); /* strip coercion */
- if (format_tree == null_pointer_node)
- {
- warning ("null format string");
- return;
- }
- if (TREE_CODE (format_tree) != ADDR_EXPR)
- return;
- format_tree = TREE_OPERAND (format_tree, 0);
- if (TREE_CODE (format_tree) != STRING_CST)
- return;
- format_chars = TREE_STRING_POINTER (format_tree);
- format_length = TREE_STRING_LENGTH (format_tree);
- if (format_length <= 1)
- warning ("zero-length format string");
- if (format_chars[--format_length] != 0)
- {
- warning ("unterminated format string");
- return;
- }
- /* Skip to first argument to check. */
- while (arg_num + 1 < info->first_arg_num)
- {
- if (params == 0)
- return;
- params = TREE_CHAIN (params);
- ++arg_num;
- }
- while (1)
- {
- if (*format_chars == 0)
- {
- if (format_chars - TREE_STRING_POINTER (format_tree) != format_length)
- warning ("embedded `\\0' in format");
- if (info->first_arg_num != 0 && params != 0)
- warning ("too many arguments for format");
- return;
- }
- if (*format_chars++ != '%')
- continue;
- if (*format_chars == 0)
- {
- warning ("spurious trailing `%%' in format");
- continue;
- }
- if (*format_chars == '%')
- {
- ++format_chars;
- continue;
- }
- flag_chars[0] = 0;
- suppressed = wide = precise = FALSE;
- if (info->is_scan)
- {
- suppressed = *format_chars == '*';
- if (suppressed)
- ++format_chars;
- while (ISDIGIT (*format_chars))
- ++format_chars;
- }
- else
- {
- while (*format_chars != 0 && index (" +#0-", *format_chars) != 0)
- {
- if (index (flag_chars, *format_chars) != 0)
- {
- sprintf (message, "repeated `%c' flag in format",
- *format_chars);
- warning (message);
- }
- i = strlen (flag_chars);
- flag_chars[i++] = *format_chars++;
- flag_chars[i] = 0;
- }
- /* "If the space and + flags both appear,
- the space flag will be ignored." */
- if (index (flag_chars, ' ') != 0
- && index (flag_chars, '+') != 0)
- warning ("use of both ` ' and `+' flags in format");
- /* "If the 0 and - flags both appear,
- the 0 flag will be ignored." */
- if (index (flag_chars, '0') != 0
- && index (flag_chars, '-') != 0)
- warning ("use of both `0' and `-' flags in format");
- if (*format_chars == '*')
- {
- wide = TRUE;
- /* "...a field width...may be indicated by an asterisk.
- In this case, an int argument supplies the field width..." */
- ++format_chars;
- if (params == 0)
- {
- warning (tfaff);
- return;
- }
- if (info->first_arg_num != 0)
- {
- cur_param = TREE_VALUE (params);
- params = TREE_CHAIN (params);
- ++arg_num;
- /* size_t is generally not valid here.
- It will work on most machines, because size_t and int
- have the same mode. But might as well warn anyway,
- since it will fail on other machines. */
- if (TYPE_MAIN_VARIANT (TREE_TYPE (cur_param))
- != integer_type_node)
- {
- sprintf (message,
- "field width is not type int (arg %d)",
- arg_num);
- warning (message);
- }
- }
- }
- else
- {
- while (ISDIGIT (*format_chars))
- {
- wide = TRUE;
- ++format_chars;
- }
- }
- if (*format_chars == '.')
- {
- precise = TRUE;
- ++format_chars;
- if (*format_chars != '*' && !ISDIGIT (*format_chars))
- warning ("`.' not followed by `*' or digit in format");
- /* "...a...precision...may be indicated by an asterisk.
- In this case, an int argument supplies the...precision." */
- if (*format_chars == '*')
- {
- if (info->first_arg_num != 0)
- {
- ++format_chars;
- if (params == 0)
- {
- warning (tfaff);
- return;
- }
- cur_param = TREE_VALUE (params);
- params = TREE_CHAIN (params);
- ++arg_num;
- if (TYPE_MAIN_VARIANT (TREE_TYPE (cur_param))
- != integer_type_node)
- {
- sprintf (message,
- "field width is not type int (arg %d)",
- arg_num);
- warning (message);
- }
- }
- }
- else
- {
- while (ISDIGIT (*format_chars))
- ++format_chars;
- }
- }
- }
- if (*format_chars == 'h' || *format_chars == 'l' || *format_chars == 'L')
- length_char = *format_chars++;
- else
- length_char = 0;
- if (suppressed && length_char != 0)
- {
- sprintf (message,
- "use of `*' and `%c' together in format",
- length_char);
- warning (message);
- }
- format_char = *format_chars;
- if (format_char == 0)
- {
- warning ("conversion lacks type at end of format");
- continue;
- }
- format_chars++;
- fci = info->is_scan ? scan_table : print_table;
- while (1)
- {
- if (fci->format_chars == 0
- || index (fci->format_chars, format_char) != 0)
- break;
- ++fci;
- }
- if (fci->format_chars == 0)
- {
- if (format_char >= 040 && format_char < 0177)
- sprintf (message,
- "unknown conversion type character `%c' in format",
- format_char);
- else
- sprintf (message,
- "unknown conversion type character 0x%x in format",
- format_char);
- warning (message);
- continue;
- }
- if (wide && index (fci->flag_chars, 'w') == 0)
- {
- sprintf (message, "width used with `%c' format",
- format_char);
- warning (message);
- }
- if (precise && index (fci->flag_chars, 'p') == 0)
- {
- sprintf (message, "precision used with `%c' format",
- format_char);
- warning (message);
- }
- if (suppressed)
- {
- if (index (fci->flag_chars, '*') == 0)
- {
- sprintf (message,
- "suppression of `%c' conversion in format",
- format_char);
- warning (message);
- }
- continue;
- }
- for (i = 0; flag_chars[i] != 0; ++i)
- {
- if (index (fci->flag_chars, flag_chars[i]) == 0)
- {
- sprintf (message, "flag `%c' used with type `%c'",
- flag_chars[i], format_char);
- warning (message);
- }
- }
- if (precise && index (flag_chars, '0') != 0
- && (format_char == 'd' || format_char == 'i'
- || format_char == 'o' || format_char == 'u'
- || format_char == 'x' || format_char == 'x'))
- {
- sprintf (message,
- "precision and `0' flag not both allowed with `%c' format",
- format_char);
- warning (message);
- }
- switch (length_char)
- {
- default: wanted_type = fci->nolen ? *(fci->nolen) : 0; break;
- case 'h': wanted_type = fci->hlen ? *(fci->hlen) : 0; break;
- case 'l': wanted_type = fci->llen ? *(fci->llen) : 0; break;
- case 'L': wanted_type = fci->bigllen ? *(fci->bigllen) : 0; break;
- }
- if (wanted_type == 0)
- {
- sprintf (message,
- "use of `%c' length character with `%c' type character",
- length_char, format_char);
- warning (message);
- }
-
- /*
- ** XXX -- should kvetch about stuff such as
- ** {
- ** const int i;
- **
- ** scanf ("%d", &i);
- ** }
- */
-
- /* Finally. . .check type of argument against desired type! */
- if (info->first_arg_num == 0)
- continue;
- if (params == 0)
- {
- warning (tfaff);
- return;
- }
- cur_param = TREE_VALUE (params);
- params = TREE_CHAIN (params);
- ++arg_num;
- cur_type = TREE_TYPE (cur_param);
-
- /* Check the types of any additional pointer arguments
- that precede the "real" argument. */
- for (i = 0; i < fci->pointer_count; ++i)
- {
- if (TREE_CODE (cur_type) == POINTER_TYPE)
- {
- cur_type = TREE_TYPE (cur_type);
- continue;
- }
- sprintf (message,
- "format argument is not a %s (arg %d)",
- ((fci->pointer_count == 1) ? "pointer" : "pointer to a pointer"),
- arg_num);
- warning (message);
- break;
- }
-
- /* Check the type of the "real" argument, if there's a type we want. */
- if (i == fci->pointer_count && wanted_type != 0
- && wanted_type != TYPE_MAIN_VARIANT (cur_type)
- /* If we want `void *', allow any pointer type.
- (Anything else would already have got a warning.) */
- && ! (wanted_type == void_type_node
- && fci->pointer_count > 0)
- /* Don't warn about differences merely in signedness. */
- && !(TREE_CODE (wanted_type) == INTEGER_TYPE
- && TREE_CODE (cur_type) == INTEGER_TYPE
- && TYPE_PRECISION (wanted_type) == TYPE_PRECISION (cur_type)))
- {
- register char *this;
- register char *that;
-
- this = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (wanted_type)));
- that = 0;
- if (TYPE_NAME (cur_type) != 0
- && TREE_CODE (cur_type) != INTEGER_TYPE
- && !(TREE_CODE (cur_type) == POINTER_TYPE
- && TREE_CODE (TREE_TYPE (cur_type)) == INTEGER_TYPE)
- && DECL_NAME (TYPE_NAME (cur_type)) != 0)
- that = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (cur_type)));
-
- /* A nameless type can't possibly match what the format wants.
- So there will be a warning for it.
- Make up a string to describe vaguely what it is. */
- if (that == 0)
- {
- if (TREE_CODE (cur_type) == POINTER_TYPE)
- that = "pointer";
- else
- that = "different type";
- }
-
- if (strcmp (this, that) != 0)
- {
- sprintf (message, "%s format, %s arg (arg %d)",
- this, that, arg_num);
- warning (message);
- }
- }
- }
-}
-\f
/* Build a function call to function FUNCTION with parameters PARAMS.
PARAMS is a list--a chain of TREE_LIST nodes--in which the
TREE_VALUE of each node is a parameter-expression.
build_function_call (function, params)
tree function, params;
{
- register tree fntype, fundecl;
+ register tree fntype, fundecl = 0;
register tree coerced_params;
- tree name = NULL_TREE;
+ tree name = NULL_TREE, assembler_name = NULL_TREE;
/* Strip NON_LVALUE_EXPRs, etc., since we aren't using as an lvalue. */
STRIP_TYPE_NOPS (function);
if (TREE_CODE (function) == FUNCTION_DECL)
{
name = DECL_NAME (function);
+ assembler_name = DECL_ASSEMBLER_NAME (function);
+
/* Differs from default_conversion by not setting TREE_ADDRESSABLE
(because calling an inline function does not mean the function
needs to be separately compiled). */
= convert_arguments (TYPE_ARG_TYPES (fntype), params, name, fundecl);
/* Check for errors in format strings. */
- if (warn_format && name != 0)
- {
- unsigned int i;
-
- /* See if this function is a format function. */
- for (i = 0; i < function_info_entries; i++)
- if (function_info_table[i].function_ident == name)
- {
- register char *message;
- /* If so, check it. */
- check_format (&function_info_table[i], coerced_params);
- break;
- }
- }
+ if (warn_format && (name || assembler_name))
+ check_function_format (name, assembler_name, coerced_params);
/* Recognize certain built-in functions so we can make tree-codes
other than CALL_EXPR. We do this when it enables fold-const.c
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) == INTEGER_TYPE
+ || TREE_CODE (type) == ENUMERAL_TYPE)
&& (TYPE_PRECISION (type) < TYPE_PRECISION (integer_type_node)))
type = integer_type_node;
#endif
/* Change in signedness doesn't matter
if a constant value is unaffected. */
;
+ /* Likewise for a constant in a NOP_EXPR. */
+ else if (TREE_CODE (val) == NOP_EXPR
+ && TREE_CODE (TREE_OPERAND (val, 0)) == INTEGER_CST
+ && int_fits_type_p (TREE_OPERAND (val, 0), type))
+ ;
+#if 0 /* We never get such tree structure here. */
else if (TREE_CODE (TREE_TYPE (val)) == ENUMERAL_TYPE
&& int_fits_type_p (TYPE_MIN_VALUE (TREE_TYPE (val)), type)
&& int_fits_type_p (TYPE_MAX_VALUE (TREE_TYPE (val)), type))
/* Change in signedness doesn't matter
if an enum value is unaffected. */
;
+#endif
+ /* If the value is extended from a narrower
+ unsigned type, it doesn't matter whether we
+ pass it as signed or unsigned; the value
+ certainly is the same either way. */
+ else if (TYPE_PRECISION (TREE_TYPE (val)) < TYPE_PRECISION (type)
+ && TREE_UNSIGNED (TREE_TYPE (val)))
+ ;
else if (TREE_UNSIGNED (type))
warn_for_assignment ("%s as unsigned due to prototype", (char *) 0, name, parmnum + 1);
else
fundecl, name, parmnum + 1);
#ifdef PROMOTE_PROTOTYPES
- if (TREE_CODE (type) == INTEGER_TYPE
+ if ((TREE_CODE (type) == INTEGER_TYPE
+ || TREE_CODE (type) == ENUMERAL_TYPE)
&& (TYPE_PRECISION (type) < TYPE_PRECISION (integer_type_node)))
parmval = default_conversion (parmval);
#endif
else
{
int flag = TREE_CONSTANT (result);
+ /* We used to use NOP_EXPR rather than NON_LVALUE_EXPR
+ so that convert_for_assignment wouldn't strip it.
+ That way, we got warnings for things like p = (1 - 1).
+ But it turns out we should not get those warnings. */
result = build1 (NON_LVALUE_EXPR, TREE_TYPE (result), result);
C_SET_EXP_ORIGINAL_CODE (result, code);
TREE_CONSTANT (result) = flag;
case FLOOR_DIV_EXPR:
case ROUND_DIV_EXPR:
case EXACT_DIV_EXPR:
- if ((code0 == INTEGER_TYPE || code0 == REAL_TYPE)
- && (code1 == INTEGER_TYPE || code1 == REAL_TYPE))
+ if ((code0 == INTEGER_TYPE || code0 == REAL_TYPE
+ || code0 == COMPLEX_TYPE)
+ && (code1 == INTEGER_TYPE || code1 == REAL_TYPE
+ || code1 == COMPLEX_TYPE))
{
if (!(code0 == INTEGER_TYPE && code1 == INTEGER_TYPE))
resultcode = RDIV_EXPR;
else
/* 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 (op0);
+ shorten = TREE_UNSIGNED (orig_op0);
common = 1;
}
break;
case TRUNC_MOD_EXPR:
case FLOOR_MOD_EXPR:
if (code0 == INTEGER_TYPE && code1 == INTEGER_TYPE)
- shorten = 1;
+ {
+ /* 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 (orig_op0)
+ || (TREE_CODE (op1) == INTEGER_CST
+ && (TREE_INT_CST_LOW (op1) != -1
+ || TREE_INT_CST_HIGH (op1) != -1)));
+ common = 1;
+ }
break;
case TRUTH_ANDIF_EXPR:
case TRUTH_AND_EXPR:
case TRUTH_OR_EXPR:
case TRUTH_XOR_EXPR:
- if ((code0 == INTEGER_TYPE || code0 == POINTER_TYPE || code0 == REAL_TYPE)
- && (code1 == INTEGER_TYPE || code1 == POINTER_TYPE || code1 == REAL_TYPE))
+ if ((code0 == INTEGER_TYPE || code0 == POINTER_TYPE
+ || code0 == REAL_TYPE || code0 == COMPLEX_TYPE)
+ && (code1 == INTEGER_TYPE || code1 == POINTER_TYPE
+ || code1 == REAL_TYPE || code1 == COMPLEX_TYPE))
{
/* Result of these operations is always an int,
but that does not mean the operands should be
but don't convert the args to int! */
result_type = integer_type_node;
converted = 1;
- if ((code0 == INTEGER_TYPE || code0 == REAL_TYPE)
- && (code1 == INTEGER_TYPE || code1 == REAL_TYPE))
+ if ((code0 == INTEGER_TYPE || code0 == REAL_TYPE
+ || code0 == COMPLEX_TYPE)
+ && (code1 == INTEGER_TYPE || code1 == REAL_TYPE
+ || code1 == COMPLEX_TYPE))
short_compare = 1;
else if (code0 == POINTER_TYPE && code1 == POINTER_TYPE)
{
register tree tt0 = TREE_TYPE (type0);
register tree tt1 = TREE_TYPE (type1);
/* Anything compares with void *. void * compares with anything.
- Otherwise, the targets must be the same. */
+ Otherwise, the targets must be compatible
+ and both must be object or both incomplete. */
if (comp_target_types (type0, type1))
;
else if (TYPE_MAIN_VARIANT (tt0) == void_type_node)
{
- if (pedantic && !integer_zerop (op0)
+ /* op0 != orig_op0 detects the case of something
+ whose value is 0 but which isn't a valid null ptr const. */
+ if (pedantic && (!integer_zerop (op0) || op0 != orig_op0)
&& TREE_CODE (tt1) == FUNCTION_TYPE)
pedwarn ("ANSI C forbids comparison of `void *' with function pointer");
}
else if (TYPE_MAIN_VARIANT (tt1) == void_type_node)
{
- if (pedantic && !integer_zerop (op1)
+ if (pedantic && (!integer_zerop (op1) || op1 != orig_op1)
&& TREE_CODE (tt0) == FUNCTION_TYPE)
pedwarn ("ANSI C forbids comparison of `void *' with function pointer");
}
case MAX_EXPR:
case MIN_EXPR:
if ((code0 == INTEGER_TYPE || code0 == REAL_TYPE)
- && (code1 == INTEGER_TYPE || code1 == REAL_TYPE))
+ && (code1 == INTEGER_TYPE || code1 == REAL_TYPE))
shorten = 1;
else if (code0 == POINTER_TYPE && code1 == POINTER_TYPE)
{
case LT_EXPR:
case GT_EXPR:
if ((code0 == INTEGER_TYPE || code0 == REAL_TYPE)
- && (code1 == INTEGER_TYPE || code1 == 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;
op1 = null_pointer_node;
- if (! flag_traditional)
+ if (pedantic)
pedwarn ("ordered comparison of pointer with integer zero");
}
else if (code1 == POINTER_TYPE && TREE_CODE (op0) == INTEGER_CST
break;
}
- if ((code0 == INTEGER_TYPE || code0 == REAL_TYPE)
- && (code1 == INTEGER_TYPE || code1 == REAL_TYPE))
+ if ((code0 == INTEGER_TYPE || code0 == REAL_TYPE || code0 == COMPLEX_TYPE)
+ &&
+ (code1 == INTEGER_TYPE || code1 == REAL_TYPE || code1 == COMPLEX_TYPE))
{
+ int none_complex = (code0 != COMPLEX_TYPE && code1 != COMPLEX_TYPE);
+
if (shorten || common || short_compare)
result_type = common_type (type0, type1);
Eg, (short)-1 | (unsigned short)-1 is (int)-1
but calculated in (unsigned short) it would be (unsigned short)-1. */
- if (shorten)
+ if (shorten && none_complex)
{
int unsigned0, unsigned1;
tree arg0 = get_narrower (op0, &unsigned0);
/* Comparison operations are shortened too but differently.
They identify themselves by setting short_compare = 1. */
- if (short_compare)
+ if (short_compare && none_complex)
{
/* Don't write &op0, etc., because that would prevent op0
from being kept in a register.
op0 = build_binary_op (MINUS_EXPR, convert (restype, op0),
convert (restype, op1), 1);
+ /* 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. */
/* This is used for unary plus, because a CONVERT_EXPR
is enough to prevent anybody from looking inside for
associativity, but won't generate any code. */
- if (!(typecode == INTEGER_TYPE || typecode == REAL_TYPE))
+ if (!(typecode == INTEGER_TYPE || typecode == REAL_TYPE
+ || typecode == COMPLEX_TYPE))
errstring = "wrong type argument to unary plus";
else if (!noconvert)
arg = default_conversion (arg);
break;
case NEGATE_EXPR:
- if (!(typecode == INTEGER_TYPE || typecode == REAL_TYPE))
+ if (!(typecode == INTEGER_TYPE || typecode == REAL_TYPE
+ || typecode == COMPLEX_TYPE))
errstring = "wrong type argument to unary minus";
else if (!noconvert)
arg = default_conversion (arg);
break;
case BIT_NOT_EXPR:
- if (typecode != INTEGER_TYPE)
+ if (typecode == COMPLEX_TYPE)
+ {
+ code = CONJ_EXPR;
+ if (!noconvert)
+ arg = default_conversion (arg);
+ }
+ else if (typecode != INTEGER_TYPE)
errstring = "wrong type argument to bit-complement";
else if (!noconvert)
arg = default_conversion (arg);
break;
case ABS_EXPR:
- if (!(typecode == INTEGER_TYPE || typecode == REAL_TYPE))
+ if (!(typecode == INTEGER_TYPE || typecode == REAL_TYPE
+ || typecode == COMPLEX_TYPE))
errstring = "wrong type argument to abs";
else if (!noconvert)
arg = default_conversion (arg);
break;
+ case CONJ_EXPR:
+ /* Conjugating a real value is a no-op, but allow it anyway. */
+ if (!(typecode == INTEGER_TYPE || typecode == REAL_TYPE
+ || typecode == COMPLEX_TYPE))
+ errstring = "wrong type argument to conjugation";
+ else if (!noconvert)
+ arg = default_conversion (arg);
+ break;
+
case TRUTH_NOT_EXPR:
if (typecode != INTEGER_TYPE
&& typecode != REAL_TYPE && typecode != POINTER_TYPE
+ && typecode != COMPLEX_TYPE
/* These will convert to a pointer. */
&& typecode != ARRAY_TYPE && typecode != FUNCTION_TYPE)
{
case NOP_EXPR:
break;
+
+ case REALPART_EXPR:
+ if (TREE_CODE (arg) == COMPLEX_CST)
+ return TREE_REALPART (arg);
+ else if (TREE_CODE (TREE_TYPE (arg)) == COMPLEX_TYPE)
+ return fold (build1 (REALPART_EXPR, TREE_TYPE (TREE_TYPE (arg)), arg));
+ else
+ return arg;
+
+ case IMAGPART_EXPR:
+ if (TREE_CODE (arg) == COMPLEX_CST)
+ return TREE_IMAGPART (arg);
+ else if (TREE_CODE (TREE_TYPE (arg)) == COMPLEX_TYPE)
+ return fold (build1 (IMAGPART_EXPR, TREE_TYPE (TREE_TYPE (arg)), arg));
+ else
+ return convert (TREE_TYPE (arg), integer_zero_node);
case PREINCREMENT_EXPR:
case POSTINCREMENT_EXPR:
if (val != 0)
return val;
+ /* Increment or decrement the real part of the value,
+ and don't change the imaginary part. */
+ if (typecode == COMPLEX_TYPE)
+ {
+ tree real, imag;
+
+ arg = stabilize_reference (arg);
+ real = build_unary_op (REALPART_EXPR, arg, 1);
+ imag = build_unary_op (IMAGPART_EXPR, arg, 1);
+ return build (COMPLEX_EXPR, TREE_TYPE (arg),
+ build_unary_op (code, real, 1), imag);
+ }
+
/* Report invalid types. */
if (typecode != POINTER_TYPE
if (typecode == POINTER_TYPE)
{
- if ((pedantic || warn_pointer_arith)
- && (TREE_CODE (TREE_TYPE (result_type)) == FUNCTION_TYPE
- || TREE_CODE (TREE_TYPE (result_type)) == VOID_TYPE))
+ /* If pointer target is an undefined struct,
+ we just cannot know how to do the arithmetic. */
+ if (TYPE_SIZE (TREE_TYPE (result_type)) == 0)
+ error ("%s of pointer to unknown structure",
+ ((code == PREINCREMENT_EXPR
+ || code == POSTINCREMENT_EXPR)
+ ? "increment" : "decrement"));
+ else if ((pedantic || warn_pointer_arith)
+ && (TREE_CODE (TREE_TYPE (result_type)) == FUNCTION_TYPE
+ || TREE_CODE (TREE_TYPE (result_type)) == VOID_TYPE))
pedwarn ("wrong type argument to %s",
((code == PREINCREMENT_EXPR
|| code == POSTINCREMENT_EXPR)
switch (code)
{
+ case REALPART_EXPR:
+ case IMAGPART_EXPR:
case COMPONENT_REF:
return lvalue_p (TREE_OPERAND (ref, 0));
char buf[80];
strcpy (buf, string);
+ /* Forbid assignments to iterators. */
+ if (TREE_CODE (arg) == VAR_DECL && ITERATOR_P (arg))
+ {
+ strcat (buf, " of iterator `%s'");
+ pedwarn (buf, IDENTIFIER_POINTER (DECL_NAME (arg)));
+ }
+
if (TREE_CODE (arg) == COMPONENT_REF)
{
if (TYPE_READONLY (TREE_TYPE (TREE_OPERAND (arg, 0))))
case ADDR_EXPR:
case COMPONENT_REF:
case ARRAY_REF:
+ case REALPART_EXPR:
+ case IMAGPART_EXPR:
x = TREE_OPERAND (x, 0);
break;
register enum tree_code code1;
register enum tree_code code2;
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. */
ifexp = truthvalue_conversion (default_conversion (ifexp));
- if (TREE_CODE (ifexp) == ERROR_MARK
- || TREE_CODE (TREE_TYPE (op1)) == ERROR_MARK
- || TREE_CODE (TREE_TYPE (op2)) == ERROR_MARK)
- return error_mark_node;
-
#if 0 /* Produces wrong result if within sizeof. */
/* Don't promote the operands separately if they promote
the same way. Return the unpromoted type and let the combined
&& TREE_CODE (TREE_TYPE (op1)) != FUNCTION_TYPE)
{
if (TREE_CODE (ifexp) == INTEGER_CST)
- return (integer_zerop (ifexp) ? op2 : op1);
+ return pedantic_non_lvalue (integer_zerop (ifexp) ? op2 : op1);
return fold (build (COND_EXPR, TREE_TYPE (op1), ifexp, op1, op2));
}
#endif
- /* They don't match; promote them both and then try to reconcile them. */
+ /* Promote both alternatives. */
if (TREE_CODE (TREE_TYPE (op1)) != VOID_TYPE)
op1 = default_conversion (op1);
if (TREE_CODE (TREE_TYPE (op2)) != VOID_TYPE)
op2 = default_conversion (op2);
- type1 = TREE_TYPE (op1);
- code1 = TREE_CODE (type1);
+ if (TREE_CODE (ifexp) == ERROR_MARK
+ || TREE_CODE (TREE_TYPE (op1)) == ERROR_MARK
+ || TREE_CODE (TREE_TYPE (op2)) == ERROR_MARK)
+ return error_mark_node;
+
+ type1 = TREE_TYPE (op1);
+ code1 = TREE_CODE (type1);
type2 = TREE_TYPE (op2);
code2 = TREE_CODE (type2);
{
if (comp_target_types (type1, type2))
result_type = common_type (type1, type2);
- else if (integer_zerop (op1) && TREE_TYPE (type1) == void_type_node)
+ else if (integer_zerop (op1) && TREE_TYPE (type1) == void_type_node
+ && TREE_CODE (orig_op1) != NOP_EXPR)
result_type = qualify_type (type2, type1);
- else if (integer_zerop (op2) && TREE_TYPE (type2) == void_type_node)
+ else if (integer_zerop (op2) && TREE_TYPE (type2) == void_type_node
+ && TREE_CODE (orig_op2) != NOP_EXPR)
result_type = qualify_type (type1, type2);
else if (TYPE_MAIN_VARIANT (TREE_TYPE (type1)) == void_type_node)
{
{
result_type = TREE_TYPE (op1);
if (TREE_CONSTANT (ifexp))
- return (integer_zerop (ifexp) ? op2 : op1);
+ return pedantic_non_lvalue (integer_zerop (ifexp) ? op2 : op1);
if (TYPE_MODE (result_type) == BLKmode)
{
#endif /* 0 */
if (TREE_CODE (ifexp) == INTEGER_CST)
- return integer_zerop (ifexp) ? op2 : op1;
+ return pedantic_non_lvalue (integer_zerop (ifexp) ? op2 : op1);
return fold (build (COND_EXPR, result_type, ifexp, op1, op2));
}
rest = internal_build_compound_expr (TREE_CHAIN (list), FALSE);
- if (! TREE_SIDE_EFFECTS (TREE_VALUE (list)))
+ /* 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;
return build (COMPOUND_EXPR, TREE_TYPE (rest), TREE_VALUE (list), rest);
else if (TREE_CODE (type) == UNION_TYPE)
{
tree field;
+ if (TREE_CODE (TREE_TYPE (value)) == ARRAY_TYPE
+ || TREE_CODE (TREE_TYPE (value)) == FUNCTION_TYPE)
+ value = default_conversion (value);
+
for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
if (comptypes (TYPE_MAIN_VARIANT (TREE_TYPE (field)),
TYPE_MAIN_VARIANT (TREE_TYPE (value))))
if (field)
{
char *name;
- tree nvalue;
+ tree t;
if (pedantic)
pedwarn ("ANSI C forbids casts to union type");
}
else
name = "";
- return digest_init (type, build_nt (CONSTRUCTOR, NULL_TREE,
- build_tree_list (field, value)),
- NULL_PTR, 0, 0, name);
+ t = digest_init (type, build (CONSTRUCTOR, type, NULL_TREE,
+ build_tree_list (field, value)),
+ 0, 0);
+ TREE_CONSTANT (t) = TREE_CONSTANT (value);
+ return t;
}
error ("cast to union type from type not present in union");
return error_mark_node;
}
else
{
- tree otype;
+ tree otype, ovalue;
/* If casting to void, avoid the error that would come
from default_conversion in the case of a non-lvalue array. */
&& !TREE_CONSTANT (value))
warning ("cast to pointer from integer of different size");
+ ovalue = value;
value = convert (type, value);
/* Ignore any integer overflow caused by the cast. */
if (TREE_CODE (value) == INTEGER_CST)
- TREE_CONSTANT_OVERFLOW (value) = 0;
+ {
+ TREE_OVERFLOW (value) = TREE_OVERFLOW (ovalue);
+ TREE_CONSTANT_OVERFLOW (value) = TREE_CONSTANT_OVERFLOW (ovalue);
+ }
}
+ /* Pedantically, don't ley (void *) (FOO *) 0 be a null pointer constant. */
+ if (pedantic && TREE_CODE (value) == INTEGER_CST
+ && TREE_CODE (expr) == INTEGER_CST
+ && TREE_CODE (TREE_TYPE (expr)) != INTEGER_TYPE)
+ value = non_lvalue (value);
+
+ /* If pedantic, don't let a cast be an lvalue. */
if (value == expr && pedantic)
- {
- /* If pedantic, don't let a cast be an lvalue. */
- return non_lvalue (value);
- }
+ value = non_lvalue (value);
+
return value;
}
\f
/* Handle (a, b) used as an "lvalue". */
case COMPOUND_EXPR:
pedantic_lvalue_warning (COMPOUND_EXPR);
+ newrhs = build_modify_expr (TREE_OPERAND (lhs, 1),
+ modifycode, rhs);
+ if (TREE_CODE (newrhs) == ERROR_MARK)
+ return error_mark_node;
return build (COMPOUND_EXPR, lhstype,
- TREE_OPERAND (lhs, 0),
- build_modify_expr (TREE_OPERAND (lhs, 1),
- modifycode, rhs));
-
+ TREE_OPERAND (lhs, 0), newrhs);
+
/* Handle (a ? b : c) used as an "lvalue". */
case COND_EXPR:
pedantic_lvalue_warning (COND_EXPR);
modifycode, rhs),
build_modify_expr (TREE_OPERAND (lhs, 2),
modifycode, rhs));
+ if (TREE_CODE (cond) == ERROR_MARK)
+ return cond;
/* Make sure the code to compute the rhs comes out
before the split. */
return build (COMPOUND_EXPR, TREE_TYPE (lhs),
result = build_modify_expr (inner_lhs, NOP_EXPR,
convert (TREE_TYPE (inner_lhs),
convert (lhstype, newrhs)));
+ if (TREE_CODE (result) == ERROR_MARK)
+ return result;
pedantic_lvalue_warning (CONVERT_EXPR);
return convert (TREE_TYPE (lhs), result);
}
if (TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (rhstype))
{
overflow_warning (rhs);
+ /* Check for Objective-C protocols. This will issue a warning if
+ there are protocol violations. No need to use the return value. */
+ maybe_objc_comptypes (type, rhstype, 0);
return rhs;
}
return error_mark_node;
}
/* Arithmetic types all interconvert, and enum is treated like int. */
- if ((codel == INTEGER_TYPE || codel == REAL_TYPE || codel == ENUMERAL_TYPE)
+ if ((codel == INTEGER_TYPE || codel == REAL_TYPE || codel == ENUMERAL_TYPE
+ || codel == COMPLEX_TYPE)
&&
- (coder == INTEGER_TYPE || coder == REAL_TYPE || coder == ENUMERAL_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)
+ else if (codel == UNION_TYPE)
{
tree memb_types;
for (memb_types = TYPE_FIELDS (type); memb_types;
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);
+ 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. */
+ 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);
+ }
+ }
}
}
/* Conversions among pointers */
if (TYPE_MAIN_VARIANT (ttl) == void_type_node
|| TYPE_MAIN_VARIANT (ttr) == void_type_node
|| comp_target_types (type, rhstype)
- || (!pedantic /* Unless pedantic, mix signed and unsigned. */
- && TREE_CODE (ttl) == INTEGER_TYPE
- && TREE_CODE (ttr) == INTEGER_TYPE
- && TYPE_PRECISION (ttl) == TYPE_PRECISION (ttr)))
+ || (unsigned_type (TYPE_MAIN_VARIANT (ttl))
+ == unsigned_type (TYPE_MAIN_VARIANT (ttr))))
{
if (pedantic
&& ((TYPE_MAIN_VARIANT (ttl) == void_type_node
&& TREE_CODE (ttr) == FUNCTION_TYPE)
||
(TYPE_MAIN_VARIANT (ttr) == void_type_node
- && !integer_zerop (rhs)
+ /* Check TREE_CODE to catch cases like (void *) (char *) 0
+ which are not ANSI null ptr constants. */
+ && (!integer_zerop (rhs) || TREE_CODE (rhs) == NOP_EXPR)
&& TREE_CODE (ttl) == FUNCTION_TYPE)))
warn_for_assignment ("ANSI forbids %s between function pointer and `void *'",
get_spelling (errtype), funname, parmnum);
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))
+ else if (! TYPE_VOLATILE (ttl) && TYPE_VOLATILE (ttr))
warn_for_assignment ("%s discards `volatile' from pointer target type",
get_spelling (errtype), funname, parmnum);
+ /* If this is not a case of ignoring a mismatch in signedness,
+ no warning. */
+ else if (TYPE_MAIN_VARIANT (ttl) == void_type_node
+ || TYPE_MAIN_VARIANT (ttr) == void_type_node
+ || comp_target_types (type, rhstype))
+ ;
+ /* If there is a mismatch, do warn. */
+ else if (pedantic)
+ warn_for_assignment ("pointer targets in %s differ in signedness",
+ get_spelling (errtype), funname, parmnum);
}
else
{
get_spelling (errtype), funname, parmnum);
}
}
- else if (unsigned_type (TYPE_MAIN_VARIANT (ttl))
- == unsigned_type (TYPE_MAIN_VARIANT (ttr)))
- warn_for_assignment ("pointer targets in %s differ in signedness",
- get_spelling (errtype), funname, parmnum);
else
warn_for_assignment ("%s from incompatible pointer type",
get_spelling (errtype), funname, parmnum);
else if (codel == POINTER_TYPE && coder == INTEGER_TYPE)
{
/* An explicit constant 0 can convert to a pointer,
- but not a 0 that results from casting or folding. */
- if (! (TREE_CODE (rhs) == INTEGER_CST && integer_zerop (rhs)))
+ or one that results from arithmetic, even including
+ a cast to integer type. */
+ if (! (TREE_CODE (rhs) == INTEGER_CST && integer_zerop (rhs))
+ &&
+ ! (TREE_CODE (rhs) == NOP_EXPR
+ && TREE_CODE (TREE_TYPE (rhs)) == INTEGER_TYPE
+ && TREE_CODE (TREE_OPERAND (rhs, 0)) == INTEGER_CST
+ && integer_zerop (TREE_OPERAND (rhs, 0))))
{
warn_for_assignment ("%s makes pointer from integer without a cast",
get_spelling (errtype), funname, parmnum);
if (!errtype)
{
if (funname)
- error ("incompatible type for argument %d of `%s'",
- parmnum, IDENTIFIER_POINTER (funname));
+ {
+ tree selector = maybe_building_objc_message_expr ();
+
+ if (selector && parmnum > 2)
+ error ("incompatible type for argument %d of `%s'",
+ parmnum - 2, IDENTIFIER_POINTER (selector));
+ else
+ error ("incompatible type for argument %d of `%s'",
+ parmnum, IDENTIFIER_POINTER (funname));
+ }
else
error ("incompatible type for argument %d of indirect function call",
parmnum);
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)));
+
return TREE_STATIC (value) ? null_pointer_node : 0;
case INTEGER_CST:
case REAL_CST:
case STRING_CST:
+ case COMPLEX_CST:
return null_pointer_node;
case ADDR_EXPR:
return 0;
}
+
+/* If VALUE is a compound expr all of whose expressions are constant, then
+ return its value. Otherwise, return error_mark_node.
+
+ This is for handling COMPOUND_EXPRs as initializer elements
+ which is allowed with a warning when -pedantic is specified. */
+
+static tree
+valid_compound_expr_initializer (value, endtype)
+ tree value;
+ tree endtype;
+{
+ if (TREE_CODE (value) == COMPOUND_EXPR)
+ {
+ if (valid_compound_expr_initializer (TREE_OPERAND (value, 0), endtype)
+ == error_mark_node)
+ return error_mark_node;
+ return valid_compound_expr_initializer (TREE_OPERAND (value, 1),
+ endtype);
+ }
+ else if (! TREE_CONSTANT (value)
+ && ! initializer_constant_valid_p (value, endtype))
+ return error_mark_node;
+ else
+ return value;
+}
\f
/* Perform appropriate conversions on the initial value of a variable,
store it in the declaration DECL,
/* Digest the specified initializer into an expression. */
- value = digest_init (type, init, NULL_PTR, TREE_STATIC (decl),
- TREE_STATIC (decl) || pedantic,
- IDENTIFIER_POINTER (DECL_NAME (decl)));
+ value = digest_init (type, init, TREE_STATIC (decl),
+ TREE_STATIC (decl) || pedantic);
/* Store the expression if valid; else report error. */
}
#endif
+ DECL_INITIAL (decl) = value;
+
/* ANSI wants warnings about out-of-range constant initializers. */
+ STRIP_TYPE_NOPS (value);
constant_expression_warning (value);
-
- DECL_INITIAL (decl) = value;
}
\f
/* Methods for storing and printing names for error messages. */
/* Push a member name on the stack. Printed as '.' STRING. */
static void
-push_member_name (string)
- char *string;
+push_member_name (decl)
+ tree decl;
+
{
+ char *string
+ = DECL_NAME (decl) ? IDENTIFIER_POINTER (DECL_NAME (decl)) : "<anonymous>";
PUSH_SPELLING (SPELLING_MEMBER, string, u.s);
}
char *buffer;
if (ofwhat == 0)
- ofwhat = print_spelling (alloca (spelling_length () + 1));
+ ofwhat = print_spelling ((char *) alloca (spelling_length () + 1));
buffer = (char *) alloca (strlen (local) + strlen (ofwhat) + 2);
if (*ofwhat)
char *buffer;
if (ofwhat == 0)
- ofwhat = print_spelling (alloca (spelling_length () + 1));
+ ofwhat = print_spelling ((char *) alloca (spelling_length () + 1));
buffer = (char *) alloca (strlen (local) + strlen (ofwhat) + 2);
if (*ofwhat)
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.
- If TAIL is nonzero, it points to a variable holding a list of elements
- of which INIT is the first. We update the list stored there by
- removing from the head all the elements that we use.
- Normally this is only one; we use more than one element only if
- TYPE is an aggregate and INIT is not a constructor.
-
The arguments REQUIRE_CONSTANT and CONSTRUCTOR_CONSTANT request errors
if non-constant initializers or elements are seen. CONSTRUCTOR_CONSTANT
- applies only to elements of constructors.
+ applies only to elements of constructors. */
- If OFWHAT is nonnull, it specifies what we are initializing, for error
- messages. Examples: variable name, variable.member, array[44].
- If OFWHAT is null, the component name is stored on the spelling stack. */
-
-tree
-digest_init (type, init, tail, require_constant, constructor_constant, ofwhat)
- tree type, init, *tail;
+static tree
+digest_init (type, init, require_constant, constructor_constant)
+ tree type, init;
int require_constant, constructor_constant;
- char *ofwhat;
{
enum tree_code code = TREE_CODE (type);
- tree element = 0;
- tree old_tail_contents;
- /* Nonzero if INIT is a braced grouping, which comes in as a CONSTRUCTOR
- tree node which has no TREE_TYPE. */
- int raw_constructor
- = TREE_CODE (init) == CONSTRUCTOR && TREE_TYPE (init) == 0;
tree inside_init = init;
- /* By default, assume we use one element from a list.
- We correct this later in the sole case where it is not true. */
-
- if (tail)
- {
- old_tail_contents = *tail;
- *tail = TREE_CHAIN (*tail);
- }
-
if (init == error_mark_node)
return init;
if (TREE_CODE (init) == NON_LVALUE_EXPR)
inside_init = TREE_OPERAND (init, 0);
- if (inside_init && raw_constructor
- && CONSTRUCTOR_ELTS (inside_init) != 0
- && TREE_CHAIN (CONSTRUCTOR_ELTS (inside_init)) == 0)
- {
- element = TREE_VALUE (CONSTRUCTOR_ELTS (inside_init));
- /* Strip NON_LVALUE_EXPRs since we aren't using as an lvalue. */
- if (element && TREE_CODE (element) == NON_LVALUE_EXPR)
- element = TREE_OPERAND (element, 0);
- }
-
/* Initialization of an array of chars from a string constant
optionally enclosed in braces. */
|| typ1 == unsigned_char_type_node
|| typ1 == unsigned_wchar_type_node
|| typ1 == signed_wchar_type_node)
- && ((inside_init && TREE_CODE (inside_init) == STRING_CST)
- || (element && TREE_CODE (element) == STRING_CST)))
+ && ((inside_init && TREE_CODE (inside_init) == STRING_CST)))
{
- tree string = element ? element : inside_init;
+ if (comptypes (TYPE_MAIN_VARIANT (TREE_TYPE (inside_init)),
+ TYPE_MAIN_VARIANT (type)))
+ return inside_init;
- if ((TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (string)))
+ if ((TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (inside_init)))
!= char_type_node)
&& TYPE_PRECISION (typ1) == TYPE_PRECISION (char_type_node))
{
error_init ("char-array%s initialized from wide string",
- " `%s'", ofwhat);
+ " `%s'", NULL);
return error_mark_node;
}
- if ((TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (string)))
+ if ((TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (inside_init)))
== char_type_node)
&& TYPE_PRECISION (typ1) != TYPE_PRECISION (char_type_node))
{
error_init ("int-array%s initialized from non-wide string",
- " `%s'", ofwhat);
+ " `%s'", NULL);
return error_mark_node;
}
- TREE_TYPE (string) = type;
+ TREE_TYPE (inside_init) = type;
if (TYPE_DOMAIN (type) != 0
&& TREE_CODE (TYPE_SIZE (type)) == INTEGER_CST)
{
register int size = TREE_INT_CST_LOW (TYPE_SIZE (type));
size = (size + BITS_PER_UNIT - 1) / BITS_PER_UNIT;
- /* Subtract 1 because it's ok to ignore the terminating null char
+ /* Subtract 1 (or sizeof (wchar_t))
+ because it's ok to ignore the terminating null char
that is counted in the length of the constant. */
- if (size < TREE_STRING_LENGTH (string) - 1)
+ if (size < TREE_STRING_LENGTH (inside_init)
+ - (TYPE_PRECISION (typ1) != TYPE_PRECISION (char_type_node)
+ ? TYPE_PRECISION (wchar_type_node) / BITS_PER_UNIT
+ : 1))
pedwarn_init (
"initializer-string for array of chars%s is too long",
- " `%s'", ofwhat);
+ " `%s'", NULL);
}
- return string;
+ return inside_init;
}
}
- /* Any type except an array can be initialized
- from an expression of the same type, optionally with braces.
- For an array, this is allowed only for a string constant. */
+ /* Any type can be initialized
+ from an expression of the same type, optionally with braces. */
if (inside_init && TREE_TYPE (inside_init) != 0
- && ((TYPE_MAIN_VARIANT (TREE_TYPE (inside_init))
- == TYPE_MAIN_VARIANT (type))
+ && (comptypes (TYPE_MAIN_VARIANT (TREE_TYPE (inside_init)),
+ TYPE_MAIN_VARIANT (type))
|| (code == ARRAY_TYPE
&& comptypes (TREE_TYPE (inside_init), type))
|| (code == POINTER_TYPE
&& (TREE_CODE (TREE_TYPE (inside_init)) == ARRAY_TYPE
|| TREE_CODE (TREE_TYPE (inside_init)) == FUNCTION_TYPE))
inside_init = default_conversion (inside_init);
- else if (code == ARRAY_TYPE && TREE_CODE (inside_init) != STRING_CST)
+ else if (code == ARRAY_TYPE && TREE_CODE (inside_init) != STRING_CST
+ && TREE_CODE (inside_init) != CONSTRUCTOR)
{
error_init ("array%s initialized from non-constant array expression",
- " `%s'", ofwhat);
+ " `%s'", NULL);
return error_mark_node;
}
&& TREE_CODE (inside_init) == VAR_DECL)
inside_init = decl_constant_value (inside_init);
- if (require_constant && ! TREE_CONSTANT (inside_init))
+ /* Compound expressions can only occur here if -pedantic or
+ -pedantic-errors is specified. In the later case, we always want
+ an error. In the former case, we simply want a warning. */
+ if (require_constant && pedantic
+ && TREE_CODE (inside_init) == COMPOUND_EXPR)
+ {
+ inside_init
+ = valid_compound_expr_initializer (inside_init,
+ TREE_TYPE (inside_init));
+ if (inside_init == error_mark_node)
+ error_init ("initializer element%s is not constant",
+ " for `%s'", NULL);
+ else
+ pedwarn_init ("initializer element%s is not constant",
+ " for `%s'", NULL);
+ if (flag_pedantic_errors)
+ inside_init = error_mark_node;
+ }
+ else if (require_constant && ! TREE_CONSTANT (inside_init))
{
error_init ("initializer element%s is not constant",
- " for `%s'", ofwhat);
+ " for `%s'", NULL);
inside_init = error_mark_node;
}
else if (require_constant
&& initializer_constant_valid_p (inside_init, TREE_TYPE (inside_init)) == 0)
{
error_init ("initializer element%s is not computable at load time",
- " for `%s'", ofwhat);
+ " for `%s'", NULL);
inside_init = error_mark_node;
}
return inside_init;
}
- if (element && (TREE_TYPE (element) == type
- || (code == ARRAY_TYPE && TREE_TYPE (element)
- && comptypes (TREE_TYPE (element), type))))
- {
- if (code == ARRAY_TYPE)
- {
- error_init ("array%s initialized from non-constant array expression",
- " `%s'", ofwhat);
- return error_mark_node;
- }
- if (pedantic && (code == RECORD_TYPE || code == UNION_TYPE))
- pedwarn ("single-expression nonscalar initializer has braces");
- if (optimize && TREE_READONLY (element) && TREE_CODE (element) == VAR_DECL)
- element = decl_constant_value (element);
-
- if (require_constant && ! TREE_CONSTANT (element))
- {
- error_init ("initializer element%s is not constant",
- " for `%s'", ofwhat);
- element = error_mark_node;
- }
- else if (require_constant
- && initializer_constant_valid_p (element, TREE_TYPE (element)) == 0)
- {
- error_init ("initializer element%s is not computable at load time",
- " for `%s'", ofwhat);
- element = error_mark_node;
- }
-
- return element;
- }
-
- /* Check for initializing a union by its first field.
- Such an initializer must use braces. */
-
- if (code == UNION_TYPE)
- {
- tree result;
- tree field = TYPE_FIELDS (type);
-
- /* Find the first named field. ANSI decided in September 1990
- that only named fields count here. */
- while (field && DECL_NAME (field) == 0)
- field = TREE_CHAIN (field);
-
- if (field == 0)
- {
- error_init ("union%s with no named members cannot be initialized",
- " `%s'", ofwhat);
- return error_mark_node;
- }
-
- if (raw_constructor)
- result = process_init_constructor (type, inside_init, NULL_PTR,
- require_constant,
- constructor_constant, ofwhat);
- else if (tail != 0)
- {
- *tail = old_tail_contents;
- result = process_init_constructor (type, NULL_TREE, tail,
- require_constant,
- constructor_constant, ofwhat);
- }
- else
- result = 0;
-
- if (result)
- return result;
- }
-
/* Handle scalar types, including conversions. */
if (code == INTEGER_TYPE || code == REAL_TYPE || code == POINTER_TYPE
- || code == ENUMERAL_TYPE)
+ || code == ENUMERAL_TYPE || code == COMPLEX_TYPE)
{
- if (raw_constructor)
- {
- if (element == 0)
- {
- error_init (
- "initializer for scalar%s requires one element",
- " `%s'", ofwhat);
- return error_mark_node;
- }
- else
- {
- /* Deal with extra levels of {...}. */
- if (TREE_CODE (element) == CONSTRUCTOR
- && TREE_TYPE (element) == 0)
- {
- error_init (
- "initializer for scalar%s requires one element",
- " `%s'", ofwhat);
- return error_mark_node;
- }
- inside_init = element;
- }
- }
-
-#if 0 /* A non-raw constructor is an actual expression. */
- if (TREE_CODE (inside_init) == CONSTRUCTOR)
- {
- error_init ("initializer for scalar%s has extra braces",
- " `%s'", ofwhat);
- return error_mark_node;
- }
-#endif
-
- SAVE_SPELLING_DEPTH
- ({
- if (ofwhat)
- push_string (ofwhat);
- inside_init
- = convert_for_assignment (type,
- default_conversion (raw_constructor
- ? inside_init
- : init),
- &initialization_message,
- NULL_TREE, NULL_TREE, 0);
- });
+ /* Note that convert_for_assignment calls default_conversion
+ for arrays and functions. We must not call it in the
+ case where inside_init is a null pointer constant. */
+ inside_init
+ = convert_for_assignment (type, init, "initialization",
+ NULL_TREE, NULL_TREE, 0);
if (require_constant && ! TREE_CONSTANT (inside_init))
{
error_init ("initializer element%s is not constant",
- " for `%s'", ofwhat);
+ " for `%s'", NULL);
inside_init = error_mark_node;
}
else if (require_constant
&& initializer_constant_valid_p (inside_init, TREE_TYPE (inside_init)) == 0)
{
error_init ("initializer element%s is not computable at load time",
- " for `%s'", ofwhat);
+ " for `%s'", NULL);
inside_init = error_mark_node;
}
if (TYPE_SIZE (type) && TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST)
{
error_init ("variable-sized object%s may not be initialized",
- " `%s'", ofwhat);
+ " `%s'", NULL);
return error_mark_node;
}
- if (code == ARRAY_TYPE || code == RECORD_TYPE)
+ /* Traditionally, you can write struct foo x = 0;
+ and it initializes the first element of x to 0. */
+ if (flag_traditional)
{
- if (raw_constructor)
- return process_init_constructor (type, inside_init,
- NULL_PTR, constructor_constant,
- constructor_constant, ofwhat);
- else if (tail != 0)
+ tree top = 0, prev = 0;
+ while (TREE_CODE (type) == RECORD_TYPE
+ || TREE_CODE (type) == ARRAY_TYPE
+ || TREE_CODE (type) == QUAL_UNION_TYPE
+ || TREE_CODE (type) == UNION_TYPE)
{
- *tail = old_tail_contents;
- return process_init_constructor (type, NULL_TREE, tail,
- constructor_constant,
- constructor_constant, ofwhat);
+ tree temp = build (CONSTRUCTOR, type, NULL_TREE, NULL_TREE);
+ if (prev == 0)
+ top = temp;
+ else
+ TREE_OPERAND (prev, 1) = build_tree_list (NULL_TREE, temp);
+ prev = temp;
+ if (TREE_CODE (type) == ARRAY_TYPE)
+ type = TREE_TYPE (type);
+ else if (TYPE_FIELDS (type))
+ type = TREE_TYPE (TYPE_FIELDS (type));
+ else
+ {
+ error_init ("invalid initializer%s", " for `%s'", NULL);
+ return error_mark_node;
+ }
}
- else if (flag_traditional)
- /* Traditionally one can say `char x[100] = 0;'. */
- return process_init_constructor (type,
- build_nt (CONSTRUCTOR, NULL_TREE,
- tree_cons (NULL_TREE,
- inside_init,
- NULL_TREE)),
- NULL_PTR, constructor_constant,
- constructor_constant, ofwhat);
- }
-
- error_init ("invalid initializer%s", " for `%s'", ofwhat);
+ TREE_OPERAND (prev, 1)
+ = build_tree_list (NULL_TREE,
+ digest_init (type, init, require_constant,
+ constructor_constant));
+ return top;
+ }
+ error_init ("invalid initializer%s", " for `%s'", NULL);
return error_mark_node;
}
\f
-/* Process a constructor for a variable of type TYPE.
- The constructor elements may be specified either with INIT or with ELTS,
- only one of which should be non-null.
+/* Handle initializers that use braces. */
- If INIT is specified, it is a CONSTRUCTOR node which is specifically
- and solely for initializing this datum.
+static void output_init_element ();
+static void output_pending_init_elements ();
+static void check_init_type_bitfields ();
- If ELTS is specified, it is the address of a variable containing
- a list of expressions. We take as many elements as we need
- from the head of the list and update the list.
+/* 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;
- In the resulting constructor, TREE_CONSTANT is set if all elts are
- constant, and TREE_STATIC is set if, in addition, all elts are simple enough
- constants that the assembler and linker can compute them.
+/* For a RECORD_TYPE or UNION_TYPE, this is the chain of fields
+ left to fill. */
+static tree constructor_fields;
- The argument CONSTANT_VALUE says to print an error if either the
- value or any element is not a constant.
+/* For an ARRAY_TYPE, this is the specified index
+ at which to store the next element we get.
+ This is a special INTEGER_CST node that we modify in place. */
+static tree constructor_index;
- The argument CONSTANT_ELEMENT says to print an error if an element
- of an aggregate is not constant. It does not apply to a value
- which is not a constructor.
+/* For an ARRAY_TYPE, this is the end index of the range
+ to intitialize with the next element, or NULL in the ordinary case
+ where the element is used just once. */
+static tree constructor_range_end;
- OFWHAT is a character string describing the object being initialized,
- for error messages. It might be "variable" or "variable.member"
- or "variable[17].member[5]". If OFWHAT is null, the description string
- is stored on the spelling stack. */
+/* For an ARRAY_TYPE, this is the maximum index. */
+static tree constructor_max_index;
-static tree
-process_init_constructor (type, init, elts, constant_value, constant_element,
- ofwhat)
- tree type, init, *elts;
- int constant_value, constant_element;
- char *ofwhat;
-{
- register tree tail;
- /* List of the elements of the result constructor,
- in reverse order. */
- register tree members = NULL;
- tree result;
- int allconstant = 1;
- int allsimple = 1;
- int erroneous = 0;
- int depth = SPELLING_DEPTH ();
+/* For a RECORD_TYPE, this is the first field not yet written out. */
+static tree constructor_unfilled_fields;
- if (ofwhat)
- push_string (ofwhat);
+/* For an ARRAY_TYPE, this is the index of the first element
+ not yet written out.
+ This is a special INTEGER_CST node that we modify in place. */
+static tree constructor_unfilled_index;
- /* Make TAIL be the list of elements to use for the initialization,
- no matter how the data was given to us. */
+/* In a RECORD_TYPE, the byte index of the next consecutive field.
+ This is so we can generate gaps between fields, when appropriate.
+ This is a special INTEGER_CST node that we modify in place. */
+static tree constructor_bit_index;
- if (elts)
- {
- if (warn_missing_braces)
- warning ("aggregate has a partly bracketed initializer");
- tail = *elts;
- }
- else
- tail = CONSTRUCTOR_ELTS (init);
+/* If we are saving up the elements rather than allocating them,
+ this is the list of elements so far (in reverse order,
+ most recent first). */
+static tree constructor_elements;
- /* Gobble as many elements as needed, and make a constructor or initial value
- for each element of this aggregate. Chain them together in result.
- If there are too few, use 0 for each scalar ultimate component. */
+/* 1 if so far this constructor's elements are all compile-time constants. */
+static int constructor_constant;
- if (TREE_CODE (type) == ARRAY_TYPE)
- {
- tree min_index, max_index, current_index, members_index;
- tree bound_type;
- tree one;
- /* These are non-zero only within a range initializer. */
- tree start_index = 0, end_index = 0;
- /* Within a range, this is the value for the elts in the range. */
- tree range_val = 0;
-
- /* If we have array bounds, set our bounds from that. Otherwise,
- we have a lower bound of zero and an unknown upper bound. Also
- set the type of the bounds; use "int" as default. */
- if (TYPE_DOMAIN (type))
- {
- min_index = members_index = TYPE_MIN_VALUE (TYPE_DOMAIN (type));
- max_index = TYPE_MAX_VALUE (TYPE_DOMAIN (type));
- bound_type = TREE_TYPE (min_index);
- }
- else
- {
- min_index = members_index = integer_zero_node;
- max_index = 0;
- bound_type = integer_type_node;
- }
+/* 1 if so far this constructor's elements are all valid address constants. */
+static int constructor_simple;
- one = convert (bound_type, integer_one_node);
+/* 1 if this constructor is erroneous so far. */
+static int constructor_erroneous;
- /* Don't leave the loop based on index if the next item has an explicit
- index value that will override it. */
+/* 1 if have called defer_addressed_constants. */
+static int constructor_subconstants_deferred;
- for (current_index = min_index; tail != 0 || end_index;
- current_index = fold (build (PLUS_EXPR, bound_type,
- current_index, one)))
- {
- register tree next1 = 0;
+/* List of pending elements at this constructor level.
+ These are elements encountered out of order
+ which belong at places we haven't reached yet in actually
+ writing the output. */
+static tree constructor_pending_elts;
- /* Handle the case where we are inside of a range.
- current_index increments through the range,
- so just keep reusing the same element of TAIL
- until the end of the range. */
- if (end_index != 0)
- {
- next1 = range_val;
- if (!tree_int_cst_lt (current_index, end_index))
- end_index = 0;
- }
+/* The SPELLING_DEPTH of this constructor. */
+static int constructor_depth;
- /* If this element specifies an index,
- move to that index before storing it in the new list. */
- else if (TREE_PURPOSE (tail) != 0)
- {
- int win = 0;
- tree index = TREE_PURPOSE (tail);
+/* 0 if implicitly pushing constructor levels is allowed. */
+int constructor_no_implicit = 0; /* 0 for C; 1 for some other languages. */
- if (index && (TREE_CODE (index) == NON_LVALUE_EXPR
- || TREE_CODE (index) == NOP_EXPR))
- index = TREE_OPERAND (index, 0);
+/* 1 if this constructor level was entered implicitly. */
+static int constructor_implicit;
- /* Begin a range. */
- if (TREE_CODE (index) == TREE_LIST)
- {
- start_index = TREE_PURPOSE (index);
- end_index = TREE_PURPOSE (TREE_CHAIN (index));
-
- /* Expose constants. It Doesn't matter if we change
- the mode.*/
- if (end_index
- && (TREE_CODE (end_index) == NON_LVALUE_EXPR
- || TREE_CODE (end_index) == NOP_EXPR))
- end_index = TREE_OPERAND (end_index, 0);
- if (start_index
- && (TREE_CODE (start_index) == NON_LVALUE_EXPR
- || TREE_CODE (start_index) == NOP_EXPR))
- start_index = TREE_OPERAND (start_index, 0);
-
- constant_expression_warning (start_index);
- constant_expression_warning (end_index);
-
- if ((TREE_CODE (start_index) == IDENTIFIER_NODE)
- || (TREE_CODE (end_index) == IDENTIFIER_NODE))
- error ("field name used as index in array initializer");
- else if ((TREE_CODE (start_index) != INTEGER_CST)
- || (TREE_CODE (end_index) != INTEGER_CST))
- error ("non-constant or non-integer array index in initializer");
- else if (tree_int_cst_lt (start_index, min_index)
- || (max_index && tree_int_cst_lt (max_index, start_index))
- || tree_int_cst_lt (end_index, min_index)
- || (max_index && tree_int_cst_lt (max_index, end_index)))
- error ("array index out of range in initializer");
- else if (tree_int_cst_lt (end_index, start_index))
- {
- /* If the range is empty, don't initialize any elements,
- but do reset current_index for the next initializer
- element. */
- warning ("empty array initializer range");
- tail = TREE_CHAIN (tail);
- current_index = end_index;
- continue;
- }
- else
- {
- current_index = start_index;
- win = 1;
- /* See if the first element is also the last. */
- if (!tree_int_cst_lt (current_index, end_index))
- end_index = 0;
- }
- }
- else if (TREE_CODE (index) == IDENTIFIER_NODE)
- error ("field name used as index in array initializer");
- else if (TREE_CODE (index) != INTEGER_CST)
- error ("non-constant array index in initializer");
- else if (tree_int_cst_lt (index, min_index)
- || (max_index && tree_int_cst_lt (max_index, index)))
- error ("array index out of range in initializer");
- else
- {
- constant_expression_warning (index);
- current_index = index, win = 1;
- }
+static int require_constant_value;
+static int require_constant_elements;
- if (!win)
- {
- /* If there was an error, end the current range. */
- end_index = 0;
- TREE_VALUE (tail) = error_mark_node;
- }
- }
+/* 1 if it is ok to output this constructor as we read it.
+ 0 means must accumulate a CONSTRUCTOR expression. */
+static int constructor_incremental;
- if (max_index && tree_int_cst_lt (max_index, current_index))
- break; /* Stop if we've indeed run out of elements. */
+/* DECL node for which an initializer is being read.
+ 0 means we are reading a constructor expression
+ such as (struct foo) {...}. */
+static tree constructor_decl;
- /* Now digest the value specified. */
- if (next1 != 0)
- ;
- else if (TREE_VALUE (tail) != 0)
- {
- tree tail1 = tail;
-
- /* Build the element of this array, with "[]" notation. For
- error messages, we assume that the index fits within a
- host int. */
- SAVE_SPELLING_DEPTH
- ({
- push_array_bounds (TREE_INT_CST_LOW (current_index));
- next1 = digest_init (TYPE_MAIN_VARIANT (TREE_TYPE (type)),
- TREE_VALUE (tail), &tail1,
- /* Both of these are the same because
- a value here is an elt overall. */
- constant_element, constant_element,
- NULL_PTR);
- });
-
- if (tail1 != 0 && TREE_CODE (tail1) != TREE_LIST)
- abort ();
- if (tail == tail1 && TYPE_DOMAIN (type) == 0)
- {
- error_init (
- "non-empty initializer for array%s of empty elements",
- " `%s'", NULL_PTR);
- /* Just ignore what we were supposed to use. */
- tail1 = 0;
- }
- tail = tail1;
- }
- else
- {
- next1 = error_mark_node;
- tail = TREE_CHAIN (tail);
- }
+/* start_init saves the ASMSPEC arg here for really_start_incremental_init. */
+static char *constructor_asmspec;
- if (end_index != 0)
- range_val = next1;
+/* Nonzero if this is an initializer for a top-level decl. */
+static int constructor_top_level;
- if (next1 == error_mark_node)
- erroneous = 1;
- else if (!TREE_CONSTANT (next1))
- allconstant = 0;
- else if (initializer_constant_valid_p (next1, TREE_TYPE (next1)) == 0)
- allsimple = 0;
+/* When we finish reading a constructor expression
+ (constructor_decl is 0), the CONSTRUCTOR goes here. */
+static tree constructor_result;
+\f
+/* This stack has a level for each implicit or explicit level of
+ structuring in the initializer, including the outermost one. It
+ saves the values of most of the variables above. */
- /* Now store NEXT1 in the list, I elements from the *end*.
- Make the list longer if necessary. */
- while (! tree_int_cst_lt (current_index, members_index))
- {
- members = tree_cons (NULL_TREE, NULL_TREE, members);
- members_index = fold (build (PLUS_EXPR, bound_type,
- members_index, one));
- }
+struct constructor_stack
+{
+ struct constructor_stack *next;
+ tree type;
+ tree fields;
+ tree index;
+ tree range_end;
+ tree max_index;
+ tree unfilled_index;
+ tree unfilled_fields;
+ tree bit_index;
+ tree elements;
+ int offset;
+ tree pending_elts;
+ int depth;
+ /* If nonzero, this value should replace the entire
+ constructor at this level. */
+ tree replacement_value;
+ char constant;
+ char simple;
+ char implicit;
+ char incremental;
+ char erroneous;
+ char outer;
+};
- {
- tree temp;
- tree idx;
-
- temp = members;
- for (idx = fold (build (MINUS_EXPR, bound_type,
- members_index, one));
- tree_int_cst_lt (current_index, idx);
- idx = fold (build (MINUS_EXPR, bound_type, idx, one)))
- temp = TREE_CHAIN (temp);
- TREE_VALUE (temp) = next1;
- }
- }
- }
- if (TREE_CODE (type) == RECORD_TYPE)
- {
- register tree field;
- int members_length = 0;
- int i;
+struct constructor_stack *constructor_stack;
- /* Don't leave the loop based on field just yet; see if next item
- overrides the expected field first. */
+/* This stack records separate initializers that are nested.
+ Nested initializers can't happen in ANSI C, but GNU C allows them
+ in cases like { ... (struct foo) { ... } ... }. */
- for (field = TYPE_FIELDS (type), i = 0; tail;
- field = TREE_CHAIN (field), i++)
- {
- register tree next1;
+struct initializer_stack
+{
+ struct initializer_stack *next;
+ tree decl;
+ char *asmspec;
+ struct constructor_stack *constructor_stack;
+ tree elements;
+ struct spelling *spelling;
+ struct spelling *spelling_base;
+ int spelling_size;
+ char top_level;
+ char incremental;
+ char require_constant_value;
+ char require_constant_elements;
+ char deferred;
+};
- /* If this element specifies a field,
- move to that field before storing it in the new list. */
- if (TREE_PURPOSE (tail) != 0)
- {
- int win = 0;
+struct initializer_stack *initializer_stack;
+\f
+/* Prepare to parse and output the initializer for variable DECL. */
- if (TREE_CODE (TREE_PURPOSE (tail)) != IDENTIFIER_NODE)
- error ("index value instead of field name in structure initializer");
- else
- {
- tree temp;
- int j;
- for (temp = TYPE_FIELDS (type), j = 0;
- temp;
- temp = TREE_CHAIN (temp), j++)
- if (DECL_NAME (temp) == TREE_PURPOSE (tail))
- break;
- if (temp)
- field = temp, i = j, win = 1;
- else
- error ("no field `%s' in structure being initialized",
- IDENTIFIER_POINTER (TREE_PURPOSE (tail)));
- }
- if (!win)
- TREE_VALUE (tail) = error_mark_node;
- }
+void
+start_init (decl, asmspec_tree, top_level)
+ tree decl;
+ tree asmspec_tree;
+ int top_level;
+{
+ char *locus;
+ struct initializer_stack *p
+ = (struct initializer_stack *) xmalloc (sizeof (struct initializer_stack));
+ char *asmspec = 0;
+
+ if (asmspec_tree)
+ asmspec = TREE_STRING_POINTER (asmspec_tree);
+
+ p->decl = constructor_decl;
+ p->asmspec = constructor_asmspec;
+ p->incremental = constructor_incremental;
+ p->require_constant_value = require_constant_value;
+ p->require_constant_elements = require_constant_elements;
+ p->constructor_stack = constructor_stack;
+ p->elements = constructor_elements;
+ p->spelling = spelling;
+ p->spelling_base = spelling_base;
+ p->spelling_size = spelling_size;
+ p->deferred = constructor_subconstants_deferred;
+ p->top_level = constructor_top_level;
+ p->next = initializer_stack;
+ initializer_stack = p;
+
+ constructor_decl = decl;
+ constructor_incremental = top_level;
+ constructor_asmspec = asmspec;
+ constructor_subconstants_deferred = 0;
+ constructor_top_level = top_level;
+
+ if (decl != 0)
+ {
+ require_constant_value = TREE_STATIC (decl);
+ require_constant_elements
+ = ((TREE_STATIC (decl) || pedantic)
+ /* For a scalar, you can always use any value to initialize,
+ even within braces. */
+ && (TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE
+ || TREE_CODE (TREE_TYPE (decl)) == RECORD_TYPE
+ || TREE_CODE (TREE_TYPE (decl)) == UNION_TYPE
+ || TREE_CODE (TREE_TYPE (decl)) == QUAL_UNION_TYPE));
+ locus = IDENTIFIER_POINTER (DECL_NAME (decl));
+ constructor_incremental |= TREE_STATIC (decl);
+ }
+ else
+ {
+ require_constant_value = 0;
+ require_constant_elements = 0;
+ locus = "(anonymous)";
+ }
- if (field == 0)
- break; /* No more fields to init. */
+ constructor_stack = 0;
- if (! DECL_NAME (field))
- {
- next1 = integer_zero_node;
- }
- else if (TREE_VALUE (tail) != 0)
- {
- tree tail1 = tail;
-
- /* Build the name of this member, with a "." for membership. */
- SAVE_SPELLING_DEPTH
- ({
- push_member_name (IDENTIFIER_POINTER (DECL_NAME (field)));
- next1 = digest_init (TREE_TYPE (field),
- TREE_VALUE (tail), &tail1,
- constant_element, constant_element,
- NULL_PTR);
- });
- if (tail1 != 0 && TREE_CODE (tail1) != TREE_LIST)
- abort ();
- tail = tail1;
- }
- else
- {
- next1 = error_mark_node;
- tail = TREE_CHAIN (tail);
- }
+ missing_braces_mentioned = 0;
- if (next1 == error_mark_node)
- erroneous = 1;
- else if (!TREE_CONSTANT (next1))
- allconstant = 0;
- else if (initializer_constant_valid_p (next1, TREE_TYPE (next1)) == 0)
- allsimple = 0;
+ spelling_base = 0;
+ spelling_size = 0;
+ RESTORE_SPELLING_DEPTH (0);
- /* Now store NEXT1 in the list, I elements from the *end*.
- Make the list longer if necessary. */
- while (i >= members_length)
- {
- members = tree_cons (NULL_TREE, NULL_TREE, members);
- members_length++;
- }
- {
- tree temp;
- int j;
-
- temp = members;
- for (j = members_length - 1; j > i; j--)
- temp = TREE_CHAIN (temp);
- TREE_VALUE (temp) = next1;
- TREE_PURPOSE (temp) = field;
- }
- }
- }
- if (TREE_CODE (type) == UNION_TYPE)
- {
- register tree field = TYPE_FIELDS (type);
- register tree next1;
+ if (locus)
+ push_string (locus);
+}
- /* Find the first named field. ANSI decided in September 1990
- that only named fields count here. */
- while (field && DECL_NAME (field) == 0)
- field = TREE_CHAIN (field);
+void
+finish_init ()
+{
+ struct initializer_stack *p = initializer_stack;
- /* For a union, get the initializer for 1 fld. */
+ /* Output subconstants (string constants, usually)
+ that were referenced within this initializer and saved up.
+ Must do this if and only if we called defer_addressed_constants. */
+ if (constructor_subconstants_deferred)
+ output_deferred_addressed_constants ();
- if (tail == 0)
- {
- error ("empty initializer for union");
- tail = build_tree_list (0, 0);
- }
+ /* Free the whole constructor stack of this initializer. */
+ while (constructor_stack)
+ {
+ struct constructor_stack *q = constructor_stack;
+ constructor_stack = q->next;
+ free (q);
+ }
- /* If this element specifies a field, initialize via that field. */
- if (TREE_PURPOSE (tail) != 0)
- {
- int win = 0;
+ /* Pop back to the data of the outer initializer (if any). */
+ constructor_decl = p->decl;
+ constructor_asmspec = p->asmspec;
+ constructor_incremental = p->incremental;
+ require_constant_value = p->require_constant_value;
+ require_constant_elements = p->require_constant_elements;
+ constructor_stack = p->constructor_stack;
+ constructor_elements = p->elements;
+ spelling = p->spelling;
+ spelling_base = p->spelling_base;
+ spelling_size = p->spelling_size;
+ constructor_subconstants_deferred = p->deferred;
+ constructor_top_level = p->top_level;
+ initializer_stack = p->next;
+ free (p);
+}
+\f
+/* Call here when we see the initializer is surrounded by braces.
+ This is instead of a call to push_init_level;
+ it is matched by a call to pop_init_level.
- if (TREE_CODE (TREE_PURPOSE (tail)) == FIELD_DECL)
- /* Handle the case of a call by build_c_cast. */
- field = TREE_PURPOSE (tail), win = 1;
- else if (TREE_CODE (TREE_PURPOSE (tail)) != IDENTIFIER_NODE)
- error ("index value instead of field name in union initializer");
- else
- {
- tree temp;
- for (temp = TYPE_FIELDS (type);
- temp;
- temp = TREE_CHAIN (temp))
- if (DECL_NAME (temp) == TREE_PURPOSE (tail))
- break;
- if (temp)
- field = temp, win = 1;
- else
- error ("no field `%s' in union being initialized",
- IDENTIFIER_POINTER (TREE_PURPOSE (tail)));
- }
- if (!win)
- TREE_VALUE (tail) = error_mark_node;
- }
+ TYPE is the type to initialize, for a constructor expression.
+ For an initializer for a decl, TYPE is zero. */
- if (TREE_VALUE (tail) != 0)
+void
+really_start_incremental_init (type)
+ tree type;
+{
+ struct constructor_stack *p
+ = (struct constructor_stack *) xmalloc (sizeof (struct constructor_stack));
+
+ if (type == 0)
+ type = TREE_TYPE (constructor_decl);
+
+ /* Turn off constructor_incremental if type is a struct with bitfields.
+ Do this before the first push, so that the corrected value
+ is available in finish_init. */
+ check_init_type_bitfields (type);
+
+ p->type = constructor_type;
+ p->fields = constructor_fields;
+ p->index = constructor_index;
+ p->range_end = constructor_range_end;
+ p->max_index = constructor_max_index;
+ p->unfilled_index = constructor_unfilled_index;
+ p->unfilled_fields = constructor_unfilled_fields;
+ p->bit_index = constructor_bit_index;
+ p->elements = 0;
+ p->constant = constructor_constant;
+ p->simple = constructor_simple;
+ p->erroneous = constructor_erroneous;
+ p->pending_elts = constructor_pending_elts;
+ p->depth = constructor_depth;
+ p->replacement_value = 0;
+ p->implicit = 0;
+ p->incremental = constructor_incremental;
+ p->outer = 0;
+ p->next = 0;
+ constructor_stack = p;
+
+ constructor_constant = 1;
+ constructor_simple = 1;
+ constructor_depth = SPELLING_DEPTH ();
+ constructor_elements = 0;
+ constructor_pending_elts = 0;
+ constructor_type = type;
+
+ if (TREE_CODE (constructor_type) == RECORD_TYPE
+ || TREE_CODE (constructor_type) == UNION_TYPE)
+ {
+ constructor_fields = TYPE_FIELDS (constructor_type);
+ /* Skip any nameless bit fields atthe beginning. */
+ while (constructor_fields != 0 && DECL_BIT_FIELD (constructor_fields)
+ && DECL_NAME (constructor_fields) == 0)
+ constructor_fields = TREE_CHAIN (constructor_fields);
+ constructor_unfilled_fields = constructor_fields;
+ constructor_bit_index = copy_node (integer_zero_node);
+ }
+ else if (TREE_CODE (constructor_type) == ARRAY_TYPE)
+ {
+ constructor_range_end = 0;
+ if (TYPE_DOMAIN (constructor_type))
{
- tree tail1 = tail;
-
- /* Build the name of this member, with a "." for membership. */
- SAVE_SPELLING_DEPTH
- ({
- push_member_name (IDENTIFIER_POINTER (DECL_NAME (field)));
- next1 = digest_init (TREE_TYPE (field),
- TREE_VALUE (tail), &tail1,
- constant_value, constant_element, NULL_PTR);
- });
- if (tail1 != 0 && TREE_CODE (tail1) != TREE_LIST)
- abort ();
- tail = tail1;
+ constructor_max_index
+ = TYPE_MAX_VALUE (TYPE_DOMAIN (constructor_type));
+ constructor_index
+ = copy_node (TYPE_MIN_VALUE (TYPE_DOMAIN (constructor_type)));
}
else
- {
- next1 = error_mark_node;
- tail = TREE_CHAIN (tail);
- }
-
- if (next1 == error_mark_node)
- erroneous = 1;
- else if (!TREE_CONSTANT (next1))
- allconstant = 0;
- else if (initializer_constant_valid_p (next1, TREE_TYPE (next1)) == 0)
- allsimple = 0;
- members = tree_cons (field, next1, members);
+ constructor_index = copy_node (integer_zero_node);
+ constructor_unfilled_index = copy_node (constructor_index);
}
-
- /* If arguments were specified as a list, just remove the ones we used. */
- if (elts)
- *elts = tail;
- /* If arguments were specified as a constructor,
- complain unless we used all the elements of the constructor. */
- else if (tail)
+ else
{
- if (TREE_CODE (type) == UNION_TYPE)
+ /* Handle the case of int x = {5}; */
+ constructor_fields = constructor_type;
+ constructor_unfilled_fields = constructor_type;
+ }
+
+ if (constructor_incremental)
+ {
+ int momentary = suspend_momentary ();
+ push_obstacks_nochange ();
+ if (TREE_PERMANENT (constructor_decl))
+ end_temporary_allocation ();
+ make_decl_rtl (constructor_decl, constructor_asmspec,
+ constructor_top_level);
+ assemble_variable (constructor_decl, constructor_top_level, 0, 1);
+ pop_obstacks ();
+ resume_momentary (momentary);
+ }
+
+ if (constructor_incremental)
+ {
+ defer_addressed_constants ();
+ constructor_subconstants_deferred = 1;
+ }
+}
+\f
+/* Push down into a subobject, for initialization.
+ If this is for an explicit set of braces, IMPLICIT is 0.
+ If it is because the next element belongs at a lower level,
+ IMPLICIT is 1. */
+
+void
+push_init_level (implicit)
+ int implicit;
+{
+ struct constructor_stack *p;
+
+ /* If we've exhausted any levels that didn't have braces,
+ pop them now. */
+ while (constructor_stack->implicit)
+ {
+ if ((TREE_CODE (constructor_type) == RECORD_TYPE
+ || TREE_CODE (constructor_type) == UNION_TYPE)
+ && constructor_fields == 0)
+ process_init_element (pop_init_level (1));
+ else if (TREE_CODE (constructor_type) == ARRAY_TYPE
+ && tree_int_cst_lt (constructor_max_index, constructor_index))
+ process_init_element (pop_init_level (1));
+ else
+ break;
+ }
+
+ /* Structure elements may require alignment. Do this now
+ if necessary for the subaggregate. */
+ if (constructor_incremental && TREE_CODE (constructor_type) == RECORD_TYPE
+ && constructor_fields)
+ {
+ /* Advance to offset of this element. */
+ if (! tree_int_cst_equal (constructor_bit_index,
+ DECL_FIELD_BITPOS (constructor_fields)))
{
- pedwarn_init ("excess elements in union initializer%s",
- " after `%s'", NULL_PTR);
+ int next = (TREE_INT_CST_LOW
+ (DECL_FIELD_BITPOS (constructor_fields))
+ / BITS_PER_UNIT);
+ int here = (TREE_INT_CST_LOW (constructor_bit_index)
+ / BITS_PER_UNIT);
+
+ assemble_zeros (next - here);
}
+ }
+
+ p = (struct constructor_stack *) xmalloc (sizeof (struct constructor_stack));
+ p->type = constructor_type;
+ p->fields = constructor_fields;
+ p->index = constructor_index;
+ p->range_end = constructor_range_end;
+ p->max_index = constructor_max_index;
+ p->unfilled_index = constructor_unfilled_index;
+ p->unfilled_fields = constructor_unfilled_fields;
+ p->bit_index = constructor_bit_index;
+ p->elements = constructor_elements;
+ p->constant = constructor_constant;
+ p->simple = constructor_simple;
+ p->erroneous = constructor_erroneous;
+ p->pending_elts = constructor_pending_elts;
+ p->depth = constructor_depth;
+ p->replacement_value = 0;
+ p->implicit = implicit;
+ p->incremental = constructor_incremental;
+ p->outer = 0;
+ p->next = constructor_stack;
+ constructor_stack = p;
+
+ constructor_constant = 1;
+ constructor_simple = 1;
+ constructor_depth = SPELLING_DEPTH ();
+ constructor_elements = 0;
+ constructor_pending_elts = 0;
+
+ /* Don't die if an entire brace-pair level is superfluous
+ in the containing level. */
+ if (constructor_type == 0)
+ ;
+ else if (TREE_CODE (constructor_type) == RECORD_TYPE
+ || TREE_CODE (constructor_type) == UNION_TYPE)
+ {
+ /* Don't die if there are extra init elts at the end. */
+ if (constructor_fields == 0)
+ constructor_type = 0;
else
{
- pedwarn_init ("excess elements in aggregate initializer%s",
- " after `%s'", NULL_PTR);
+ constructor_type = TREE_TYPE (constructor_fields);
+ push_member_name (constructor_fields);
}
}
+ else if (TREE_CODE (constructor_type) == ARRAY_TYPE)
+ {
+ constructor_type = TREE_TYPE (constructor_type);
+ push_array_bounds (TREE_INT_CST_LOW (constructor_index));
+ }
- /* It might be possible to use SAVE_SPELLING_DEPTH, but I suspect that
- some preprocessor somewhere won't accept that much text as an argument.
- It's also likely to make debugging difficult. */
+ 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;
+ }
- RESTORE_SPELLING_DEPTH (depth);
+ /* Turn off constructor_incremental if type is a struct with bitfields. */
+ check_init_type_bitfields (constructor_type);
- if (erroneous)
- return error_mark_node;
+ if (implicit && warn_missing_braces && !missing_braces_mentioned)
+ {
+ missing_braces_mentioned = 1;
+ warning_init ("missing braces around initializer%s", " for `%s'", NULL);
+ }
- result = build (CONSTRUCTOR, type, NULL_TREE, nreverse (members));
- if (allconstant) TREE_CONSTANT (result) = 1;
- if (allconstant && allsimple) TREE_STATIC (result) = 1;
- return result;
+ 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)
+ && DECL_NAME (constructor_fields) == 0)
+ constructor_fields = TREE_CHAIN (constructor_fields);
+ constructor_unfilled_fields = constructor_fields;
+ constructor_bit_index = copy_node (integer_zero_node);
+ }
+ else if (TREE_CODE (constructor_type) == ARRAY_TYPE)
+ {
+ constructor_range_end = 0;
+ if (TYPE_DOMAIN (constructor_type))
+ {
+ constructor_max_index
+ = TYPE_MAX_VALUE (TYPE_DOMAIN (constructor_type));
+ constructor_index
+ = copy_node (TYPE_MIN_VALUE (TYPE_DOMAIN (constructor_type)));
+ }
+ else
+ constructor_index = copy_node (integer_zero_node);
+ constructor_unfilled_index = copy_node (constructor_index);
+ }
+ else
+ {
+ warning_init ("braces around scalar initializer%s", " for `%s'", NULL);
+ constructor_fields = constructor_type;
+ constructor_unfilled_fields = constructor_type;
+ }
+}
+
+/* Don't read a struct incrementally if it has any bitfields,
+ because the incremental reading code doesn't know how to
+ handle bitfields yet. */
+
+static void
+check_init_type_bitfields (type)
+ tree type;
+{
+ if (TREE_CODE (type) == RECORD_TYPE)
+ {
+ tree tail;
+ for (tail = TYPE_FIELDS (type); tail;
+ tail = TREE_CHAIN (tail))
+ if (DECL_BIT_FIELD (tail)
+ /* This catches cases like `int foo : 8;'. */
+ || DECL_MODE (tail) != TYPE_MODE (TREE_TYPE (tail)))
+ {
+ constructor_incremental = 0;
+ break;
+ }
+ }
+}
+
+/* At the end of an implicit or explicit brace level,
+ finish up that level of constructor.
+ If we were outputting the elements as they are read, return 0
+ from inner levels (process_init_element ignores that),
+ but return error_mark_node from the outermost level
+ (that's what we want to put in DECL_INITIAL).
+ Otherwise, return a CONSTRUCTOR expression. */
+
+tree
+pop_init_level (implicit)
+ int implicit;
+{
+ struct constructor_stack *p;
+ int size;
+ tree constructor = 0;
+
+ if (implicit == 0)
+ {
+ /* When we come to an explicit close brace,
+ pop any inner levels that didn't have explicit braces. */
+ while (constructor_stack->implicit)
+ process_init_element (pop_init_level (1));
+ }
+
+ p = constructor_stack;
+
+ if (constructor_type != 0)
+ size = int_size_in_bytes (constructor_type);
+
+ /* Now output all pending elements. */
+ output_pending_init_elements (1);
+
+#if 0 /* c-parse.in warns about {}. */
+ /* In ANSI, each brace level must have at least one element. */
+ if (! implicit && pedantic
+ && (TREE_CODE (constructor_type) == ARRAY_TYPE
+ ? integer_zerop (constructor_unfilled_index)
+ : constructor_unfilled_fields == TYPE_FIELDS (constructor_type)))
+ pedwarn_init ("empty braces in initializer%s", " for `%s'", NULL);
+#endif
+
+ /* Pad out the end of the structure. */
+
+ if (p->replacement_value)
+ {
+ /* If this closes a superfluous brace pair,
+ just pass out the element between them. */
+ constructor = p->replacement_value;
+ /* If this is the top level thing within the initializer,
+ and it's for a variable, then since we already called
+ assemble_variable, we must output the value now. */
+ if (p->next == 0 && constructor_decl != 0
+ && constructor_incremental)
+ {
+ constructor = digest_init (constructor_type, constructor,
+ 0, 0);
+
+ /* If initializing an array of unknown size,
+ determine the size now. */
+ if (TREE_CODE (constructor_type) == ARRAY_TYPE
+ && TYPE_DOMAIN (constructor_type) == 0)
+ {
+ int failure;
+ int momentary_p;
+
+ push_obstacks_nochange ();
+ if (TREE_PERMANENT (constructor_type))
+ end_temporary_allocation ();
+
+ momentary_p = suspend_momentary ();
+
+ /* We shouldn't have an incomplete array type within
+ some other type. */
+ if (constructor_stack->next)
+ abort ();
+
+ failure
+ = complete_array_type (constructor_type,
+ constructor, 0);
+ if (failure)
+ abort ();
+
+ size = int_size_in_bytes (constructor_type);
+ resume_momentary (momentary_p);
+ pop_obstacks ();
+ }
+
+ output_constant (constructor, size);
+ }
+ }
+ else if (constructor_type == 0)
+ ;
+ else if (TREE_CODE (constructor_type) != RECORD_TYPE
+ && TREE_CODE (constructor_type) != UNION_TYPE
+ && TREE_CODE (constructor_type) != ARRAY_TYPE
+ && ! constructor_incremental)
+ {
+ /* A nonincremental scalar initializer--just return
+ the element, after verifying there is just one. */
+ if (constructor_elements == 0)
+ {
+ error_init ("empty scalar initializer%s",
+ " for `%s'", NULL);
+ constructor = error_mark_node;
+ }
+ else if (TREE_CHAIN (constructor_elements) != 0)
+ {
+ error_init ("extra elements in scalar initializer%s",
+ " for `%s'", NULL);
+ constructor = TREE_VALUE (constructor_elements);
+ }
+ else
+ constructor = TREE_VALUE (constructor_elements);
+ }
+ else if (! constructor_incremental)
+ {
+ if (constructor_erroneous)
+ constructor = error_mark_node;
+ else
+ {
+ int momentary = suspend_momentary ();
+
+ constructor = build (CONSTRUCTOR, constructor_type, NULL_TREE,
+ nreverse (constructor_elements));
+ if (constructor_constant)
+ TREE_CONSTANT (constructor) = 1;
+ if (constructor_constant && constructor_simple)
+ TREE_STATIC (constructor) = 1;
+
+ resume_momentary (momentary);
+ }
+ }
+ else
+ {
+ tree filled;
+ int momentary = suspend_momentary ();
+
+ if (TREE_CODE (constructor_type) == RECORD_TYPE
+ || TREE_CODE (constructor_type) == UNION_TYPE)
+ {
+ /* Find the offset of the end of that field. */
+ filled = size_binop (CEIL_DIV_EXPR,
+ constructor_bit_index,
+ size_int (BITS_PER_UNIT));
+ }
+ else if (TREE_CODE (constructor_type) == ARRAY_TYPE)
+ {
+ /* If initializing an array of unknown size,
+ determine the size now. */
+ if (TREE_CODE (constructor_type) == ARRAY_TYPE
+ && TYPE_DOMAIN (constructor_type) == 0)
+ {
+ tree maxindex
+ = size_binop (MINUS_EXPR,
+ constructor_unfilled_index,
+ integer_one_node);
+
+ push_obstacks_nochange ();
+ if (TREE_PERMANENT (constructor_type))
+ end_temporary_allocation ();
+ maxindex = copy_node (maxindex);
+ TYPE_DOMAIN (constructor_type) = build_index_type (maxindex);
+ TREE_TYPE (maxindex) = TYPE_DOMAIN (constructor_type);
+
+ /* We shouldn't have an incomplete array type within
+ some other type. */
+ if (constructor_stack->next)
+ abort ();
+
+ 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'");
+ layout_type (constructor_type);
+ size = int_size_in_bytes (constructor_type);
+ pop_obstacks ();
+ }
+
+ filled = size_binop (MULT_EXPR, constructor_unfilled_index,
+ size_in_bytes (TREE_TYPE (constructor_type)));
+ }
+ else
+ filled = 0;
+
+ if (filled != 0)
+ assemble_zeros (size - TREE_INT_CST_LOW (filled));
+
+ resume_momentary (momentary);
+ }
+
+
+ constructor_type = p->type;
+ constructor_fields = p->fields;
+ constructor_index = p->index;
+ constructor_range_end = p->range_end;
+ constructor_max_index = p->max_index;
+ constructor_unfilled_index = p->unfilled_index;
+ constructor_unfilled_fields = p->unfilled_fields;
+ constructor_bit_index = p->bit_index;
+ constructor_elements = p->elements;
+ constructor_constant = p->constant;
+ constructor_simple = p->simple;
+ constructor_erroneous = p->erroneous;
+ constructor_pending_elts = p->pending_elts;
+ constructor_depth = p->depth;
+ constructor_incremental = p->incremental;
+ RESTORE_SPELLING_DEPTH (constructor_depth);
+
+ constructor_stack = p->next;
+ free (p);
+
+ if (constructor == 0)
+ {
+ if (constructor_stack == 0)
+ return error_mark_node;
+ return NULL_TREE;
+ }
+ return constructor;
+}
+
+/* Within an array initializer, specify the next index to be initialized.
+ FIRST is that index. If LAST is nonzero, then initialize a range
+ of indices, running from FIRST through LAST. */
+
+void
+set_init_index (first, last)
+ tree first, last;
+{
+ while ((TREE_CODE (first) == NOP_EXPR
+ || TREE_CODE (first) == CONVERT_EXPR
+ || TREE_CODE (first) == NON_LVALUE_EXPR)
+ && (TYPE_MODE (TREE_TYPE (first))
+ == TYPE_MODE (TREE_TYPE (TREE_OPERAND (first, 0)))))
+ (first) = TREE_OPERAND (first, 0);
+ if (last)
+ while ((TREE_CODE (last) == NOP_EXPR
+ || TREE_CODE (last) == CONVERT_EXPR
+ || TREE_CODE (last) == NON_LVALUE_EXPR)
+ && (TYPE_MODE (TREE_TYPE (last))
+ == TYPE_MODE (TREE_TYPE (TREE_OPERAND (last, 0)))))
+ (last) = TREE_OPERAND (last, 0);
+
+ if (TREE_CODE (first) != INTEGER_CST)
+ error_init ("nonconstant array index in initializer%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 (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);
+
+ if (last != 0 && tree_int_cst_lt (last, first))
+ error_init ("empty index range in initializer%s", " for `%s'", NULL);
+ else
+ {
+ if (pedantic)
+ pedwarn ("ANSI C forbids specifying element to initialize");
+ constructor_range_end = last;
+ }
+ }
+}
+
+/* Within a struct initializer, specify the next field to be initialized. */
+
+void
+set_init_label (fieldname)
+ tree fieldname;
+{
+ tree tail;
+ int passed = 0;
+
+ for (tail = TYPE_FIELDS (constructor_type); tail;
+ tail = TREE_CHAIN (tail))
+ {
+ if (tail == constructor_unfilled_fields)
+ passed = 1;
+ if (DECL_NAME (tail) == fieldname)
+ break;
+ }
+
+ if (tail == 0)
+ error ("unknown field `%s' specified in initializer",
+ IDENTIFIER_POINTER (fieldname));
+ else if (!passed)
+ error ("field `%s' already initialized",
+ IDENTIFIER_POINTER (fieldname));
+ else
+ {
+ constructor_fields = tail;
+ if (pedantic)
+ pedwarn ("ANSI C forbids specifying structure member to initialize");
+ }
+}
+\f
+/* "Output" the next constructor element.
+ At top level, really output it to assembler code now.
+ Otherwise, collect it in a list from which we will make a CONSTRUCTOR.
+ TYPE is the data type that the containing data type wants here.
+ FIELD is the field (a FIELD_DECL) or the index that this element fills.
+
+ PENDING if non-nil means output pending elements that belong
+ right after this element. (PENDING is normally 1;
+ it is 0 while outputting pending elements, to avoid recursion.) */
+
+static void
+output_init_element (value, type, field, pending)
+ tree value, type, field;
+ int pending;
+{
+ int duplicate = 0;
+
+ if (TREE_CODE (TREE_TYPE (value)) == FUNCTION_TYPE
+ || (TREE_CODE (TREE_TYPE (value)) == ARRAY_TYPE
+ && !(TREE_CODE (value) == STRING_CST
+ && TREE_CODE (type) == ARRAY_TYPE
+ && TREE_CODE (TREE_TYPE (type)) == INTEGER_TYPE)
+ && !comptypes (TYPE_MAIN_VARIANT (TREE_TYPE (value)),
+ TYPE_MAIN_VARIANT (type))))
+ value = default_conversion (value);
+
+ if (value == error_mark_node)
+ constructor_erroneous = 1;
+ else if (!TREE_CONSTANT (value))
+ constructor_constant = 0;
+ else if (initializer_constant_valid_p (value, TREE_TYPE (value)) == 0)
+ constructor_simple = 0;
+
+ if (require_constant_value && ! TREE_CONSTANT (value))
+ {
+ error_init ("initializer element%s is not constant",
+ " for `%s'", NULL);
+ value = error_mark_node;
+ }
+ else if (require_constant_elements
+ && initializer_constant_valid_p (value, TREE_TYPE (value)) == 0)
+ {
+ error_init ("initializer element%s is not computable at load time",
+ " for `%s'", NULL);
+ value = error_mark_node;
+ }
+
+ /* If this element duplicates one on constructor_pending_elts,
+ print a message and ignore it. Don't do this when we're
+ processing elements taken off constructor_pending_elts,
+ because we'd always get spurious errors. */
+ if (pending)
+ {
+ if (TREE_CODE (constructor_type) == RECORD_TYPE
+ || TREE_CODE (constructor_type) == UNION_TYPE)
+ {
+ if (purpose_member (field, constructor_pending_elts))
+ {
+ error_init ("duplicate initializer%s", " for `%s'", NULL);
+ duplicate = 1;
+ }
+ }
+ if (TREE_CODE (constructor_type) == ARRAY_TYPE)
+ {
+ tree tail;
+ for (tail = constructor_pending_elts; tail;
+ tail = TREE_CHAIN (tail))
+ if (TREE_PURPOSE (tail) != 0
+ && TREE_CODE (TREE_PURPOSE (tail)) == INTEGER_CST
+ && tree_int_cst_equal (TREE_PURPOSE (tail), constructor_index))
+ break;
+
+ if (tail != 0)
+ {
+ error_init ("duplicate initializer%s", " for `%s'", NULL);
+ duplicate = 1;
+ }
+ }
+ }
+
+ /* If this element doesn't come next in sequence,
+ put it on constructor_pending_elts. */
+ if (TREE_CODE (constructor_type) == ARRAY_TYPE
+ && !tree_int_cst_equal (field, constructor_unfilled_index))
+ {
+ if (! duplicate)
+ /* The copy_node is needed in case field is actually
+ constructor_index, which is modified in place. */
+ constructor_pending_elts
+ = tree_cons (copy_node (field),
+ digest_init (type, value, 0, 0),
+ constructor_pending_elts);
+ }
+ else if (TREE_CODE (constructor_type) == RECORD_TYPE
+ && field != constructor_unfilled_fields)
+ {
+ /* We do this for records but not for unions. In a union,
+ no matter which field is specified, it can be initialized
+ right away since it starts at the beginning of the union. */
+ if (!duplicate)
+ constructor_pending_elts
+ = tree_cons (field,
+ digest_init (type, value, 0, 0),
+ constructor_pending_elts);
+ }
+ else
+ {
+ /* Otherwise, output this element either to
+ constructor_elements or to the assembler file. */
+
+ if (!duplicate)
+ {
+ if (! constructor_incremental)
+ {
+ if (field && TREE_CODE (field) == INTEGER_CST)
+ field = copy_node (field);
+ constructor_elements
+ = tree_cons (field, digest_init (type, value, 0, 0),
+ constructor_elements);
+ }
+ else
+ {
+ /* Structure elements may require alignment.
+ Do this, if necessary. */
+ if (TREE_CODE (constructor_type) == RECORD_TYPE)
+ {
+ /* Advance to offset of this element. */
+ if (! tree_int_cst_equal (constructor_bit_index,
+ DECL_FIELD_BITPOS (constructor_fields)))
+ {
+ int next = (TREE_INT_CST_LOW (DECL_FIELD_BITPOS (field))
+ / BITS_PER_UNIT);
+ int here = (TREE_INT_CST_LOW (constructor_bit_index)
+ / BITS_PER_UNIT);
+
+ assemble_zeros (next - here);
+ }
+ }
+ output_constant (digest_init (type, value, 0, 0),
+ int_size_in_bytes (type));
+
+ /* For a record or union,
+ keep track of end position of last field. */
+ 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_INT_CST_LOW (constructor_bit_index)
+ = TREE_INT_CST_LOW (temp);
+ TREE_INT_CST_HIGH (constructor_bit_index)
+ = TREE_INT_CST_HIGH (temp);
+ }
+ }
+ }
+
+ /* Advance the variable that indicates sequential elements output. */
+ if (TREE_CODE (constructor_type) == ARRAY_TYPE)
+ {
+ tree tem = size_binop (PLUS_EXPR, constructor_unfilled_index,
+ integer_one_node);
+ TREE_INT_CST_LOW (constructor_unfilled_index)
+ = TREE_INT_CST_LOW (tem);
+ TREE_INT_CST_HIGH (constructor_unfilled_index)
+ = TREE_INT_CST_HIGH (tem);
+ }
+ else if (TREE_CODE (constructor_type) == RECORD_TYPE)
+ constructor_unfilled_fields = TREE_CHAIN (constructor_unfilled_fields);
+ else if (TREE_CODE (constructor_type) == UNION_TYPE)
+ constructor_unfilled_fields = 0;
+
+ /* Now output any pending elements which have become next. */
+ if (pending)
+ output_pending_init_elements (0);
+ }
+}
+
+/* Output any pending elements which have become next.
+ As we output elements, constructor_unfilled_{fields,index}
+ advances, which may cause other elements to become next;
+ if so, they too are output.
+
+ If ALL is 0, we return when there are
+ no more pending elements to output now.
+
+ If ALL is 1, we output space as necessary so that
+ we can output all the pending elements. */
+
+static void
+output_pending_init_elements (all)
+ int all;
+{
+ tree tail;
+ tree next;
+
+ retry:
+
+ /* Look thru the whole pending list.
+ If we find an element that should be output now,
+ output it. Otherwise, set NEXT to the element
+ that comes first among those still pending. */
+
+ next = 0;
+ for (tail = constructor_pending_elts; tail;
+ tail = TREE_CHAIN (tail))
+ {
+ if (TREE_CODE (constructor_type) == ARRAY_TYPE)
+ {
+ if (tree_int_cst_equal (TREE_PURPOSE (tail),
+ constructor_unfilled_index))
+ {
+ output_init_element (TREE_VALUE (tail), TREE_TYPE (constructor_type),
+ constructor_unfilled_index, 0);
+ goto retry;
+ }
+ else if (tree_int_cst_lt (TREE_PURPOSE (tail),
+ constructor_unfilled_index))
+ ;
+ else if (next == 0
+ || tree_int_cst_lt (TREE_PURPOSE (tail),
+ next))
+ next = TREE_PURPOSE (tail);
+ }
+ else if (TREE_CODE (constructor_type) == RECORD_TYPE
+ || TREE_CODE (constructor_type) == UNION_TYPE)
+ {
+ if (TREE_PURPOSE (tail) == constructor_unfilled_fields)
+ {
+ output_init_element (TREE_VALUE (tail),
+ TREE_TYPE (constructor_unfilled_fields),
+ constructor_unfilled_fields,
+ 0);
+ goto retry;
+ }
+ else if (constructor_unfilled_fields == 0
+ || tree_int_cst_lt (DECL_FIELD_BITPOS (TREE_PURPOSE (tail)),
+ DECL_FIELD_BITPOS (constructor_unfilled_fields)))
+ ;
+ else if (next == 0
+ || tree_int_cst_lt (DECL_FIELD_BITPOS (TREE_PURPOSE (tail)),
+ DECL_FIELD_BITPOS (next)))
+ next = TREE_PURPOSE (tail);
+ }
+ }
+
+ /* Ordinarily return, but not if we want to output all
+ and there are elements left. */
+ if (! (all && next != 0))
+ return;
+
+ /* Generate space up to the position of NEXT. */
+ if (constructor_incremental)
+ {
+ tree filled;
+ tree nextpos_tree;
+
+ if (TREE_CODE (constructor_type) == RECORD_TYPE
+ || TREE_CODE (constructor_type) == UNION_TYPE)
+ {
+ /* Find the last field written out. */
+ 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));
+ nextpos_tree = size_binop (CEIL_DIV_EXPR,
+ DECL_FIELD_BITPOS (next),
+ size_int (BITS_PER_UNIT));
+ constructor_unfilled_fields = next;
+ }
+ else if (TREE_CODE (constructor_type) == ARRAY_TYPE)
+ {
+ filled = size_binop (MULT_EXPR, constructor_unfilled_index,
+ size_in_bytes (TREE_TYPE (constructor_type)));
+ nextpos_tree
+ = size_binop (MULT_EXPR, next,
+ size_in_bytes (TREE_TYPE (constructor_type)));
+ TREE_INT_CST_LOW (constructor_unfilled_index)
+ = TREE_INT_CST_LOW (next);
+ TREE_INT_CST_HIGH (constructor_unfilled_index)
+ = TREE_INT_CST_HIGH (next);
+ }
+ else
+ filled = 0;
+
+ if (filled)
+ {
+ int nextpos = TREE_INT_CST_LOW (nextpos_tree);
+
+ assemble_zeros (nextpos - TREE_INT_CST_LOW (filled));
+ }
+ }
+ else
+ {
+ /* If it's not incremental, just skip over the gap,
+ so that after jumping to retry we will output the next
+ successive element. */
+ if (TREE_CODE (constructor_type) == RECORD_TYPE
+ || TREE_CODE (constructor_type) == UNION_TYPE)
+ constructor_unfilled_fields = next;
+ else if (TREE_CODE (constructor_type) == ARRAY_TYPE)
+ {
+ TREE_INT_CST_LOW (constructor_unfilled_index)
+ = TREE_INT_CST_LOW (next);
+ TREE_INT_CST_HIGH (constructor_unfilled_index)
+ = TREE_INT_CST_HIGH (next);
+ }
+ }
+
+ goto retry;
+}
+\f
+/* Add one non-braced element to the current constructor level.
+ This adjusts the current position within the constructor's type.
+ This may also start or terminate implicit levels
+ to handle a partly-braced initializer.
+
+ Once this has found the correct level for the new element,
+ it calls output_init_element.
+
+ Note: if we are incrementally outputting this constructor,
+ this function may be called with a null argument
+ representing a sub-constructor that was already incrementally output.
+ When that happens, we output nothing, but we do the bookkeeping
+ to skip past that element of the current constructor. */
+
+void
+process_init_element (value)
+ tree value;
+{
+ tree orig_value = value;
+ int string_flag = value != 0 && TREE_CODE (value) == STRING_CST;
+
+ /* Handle superfluous braces around string cst as in
+ char x[] = {"foo"}; */
+ if (string_flag
+ && TREE_CODE (constructor_type) == ARRAY_TYPE
+ && TREE_CODE (TREE_TYPE (constructor_type)) == INTEGER_TYPE
+ && integer_zerop (constructor_unfilled_index))
+ {
+ constructor_stack->replacement_value = value;
+ return;
+ }
+
+ if (constructor_stack->replacement_value != 0)
+ {
+ error_init ("excess elements in struct initializer%s",
+ " after `%s'", NULL_PTR);
+ return;
+ }
+
+ /* Ignore elements of a brace group if it is entirely superfluous
+ and has already been diagnosed. */
+ if (constructor_type == 0)
+ return;
+
+ /* If we've exhausted any levels that didn't have braces,
+ pop them now. */
+ while (constructor_stack->implicit)
+ {
+ if ((TREE_CODE (constructor_type) == RECORD_TYPE
+ || TREE_CODE (constructor_type) == UNION_TYPE)
+ && constructor_fields == 0)
+ process_init_element (pop_init_level (1));
+ else if (TREE_CODE (constructor_type) == ARRAY_TYPE
+ && tree_int_cst_lt (constructor_max_index, constructor_index))
+ process_init_element (pop_init_level (1));
+ else
+ break;
+ }
+
+ while (1)
+ {
+ if (TREE_CODE (constructor_type) == RECORD_TYPE)
+ {
+ tree fieldtype;
+ enum tree_code fieldcode;
+
+ if (constructor_fields == 0)
+ {
+ pedwarn_init ("excess elements in struct initializer%s",
+ " after `%s'", NULL_PTR);
+ break;
+ }
+
+ fieldtype = TYPE_MAIN_VARIANT (TREE_TYPE (constructor_fields));
+ fieldcode = TREE_CODE (fieldtype);
+
+ /* Accept a string constant to initialize a subarray. */
+ if (value != 0
+ && fieldcode == ARRAY_TYPE
+ && TREE_CODE (TREE_TYPE (fieldtype)) == INTEGER_TYPE
+ && string_flag)
+ value = orig_value;
+ /* 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
+ && TYPE_MAIN_VARIANT (TREE_TYPE (value)) != fieldtype
+ && (fieldcode == RECORD_TYPE || fieldcode == ARRAY_TYPE
+ || fieldcode == UNION_TYPE))
+ {
+ push_init_level (1);
+ continue;
+ }
+
+ if (value)
+ {
+ push_member_name (constructor_fields);
+ output_init_element (value, fieldtype, constructor_fields, 1);
+ RESTORE_SPELLING_DEPTH (constructor_depth);
+ }
+ else
+ /* Do the bookkeeping for an element that was
+ directly output as a constructor. */
+ {
+ /* For a record, keep track of end position of last field. */
+ tree temp = size_binop (PLUS_EXPR,
+ DECL_FIELD_BITPOS (constructor_fields),
+ DECL_SIZE (constructor_fields));
+ TREE_INT_CST_LOW (constructor_bit_index)
+ = TREE_INT_CST_LOW (temp);
+ TREE_INT_CST_HIGH (constructor_bit_index)
+ = TREE_INT_CST_HIGH (temp);
+
+ constructor_unfilled_fields = TREE_CHAIN (constructor_fields);
+ }
+
+ constructor_fields = TREE_CHAIN (constructor_fields);
+ /* Skip any nameless bit fields atthe beginning. */
+ while (constructor_fields != 0 && DECL_BIT_FIELD (constructor_fields)
+ && DECL_NAME (constructor_fields) == 0)
+ constructor_fields = TREE_CHAIN (constructor_fields);
+ break;
+ }
+ if (TREE_CODE (constructor_type) == UNION_TYPE)
+ {
+ tree fieldtype;
+ enum tree_code fieldcode;
+
+ if (constructor_fields == 0)
+ {
+ pedwarn_init ("excess elements in union initializer%s",
+ " after `%s'", NULL_PTR);
+ break;
+ }
+
+ fieldtype = TYPE_MAIN_VARIANT (TREE_TYPE (constructor_fields));
+ fieldcode = TREE_CODE (fieldtype);
+
+ /* Accept a string constant to initialize a subarray. */
+ if (value != 0
+ && fieldcode == ARRAY_TYPE
+ && TREE_CODE (TREE_TYPE (fieldtype)) == INTEGER_TYPE
+ && string_flag)
+ value = orig_value;
+ /* 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
+ && TYPE_MAIN_VARIANT (TREE_TYPE (value)) != fieldtype
+ && (fieldcode == RECORD_TYPE || fieldcode == ARRAY_TYPE
+ || fieldcode == UNION_TYPE))
+ {
+ push_init_level (1);
+ continue;
+ }
+
+ if (value)
+ {
+ push_member_name (constructor_fields);
+ output_init_element (value, fieldtype, constructor_fields, 1);
+ RESTORE_SPELLING_DEPTH (constructor_depth);
+ }
+ else
+ /* Do the bookkeeping for an element that was
+ directly output as a constructor. */
+ {
+ TREE_INT_CST_LOW (constructor_bit_index)
+ = TREE_INT_CST_LOW (DECL_SIZE (constructor_fields));
+ TREE_INT_CST_HIGH (constructor_bit_index)
+ = TREE_INT_CST_HIGH (DECL_SIZE (constructor_fields));
+
+ constructor_unfilled_fields = TREE_CHAIN (constructor_fields);
+ }
+
+ constructor_fields = 0;
+ break;
+ }
+ if (TREE_CODE (constructor_type) == ARRAY_TYPE)
+ {
+ tree elttype = TYPE_MAIN_VARIANT (TREE_TYPE (constructor_type));
+ enum tree_code eltcode = TREE_CODE (elttype);
+
+ /* Accept a string constant to initialize a subarray. */
+ if (value != 0
+ && eltcode == ARRAY_TYPE
+ && TREE_CODE (TREE_TYPE (elttype)) == INTEGER_TYPE
+ && string_flag)
+ value = orig_value;
+ /* 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
+ && TYPE_MAIN_VARIANT (TREE_TYPE (value)) != elttype
+ && (eltcode == RECORD_TYPE || eltcode == ARRAY_TYPE
+ || eltcode == UNION_TYPE))
+ {
+ push_init_level (1);
+ continue;
+ }
+
+ if (constructor_max_index != 0
+ && tree_int_cst_lt (constructor_max_index, constructor_index))
+ {
+ pedwarn_init ("excess elements in array initializer%s",
+ " after `%s'", NULL_PTR);
+ break;
+ }
+
+ /* Now output the actual element.
+ Ordinarily, output once.
+ If there is a range, repeat it till we advance past the range. */
+ do
+ {
+ tree tem;
+
+ if (value)
+ {
+ push_array_bounds (TREE_INT_CST_LOW (constructor_index));
+ output_init_element (value, elttype, constructor_index, 1);
+ RESTORE_SPELLING_DEPTH (constructor_depth);
+ }
+
+ tem = size_binop (PLUS_EXPR, constructor_index,
+ integer_one_node);
+ TREE_INT_CST_LOW (constructor_index)
+ = TREE_INT_CST_LOW (tem);
+ TREE_INT_CST_HIGH (constructor_index)
+ = TREE_INT_CST_HIGH (tem);
+
+ if (!value)
+ /* If we are doing the bookkeeping for an element that was
+ directly output as a constructor,
+ we must update constructor_unfilled_index. */
+ {
+ TREE_INT_CST_LOW (constructor_unfilled_index)
+ = TREE_INT_CST_LOW (constructor_index);
+ TREE_INT_CST_HIGH (constructor_unfilled_index)
+ = TREE_INT_CST_HIGH (constructor_index);
+ }
+ }
+ while (! (constructor_range_end == 0
+ || tree_int_cst_lt (constructor_range_end,
+ constructor_index)));
+
+ break;
+ }
+
+ /* Handle the sole element allowed in a braced initializer
+ for a scalar variable. */
+ if (constructor_fields == 0)
+ {
+ pedwarn_init ("excess elements in scalar initializer%s",
+ " after `%s'", NULL_PTR);
+ break;
+ }
+
+ if (value)
+ output_init_element (value, constructor_type, NULL_TREE, 1);
+ constructor_fields = 0;
+ break;
+ }
+
+ /* 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)
+ clear_momentary ();
}
\f
/* Expand an ASM statement with operands, handling output operands
tree t = convert_for_assignment (valtype, retval, "return",
NULL_TREE, NULL_TREE, 0);
tree res = DECL_RESULT (current_function_decl);
+
+ if (t == error_mark_node)
+ return;
+
t = build (MODIFY_EXPR, TREE_TYPE (res),
res, convert (TREE_TYPE (res), t));
+ TREE_SIDE_EFFECTS (t) = 1;
expand_return (t);
current_function_returns_value = 1;
}