X-Git-Url: http://git.sourceforge.jp/view?a=blobdiff_plain;f=gcc%2Fc-typeck.c;h=64f0f07d89ad6e34e657cf79d3fa9c8768c8336a;hb=4206f59199f12699c724219ebf37a58cfeaecbd1;hp=3cbf6c6f3efdbef9910d9cd3fde9fbcd77c86a75;hpb=d0a47c8d249dba52c8718c62d27990a4f18f2a34;p=pf3gnuchains%2Fgcc-fork.git diff --git a/gcc/c-typeck.c b/gcc/c-typeck.c index 3cbf6c6f3ef..64f0f07d89a 100644 --- a/gcc/c-typeck.c +++ b/gcc/c-typeck.c @@ -2,22 +2,22 @@ Copyright (C) 1987, 1988, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 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. @@ -41,6 +41,7 @@ Boston, MA 02111-1307, USA. */ #include "toplev.h" #include "intl.h" #include "ggc.h" +#include "target.h" /* Nonzero if we've already printed a "missing braces around initializer" message within this initializer. */ @@ -54,11 +55,12 @@ 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_for_broken_optimization PARAMS ((tree)); -static tree lookup_field PARAMS ((tree, tree, 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 *, @@ -190,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. */ @@ -205,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. */ @@ -435,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. */ @@ -482,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. */ @@ -508,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. */ @@ -516,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; @@ -651,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. */ @@ -785,82 +797,7 @@ 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); - tree t; - - if (code == FUNCTION_TYPE) - t = size_int (FUNCTION_BOUNDARY / BITS_PER_UNIT); - else if (code == VOID_TYPE || code == ERROR_MARK) - t = size_one_node; - else if (code == ERROR_MARK) - t = size_one_node; - else if (!COMPLETE_TYPE_P (type)) - { - error ("__alignof__ applied to an incomplete type"); - t = size_zero_node; - } - else - t = size_int (TYPE_ALIGN (type) / BITS_PER_UNIT); - - return fold (build1 (NOP_EXPR, c_size_type_node, t)); -} -/* 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; -{ - tree t; - - if (TREE_CODE (expr) == VAR_DECL) - t = size_int (DECL_ALIGN (expr) / BITS_PER_UNIT); - - else if (TREE_CODE (expr) == COMPONENT_REF - && DECL_C_BIT_FIELD (TREE_OPERAND (expr, 1))) - { - error ("`__alignof' applied to a bit-field"); - t = size_one_node; - } - else if (TREE_CODE (expr) == COMPONENT_REF - && TREE_CODE (TREE_OPERAND (expr, 1)) == FIELD_DECL) - t = size_int (DECL_ALIGN (TREE_OPERAND (expr, 1)) / BITS_PER_UNIT); - - else 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 fold (build1 (NOP_EXPR, c_size_type_node, t)); -} - /* Return either DECL or its known constant value (if it has one). */ tree @@ -902,6 +839,110 @@ decl_constant_value_for_broken_optimization (decl) return decl_constant_value (decl); } + +/* 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))) + { + if (TREE_CODE (exp) == NON_LVALUE_EXPR) + not_lvalue = 1; + 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)); + + if (code == FUNCTION_TYPE) + { + return build_unary_op (ADDR_EXPR, exp, 0); + } + if (code == ARRAY_TYPE) + { + 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)) + { + constp = TREE_READONLY (exp); + volatilep = TREE_THIS_VOLATILE (exp); + } + + if (TYPE_QUALS (type) || constp || volatilep) + restype + = c_build_qualified_type (restype, + TYPE_QUALS (type) + | (constp * TYPE_QUAL_CONST) + | (volatilep * TYPE_QUAL_VOLATILE)); + + if (TREE_CODE (exp) == INDIRECT_REF) + return convert (TYPE_POINTER_TO (restype), + TREE_OPERAND (exp, 0)); + + if (TREE_CODE (exp) == COMPOUND_EXPR) + { + tree op1 = default_conversion (TREE_OPERAND (exp, 1)); + return build (COMPOUND_EXPR, TREE_TYPE (op1), + TREE_OPERAND (exp, 0), op1); + } + + lvalue_array_p = !not_lvalue && lvalue_p (exp); + if (!flag_isoc99 && !lvalue_array_p + && !(TREE_CODE (exp) == CONSTRUCTOR && TREE_STATIC (exp))) + { + /* 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); + + if (TREE_CODE (exp) == VAR_DECL) + { + /* ??? This is not really quite correct + in that the type of the operand of ADDR_EXPR + is not the target type of the type of the ADDR_EXPR itself. + Question is, can this lossage be avoided? */ + adr = build1 (ADDR_EXPR, ptrtype, exp); + if (mark_addressable (exp) == 0) + return error_mark_node; + TREE_CONSTANT (adr) = staticp (exp); + TREE_SIDE_EFFECTS (adr) = 0; /* Default would be, same as EXP. */ + return adr; + } + /* This way is better for a COMPONENT_REF since it can + simplify the offset for a component. */ + adr = build_unary_op (ADDR_EXPR, exp, 1); + return convert (ptrtype, adr); + } + return exp; +} + /* Perform default promotions for C data used in expressions. Arrays and functions are converted to pointers; enumeral types or short or char, to int. @@ -911,8 +952,12 @@ tree default_conversion (exp) tree exp; { - register tree type = TREE_TYPE (exp); - register enum tree_code code = TREE_CODE (type); + 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) @@ -932,11 +977,16 @@ default_conversion (exp) 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) @@ -982,83 +1032,23 @@ default_conversion (exp) 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 restype = TREE_TYPE (type); - tree ptrtype; - int constp = 0; - int volatilep = 0; - - if (TREE_CODE_CLASS (TREE_CODE (exp)) == 'r' || DECL_P (exp)) - { - constp = TREE_READONLY (exp); - volatilep = TREE_THIS_VOLATILE (exp); - } - - if (TYPE_QUALS (type) || constp || volatilep) - restype - = c_build_qualified_type (restype, - TYPE_QUALS (type) - | (constp * TYPE_QUAL_CONST) - | (volatilep * TYPE_QUAL_VOLATILE)); - - if (TREE_CODE (exp) == INDIRECT_REF) - return convert (TYPE_POINTER_TO (restype), - TREE_OPERAND (exp, 0)); - - if (TREE_CODE (exp) == COMPOUND_EXPR) - { - tree op1 = default_conversion (TREE_OPERAND (exp, 1)); - return build (COMPOUND_EXPR, TREE_TYPE (op1), - TREE_OPERAND (exp, 0), op1); - } - - if (! lvalue_p (exp) - && ! (TREE_CODE (exp) == CONSTRUCTOR && TREE_STATIC (exp))) - { - error ("invalid use of non-lvalue array"); - return error_mark_node; - } - - ptrtype = build_pointer_type (restype); - - if (TREE_CODE (exp) == VAR_DECL) - { - /* ??? This is not really quite correct - in that the type of the operand of ADDR_EXPR - is not the target type of the type of the ADDR_EXPR itself. - Question is, can this lossage be avoided? */ - adr = build1 (ADDR_EXPR, ptrtype, exp); - if (mark_addressable (exp) == 0) - return error_mark_node; - TREE_CONSTANT (adr) = staticp (exp); - TREE_SIDE_EFFECTS (adr) = 0; /* Default would be, same as EXP. */ - return adr; - } - /* This way is better for a COMPONENT_REF since it can - simplify the offset for a component. */ - adr = build_unary_op (ADDR_EXPR, exp, 1); - return convert (ptrtype, adr); - } 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. */ +/* 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 @@ -1084,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. */ @@ -1117,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 @@ -1155,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; } @@ -1184,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) { @@ -1201,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) @@ -1242,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) { @@ -1255,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) { @@ -1526,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. */ @@ -1574,8 +1552,8 @@ build_function_call (function, params) /* Check for errors in format strings. */ - if (warn_format && (name || assembler_name)) - check_function_format (NULL, 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 @@ -1623,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 @@ -1634,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) { @@ -1653,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); @@ -1716,7 +1692,8 @@ convert_arguments (typelist, values, name, fundecl) 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. */ ; @@ -1766,9 +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 - || TREE_CODE (type) == BOOLEAN_TYPE) + && INTEGRAL_TYPE_P (type) && (TYPE_PRECISION (type) < TYPE_PRECISION (integer_type_node))) parmval = default_conversion (parmval); } @@ -1818,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); } @@ -4579,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++) { @@ -4597,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) @@ -4610,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++) @@ -4730,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 @@ -4761,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) { @@ -4791,14 +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) - pedwarn ("initializer element is not computable at load time"); return inside_init; } @@ -4968,6 +4993,9 @@ 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; @@ -5005,6 +5033,7 @@ struct constructor_stack char erroneous; char outer; char incremental; + char designated; }; struct constructor_stack *constructor_stack; @@ -5081,6 +5110,7 @@ start_init (decl, asmspec_tree, top_level) constructor_decl = decl; constructor_asmspec = asmspec; constructor_subconstants_deferred = 0; + constructor_designated = 0; constructor_top_level = top_level; if (decl != 0) @@ -5190,6 +5220,7 @@ really_start_incremental_init (type) p->range_stack = 0; p->outer = 0; p->incremental = constructor_incremental; + p->designated = constructor_designated; p->next = 0; constructor_stack = p; @@ -5200,6 +5231,7 @@ really_start_incremental_init (type) constructor_pending_elts = 0; constructor_type = type; constructor_incremental = 1; + constructor_designated = 0; designator_depth = 0; designator_errorneous = 0; @@ -5223,7 +5255,8 @@ really_start_incremental_init (type) = TYPE_MAX_VALUE (TYPE_DOMAIN (constructor_type)); /* Detect non-empty initializations of zero-length arrays. */ - if (constructor_max_index == NULL_TREE) + if (constructor_max_index == NULL_TREE + && TYPE_SIZE (constructor_type)) constructor_max_index = build_int_2 (-1, -1); constructor_index @@ -5300,6 +5333,7 @@ push_init_level (implicit) p->implicit = implicit; p->outer = 0; p->incremental = constructor_incremental; + p->designated = constructor_designated; p->next = constructor_stack; p->range_stack = 0; constructor_stack = p; @@ -5309,6 +5343,7 @@ push_init_level (implicit) constructor_depth = SPELLING_DEPTH (); constructor_elements = 0; constructor_incremental = 1; + constructor_designated = 0; constructor_pending_elts = 0; if (!implicit) { @@ -5385,14 +5420,15 @@ push_init_level (implicit) { 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))); - - /* ??? For GCC 3.1, remove special case initialization of - zero-length array members from pop_init_level and set - constructor_max_index such that we get the normal - "excess elements" warning. */ } else constructor_index = bitsize_zero_node; @@ -5427,7 +5463,6 @@ pop_init_level (implicit) int implicit; { struct constructor_stack *p; - HOST_WIDE_INT size = 0; tree constructor = 0; if (implicit == 0) @@ -5443,9 +5478,6 @@ pop_init_level (implicit) 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 @@ -5464,26 +5496,16 @@ pop_init_level (implicit) else if (pedantic) pedwarn_init ("initialization of a flexible array member"); - /* We have already issued an error message for the existance + /* 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 - { - warning_init ("deprecated initialization of zero-length array"); - - /* We must be initializing the last member of a top-level struct. */ - if (TREE_CHAIN (constructor_fields) != NULL_TREE) - { - error_init ("initialization of zero-length array before end of structure"); - /* Discard the initializer so that we do not abort later. */ - constructor_type = NULL_TREE; - } - else if (constructor_depth > 2) - error_init ("initialization of zero-length array inside a nested context"); - } + /* 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. */ @@ -5498,7 +5520,9 @@ pop_init_level (implicit) || integer_zerop (DECL_SIZE (constructor_unfilled_fields)))) constructor_unfilled_fields = TREE_CHAIN (constructor_unfilled_fields); - if (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"); @@ -5564,6 +5588,7 @@ pop_init_level (implicit) 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; if (!p->implicit) @@ -5610,6 +5635,7 @@ set_designator (array) braces. */ while (constructor_stack->implicit) process_init_element (pop_init_level (1)); + constructor_designated = 1; return 0; } @@ -5645,6 +5671,7 @@ set_designator (array) return 1; } + constructor_designated = 1; push_init_level (2); return 0; } @@ -5783,7 +5810,7 @@ set_init_label (fieldname) } /* 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 @@ -5857,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; @@ -5881,7 +5908,7 @@ add_pending_init (purpose, value) } else { - /* LR rotation. */ + /* LR rotation. */ struct init_node *t = r->right; r->right = t->left; @@ -5930,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; @@ -5989,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; } @@ -6622,8 +6649,12 @@ 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 && !in_system_header + 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"); @@ -6872,9 +6903,7 @@ build_asm_stmt (cv_qualifier, string, outputs, inputs, clobbers) 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)) - 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)); + TREE_VALUE (tail) = default_function_array_conversion (TREE_VALUE (tail)); return add_stmt (build_stmt (ASM_STMT, cv_qualifier, string, outputs, inputs, clobbers)); @@ -6894,10 +6923,10 @@ c_expand_asm_operands (string, outputs, inputs, clobbers, vol, filename, line) int line; { int noutputs = list_length (outputs); - register int i; + 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 *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++) @@ -7062,7 +7091,7 @@ tree c_start_case (exp) tree exp; { - register enum tree_code code; + enum tree_code code; tree type; struct c_switch *cs; @@ -7071,8 +7100,7 @@ c_start_case (exp) code = TREE_CODE (TREE_TYPE (exp)); type = TREE_TYPE (exp); - if (code != INTEGER_TYPE - && code != ENUMERAL_TYPE + if (! INTEGRAL_TYPE_P (type) && code != ERROR_MARK) { error ("switch quantity not an integer");