From 19d76e60032abd265bc9a5f6daf7dcf39a03e725 Mon Sep 17 00:00:00 2001 From: Richard Kenner Date: Wed, 6 Oct 1993 19:32:11 -0400 Subject: [PATCH] None. FIxing RCS messup. From-SVN: r5652 --- gcc/c-typeck.c | 673 +++++++++------------------------------------------------ 1 file changed, 102 insertions(+), 571 deletions(-) diff --git a/gcc/c-typeck.c b/gcc/c-typeck.c index 206f5c6..05a4e02 100644 --- a/gcc/c-typeck.c +++ b/gcc/c-typeck.c @@ -960,7 +960,8 @@ default_conversion (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) { @@ -1033,11 +1034,16 @@ default_conversion (exp) return exp; } -/* Look up component name in the structure type definition. */ +/* 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) +lookup_field (type, component, indirect) tree type, component; + tree *indirect; { tree field; @@ -1066,11 +1072,15 @@ lookup_field (type, component) /* Step through all anon unions in linear fashion. */ while (DECL_NAME (field_array[bot]) == NULL_TREE) { - tree anon; + tree anon, junk; + field = field_array[bot++]; - anon = lookup_field (TREE_TYPE (field), component); + anon = lookup_field (TREE_TYPE (field), component, &junk); if (anon != NULL_TREE) - return anon; + { + *indirect = field; + return anon; + } } /* Entire record is only anon unions. */ @@ -1101,9 +1111,13 @@ lookup_field (type, component) { if (DECL_NAME (field) == NULL_TREE) { - tree anon = lookup_field (TREE_TYPE (field), component); + tree junk; + tree anon = lookup_field (TREE_TYPE (field), component, &junk); if (anon != NULL_TREE) - return anon; + { + *indirect = field; + return anon; + } } if (DECL_NAME (field) == component) @@ -1111,6 +1125,7 @@ lookup_field (type, component) } } + *indirect = NULL_TREE; return field; } @@ -1147,13 +1162,15 @@ build_component_ref (datum, component) 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; } - field = lookup_field (type, component); + field = lookup_field (type, component, &indirect); if (!field) { @@ -1166,6 +1183,19 @@ build_component_ref (datum, component) 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)) @@ -1373,541 +1403,6 @@ build_array_ref (array, index) } } -/* 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, "-w" }, - { "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 is - included or not), since it is common to call printf without - including . 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"; - -/* 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 (info->is_scan && format_char == '[') - { - /* Skip over scan set, in case it happens to have '%' in it. */ - if (*format_chars == '^') - ++format_chars; - /* Find closing bracket; if one is hit immediately, then - it's part of the scan set rather than a terminator. */ - if (*format_chars == ']') - ++format_chars; - while (*format_chars && *format_chars != ']') - ++format_chars; - if (*format_chars != ']') - /* The end of the format string was reached. */ - warning ("no closing `]' for `%%[' format"); - } - 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 - && (wanted_type == (TREE_UNSIGNED (wanted_type) - ? unsigned_type : signed_type) (cur_type)))) - { - register char *this; - register char *that; - - this = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (wanted_type))); - that = 0; - if (TREE_CODE (cur_type) != ERROR_MARK - && 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)) - { - if (TREE_CODE (TYPE_NAME (cur_type)) == TYPE_DECL - && DECL_NAME (TYPE_NAME (cur_type)) != 0) - that = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (cur_type))); - else - that = IDENTIFIER_POINTER (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); - } - } - } -} - /* 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. @@ -1919,7 +1414,7 @@ build_function_call (function, params) { register tree fntype, fundecl; 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); @@ -1928,6 +1423,8 @@ build_function_call (function, params) 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). */ @@ -1962,21 +1459,9 @@ build_function_call (function, params) = 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 @@ -3987,8 +3472,8 @@ build_c_cast (type, expr) } else name = ""; - return digest_init (type, build_nt (CONSTRUCTOR, NULL_TREE, - build_tree_list (field, value)), + return digest_init (type, build (CONSTRUCTOR, type, NULL_TREE, + build_tree_list (field, value)), 0, 0); } error ("cast to union type from type not present in union"); @@ -4112,11 +3597,13 @@ build_modify_expr (lhs, modifycode, rhs) /* 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); @@ -4131,6 +3618,8 @@ build_modify_expr (lhs, modifycode, rhs) 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), @@ -4173,6 +3662,8 @@ build_modify_expr (lhs, modifycode, rhs) 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); } @@ -4780,9 +4271,12 @@ push_string (string) /* 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)) : ""; PUSH_SPELLING (SPELLING_MEMBER, string, u.s); } @@ -5519,7 +5013,7 @@ push_init_level (implicit) else { constructor_type = TREE_TYPE (constructor_fields); - push_member_name (IDENTIFIER_POINTER (DECL_NAME (constructor_fields))); + push_member_name (constructor_fields); } } else if (TREE_CODE (constructor_type) == ARRAY_TYPE) @@ -5679,6 +5173,28 @@ pop_init_level (implicit) } 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) @@ -5693,6 +5209,7 @@ pop_init_level (implicit) TREE_CONSTANT (constructor) = 1; if (constructor_constant && constructor_simple) TREE_STATIC (constructor) = 1; + resume_momentary (momentary); } } @@ -5792,6 +5309,20 @@ 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) @@ -5960,7 +5491,7 @@ output_init_element (value, type, field, pending) { if (! constructor_incremental) { - if (TREE_CODE (field) == INTEGER_CST) + if (field && TREE_CODE (field) == INTEGER_CST) field = copy_node (field); constructor_elements = tree_cons (field, digest_init (type, value, 0, 0), @@ -6258,7 +5789,7 @@ process_init_element (value) if (value) { - push_member_name (IDENTIFIER_POINTER (DECL_NAME (constructor_fields))); + push_member_name (constructor_fields); output_init_element (value, fieldtype, constructor_fields, 1); RESTORE_SPELLING_DEPTH (constructor_depth); } @@ -6315,7 +5846,7 @@ process_init_element (value) if (value) { - push_member_name (IDENTIFIER_POINTER (DECL_NAME (constructor_fields))); + push_member_name (constructor_fields); output_init_element (value, fieldtype, constructor_fields, 1); RESTORE_SPELLING_DEPTH (constructor_depth); } -- 2.7.4