X-Git-Url: http://git.sourceforge.jp/view?a=blobdiff_plain;f=gcc%2Fc-typeck.c;h=9e4f0fb1501261328a318d858854a419ab69fe91;hb=8adfde8a54ea40ae2cf42010468ac64be35430b6;hp=1193f05fe99efb3f68bb13d783ba6636965e69eb;hpb=3ac2c7b88c0b2f55aa25765a7bcc0438b315d87d;p=pf3gnuchains%2Fgcc-fork.git diff --git a/gcc/c-typeck.c b/gcc/c-typeck.c index 1193f05fe99..9e4f0fb1501 100644 --- a/gcc/c-typeck.c +++ b/gcc/c-typeck.c @@ -23,11 +23,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA /* This file is part of the C front end. It contains routines to build C expressions given their operands, including computing the types of the result, C-specific error checks, - and some optimization. - - There are also routines to build RETURN_STMT nodes and CASE_STMT nodes, - and to process initializations in declarations (since they work - like a strange sort of assignment). */ + and some optimization. */ #include "config.h" #include "system.h" @@ -45,25 +41,58 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA #include "intl.h" #include "ggc.h" #include "target.h" +#include "tree-iterator.h" +#include "tree-gimple.h" + +/* Places where an lvalue, or modifiable lvalue, may be required. + Used to select diagnostic messages in lvalue_or_else and + readonly_error. */ +enum lvalue_use { + lv_assign, + lv_increment, + lv_decrement, + lv_addressof, + lv_asm +}; + +/* Possible cases of implicit bad conversions. Used to select + diagnostic messages in convert_for_assignment. */ +enum impl_conv { + ic_argpass, + ic_argpass_nonproto, + ic_assign, + ic_init, + ic_return +}; + +/* The level of nesting inside "__alignof__". */ +int in_alignof; + +/* The level of nesting inside "sizeof". */ +int in_sizeof; + +/* The level of nesting inside "typeof". */ +int in_typeof; /* Nonzero if we've already printed a "missing braces around initializer" message within this initializer. */ static int missing_braces_mentioned; +static int require_constant_value; +static int require_constant_elements; + static tree qualify_type (tree, tree); -static int tagged_types_tu_compatible_p (tree, tree, int); +static int tagged_types_tu_compatible_p (tree, tree); static int comp_target_types (tree, tree, int); -static int function_types_compatible_p (tree, tree, int); -static int type_lists_compatible_p (tree, tree, int); +static int function_types_compatible_p (tree, tree); +static int type_lists_compatible_p (tree, tree); static tree decl_constant_value_for_broken_optimization (tree); static tree default_function_array_conversion (tree); static tree lookup_field (tree, tree); static tree convert_arguments (tree, tree, tree, tree); static tree pointer_diff (tree, tree); -static tree internal_build_compound_expr (tree, int); -static tree convert_for_assignment (tree, tree, const char *, tree, tree, +static tree convert_for_assignment (tree, tree, enum impl_conv, tree, tree, int); -static void warn_for_assignment (const char *, const char *, tree, int); static tree valid_compound_expr_initializer (tree, tree); static void push_string (const char *); static void push_member_name (tree); @@ -71,8 +100,8 @@ static void push_array_bounds (int); static int spelling_length (void); static char *print_spelling (char *); static void warning_init (const char *); -static tree digest_init (tree, tree, int); -static void output_init_element (tree, tree, tree, int); +static tree digest_init (tree, tree, bool, int); +static void output_init_element (tree, bool, tree, tree, int); static void output_pending_init_elements (int); static int set_designator (int); static void push_range_stack (tree); @@ -80,6 +109,8 @@ static void add_pending_init (tree, tree); static void set_nonincremental_init (void); static void set_nonincremental_init_from_string (tree); static tree find_init_member (tree); +static int lvalue_or_else (tree, enum lvalue_use); +static void readonly_error (tree, enum lvalue_use); /* Do `exp = require_complete_type (exp);' to make sure exp does not have an incomplete type. (That includes void types.) */ @@ -115,7 +146,7 @@ c_incomplete_type_error (tree value, tree type) if (value != 0 && (TREE_CODE (value) == VAR_DECL || TREE_CODE (value) == PARM_DECL)) - error ("`%s' has an incomplete type", + error ("%qs has an incomplete type", IDENTIFIER_POINTER (DECL_NAME (value))); else { @@ -155,15 +186,15 @@ c_incomplete_type_error (tree value, tree type) return; default: - abort (); + gcc_unreachable (); } if (TREE_CODE (TYPE_NAME (type)) == IDENTIFIER_NODE) - error ("invalid use of undefined type `%s %s'", + error ("invalid use of undefined type %<%s %s%>", type_code_string, IDENTIFIER_POINTER (TYPE_NAME (type))); else /* If this type has a typedef-name, the TYPE_NAME is a TYPE_DECL. */ - error ("invalid use of incomplete typedef `%s'", + error ("invalid use of incomplete typedef %qs", IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type)))); } } @@ -199,19 +230,14 @@ qualify_type (tree type, tree like) TYPE_QUALS (type) | TYPE_QUALS (like)); } -/* Return the composite type of two compatible types, or the common - type for two arithmetic types under the usual arithmetic - conversions. +/* Return the composite type of two compatible types. - Unless both types are arithmetic types, we assume that comptypes - has already been done and returned 1; if that isn't so, this may - crash. In particular, we assume that qualifiers match. - - This is the type for the result of most arithmetic operations - if the operands have the given two types. */ + We assume that comptypes has already been done and returned + nonzero; if that isn't so, this may crash. In particular, we + assume that qualifiers match. */ tree -common_type (tree t1, tree t2) +composite_type (tree t1, tree t2) { enum tree_code code1; enum tree_code code2; @@ -227,131 +253,55 @@ common_type (tree t1, tree t2) if (t2 == error_mark_node) return t1; + code1 = TREE_CODE (t1); + code2 = TREE_CODE (t2); + /* Merge the attributes. */ attributes = targetm.merge_type_attributes (t1, t2); - /* Treat an enum type as the unsigned integer type of the same width. */ - - if (TREE_CODE (t1) == ENUMERAL_TYPE) - t1 = c_common_type_for_size (TYPE_PRECISION (t1), 1); - if (TREE_CODE (t2) == ENUMERAL_TYPE) - t2 = c_common_type_for_size (TYPE_PRECISION (t2), 1); + /* If one is an enumerated type and the other is the compatible + integer type, the composite type might be either of the two + (DR#013 question 3). For consistency, use the enumerated type as + the composite type. */ - code1 = TREE_CODE (t1); - code2 = TREE_CODE (t2); - - /* If one type is complex, form the common type of the non-complex - components, then make that complex. Use T1 or T2 if it is the - required type. */ - if (code1 == COMPLEX_TYPE || code2 == COMPLEX_TYPE) - { - tree subtype1 = code1 == COMPLEX_TYPE ? TREE_TYPE (t1) : t1; - tree subtype2 = code2 == COMPLEX_TYPE ? TREE_TYPE (t2) : t2; - tree subtype = common_type (subtype1, subtype2); + if (code1 == ENUMERAL_TYPE && code2 == INTEGER_TYPE) + return t1; + if (code2 == ENUMERAL_TYPE && code1 == INTEGER_TYPE) + return t2; - if (code1 == COMPLEX_TYPE && TREE_TYPE (t1) == subtype) - return build_type_attribute_variant (t1, attributes); - else if (code2 == COMPLEX_TYPE && TREE_TYPE (t2) == subtype) - return build_type_attribute_variant (t2, attributes); - else - return build_type_attribute_variant (build_complex_type (subtype), - attributes); - } + gcc_assert (code1 == code2); switch (code1) { - case INTEGER_TYPE: - case REAL_TYPE: - /* If only one is real, use it as the result. */ - - if (code1 == REAL_TYPE && code2 != REAL_TYPE) - return build_type_attribute_variant (t1, attributes); - - if (code2 == REAL_TYPE && code1 != REAL_TYPE) - return build_type_attribute_variant (t2, attributes); - - /* Both real or both integers; use the one with greater precision. */ - - if (TYPE_PRECISION (t1) > TYPE_PRECISION (t2)) - return build_type_attribute_variant (t1, attributes); - else if (TYPE_PRECISION (t2) > TYPE_PRECISION (t1)) - return build_type_attribute_variant (t2, attributes); - - /* Same precision. Prefer long longs to longs to ints when the - same precision, following the C99 rules on integer type rank - (which are equivalent to the C90 rules for C90 types). */ - - if (TYPE_MAIN_VARIANT (t1) == long_long_unsigned_type_node - || TYPE_MAIN_VARIANT (t2) == long_long_unsigned_type_node) - return build_type_attribute_variant (long_long_unsigned_type_node, - attributes); - - if (TYPE_MAIN_VARIANT (t1) == long_long_integer_type_node - || TYPE_MAIN_VARIANT (t2) == long_long_integer_type_node) - { - if (TYPE_UNSIGNED (t1) || TYPE_UNSIGNED (t2)) - t1 = long_long_unsigned_type_node; - else - t1 = long_long_integer_type_node; - return build_type_attribute_variant (t1, attributes); - } - - if (TYPE_MAIN_VARIANT (t1) == long_unsigned_type_node - || TYPE_MAIN_VARIANT (t2) == long_unsigned_type_node) - return build_type_attribute_variant (long_unsigned_type_node, - attributes); - - if (TYPE_MAIN_VARIANT (t1) == long_integer_type_node - || TYPE_MAIN_VARIANT (t2) == long_integer_type_node) - { - /* But preserve unsignedness from the other type, - since long cannot hold all the values of an unsigned int. */ - if (TYPE_UNSIGNED (t1) || TYPE_UNSIGNED (t2)) - t1 = long_unsigned_type_node; - else - t1 = long_integer_type_node; - return build_type_attribute_variant (t1, attributes); - } - - /* Likewise, prefer long double to double even if same size. */ - if (TYPE_MAIN_VARIANT (t1) == long_double_type_node - || TYPE_MAIN_VARIANT (t2) == long_double_type_node) - return build_type_attribute_variant (long_double_type_node, - attributes); - - /* Otherwise prefer the unsigned one. */ - - if (TYPE_UNSIGNED (t1)) - return build_type_attribute_variant (t1, attributes); - else - return build_type_attribute_variant (t2, attributes); - case POINTER_TYPE: - /* For two pointers, do this recursively on the target type, - and combine the qualifiers of the two types' targets. */ - /* This code was turned off; I don't know why. - But ANSI C specifies doing this with the qualifiers. - So I turned it on again. */ + /* For two pointers, do this recursively on the target type. */ { tree pointed_to_1 = TREE_TYPE (t1); tree pointed_to_2 = TREE_TYPE (t2); - tree target = common_type (TYPE_MAIN_VARIANT (pointed_to_1), - TYPE_MAIN_VARIANT (pointed_to_2)); - t1 = build_pointer_type (c_build_qualified_type - (target, - TYPE_QUALS (pointed_to_1) | - TYPE_QUALS (pointed_to_2))); - return build_type_attribute_variant (t1, attributes); + tree target = composite_type (pointed_to_1, pointed_to_2); + t1 = build_pointer_type (target); + t1 = build_type_attribute_variant (t1, attributes); + return qualify_type (t1, t2); } case ARRAY_TYPE: { - tree elt = common_type (TREE_TYPE (t1), TREE_TYPE (t2)); + tree elt = composite_type (TREE_TYPE (t1), TREE_TYPE (t2)); + + /* We should not have any type quals on arrays at all. */ + gcc_assert (!TYPE_QUALS (t1) && !TYPE_QUALS (t2)); + /* Save space: see if the result is identical to one of the args. */ if (elt == TREE_TYPE (t1) && TYPE_DOMAIN (t1)) return build_type_attribute_variant (t1, attributes); if (elt == TREE_TYPE (t2) && TYPE_DOMAIN (t2)) return build_type_attribute_variant (t2, attributes); + + if (elt == TREE_TYPE (t1) && !TYPE_DOMAIN (t2) && !TYPE_DOMAIN (t1)) + return build_type_attribute_variant (t1, attributes); + if (elt == TREE_TYPE (t2) && !TYPE_DOMAIN (t2) && !TYPE_DOMAIN (t1)) + return build_type_attribute_variant (t2, attributes); + /* Merge the element types, and have a size if either arg has one. */ t1 = build_array_type (elt, TYPE_DOMAIN (TYPE_DOMAIN (t1) ? t1 : t2)); return build_type_attribute_variant (t1, attributes); @@ -361,7 +311,7 @@ common_type (tree t1, tree t2) /* Function types: prefer the one that specified arg types. If both do, merge the arg types. Also merge the return types. */ { - tree valtype = common_type (TREE_TYPE (t1), TREE_TYPE (t2)); + tree valtype = composite_type (TREE_TYPE (t1), TREE_TYPE (t2)); tree p1 = TYPE_ARG_TYPES (t1); tree p2 = TYPE_ARG_TYPES (t2); int len; @@ -369,21 +319,23 @@ common_type (tree t1, tree t2) int i; /* Save space: see if the result is identical to one of the args. */ - if (valtype == TREE_TYPE (t1) && ! TYPE_ARG_TYPES (t2)) + if (valtype == TREE_TYPE (t1) && !TYPE_ARG_TYPES (t2)) return build_type_attribute_variant (t1, attributes); - if (valtype == TREE_TYPE (t2) && ! TYPE_ARG_TYPES (t1)) + if (valtype == TREE_TYPE (t2) && !TYPE_ARG_TYPES (t1)) return build_type_attribute_variant (t2, attributes); /* Simple way if one arg fails to specify argument types. */ if (TYPE_ARG_TYPES (t1) == 0) { - t1 = build_function_type (valtype, TYPE_ARG_TYPES (t2)); - return build_type_attribute_variant (t1, attributes); + t1 = build_function_type (valtype, TYPE_ARG_TYPES (t2)); + t1 = build_type_attribute_variant (t1, attributes); + return qualify_type (t1, t2); } if (TYPE_ARG_TYPES (t2) == 0) { t1 = build_function_type (valtype, TYPE_ARG_TYPES (t1)); - return build_type_attribute_variant (t1, attributes); + t1 = build_type_attribute_variant (t1, attributes); + return qualify_type (t1, t2); } /* If both args specify argument types, we must merge the two @@ -425,8 +377,7 @@ common_type (tree t1, tree t2) tree memb; for (memb = TYPE_FIELDS (TREE_VALUE (p1)); memb; memb = TREE_CHAIN (memb)) - if (comptypes (TREE_TYPE (memb), TREE_VALUE (p2), - COMPARE_STRICT)) + if (comptypes (TREE_TYPE (memb), TREE_VALUE (p2))) { TREE_VALUE (n) = TREE_VALUE (p2); if (pedantic) @@ -440,8 +391,7 @@ common_type (tree t1, tree t2) tree memb; for (memb = TYPE_FIELDS (TREE_VALUE (p2)); memb; memb = TREE_CHAIN (memb)) - if (comptypes (TREE_TYPE (memb), TREE_VALUE (p1), - COMPARE_STRICT)) + if (comptypes (TREE_TYPE (memb), TREE_VALUE (p1))) { TREE_VALUE (n) = TREE_VALUE (p1); if (pedantic) @@ -449,12 +399,13 @@ common_type (tree t1, tree t2) goto parm_done; } } - TREE_VALUE (n) = common_type (TREE_VALUE (p1), TREE_VALUE (p2)); + TREE_VALUE (n) = composite_type (TREE_VALUE (p1), TREE_VALUE (p2)); parm_done: ; } c_override_global_bindings_to_false = false; t1 = build_function_type (valtype, newargs); + t1 = qualify_type (t1, t2); /* ... falls through ... */ } @@ -463,13 +414,186 @@ common_type (tree t1, tree t2) } } + +/* Return the type of a conditional expression between pointers to + possibly differently qualified versions of compatible types. + + We assume that comp_target_types has already been done and returned + nonzero; if that isn't so, this may crash. */ + +static tree +common_pointer_type (tree t1, tree t2) +{ + tree attributes; + tree pointed_to_1; + tree pointed_to_2; + tree target; + + /* Save time if the two types are the same. */ + + if (t1 == t2) return t1; + + /* If one type is nonsense, use the other. */ + if (t1 == error_mark_node) + return t2; + if (t2 == error_mark_node) + return t1; + + gcc_assert (TREE_CODE (t1) == POINTER_TYPE + && TREE_CODE (t2) == POINTER_TYPE); + + /* Merge the attributes. */ + attributes = targetm.merge_type_attributes (t1, t2); + + /* Find the composite type of the target types, and combine the + qualifiers of the two types' targets. */ + pointed_to_1 = TREE_TYPE (t1); + pointed_to_2 = TREE_TYPE (t2); + target = composite_type (TYPE_MAIN_VARIANT (pointed_to_1), + TYPE_MAIN_VARIANT (pointed_to_2)); + t1 = build_pointer_type (c_build_qualified_type + (target, + TYPE_QUALS (pointed_to_1) | + TYPE_QUALS (pointed_to_2))); + return build_type_attribute_variant (t1, attributes); +} + +/* Return the common type for two arithmetic types under the usual + arithmetic conversions. The default conversions have already been + applied, and enumerated types converted to their compatible integer + types. The resulting type is unqualified and has no attributes. + + This is the type for the result of most arithmetic operations + if the operands have the given two types. */ + +tree +common_type (tree t1, tree t2) +{ + enum tree_code code1; + enum tree_code code2; + + /* If one type is nonsense, use the other. */ + if (t1 == error_mark_node) + return t2; + if (t2 == error_mark_node) + return t1; + + if (TYPE_QUALS (t1) != TYPE_UNQUALIFIED) + t1 = TYPE_MAIN_VARIANT (t1); + + if (TYPE_QUALS (t2) != TYPE_UNQUALIFIED) + t2 = TYPE_MAIN_VARIANT (t2); + + if (TYPE_ATTRIBUTES (t1) != NULL_TREE) + t1 = build_type_attribute_variant (t1, NULL_TREE); + + if (TYPE_ATTRIBUTES (t2) != NULL_TREE) + t2 = build_type_attribute_variant (t2, NULL_TREE); + + /* Save time if the two types are the same. */ + + if (t1 == t2) return t1; + + code1 = TREE_CODE (t1); + code2 = TREE_CODE (t2); + + gcc_assert (code1 == VECTOR_TYPE || code1 == COMPLEX_TYPE + || code1 == REAL_TYPE || code1 == INTEGER_TYPE); + gcc_assert (code2 == VECTOR_TYPE || code2 == COMPLEX_TYPE + || code2 == REAL_TYPE || code2 == INTEGER_TYPE); + + /* If one type is a vector type, return that type. (How the usual + arithmetic conversions apply to the vector types extension is not + precisely specified.) */ + if (code1 == VECTOR_TYPE) + return t1; + + if (code2 == VECTOR_TYPE) + return t2; + + /* If one type is complex, form the common type of the non-complex + components, then make that complex. Use T1 or T2 if it is the + required type. */ + if (code1 == COMPLEX_TYPE || code2 == COMPLEX_TYPE) + { + tree subtype1 = code1 == COMPLEX_TYPE ? TREE_TYPE (t1) : t1; + tree subtype2 = code2 == COMPLEX_TYPE ? TREE_TYPE (t2) : t2; + tree subtype = common_type (subtype1, subtype2); + + if (code1 == COMPLEX_TYPE && TREE_TYPE (t1) == subtype) + return t1; + else if (code2 == COMPLEX_TYPE && TREE_TYPE (t2) == subtype) + return t2; + else + return build_complex_type (subtype); + } + + /* If only one is real, use it as the result. */ + + if (code1 == REAL_TYPE && code2 != REAL_TYPE) + return t1; + + if (code2 == REAL_TYPE && code1 != REAL_TYPE) + return t2; + + /* Both real or both integers; use the one with greater precision. */ + + if (TYPE_PRECISION (t1) > TYPE_PRECISION (t2)) + return t1; + else if (TYPE_PRECISION (t2) > TYPE_PRECISION (t1)) + return t2; + + /* Same precision. Prefer long longs to longs to ints when the + same precision, following the C99 rules on integer type rank + (which are equivalent to the C90 rules for C90 types). */ + + if (TYPE_MAIN_VARIANT (t1) == long_long_unsigned_type_node + || TYPE_MAIN_VARIANT (t2) == long_long_unsigned_type_node) + return long_long_unsigned_type_node; + + if (TYPE_MAIN_VARIANT (t1) == long_long_integer_type_node + || TYPE_MAIN_VARIANT (t2) == long_long_integer_type_node) + { + if (TYPE_UNSIGNED (t1) || TYPE_UNSIGNED (t2)) + return long_long_unsigned_type_node; + else + return long_long_integer_type_node; + } + + if (TYPE_MAIN_VARIANT (t1) == long_unsigned_type_node + || TYPE_MAIN_VARIANT (t2) == long_unsigned_type_node) + return long_unsigned_type_node; + + if (TYPE_MAIN_VARIANT (t1) == long_integer_type_node + || TYPE_MAIN_VARIANT (t2) == long_integer_type_node) + { + /* But preserve unsignedness from the other type, + since long cannot hold all the values of an unsigned int. */ + if (TYPE_UNSIGNED (t1) || TYPE_UNSIGNED (t2)) + return long_unsigned_type_node; + else + return long_integer_type_node; + } + + /* Likewise, prefer long double to double even if same size. */ + if (TYPE_MAIN_VARIANT (t1) == long_double_type_node + || TYPE_MAIN_VARIANT (t2) == long_double_type_node) + return long_double_type_node; + + /* Otherwise prefer the unsigned one. */ + + if (TYPE_UNSIGNED (t1)) + return t1; + else + return t2; +} /* Return 1 if TYPE1 and TYPE2 are compatible types for assignment or various other operations. Return 2 if they are compatible but a warning may be needed if you use them together. */ int -comptypes (tree type1, tree type2, int flags) +comptypes (tree type1, tree type2) { tree t1 = type1; tree t2 = type2; @@ -506,9 +630,10 @@ comptypes (tree type1, tree type2, int flags) /* Different classes of types can't be compatible. */ - if (TREE_CODE (t1) != TREE_CODE (t2)) return 0; + if (TREE_CODE (t1) != TREE_CODE (t2)) + return 0; - /* Qualifiers must match. */ + /* Qualifiers must match. C99 6.7.3p9 */ if (TYPE_QUALS (t1) != TYPE_QUALS (t2)) return 0; @@ -521,7 +646,7 @@ comptypes (tree type1, tree type2, int flags) return 1; /* 1 if no need for warning yet, 2 if warning cause has been seen. */ - if (! (attrval = targetm.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. */ @@ -535,11 +660,11 @@ comptypes (tree type1, tree type2, int flags) if (c_dialect_objc () && (val = objc_comptypes (t1, t2, 0)) >= 0) break; val = (TREE_TYPE (t1) == TREE_TYPE (t2) - ? 1 : comptypes (TREE_TYPE (t1), TREE_TYPE (t2), flags)); + ? 1 : comptypes (TREE_TYPE (t1), TREE_TYPE (t2))); break; case FUNCTION_TYPE: - val = function_types_compatible_p (t1, t2, flags); + val = function_types_compatible_p (t1, t2); break; case ARRAY_TYPE: @@ -552,21 +677,20 @@ comptypes (tree type1, tree type2, int flags) /* Target types must match incl. qualifiers. */ if (TREE_TYPE (t1) != TREE_TYPE (t2) - && 0 == (val = comptypes (TREE_TYPE (t1), TREE_TYPE (t2), - flags))) + && 0 == (val = comptypes (TREE_TYPE (t1), TREE_TYPE (t2)))) return 0; /* Sizes must match unless one is missing or variable. */ if (d1 == 0 || d2 == 0 || d1 == d2) break; - d1_zero = ! TYPE_MAX_VALUE (d1); - d2_zero = ! TYPE_MAX_VALUE (d2); + d1_zero = !TYPE_MAX_VALUE (d1); + d2_zero = !TYPE_MAX_VALUE (d2); - d1_variable = (! d1_zero + d1_variable = (!d1_zero && (TREE_CODE (TYPE_MIN_VALUE (d1)) != INTEGER_CST || TREE_CODE (TYPE_MAX_VALUE (d1)) != INTEGER_CST)); - d2_variable = (! d2_zero + d2_variable = (!d2_zero && (TREE_CODE (TYPE_MIN_VALUE (d2)) != INTEGER_CST || TREE_CODE (TYPE_MAX_VALUE (d2)) != INTEGER_CST)); @@ -575,8 +699,8 @@ comptypes (tree type1, tree type2, int flags) 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))) + || !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; break; @@ -591,12 +715,12 @@ comptypes (tree type1, tree type2, int flags) case ENUMERAL_TYPE: case UNION_TYPE: if (val != 1 && !same_translation_unit_p (t1, t2)) - val = tagged_types_tu_compatible_p (t1, t2, flags); + val = tagged_types_tu_compatible_p (t1, t2); break; case VECTOR_TYPE: val = TYPE_VECTOR_SUBPARTS (t1) == TYPE_VECTOR_SUBPARTS (t2) - && comptypes (TREE_TYPE (t1), TREE_TYPE (t2), 0); + && comptypes (TREE_TYPE (t1), TREE_TYPE (t2)); break; default: @@ -622,7 +746,7 @@ comp_target_types (tree ttl, tree ttr, int reflexive) return val; val = comptypes (TYPE_MAIN_VARIANT (TREE_TYPE (ttl)), - TYPE_MAIN_VARIANT (TREE_TYPE (ttr)), COMPARE_STRICT); + TYPE_MAIN_VARIANT (TREE_TYPE (ttr))); if (val == 2 && pedantic) pedwarn ("types are not quite compatible"); @@ -641,19 +765,25 @@ same_translation_unit_p (tree t1, tree t2) while (t1 && TREE_CODE (t1) != TRANSLATION_UNIT_DECL) switch (TREE_CODE_CLASS (TREE_CODE (t1))) { - case 'd': t1 = DECL_CONTEXT (t1); break; - case 't': t1 = TYPE_CONTEXT (t1); break; - case 'x': t1 = BLOCK_SUPERCONTEXT (t1); break; /* assume block */ - default: abort (); + case tcc_declaration: + t1 = DECL_CONTEXT (t1); break; + case tcc_type: + t1 = TYPE_CONTEXT (t1); break; + case tcc_exceptional: + t1 = BLOCK_SUPERCONTEXT (t1); break; /* assume block */ + default: gcc_unreachable (); } while (t2 && TREE_CODE (t2) != TRANSLATION_UNIT_DECL) switch (TREE_CODE_CLASS (TREE_CODE (t2))) { - case 'd': t2 = DECL_CONTEXT (t2); break; - case 't': t2 = TYPE_CONTEXT (t2); break; - case 'x': t2 = BLOCK_SUPERCONTEXT (t2); break; /* assume block */ - default: abort (); + case tcc_declaration: + t2 = DECL_CONTEXT (t2); break; + case tcc_type: + t2 = TYPE_CONTEXT (t2); break; + case tcc_exceptional: + t2 = BLOCK_SUPERCONTEXT (t2); break; /* assume block */ + default: gcc_unreachable (); } return t1 == t2; @@ -682,11 +812,11 @@ static const struct tagged_tu_seen * tagged_tu_seen_base; rules. */ static int -tagged_types_tu_compatible_p (tree t1, tree t2, int flags) +tagged_types_tu_compatible_p (tree t1, tree t2) { tree s1, s2; bool needs_warning = false; - + /* We have to verify that the tags of the types are the same. This is harder than it looks because this may be a typedef, so we have to go look at the original type. It may even be a typedef of a @@ -706,33 +836,33 @@ tagged_types_tu_compatible_p (tree t1, tree t2, int flags) /* C90 didn't have the requirement that the two tags be the same. */ if (flag_isoc99 && TYPE_NAME (t1) != TYPE_NAME (t2)) return 0; - + /* C90 didn't say what happened if one or both of the types were incomplete; we choose to follow C99 rules here, which is that they are compatible. */ if (TYPE_SIZE (t1) == NULL || TYPE_SIZE (t2) == NULL) return 1; - + { const struct tagged_tu_seen * tts_i; for (tts_i = tagged_tu_seen_base; tts_i != NULL; tts_i = tts_i->next) if (tts_i->t1 == t1 && tts_i->t2 == t2) return 1; } - + switch (TREE_CODE (t1)) { case ENUMERAL_TYPE: { - + /* Speed up the case where the type values are in the same order. */ tree tv1 = TYPE_VALUES (t1); tree tv2 = TYPE_VALUES (t2); - + if (tv1 == tv2) return 1; - + for (;tv1 && tv2; tv1 = TREE_CHAIN (tv1), tv2 = TREE_CHAIN (tv2)) { if (TREE_PURPOSE (tv1) != TREE_PURPOSE (tv2)) @@ -740,15 +870,15 @@ tagged_types_tu_compatible_p (tree t1, tree t2, int flags) if (simple_cst_equal (TREE_VALUE (tv1), TREE_VALUE (tv2)) != 1) return 0; } - + if (tv1 == NULL_TREE && tv2 == NULL_TREE) return 1; if (tv1 == NULL_TREE || tv2 == NULL_TREE) return 0; - + if (list_length (TYPE_VALUES (t1)) != list_length (TYPE_VALUES (t2))) return 0; - + for (s1 = TYPE_VALUES (t1); s1; s1 = TREE_CHAIN (s1)) { s2 = purpose_member (TREE_PURPOSE (s1), TYPE_VALUES (t2)); @@ -773,18 +903,18 @@ tagged_types_tu_compatible_p (tree t1, tree t2, int flags) tts.t1 = t1; tts.t2 = t2; tagged_tu_seen_base = &tts; - + if (DECL_NAME (s1) != NULL) - for (s2 = TYPE_VALUES (t2); s2; s2 = TREE_CHAIN (s2)) + for (s2 = TYPE_FIELDS (t2); s2; s2 = TREE_CHAIN (s2)) if (DECL_NAME (s1) == DECL_NAME (s2)) { int result; - result = comptypes (TREE_TYPE (s1), TREE_TYPE (s2), flags); + result = comptypes (TREE_TYPE (s1), TREE_TYPE (s2)); if (result == 0) break; if (result == 2) needs_warning = true; - + if (TREE_CODE (s1) == FIELD_DECL && simple_cst_equal (DECL_FIELD_BIT_OFFSET (s1), DECL_FIELD_BIT_OFFSET (s2)) != 1) @@ -794,7 +924,7 @@ tagged_types_tu_compatible_p (tree t1, tree t2, int flags) break; } tagged_tu_seen_base = tts.next; - if (! ok) + if (!ok) return 0; } return needs_warning ? 2 : 1; @@ -803,13 +933,13 @@ tagged_types_tu_compatible_p (tree t1, tree t2, int flags) case RECORD_TYPE: { struct tagged_tu_seen tts; - + tts.next = tagged_tu_seen_base; tts.t1 = t1; tts.t2 = t2; tagged_tu_seen_base = &tts; - - for (s1 = TYPE_FIELDS (t1), s2 = TYPE_FIELDS (t2); + + for (s1 = TYPE_FIELDS (t1), s2 = TYPE_FIELDS (t2); s1 && s2; s1 = TREE_CHAIN (s1), s2 = TREE_CHAIN (s2)) { @@ -817,12 +947,12 @@ tagged_types_tu_compatible_p (tree t1, tree t2, int flags) if (TREE_CODE (s1) != TREE_CODE (s2) || DECL_NAME (s1) != DECL_NAME (s2)) break; - result = comptypes (TREE_TYPE (s1), TREE_TYPE (s2), flags); + result = comptypes (TREE_TYPE (s1), TREE_TYPE (s2)); if (result == 0) break; if (result == 2) needs_warning = true; - + if (TREE_CODE (s1) == FIELD_DECL && simple_cst_equal (DECL_FIELD_BIT_OFFSET (s1), DECL_FIELD_BIT_OFFSET (s2)) != 1) @@ -835,7 +965,7 @@ tagged_types_tu_compatible_p (tree t1, tree t2, int flags) } default: - abort (); + gcc_unreachable (); } } @@ -847,7 +977,7 @@ tagged_types_tu_compatible_p (tree t1, tree t2, int flags) Otherwise, the argument types must match. */ static int -function_types_compatible_p (tree f1, tree f2, int flags) +function_types_compatible_p (tree f1, tree f2) { tree args1, args2; /* 1 if no need for warning yet, 2 if warning cause has been seen. */ @@ -858,17 +988,17 @@ function_types_compatible_p (tree f1, tree f2, int flags) ret1 = TREE_TYPE (f1); ret2 = TREE_TYPE (f2); - /* 'volatile' qualifiers on a function's return type mean the function - is noreturn. */ - if (pedantic && TYPE_VOLATILE (ret1) != TYPE_VOLATILE (ret2)) - pedwarn ("function return types not compatible due to `volatile'"); + /* 'volatile' qualifiers on a function's return type used to mean + the function is noreturn. */ + if (TYPE_VOLATILE (ret1) != TYPE_VOLATILE (ret2)) + pedwarn ("function return types not compatible due to %"); if (TYPE_VOLATILE (ret1)) ret1 = build_qualified_type (TYPE_MAIN_VARIANT (ret1), TYPE_QUALS (ret1) & ~TYPE_QUAL_VOLATILE); if (TYPE_VOLATILE (ret2)) ret2 = build_qualified_type (TYPE_MAIN_VARIANT (ret2), TYPE_QUALS (ret2) & ~TYPE_QUAL_VOLATILE); - val = comptypes (ret1, ret2, flags); + val = comptypes (ret1, ret2); if (val == 0) return 0; @@ -886,8 +1016,7 @@ function_types_compatible_p (tree f1, tree f2, int flags) compare that with the other type's arglist. If they don't match, ask for a warning (but no error). */ if (TYPE_ACTUAL_ARG_TYPES (f1) - && 1 != type_lists_compatible_p (args2, TYPE_ACTUAL_ARG_TYPES (f1), - flags)) + && 1 != type_lists_compatible_p (args2, TYPE_ACTUAL_ARG_TYPES (f1))) val = 2; return val; } @@ -896,14 +1025,13 @@ function_types_compatible_p (tree f1, tree f2, int flags) if (!self_promoting_args_p (args1)) return 0; if (TYPE_ACTUAL_ARG_TYPES (f2) - && 1 != type_lists_compatible_p (args1, TYPE_ACTUAL_ARG_TYPES (f2), - flags)) + && 1 != type_lists_compatible_p (args1, TYPE_ACTUAL_ARG_TYPES (f2))) val = 2; return val; } /* Both types have argument lists: compare them and propagate results. */ - val1 = type_lists_compatible_p (args1, args2, flags); + val1 = type_lists_compatible_p (args1, args2); return val1 != 1 ? val1 : val; } @@ -912,7 +1040,7 @@ function_types_compatible_p (tree f1, tree f2, int flags) or 2 for compatible with warning. */ static int -type_lists_compatible_p (tree args1, tree args2, int flags) +type_lists_compatible_p (tree args1, tree args2) { /* 1 if no need for warning yet, 2 if warning cause has been seen. */ int val = 1; @@ -944,9 +1072,8 @@ type_lists_compatible_p (tree args1, tree args2, int flags) else if (TREE_CODE (TREE_VALUE (args1)) == ERROR_MARK || TREE_CODE (TREE_VALUE (args2)) == ERROR_MARK) ; - else if (! (newval = comptypes (TYPE_MAIN_VARIANT (TREE_VALUE (args1)), - TYPE_MAIN_VARIANT (TREE_VALUE (args2)), - flags))) + 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. */ @@ -960,8 +1087,7 @@ type_lists_compatible_p (tree args1, tree args2, int flags) tree memb; for (memb = TYPE_FIELDS (TREE_VALUE (args1)); memb; memb = TREE_CHAIN (memb)) - if (comptypes (TREE_TYPE (memb), TREE_VALUE (args2), - flags)) + if (comptypes (TREE_TYPE (memb), TREE_VALUE (args2))) break; if (memb == 0) return 0; @@ -976,8 +1102,7 @@ type_lists_compatible_p (tree args1, tree args2, int flags) tree memb; for (memb = TYPE_FIELDS (TREE_VALUE (args2)); memb; memb = TREE_CHAIN (memb)) - if (comptypes (TREE_TYPE (memb), TREE_VALUE (args1), - flags)) + if (comptypes (TREE_TYPE (memb), TREE_VALUE (args1))) break; if (memb == 0) return 0; @@ -1027,7 +1152,7 @@ decl_constant_value (tree decl) isn't valid for a PARM_DECL. */ current_function_decl != 0 && TREE_CODE (decl) != PARM_DECL - && ! TREE_THIS_VOLATILE (decl) + && !TREE_THIS_VOLATILE (decl) && TREE_READONLY (decl) && DECL_INITIAL (decl) != 0 && TREE_CODE (DECL_INITIAL (decl)) != ERROR_MARK @@ -1086,9 +1211,8 @@ default_function_array_conversion (tree 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)); + if (TREE_NO_WARNING (orig_exp)) + TREE_NO_WARNING (exp) = 1; if (code == FUNCTION_TYPE) { @@ -1103,7 +1227,7 @@ default_function_array_conversion (tree exp) int volatilep = 0; int lvalue_array_p; - if (TREE_CODE_CLASS (TREE_CODE (exp)) == 'r' || DECL_P (exp)) + if (REFERENCE_CLASS_P (exp) || DECL_P (exp)) { constp = TREE_READONLY (exp); volatilep = TREE_THIS_VOLATILE (exp); @@ -1117,14 +1241,14 @@ default_function_array_conversion (tree exp) | (volatilep * TYPE_QUAL_VOLATILE)); if (TREE_CODE (exp) == INDIRECT_REF) - return convert (TYPE_POINTER_TO (restype), + return convert (build_pointer_type (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); + return build2 (COMPOUND_EXPR, TREE_TYPE (op1), + TREE_OPERAND (exp, 0), op1); } lvalue_array_p = !not_lvalue && lvalue_p (exp); @@ -1141,10 +1265,10 @@ default_function_array_conversion (tree exp) 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? */ + /* We are making an ADDR_EXPR of ptrtype. This is a valid + ADDR_EXPR because it's the best way of representing what + happens in C when we take the address of an array and place + it in a pointer to the element type. */ adr = build1 (ADDR_EXPR, ptrtype, exp); if (!c_mark_addressable (exp)) return error_mark_node; @@ -1198,9 +1322,8 @@ default_conversion (tree exp) && 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)); + if (TREE_NO_WARNING (orig_exp)) + TREE_NO_WARNING (exp) = 1; /* Normally convert enums to int, but convert wide enums to something wider. */ @@ -1347,25 +1470,8 @@ build_component_ref (tree datum, tree component) tree field = NULL; tree ref; - /* If DATUM is a COMPOUND_EXPR, move our reference inside it. - 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), non_lvalue (value)); - } - default: - break; - } + if (!objc_is_public (datum, component)) + return error_mark_node; /* See if there is a field or component with name COMPONENT. */ @@ -1381,8 +1487,7 @@ build_component_ref (tree datum, tree component) if (!field) { - error ("%s has no member named `%s'", - code == RECORD_TYPE ? "structure" : "union", + error ("%qT has no member named %qs", type, IDENTIFIER_POINTER (component)); return error_mark_node; } @@ -1399,7 +1504,8 @@ build_component_ref (tree datum, tree component) if (TREE_TYPE (subdatum) == error_mark_node) return error_mark_node; - ref = build (COMPONENT_REF, TREE_TYPE (subdatum), datum, subdatum); + ref = build3 (COMPONENT_REF, TREE_TYPE (subdatum), datum, subdatum, + NULL_TREE); if (TREE_READONLY (datum) || TREE_READONLY (subdatum)) TREE_READONLY (ref) = 1; if (TREE_THIS_VOLATILE (datum) || TREE_THIS_VOLATILE (subdatum)) @@ -1417,7 +1523,7 @@ build_component_ref (tree datum, tree component) return ref; } else if (code != ERROR_MARK) - error ("request for member `%s' in something not a structure or union", + error ("request for member %qs in something not a structure or union", IDENTIFIER_POINTER (component)); return error_mark_node; @@ -1450,7 +1556,7 @@ build_indirect_ref (tree ptr, const char *errorstring) return error_mark_node; } if (VOID_TYPE_P (t) && skip_evaluation == 0) - warning ("dereferencing `void *' pointer"); + warning ("dereferencing % pointer"); /* We *must* set TREE_READONLY when dereferencing a pointer to const, so that we get the proper error message if the result is used @@ -1467,7 +1573,7 @@ build_indirect_ref (tree ptr, const char *errorstring) } } else if (TREE_CODE (pointer) != ERROR_MARK) - error ("invalid type argument of `%s'", errorstring); + error ("invalid type argument of %qs", errorstring); return error_mark_node; } @@ -1505,7 +1611,7 @@ build_array_ref (tree array, tree index) must have done so deliberately. */ if (warn_char_subscripts && TYPE_MAIN_VARIANT (TREE_TYPE (index)) == char_type_node) - warning ("array subscript has type `char'"); + warning ("array subscript has type %"); /* Apply default promotions *after* noticing character types. */ index = default_conversion (index); @@ -1534,7 +1640,7 @@ build_array_ref (tree array, tree index) to access a non-existent part of the register. */ if (TREE_CODE (index) == INTEGER_CST && TYPE_DOMAIN (TREE_TYPE (array)) - && ! int_fits_type_p (index, TYPE_DOMAIN (TREE_TYPE (array)))) + && !int_fits_type_p (index, TYPE_DOMAIN (TREE_TYPE (array)))) { if (!c_mark_addressable (array)) return error_mark_node; @@ -1546,13 +1652,13 @@ build_array_ref (tree array, tree index) while (TREE_CODE (foo) == COMPONENT_REF) foo = TREE_OPERAND (foo, 0); if (TREE_CODE (foo) == VAR_DECL && C_DECL_REGISTER (foo)) - pedwarn ("ISO C forbids subscripting `register' array"); - else if (! flag_isoc99 && ! lvalue_p (foo)) + pedwarn ("ISO C forbids subscripting % array"); + else if (!flag_isoc99 && !lvalue_p (foo)) pedwarn ("ISO C90 forbids subscripting non-lvalue array"); } type = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (array))); - rval = build (ARRAY_REF, type, array, index); + rval = build4 (ARRAY_REF, type, array, index, NULL_TREE, NULL_TREE); /* Array ref is const/volatile if the array elements are or if the array is. */ TREE_READONLY (rval) @@ -1581,7 +1687,7 @@ build_array_ref (tree array, tree index) if (warn_char_subscripts && TREE_CODE (TREE_TYPE (index)) == INTEGER_TYPE && TYPE_MAIN_VARIANT (TREE_TYPE (index)) == char_type_node) - warning ("subscript has type `char'"); + warning ("subscript has type %"); /* Put the integer in IND to simplify error checking. */ if (TREE_CODE (TREE_TYPE (ar)) == INTEGER_TYPE) @@ -1618,7 +1724,7 @@ build_external_ref (tree id, int fun) { tree ref; tree decl = lookup_name (id); - tree objc_ivar = lookup_objc_ivar (id); + tree objc_ivar = objc_lookup_ivar (id); if (decl && decl != error_mark_node) { @@ -1627,7 +1733,7 @@ build_external_ref (tree id, int fun) ref = decl; else if (decl != objc_ivar && !DECL_FILE_SCOPE_P (decl)) { - warning ("local declaration of `%s' hides instance variable", + warning ("local declaration of %qs hides instance variable", IDENTIFIER_POINTER (id)); ref = decl; } @@ -1659,6 +1765,16 @@ build_external_ref (tree id, int fun) assemble_external (ref); TREE_USED (ref) = 1; + if (TREE_CODE (ref) == FUNCTION_DECL && !in_alignof) + { + if (!in_sizeof && !in_typeof) + C_DECL_USED (ref) = 1; + else if (DECL_INITIAL (ref) == 0 + && DECL_EXTERNAL (ref) + && !TREE_PUBLIC (ref)) + record_maybe_used_decl (ref); + } + if (TREE_CODE (ref) == CONST_DECL) { ref = DECL_INITIAL (ref); @@ -1680,6 +1796,95 @@ build_external_ref (tree id, int fun) return ref; } +/* Record details of decls possibly used inside sizeof or typeof. */ +struct maybe_used_decl +{ + /* The decl. */ + tree decl; + /* The level seen at (in_sizeof + in_typeof). */ + int level; + /* The next one at this level or above, or NULL. */ + struct maybe_used_decl *next; +}; + +static struct maybe_used_decl *maybe_used_decls; + +/* Record that DECL, an undefined static function reference seen + inside sizeof or typeof, might be used if the operand of sizeof is + a VLA type or the operand of typeof is a variably modified + type. */ + +void +record_maybe_used_decl (tree decl) +{ + struct maybe_used_decl *t = XOBNEW (&parser_obstack, struct maybe_used_decl); + t->decl = decl; + t->level = in_sizeof + in_typeof; + t->next = maybe_used_decls; + maybe_used_decls = t; +} + +/* Pop the stack of decls possibly used inside sizeof or typeof. If + USED is false, just discard them. If it is true, mark them used + (if no longer inside sizeof or typeof) or move them to the next + level up (if still inside sizeof or typeof). */ + +void +pop_maybe_used (bool used) +{ + struct maybe_used_decl *p = maybe_used_decls; + int cur_level = in_sizeof + in_typeof; + while (p && p->level > cur_level) + { + if (used) + { + if (cur_level == 0) + C_DECL_USED (p->decl) = 1; + else + p->level = cur_level; + } + p = p->next; + } + if (!used || cur_level == 0) + maybe_used_decls = p; +} + +/* Return the result of sizeof applied to EXPR. */ + +struct c_expr +c_expr_sizeof_expr (struct c_expr expr) +{ + struct c_expr ret; + if (expr.value == error_mark_node) + { + ret.value = error_mark_node; + ret.original_code = ERROR_MARK; + pop_maybe_used (false); + } + else + { + ret.value = c_sizeof (TREE_TYPE (expr.value)); + ret.original_code = ERROR_MARK; + pop_maybe_used (C_TYPE_VARIABLE_SIZE (TREE_TYPE (expr.value))); + } + return ret; +} + +/* Return the result of sizeof applied to T, a structure for the type + name passed to sizeof (rather than the type itself). */ + +struct c_expr +c_expr_sizeof_type (struct c_type_name *t) +{ + tree type; + struct c_expr ret; + type = groktypename (t); + ret.value = c_sizeof (type); + ret.original_code = ERROR_MARK; + pop_maybe_used (C_TYPE_VARIABLE_SIZE (type)); + return ret; +} + /* Build a function call to function FUNCTION with parameters PARAMS. PARAMS is a list--a chain of TREE_LIST nodes--in which the TREE_VALUE of each node is a parameter-expression. @@ -1721,7 +1926,7 @@ build_function_call (tree function, tree params) if (!(TREE_CODE (fntype) == POINTER_TYPE && TREE_CODE (TREE_TYPE (fntype)) == FUNCTION_TYPE)) { - error ("called object is not a function"); + error ("called object %qE is not a function", function); return error_mark_node; } @@ -1740,11 +1945,11 @@ build_function_call (tree function, tree params) ??? This doesn't work for Objective-C because objc_comptypes refuses to compare function prototypes, yet the compiler appears to build calls that are flagged as invalid by C's comptypes. */ - if (! c_dialect_objc () + if (!c_dialect_objc () && TREE_CODE (function) == NOP_EXPR && TREE_CODE (tem = TREE_OPERAND (function, 0)) == ADDR_EXPR && TREE_CODE (tem = TREE_OPERAND (tem, 0)) == FUNCTION_DECL - && ! comptypes (fntype, TREE_TYPE (tem), COMPARE_STRICT)) + && !comptypes (fntype, TREE_TYPE (tem))) { tree return_type = TREE_TYPE (fntype); tree trap = build_function_call (built_in_decls[BUILT_IN_TRAP], @@ -1772,7 +1977,7 @@ build_function_call (tree function, tree params) else rhs = fold (build1 (NOP_EXPR, return_type, integer_zero_node)); - return build (COMPOUND_EXPR, return_type, trap, rhs); + return build2 (COMPOUND_EXPR, return_type, trap, rhs); } } @@ -1780,30 +1985,30 @@ build_function_call (tree function, tree params) function prototype, or apply default promotions. */ coerced_params - = convert_arguments (TYPE_ARG_TYPES (fntype), params, name, fundecl); + = convert_arguments (TYPE_ARG_TYPES (fntype), params, function, fundecl); + + if (coerced_params == error_mark_node) + return error_mark_node; /* Check that the arguments to the function are valid. */ check_function_arguments (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 - to do something useful. */ + result = build3 (CALL_EXPR, TREE_TYPE (fntype), + function, coerced_params, NULL_TREE); + TREE_SIDE_EFFECTS (result) = 1; - if (TREE_CODE (function) == ADDR_EXPR - && TREE_CODE (TREE_OPERAND (function, 0)) == FUNCTION_DECL - && DECL_BUILT_IN (TREE_OPERAND (function, 0))) + if (require_constant_value) { - result = expand_tree_builtin (TREE_OPERAND (function, 0), - params, coerced_params); - if (result) - return result; - } + result = fold_initializer (result); - result = build (CALL_EXPR, TREE_TYPE (fntype), - function, coerced_params, NULL_TREE); - TREE_SIDE_EFFECTS (result) = 1; - result = fold (result); + if (TREE_CONSTANT (result) + && (name == NULL_TREE + || strncmp (IDENTIFIER_POINTER (name), "__builtin_", 10) != 0)) + pedwarn_init ("initializer element is not constant"); + } + else + result = fold (result); if (VOID_TYPE_P (TREE_TYPE (result))) return result; @@ -1812,7 +2017,8 @@ build_function_call (tree function, tree params) /* Convert the argument expressions in the list VALUES to the types in the list TYPELIST. The result is a list of converted - argument expressions. + argument expressions, unless there are too few arguments in which + case it is error_mark_node. If TYPELIST is exhausted, or when an element has NULL as its type, perform the default conversions. @@ -1821,7 +2027,8 @@ build_function_call (tree function, tree params) It may be 0, if that info is not available. It is used only for generating error messages. - NAME is an IDENTIFIER_NODE or 0. It is used only for error messages. + FUNCTION is a tree for the called function. It is used only for + error messages, where it is formatted with %qE. This is also where warnings about wrong number of args are generated. @@ -1829,11 +2036,21 @@ build_function_call (tree function, tree params) with the elements of the list in the TREE_VALUE slots of those nodes. */ static tree -convert_arguments (tree typelist, tree values, tree name, tree fundecl) +convert_arguments (tree typelist, tree values, tree function, tree fundecl) { tree typetail, valtail; tree result = NULL; int parmnum; + tree selector; + + /* Change pointer to function to the function itself for + diagnostics. */ + if (TREE_CODE (function) == ADDR_EXPR + && TREE_CODE (TREE_OPERAND (function, 0)) == FUNCTION_DECL) + function = TREE_OPERAND (function, 0); + + /* Handle an ObjC selector specially for diagnostics. */ + selector = objc_message_selector (); /* Scan the given expressions and types, producing individual converted arguments and pushing them on RESULT in reverse order. */ @@ -1844,17 +2061,21 @@ convert_arguments (tree typelist, tree values, tree name, tree fundecl) { tree type = typetail ? TREE_VALUE (typetail) : 0; tree val = TREE_VALUE (valtail); + tree rname = function; + int argnum = parmnum + 1; if (type == void_type_node) { - if (name) - error ("too many arguments to function `%s'", - IDENTIFIER_POINTER (name)); - else - error ("too many arguments to function"); + error ("too many arguments to function %qE", function); break; } + if (selector && argnum > 2) + { + rname = selector; + argnum -= 2; + } + /* Strip NON_LVALUE_EXPRs since we aren't using as an lvalue. */ /* Do not use STRIP_NOPS here! We do not want an enumerator with value 0 to convert automatically to a pointer. */ @@ -1881,26 +2102,38 @@ convert_arguments (tree typelist, tree values, tree name, tree fundecl) differ from the default conversions. */ if (warn_conversion || warn_traditional) { - int formal_prec = TYPE_PRECISION (type); + unsigned 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); + warning ("passing argument %d of %qE as integer " + "rather than floating due to prototype", + argnum, rname); 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); + warning ("passing argument %d of %qE as integer " + "rather than complex due to prototype", + argnum, rname); 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); + warning ("passing argument %d of %qE as complex " + "rather than floating due to prototype", + argnum, rname); 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); + warning ("passing argument %d of %qE as floating " + "rather than integer due to prototype", + argnum, rname); 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); + warning ("passing argument %d of %qE as complex " + "rather than integer due to prototype", + argnum, rname); 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); + warning ("passing argument %d of %qE as floating " + "rather than complex due to prototype", + argnum, rname); /* ??? At some point, messages should be written about conversions between complex types, but that's too messy to do now. */ @@ -1910,7 +2143,9 @@ convert_arguments (tree typelist, tree values, tree name, tree fundecl) /* Warn if any argument is passed as `float', since without a prototype it would be `double'. */ 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); + warning ("passing argument %d of %qE as % " + "rather than % due to prototype", + argnum, rname); } /* Detect integer changing in width or signedness. These warnings are only activated with @@ -1928,7 +2163,8 @@ convert_arguments (tree typelist, tree values, tree name, tree fundecl) and the actual arg is that enum type. */ ; else if (formal_prec != TYPE_PRECISION (type1)) - warn_for_assignment ("%s with different width due to prototype", (char *) 0, name, parmnum + 1); + warning ("passing argument %d of %qE with different " + "width due to prototype", argnum, rname); else if (TYPE_UNSIGNED (type) == TYPE_UNSIGNED (type1)) ; /* Don't complain if the formal parameter type @@ -1954,15 +2190,17 @@ convert_arguments (tree typelist, tree values, tree name, tree fundecl) && TYPE_UNSIGNED (TREE_TYPE (val))) ; else if (TYPE_UNSIGNED (type)) - warn_for_assignment ("%s as unsigned due to prototype", (char *) 0, name, parmnum + 1); + warning ("passing argument %d of %qE as unsigned " + "due to prototype", argnum, rname); else - warn_for_assignment ("%s as signed due to prototype", (char *) 0, name, parmnum + 1); + warning ("passing argument %d of %qE as signed " + "due to prototype", argnum, rname); } } - parmval = convert_for_assignment (type, val, - (char *) 0, /* arg passing */ - fundecl, name, parmnum + 1); + parmval = convert_for_assignment (type, val, ic_argpass, + fundecl, function, + parmnum + 1); if (targetm.calls.promote_prototypes (fundecl ? TREE_TYPE (fundecl) : 0) && INTEGRAL_TYPE_P (type) @@ -1986,11 +2224,8 @@ convert_arguments (tree typelist, tree values, tree name, tree fundecl) if (typetail != 0 && TREE_VALUE (typetail) != void_type_node) { - if (name) - error ("too few arguments to function `%s'", - IDENTIFIER_POINTER (name)); - else - error ("too few arguments to function"); + error ("too few arguments to function %qE", function); + return error_mark_node; } return nreverse (result); @@ -2002,28 +2237,23 @@ convert_arguments (tree typelist, tree values, tree name, tree fundecl) we check for operands that were written with other binary operators in a way that is likely to confuse the user. */ -tree -parser_build_binary_op (enum tree_code code, tree arg1, tree arg2) +struct c_expr +parser_build_binary_op (enum tree_code code, struct c_expr arg1, + struct c_expr arg2) { - tree result = build_binary_op (code, arg1, arg2, 1); + struct c_expr result; - char class; - char class1 = TREE_CODE_CLASS (TREE_CODE (arg1)); - char class2 = TREE_CODE_CLASS (TREE_CODE (arg2)); - enum tree_code code1 = ERROR_MARK; - enum tree_code code2 = ERROR_MARK; + enum tree_code code1 = arg1.original_code; + enum tree_code code2 = arg2.original_code; - if (TREE_CODE (result) == ERROR_MARK) - return error_mark_node; + result.value = build_binary_op (code, arg1.value, arg2.value, 1); + result.original_code = code; - if (IS_EXPR_CODE_CLASS (class1)) - code1 = C_EXP_ORIGINAL_CODE (arg1); - if (IS_EXPR_CODE_CLASS (class2)) - code2 = C_EXP_ORIGINAL_CODE (arg2); + if (TREE_CODE (result.value) == ERROR_MARK) + return result; /* Check for cases such as x+y< used in subtraction"); if (TREE_CODE (target_type) == FUNCTION_TYPE) pedwarn ("pointer to a function used in subtraction"); } @@ -2192,7 +2390,7 @@ pointer_diff (tree op0, tree op1) op1 = c_size_in_bytes (target_type); /* Divide by the size, in easiest possible way. */ - return fold (build (EXACT_DIV_EXPR, restype, op0, convert (restype, op1))); + return fold (build2 (EXACT_DIV_EXPR, restype, op0, convert (restype, op1))); } /* Construct and perhaps optimize a tree representation @@ -2226,7 +2424,8 @@ build_unary_op (enum tree_code code, tree xarg, int flag) is enough to prevent anybody from looking inside for associativity, but won't generate any code. */ if (!(typecode == INTEGER_TYPE || typecode == REAL_TYPE - || typecode == COMPLEX_TYPE)) + || typecode == COMPLEX_TYPE + || typecode == VECTOR_TYPE)) { error ("wrong type argument to unary plus"); return error_mark_node; @@ -2258,7 +2457,7 @@ build_unary_op (enum tree_code code, tree xarg, int flag) { code = CONJ_EXPR; if (pedantic) - pedwarn ("ISO C does not support `~' for complex conjugation"); + pedwarn ("ISO C does not support %<~%> for complex conjugation"); if (!noconvert) arg = default_conversion (arg); } @@ -2335,13 +2534,14 @@ build_unary_op (enum tree_code code, tree xarg, int flag) tree real, imag; if (pedantic) - pedwarn ("ISO C does not support `++' and `--' on complex types"); + pedwarn ("ISO C does not support %<++%> and %<--%>" + " on complex types"); arg = stabilize_reference (arg); real = build_unary_op (REALPART_EXPR, arg, 1); imag = build_unary_op (IMAGPART_EXPR, arg, 1); - return build (COMPLEX_EXPR, TREE_TYPE (arg), - build_unary_op (code, real, 1), imag); + return build2 (COMPLEX_EXPR, TREE_TYPE (arg), + build_unary_op (code, real, 1), imag); } /* Report invalid types. */ @@ -2397,8 +2597,8 @@ build_unary_op (enum tree_code code, tree xarg, int flag) /* Complain about anything else that is not a true lvalue. */ if (!lvalue_or_else (arg, ((code == PREINCREMENT_EXPR || code == POSTINCREMENT_EXPR) - ? "invalid lvalue in increment" - : "invalid lvalue in decrement"))) + ? lv_increment + : lv_decrement))) return error_mark_node; /* Report a read-only lvalue. */ @@ -2406,12 +2606,12 @@ build_unary_op (enum tree_code code, tree xarg, int flag) readonly_error (arg, ((code == PREINCREMENT_EXPR || code == POSTINCREMENT_EXPR) - ? "increment" : "decrement")); + ? lv_increment : lv_decrement)); if (TREE_CODE (TREE_TYPE (arg)) == BOOLEAN_TYPE) val = boolean_increment (code, arg); else - val = build (code, TREE_TYPE (arg), arg, inc); + val = build2 (code, TREE_TYPE (arg), arg, inc); TREE_SIDE_EFFECTS (val) = 1; val = convert (result_type, val); if (TREE_CODE (val) != code) @@ -2443,7 +2643,7 @@ build_unary_op (enum tree_code code, tree xarg, int flag) /* Anything not already handled and not a true memory reference or a non-lvalue array is an error. */ else if (typecode != FUNCTION_TYPE && !flag - && !lvalue_or_else (arg, "invalid lvalue in unary `&'")) + && !lvalue_or_else (arg, lv_addressof)) return error_mark_node; /* Ordinary case; arg is a COMPONENT_REF or a decl. */ @@ -2453,42 +2653,38 @@ build_unary_op (enum tree_code code, tree xarg, int flag) to which the address will point. Note that you can't get a restricted pointer by taking the address of something, so we only have to deal with `const' and `volatile' here. */ - if ((DECL_P (arg) || TREE_CODE_CLASS (TREE_CODE (arg)) == 'r') + if ((DECL_P (arg) || REFERENCE_CLASS_P (arg)) && (TREE_READONLY (arg) || TREE_THIS_VOLATILE (arg))) argtype = c_build_type_variant (argtype, TREE_READONLY (arg), TREE_THIS_VOLATILE (arg)); - argtype = build_pointer_type (argtype); - if (!c_mark_addressable (arg)) return error_mark_node; - { - tree addr; + if (TREE_CODE (arg) == COMPONENT_REF + && DECL_C_BIT_FIELD (TREE_OPERAND (arg, 1))) + { + error ("attempt to take address of bit-field structure member %qD", + TREE_OPERAND (arg, 1)); + return error_mark_node; + } - if (TREE_CODE (arg) == COMPONENT_REF) - { - tree field = TREE_OPERAND (arg, 1); + argtype = build_pointer_type (argtype); - addr = build_unary_op (ADDR_EXPR, TREE_OPERAND (arg, 0), flag); + /* ??? Cope with user tricks that amount to offsetof. Delete this + when we have proper support for integer constant expressions. */ + val = get_base_address (arg); + if (val && TREE_CODE (val) == INDIRECT_REF + && integer_zerop (TREE_OPERAND (val, 0))) + return fold_convert (argtype, fold_offsetof (arg)); - if (DECL_C_BIT_FIELD (field)) - { - error ("attempt to take address of bit-field structure member `%s'", - IDENTIFIER_POINTER (DECL_NAME (field))); - return error_mark_node; - } + val = build1 (ADDR_EXPR, argtype, arg); - addr = fold (build (PLUS_EXPR, argtype, - convert (argtype, addr), - convert (argtype, byte_position (field)))); - } - else - addr = build1 (code, argtype, arg); + if (TREE_CODE (arg) == COMPOUND_LITERAL_EXPR) + TREE_INVARIANT (val) = TREE_CONSTANT (val) = 1; - return addr; - } + return val; default: break; @@ -2496,7 +2692,8 @@ build_unary_op (enum tree_code code, tree xarg, int flag) if (argtype == 0) argtype = TREE_TYPE (arg); - return fold (build1 (code, argtype, arg)); + val = build1 (code, argtype, arg); + return require_constant_value ? fold_initializer (val) : fold (val); } /* Return nonzero if REF is an lvalue valid for this language. @@ -2529,7 +2726,6 @@ lvalue_p (tree ref) && TREE_CODE (TREE_TYPE (ref)) != METHOD_TYPE); case BIND_EXPR: - case RTL_EXPR: return TREE_CODE (TREE_TYPE (ref)) == ARRAY_TYPE; default: @@ -2538,38 +2734,73 @@ lvalue_p (tree ref) } /* Return nonzero if REF is an lvalue valid for this language; - otherwise, print an error message and return zero. */ + otherwise, print an error message and return zero. USE says + how the lvalue is being used and so selects the error message. */ -int -lvalue_or_else (tree ref, const char *msgid) +static int +lvalue_or_else (tree ref, enum lvalue_use use) { int win = lvalue_p (ref); - if (! win) - error ("%s", msgid); + if (!win) + { + switch (use) + { + case lv_assign: + error ("invalid lvalue in assignment"); + break; + case lv_increment: + error ("invalid lvalue in increment"); + break; + case lv_decrement: + error ("invalid lvalue in decrement"); + break; + case lv_addressof: + error ("invalid lvalue in unary %<&%>"); + break; + case lv_asm: + error ("invalid lvalue in asm statement"); + break; + default: + gcc_unreachable (); + } + } return win; } -/* Warn about storing in something that is `const'. */ +/* Give an error for storing in something that is 'const'. */ -void -readonly_error (tree arg, const char *msgid) +static void +readonly_error (tree arg, enum lvalue_use use) { + gcc_assert (use == lv_assign || use == lv_increment || use == lv_decrement); + /* Using this macro rather than (for example) arrays of messages + ensures that all the format strings are checked at compile + time. */ +#define READONLY_MSG(A, I, D) (use == lv_assign \ + ? (A) \ + : (use == lv_increment ? (I) : (D))) if (TREE_CODE (arg) == COMPONENT_REF) { if (TYPE_READONLY (TREE_TYPE (TREE_OPERAND (arg, 0)))) - readonly_error (TREE_OPERAND (arg, 0), msgid); + readonly_error (TREE_OPERAND (arg, 0), use); else - error ("%s of read-only member `%s'", _(msgid), + error (READONLY_MSG (N_("assignment of read-only member %qs"), + N_("increment of read-only member %qs"), + N_("decrement of read-only member %qs")), IDENTIFIER_POINTER (DECL_NAME (TREE_OPERAND (arg, 1)))); } else if (TREE_CODE (arg) == VAR_DECL) - error ("%s of read-only variable `%s'", _(msgid), + error (READONLY_MSG (N_("assignment of read-only variable %qs"), + N_("increment of read-only variable %qs"), + N_("decrement of read-only variable %qs")), IDENTIFIER_POINTER (DECL_NAME (arg))); else - error ("%s of read-only location", _(msgid)); + error (READONLY_MSG (N_("assignment of read-only location"), + N_("increment of read-only location"), + N_("decrement of read-only location"))); } /* Mark EXP saying that we need to be able to take the @@ -2587,7 +2818,7 @@ c_mark_addressable (tree exp) case COMPONENT_REF: if (DECL_C_BIT_FIELD (TREE_OPERAND (x, 1))) { - error ("cannot take address of bit-field `%s'", + error ("cannot take address of bit-field %qs", IDENTIFIER_POINTER (DECL_NAME (TREE_OPERAND (x, 1)))); return false; } @@ -2615,26 +2846,25 @@ c_mark_addressable (tree exp) { if (TREE_PUBLIC (x) || TREE_STATIC (x) || DECL_EXTERNAL (x)) { - error ("global register variable `%s' used in nested function", + error ("global register variable %qs used in nested function", IDENTIFIER_POINTER (DECL_NAME (x))); return false; } - pedwarn ("register variable `%s' used in nested function", + pedwarn ("register variable %qs used in nested function", IDENTIFIER_POINTER (DECL_NAME (x))); } else if (C_DECL_REGISTER (x)) { if (TREE_PUBLIC (x) || TREE_STATIC (x) || DECL_EXTERNAL (x)) { - error ("address of global register variable `%s' requested", + error ("address of global register variable %qs requested", IDENTIFIER_POINTER (DECL_NAME (x))); return false; } - pedwarn ("address of register variable `%s' requested", + pedwarn ("address of register variable %qs requested", IDENTIFIER_POINTER (DECL_NAME (x))); } - put_var_into_stack (x, /*rescan=*/true); /* drops in */ case FUNCTION_DECL: @@ -2715,13 +2945,13 @@ build_conditional_expr (tree ifexp, tree op1, tree op2) /* Do not warn if the result type is signed, since the signed type will only be chosen if it can represent all the values of the unsigned type. */ - if (! TYPE_UNSIGNED (result_type)) + if (!TYPE_UNSIGNED (result_type)) /* OK */; /* Do not warn if the signed quantity is an unsuffixed integer literal (or some static constant expression involving such literals) and it is non-negative. */ - else if ((unsigned_op2 && c_tree_expr_nonnegative_p (op1)) - || (unsigned_op1 && c_tree_expr_nonnegative_p (op2))) + else if ((unsigned_op2 && tree_expr_nonnegative_p (op1)) + || (unsigned_op1 && tree_expr_nonnegative_p (op2))) /* OK */; else warning ("signed and unsigned type in conditional expression"); @@ -2737,7 +2967,7 @@ build_conditional_expr (tree ifexp, tree op1, tree op2) else if (code1 == POINTER_TYPE && code2 == POINTER_TYPE) { if (comp_target_types (type1, type2, 1)) - result_type = common_type (type1, type2); + result_type = common_pointer_type (type1, type2); else if (integer_zerop (op1) && TREE_TYPE (type1) == void_type_node && TREE_CODE (orig_op1) != NOP_EXPR) result_type = qualify_type (type2, type1); @@ -2747,14 +2977,16 @@ build_conditional_expr (tree ifexp, tree op1, tree op2) else if (VOID_TYPE_P (TREE_TYPE (type1))) { if (pedantic && TREE_CODE (TREE_TYPE (type2)) == FUNCTION_TYPE) - pedwarn ("ISO C forbids conditional expr between `void *' and function pointer"); + pedwarn ("ISO C forbids conditional expr between " + "% and function pointer"); result_type = build_pointer_type (qualify_type (TREE_TYPE (type1), TREE_TYPE (type2))); } else if (VOID_TYPE_P (TREE_TYPE (type2))) { if (pedantic && TREE_CODE (TREE_TYPE (type1)) == FUNCTION_TYPE) - pedwarn ("ISO C forbids conditional expr between `void *' and function pointer"); + pedwarn ("ISO C forbids conditional expr between " + "% and function pointer"); result_type = build_pointer_type (qualify_type (TREE_TYPE (type2), TREE_TYPE (type1))); } @@ -2766,7 +2998,7 @@ build_conditional_expr (tree ifexp, tree op1, tree op2) } else if (code1 == POINTER_TYPE && code2 == INTEGER_TYPE) { - if (! integer_zerop (op2)) + if (!integer_zerop (op2)) pedwarn ("pointer/integer type mismatch in conditional expression"); else { @@ -2810,47 +3042,26 @@ build_conditional_expr (tree ifexp, tree op1, tree op2) if (TREE_CODE (ifexp) == INTEGER_CST) return non_lvalue (integer_zerop (ifexp) ? op2 : op1); - return fold (build (COND_EXPR, result_type, ifexp, op1, op2)); + return fold (build3 (COND_EXPR, result_type, ifexp, op1, op2)); } -/* Given a list of expressions, return a compound expression - that performs them all and returns the value of the last of them. */ +/* Return a compound expression that performs two expressions and + returns the value of the second of them. */ tree -build_compound_expr (tree list) -{ - return internal_build_compound_expr (list, TRUE); -} - -static tree -internal_build_compound_expr (tree list, int first_p) -{ - tree rest; - - if (TREE_CHAIN (list) == 0) - { - /* Convert arrays and functions to pointers when there - really is a comma operator. */ - if (!first_p) - TREE_VALUE (list) - = default_function_array_conversion (TREE_VALUE (list)); - - /* Don't let (0, 0) be null pointer constant. */ - if (!first_p && integer_zerop (TREE_VALUE (list))) - return non_lvalue (TREE_VALUE (list)); - return TREE_VALUE (list); - } - - rest = internal_build_compound_expr (TREE_CHAIN (list), FALSE); +build_compound_expr (tree expr1, tree expr2) +{ + /* Convert arrays and functions to pointers. */ + expr2 = default_function_array_conversion (expr2); - if (! TREE_SIDE_EFFECTS (TREE_VALUE (list))) + if (!TREE_SIDE_EFFECTS (expr1)) { /* The left-hand operand of a comma expression is like an expression statement: with -Wextra or -Wunused, we should warn if it doesn't have any side-effects, unless it was explicitly cast to (void). */ if (warn_unused_value - && ! (TREE_CODE (TREE_VALUE (list)) == CONVERT_EXPR - && VOID_TYPE_P (TREE_TYPE (TREE_VALUE (list))))) + && !(TREE_CODE (expr1) == CONVERT_EXPR + && VOID_TYPE_P (TREE_TYPE (expr1)))) warning ("left-hand operand of comma expression has no effect"); } @@ -2859,9 +3070,9 @@ internal_build_compound_expr (tree list, int first_p) `foo() + bar(), baz()' the result of the `+' operator is not used, so we should issue a warning. */ else if (warn_unused_value) - warn_if_unused_value (TREE_VALUE (list)); + warn_if_unused_value (expr1, input_location); - return build (COMPOUND_EXPR, TREE_TYPE (rest), TREE_VALUE (list), rest); + return build2 (COMPOUND_EXPR, TREE_TYPE (expr2), expr1, expr2); } /* Build an expression representing a cast to type TYPE of expression EXPR. */ @@ -2877,8 +3088,10 @@ build_c_cast (tree type, tree expr) /* The ObjC front-end uses TYPE_MAIN_VARIANT to tie together types differing only in qualifications. But when constructing cast expressions, the protocols do matter and must be kept around. */ - if (!c_dialect_objc () || !objc_is_object_ptr (type)) - type = TYPE_MAIN_VARIANT (type); + if (objc_is_object_ptr (type) && objc_is_object_ptr (TREE_TYPE (expr))) + return build1 (NOP_EXPR, type, expr); + + type = TYPE_MAIN_VARIANT (type); if (TREE_CODE (type) == ARRAY_TYPE) { @@ -2908,7 +3121,7 @@ build_c_cast (tree type, tree expr) for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field)) if (comptypes (TYPE_MAIN_VARIANT (TREE_TYPE (field)), - TYPE_MAIN_VARIANT (TREE_TYPE (value)), COMPARE_STRICT)) + TYPE_MAIN_VARIANT (TREE_TYPE (value)))) break; if (field) @@ -2920,7 +3133,7 @@ build_c_cast (tree type, tree expr) t = digest_init (type, build_constructor (type, build_tree_list (field, value)), - 0); + true, 0); TREE_CONSTANT (t) = TREE_CONSTANT (value); TREE_INVARIANT (t) = TREE_INVARIANT (value); return t; @@ -3007,7 +3220,8 @@ build_c_cast (tree type, tree expr) if (warn_bad_function_cast && TREE_CODE (value) == CALL_EXPR && TREE_CODE (type) != TREE_CODE (otype)) - warning ("cast does not match function type"); + warning ("cast from function call of type %qT to non-matching " + "type %qT", otype, type); if (TREE_CODE (type) == POINTER_TYPE && TREE_CODE (otype) == INTEGER_TYPE @@ -3068,19 +3282,20 @@ build_c_cast (tree type, tree expr) /* Ignore any integer overflow caused by the cast. */ if (TREE_CODE (value) == INTEGER_CST) { - TREE_OVERFLOW (value) = TREE_OVERFLOW (ovalue); - - if (TREE_CODE_CLASS (TREE_CODE (ovalue)) == 'c') + if (EXPR_P (ovalue)) + /* If OVALUE had overflow set, then so will VALUE, so it + is safe to overwrite. */ + TREE_OVERFLOW (value) = TREE_OVERFLOW (ovalue); + else + TREE_OVERFLOW (value) = 0; + + if (CONSTANT_CLASS_P (ovalue)) + /* Similarly, constant_overflow cannot have become + cleared. */ TREE_CONSTANT_OVERFLOW (value) = TREE_CONSTANT_OVERFLOW (ovalue); } } - /* Don't let (void *) (FOO *) 0 be a null pointer constant. */ - if (TREE_CODE (value) == INTEGER_CST - && TREE_CODE (expr) == INTEGER_CST - && TREE_CODE (TREE_TYPE (expr)) != INTEGER_TYPE) - value = non_lvalue (value); - /* Don't let a cast be an lvalue. */ if (value == expr) value = non_lvalue (value); @@ -3090,15 +3305,16 @@ build_c_cast (tree type, tree expr) /* Interpret a cast of expression EXPR to type TYPE. */ tree -c_cast_expr (tree type, tree expr) +c_cast_expr (struct c_type_name *type_name, tree expr) { + tree type; int saved_wsp = warn_strict_prototypes; /* This avoids warnings about unprototyped casts on integers. E.g. "#define SIG_DFL (void(*)())0". */ if (TREE_CODE (expr) == INTEGER_CST) warn_strict_prototypes = 0; - type = groktypename (type); + type = groktypename (type_name); warn_strict_prototypes = saved_wsp; return build_c_cast (type, expr); @@ -3142,16 +3358,16 @@ build_modify_expr (tree lhs, enum tree_code modifycode, tree rhs) newrhs = build_binary_op (modifycode, lhs, rhs, 1); } - if (!lvalue_or_else (lhs, "invalid lvalue in assignment")) + if (!lvalue_or_else (lhs, lv_assign)) return error_mark_node; - /* Warn about storing in something that is `const'. */ + /* Give an error for storing in something that is 'const'. */ if (TREE_READONLY (lhs) || TYPE_READONLY (lhstype) || ((TREE_CODE (lhstype) == RECORD_TYPE || TREE_CODE (lhstype) == UNION_TYPE) && C_TYPE_FIELDS_READONLY (lhstype))) - readonly_error (lhs, "assignment"); + readonly_error (lhs, lv_assign); /* If storing into a structure or union member, it has probably been given type `int'. @@ -3176,14 +3392,14 @@ build_modify_expr (tree lhs, enum tree_code modifycode, tree rhs) /* Convert new value to destination type. */ - newrhs = convert_for_assignment (lhstype, newrhs, _("assignment"), + newrhs = convert_for_assignment (lhstype, newrhs, ic_assign, NULL_TREE, NULL_TREE, 0); if (TREE_CODE (newrhs) == ERROR_MARK) return error_mark_node; - /* Scan operands */ + /* Scan operands. */ - result = build (MODIFY_EXPR, lhstype, lhs, newrhs); + result = build2 (MODIFY_EXPR, lhstype, lhs, newrhs); TREE_SIDE_EFFECTS (result) = 1; /* If we got the LHS in a different type for storing in, @@ -3193,7 +3409,7 @@ build_modify_expr (tree lhs, enum tree_code modifycode, tree rhs) if (olhstype == TREE_TYPE (result)) return result; - return convert_for_assignment (olhstype, result, _("assignment"), + return convert_for_assignment (olhstype, result, ic_assign, NULL_TREE, NULL_TREE, 0); } @@ -3202,21 +3418,66 @@ build_modify_expr (tree lhs, enum tree_code modifycode, tree rhs) The real work of conversion is done by `convert'. The purpose of this function is to generate error messages for assignments that are not allowed in C. - ERRTYPE is a string to use in error messages: - "assignment", "return", etc. If it is null, this is parameter passing - for a function call (and different error messages are output). + ERRTYPE says whether it is argument passing, assignment, + initialization or return. - FUNNAME is the name of the function being called, - as an IDENTIFIER_NODE, or null. + FUNCTION is a tree for the function being called. PARMNUM is the number of the argument, for printing in error messages. */ static tree -convert_for_assignment (tree type, tree rhs, const char *errtype, - tree fundecl, tree funname, int parmnum) +convert_for_assignment (tree type, tree rhs, enum impl_conv errtype, + tree fundecl, tree function, int parmnum) { enum tree_code codel = TREE_CODE (type); tree rhstype; enum tree_code coder; + tree rname = NULL_TREE; + + if (errtype == ic_argpass || errtype == ic_argpass_nonproto) + { + tree selector; + /* Change pointer to function to the function itself for + diagnostics. */ + if (TREE_CODE (function) == ADDR_EXPR + && TREE_CODE (TREE_OPERAND (function, 0)) == FUNCTION_DECL) + function = TREE_OPERAND (function, 0); + + /* Handle an ObjC selector specially for diagnostics. */ + selector = objc_message_selector (); + rname = function; + if (selector && parmnum > 2) + { + rname = selector; + parmnum -= 2; + } + } + + /* This macro is used to emit diagnostics to ensure that all format + strings are complete sentences, visible to gettext and checked at + compile time. */ +#define WARN_FOR_ASSIGNMENT(AR, AS, IN, RE) \ + do { \ + switch (errtype) \ + { \ + case ic_argpass: \ + pedwarn (AR, parmnum, rname); \ + break; \ + case ic_argpass_nonproto: \ + warning (AR, parmnum, rname); \ + break; \ + case ic_assign: \ + pedwarn (AS); \ + break; \ + case ic_init: \ + pedwarn (IN); \ + break; \ + case ic_return: \ + pedwarn (RE); \ + break; \ + default: \ + gcc_unreachable (); \ + } \ + } while (0) /* Strip NON_LVALUE_EXPRs since we aren't using as an lvalue. */ /* Do not use STRIP_NOPS here. We do not want an enumerator @@ -3249,6 +3510,11 @@ convert_for_assignment (tree type, tree rhs, const char *errtype, if (coder == VOID_TYPE) { + /* Except for passing an argument to an unprototyped function, + this is a constraint violation. When passing an argument to + an unprototyped function, it is compile-time undefined; + making it a constraint in that case was rejected in + DR#252. */ error ("void value not ignored as it ought to be"); return error_mark_node; } @@ -3256,7 +3522,7 @@ convert_for_assignment (tree type, tree rhs, const char *errtype, This code doesn't fully support references, it's just for the special case of va_start and va_copy. */ if (codel == REFERENCE_TYPE - && comptypes (TREE_TYPE (type), TREE_TYPE (rhs), COMPARE_STRICT) == 1) + && comptypes (TREE_TYPE (type), TREE_TYPE (rhs)) == 1) { if (!lvalue_p (rhs)) { @@ -3279,7 +3545,7 @@ convert_for_assignment (tree type, tree rhs, const char *errtype, return rhs; } /* Some types can interconvert without explicit casts. */ - else if (codel == VECTOR_TYPE + else if (codel == VECTOR_TYPE && coder == VECTOR_TYPE && vector_types_convertible_p (type, TREE_TYPE (rhs))) return convert (type, rhs); /* Arithmetic types all interconvert, and enum is treated like int. */ @@ -3293,7 +3559,8 @@ convert_for_assignment (tree type, tree rhs, const char *errtype, /* Conversion to a transparent union from its member types. This applies only to function arguments. */ - else if (codel == UNION_TYPE && TYPE_TRANSPARENT_UNION (type) && ! errtype) + else if (codel == UNION_TYPE && TYPE_TRANSPARENT_UNION (type) + && (errtype == ic_argpass || errtype == ic_argpass_nonproto)) { tree memb_types; tree marginal_memb_type = 0; @@ -3304,7 +3571,7 @@ convert_for_assignment (tree type, tree rhs, const char *errtype, tree memb_type = TREE_TYPE (memb_types); if (comptypes (TYPE_MAIN_VARIANT (memb_type), - TYPE_MAIN_VARIANT (rhstype), COMPARE_STRICT)) + TYPE_MAIN_VARIANT (rhstype))) break; if (TREE_CODE (memb_type) != POINTER_TYPE) @@ -3333,7 +3600,7 @@ convert_for_assignment (tree type, tree rhs, const char *errtype, break; /* Keep looking for a better type, but remember this one. */ - if (! marginal_memb_type) + if (!marginal_memb_type) marginal_memb_type = memb_type; } } @@ -3350,7 +3617,7 @@ convert_for_assignment (tree type, tree rhs, const char *errtype, if (memb_types || marginal_memb_type) { - if (! memb_types) + if (!memb_types) { /* We have only a marginally acceptable member type; it needs a warning. */ @@ -3368,16 +3635,30 @@ convert_for_assignment (tree type, tree rhs, const char *errtype, function where an ordinary one is wanted, but not vice-versa. */ if (TYPE_QUALS (ttl) & ~TYPE_QUALS (ttr)) - warn_for_assignment ("%s makes qualified function pointer from unqualified", - errtype, funname, parmnum); + WARN_FOR_ASSIGNMENT (N_("passing argument %d of %qE " + "makes qualified function " + "pointer from unqualified"), + N_("assignment makes qualified " + "function pointer from " + "unqualified"), + N_("initialization makes qualified " + "function pointer from " + "unqualified"), + N_("return makes qualified function " + "pointer from unqualified")); } else if (TYPE_QUALS (ttr) & ~TYPE_QUALS (ttl)) - warn_for_assignment ("%s discards qualifiers from pointer target type", - errtype, funname, - parmnum); + WARN_FOR_ASSIGNMENT (N_("passing argument %d of %qE discards " + "qualifiers from pointer target type"), + N_("assignment discards qualifiers " + "from pointer target type"), + N_("initialization discards qualifiers " + "from pointer target type"), + N_("return discards qualifiers from " + "pointer target type")); } - if (pedantic && ! DECL_IN_SYSTEM_HEADER (fundecl)) + if (pedantic && !DECL_IN_SYSTEM_HEADER (fundecl)) pedwarn ("ISO C prohibits argument conversion to union type"); return build1 (NOP_EXPR, type, rhs); @@ -3416,25 +3697,44 @@ convert_for_assignment (tree type, tree rhs, const char *errtype, which are not ANSI null ptr constants. */ && (!integer_zerop (rhs) || TREE_CODE (rhs) == NOP_EXPR) && TREE_CODE (ttl) == FUNCTION_TYPE))) - warn_for_assignment ("ISO C forbids %s between function pointer and `void *'", - errtype, funname, parmnum); + WARN_FOR_ASSIGNMENT (N_("ISO C forbids passing argument %d of " + "%qE between function pointer " + "and %"), + N_("ISO C forbids assignment between " + "function pointer and %"), + N_("ISO C forbids initialization between " + "function pointer and %"), + N_("ISO C forbids return between function " + "pointer and %")); /* Const and volatile mean something different for function types, so the usual warnings are not appropriate. */ else if (TREE_CODE (ttr) != FUNCTION_TYPE && TREE_CODE (ttl) != FUNCTION_TYPE) { if (TYPE_QUALS (ttr) & ~TYPE_QUALS (ttl)) - warn_for_assignment ("%s discards qualifiers from pointer target type", - errtype, funname, parmnum); + WARN_FOR_ASSIGNMENT (N_("passing argument %d of %qE discards " + "qualifiers from pointer target type"), + N_("assignment discards qualifiers " + "from pointer target type"), + N_("initialization discards qualifiers " + "from pointer target type"), + N_("return discards qualifiers from " + "pointer target type")); /* If this is not a case of ignoring a mismatch in signedness, no warning. */ else if (VOID_TYPE_P (ttl) || VOID_TYPE_P (ttr) || target_cmp) ; /* If there is a mismatch, do warn. */ - else if (pedantic) - warn_for_assignment ("pointer targets in %s differ in signedness", - errtype, funname, parmnum); + else + WARN_FOR_ASSIGNMENT (N_("pointer targets in passing argument " + "%d of %qE differ in signedness"), + N_("pointer targets in assignment " + "differ in signedness"), + N_("pointer targets in initialization " + "differ in signedness"), + N_("pointer targets in return differ " + "in signedness")); } else if (TREE_CODE (ttl) == FUNCTION_TYPE && TREE_CODE (ttr) == FUNCTION_TYPE) @@ -3444,17 +3744,30 @@ convert_for_assignment (tree type, tree rhs, const char *errtype, it is okay to use a const or volatile function where an ordinary one is wanted, but not vice-versa. */ if (TYPE_QUALS (ttl) & ~TYPE_QUALS (ttr)) - warn_for_assignment ("%s makes qualified function pointer from unqualified", - errtype, funname, parmnum); + WARN_FOR_ASSIGNMENT (N_("passing argument %d of %qE makes " + "qualified function pointer " + "from unqualified"), + N_("assignment makes qualified function " + "pointer from unqualified"), + N_("initialization makes qualified " + "function pointer from unqualified"), + N_("return makes qualified function " + "pointer from unqualified")); } } else - warn_for_assignment ("%s from incompatible pointer type", - errtype, funname, parmnum); + WARN_FOR_ASSIGNMENT (N_("passing argument %d of %qE from " + "incompatible pointer type"), + N_("assignment from incompatible pointer type"), + N_("initialization from incompatible " + "pointer type"), + N_("return from incompatible pointer type")); return convert (type, rhs); } else if (codel == POINTER_TYPE && coder == ARRAY_TYPE) { + /* ??? This should not be an error when inlining calls to + unprototyped functions. */ error ("invalid use of non-lvalue array"); return error_mark_node; } @@ -3463,45 +3776,58 @@ convert_for_assignment (tree type, tree rhs, const char *errtype, /* An explicit constant 0 can convert to a pointer, or one that results from arithmetic, even including a cast to integer type. */ - if (! (TREE_CODE (rhs) == INTEGER_CST && integer_zerop (rhs)) + if (!(TREE_CODE (rhs) == INTEGER_CST && integer_zerop (rhs)) && - ! (TREE_CODE (rhs) == NOP_EXPR - && TREE_CODE (TREE_TYPE (rhs)) == INTEGER_TYPE - && TREE_CODE (TREE_OPERAND (rhs, 0)) == INTEGER_CST - && integer_zerop (TREE_OPERAND (rhs, 0)))) - warn_for_assignment ("%s makes pointer from integer without a cast", - errtype, funname, parmnum); + !(TREE_CODE (rhs) == NOP_EXPR + && TREE_CODE (TREE_TYPE (rhs)) == INTEGER_TYPE + && TREE_CODE (TREE_OPERAND (rhs, 0)) == INTEGER_CST + && integer_zerop (TREE_OPERAND (rhs, 0)))) + WARN_FOR_ASSIGNMENT (N_("passing argument %d of %qE makes " + "pointer from integer without a cast"), + N_("assignment makes pointer from integer " + "without a cast"), + N_("initialization makes pointer from " + "integer without a cast"), + N_("return makes pointer from integer " + "without a cast")); return convert (type, rhs); } else if (codel == INTEGER_TYPE && coder == POINTER_TYPE) { - warn_for_assignment ("%s makes integer from pointer without a cast", - errtype, funname, parmnum); + WARN_FOR_ASSIGNMENT (N_("passing argument %d of %qE makes integer " + "from pointer without a cast"), + N_("assignment makes integer from pointer " + "without a cast"), + N_("initialization makes integer from pointer " + "without a cast"), + N_("return makes integer from pointer " + "without a cast")); return convert (type, rhs); } else if (codel == BOOLEAN_TYPE && coder == POINTER_TYPE) return convert (type, rhs); - if (!errtype) + switch (errtype) { - if (funname) - { - tree selector = objc_message_selector (); - - if (selector && parmnum > 2) - error ("incompatible type for argument %d of `%s'", - parmnum - 2, IDENTIFIER_POINTER (selector)); - else - error ("incompatible type for argument %d of `%s'", - parmnum, IDENTIFIER_POINTER (funname)); - } - else - error ("incompatible type for argument %d of indirect function call", - parmnum); + case ic_argpass: + case ic_argpass_nonproto: + /* ??? This should not be an error when inlining calls to + unprototyped functions. */ + error ("incompatible type for argument %d of %qE", parmnum, rname); + break; + case ic_assign: + error ("incompatible types in assignment"); + break; + case ic_init: + error ("incompatible types in initialization"); + break; + case ic_return: + error ("incompatible types in return"); + break; + default: + gcc_unreachable (); } - else - error ("incompatible types in %s", errtype); return error_mark_node; } @@ -3517,80 +3843,19 @@ c_convert_parm_for_inlining (tree parm, tree value, tree fn, int argnum) /* If FN was prototyped, the value has been converted already in convert_arguments. */ - if (! value || TYPE_ARG_TYPES (TREE_TYPE (fn))) + if (!value || TYPE_ARG_TYPES (TREE_TYPE (fn))) return value; type = TREE_TYPE (parm); ret = convert_for_assignment (type, value, - (char *) 0 /* arg passing */, fn, - DECL_NAME (fn), argnum); + ic_argpass_nonproto, fn, + fn, argnum); if (targetm.calls.promote_prototypes (TREE_TYPE (fn)) && INTEGRAL_TYPE_P (type) && (TYPE_PRECISION (type) < TYPE_PRECISION (integer_type_node))) ret = default_conversion (ret); return ret; } - -/* Print a warning using MSGID. - It gets OPNAME as its one parameter. - if OPNAME is null and ARGNUM is 0, it is replaced by "passing arg of `FUNCTION'". - Otherwise if OPNAME is null, it is replaced by "passing arg ARGNUM of `FUNCTION'". - FUNCTION and ARGNUM are handled specially if we are building an - Objective-C selector. */ - -static void -warn_for_assignment (const char *msgid, const char *opname, tree function, - int argnum) -{ - if (opname == 0) - { - tree selector = objc_message_selector (); - char * new_opname; - - if (selector && argnum > 2) - { - function = selector; - argnum -= 2; - } - if (argnum == 0) - { - if (function) - { - /* Function name is known; supply it. */ - const char *const argstring = _("passing arg of `%s'"); - new_opname = alloca (IDENTIFIER_LENGTH (function) - + strlen (argstring) + 1 + 1); - sprintf (new_opname, argstring, - IDENTIFIER_POINTER (function)); - } - else - { - /* Function name unknown (call through ptr). */ - const char *const argnofun = _("passing arg of pointer to function"); - new_opname = alloca (strlen (argnofun) + 1 + 1); - sprintf (new_opname, argnofun); - } - } - else if (function) - { - /* Function name is known; supply it. */ - const char *const argstring = _("passing arg %d of `%s'"); - new_opname = alloca (IDENTIFIER_LENGTH (function) - + strlen (argstring) + 1 + 25 /*%d*/ + 1); - sprintf (new_opname, argstring, argnum, - IDENTIFIER_POINTER (function)); - } - else - { - /* Function name unknown (call through ptr); just give arg number. */ - const char *const argnofun = _("passing arg %d of pointer to function"); - new_opname = alloca (strlen (argnofun) + 1 + 25 /*%d*/ + 1); - sprintf (new_opname, argnofun, argnum); - } - opname = new_opname; - } - pedwarn (msgid, opname); -} /* If VALUE is a compound expr all of whose expressions are constant, then return its value. Otherwise, return error_mark_node. @@ -3609,8 +3874,7 @@ valid_compound_expr_initializer (tree value, tree endtype) return valid_compound_expr_initializer (TREE_OPERAND (value, 1), endtype); } - else if (! TREE_CONSTANT (value) - && ! initializer_constant_valid_p (value, endtype)) + else if (!initializer_constant_valid_p (value, endtype)) return error_mark_node; else return value; @@ -3634,12 +3898,12 @@ store_init_value (tree decl, tree init) /* Digest the specified initializer into an expression. */ - value = digest_init (type, init, TREE_STATIC (decl)); + value = digest_init (type, init, true, TREE_STATIC (decl)); /* Store the expression if valid; else report error. */ if (warn_traditional && !in_system_header - && AGGREGATE_TYPE_P (TREE_TYPE (decl)) && ! TREE_STATIC (decl)) + && AGGREGATE_TYPE_P (TREE_TYPE (decl)) && !TREE_STATIC (decl)) warning ("traditional C rejects automatic aggregate initialization"); DECL_INITIAL (decl) = value; @@ -3715,11 +3979,8 @@ static int spelling_size; /* Size of the spelling stack. */ if (depth >= spelling_size) \ { \ spelling_size += 10; \ - if (spelling_base == 0) \ - spelling_base = xmalloc (spelling_size * sizeof (struct spelling)); \ - else \ - spelling_base = xrealloc (spelling_base, \ - spelling_size * sizeof (struct spelling)); \ + spelling_base = XRESIZEVEC (struct spelling, spelling_base, \ + spelling_size); \ RESTORE_SPELLING_DEPTH (depth); \ } \ \ @@ -3809,9 +4070,9 @@ error_init (const char *msgid) char *ofwhat; error ("%s", _(msgid)); - ofwhat = print_spelling (alloca (spelling_length () + 1)); + ofwhat = print_spelling ((char *) alloca (spelling_length () + 1)); if (*ofwhat) - error ("(near initialization for `%s')", ofwhat); + error ("(near initialization for %qs)", ofwhat); } /* Issue a pedantic warning for a bad initializer component. @@ -3824,9 +4085,9 @@ pedwarn_init (const char *msgid) char *ofwhat; pedwarn ("%s", _(msgid)); - ofwhat = print_spelling (alloca (spelling_length () + 1)); + ofwhat = print_spelling ((char *) alloca (spelling_length () + 1)); if (*ofwhat) - pedwarn ("(near initialization for `%s')", ofwhat); + pedwarn ("(near initialization for %qs)", ofwhat); } /* Issue a warning for a bad initializer component. @@ -3839,19 +4100,37 @@ warning_init (const char *msgid) char *ofwhat; warning ("%s", _(msgid)); - ofwhat = print_spelling (alloca (spelling_length () + 1)); + ofwhat = print_spelling ((char *) alloca (spelling_length () + 1)); if (*ofwhat) - warning ("(near initialization for `%s')", ofwhat); + warning ("(near initialization for %qs)", ofwhat); } +/* If TYPE is an array type and EXPR is a parenthesized string + constant, warn if pedantic that EXPR is being used to initialize an + object of type TYPE. */ + +void +maybe_warn_string_init (tree type, struct c_expr expr) +{ + if (pedantic + && TREE_CODE (type) == ARRAY_TYPE + && TREE_CODE (expr.value) == STRING_CST + && expr.original_code != STRING_CST) + pedwarn_init ("array initialized from parenthesized string constant"); +} + /* Digest the parser output INIT as an initializer for type TYPE. Return a C expression of type TYPE to represent the initial value. + If INIT is a string constant, STRICT_STRING is true if it is + unparenthesized or we should not warn here for it being parenthesized. + For other types of INIT, STRICT_STRING is not used. + REQUIRE_CONSTANT requests an error if non-constant initializers or elements are seen. */ static tree -digest_init (tree type, tree init, int require_constant) +digest_init (tree type, tree init, bool strict_string, int require_constant) { enum tree_code code = TREE_CODE (type); tree inside_init = init; @@ -3872,32 +4151,41 @@ digest_init (tree type, tree init, int require_constant) /* Initialization of an array of chars from a string constant optionally enclosed in braces. */ - if (code == ARRAY_TYPE) + if (code == ARRAY_TYPE && inside_init + && TREE_CODE (inside_init) == STRING_CST) { tree typ1 = TYPE_MAIN_VARIANT (TREE_TYPE (type)); - if ((typ1 == char_type_node - || typ1 == signed_char_type_node - || typ1 == unsigned_char_type_node - || typ1 == unsigned_wchar_type_node - || typ1 == signed_wchar_type_node) - && ((inside_init && TREE_CODE (inside_init) == STRING_CST))) + /* Note that an array could be both an array of character type + and an array of wchar_t if wchar_t is signed char or unsigned + char. */ + bool char_array = (typ1 == char_type_node + || typ1 == signed_char_type_node + || typ1 == unsigned_char_type_node); + bool wchar_array = !!comptypes (typ1, wchar_type_node); + if (char_array || wchar_array) { + struct c_expr expr; + bool char_string; + expr.value = inside_init; + expr.original_code = (strict_string ? STRING_CST : ERROR_MARK); + maybe_warn_string_init (type, expr); + + char_string + = (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (inside_init))) + == char_type_node); + if (comptypes (TYPE_MAIN_VARIANT (TREE_TYPE (inside_init)), - TYPE_MAIN_VARIANT (type), COMPARE_STRICT)) + TYPE_MAIN_VARIANT (type))) return inside_init; - if ((TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (inside_init))) - != char_type_node) - && TYPE_PRECISION (typ1) == TYPE_PRECISION (char_type_node)) + if (!wchar_array && !char_string) { error_init ("char-array initialized from wide string"); return error_mark_node; } - if ((TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (inside_init))) - == char_type_node) - && TYPE_PRECISION (typ1) != TYPE_PRECISION (char_type_node)) + if (char_string && !char_array) { - error_init ("int-array initialized from non-wide string"); + error_init ("wchar_t-array initialized from non-wide string"); return error_mark_node; } @@ -3919,19 +4207,25 @@ digest_init (tree type, tree init, int require_constant) return inside_init; } + else if (INTEGRAL_TYPE_P (typ1)) + { + error_init ("array of inappropriate type initialized " + "from string constant"); + return error_mark_node; + } } /* Build a VECTOR_CST from a *constant* vector constructor. If the vector constructor is not constant (e.g. {1,2,3,foo()}) then punt below and handle as a constructor. */ if (code == VECTOR_TYPE + && TREE_CODE (TREE_TYPE (inside_init)) == VECTOR_TYPE && vector_types_convertible_p (TREE_TYPE (inside_init), type) && TREE_CONSTANT (inside_init)) { if (TREE_CODE (inside_init) == VECTOR_CST && comptypes (TYPE_MAIN_VARIANT (TREE_TYPE (inside_init)), - TYPE_MAIN_VARIANT (type), - COMPARE_STRICT)) + TYPE_MAIN_VARIANT (type))) return inside_init; else return build_vector (type, CONSTRUCTOR_ELTS (inside_init)); @@ -3942,19 +4236,19 @@ digest_init (tree type, tree init, int require_constant) if (inside_init && TREE_TYPE (inside_init) != 0 && (comptypes (TYPE_MAIN_VARIANT (TREE_TYPE (inside_init)), - TYPE_MAIN_VARIANT (type), COMPARE_STRICT) + TYPE_MAIN_VARIANT (type)) || (code == ARRAY_TYPE - && comptypes (TREE_TYPE (inside_init), type, COMPARE_STRICT)) + && comptypes (TREE_TYPE (inside_init), type)) || (code == VECTOR_TYPE - && comptypes (TREE_TYPE (inside_init), type, COMPARE_STRICT)) + && comptypes (TREE_TYPE (inside_init), type)) || (code == POINTER_TYPE && TREE_CODE (TREE_TYPE (inside_init)) == ARRAY_TYPE && comptypes (TREE_TYPE (TREE_TYPE (inside_init)), - TREE_TYPE (type), COMPARE_STRICT)) + TREE_TYPE (type))) || (code == POINTER_TYPE && TREE_CODE (TREE_TYPE (inside_init)) == FUNCTION_TYPE && comptypes (TREE_TYPE (inside_init), - TREE_TYPE (type), COMPARE_STRICT)))) + TREE_TYPE (type))))) { if (code == POINTER_TYPE) { @@ -4009,16 +4303,8 @@ digest_init (tree type, tree init, int require_constant) inside_init = error_mark_node; } 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)))) + && !initializer_constant_valid_p (inside_init, + TREE_TYPE (inside_init))) { error_init ("initializer element is not constant"); inside_init = error_mark_node; @@ -4037,16 +4323,20 @@ digest_init (tree type, tree init, int require_constant) for arrays and functions. We must not call it in the case where inside_init is a null pointer constant. */ inside_init - = convert_for_assignment (type, init, _("initialization"), + = convert_for_assignment (type, init, ic_init, NULL_TREE, NULL_TREE, 0); - if (require_constant && ! TREE_CONSTANT (inside_init)) + /* Check to see if we have already given an error message. */ + if (inside_init == error_mark_node) + ; + else if (require_constant && !TREE_CONSTANT (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) + && !initializer_constant_valid_p (inside_init, + TREE_TYPE (inside_init))) { error_init ("initializer element is not computable at load time"); inside_init = error_mark_node; @@ -4138,17 +4428,11 @@ static int constructor_depth; /* 0 if implicitly pushing constructor levels is allowed. */ int constructor_no_implicit = 0; /* 0 for C; 1 for some other languages. */ -static int require_constant_value; -static int require_constant_elements; - /* DECL node for which an initializer is being read. 0 means we are reading a constructor expression such as (struct foo) {...}. */ static tree constructor_decl; -/* start_init saves the ASMSPEC arg here for really_start_incremental_init. */ -static const char *constructor_asmspec; - /* Nonzero if this is an initializer for a top-level decl. */ static int constructor_top_level; @@ -4182,9 +4466,9 @@ struct constructor_stack struct init_node *pending_elts; int offset; int depth; - /* If nonzero, this value should replace the entire + /* If value nonzero, this value should replace the entire constructor at this level. */ - tree replacement_value; + struct c_expr replacement_value; struct constructor_range_stack *range_stack; char constant; char simple; @@ -4220,7 +4504,6 @@ struct initializer_stack { struct initializer_stack *next; tree decl; - const char *asmspec; struct constructor_stack *constructor_stack; struct constructor_range_stack *constructor_range_stack; tree elements; @@ -4237,17 +4520,12 @@ struct initializer_stack *initializer_stack; /* Prepare to parse and output the initializer for variable DECL. */ void -start_init (tree decl, tree asmspec_tree, int top_level) +start_init (tree decl, tree asmspec_tree ATTRIBUTE_UNUSED, int top_level) { const char *locus; struct initializer_stack *p = xmalloc (sizeof (struct initializer_stack)); - const char *asmspec = 0; - - if (asmspec_tree) - asmspec = TREE_STRING_POINTER (asmspec_tree); p->decl = constructor_decl; - p->asmspec = constructor_asmspec; p->require_constant_value = require_constant_value; p->require_constant_elements = require_constant_elements; p->constructor_stack = constructor_stack; @@ -4261,7 +4539,6 @@ start_init (tree decl, tree asmspec_tree, int top_level) initializer_stack = p; constructor_decl = decl; - constructor_asmspec = asmspec; constructor_designated = 0; constructor_top_level = top_level; @@ -4311,14 +4588,12 @@ finish_init (void) free (q); } - if (constructor_range_stack) - abort (); + gcc_assert (!constructor_range_stack); /* Pop back to the data of the outer initializer (if any). */ free (spelling_base); - + constructor_decl = p->decl; - constructor_asmspec = p->asmspec; require_constant_value = p->require_constant_value; require_constant_elements = p->require_constant_elements; constructor_stack = p->constructor_stack; @@ -4342,7 +4617,7 @@ finish_init (void) void really_start_incremental_init (tree type) { - struct constructor_stack *p = xmalloc (sizeof (struct constructor_stack)); + struct constructor_stack *p = XNEW (struct constructor_stack); if (type == 0) type = TREE_TYPE (constructor_decl); @@ -4363,7 +4638,8 @@ really_start_incremental_init (tree type) p->erroneous = constructor_erroneous; p->pending_elts = constructor_pending_elts; p->depth = constructor_depth; - p->replacement_value = 0; + p->replacement_value.value = 0; + p->replacement_value.original_code = ERROR_MARK; p->implicit = 0; p->range_stack = 0; p->outer = 0; @@ -4405,14 +4681,14 @@ really_start_incremental_init (tree 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_max_index = build_int_cst (NULL_TREE, -1); /* constructor_max_index needs to be an INTEGER_CST. Attempts to initialize VLAs will cause a proper error; avoid tree checking errors as well by setting a safe value. */ if (constructor_max_index && TREE_CODE (constructor_max_index) != INTEGER_CST) - constructor_max_index = build_int_2 (-1, -1); + constructor_max_index = build_int_cst (NULL_TREE, -1); constructor_index = convert (bitsizetype, @@ -4427,7 +4703,7 @@ really_start_incremental_init (tree type) { /* Vectors are like simple fixed-size arrays. */ constructor_max_index = - build_int_2 (TYPE_VECTOR_SUBPARTS (constructor_type) - 1, 0); + build_int_cst (NULL_TREE, TYPE_VECTOR_SUBPARTS (constructor_type) - 1); constructor_index = convert (bitsizetype, bitsize_zero_node); constructor_unfilled_index = constructor_index; } @@ -4478,7 +4754,7 @@ push_init_level (int implicit) value = find_init_member (constructor_index); } - p = xmalloc (sizeof (struct constructor_stack)); + p = XNEW (struct constructor_stack); p->type = constructor_type; p->fields = constructor_fields; p->index = constructor_index; @@ -4492,7 +4768,8 @@ push_init_level (int implicit) p->erroneous = constructor_erroneous; p->pending_elts = constructor_pending_elts; p->depth = constructor_depth; - p->replacement_value = 0; + p->replacement_value.value = 0; + p->replacement_value.original_code = ERROR_MARK; p->implicit = implicit; p->outer = 0; p->incremental = constructor_incremental; @@ -4581,7 +4858,7 @@ push_init_level (int implicit) { /* Vectors are like simple fixed-size arrays. */ constructor_max_index = - build_int_2 (TYPE_VECTOR_SUBPARTS (constructor_type) - 1, 0); + build_int_cst (NULL_TREE, TYPE_VECTOR_SUBPARTS (constructor_type) - 1); constructor_index = convert (bitsizetype, integer_zero_node); constructor_unfilled_index = constructor_index; } @@ -4595,14 +4872,14 @@ push_init_level (int implicit) /* 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_max_index = build_int_cst (NULL_TREE, -1); /* constructor_max_index needs to be an INTEGER_CST. Attempts to initialize VLAs will cause a proper error; avoid tree checking errors as well by setting a safe value. */ if (constructor_max_index && TREE_CODE (constructor_max_index) != INTEGER_CST) - constructor_max_index = build_int_2 (-1, -1); + constructor_max_index = build_int_cst (NULL_TREE, -1); constructor_index = convert (bitsizetype, @@ -4629,18 +4906,23 @@ push_init_level (int implicit) } /* 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 + finish up that level of constructor. If a single expression + with redundant braces initialized that level, return the + c_expr structure for that expression. Otherwise, the original_code + element is set to ERROR_MARK. + If we were outputting the elements as they are read, return 0 as the value from inner levels (process_init_element ignores that), - but return error_mark_node from the outermost level + but return error_mark_node as the value from the outermost level (that's what we want to put in DECL_INITIAL). - Otherwise, return a CONSTRUCTOR expression. */ + Otherwise, return a CONSTRUCTOR expression as the value. */ -tree +struct c_expr pop_init_level (int implicit) { struct constructor_stack *p; - tree constructor = 0; + struct c_expr ret; + ret.value = 0; + ret.original_code = ERROR_MARK; if (implicit == 0) { @@ -4649,8 +4931,7 @@ pop_init_level (int implicit) while (constructor_stack->implicit) process_init_element (pop_init_level (1)); - if (constructor_range_stack) - abort (); + gcc_assert (!constructor_range_stack); } /* Now output all pending elements. */ @@ -4664,14 +4945,16 @@ pop_init_level (int implicit) if (constructor_type && constructor_fields && TREE_CODE (constructor_type) == ARRAY_TYPE && TYPE_DOMAIN (constructor_type) - && ! TYPE_MAX_VALUE (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)) + else { + gcc_assert (!TYPE_SIZE (constructor_type)); + if (constructor_depth > 2) error_init ("initialization of flexible array member in a nested context"); else if (pedantic) @@ -4683,21 +4966,17 @@ pop_init_level (int implicit) 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 + if (warn_missing_field_initializers && constructor_type && TREE_CODE (constructor_type) == RECORD_TYPE && constructor_unfilled_fields) { /* Do not warn for flexible array members or zero-length arrays. */ while (constructor_unfilled_fields - && (! DECL_SIZE (constructor_unfilled_fields) + && (!DECL_SIZE (constructor_unfilled_fields) || integer_zerop (DECL_SIZE (constructor_unfilled_fields)))) constructor_unfilled_fields = TREE_CHAIN (constructor_unfilled_fields); @@ -4712,10 +4991,10 @@ pop_init_level (int implicit) } /* Pad out the end of the structure. */ - if (p->replacement_value) + if (p->replacement_value.value) /* If this closes a superfluous brace pair, just pass out the element between them. */ - constructor = p->replacement_value; + ret = p->replacement_value; else if (constructor_type == 0) ; else if (TREE_CODE (constructor_type) != RECORD_TYPE @@ -4729,28 +5008,28 @@ pop_init_level (int implicit) { if (!constructor_erroneous) error_init ("empty scalar initializer"); - constructor = error_mark_node; + ret.value = error_mark_node; } else if (TREE_CHAIN (constructor_elements) != 0) { error_init ("extra elements in scalar initializer"); - constructor = TREE_VALUE (constructor_elements); + ret.value = TREE_VALUE (constructor_elements); } else - constructor = TREE_VALUE (constructor_elements); + ret.value = TREE_VALUE (constructor_elements); } else { if (constructor_erroneous) - constructor = error_mark_node; + ret.value = error_mark_node; else { - constructor = build_constructor (constructor_type, - nreverse (constructor_elements)); + ret.value = build_constructor (constructor_type, + nreverse (constructor_elements)); if (constructor_constant) - TREE_CONSTANT (constructor) = TREE_INVARIANT (constructor) = 1; + TREE_CONSTANT (ret.value) = TREE_INVARIANT (ret.value) = 1; if (constructor_constant && constructor_simple) - TREE_STATIC (constructor) = 1; + TREE_STATIC (ret.value) = 1; } } @@ -4776,13 +5055,16 @@ pop_init_level (int implicit) constructor_stack = p->next; free (p); - if (constructor == 0) + if (ret.value == 0) { if (constructor_stack == 0) - return error_mark_node; - return NULL_TREE; + { + ret.value = error_mark_node; + return ret; + } + return ret; } - return constructor; + return ret; } /* Common handling for both array range and field name designators. @@ -4799,14 +5081,14 @@ set_designator (int array) if (constructor_type == 0) return 1; - /* If there were errors in this designator list already, bail out silently. */ + /* 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 (); + gcc_assert (!constructor_range_stack); /* Designator list starts at the level of closest explicit braces. */ @@ -4822,19 +5104,20 @@ set_designator (int array) return 1; } - if (TREE_CODE (constructor_type) == RECORD_TYPE - || TREE_CODE (constructor_type) == UNION_TYPE) + switch (TREE_CODE (constructor_type)) { + case RECORD_TYPE: + case 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) - { + break; + case ARRAY_TYPE: subtype = TYPE_MAIN_VARIANT (TREE_TYPE (constructor_type)); + break; + default: + gcc_unreachable (); } - else - abort (); subcode = TREE_CODE (subtype); if (array && subcode != ARRAY_TYPE) @@ -4862,7 +5145,7 @@ push_range_stack (tree range_end) { struct constructor_range_stack *p; - p = ggc_alloc (sizeof (struct constructor_range_stack)); + p = GGC_NEW (struct constructor_range_stack); p->prev = constructor_range_stack; p->next = 0; p->fields = constructor_fields; @@ -4887,6 +5170,13 @@ set_init_index (tree first, tree last) designator_errorneous = 1; + if (!INTEGRAL_TYPE_P (TREE_TYPE (first)) + || (last && !INTEGRAL_TYPE_P (TREE_TYPE (last)))) + { + error_init ("array index in initializer not of integer type"); + return; + } + while ((TREE_CODE (first) == NOP_EXPR || TREE_CODE (first) == CONVERT_EXPR || TREE_CODE (first) == NON_LVALUE_EXPR) @@ -4972,7 +5262,7 @@ set_init_label (tree fieldname) } if (tail == 0) - error ("unknown field `%s' specified in initializer", + error ("unknown field %qs specified in initializer", IDENTIFIER_POINTER (fieldname)); else { @@ -5036,7 +5326,7 @@ add_pending_init (tree purpose, tree value) } } - r = ggc_alloc (sizeof (struct init_node)); + r = GGC_NEW (struct init_node); r->purpose = purpose; r->value = value; @@ -5247,18 +5537,17 @@ set_nonincremental_init_from_string (tree str) const char *p, *end; int byte, wchar_bytes, charwidth, bitpos; - if (TREE_CODE (constructor_type) != ARRAY_TYPE) - abort (); + gcc_assert (TREE_CODE (constructor_type) == ARRAY_TYPE); 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 (); - + { + gcc_assert (TYPE_PRECISION (TREE_TYPE (TREE_TYPE (str))) + == TYPE_PRECISION (wchar_type_node)); + wchar_bytes = TYPE_PRECISION (wchar_type_node) / BITS_PER_UNIT; + } charwidth = TYPE_PRECISION (char_type_node); type = TREE_TYPE (constructor_type); p = TREE_STRING_POINTER (str); @@ -5311,8 +5600,7 @@ set_nonincremental_init_from_string (tree str) << (bitpos - HOST_BITS_PER_WIDE_INT); } - value = build_int_2 (val[1], val[0]); - TREE_TYPE (value) = type; + value = build_int_cst_wide (type, val[1], val[0]); add_pending_init (purpose, value); } @@ -5379,13 +5667,17 @@ find_init_member (tree field) Otherwise, collect it in a list from which we will make a CONSTRUCTOR. TYPE is the data type that the containing data type wants here. FIELD is the field (a FIELD_DECL) or the index that this element fills. + If VALUE is a string constant, STRICT_STRING is true if it is + unparenthesized or we should not warn here for it being parenthesized. + For other types of VALUE, STRICT_STRING is not used. PENDING if non-nil means output pending elements that belong right after this element. (PENDING is normally 1; it is 0 while outputting pending elements, to avoid recursion.) */ static void -output_init_element (tree value, tree type, tree field, int pending) +output_init_element (tree value, bool strict_string, tree type, tree field, + int pending) { if (type == error_mark_node) { @@ -5396,9 +5688,9 @@ output_init_element (tree value, tree type, tree field, int pending) || (TREE_CODE (TREE_TYPE (value)) == ARRAY_TYPE && !(TREE_CODE (value) == STRING_CST && TREE_CODE (type) == ARRAY_TYPE - && TREE_CODE (TREE_TYPE (type)) == INTEGER_TYPE) + && INTEGRAL_TYPE_P (TREE_TYPE (type))) && !comptypes (TYPE_MAIN_VARIANT (TREE_TYPE (value)), - TYPE_MAIN_VARIANT (type), COMPARE_STRICT))) + TYPE_MAIN_VARIANT (type)))) value = default_conversion (value); if (TREE_CODE (value) == COMPOUND_LITERAL_EXPR @@ -5415,21 +5707,23 @@ output_init_element (tree value, tree type, tree field, int pending) constructor_erroneous = 1; else if (!TREE_CONSTANT (value)) constructor_constant = 0; - else if (initializer_constant_valid_p (value, TREE_TYPE (value)) == 0 + else if (!initializer_constant_valid_p (value, TREE_TYPE (value)) || ((TREE_CODE (constructor_type) == RECORD_TYPE || TREE_CODE (constructor_type) == UNION_TYPE) && DECL_C_BIT_FIELD (field) && TREE_CODE (value) != INTEGER_CST)) constructor_simple = 0; - if (require_constant_value && ! TREE_CONSTANT (value)) + if (!initializer_constant_valid_p (value, TREE_TYPE (value))) { - error_init ("initializer element is not constant"); - value = error_mark_node; + if (require_constant_value) + { + error_init ("initializer element is not constant"); + value = error_mark_node; + } + else if (require_constant_elements) + pedwarn ("initializer element is not computable at load time"); } - else if (require_constant_elements - && initializer_constant_valid_p (value, TREE_TYPE (value)) == 0) - 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. */ @@ -5441,7 +5735,7 @@ output_init_element (tree value, tree type, tree field, int pending) || TREE_CHAIN (field))))) return; - value = digest_init (type, value, require_constant_value); + value = digest_init (type, value, strict_string, require_constant_value); if (value == error_mark_node) { constructor_erroneous = 1; @@ -5561,7 +5855,7 @@ output_pending_init_elements (int all) { if (tree_int_cst_equal (elt->purpose, constructor_unfilled_index)) - output_init_element (elt->value, + output_init_element (elt->value, true, TREE_TYPE (constructor_type), constructor_unfilled_index, 0); else if (tree_int_cst_lt (constructor_unfilled_index, @@ -5615,7 +5909,7 @@ output_pending_init_elements (int all) if (tree_int_cst_equal (elt_bitpos, ctor_unfilled_bitpos)) { constructor_unfilled_fields = elt->purpose; - output_init_element (elt->value, TREE_TYPE (elt->purpose), + output_init_element (elt->value, true, TREE_TYPE (elt->purpose), elt->purpose, 0); } else if (tree_int_cst_lt (ctor_unfilled_bitpos, elt_bitpos)) @@ -5657,7 +5951,7 @@ output_pending_init_elements (int all) /* Ordinarily return, but not if we want to output all and there are elements left. */ - if (! (all && next != 0)) + if (!(all && next != 0)) return; /* If it's not incremental, just skip over the gap, so that after @@ -5682,10 +5976,11 @@ output_pending_init_elements (int all) it calls output_init_element. */ void -process_init_element (tree value) +process_init_element (struct c_expr value) { - tree orig_value = value; - int string_flag = value != 0 && TREE_CODE (value) == STRING_CST; + tree orig_value = value.value; + int string_flag = orig_value != 0 && TREE_CODE (orig_value) == STRING_CST; + bool strict_string = value.original_code == STRING_CST; designator_depth = 0; designator_errorneous = 0; @@ -5695,16 +5990,16 @@ process_init_element (tree value) if (string_flag && constructor_type && TREE_CODE (constructor_type) == ARRAY_TYPE - && TREE_CODE (TREE_TYPE (constructor_type)) == INTEGER_TYPE + && INTEGRAL_TYPE_P (TREE_TYPE (constructor_type)) && integer_zerop (constructor_unfilled_index)) { - if (constructor_stack->replacement_value) + if (constructor_stack->replacement_value.value) error_init ("excess elements in char array initializer"); constructor_stack->replacement_value = value; return; } - if (constructor_stack->replacement_value != 0) + if (constructor_stack->replacement_value.value != 0) { error_init ("excess elements in struct initializer"); return; @@ -5737,10 +6032,10 @@ process_init_element (tree value) { /* If value is a compound literal and we'll be just using its content, don't put it into a SAVE_EXPR. */ - if (TREE_CODE (value) != COMPOUND_LITERAL_EXPR + if (TREE_CODE (value.value) != COMPOUND_LITERAL_EXPR || !require_constant_value || flag_isoc99) - value = save_expr (value); + value.value = save_expr (value.value); } while (1) @@ -5772,16 +6067,16 @@ process_init_element (tree value) } /* Accept a string constant to initialize a subarray. */ - if (value != 0 + if (value.value != 0 && fieldcode == ARRAY_TYPE - && TREE_CODE (TREE_TYPE (fieldtype)) == INTEGER_TYPE + && INTEGRAL_TYPE_P (TREE_TYPE (fieldtype)) && string_flag) - value = orig_value; + value.value = orig_value; /* Otherwise, if we have come to a subaggregate, and we don't have an element of its type, push into it. */ - else if (value != 0 && !constructor_no_implicit - && value != error_mark_node - && TYPE_MAIN_VARIANT (TREE_TYPE (value)) != fieldtype + else if (value.value != 0 && !constructor_no_implicit + && value.value != error_mark_node + && TYPE_MAIN_VARIANT (TREE_TYPE (value.value)) != fieldtype && (fieldcode == RECORD_TYPE || fieldcode == ARRAY_TYPE || fieldcode == UNION_TYPE)) { @@ -5789,10 +6084,11 @@ process_init_element (tree value) continue; } - if (value) + if (value.value) { push_member_name (constructor_fields); - output_init_element (value, fieldtype, constructor_fields, 1); + output_init_element (value.value, strict_string, + fieldtype, constructor_fields, 1); RESTORE_SPELLING_DEPTH (constructor_depth); } else @@ -5854,20 +6150,21 @@ process_init_element (tree value) __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)))) + && !(value.value && (integer_zerop (value.value) + || real_zerop (value.value)))) warning ("traditional C rejects initialization of unions"); /* Accept a string constant to initialize a subarray. */ - if (value != 0 + if (value.value != 0 && fieldcode == ARRAY_TYPE - && TREE_CODE (TREE_TYPE (fieldtype)) == INTEGER_TYPE + && INTEGRAL_TYPE_P (TREE_TYPE (fieldtype)) && string_flag) - value = orig_value; + value.value = orig_value; /* Otherwise, if we have come to a subaggregate, and we don't have an element of its type, push into it. */ - else if (value != 0 && !constructor_no_implicit - && value != error_mark_node - && TYPE_MAIN_VARIANT (TREE_TYPE (value)) != fieldtype + else if (value.value != 0 && !constructor_no_implicit + && value.value != error_mark_node + && TYPE_MAIN_VARIANT (TREE_TYPE (value.value)) != fieldtype && (fieldcode == RECORD_TYPE || fieldcode == ARRAY_TYPE || fieldcode == UNION_TYPE)) { @@ -5875,10 +6172,11 @@ process_init_element (tree value) continue; } - if (value) + if (value.value) { push_member_name (constructor_fields); - output_init_element (value, fieldtype, constructor_fields, 1); + output_init_element (value.value, strict_string, + fieldtype, constructor_fields, 1); RESTORE_SPELLING_DEPTH (constructor_depth); } else @@ -5897,16 +6195,16 @@ process_init_element (tree value) enum tree_code eltcode = TREE_CODE (elttype); /* Accept a string constant to initialize a subarray. */ - if (value != 0 + if (value.value != 0 && eltcode == ARRAY_TYPE - && TREE_CODE (TREE_TYPE (elttype)) == INTEGER_TYPE + && INTEGRAL_TYPE_P (TREE_TYPE (elttype)) && string_flag) - value = orig_value; + value.value = orig_value; /* Otherwise, if we have come to a subaggregate, and we don't have an element of its type, push into it. */ - else if (value != 0 && !constructor_no_implicit - && value != error_mark_node - && TYPE_MAIN_VARIANT (TREE_TYPE (value)) != elttype + else if (value.value != 0 && !constructor_no_implicit + && value.value != error_mark_node + && TYPE_MAIN_VARIANT (TREE_TYPE (value.value)) != elttype && (eltcode == RECORD_TYPE || eltcode == ARRAY_TYPE || eltcode == UNION_TYPE)) { @@ -5923,17 +6221,18 @@ process_init_element (tree value) } /* Now output the actual element. */ - if (value) + if (value.value) { push_array_bounds (tree_low_cst (constructor_index, 0)); - output_init_element (value, elttype, constructor_index, 1); + output_init_element (value.value, strict_string, + elttype, constructor_index, 1); RESTORE_SPELLING_DEPTH (constructor_depth); } constructor_index = size_binop (PLUS_EXPR, constructor_index, bitsize_one_node); - if (! value) + if (!value.value) /* If we are doing the bookkeeping for an element that was directly output as a constructor, we must update constructor_unfilled_index. */ @@ -5952,13 +6251,14 @@ process_init_element (tree value) } /* Now output the actual element. */ - if (value) - output_init_element (value, elttype, constructor_index, 1); + if (value.value) + output_init_element (value.value, strict_string, + elttype, constructor_index, 1); constructor_index = size_binop (PLUS_EXPR, constructor_index, bitsize_one_node); - if (! value) + if (!value.value) /* If we are doing the bookkeeping for an element that was directly output as a constructor, we must update constructor_unfilled_index. */ @@ -5974,8 +6274,9 @@ process_init_element (tree value) } else { - if (value) - output_init_element (value, constructor_type, NULL_TREE, 1); + if (value.value) + output_init_element (value.value, strict_string, + constructor_type, NULL_TREE, 1); constructor_fields = 0; } @@ -5990,16 +6291,14 @@ process_init_element (tree value) constructor_range_stack = 0; while (constructor_stack != range_stack->stack) { - if (!constructor_stack->implicit) - abort (); + gcc_assert (constructor_stack->implicit); 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 (); + gcc_assert (constructor_stack->implicit); process_init_element (pop_init_level (1)); } @@ -6038,7 +6337,7 @@ process_init_element (tree value) /* Build a complete asm-statement, whose components are a CV_QUALIFIER (guaranteed to be 'volatile' or null) and ARGS (represented using - an ASM_STMT node). */ + an ASM_EXPR node). */ tree build_asm_stmt (tree cv_qualifier, tree args) { @@ -6051,7 +6350,7 @@ build_asm_stmt (tree cv_qualifier, tree args) some INPUTS, and some CLOBBERS. The latter three may be NULL. SIMPLE indicates whether there was anything at all after the string in the asm expression -- asm("blah") and asm("blah" : ) - are subtly different. We use a ASM_STMT node to represent this. */ + are subtly different. We use a ASM_EXPR node to represent this. */ tree build_asm_expr (tree string, tree outputs, tree inputs, tree clobbers, bool simple) @@ -6073,7 +6372,7 @@ build_asm_expr (tree string, tree outputs, tree inputs, tree clobbers, tree output = TREE_VALUE (tail); STRIP_NOPS (output); TREE_VALUE (tail) = output; - lvalue_or_else (output, "invalid lvalue in asm statement"); + lvalue_or_else (output, lv_asm); constraint = TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (tail))); @@ -6102,7 +6401,7 @@ build_asm_expr (tree string, tree outputs, tree inputs, tree clobbers, for (tail = inputs; tail; tail = TREE_CHAIN (tail)) TREE_VALUE (tail) = default_function_array_conversion (TREE_VALUE (tail)); - args = build_stmt (ASM_STMT, string, outputs, inputs, clobbers); + args = build_stmt (ASM_EXPR, string, outputs, inputs, clobbers); /* Simple asm statements are treated as volatile. */ if (simple) @@ -6112,94 +6411,59 @@ build_asm_expr (tree string, tree outputs, tree inputs, tree clobbers, } return args; } + +/* Generate a goto statement to LABEL. */ -/* 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 (tree string, tree outputs, tree inputs, - tree clobbers, int vol, location_t locus) +tree +c_finish_goto_label (tree label) { - int noutputs = list_length (outputs); - int i; - /* o[I] is the place that output number I should be written. */ - tree *o = 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); - if (o[i] == error_mark_node) - return; - } + tree decl = lookup_label (label); + if (!decl) + return NULL_TREE; - /* 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, locus); - - /* Copy all the intermediate outputs into the specified outputs. */ - for (i = 0, tail = outputs; tail; tail = TREE_CHAIN (tail), i++) - { - if (o[i] != TREE_VALUE (tail)) - { - expand_expr (build_modify_expr (o[i], NOP_EXPR, TREE_VALUE (tail)), - NULL_RTX, VOIDmode, EXPAND_NORMAL); - free_temp_slots (); + TREE_USED (decl) = 1; + return add_stmt (build1 (GOTO_EXPR, void_type_node, decl)); +} - /* 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.) */ - else - { - tree type = TREE_TYPE (o[i]); - if (TREE_READONLY (o[i]) - || TYPE_READONLY (type) - || ((TREE_CODE (type) == RECORD_TYPE - || TREE_CODE (type) == UNION_TYPE) - && C_TYPE_FIELDS_READONLY (type))) - readonly_error (o[i], "modification by `asm'"); - } - } +/* Generate a computed goto statement to EXPR. */ - /* Those MODIFY_EXPRs could do autoincrements. */ - emit_queue (); +tree +c_finish_goto_ptr (tree expr) +{ + if (pedantic) + pedwarn ("ISO C forbids %"); + expr = convert (ptr_type_node, expr); + return add_stmt (build1 (GOTO_EXPR, void_type_node, expr)); } - -/* Expand a C `return' statement. - RETVAL is the expression for what to return, - or a null pointer for `return;' with no value. */ + +/* Generate a C `return' statement. RETVAL is the expression for what + to return, or a null pointer for `return;' with no value. */ tree -c_expand_return (tree retval) +c_finish_return (tree retval) { tree valtype = TREE_TYPE (TREE_TYPE (current_function_decl)); if (TREE_THIS_VOLATILE (current_function_decl)) - warning ("function declared `noreturn' has a `return' statement"); + warning ("function declared % has a % statement"); if (!retval) { current_function_returns_null = 1; if ((warn_return_type || flag_isoc99) && valtype != 0 && TREE_CODE (valtype) != VOID_TYPE) - pedwarn_c99 ("`return' with no value, in function returning non-void"); + pedwarn_c99 ("% with no value, in " + "function returning non-void"); } 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"); + pedwarn ("% with a value, in function returning void"); } else { - tree t = convert_for_assignment (valtype, retval, _("return"), + tree t = convert_for_assignment (valtype, retval, ic_return, NULL_TREE, NULL_TREE, 0); tree res = DECL_RESULT (current_function_decl); tree inner; @@ -6228,7 +6492,7 @@ c_expand_return (tree retval) { tree op1 = TREE_OPERAND (inner, 1); - while (! POINTER_TYPE_P (TREE_TYPE (op1)) + while (!POINTER_TYPE_P (TREE_TYPE (op1)) && (TREE_CODE (op1) == NOP_EXPR || TREE_CODE (op1) == NON_LVALUE_EXPR || TREE_CODE (op1) == CONVERT_EXPR)) @@ -6244,12 +6508,13 @@ c_expand_return (tree retval) case ADDR_EXPR: inner = TREE_OPERAND (inner, 0); - while (TREE_CODE_CLASS (TREE_CODE (inner)) == 'r') + while (REFERENCE_CLASS_P (inner) + && TREE_CODE (inner) != INDIRECT_REF) inner = TREE_OPERAND (inner, 0); if (DECL_P (inner) - && ! DECL_EXTERNAL (inner) - && ! TREE_STATIC (inner) + && !DECL_EXTERNAL (inner) + && !TREE_STATIC (inner) && DECL_CONTEXT (inner) == current_function_decl) warning ("function returns address of local variable"); break; @@ -6261,21 +6526,27 @@ c_expand_return (tree retval) break; } - retval = build (MODIFY_EXPR, TREE_TYPE (res), res, t); + retval = build2 (MODIFY_EXPR, TREE_TYPE (res), res, t); } - return add_stmt (build_return_stmt (retval)); + return add_stmt (build_stmt (RETURN_EXPR, retval)); } struct c_switch { /* The SWITCH_STMT being built. */ tree switch_stmt; + + /* The original type of the testing expression, i.e. before the + default conversion is applied. */ + tree orig_type; + /* 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; }; @@ -6286,7 +6557,7 @@ struct c_switch { during the processing of the body of a function, and we never collect at that point. */ -static struct c_switch *switch_stack; +struct c_switch *c_switch_stack; /* Start a C switch statement, testing expression EXP. Return the new SWITCH_STMT. */ @@ -6303,7 +6574,7 @@ c_start_case (tree exp) code = TREE_CODE (TREE_TYPE (exp)); orig_type = TREE_TYPE (exp); - if (! INTEGRAL_TYPE_P (orig_type) + if (!INTEGRAL_TYPE_P (orig_type) && code != ERROR_MARK) { error ("switch quantity not an integer"); @@ -6316,7 +6587,8 @@ c_start_case (tree 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"); + warning ("% switch expression not converted to " + "% in ISO C"); exp = default_conversion (exp); type = TREE_TYPE (exp); @@ -6324,13 +6596,15 @@ c_start_case (tree exp) } /* Add this new SWITCH_STMT to the stack. */ - cs = xmalloc (sizeof (*cs)); - cs->switch_stmt = build_stmt (SWITCH_STMT, exp, NULL_TREE, orig_type); + cs = XNEW (struct c_switch); + cs->switch_stmt = build_stmt ((enum tree_code) SWITCH_STMT, exp, NULL_TREE, + orig_type); + cs->orig_type = orig_type; cs->cases = splay_tree_new (case_compare, NULL, NULL); - cs->next = switch_stack; - switch_stack = cs; + cs->next = c_switch_stack; + c_switch_stack = cs; - return add_stmt (switch_stack->switch_stmt); + return add_stmt (cs->switch_stmt); } /* Process a case label. */ @@ -6340,26 +6614,19 @@ do_case (tree low_value, tree high_value) { tree label = NULL_TREE; - if (switch_stack) + if (c_switch_stack) { - bool switch_was_empty_p = (SWITCH_BODY (switch_stack->switch_stmt) == NULL_TREE); - - label = c_add_case_label (switch_stack->cases, - SWITCH_COND (switch_stack->switch_stmt), + label = c_add_case_label (c_switch_stack->cases, + SWITCH_COND (c_switch_stack->switch_stmt), + c_switch_stack->orig_type, low_value, high_value); if (label == error_mark_node) label = NULL_TREE; - else if (switch_was_empty_p) - { - /* Attach the first case label to the SWITCH_BODY. */ - SWITCH_BODY (switch_stack->switch_stmt) = TREE_CHAIN (switch_stack->switch_stmt); - TREE_CHAIN (switch_stack->switch_stmt) = NULL_TREE; - } } else if (low_value) error ("case label not within a switch statement"); else - error ("`default' label not within a switch statement"); + error ("% label not within a switch statement"); return label; } @@ -6367,22 +6634,409 @@ do_case (tree low_value, tree high_value) /* Finish the switch statement. */ void -c_finish_case (void) +c_finish_case (tree body) { - struct c_switch *cs = switch_stack; + struct c_switch *cs = c_switch_stack; + + SWITCH_BODY (cs->switch_stmt) = body; /* Emit warnings as needed. */ c_do_switch_warnings (cs->cases, cs->switch_stmt); - /* Rechain the next statements to the SWITCH_STMT. */ - last_tree = cs->switch_stmt; - /* Pop the stack. */ - switch_stack = switch_stack->next; + c_switch_stack = cs->next; splay_tree_delete (cs->cases); - free (cs); + XDELETE (cs); +} + +/* Emit an if statement. IF_LOCUS is the location of the 'if'. COND, + THEN_BLOCK and ELSE_BLOCK are expressions to be used; ELSE_BLOCK + may be null. NESTED_IF is true if THEN_BLOCK contains another IF + statement, and was not surrounded with parenthesis. */ + +void +c_finish_if_stmt (location_t if_locus, tree cond, tree then_block, + tree else_block, bool nested_if) +{ + tree stmt; + + /* Diagnose an ambiguous else if if-then-else is nested inside if-then. */ + if (warn_parentheses && nested_if && else_block == NULL) + { + tree inner_if = then_block; + + /* We know from the grammar productions that there is an IF nested + within THEN_BLOCK. Due to labels and c99 conditional declarations, + it might not be exactly THEN_BLOCK, but should be the last + non-container statement within. */ + while (1) + switch (TREE_CODE (inner_if)) + { + case COND_EXPR: + goto found; + case BIND_EXPR: + inner_if = BIND_EXPR_BODY (inner_if); + break; + case STATEMENT_LIST: + inner_if = expr_last (then_block); + break; + case TRY_FINALLY_EXPR: + case TRY_CATCH_EXPR: + inner_if = TREE_OPERAND (inner_if, 0); + break; + default: + gcc_unreachable (); + } + found: + + if (COND_EXPR_ELSE (inner_if)) + warning ("%Hsuggest explicit braces to avoid ambiguous %", + &if_locus); + } + + /* Diagnose ";" via the special empty statement node that we create. */ + if (extra_warnings) + { + if (TREE_CODE (then_block) == NOP_EXPR && !TREE_TYPE (then_block)) + { + if (!else_block) + warning ("%Hempty body in an if-statement", + EXPR_LOCUS (then_block)); + then_block = alloc_stmt_list (); + } + if (else_block + && TREE_CODE (else_block) == NOP_EXPR + && !TREE_TYPE (else_block)) + { + warning ("%Hempty body in an else-statement", + EXPR_LOCUS (else_block)); + else_block = alloc_stmt_list (); + } + } + + stmt = build3 (COND_EXPR, NULL_TREE, cond, then_block, else_block); + SET_EXPR_LOCATION (stmt, if_locus); + add_stmt (stmt); +} + +/* Emit a general-purpose loop construct. START_LOCUS is the location of + the beginning of the loop. COND is the loop condition. COND_IS_FIRST + is false for DO loops. INCR is the FOR increment expression. BODY is + the statement controlled by the loop. BLAB is the break label. CLAB is + the continue label. Everything is allowed to be NULL. */ + +void +c_finish_loop (location_t start_locus, tree cond, tree incr, tree body, + tree blab, tree clab, bool cond_is_first) +{ + tree entry = NULL, exit = NULL, t; + + /* Detect do { ... } while (0) and don't generate loop construct. */ + if (cond && !cond_is_first && integer_zerop (cond)) + cond = NULL; + if (cond_is_first || cond) + { + tree top = build1 (LABEL_EXPR, void_type_node, NULL_TREE); + + /* If we have an exit condition, then we build an IF with gotos either + out of the loop, or to the top of it. If there's no exit condition, + then we just build a jump back to the top. */ + exit = build_and_jump (&LABEL_EXPR_LABEL (top)); + + if (cond) + { + /* Canonicalize the loop condition to the end. This means + generating a branch to the loop condition. Reuse the + continue label, if possible. */ + if (cond_is_first) + { + if (incr || !clab) + { + entry = build1 (LABEL_EXPR, void_type_node, NULL_TREE); + t = build_and_jump (&LABEL_EXPR_LABEL (entry)); + } + else + t = build1 (GOTO_EXPR, void_type_node, clab); + SET_EXPR_LOCATION (t, start_locus); + add_stmt (t); + } + + t = build_and_jump (&blab); + exit = build3 (COND_EXPR, void_type_node, cond, exit, t); + exit = fold (exit); + if (cond_is_first) + SET_EXPR_LOCATION (exit, start_locus); + else + SET_EXPR_LOCATION (exit, input_location); + } + + add_stmt (top); + } + + if (body) + add_stmt (body); + if (clab) + add_stmt (build1 (LABEL_EXPR, void_type_node, clab)); + if (incr) + add_stmt (incr); + if (entry) + add_stmt (entry); + if (exit) + add_stmt (exit); + if (blab) + add_stmt (build1 (LABEL_EXPR, void_type_node, blab)); +} + +tree +c_finish_bc_stmt (tree *label_p, bool is_break) +{ + tree label = *label_p; + + if (!label) + *label_p = label = create_artificial_label (); + else if (TREE_CODE (label) != LABEL_DECL) + { + if (is_break) + error ("break statement not within loop or switch"); + else + error ("continue statement not within a loop"); + return NULL_TREE; + } + + return add_stmt (build1 (GOTO_EXPR, void_type_node, label)); +} + +/* A helper routine for c_process_expr_stmt and c_finish_stmt_expr. */ + +static void +emit_side_effect_warnings (tree expr) +{ + if (expr == error_mark_node) + ; + else if (!TREE_SIDE_EFFECTS (expr)) + { + if (!VOID_TYPE_P (TREE_TYPE (expr)) && !TREE_NO_WARNING (expr)) + warning ("%Hstatement with no effect", + EXPR_HAS_LOCATION (expr) ? EXPR_LOCUS (expr) : &input_location); + } + else if (warn_unused_value) + warn_if_unused_value (expr, input_location); +} + +/* Process an expression as if it were a complete statement. Emit + diagnostics, but do not call ADD_STMT. */ + +tree +c_process_expr_stmt (tree expr) +{ + if (!expr) + return NULL_TREE; + + /* Do default conversion if safe and possibly important, + in case within ({...}). */ + if ((TREE_CODE (TREE_TYPE (expr)) == ARRAY_TYPE + && (flag_isoc99 || lvalue_p (expr))) + || TREE_CODE (TREE_TYPE (expr)) == FUNCTION_TYPE) + expr = default_conversion (expr); + + if (warn_sequence_point) + verify_sequence_points (expr); + + if (TREE_TYPE (expr) != error_mark_node + && !COMPLETE_OR_VOID_TYPE_P (TREE_TYPE (expr)) + && TREE_CODE (TREE_TYPE (expr)) != ARRAY_TYPE) + error ("expression statement has incomplete type"); + + /* If we're not processing a statement expression, warn about unused values. + Warnings for statement expressions will be emitted later, once we figure + out which is the result. */ + if (!STATEMENT_LIST_STMT_EXPR (cur_stmt_list) + && (extra_warnings || warn_unused_value)) + emit_side_effect_warnings (expr); + + /* If the expression is not of a type to which we cannot assign a line + number, wrap the thing in a no-op NOP_EXPR. */ + if (DECL_P (expr) || CONSTANT_CLASS_P (expr)) + expr = build1 (NOP_EXPR, TREE_TYPE (expr), expr); + + if (EXPR_P (expr)) + SET_EXPR_LOCATION (expr, input_location); + + return expr; +} + +/* Emit an expression as a statement. */ + +tree +c_finish_expr_stmt (tree expr) +{ + if (expr) + return add_stmt (c_process_expr_stmt (expr)); + else + return NULL; +} + +/* Do the opposite and emit a statement as an expression. To begin, + create a new binding level and return it. */ + +tree +c_begin_stmt_expr (void) +{ + tree ret; + + /* We must force a BLOCK for this level so that, if it is not expanded + later, there is a way to turn off the entire subtree of blocks that + are contained in it. */ + keep_next_level (); + ret = c_begin_compound_stmt (true); + + /* Mark the current statement list as belonging to a statement list. */ + STATEMENT_LIST_STMT_EXPR (ret) = 1; + + return ret; +} + +tree +c_finish_stmt_expr (tree body) +{ + tree last, type, tmp, val; + tree *last_p; + + body = c_end_compound_stmt (body, true); + + /* Locate the last statement in BODY. See c_end_compound_stmt + about always returning a BIND_EXPR. */ + last_p = &BIND_EXPR_BODY (body); + last = BIND_EXPR_BODY (body); + + continue_searching: + if (TREE_CODE (last) == STATEMENT_LIST) + { + tree_stmt_iterator i; + + /* This can happen with degenerate cases like ({ }). No value. */ + if (!TREE_SIDE_EFFECTS (last)) + return body; + + /* If we're supposed to generate side effects warnings, process + all of the statements except the last. */ + if (extra_warnings || warn_unused_value) + { + for (i = tsi_start (last); !tsi_one_before_end_p (i); tsi_next (&i)) + emit_side_effect_warnings (tsi_stmt (i)); + } + else + i = tsi_last (last); + last_p = tsi_stmt_ptr (i); + last = *last_p; + } + + /* If the end of the list is exception related, then the list was split + by a call to push_cleanup. Continue searching. */ + if (TREE_CODE (last) == TRY_FINALLY_EXPR + || TREE_CODE (last) == TRY_CATCH_EXPR) + { + last_p = &TREE_OPERAND (last, 0); + last = *last_p; + goto continue_searching; + } + + /* In the case that the BIND_EXPR is not necessary, return the + expression out from inside it. */ + if (last == error_mark_node + || (last == BIND_EXPR_BODY (body) + && BIND_EXPR_VARS (body) == NULL)) + return last; + + /* Extract the type of said expression. */ + type = TREE_TYPE (last); + + /* If we're not returning a value at all, then the BIND_EXPR that + we already have is a fine expression to return. */ + if (!type || VOID_TYPE_P (type)) + return body; + + /* Now that we've located the expression containing the value, it seems + silly to make voidify_wrapper_expr repeat the process. Create a + temporary of the appropriate type and stick it in a TARGET_EXPR. */ + tmp = create_tmp_var_raw (type, NULL); + + /* Unwrap a no-op NOP_EXPR as added by c_finish_expr_stmt. This avoids + tree_expr_nonnegative_p giving up immediately. */ + val = last; + if (TREE_CODE (val) == NOP_EXPR + && TREE_TYPE (val) == TREE_TYPE (TREE_OPERAND (val, 0))) + val = TREE_OPERAND (val, 0); + + *last_p = build2 (MODIFY_EXPR, void_type_node, tmp, val); + SET_EXPR_LOCUS (*last_p, EXPR_LOCUS (last)); + + return build4 (TARGET_EXPR, type, tmp, body, NULL_TREE, NULL_TREE); +} + +/* Begin and end compound statements. This is as simple as pushing + and popping new statement lists from the tree. */ + +tree +c_begin_compound_stmt (bool do_scope) +{ + tree stmt = push_stmt_list (); + if (do_scope) + push_scope (); + return stmt; +} + +tree +c_end_compound_stmt (tree stmt, bool do_scope) +{ + tree block = NULL; + + if (do_scope) + { + if (c_dialect_objc ()) + objc_clear_super_receiver (); + block = pop_scope (); + } + + stmt = pop_stmt_list (stmt); + stmt = c_build_bind_expr (block, stmt); + + /* If this compound statement is nested immediately inside a statement + expression, then force a BIND_EXPR to be created. Otherwise we'll + do the wrong thing for ({ { 1; } }) or ({ 1; { } }). In particular, + STATEMENT_LISTs merge, and thus we can lose track of what statement + was really last. */ + if (cur_stmt_list + && STATEMENT_LIST_STMT_EXPR (cur_stmt_list) + && TREE_CODE (stmt) != BIND_EXPR) + { + stmt = build3 (BIND_EXPR, void_type_node, NULL, stmt, NULL); + TREE_SIDE_EFFECTS (stmt) = 1; + } + + return stmt; } +/* Queue a cleanup. CLEANUP is an expression/statement to be executed + when the current scope is exited. EH_ONLY is true when this is not + meant to apply to normal control flow transfer. */ + +void +push_cleanup (tree ARG_UNUSED (decl), tree cleanup, bool eh_only) +{ + enum tree_code code; + tree stmt, list; + bool stmt_expr; + + code = eh_only ? TRY_CATCH_EXPR : TRY_FINALLY_EXPR; + stmt = build_stmt (code, NULL, cleanup); + add_stmt (stmt); + stmt_expr = STATEMENT_LIST_STMT_EXPR (cur_stmt_list); + list = push_stmt_list (); + TREE_OPERAND (stmt, 0) = list; + STATEMENT_LIST_STMT_EXPR (list) = stmt_expr; +} + /* Build a binary-operation expression without default conversions. CODE is the kind of expression to build. This function differs from `build' in several ways: @@ -6521,6 +7175,11 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1, && (code1 == INTEGER_TYPE || code1 == REAL_TYPE || code1 == COMPLEX_TYPE || code1 == VECTOR_TYPE)) { + if (code0 == COMPLEX_TYPE || code0 == VECTOR_TYPE) + code0 = TREE_CODE (TREE_TYPE (TREE_TYPE (op0))); + if (code1 == COMPLEX_TYPE || code1 == VECTOR_TYPE) + code1 = TREE_CODE (TREE_TYPE (TREE_TYPE (op1))); + if (!(code0 == INTEGER_TYPE && code1 == INTEGER_TYPE)) resultcode = RDIV_EXPR; else @@ -6531,7 +7190,7 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1, dividing by something we know != -1. */ shorten = (TYPE_UNSIGNED (TREE_TYPE (orig_op0)) || (TREE_CODE (op1) == INTEGER_CST - && ! integer_all_onesp (op1))); + && !integer_all_onesp (op1))); common = 1; } break; @@ -6558,7 +7217,7 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1, only if unsigned or if dividing by something we know != -1. */ shorten = (TYPE_UNSIGNED (TREE_TYPE (orig_op0)) || (TREE_CODE (op1) == INTEGER_CST - && ! integer_all_onesp (op1))); + && !integer_all_onesp (op1))); common = 1; } break; @@ -6596,7 +7255,7 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1, warning ("right shift count is negative"); else { - if (! integer_zerop (op1)) + if (!integer_zerop (op1)) short_shift = 1; if (compare_tree_int (op1, TYPE_PRECISION (type0)) >= 0) @@ -6681,20 +7340,22 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1, Otherwise, the targets must be compatible and both must be object or both incomplete. */ if (comp_target_types (type0, type1, 1)) - result_type = common_type (type0, type1); + result_type = common_pointer_type (type0, type1); else if (VOID_TYPE_P (tt0)) { /* op0 != orig_op0 detects the case of something whose value is 0 but which isn't a valid null ptr const. */ if (pedantic && (!integer_zerop (op0) || op0 != orig_op0) && TREE_CODE (tt1) == FUNCTION_TYPE) - pedwarn ("ISO C forbids comparison of `void *' with function pointer"); + pedwarn ("ISO C forbids comparison of %" + " with function pointer"); } else if (VOID_TYPE_P (tt1)) { if (pedantic && (!integer_zerop (op1) || op1 != orig_op1) && TREE_CODE (tt0) == FUNCTION_TYPE) - pedwarn ("ISO C forbids comparison of `void *' with function pointer"); + pedwarn ("ISO C forbids comparison of %" + " with function pointer"); } else pedwarn ("comparison of distinct pointer types lacks a cast"); @@ -6729,7 +7390,7 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1, { if (comp_target_types (type0, type1, 1)) { - result_type = common_type (type0, type1); + result_type = common_pointer_type (type0, type1); if (pedantic && TREE_CODE (TREE_TYPE (type0)) == FUNCTION_TYPE) pedwarn ("ISO C forbids ordered comparisons of pointers to functions"); @@ -6754,7 +7415,7 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1, { if (comp_target_types (type0, type1, 1)) { - result_type = common_type (type0, type1); + result_type = common_pointer_type (type0, type1); if (!COMPLETE_TYPE_P (TREE_TYPE (type0)) != !COMPLETE_TYPE_P (TREE_TYPE (type1))) pedwarn ("comparison of complete and incomplete pointers"); @@ -6959,8 +7620,8 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1, if (warn_sign_compare && skip_evaluation == 0) { - int op0_signed = ! TYPE_UNSIGNED (TREE_TYPE (orig_op0)); - int op1_signed = ! TYPE_UNSIGNED (TREE_TYPE (orig_op1)); + int op0_signed = !TYPE_UNSIGNED (TREE_TYPE (orig_op0)); + int op1_signed = !TYPE_UNSIGNED (TREE_TYPE (orig_op1)); int unsignedp0, unsignedp1; tree primop0 = get_narrower (op0, &unsignedp0); tree primop1 = get_narrower (op1, &unsignedp1); @@ -6979,7 +7640,7 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1, Do not warn if the comparison is being done in a signed type, since the signed type will only be chosen if it can represent all the values of the unsigned type. */ - if (! TYPE_UNSIGNED (result_type)) + if (!TYPE_UNSIGNED (result_type)) /* OK */; /* Do not warn if both operands are the same signedness. */ else if (op0_signed == op1_signed) @@ -6998,7 +7659,7 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1, constant expression involving such literals or a conditional expression involving such literals) and it is non-negative. */ - if (c_tree_expr_nonnegative_p (sop)) + if (tree_expr_nonnegative_p (sop)) /* OK */; /* Do not warn if the comparison is an equality operation, the unsigned quantity is an integral constant, and it @@ -7014,7 +7675,7 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1, else if (TREE_CODE (uop) == INTEGER_CST && TREE_CODE (TREE_TYPE (uop)) == ENUMERAL_TYPE && int_fits_type_p - (TYPE_MAX_VALUE (TREE_TYPE(uop)), + (TYPE_MAX_VALUE (TREE_TYPE (uop)), c_common_signed_type (result_type))) /* OK */; else @@ -7062,7 +7723,7 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1, if (bits < TYPE_PRECISION (result_type) && bits < HOST_BITS_PER_WIDE_INT && unsignedp) { - mask = (~ (HOST_WIDE_INT) 0) << bits; + mask = (~(HOST_WIDE_INT) 0) << bits; if ((mask & constant) != mask) warning ("comparison of promoted ~unsigned with constant"); } @@ -7090,27 +7751,31 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1, return error_mark_node; } - if (! converted) + if (!converted) { if (TREE_TYPE (op0) != result_type) op0 = convert (result_type, op0); if (TREE_TYPE (op1) != result_type) op1 = convert (result_type, op1); + + /* This can happen if one operand has a vector type, and the other + has a different type. */ + if (TREE_CODE (op0) == ERROR_MARK || TREE_CODE (op1) == ERROR_MARK) + return error_mark_node; } if (build_type == NULL_TREE) build_type = result_type; { - tree result = build (resultcode, build_type, op0, op1); + tree result = build2 (resultcode, build_type, op0, op1); /* Treat expressions in initializers specially as they can't trap. */ - result = initializer_stack ? fold_initializer (result) - : fold (result); + result = require_constant_value ? fold_initializer (result) + : fold (result); if (final_type != 0) result = convert (final_type, result); return result; } } -