X-Git-Url: http://git.sourceforge.jp/view?a=blobdiff_plain;f=gcc%2Fc-typeck.c;h=64f0f07d89ad6e34e657cf79d3fa9c8768c8336a;hb=4206f59199f12699c724219ebf37a58cfeaecbd1;hp=66ec40e3034e5149b8012db12c490d54789b1fa5;hpb=fa6ddf2354750ce657590f07e89e1153c2077b03;p=pf3gnuchains%2Fgcc-fork.git diff --git a/gcc/c-typeck.c b/gcc/c-typeck.c index 66ec40e3034..64f0f07d89a 100644 --- a/gcc/c-typeck.c +++ b/gcc/c-typeck.c @@ -1,23 +1,23 @@ /* Build expressions with type checking for C compiler. Copyright (C) 1987, 1988, 1991, 1992, 1993, 1994, 1995, 1996, 1997, - 1998, 1999, 2000 Free Software Foundation, Inc. + 1998, 1999, 2000, 2001 Free Software Foundation, Inc. -This file is part of GNU CC. +This file is part of GCC. -GNU CC is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2, or (at your option) -any later version. +GCC is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free +Software Foundation; either version 2, or (at your option) any later +version. -GNU CC is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. +GCC is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. You should have received a copy of the GNU General Public License -along with GNU CC; see the file COPYING. If not, write to -the Free Software Foundation, 59 Temple Place - Suite 330, -Boston, MA 02111-1307, USA. */ +along with GCC; see the file COPYING. If not, write to the Free +Software Foundation, 59 Temple Place - Suite 330, Boston, MA +02111-1307, USA. */ /* This file is part of the C front end. @@ -40,8 +40,8 @@ Boston, MA 02111-1307, USA. */ #include "expr.h" #include "toplev.h" #include "intl.h" -#include "defaults.h" #include "ggc.h" +#include "target.h" /* Nonzero if we've already printed a "missing braces around initializer" message within this initializer. */ @@ -54,12 +54,13 @@ static tree qualify_type PARAMS ((tree, tree)); static int comp_target_types PARAMS ((tree, tree)); static int function_types_compatible_p PARAMS ((tree, tree)); static int type_lists_compatible_p PARAMS ((tree, tree)); -static tree decl_constant_value PARAMS ((tree)); -static tree lookup_field PARAMS ((tree, tree, tree *)); +static tree decl_constant_value_for_broken_optimization PARAMS ((tree)); +static tree default_function_array_conversion PARAMS ((tree)); +static tree lookup_field PARAMS ((tree, tree)); static tree convert_arguments PARAMS ((tree, tree, tree, tree)); static tree pointer_int_sum PARAMS ((enum tree_code, tree, tree)); static tree pointer_diff PARAMS ((tree, tree)); -static tree unary_complex_lvalue PARAMS ((enum tree_code, tree)); +static tree unary_complex_lvalue PARAMS ((enum tree_code, tree, int)); static void pedantic_lvalue_warning PARAMS ((enum tree_code)); static tree internal_build_compound_expr PARAMS ((tree, int)); static tree convert_for_assignment PARAMS ((tree, tree, const char *, @@ -74,11 +75,14 @@ static int spelling_length PARAMS ((void)); static char *print_spelling PARAMS ((char *)); static void warning_init PARAMS ((const char *)); static tree digest_init PARAMS ((tree, tree, int, int)); -static void check_init_type_bitfields PARAMS ((tree)); static void output_init_element PARAMS ((tree, tree, tree, int)); static void output_pending_init_elements PARAMS ((int)); +static int set_designator PARAMS ((int)); +static void push_range_stack PARAMS ((tree)); static void add_pending_init PARAMS ((tree, tree)); -static int pending_init_member PARAMS ((tree)); +static void set_nonincremental_init PARAMS ((void)); +static void set_nonincremental_init_from_string PARAMS ((tree)); +static tree find_init_member PARAMS ((tree)); /* Do `exp = require_complete_type (exp);' to make sure exp does not have an incomplete type. (That includes void types.) */ @@ -188,8 +192,8 @@ tree common_type (t1, t2) tree t1, t2; { - register enum tree_code code1; - register enum tree_code code2; + enum tree_code code1; + enum tree_code code2; tree attributes; /* Save time if the two types are the same. */ @@ -203,7 +207,7 @@ common_type (t1, t2) return t1; /* Merge the attributes. */ - attributes = merge_machine_type_attributes (t1, t2); + attributes = (*targetm.merge_type_attributes) (t1, t2); /* Treat an enum type as the unsigned integer type of the same width. */ @@ -351,6 +355,9 @@ common_type (t1, t2) /* If both args specify argument types, we must merge the two lists, argument by argument. */ + pushlevel (0); + declare_parm_level (1); + len = list_length (p1); newargs = 0; @@ -410,6 +417,8 @@ common_type (t1, t2) parm_done: ; } + poplevel (0, 0, 0); + t1 = build_function_type (valtype, newargs); /* ... falls through ... */ } @@ -428,8 +437,8 @@ int comptypes (type1, type2) tree type1, type2; { - register tree t1 = type1; - register tree t2 = type2; + tree t1 = type1; + tree t2 = type2; int attrval, val; /* Suppress errors caused by previously reported errors. */ @@ -475,12 +484,8 @@ comptypes (type1, type2) if (TYPE_MAIN_VARIANT (t1) == TYPE_MAIN_VARIANT (t2)) return 1; -#ifndef COMP_TYPE_ATTRIBUTES -#define COMP_TYPE_ATTRIBUTES(t1,t2) 1 -#endif - /* 1 if no need for warning yet, 2 if warning cause has been seen. */ - if (! (attrval = COMP_TYPE_ATTRIBUTES (t1, t2))) + if (! (attrval = (*targetm.comp_type_attributes) (t1, t2))) return 0; /* 1 if no need for warning yet, 2 if warning cause has been seen. */ @@ -501,6 +506,8 @@ comptypes (type1, type2) { tree d1 = TYPE_DOMAIN (t1); tree d2 = TYPE_DOMAIN (t2); + bool d1_variable, d2_variable; + bool d1_zero, d2_zero; val = 1; /* Target types must match incl. qualifiers. */ @@ -509,14 +516,25 @@ comptypes (type1, type2) return 0; /* Sizes must match unless one is missing or variable. */ - if (d1 == 0 || d2 == 0 || d1 == d2 - || TREE_CODE (TYPE_MIN_VALUE (d1)) != INTEGER_CST - || TREE_CODE (TYPE_MIN_VALUE (d2)) != INTEGER_CST - || TREE_CODE (TYPE_MAX_VALUE (d1)) != INTEGER_CST - || TREE_CODE (TYPE_MAX_VALUE (d2)) != INTEGER_CST) + if (d1 == 0 || d2 == 0 || d1 == d2) break; - if (! tree_int_cst_equal (TYPE_MIN_VALUE (d1), TYPE_MIN_VALUE (d2)) + d1_zero = ! TYPE_MAX_VALUE (d1); + d2_zero = ! TYPE_MAX_VALUE (d2); + + d1_variable = (! d1_zero + && (TREE_CODE (TYPE_MIN_VALUE (d1)) != INTEGER_CST + || TREE_CODE (TYPE_MAX_VALUE (d1)) != INTEGER_CST)); + d2_variable = (! d2_zero + && (TREE_CODE (TYPE_MIN_VALUE (d2)) != INTEGER_CST + || TREE_CODE (TYPE_MAX_VALUE (d2)) != INTEGER_CST)); + + if (d1_variable || d2_variable) + break; + if (d1_zero && d2_zero) + break; + if (d1_zero || d2_zero + || ! tree_int_cst_equal (TYPE_MIN_VALUE (d1), TYPE_MIN_VALUE (d2)) || ! tree_int_cst_equal (TYPE_MAX_VALUE (d1), TYPE_MAX_VALUE (d2))) val = 0; @@ -644,7 +662,8 @@ type_lists_compatible_p (args1, args2) if (simple_type_promotes_to (TREE_VALUE (args1)) != NULL_TREE) return 0; } - else if (! (newval = comptypes (TREE_VALUE (args1), TREE_VALUE (args2)))) + else if (! (newval = comptypes (TYPE_MAIN_VARIANT (TREE_VALUE (args1)), + TYPE_MAIN_VARIANT (TREE_VALUE (args2))))) { /* Allow wait (union {union wait *u; int *i} *) and wait (union wait *) to be compatible. */ @@ -698,33 +717,38 @@ c_sizeof (type) tree type; { enum tree_code code = TREE_CODE (type); + tree size; if (code == FUNCTION_TYPE) { if (pedantic || warn_pointer_arith) pedwarn ("sizeof applied to a function type"); - return size_one_node; + size = size_one_node; } - if (code == VOID_TYPE) + else if (code == VOID_TYPE) { if (pedantic || warn_pointer_arith) pedwarn ("sizeof applied to a void type"); - return size_one_node; + size = size_one_node; } - - if (code == ERROR_MARK) - return size_one_node; - - if (!COMPLETE_TYPE_P (type)) + else if (code == ERROR_MARK) + size = size_one_node; + else if (!COMPLETE_TYPE_P (type)) { error ("sizeof applied to an incomplete type"); - return size_zero_node; + size = size_zero_node; } - - /* Convert in case a char is more than one unit. */ - return size_binop (CEIL_DIV_EXPR, TYPE_SIZE_UNIT (type), - size_int (TYPE_PRECISION (char_type_node) - / BITS_PER_UNIT)); + else + /* Convert in case a char is more than one unit. */ + size = size_binop (CEIL_DIV_EXPR, TYPE_SIZE_UNIT (type), + size_int (TYPE_PRECISION (char_type_node) + / BITS_PER_UNIT)); + + /* SIZE will have an integer type with TYPE_IS_SIZETYPE set. + TYPE_IS_SIZETYPE means that certain things (like overflow) will + never happen. However, this node should really have type + `size_t', which is just a typedef for an ordinary integer type. */ + return fold (build1 (NOP_EXPR, c_size_type_node, size)); } tree @@ -732,17 +756,23 @@ c_sizeof_nowarn (type) tree type; { enum tree_code code = TREE_CODE (type); + tree size; if (code == FUNCTION_TYPE || code == VOID_TYPE || code == ERROR_MARK) - return size_one_node; - - if (!COMPLETE_TYPE_P (type)) - return size_zero_node; - - /* Convert in case a char is more than one unit. */ - return size_binop (CEIL_DIV_EXPR, TYPE_SIZE_UNIT (type), - size_int (TYPE_PRECISION (char_type_node) - / BITS_PER_UNIT)); + size = size_one_node; + else if (!COMPLETE_TYPE_P (type)) + size = size_zero_node; + else + /* Convert in case a char is more than one unit. */ + size = size_binop (CEIL_DIV_EXPR, TYPE_SIZE_UNIT (type), + size_int (TYPE_PRECISION (char_type_node) + / BITS_PER_UNIT)); + + /* SIZE will have an integer type with TYPE_IS_SIZETYPE set. + TYPE_IS_SIZETYPE means that certain things (like overflow) will + never happen. However, this node should really have type + `size_t', which is just a typedef for an ordinary integer type. */ + return fold (build1 (NOP_EXPR, c_size_type_node, size)); } /* Compute the size to increment a pointer by. */ @@ -767,87 +797,18 @@ c_size_in_bytes (type) size_int (TYPE_PRECISION (char_type_node) / BITS_PER_UNIT)); } - -/* Implement the __alignof keyword: Return the minimum required - alignment of TYPE, measured in bytes. */ - -tree -c_alignof (type) - tree type; -{ - enum tree_code code = TREE_CODE (type); - - if (code == FUNCTION_TYPE) - return size_int (FUNCTION_BOUNDARY / BITS_PER_UNIT); - - if (code == VOID_TYPE || code == ERROR_MARK) - return size_one_node; - - if (!COMPLETE_TYPE_P (type)) - { - error ("__alignof__ applied to an incomplete type"); - return size_zero_node; - } - - return size_int (TYPE_ALIGN (type) / BITS_PER_UNIT); -} -/* Implement the __alignof keyword: Return the minimum required - alignment of EXPR, measured in bytes. For VAR_DECL's and - FIELD_DECL's return DECL_ALIGN (which can be set from an - "aligned" __attribute__ specification). */ - -tree -c_alignof_expr (expr) - tree expr; -{ - if (TREE_CODE (expr) == VAR_DECL) - return size_int (DECL_ALIGN (expr) / BITS_PER_UNIT); - - if (TREE_CODE (expr) == COMPONENT_REF - && DECL_C_BIT_FIELD (TREE_OPERAND (expr, 1))) - { - error ("`__alignof' applied to a bit-field"); - return size_one_node; - } - else if (TREE_CODE (expr) == COMPONENT_REF - && TREE_CODE (TREE_OPERAND (expr, 1)) == FIELD_DECL) - return size_int (DECL_ALIGN (TREE_OPERAND (expr, 1)) / BITS_PER_UNIT); - - if (TREE_CODE (expr) == INDIRECT_REF) - { - tree t = TREE_OPERAND (expr, 0); - tree best = t; - int bestalign = TYPE_ALIGN (TREE_TYPE (TREE_TYPE (t))); - - while (TREE_CODE (t) == NOP_EXPR - && TREE_CODE (TREE_TYPE (TREE_OPERAND (t, 0))) == POINTER_TYPE) - { - int thisalign; - - t = TREE_OPERAND (t, 0); - thisalign = TYPE_ALIGN (TREE_TYPE (TREE_TYPE (t))); - if (thisalign > bestalign) - best = t, bestalign = thisalign; - } - return c_alignof (TREE_TYPE (TREE_TYPE (best))); - } - else - return c_alignof (TREE_TYPE (expr)); -} - /* Return either DECL or its known constant value (if it has one). */ -static tree +tree decl_constant_value (decl) tree decl; { if (/* Don't change a variable array bound or initial value to a constant in a place where a variable is invalid. */ current_function_decl != 0 - && ! pedantic && ! TREE_THIS_VOLATILE (decl) - && TREE_READONLY (decl) && ! ITERATOR_P (decl) + && TREE_READONLY (decl) && DECL_INITIAL (decl) != 0 && TREE_CODE (DECL_INITIAL (decl)) != ERROR_MARK /* This is invalid if initial value is not constant. @@ -855,103 +816,74 @@ decl_constant_value (decl) or a variable, then re-evaluating it could give different results. */ && TREE_CONSTANT (DECL_INITIAL (decl)) /* Check for cases where this is sub-optimal, even though valid. */ - && TREE_CODE (DECL_INITIAL (decl)) != CONSTRUCTOR - && DECL_MODE (decl) != BLKmode) + && TREE_CODE (DECL_INITIAL (decl)) != CONSTRUCTOR) return DECL_INITIAL (decl); return decl; } -/* Perform default promotions for C data used in expressions. - Arrays and functions are converted to pointers; - enumeral types or short or char, to int. - In addition, manifest constants symbols are replaced by their values. */ +/* Return either DECL or its known constant value (if it has one), but + return DECL if pedantic or DECL has mode BLKmode. This is for + bug-compatibility with the old behavior of decl_constant_value + (before GCC 3.0); every use of this function is a bug and it should + be removed before GCC 3.1. It is not appropriate to use pedantic + in a way that affects optimization, and BLKmode is probably not the + right test for avoiding misoptimizations either. */ -tree -default_conversion (exp) - tree exp; +static tree +decl_constant_value_for_broken_optimization (decl) + tree decl; { - register tree type = TREE_TYPE (exp); - register enum tree_code code = TREE_CODE (type); + if (pedantic || DECL_MODE (decl) == BLKmode) + return decl; + else + return decl_constant_value (decl); +} - /* Constants can be used directly unless they're not loadable. */ - if (TREE_CODE (exp) == CONST_DECL) - exp = DECL_INITIAL (exp); - /* Replace a nonvolatile const static variable with its value unless - it is an array, in which case we must be sure that taking the - address of the array produces consistent results. */ - else if (optimize && TREE_CODE (exp) == VAR_DECL && code != ARRAY_TYPE) - { - exp = decl_constant_value (exp); - type = TREE_TYPE (exp); - } +/* Perform the default conversion of arrays and functions to pointers. + Return the result of converting EXP. For any other expression, just + return EXP. */ + +static tree +default_function_array_conversion (exp) + tree exp; +{ + tree orig_exp; + tree type = TREE_TYPE (exp); + enum tree_code code = TREE_CODE (type); + int not_lvalue = 0; /* Strip NON_LVALUE_EXPRs and no-op conversions, since we aren't using as an lvalue. Do not use STRIP_NOPS here! It will remove conversions from pointer to integer and cause infinite recursion. */ + orig_exp = exp; while (TREE_CODE (exp) == NON_LVALUE_EXPR || (TREE_CODE (exp) == NOP_EXPR && TREE_TYPE (TREE_OPERAND (exp, 0)) == TREE_TYPE (exp))) - exp = TREE_OPERAND (exp, 0); - - /* Normally convert enums to int, - but convert wide enums to something wider. */ - if (code == ENUMERAL_TYPE) - { - type = type_for_size (MAX (TYPE_PRECISION (type), - TYPE_PRECISION (integer_type_node)), - ((flag_traditional - || (TYPE_PRECISION (type) - >= TYPE_PRECISION (integer_type_node))) - && TREE_UNSIGNED (type))); - - return convert (type, exp); - } - - if (TREE_CODE (exp) == COMPONENT_REF - && DECL_C_BIT_FIELD (TREE_OPERAND (exp, 1)) - /* If it's thinner than an int, promote it like a - C_PROMOTING_INTEGER_TYPE_P, otherwise leave it alone. */ - && 0 > compare_tree_int (DECL_SIZE (TREE_OPERAND (exp, 1)), - TYPE_PRECISION (integer_type_node))) - return convert (flag_traditional && TREE_UNSIGNED (type) - ? unsigned_type_node : integer_type_node, - exp); - - if (C_PROMOTING_INTEGER_TYPE_P (type)) { - /* Traditionally, unsignedness is preserved in default promotions. - Also preserve unsignedness if not really getting any wider. */ - if (TREE_UNSIGNED (type) - && (flag_traditional - || TYPE_PRECISION (type) == TYPE_PRECISION (integer_type_node))) - return convert (unsigned_type_node, exp); - - return convert (integer_type_node, exp); + if (TREE_CODE (exp) == NON_LVALUE_EXPR) + not_lvalue = 1; + exp = TREE_OPERAND (exp, 0); } - if (flag_traditional && !flag_allow_single_precision - && TYPE_MAIN_VARIANT (type) == float_type_node) - return convert (double_type_node, exp); + /* Preserve the original expression code. */ + if (IS_EXPR_CODE_CLASS (TREE_CODE_CLASS (TREE_CODE (exp)))) + C_SET_EXP_ORIGINAL_CODE (exp, C_EXP_ORIGINAL_CODE (orig_exp)); - if (code == VOID_TYPE) - { - error ("void value not ignored as it ought to be"); - return error_mark_node; - } if (code == FUNCTION_TYPE) { return build_unary_op (ADDR_EXPR, exp, 0); } if (code == ARRAY_TYPE) { - register tree adr; + tree adr; tree restype = TREE_TYPE (type); tree ptrtype; int constp = 0; int volatilep = 0; + int lvalue_array_p; if (TREE_CODE_CLASS (TREE_CODE (exp)) == 'r' || DECL_P (exp)) { @@ -977,11 +909,15 @@ default_conversion (exp) TREE_OPERAND (exp, 0), op1); } - if (! lvalue_p (exp) - && ! (TREE_CODE (exp) == CONSTRUCTOR && TREE_STATIC (exp))) + lvalue_array_p = !not_lvalue && lvalue_p (exp); + if (!flag_isoc99 && !lvalue_array_p + && !(TREE_CODE (exp) == CONSTRUCTOR && TREE_STATIC (exp))) { - error ("invalid use of non-lvalue array"); - return error_mark_node; + /* Before C99, non-lvalue arrays do not decay to pointers. + Normally, using such an array would be invalid; but it can + be used correctly inside sizeof or as a statement expression. + Thus, do not give an error here; an error will result later. */ + return exp; } ptrtype = build_pointer_type (restype); @@ -1006,18 +942,113 @@ default_conversion (exp) } return exp; } - -/* 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. */ +/* Perform default promotions for C data used in expressions. + Arrays and functions are converted to pointers; + enumeral types or short or char, to int. + In addition, manifest constants symbols are replaced by their values. */ + +tree +default_conversion (exp) + tree exp; +{ + tree orig_exp; + tree type = TREE_TYPE (exp); + enum tree_code code = TREE_CODE (type); + + if (code == FUNCTION_TYPE || code == ARRAY_TYPE) + return default_function_array_conversion (exp); + + /* Constants can be used directly unless they're not loadable. */ + if (TREE_CODE (exp) == CONST_DECL) + exp = DECL_INITIAL (exp); + + /* Replace a nonvolatile const static variable with its value unless + it is an array, in which case we must be sure that taking the + address of the array produces consistent results. */ + else if (optimize && TREE_CODE (exp) == VAR_DECL && code != ARRAY_TYPE) + { + exp = decl_constant_value_for_broken_optimization (exp); + type = TREE_TYPE (exp); + } + + /* Strip NON_LVALUE_EXPRs and no-op conversions, since we aren't using as + an lvalue. + + Do not use STRIP_NOPS here! It will remove conversions from pointer + to integer and cause infinite recursion. */ + orig_exp = exp; + while (TREE_CODE (exp) == NON_LVALUE_EXPR + || (TREE_CODE (exp) == NOP_EXPR + && TREE_TYPE (TREE_OPERAND (exp, 0)) == TREE_TYPE (exp))) + exp = TREE_OPERAND (exp, 0); + + /* Preserve the original expression code. */ + if (IS_EXPR_CODE_CLASS (TREE_CODE_CLASS (TREE_CODE (exp)))) + C_SET_EXP_ORIGINAL_CODE (exp, C_EXP_ORIGINAL_CODE (orig_exp)); + + /* Normally convert enums to int, + but convert wide enums to something wider. */ + if (code == ENUMERAL_TYPE) + { + type = type_for_size (MAX (TYPE_PRECISION (type), + TYPE_PRECISION (integer_type_node)), + ((flag_traditional + || (TYPE_PRECISION (type) + >= TYPE_PRECISION (integer_type_node))) + && TREE_UNSIGNED (type))); + + return convert (type, exp); + } + + if (TREE_CODE (exp) == COMPONENT_REF + && DECL_C_BIT_FIELD (TREE_OPERAND (exp, 1)) + /* If it's thinner than an int, promote it like a + c_promoting_integer_type_p, otherwise leave it alone. */ + && 0 > compare_tree_int (DECL_SIZE (TREE_OPERAND (exp, 1)), + TYPE_PRECISION (integer_type_node))) + return convert (flag_traditional && TREE_UNSIGNED (type) + ? unsigned_type_node : integer_type_node, + exp); + + if (c_promoting_integer_type_p (type)) + { + /* Traditionally, unsignedness is preserved in default promotions. + Also preserve unsignedness if not really getting any wider. */ + if (TREE_UNSIGNED (type) + && (flag_traditional + || TYPE_PRECISION (type) == TYPE_PRECISION (integer_type_node))) + return convert (unsigned_type_node, exp); + + return convert (integer_type_node, exp); + } + + if (flag_traditional && !flag_allow_single_precision + && TYPE_MAIN_VARIANT (type) == float_type_node) + return convert (double_type_node, exp); + + if (code == VOID_TYPE) + { + error ("void value not ignored as it ought to be"); + return error_mark_node; + } + return exp; +} + +/* Look up COMPONENT in a structure or union DECL. + + If the component name is not found, returns NULL_TREE. Otherwise, + the return value is a TREE_LIST, with each TREE_VALUE a FIELD_DECL + stepping down the chain to the component, which is in the last + TREE_VALUE of the list. Normally the list is of length one, but if + the component is embedded within (nested) anonymous structures or + unions, the list steps down the chain to the component. */ static tree -lookup_field (type, component, indirect) - tree type, component; - tree *indirect; +lookup_field (decl, component) + tree decl, component; { + tree type = TREE_TYPE (decl); tree field; /* If TYPE_LANG_SPECIFIC is set, then it is a sorted array of pointers @@ -1043,18 +1074,15 @@ lookup_field (type, component, indirect) /* Step through all anon unions in linear fashion. */ while (DECL_NAME (field_array[bot]) == NULL_TREE) { - tree anon = 0, junk; - field = field_array[bot++]; if (TREE_CODE (TREE_TYPE (field)) == RECORD_TYPE || TREE_CODE (TREE_TYPE (field)) == UNION_TYPE) - anon = lookup_field (TREE_TYPE (field), component, &junk); - - if (anon != NULL_TREE) { - *indirect = field; - return anon; - } + tree anon = lookup_field (field, component); + + if (anon) + return tree_cons (NULL_TREE, field, anon); + } } /* Entire record is only anon unions. */ @@ -1076,35 +1104,31 @@ lookup_field (type, component, indirect) if (DECL_NAME (field_array[bot]) == component) field = field_array[bot]; else if (DECL_NAME (field) != component) - field = 0; + return NULL_TREE; } else { for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field)) { - if (DECL_NAME (field) == NULL_TREE) + if (DECL_NAME (field) == NULL_TREE + && (TREE_CODE (TREE_TYPE (field)) == RECORD_TYPE + || TREE_CODE (TREE_TYPE (field)) == UNION_TYPE)) { - tree junk; - tree anon = 0; + tree anon = lookup_field (field, component); - if (TREE_CODE (TREE_TYPE (field)) == RECORD_TYPE - || TREE_CODE (TREE_TYPE (field)) == UNION_TYPE) - anon = lookup_field (TREE_TYPE (field), component, &junk); - - if (anon != NULL_TREE) - { - *indirect = field; - return anon; - } + if (anon) + return tree_cons (NULL_TREE, field, anon); } if (DECL_NAME (field) == component) break; } + + if (field == NULL_TREE) + return NULL_TREE; } - *indirect = NULL_TREE; - return field; + return tree_cons (NULL_TREE, field, NULL_TREE); } /* Make an expression to refer to the COMPONENT field of @@ -1114,27 +1138,27 @@ tree build_component_ref (datum, component) tree datum, component; { - register tree type = TREE_TYPE (datum); - register enum tree_code code = TREE_CODE (type); - register tree field = NULL; - register tree ref; + tree type = TREE_TYPE (datum); + enum tree_code code = TREE_CODE (type); + tree field = NULL; + tree ref; - /* If DATUM is a COMPOUND_EXPR or COND_EXPR, move our reference inside it - unless we are not to support things not strictly ANSI. */ + /* If DATUM is a COMPOUND_EXPR, move our reference inside it. + If pedantic ensure that the arguments are not lvalues; otherwise, + if the component is an array, it would wrongly decay to a pointer in + C89 mode. + We cannot do this with a COND_EXPR, because in a conditional expression + the default promotions are applied to both sides, and this would yield + the wrong type of the result; for example, if the components have + type "char". */ switch (TREE_CODE (datum)) { case COMPOUND_EXPR: { tree value = build_component_ref (TREE_OPERAND (datum, 1), component); return build (COMPOUND_EXPR, TREE_TYPE (value), - TREE_OPERAND (datum, 0), value); + TREE_OPERAND (datum, 0), pedantic_non_lvalue (value)); } - case COND_EXPR: - return build_conditional_expr - (TREE_OPERAND (datum, 0), - build_component_ref (TREE_OPERAND (datum, 1), component), - build_component_ref (TREE_OPERAND (datum, 2), component)); - default: break; } @@ -1143,15 +1167,13 @@ build_component_ref (datum, component) if (code == RECORD_TYPE || code == UNION_TYPE) { - tree indirect = 0; - if (!COMPLETE_TYPE_P (type)) { incomplete_type_error (NULL_TREE, type); return error_mark_node; } - field = lookup_field (type, component, &indirect); + field = lookup_field (datum, component); if (!field) { @@ -1160,29 +1182,27 @@ build_component_ref (datum, component) IDENTIFIER_POINTER (component)); return error_mark_node; } - 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) + /* Chain the COMPONENT_REFs if necessary down to the FIELD. + This might be better solved in future the way the C++ front + end does it - by giving the anonymous entities each a + separate name and type, and then have build_component_ref + recursively call itself. We can't do that here. */ + for (; field; field = TREE_CHAIN (field)) { - ref = build (COMPONENT_REF, TREE_TYPE (indirect), datum, indirect); - if (TREE_READONLY (datum) || TREE_READONLY (indirect)) + tree subdatum = TREE_VALUE (field); + + if (TREE_TYPE (subdatum) == error_mark_node) + return error_mark_node; + + ref = build (COMPONENT_REF, TREE_TYPE (subdatum), datum, subdatum); + if (TREE_READONLY (datum) || TREE_READONLY (subdatum)) TREE_READONLY (ref) = 1; - if (TREE_THIS_VOLATILE (datum) || TREE_THIS_VOLATILE (indirect)) + if (TREE_THIS_VOLATILE (datum) || TREE_THIS_VOLATILE (subdatum)) 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) = 1; - if (TREE_THIS_VOLATILE (datum) || TREE_THIS_VOLATILE (field)) - TREE_THIS_VOLATILE (ref) = 1; - return ref; } else if (code != ERROR_MARK) @@ -1201,8 +1221,8 @@ build_indirect_ref (ptr, errorstring) tree ptr; const char *errorstring; { - register tree pointer = default_conversion (ptr); - register tree type = TREE_TYPE (pointer); + tree pointer = default_conversion (ptr); + tree type = TREE_TYPE (pointer); if (TREE_CODE (type) == POINTER_TYPE) { @@ -1214,8 +1234,7 @@ build_indirect_ref (ptr, errorstring) else { tree t = TREE_TYPE (type); - register tree ref = build1 (INDIRECT_REF, - TYPE_MAIN_VARIANT (t), pointer); + tree ref = build1 (INDIRECT_REF, TYPE_MAIN_VARIANT (t), pointer); if (!COMPLETE_OR_VOID_TYPE_P (t) && TREE_CODE (t) != ARRAY_TYPE) { @@ -1315,20 +1334,14 @@ build_array_ref (array, index) return error_mark_node; } - if (pedantic && !lvalue_p (array)) - { - if (DECL_REGISTER (array)) - pedwarn ("ISO C forbids subscripting `register' array"); - else - pedwarn ("ISO C89 forbids subscripting non-lvalue array"); - } - if (pedantic) { tree foo = array; while (TREE_CODE (foo) == COMPONENT_REF) foo = TREE_OPERAND (foo, 0); if (TREE_CODE (foo) == VAR_DECL && DECL_REGISTER (foo)) + pedwarn ("ISO C forbids subscripting `register' array"); + else if (! flag_isoc99 && ! lvalue_p (foo)) pedwarn ("ISO C89 forbids subscripting non-lvalue array"); } @@ -1491,8 +1504,8 @@ tree build_function_call (function, params) tree function, params; { - register tree fntype, fundecl = 0; - register tree coerced_params; + tree fntype, fundecl = 0; + tree coerced_params; tree name = NULL_TREE, assembler_name = NULL_TREE, result; /* Strip NON_LVALUE_EXPRs, etc., since we aren't using as an lvalue. */ @@ -1539,8 +1552,8 @@ build_function_call (function, params) /* Check for errors in format strings. */ - if (warn_format && (name || assembler_name)) - check_function_format (name, assembler_name, coerced_params); + if (warn_format) + check_function_format (NULL, TYPE_ATTRIBUTES (fntype), 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 @@ -1558,8 +1571,9 @@ build_function_call (function, params) result = build (CALL_EXPR, TREE_TYPE (fntype), function, coerced_params, NULL_TREE); - TREE_SIDE_EFFECTS (result) = 1; + result = fold (result); + if (VOID_TYPE_P (TREE_TYPE (result))) return result; return require_complete_type (result); @@ -1587,8 +1601,8 @@ static tree convert_arguments (typelist, values, name, fundecl) tree typelist, values, name, fundecl; { - register tree typetail, valtail; - register tree result = NULL; + tree typetail, valtail; + tree result = NULL; int parmnum; /* Scan the given expressions and types, producing individual @@ -1598,8 +1612,8 @@ convert_arguments (typelist, values, name, fundecl) valtail; valtail = TREE_CHAIN (valtail), parmnum++) { - register tree type = typetail ? TREE_VALUE (typetail) : 0; - register tree val = TREE_VALUE (valtail); + tree type = typetail ? TREE_VALUE (typetail) : 0; + tree val = TREE_VALUE (valtail); if (type == void_type_node) { @@ -1617,9 +1631,7 @@ convert_arguments (typelist, values, name, fundecl) if (TREE_CODE (val) == NON_LVALUE_EXPR) val = TREE_OPERAND (val, 0); - if (TREE_CODE (TREE_TYPE (val)) == ARRAY_TYPE - || TREE_CODE (TREE_TYPE (val)) == FUNCTION_TYPE) - val = default_conversion (val); + val = default_function_array_conversion (val); val = require_complete_type (val); @@ -1637,19 +1649,25 @@ convert_arguments (typelist, values, name, fundecl) { /* Optionally warn about conversions that differ from the default conversions. */ - if (warn_conversion) + if (warn_conversion || warn_traditional) { int formal_prec = TYPE_PRECISION (type); if (INTEGRAL_TYPE_P (type) && TREE_CODE (TREE_TYPE (val)) == REAL_TYPE) warn_for_assignment ("%s as integer rather than floating due to prototype", (char *) 0, name, parmnum + 1); + if (INTEGRAL_TYPE_P (type) + && TREE_CODE (TREE_TYPE (val)) == COMPLEX_TYPE) + warn_for_assignment ("%s as integer rather than complex due to prototype", (char *) 0, name, parmnum + 1); else if (TREE_CODE (type) == COMPLEX_TYPE && TREE_CODE (TREE_TYPE (val)) == REAL_TYPE) warn_for_assignment ("%s as complex rather than floating due to prototype", (char *) 0, name, parmnum + 1); else if (TREE_CODE (type) == REAL_TYPE && INTEGRAL_TYPE_P (TREE_TYPE (val))) warn_for_assignment ("%s as floating rather than integer due to prototype", (char *) 0, name, parmnum + 1); + else if (TREE_CODE (type) == COMPLEX_TYPE + && INTEGRAL_TYPE_P (TREE_TYPE (val))) + warn_for_assignment ("%s as complex rather than integer due to prototype", (char *) 0, name, parmnum + 1); else if (TREE_CODE (type) == REAL_TYPE && TREE_CODE (TREE_TYPE (val)) == COMPLEX_TYPE) warn_for_assignment ("%s as floating rather than complex due to prototype", (char *) 0, name, parmnum + 1); @@ -1664,15 +1682,18 @@ convert_arguments (typelist, values, name, fundecl) if (formal_prec == TYPE_PRECISION (float_type_node)) warn_for_assignment ("%s as `float' rather than `double' due to prototype", (char *) 0, name, parmnum + 1); } - /* Detect integer changing in width or signedness. */ - else if (INTEGRAL_TYPE_P (type) + /* Detect integer changing in width or signedness. + These warnings are only activated with + -Wconversion, not with -Wtraditional. */ + else if (warn_conversion && INTEGRAL_TYPE_P (type) && INTEGRAL_TYPE_P (TREE_TYPE (val))) { tree would_have_been = default_conversion (val); tree type1 = TREE_TYPE (would_have_been); if (TREE_CODE (type) == ENUMERAL_TYPE - && type == TREE_TYPE (val)) + && (TYPE_MAIN_VARIANT (type) + == TYPE_MAIN_VARIANT (TREE_TYPE (val)))) /* No warning if function asks for enum and the actual arg is that enum type. */ ; @@ -1722,8 +1743,7 @@ convert_arguments (typelist, values, name, fundecl) fundecl, name, parmnum + 1); if (PROMOTE_PROTOTYPES - && (TREE_CODE (type) == INTEGER_TYPE - || TREE_CODE (type) == ENUMERAL_TYPE) + && INTEGRAL_TYPE_P (type) && (TYPE_PRECISION (type) < TYPE_PRECISION (integer_type_node))) parmval = default_conversion (parmval); } @@ -1773,11 +1793,9 @@ parser_build_binary_op (code, arg1, arg2) enum tree_code code1 = ERROR_MARK; enum tree_code code2 = ERROR_MARK; - if (class1 == 'e' || class1 == '1' - || class1 == '2' || class1 == '<') + if (IS_EXPR_CODE_CLASS (class1)) code1 = C_EXP_ORIGINAL_CODE (arg1); - if (class2 == 'e' || class2 == '1' - || class2 == '2' || class2 == '<') + if (IS_EXPR_CODE_CLASS (class2)) code2 = C_EXP_ORIGINAL_CODE (arg2); /* Check for cases such as x+y<"; PUSH_SPELLING (SPELLING_MEMBER, string, u.s); } @@ -4511,8 +4598,8 @@ push_array_bounds (bounds) static int spelling_length () { - register int size = 0; - register struct spelling *p; + int size = 0; + struct spelling *p; for (p = spelling_base; p < spelling; p++) { @@ -4529,10 +4616,10 @@ spelling_length () static char * print_spelling (buffer) - register char *buffer; + char *buffer; { - register char *d = buffer; - register struct spelling *p; + char *d = buffer; + struct spelling *p; for (p = spelling_base; p < spelling; p++) if (p->kind == SPELLING_BOUNDS) @@ -4542,7 +4629,7 @@ print_spelling (buffer) } else { - register const char *s; + const char *s; if (p->kind == SPELLING_MEMBER) *d++ = '.'; for (s = p->u.s; (*d = *s++); d++) @@ -4626,6 +4713,8 @@ digest_init (type, init, require_constant, constructor_constant) if (TREE_CODE (init) == NON_LVALUE_EXPR) inside_init = TREE_OPERAND (init, 0); + inside_init = fold (inside_init); + /* Initialization of an array of chars from a string constant optionally enclosed in braces. */ @@ -4660,6 +4749,7 @@ digest_init (type, init, require_constant, constructor_constant) TREE_TYPE (inside_init) = type; if (TYPE_DOMAIN (type) != 0 + && TYPE_SIZE (type) != 0 && TREE_CODE (TYPE_SIZE (type)) == INTEGER_CST /* Subtract 1 (or sizeof (wchar_t)) because it's ok to ignore the terminating null char @@ -4691,10 +4781,8 @@ digest_init (type, init, require_constant, constructor_constant) && comptypes (TREE_TYPE (TREE_TYPE (inside_init)), TREE_TYPE (type))))) { - if (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); + if (code == POINTER_TYPE) + inside_init = default_function_array_conversion (inside_init); else if (code == ARRAY_TYPE && TREE_CODE (inside_init) != STRING_CST && TREE_CODE (inside_init) != CONSTRUCTOR) { @@ -4703,7 +4791,7 @@ digest_init (type, init, require_constant, constructor_constant) } if (optimize && TREE_CODE (inside_init) == VAR_DECL) - inside_init = decl_constant_value (inside_init); + inside_init = decl_constant_value_for_broken_optimization (inside_init); /* Compound expressions can only occur here if -pedantic or -pedantic-errors is specified. In the later case, we always want @@ -4721,17 +4809,21 @@ digest_init (type, init, require_constant, constructor_constant) if (flag_pedantic_errors) inside_init = error_mark_node; } - else if (require_constant && ! TREE_CONSTANT (inside_init)) + else if (require_constant + && (!TREE_CONSTANT (inside_init) + /* This test catches things like `7 / 0' which + result in an expression for which TREE_CONSTANT + is true, but which is not actually something + that is a legal constant. We really should not + be using this function, because it is a part of + the back-end. Instead, the expression should + already have been turned into ERROR_MARK_NODE. */ + || !initializer_constant_valid_p (inside_init, + TREE_TYPE (inside_init)))) { error_init ("initializer element is not constant"); inside_init = error_mark_node; } - else if (require_constant - && initializer_constant_valid_p (inside_init, TREE_TYPE (inside_init)) == 0) - { - error_init ("initializer element is not computable at load time"); - inside_init = error_mark_node; - } return inside_init; } @@ -4739,7 +4831,7 @@ digest_init (type, init, require_constant, constructor_constant) /* Handle scalar types, including conversions. */ if (code == INTEGER_TYPE || code == REAL_TYPE || code == POINTER_TYPE - || code == ENUMERAL_TYPE || code == COMPLEX_TYPE) + || code == ENUMERAL_TYPE || code == BOOLEAN_TYPE || code == COMPLEX_TYPE) { /* Note that convert_for_assignment calls default_conversion for arrays and functions. We must not call it in the @@ -4827,11 +4919,6 @@ static tree constructor_fields; at which to store the next element we get. */ static tree constructor_index; -/* For an ARRAY_TYPE, this is the end index of the range - to initialize with the next element, or NULL in the ordinary case - where the element is used just once. */ -static tree constructor_range_end; - /* For an ARRAY_TYPE, this is the maximum index. */ static tree constructor_max_index; @@ -4851,6 +4938,10 @@ static tree constructor_bit_index; most recent first). */ static tree constructor_elements; +/* 1 if constructor should be incrementally stored into a constructor chain, + 0 if all the elements should be kept in AVL tree. */ +static int constructor_incremental; + /* 1 if so far this constructor's elements are all compile-time constants. */ static int constructor_constant; @@ -4891,54 +4982,77 @@ int constructor_no_implicit = 0; /* 0 for C; 1 for some other languages. */ static int require_constant_value; static int require_constant_elements; -/* 1 if it is ok to output this constructor as we read it. - 0 means must accumulate a CONSTRUCTOR expression. */ -static int constructor_incremental; - /* 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; /* start_init saves the ASMSPEC arg here for really_start_incremental_init. */ -static char *constructor_asmspec; +static const char *constructor_asmspec; /* Nonzero if this is an initializer for a top-level decl. */ static int constructor_top_level; +/* Nonzero if there were any member designators in this initializer. */ +static int constructor_designated; + +/* Nesting depth of designator list. */ +static int designator_depth; + +/* Nonzero if there were diagnosed errors in this designator list. */ +static int designator_errorneous; + /* 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. */ +struct constructor_range_stack; + 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; struct init_node *pending_elts; + int offset; int depth; /* If nonzero, this value should replace the entire constructor at this level. */ tree replacement_value; + struct constructor_range_stack *range_stack; char constant; char simple; char implicit; - char incremental; char erroneous; char outer; + char incremental; + char designated; }; struct constructor_stack *constructor_stack; +/* This stack represents designators from some range designator up to + the last designator in the list. */ + +struct constructor_range_stack +{ + struct constructor_range_stack *next, *prev; + struct constructor_stack *stack; + tree range_start; + tree index; + tree range_end; + tree fields; +}; + +struct constructor_range_stack *constructor_range_stack; + /* 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) { ... } ... }. */ @@ -4947,14 +5061,14 @@ struct initializer_stack { struct initializer_stack *next; tree decl; - char *asmspec; + const char *asmspec; struct constructor_stack *constructor_stack; + struct constructor_range_stack *constructor_range_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; @@ -4973,17 +5087,17 @@ start_init (decl, asmspec_tree, top_level) const char *locus; struct initializer_stack *p = (struct initializer_stack *) xmalloc (sizeof (struct initializer_stack)); - char *asmspec = 0; + const 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->constructor_range_stack = constructor_range_stack; p->elements = constructor_elements; p->spelling = spelling; p->spelling_base = spelling_base; @@ -4994,16 +5108,16 @@ start_init (decl, asmspec_tree, top_level) initializer_stack = p; constructor_decl = decl; - constructor_incremental = top_level; constructor_asmspec = asmspec; constructor_subconstants_deferred = 0; + constructor_designated = 0; constructor_top_level = top_level; if (decl != 0) { require_constant_value = TREE_STATIC (decl); require_constant_elements - = ((TREE_STATIC (decl) || pedantic) + = ((TREE_STATIC (decl) || (pedantic && !flag_isoc99)) /* For a scalar, you can always use any value to initialize, even within braces. */ && (TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE @@ -5011,7 +5125,6 @@ start_init (decl, asmspec_tree, top_level) || 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 { @@ -5021,6 +5134,7 @@ start_init (decl, asmspec_tree, top_level) } constructor_stack = 0; + constructor_range_stack = 0; missing_braces_mentioned = 0; @@ -5051,13 +5165,16 @@ finish_init () free (q); } + if (constructor_range_stack) + abort (); + /* 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_range_stack = p->constructor_range_stack; constructor_elements = p->elements; spelling = p->spelling; spelling_base = p->spelling_base; @@ -5085,15 +5202,9 @@ really_start_incremental_init (type) 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; @@ -5106,8 +5217,10 @@ really_start_incremental_init (type) p->depth = constructor_depth; p->replacement_value = 0; p->implicit = 0; - p->incremental = constructor_incremental; + p->range_stack = 0; p->outer = 0; + p->incremental = constructor_incremental; + p->designated = constructor_designated; p->next = 0; constructor_stack = p; @@ -5117,6 +5230,10 @@ really_start_incremental_init (type) constructor_elements = 0; constructor_pending_elts = 0; constructor_type = type; + constructor_incremental = 1; + constructor_designated = 0; + designator_depth = 0; + designator_errorneous = 0; if (TREE_CODE (constructor_type) == RECORD_TYPE || TREE_CODE (constructor_type) == UNION_TYPE) @@ -5132,11 +5249,16 @@ really_start_incremental_init (type) } 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)); + + /* Detect non-empty initializations of zero-length arrays. */ + if (constructor_max_index == NULL_TREE + && TYPE_SIZE (constructor_type)) + constructor_max_index = build_int_2 (-1, -1); + constructor_index = convert (bitsizetype, TYPE_MIN_VALUE (TYPE_DOMAIN (constructor_type))); @@ -5152,28 +5274,19 @@ really_start_incremental_init (type) constructor_fields = constructor_type; constructor_unfilled_fields = constructor_type; } - - if (constructor_incremental) - { - make_decl_rtl (constructor_decl, constructor_asmspec, - constructor_top_level); - assemble_variable (constructor_decl, constructor_top_level, 0, 1); - - defer_addressed_constants (); - constructor_subconstants_deferred = 1; - } } /* 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. */ + IMPLICIT is 1 (or 2 if the push is because of designator list). */ void push_init_level (implicit) int implicit; { struct constructor_stack *p; + tree value = NULL_TREE; /* If we've exhausted any levels that didn't have braces, pop them now. */ @@ -5190,35 +5303,22 @@ push_init_level (implicit) break; } - /* Structure elements may require alignment. Do this now if necessary - for the subaggregate, and if it comes next in sequence. Don't do - this for subaggregates that will go on the pending list. */ - if (constructor_incremental && constructor_type != 0 - && TREE_CODE (constructor_type) == RECORD_TYPE && constructor_fields - && constructor_fields == constructor_unfilled_fields) - { - /* Advance to offset of this element. */ - if (! tree_int_cst_equal (constructor_bit_index, - bit_position (constructor_fields))) - assemble_zeros - (tree_low_cst - (size_binop (TRUNC_DIV_EXPR, - size_binop (MINUS_EXPR, - bit_position (constructor_fields), - constructor_bit_index), - bitsize_unit_node), - 1)); - - /* Indicate that we have now filled the structure up to the current - field. */ - constructor_unfilled_fields = constructor_fields; + /* Unless this is an explicit brace, we need to preserve previous + content if any. */ + if (implicit) + { + if ((TREE_CODE (constructor_type) == RECORD_TYPE + || TREE_CODE (constructor_type) == UNION_TYPE) + && constructor_fields) + value = find_init_member (constructor_fields); + else if (TREE_CODE (constructor_type) == ARRAY_TYPE) + value = find_init_member (constructor_index); } 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; @@ -5231,16 +5331,27 @@ push_init_level (implicit) p->depth = constructor_depth; p->replacement_value = 0; p->implicit = implicit; - p->incremental = constructor_incremental; p->outer = 0; + p->incremental = constructor_incremental; + p->designated = constructor_designated; p->next = constructor_stack; + p->range_stack = 0; constructor_stack = p; constructor_constant = 1; constructor_simple = 1; constructor_depth = SPELLING_DEPTH (); constructor_elements = 0; + constructor_incremental = 1; + constructor_designated = 0; constructor_pending_elts = 0; + if (!implicit) + { + p->range_stack = constructor_range_stack; + constructor_range_stack = 0; + designator_depth = 0; + designator_errorneous = 0; + } /* Don't die if an entire brace-pair level is superfluous in the containing level. */ @@ -5257,8 +5368,6 @@ push_init_level (implicit) constructor_type = TREE_TYPE (constructor_fields); push_member_name (constructor_fields); constructor_depth++; - if (constructor_fields != constructor_unfilled_fields) - constructor_incremental = 0; } } else if (TREE_CODE (constructor_type) == ARRAY_TYPE) @@ -5266,9 +5375,6 @@ push_init_level (implicit) constructor_type = TREE_TYPE (constructor_type); push_array_bounds (tree_low_cst (constructor_index, 0)); constructor_depth++; - if (! tree_int_cst_equal (constructor_index, constructor_unfilled_index) - || constructor_range_end != 0) - constructor_incremental = 0; } if (constructor_type == 0) @@ -5279,10 +5385,18 @@ push_init_level (implicit) return; } - /* Turn off constructor_incremental if type is a struct with bitfields. */ - check_init_type_bitfields (constructor_type); + if (value && TREE_CODE (value) == CONSTRUCTOR) + { + constructor_constant = TREE_CONSTANT (value); + constructor_simple = TREE_STATIC (value); + constructor_elements = TREE_OPERAND (value, 1); + if (constructor_elements + && (TREE_CODE (constructor_type) == RECORD_TYPE + || TREE_CODE (constructor_type) == ARRAY_TYPE)) + set_nonincremental_init (); + } - if (implicit && warn_missing_braces && !missing_braces_mentioned) + if (implicit == 1 && warn_missing_braces && !missing_braces_mentioned) { missing_braces_mentioned = 1; warning_init ("missing braces around initializer"); @@ -5302,20 +5416,31 @@ push_init_level (implicit) } 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)); + + /* Detect non-empty initializations of zero-length arrays. */ + if (constructor_max_index == NULL_TREE + && TYPE_SIZE (constructor_type)) + constructor_max_index = build_int_2 (-1, -1); + constructor_index = convert (bitsizetype, - TYPE_MIN_VALUE - (TYPE_DOMAIN (constructor_type))); + TYPE_MIN_VALUE (TYPE_DOMAIN (constructor_type))); } else constructor_index = bitsize_zero_node; constructor_unfilled_index = constructor_index; + if (value && TREE_CODE (value) == STRING_CST) + { + /* We need to split the char/wchar array into individual + characters, so that we don't have to special case it + everywhere. */ + set_nonincremental_init_from_string (value); + } } else { @@ -5325,45 +5450,6 @@ push_init_level (implicit) } } -/* 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_C_BIT_FIELD (tail)) - { - constructor_incremental = 0; - break; - } - - check_init_type_bitfields (TREE_TYPE (tail)); - } - } - - else if (TREE_CODE (type) == UNION_TYPE) - { - tree tail = TYPE_FIELDS (type); - if (tail && DECL_C_BIT_FIELD (tail)) - /* We also use the nonincremental algorithm for initiliazation - of unions whose first member is a bitfield, becuase the - incremental algorithm has no code for dealing with - bitfields. */ - constructor_incremental = 0; - } - - else if (TREE_CODE (type) == ARRAY_TYPE) - check_init_type_bitfields (TREE_TYPE (type)); -} - /* 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 @@ -5377,7 +5463,6 @@ pop_init_level (implicit) int implicit; { struct constructor_stack *p; - HOST_WIDE_INT size = 0; tree constructor = 0; if (implicit == 0) @@ -5386,12 +5471,42 @@ pop_init_level (implicit) pop any inner levels that didn't have explicit braces. */ while (constructor_stack->implicit) process_init_element (pop_init_level (1)); + + if (constructor_range_stack) + abort (); } p = constructor_stack; - if (constructor_type != 0) - size = int_size_in_bytes (constructor_type); + /* Error for initializing a flexible array member, or a zero-length + array member in an inappropriate context. */ + if (constructor_type && constructor_fields + && TREE_CODE (constructor_type) == ARRAY_TYPE + && TYPE_DOMAIN (constructor_type) + && ! TYPE_MAX_VALUE (TYPE_DOMAIN (constructor_type))) + { + /* Silently discard empty initializations. The parser will + already have pedwarned for empty brackets. */ + if (integer_zerop (constructor_unfilled_index)) + constructor_type = NULL_TREE; + else if (! TYPE_SIZE (constructor_type)) + { + if (constructor_depth > 2) + error_init ("initialization of flexible array member in a nested context"); + else if (pedantic) + pedwarn_init ("initialization of a flexible array member"); + + /* We have already issued an error message for the existence + of a flexible array member not at the end of the structure. + Discard the initializer so that we do not abort later. */ + if (TREE_CHAIN (constructor_fields) != NULL_TREE) + constructor_type = NULL_TREE; + } + else + /* Zero-length arrays are no longer special, so we should no longer + get here. */ + abort(); + } /* Warn when some struct elements are implicitly initialized to zero. */ if (extra_warnings @@ -5399,71 +5514,43 @@ pop_init_level (implicit) && TREE_CODE (constructor_type) == RECORD_TYPE && constructor_unfilled_fields) { - push_member_name (constructor_unfilled_fields); - warning_init ("missing initializer"); - RESTORE_SPELLING_DEPTH (constructor_depth); + /* Do not warn for flexible array members or zero-length arrays. */ + while (constructor_unfilled_fields + && (! DECL_SIZE (constructor_unfilled_fields) + || integer_zerop (DECL_SIZE (constructor_unfilled_fields)))) + constructor_unfilled_fields = TREE_CHAIN (constructor_unfilled_fields); + + /* Do not warn if this level of the initializer uses member + designators; it is likely to be deliberate. */ + if (constructor_unfilled_fields && !constructor_designated) + { + push_member_name (constructor_unfilled_fields); + warning_init ("missing initializer"); + RESTORE_SPELLING_DEPTH (constructor_depth); + } } /* Now output all pending elements. */ + constructor_incremental = 1; 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"); -#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, - require_constant_value, - require_constant_elements); - - /* If initializing an array of unknown size, - determine the size now. */ - if (TREE_CODE (constructor_type) == ARRAY_TYPE - && TYPE_DOMAIN (constructor_type) == 0) - { - /* We shouldn't have an incomplete array type within - some other type. */ - if (constructor_stack->next) - abort (); - - if (complete_array_type (constructor_type, constructor, 0)) - abort (); - - size = int_size_in_bytes (constructor_type); - } - - output_constant (constructor, size); - } - } + /* If this closes a superfluous brace pair, + just pass out the element between them. */ + constructor = p->replacement_value; 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) + && TREE_CODE (constructor_type) != ARRAY_TYPE) { /* A nonincremental scalar initializer--just return the element, after verifying there is just one. */ if (constructor_elements == 0) { - error_init ("empty scalar initializer"); + if (!constructor_erroneous) + error_init ("empty scalar initializer"); constructor = error_mark_node; } else if (TREE_CHAIN (constructor_elements) != 0) @@ -5474,7 +5561,7 @@ pop_init_level (implicit) else constructor = TREE_VALUE (constructor_elements); } - else if (! constructor_incremental) + else { if (constructor_erroneous) constructor = error_mark_node; @@ -5488,62 +5575,10 @@ pop_init_level (implicit) TREE_STATIC (constructor) = 1; } } - else - { - tree filled; - - 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, - bitsize_unit_node); - - 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 - = copy_node (size_diffop (constructor_unfilled_index, - bitsize_one_node)); - - TYPE_DOMAIN (constructor_type) = build_index_type (maxindex); - TREE_TYPE (maxindex) = TYPE_DOMAIN (constructor_type); - - /* TYPE_MAX_VALUE is always one less than the number of elements - in the array, because we start counting at zero. Therefore, - warn only if the value is less than zero. */ - if (pedantic - && (tree_int_cst_sgn - (TYPE_MAX_VALUE (TYPE_DOMAIN (constructor_type))) - < 0)) - error_with_decl (constructor_decl, - "zero or negative array size `%s'"); - - layout_type (constructor_type); - size = int_size_in_bytes (constructor_type); - } - - filled - = size_binop (MULT_EXPR, constructor_unfilled_index, - convert (bitsizetype, - TYPE_SIZE_UNIT - (TREE_TYPE (constructor_type)))); - } - else - filled = 0; - - if (filled != 0) - assemble_zeros (size - tree_low_cst (filled, 1)); - } - 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; @@ -5552,9 +5587,12 @@ pop_init_level (implicit) constructor_constant = p->constant; constructor_simple = p->simple; constructor_erroneous = p->erroneous; + constructor_incremental = p->incremental; + constructor_designated = p->designated; constructor_pending_elts = p->pending_elts; constructor_depth = p->depth; - constructor_incremental = p->incremental; + if (!p->implicit) + constructor_range_stack = p->range_stack; RESTORE_SPELLING_DEPTH (constructor_depth); constructor_stack = p->next; @@ -5569,6 +5607,99 @@ pop_init_level (implicit) return constructor; } +/* Common handling for both array range and field name designators. + ARRAY argument is non-zero for array ranges. Returns zero for success. */ + +static int +set_designator (array) + int array; +{ + tree subtype; + enum tree_code subcode; + + /* Don't die if an entire brace-pair level is superfluous + in the containing level. */ + if (constructor_type == 0) + return 1; + + /* If there were errors in this designator list already, bail out silently. */ + if (designator_errorneous) + return 1; + + if (!designator_depth) + { + if (constructor_range_stack) + abort (); + + /* Designator list starts at the level of closest explicit + braces. */ + while (constructor_stack->implicit) + process_init_element (pop_init_level (1)); + constructor_designated = 1; + return 0; + } + + if (constructor_no_implicit) + { + error_init ("initialization designators may not nest"); + return 1; + } + + if (TREE_CODE (constructor_type) == RECORD_TYPE + || TREE_CODE (constructor_type) == UNION_TYPE) + { + subtype = TREE_TYPE (constructor_fields); + if (subtype != error_mark_node) + subtype = TYPE_MAIN_VARIANT (subtype); + } + else if (TREE_CODE (constructor_type) == ARRAY_TYPE) + { + subtype = TYPE_MAIN_VARIANT (TREE_TYPE (constructor_type)); + } + else + abort (); + + subcode = TREE_CODE (subtype); + if (array && subcode != ARRAY_TYPE) + { + error_init ("array index in non-array initializer"); + return 1; + } + else if (!array && subcode != RECORD_TYPE && subcode != UNION_TYPE) + { + error_init ("field name not in record or union initializer"); + return 1; + } + + constructor_designated = 1; + push_init_level (2); + return 0; +} + +/* If there are range designators in designator list, push a new designator + to constructor_range_stack. RANGE_END is end of such stack range or + NULL_TREE if there is no range designator at this level. */ + +static void +push_range_stack (range_end) + tree range_end; +{ + struct constructor_range_stack *p; + + p = (struct constructor_range_stack *) + ggc_alloc (sizeof (struct constructor_range_stack)); + p->prev = constructor_range_stack; + p->next = 0; + p->fields = constructor_fields; + p->range_start = constructor_index; + p->index = constructor_index; + p->stack = constructor_stack; + p->range_end = range_end; + if (constructor_range_stack) + constructor_range_stack->next = p; + constructor_range_stack = p; +} + /* 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. */ @@ -5577,6 +5708,11 @@ void set_init_index (first, last) tree first, last; { + if (set_designator (1)) + return; + + designator_errorneous = 1; + while ((TREE_CODE (first) == NOP_EXPR || TREE_CODE (first) == CONVERT_EXPR || TREE_CODE (first) == NON_LVALUE_EXPR) @@ -5596,23 +5732,40 @@ set_init_index (first, last) error_init ("nonconstant array index in initializer"); else if (last != 0 && TREE_CODE (last) != INTEGER_CST) error_init ("nonconstant array index in initializer"); - else if (! constructor_unfilled_index) + else if (TREE_CODE (constructor_type) != ARRAY_TYPE) error_init ("array index in non-array initializer"); - else if (tree_int_cst_lt (first, constructor_unfilled_index)) - error_init ("duplicate array index in initializer"); + else if (constructor_max_index + && tree_int_cst_lt (constructor_max_index, first)) + error_init ("array index in initializer exceeds array bounds"); else { constructor_index = convert (bitsizetype, first); - if (last != 0 && tree_int_cst_lt (last, first)) - error_init ("empty index range in initializer"); - else + if (last) { - if (pedantic) - pedwarn ("ISO C89 forbids specifying element to initialize"); - - constructor_range_end = last ? convert (bitsizetype, last) : 0; + if (tree_int_cst_equal (first, last)) + last = 0; + else if (tree_int_cst_lt (last, first)) + { + error_init ("empty index range in initializer"); + last = 0; + } + else + { + last = convert (bitsizetype, last); + if (constructor_max_index != 0 + && tree_int_cst_lt (constructor_max_index, last)) + { + error_init ("array index range in initializer exceeds array bounds"); + last = 0; + } + } } + + designator_depth++; + designator_errorneous = 0; + if (constructor_range_stack || last) + push_range_stack (last); } } @@ -5623,18 +5776,22 @@ set_init_label (fieldname) tree fieldname; { tree tail; - int passed = 0; - /* Don't die if an entire brace-pair level is superfluous - in the containing level. */ - if (constructor_type == 0) + if (set_designator (0)) return; + designator_errorneous = 1; + + if (TREE_CODE (constructor_type) != RECORD_TYPE + && TREE_CODE (constructor_type) != UNION_TYPE) + { + error_init ("field name not in record or union initializer"); + return; + } + for (tail = TYPE_FIELDS (constructor_type); tail; tail = TREE_CHAIN (tail)) { - if (tail == constructor_unfilled_fields) - passed = 1; if (DECL_NAME (tail) == fieldname) break; } @@ -5642,19 +5799,18 @@ set_init_label (fieldname) 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 ("ISO C89 forbids specifying structure member to initialize"); + designator_depth++; + designator_errorneous = 0; + if (constructor_range_stack) + push_range_stack (NULL_TREE); } } /* Add a new initializer to the tree of pending initializers. PURPOSE - indentifies the initializer, either array index or field in a structure. + identifies the initializer, either array index or field in a structure. VALUE is the value of that index or field. */ static void @@ -5673,24 +5829,36 @@ add_pending_init (purpose, value) p = *q; if (tree_int_cst_lt (purpose, p->purpose)) q = &p->left; - else if (p->purpose != purpose) + else if (tree_int_cst_lt (p->purpose, purpose)) q = &p->right; else - abort (); + { + if (TREE_SIDE_EFFECTS (p->value)) + warning_init ("initialized field with side-effects overwritten"); + p->value = value; + return; + } } } else { + tree bitpos; + + bitpos = bit_position (purpose); while (*q != NULL) { p = *q; - if (tree_int_cst_lt (bit_position (purpose), - bit_position (p->purpose))) + if (tree_int_cst_lt (bitpos, bit_position (p->purpose))) q = &p->left; else if (p->purpose != purpose) q = &p->right; else - abort (); + { + if (TREE_SIDE_EFFECTS (p->value)) + warning_init ("initialized field with side-effects overwritten"); + p->value = value; + return; + } } } @@ -5716,7 +5884,7 @@ add_pending_init (purpose, value) { if (r->balance < 0) { - /* L rotation. */ + /* L rotation. */ p->left = r->right; if (p->left) p->left->parent = p; @@ -5740,7 +5908,7 @@ add_pending_init (purpose, value) } else { - /* LR rotation. */ + /* LR rotation. */ struct init_node *t = r->right; r->right = t->left; @@ -5789,7 +5957,7 @@ add_pending_init (purpose, value) { if (r->balance > 0) { - /* R rotation. */ + /* R rotation. */ p->right = r->left; if (p->right) p->right->parent = p; @@ -5848,7 +6016,7 @@ add_pending_init (purpose, value) } else { - /* p->balance == -1; growth of right side balances the node. */ + /* p->balance == -1; growth of right side balances the node. */ p->balance = 0; break; } @@ -5859,41 +6027,178 @@ add_pending_init (purpose, value) } } -/* Return nonzero if FIELD is equal to the index of a pending initializer. */ +/* Build AVL tree from a sorted chain. */ -static int -pending_init_member (field) +static void +set_nonincremental_init () +{ + tree chain; + + if (TREE_CODE (constructor_type) != RECORD_TYPE + && TREE_CODE (constructor_type) != ARRAY_TYPE) + return; + + for (chain = constructor_elements; chain; chain = TREE_CHAIN (chain)) + add_pending_init (TREE_PURPOSE (chain), TREE_VALUE (chain)); + constructor_elements = 0; + if (TREE_CODE (constructor_type) == RECORD_TYPE) + { + constructor_unfilled_fields = TYPE_FIELDS (constructor_type); + /* Skip any nameless bit fields at the beginning. */ + while (constructor_unfilled_fields != 0 + && DECL_C_BIT_FIELD (constructor_unfilled_fields) + && DECL_NAME (constructor_unfilled_fields) == 0) + constructor_unfilled_fields = TREE_CHAIN (constructor_unfilled_fields); + + } + else if (TREE_CODE (constructor_type) == ARRAY_TYPE) + { + if (TYPE_DOMAIN (constructor_type)) + constructor_unfilled_index + = convert (bitsizetype, + TYPE_MIN_VALUE (TYPE_DOMAIN (constructor_type))); + else + constructor_unfilled_index = bitsize_zero_node; + } + constructor_incremental = 0; +} + +/* Build AVL tree from a string constant. */ + +static void +set_nonincremental_init_from_string (str) + tree str; +{ + tree value, purpose, type; + HOST_WIDE_INT val[2]; + const char *p, *end; + int byte, wchar_bytes, charwidth, bitpos; + + if (TREE_CODE (constructor_type) != ARRAY_TYPE) + abort (); + + if (TYPE_PRECISION (TREE_TYPE (TREE_TYPE (str))) + == TYPE_PRECISION (char_type_node)) + wchar_bytes = 1; + else if (TYPE_PRECISION (TREE_TYPE (TREE_TYPE (str))) + == TYPE_PRECISION (wchar_type_node)) + wchar_bytes = TYPE_PRECISION (wchar_type_node) / BITS_PER_UNIT; + else + abort (); + + charwidth = TYPE_PRECISION (char_type_node); + type = TREE_TYPE (constructor_type); + p = TREE_STRING_POINTER (str); + end = p + TREE_STRING_LENGTH (str); + + for (purpose = bitsize_zero_node; + p < end && !tree_int_cst_lt (constructor_max_index, purpose); + purpose = size_binop (PLUS_EXPR, purpose, bitsize_one_node)) + { + if (wchar_bytes == 1) + { + val[1] = (unsigned char) *p++; + val[0] = 0; + } + else + { + val[0] = 0; + val[1] = 0; + for (byte = 0; byte < wchar_bytes; byte++) + { + if (BYTES_BIG_ENDIAN) + bitpos = (wchar_bytes - byte - 1) * charwidth; + else + bitpos = byte * charwidth; + val[bitpos < HOST_BITS_PER_WIDE_INT] + |= ((unsigned HOST_WIDE_INT) ((unsigned char) *p++)) + << (bitpos % HOST_BITS_PER_WIDE_INT); + } + } + + if (!TREE_UNSIGNED (type)) + { + bitpos = ((wchar_bytes - 1) * charwidth) + HOST_BITS_PER_CHAR; + if (bitpos < HOST_BITS_PER_WIDE_INT) + { + if (val[1] & (((HOST_WIDE_INT) 1) << (bitpos - 1))) + { + val[1] |= ((HOST_WIDE_INT) -1) << bitpos; + val[0] = -1; + } + } + else if (bitpos == HOST_BITS_PER_WIDE_INT) + { + if (val[1] < 0) + val[0] = -1; + } + else if (val[0] & (((HOST_WIDE_INT) 1) + << (bitpos - 1 - HOST_BITS_PER_WIDE_INT))) + val[0] |= ((HOST_WIDE_INT) -1) + << (bitpos - HOST_BITS_PER_WIDE_INT); + } + + value = build_int_2 (val[1], val[0]); + TREE_TYPE (value) = type; + add_pending_init (purpose, value); + } + + constructor_incremental = 0; +} + +/* Return value of FIELD in pending initializer or zero if the field was + not initialized yet. */ + +static tree +find_init_member (field) tree field; { struct init_node *p; - p = constructor_pending_elts; if (TREE_CODE (constructor_type) == ARRAY_TYPE) { + if (constructor_incremental + && tree_int_cst_lt (field, constructor_unfilled_index)) + set_nonincremental_init (); + + p = constructor_pending_elts; while (p) { - if (field == p->purpose) - return 1; - else if (tree_int_cst_lt (field, p->purpose)) + if (tree_int_cst_lt (field, p->purpose)) p = p->left; - else + else if (tree_int_cst_lt (p->purpose, field)) p = p->right; + else + return p->value; } } - else + else if (TREE_CODE (constructor_type) == RECORD_TYPE) { + tree bitpos = bit_position (field); + + if (constructor_incremental + && (!constructor_unfilled_fields + || tree_int_cst_lt (bitpos, + bit_position (constructor_unfilled_fields)))) + set_nonincremental_init (); + + p = constructor_pending_elts; while (p) { if (field == p->purpose) - return 1; - else if (tree_int_cst_lt (bit_position (field), - bit_position (p->purpose))) + return p->value; + else if (tree_int_cst_lt (bitpos, bit_position (p->purpose))) p = p->left; else p = p->right; } } - + else if (TREE_CODE (constructor_type) == UNION_TYPE) + { + if (constructor_elements + && TREE_PURPOSE (constructor_elements) == field) + return TREE_VALUE (constructor_elements); + } return 0; } @@ -5912,8 +6217,6 @@ 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 @@ -5941,122 +6244,111 @@ output_init_element (value, type, field, pending) } else if (require_constant_elements && initializer_constant_valid_p (value, TREE_TYPE (value)) == 0) - { - error_init ("initializer element is not computable at load time"); - value = error_mark_node; - } + pedwarn ("initializer element is not computable at load time"); + + /* If this field is empty (and not at the end of structure), + don't do anything other than checking the initializer. */ + if (field + && (TREE_TYPE (field) == error_mark_node + || (COMPLETE_TYPE_P (TREE_TYPE (field)) + && integer_zerop (TYPE_SIZE (TREE_TYPE (field))) + && (TREE_CODE (constructor_type) == ARRAY_TYPE + || TREE_CHAIN (field))))) + return; - /* 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 (value == error_mark_node) { - if (TREE_CODE (constructor_type) == RECORD_TYPE - || TREE_CODE (constructor_type) == UNION_TYPE - || TREE_CODE (constructor_type) == ARRAY_TYPE) - { - if (pending_init_member (field)) - { - error_init ("duplicate initializer"); - duplicate = 1; - } - } + constructor_erroneous = 1; + return; } /* 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)) + && (!constructor_incremental + || !tree_int_cst_equal (field, constructor_unfilled_index))) { - if (! duplicate) - add_pending_init (field, - digest_init (type, value, require_constant_value, - require_constant_elements)); + if (constructor_incremental + && tree_int_cst_lt (field, constructor_unfilled_index)) + set_nonincremental_init (); + + add_pending_init (field, + digest_init (type, value, require_constant_value, + require_constant_elements)); + return; } else if (TREE_CODE (constructor_type) == RECORD_TYPE - && field != constructor_unfilled_fields) + && (!constructor_incremental + || 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) - add_pending_init (field, - digest_init (type, value, require_constant_value, - require_constant_elements)); - } - else - { - /* Otherwise, output this element either to - constructor_elements or to the assembler file. */ - - if (!duplicate) + if (constructor_incremental) { - if (! constructor_incremental) - { - if (field && TREE_CODE (field) == INTEGER_CST) - field = copy_node (field); - constructor_elements - = tree_cons (field, digest_init (type, value, - require_constant_value, - require_constant_elements), - constructor_elements); - } + if (!constructor_unfilled_fields) + set_nonincremental_init (); else { - /* Structure elements may require alignment. - Do this, if necessary. */ - if (TREE_CODE (constructor_type) == RECORD_TYPE - && ! tree_int_cst_equal (constructor_bit_index, - bit_position (field))) - /* Advance to offset of this element. */ - assemble_zeros - (tree_low_cst - (size_binop (TRUNC_DIV_EXPR, - size_binop (MINUS_EXPR, bit_position (field), - constructor_bit_index), - bitsize_unit_node), - 0)); - - output_constant (digest_init (type, value, - require_constant_value, - require_constant_elements), - 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) - constructor_bit_index - = size_binop (PLUS_EXPR, bit_position (field), - DECL_SIZE (field)); + tree bitpos, unfillpos; + + bitpos = bit_position (field); + unfillpos = bit_position (constructor_unfilled_fields); + + if (tree_int_cst_lt (bitpos, unfillpos)) + set_nonincremental_init (); } } - /* Advance the variable that indicates sequential elements output. */ - if (TREE_CODE (constructor_type) == ARRAY_TYPE) - constructor_unfilled_index - = size_binop (PLUS_EXPR, constructor_unfilled_index, - bitsize_one_node); - else if (TREE_CODE (constructor_type) == RECORD_TYPE) - { - constructor_unfilled_fields - = TREE_CHAIN (constructor_unfilled_fields); - - /* Skip any nameless bit fields. */ - while (constructor_unfilled_fields != 0 - && DECL_C_BIT_FIELD (constructor_unfilled_fields) - && DECL_NAME (constructor_unfilled_fields) == 0) - constructor_unfilled_fields = - TREE_CHAIN (constructor_unfilled_fields); - } - else if (TREE_CODE (constructor_type) == UNION_TYPE) - constructor_unfilled_fields = 0; + add_pending_init (field, + digest_init (type, value, require_constant_value, + require_constant_elements)); + return; + } + else if (TREE_CODE (constructor_type) == UNION_TYPE + && constructor_elements) + { + if (TREE_SIDE_EFFECTS (TREE_VALUE (constructor_elements))) + warning_init ("initialized field with side-effects overwritten"); + + /* We can have just one union field set. */ + constructor_elements = 0; + } - /* Now output any pending elements which have become next. */ - if (pending) - output_pending_init_elements (0); + /* Otherwise, output this element either to + constructor_elements or to the assembler file. */ + + if (field && TREE_CODE (field) == INTEGER_CST) + field = copy_node (field); + constructor_elements + = tree_cons (field, digest_init (type, value, + require_constant_value, + require_constant_elements), + constructor_elements); + + /* Advance the variable that indicates sequential elements output. */ + if (TREE_CODE (constructor_type) == ARRAY_TYPE) + constructor_unfilled_index + = size_binop (PLUS_EXPR, constructor_unfilled_index, + bitsize_one_node); + else if (TREE_CODE (constructor_type) == RECORD_TYPE) + { + constructor_unfilled_fields + = TREE_CHAIN (constructor_unfilled_fields); + + /* Skip any nameless bit fields. */ + while (constructor_unfilled_fields != 0 + && DECL_C_BIT_FIELD (constructor_unfilled_fields) + && DECL_NAME (constructor_unfilled_fields) == 0) + 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. @@ -6132,18 +6424,23 @@ output_pending_init_elements (all) else if (TREE_CODE (constructor_type) == RECORD_TYPE || TREE_CODE (constructor_type) == UNION_TYPE) { + tree ctor_unfilled_bitpos, elt_bitpos; + /* If the current record is complete we are done. */ if (constructor_unfilled_fields == 0) break; - if (elt->purpose == constructor_unfilled_fields) + + ctor_unfilled_bitpos = bit_position (constructor_unfilled_fields); + elt_bitpos = bit_position (elt->purpose); + /* We can't compare fields here because there might be empty + fields in between. */ + if (tree_int_cst_equal (elt_bitpos, ctor_unfilled_bitpos)) { - output_init_element (elt->value, - TREE_TYPE (constructor_unfilled_fields), - constructor_unfilled_fields, - 0); + constructor_unfilled_fields = elt->purpose; + output_init_element (elt->value, TREE_TYPE (elt->purpose), + elt->purpose, 0); } - else if (tree_int_cst_lt (bit_position (constructor_unfilled_fields), - bit_position (elt->purpose))) + else if (tree_int_cst_lt (ctor_unfilled_bitpos, elt_bitpos)) { /* Advance to the next smaller node. */ if (elt->left) @@ -6169,9 +6466,8 @@ output_pending_init_elements (all) elt = elt->parent; elt = elt->parent; if (elt - && (tree_int_cst_lt - (bit_position (constructor_unfilled_fields), - bit_position (elt->purpose)))) + && (tree_int_cst_lt (ctor_unfilled_bitpos, + bit_position (elt->purpose)))) { next = elt->purpose; break; @@ -6186,66 +6482,13 @@ output_pending_init_elements (all) if (! (all && next != 0)) return; - /* Generate space up to the position of NEXT. */ - if (constructor_incremental) - { - tree filled; - tree nextpos_tree = bitsize_zero_node; - - if (TREE_CODE (constructor_type) == RECORD_TYPE - || TREE_CODE (constructor_type) == UNION_TYPE) - { - tree tail; - - /* Find the last field written out, if any. */ - for (tail = TYPE_FIELDS (constructor_type); tail; - tail = TREE_CHAIN (tail)) - if (TREE_CHAIN (tail) == constructor_unfilled_fields) - break; - - if (tail) - /* Find the offset of the end of that field. */ - filled = size_binop (CEIL_DIV_EXPR, - size_binop (PLUS_EXPR, bit_position (tail), - DECL_SIZE (tail)), - bitsize_unit_node); - else - filled = bitsize_zero_node; - - nextpos_tree = convert (bitsizetype, byte_position (next)); - constructor_bit_index = bit_position (next); - constructor_unfilled_fields = next; - } - else if (TREE_CODE (constructor_type) == ARRAY_TYPE) - { - filled - = size_binop (MULT_EXPR, constructor_unfilled_index, - convert (bitsizetype, - TYPE_SIZE_UNIT - (TREE_TYPE (constructor_type)))); - nextpos_tree - = size_binop (MULT_EXPR, next, - convert (bitsizetype, TYPE_SIZE_UNIT - (TREE_TYPE (constructor_type)))); - constructor_unfilled_index = next; - } - else - filled = 0; - - if (filled) - assemble_zeros (tree_low_cst (size_diffop (nextpos_tree, filled), 1)); - } - 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) - constructor_unfilled_index = next; - } + /* 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) + constructor_unfilled_index = next; /* ELT now points to the node in the pending tree with the next initializer to output. */ @@ -6258,13 +6501,7 @@ output_pending_init_elements (all) 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. */ + it calls output_init_element. */ void process_init_element (value) @@ -6273,6 +6510,9 @@ process_init_element (value) tree orig_value = value; int string_flag = value != 0 && TREE_CODE (value) == STRING_CST; + designator_depth = 0; + designator_errorneous = 0; + /* Handle superfluous braces around string cst as in char x[] = {"foo"}; */ if (string_flag @@ -6315,6 +6555,10 @@ process_init_element (value) break; } + /* In the case of [LO ... HI] = VALUE, only evaluate VALUE once. */ + if (constructor_range_stack) + value = save_expr (value); + while (1) { if (TREE_CODE (constructor_type) == RECORD_TYPE) @@ -6362,10 +6606,11 @@ process_init_element (value) directly output as a constructor. */ { /* For a record, keep track of end position of last field. */ - constructor_bit_index - = size_binop (PLUS_EXPR, - bit_position (constructor_fields), - DECL_SIZE (constructor_fields)); + if (DECL_SIZE (constructor_fields)) + constructor_bit_index + = size_binop (PLUS_EXPR, + bit_position (constructor_fields), + DECL_SIZE (constructor_fields)); constructor_unfilled_fields = TREE_CHAIN (constructor_fields); /* Skip any nameless bit fields. */ @@ -6382,9 +6627,8 @@ process_init_element (value) && DECL_C_BIT_FIELD (constructor_fields) && DECL_NAME (constructor_fields) == 0) constructor_fields = TREE_CHAIN (constructor_fields); - break; } - if (TREE_CODE (constructor_type) == UNION_TYPE) + else if (TREE_CODE (constructor_type) == UNION_TYPE) { tree fieldtype; enum tree_code fieldcode; @@ -6405,8 +6649,13 @@ process_init_element (value) under the assumption that the zero initializer in user code appears conditioned on e.g. __STDC__ to avoid "missing initializer" warnings and relies on default - initialization to zero in the traditional C case. */ - if (warn_traditional && !integer_zerop (value)) + initialization to zero in the traditional C case. + We also skip the warning if the initializer is designated, + again on the assumption that this must be conditional on + __STDC__ anyway (and we've already complained about the + member-designator already). */ + if (warn_traditional && !in_system_header && !constructor_designated + && !(value && (integer_zerop (value) || real_zerop (value)))) warning ("traditional C rejects initialization of unions"); /* Accept a string constant to initialize a subarray. */ @@ -6442,9 +6691,8 @@ process_init_element (value) } constructor_fields = 0; - break; } - if (TREE_CODE (constructor_type) == ARRAY_TYPE) + else if (TREE_CODE (constructor_type) == ARRAY_TYPE) { tree elttype = TYPE_MAIN_VARIANT (TREE_TYPE (constructor_type)); enum tree_code eltcode = TREE_CODE (elttype); @@ -6468,104 +6716,166 @@ process_init_element (value) } if (constructor_max_index != 0 - && tree_int_cst_lt (constructor_max_index, constructor_index)) + && (tree_int_cst_lt (constructor_max_index, constructor_index) + || integer_all_onesp (constructor_max_index))) { pedwarn_init ("excess elements in array initializer"); break; } - /* In the case of [LO .. HI] = VALUE, only evaluate VALUE once. */ - if (constructor_range_end) + /* Now output the actual element. */ + if (value) { - if (constructor_max_index != 0 - && tree_int_cst_lt (constructor_max_index, - constructor_range_end)) - { - pedwarn_init ("excess elements in array initializer"); - constructor_range_end = constructor_max_index; - } - - value = save_expr (value); + push_array_bounds (tree_low_cst (constructor_index, 0)); + output_init_element (value, elttype, constructor_index, 1); + RESTORE_SPELLING_DEPTH (constructor_depth); } - /* Now output the actual element. - Ordinarily, output once. - If there is a range, repeat it till we advance past the range. */ - do - { - if (value) - { - push_array_bounds (tree_low_cst (constructor_index, 0)); - output_init_element (value, elttype, constructor_index, 1); - RESTORE_SPELLING_DEPTH (constructor_depth); - } - - constructor_index - = size_binop (PLUS_EXPR, constructor_index, bitsize_one_node); - - if (! value) - /* If we are doing the bookkeeping for an element that was - directly output as a constructor, we must update - constructor_unfilled_index. */ - constructor_unfilled_index = constructor_index; - } - while (! (constructor_range_end == 0 - || tree_int_cst_lt (constructor_range_end, - constructor_index))); + constructor_index + = size_binop (PLUS_EXPR, constructor_index, bitsize_one_node); - break; + if (! value) + /* If we are doing the bookkeeping for an element that was + directly output as a constructor, we must update + constructor_unfilled_index. */ + constructor_unfilled_index = constructor_index; } /* Handle the sole element allowed in a braced initializer for a scalar variable. */ - if (constructor_fields == 0) + else if (constructor_fields == 0) { pedwarn_init ("excess elements in scalar initializer"); break; } + else + { + if (value) + output_init_element (value, constructor_type, NULL_TREE, 1); + constructor_fields = 0; + } + + /* Handle range initializers either at this level or anywhere higher + in the designator stack. */ + if (constructor_range_stack) + { + struct constructor_range_stack *p, *range_stack; + int finish = 0; + + range_stack = constructor_range_stack; + constructor_range_stack = 0; + while (constructor_stack != range_stack->stack) + { + if (!constructor_stack->implicit) + abort (); + process_init_element (pop_init_level (1)); + } + for (p = range_stack; + !p->range_end || tree_int_cst_equal (p->index, p->range_end); + p = p->prev) + { + if (!constructor_stack->implicit) + abort (); + process_init_element (pop_init_level (1)); + } + + p->index = size_binop (PLUS_EXPR, p->index, bitsize_one_node); + if (tree_int_cst_equal (p->index, p->range_end) && !p->prev) + finish = 1; + + while (1) + { + constructor_index = p->index; + constructor_fields = p->fields; + if (finish && p->range_end && p->index == p->range_start) + { + finish = 0; + p->prev = 0; + } + p = p->next; + if (!p) + break; + push_init_level (2); + p->stack = constructor_stack; + if (p->range_end && tree_int_cst_equal (p->index, p->range_end)) + p->index = p->range_start; + } + + if (!finish) + constructor_range_stack = range_stack; + continue; + } - if (value) - output_init_element (value, constructor_type, NULL_TREE, 1); - constructor_fields = 0; break; } + + constructor_range_stack = 0; } -/* Expand an ASM statement with operands, handling output operands - that are not variables or INDIRECT_REFS by transforming such - cases into cases that expand_asm_operands can handle. +/* Build a simple asm-statement, from one string literal. */ +tree +simple_asm_stmt (expr) + tree expr; +{ + STRIP_NOPS (expr); - Arguments are same as for expand_asm_operands. */ + if (TREE_CODE (expr) == ADDR_EXPR) + expr = TREE_OPERAND (expr, 0); -void -c_expand_asm_operands (string, outputs, inputs, clobbers, vol, filename, line) - tree string, outputs, inputs, clobbers; - int vol; - const char *filename; - int line; + if (TREE_CODE (expr) == STRING_CST) + { + tree stmt; + + if (TREE_CHAIN (expr)) + expr = combine_strings (expr); + stmt = add_stmt (build_stmt (ASM_STMT, NULL_TREE, expr, + NULL_TREE, NULL_TREE, + NULL_TREE)); + ASM_INPUT_P (stmt) = 1; + return stmt; + } + + error ("argument of `asm' is not a constant string"); + return NULL_TREE; +} + +/* Build an asm-statement, whose components are a CV_QUALIFIER, a + STRING, some OUTPUTS, some INPUTS, and some CLOBBERS. */ + +tree +build_asm_stmt (cv_qualifier, string, outputs, inputs, clobbers) + tree cv_qualifier; + tree string; + tree outputs; + tree inputs; + tree clobbers; { - int noutputs = list_length (outputs); - register int i; - /* o[I] is the place that output number I should be written. */ - register tree *o = (tree *) alloca (noutputs * sizeof (tree)); - register tree tail; + tree tail; - if (TREE_CODE (string) == ADDR_EXPR) - string = TREE_OPERAND (string, 0); + if (TREE_CHAIN (string)) + string = combine_strings (string); if (TREE_CODE (string) != STRING_CST) { error ("asm template is not a string constant"); - return; + return NULL_TREE; } - /* Record the contents of OUTPUTS before it is modified. */ - for (i = 0, tail = outputs; tail; tail = TREE_CHAIN (tail), i++) + if (cv_qualifier != NULL_TREE + && cv_qualifier != ridpointers[(int) RID_VOLATILE]) + { + warning ("%s qualifier ignored on asm", + IDENTIFIER_POINTER (cv_qualifier)); + cv_qualifier = NULL_TREE; + } + + /* We can remove output conversions that change the type, + but not the mode. */ + for (tail = outputs; tail; tail = TREE_CHAIN (tail)) { tree output = TREE_VALUE (tail); - /* We can remove conversions that just change the type, not the mode. */ STRIP_NOPS (output); - o[i] = output; + TREE_VALUE (tail) = output; /* Allow conversions as LHS here. build_modify_expr as called below will do the right thing with them. */ @@ -6578,20 +6888,52 @@ c_expand_asm_operands (string, outputs, inputs, clobbers, vol, filename, line) || TREE_CODE (output) == FIX_CEIL_EXPR) output = TREE_OPERAND (output, 0); - lvalue_or_else (o[i], "invalid lvalue in asm statement"); + lvalue_or_else (TREE_VALUE (tail), "invalid lvalue in asm statement"); + } + + /* Remove output conversions that change the type but not the mode. */ + for (tail = outputs; tail; tail = TREE_CHAIN (tail)) + { + tree output = TREE_VALUE (tail); + STRIP_NOPS (output); + TREE_VALUE (tail) = output; } - /* Perform default conversions on array and function inputs. */ - /* Don't do this for other types-- - it would screw up operands expected to be in memory. */ - for (i = 0, tail = inputs; tail; tail = TREE_CHAIN (tail), i++) - if (TREE_CODE (TREE_TYPE (TREE_VALUE (tail))) == ARRAY_TYPE - || TREE_CODE (TREE_TYPE (TREE_VALUE (tail))) == FUNCTION_TYPE) - TREE_VALUE (tail) = default_conversion (TREE_VALUE (tail)); + /* Perform default conversions on array and function inputs. + Don't do this for other types as it would screw up operands + expected to be in memory. */ + for (tail = inputs; tail; tail = TREE_CHAIN (tail)) + TREE_VALUE (tail) = default_function_array_conversion (TREE_VALUE (tail)); + + return add_stmt (build_stmt (ASM_STMT, cv_qualifier, string, + outputs, inputs, clobbers)); +} + +/* Expand an ASM statement with operands, handling output operands + that are not variables or INDIRECT_REFS by transforming such + cases into cases that expand_asm_operands can handle. + + Arguments are same as for expand_asm_operands. */ + +void +c_expand_asm_operands (string, outputs, inputs, clobbers, vol, filename, line) + tree string, outputs, inputs, clobbers; + int vol; + const char *filename; + int line; +{ + int noutputs = list_length (outputs); + int i; + /* o[I] is the place that output number I should be written. */ + tree *o = (tree *) alloca (noutputs * sizeof (tree)); + tree tail; + + /* Record the contents of OUTPUTS before it is modified. */ + for (i = 0, tail = outputs; tail; tail = TREE_CHAIN (tail), i++) + o[i] = TREE_VALUE (tail); - /* Generate the ASM_OPERANDS insn; - store into the TREE_VALUEs of OUTPUTS some trees for - where the values were actually stored. */ + /* Generate the ASM_OPERANDS insn; store into the TREE_VALUEs of + OUTPUTS some trees for where the values were actually stored. */ expand_asm_operands (string, outputs, inputs, clobbers, vol, filename, line); /* Copy all the intermediate outputs into the specified outputs. */ @@ -6602,6 +6944,10 @@ c_expand_asm_operands (string, outputs, inputs, clobbers, vol, filename, line) expand_expr (build_modify_expr (o[i], NOP_EXPR, TREE_VALUE (tail)), NULL_RTX, VOIDmode, EXPAND_NORMAL); free_temp_slots (); + + /* Restore the original value so that it's correct the next + time we expand this function. */ + TREE_VALUE (tail) = o[i]; } /* Detect modification of read-only values. (Otherwise done by build_modify_expr.) */ @@ -6625,7 +6971,7 @@ c_expand_asm_operands (string, outputs, inputs, clobbers, vol, filename, line) RETVAL is the expression for what to return, or a null pointer for `return;' with no value. */ -void +tree c_expand_return (retval) tree retval; { @@ -6640,14 +6986,12 @@ c_expand_return (retval) if ((warn_return_type || flag_isoc99) && valtype != 0 && TREE_CODE (valtype) != VOID_TYPE) pedwarn_c99 ("`return' with no value, in function returning non-void"); - expand_null_return (); } else if (valtype == 0 || TREE_CODE (valtype) == VOID_TYPE) { current_function_returns_null = 1; if (pedantic || TREE_CODE (TREE_TYPE (retval)) != VOID_TYPE) pedwarn ("`return' with a value, in function returning void"); - expand_return (retval); } else { @@ -6657,7 +7001,7 @@ c_expand_return (retval) tree inner; if (t == error_mark_node) - return; + return NULL_TREE; inner = t = convert (TREE_TYPE (res), t); @@ -6712,58 +7056,125 @@ c_expand_return (retval) break; } - t = build (MODIFY_EXPR, TREE_TYPE (res), res, t); - TREE_SIDE_EFFECTS (t) = 1; - expand_return (t); + retval = build (MODIFY_EXPR, TREE_TYPE (res), res, t); current_function_returns_value = 1; } + + return add_stmt (build_return_stmt (retval)); } -/* Start a C switch statement, testing expression EXP. - Return EXP if it is valid, an error node otherwise. */ +struct c_switch { + /* The SWITCH_STMT being built. */ + tree switch_stmt; + /* A splay-tree mapping the low element of a case range to the high + element, or NULL_TREE if there is no high element. Used to + determine whether or not a new case label duplicates an old case + label. We need a tree, rather than simply a hash table, because + of the GNU case range extension. */ + splay_tree cases; + /* The next node on the stack. */ + struct c_switch *next; +}; + +/* A stack of the currently active switch statements. The innermost + switch statement is on the top of the stack. There is no need to + mark the stack for garbage collection because it is only active + during the processing of the body of a function, and we never + collect at that point. */ + +static struct c_switch *switch_stack; + +/* Start a C switch statement, testing expression EXP. Return the new + SWITCH_STMT. */ tree -c_expand_start_case (exp) +c_start_case (exp) tree exp; { - register enum tree_code code; + enum tree_code code; tree type; + struct c_switch *cs; + + if (exp != error_mark_node) + { + code = TREE_CODE (TREE_TYPE (exp)); + type = TREE_TYPE (exp); + + if (! INTEGRAL_TYPE_P (type) + && code != ERROR_MARK) + { + error ("switch quantity not an integer"); + exp = integer_zero_node; + } + else + { + tree index; + type = TYPE_MAIN_VARIANT (TREE_TYPE (exp)); + + if (warn_traditional && !in_system_header + && (type == long_integer_type_node + || type == long_unsigned_type_node)) + warning ("`long' switch expression not converted to `int' in ISO C"); + + exp = default_conversion (exp); + type = TREE_TYPE (exp); + index = get_unwidened (exp, NULL_TREE); + /* We can't strip a conversion from a signed type to an + unsigned, because if we did, int_fits_type_p would do the + wrong thing when checking case values for being in range, + and it's too hard to do the right thing. */ + if (TREE_UNSIGNED (TREE_TYPE (exp)) + == TREE_UNSIGNED (TREE_TYPE (index))) + exp = index; + } + } + + /* Add this new SWITCH_STMT to the stack. */ + cs = (struct c_switch *) xmalloc (sizeof (*cs)); + cs->switch_stmt = build_stmt (SWITCH_STMT, exp, NULL_TREE, NULL_TREE); + cs->cases = splay_tree_new (case_compare, NULL, NULL); + cs->next = switch_stack; + switch_stack = cs; - if (TREE_CODE (exp) == ERROR_MARK) - return exp; + return add_stmt (switch_stack->switch_stmt); +} + +/* Process a case label. */ - code = TREE_CODE (TREE_TYPE (exp)); - type = TREE_TYPE (exp); +tree +do_case (low_value, high_value) + tree low_value; + tree high_value; +{ + tree label = NULL_TREE; - if (code != INTEGER_TYPE && code != ENUMERAL_TYPE && code != ERROR_MARK) + if (switch_stack) { - error ("switch quantity not an integer"); - exp = error_mark_node; + label = c_add_case_label (switch_stack->cases, + SWITCH_COND (switch_stack->switch_stmt), + low_value, high_value); + if (label == error_mark_node) + label = NULL_TREE; } + else if (low_value) + error ("case label not within a switch statement"); else - { - tree index; - type = TYPE_MAIN_VARIANT (TREE_TYPE (exp)); + error ("`default' label not within a switch statement"); - if (warn_traditional - && ! in_system_header - && (type == long_integer_type_node - || type == long_unsigned_type_node)) - warning ("`long' switch expression not converted to `int' in ISO C"); + return label; +} - exp = default_conversion (exp); - type = TREE_TYPE (exp); - index = get_unwidened (exp, NULL_TREE); - /* We can't strip a conversion from a signed type to an unsigned, - because if we did, int_fits_type_p would do the wrong thing - when checking case values for being in range, - and it's too hard to do the right thing. */ - if (TREE_UNSIGNED (TREE_TYPE (exp)) - == TREE_UNSIGNED (TREE_TYPE (index))) - exp = index; - } +/* Finish the switch statement. */ - expand_start_case (1, exp, type, "switch statement"); +void +c_finish_case () +{ + struct c_switch *cs = switch_stack; - return exp; + RECHAIN_STMTS (cs->switch_stmt, SWITCH_BODY (cs->switch_stmt)); + + /* Pop the stack. */ + switch_stack = switch_stack->next; + splay_tree_delete (cs->cases); + free (cs); }