X-Git-Url: http://git.sourceforge.jp/view?p=pf3gnuchains%2Fgcc-fork.git;a=blobdiff_plain;f=gcc%2Fc-typeck.c;h=d6ffc87cf3999ff708f49a6a7ee18676d404d10e;hp=27c8cd47c83815f283edbccd5478092505f9a146;hb=3ac15270c9e8eaacc82d5ef15ed8df6c3ca4b7bf;hpb=841667053837143adaa91e24e7214b191ee179a1 diff --git a/gcc/c-typeck.c b/gcc/c-typeck.c index 27c8cd47c83..d6ffc87cf39 100644 --- a/gcc/c-typeck.c +++ b/gcc/c-typeck.c @@ -1,6 +1,6 @@ /* Build expressions with type checking for C compiler. - Copyright (C) 1987, 1988, 1991, 1992, 1993, 1994, 1995, 1996, 1997, - 1998, 1999, 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc. + Copyright (C) 1987, 1988, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, + 1999, 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc. This file is part of GCC. @@ -43,16 +43,16 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA #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 +#include "tree-flow.h" + +/* 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__". */ @@ -64,6 +64,8 @@ int in_sizeof; /* The level of nesting inside "typeof". */ int in_typeof; +struct c_label_context *label_context_stack; + /* Nonzero if we've already printed a "missing braces around initializer" message within this initializer. */ static int missing_braces_mentioned; @@ -81,9 +83,8 @@ 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 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); @@ -100,8 +101,10 @@ 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); +static int lvalue_or_else (tree, enum lvalue_use); +static int lvalue_p (tree); +static void record_maybe_used_decl (tree); /* Do `exp = require_complete_type (exp);' to make sure exp does not have an incomplete type. (That includes void types.) */ @@ -137,8 +140,7 @@ c_incomplete_type_error (tree value, tree type) if (value != 0 && (TREE_CODE (value) == VAR_DECL || TREE_CODE (value) == PARM_DECL)) - error ("%qs has an incomplete type", - IDENTIFIER_POINTER (DECL_NAME (value))); + error ("%qD has an incomplete type", value); else { retry: @@ -181,12 +183,11 @@ c_incomplete_type_error (tree value, tree type) } if (TREE_CODE (TYPE_NAME (type)) == IDENTIFIER_NODE) - error ("invalid use of undefined type %<%s %s%>", - type_code_string, IDENTIFIER_POINTER (TYPE_NAME (type))); + error ("invalid use of undefined type %<%s %E%>", + type_code_string, TYPE_NAME (type)); else /* If this type has a typedef-name, the TYPE_NAME is a TYPE_DECL. */ - error ("invalid use of incomplete typedef %qs", - IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type)))); + error ("invalid use of incomplete typedef %qD", TYPE_NAME (type)); } } @@ -278,7 +279,9 @@ composite_type (tree t1, tree t2) case ARRAY_TYPE: { tree elt = composite_type (TREE_TYPE (t1), TREE_TYPE (t2)); - + int quals; + tree unqual_elt; + /* We should not have any type quals on arrays at all. */ gcc_assert (!TYPE_QUALS (t1) && !TYPE_QUALS (t2)); @@ -293,8 +296,16 @@ composite_type (tree t1, tree t2) 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)); + /* Merge the element types, and have a size if either arg has + one. We may have qualifiers on the element types. To set + up TYPE_MAIN_VARIANT correctly, we need to form the + composite of the unqualified types and add the qualifiers + back at the end. */ + quals = TYPE_QUALS (strip_array_types (elt)); + unqual_elt = c_build_qualified_type (elt, TYPE_UNQUALIFIED); + t1 = build_array_type (unqual_elt, + TYPE_DOMAIN (TYPE_DOMAIN (t1) ? t1 : t2)); + t1 = c_build_qualified_type (t1, quals); return build_type_attribute_variant (t1, attributes); } @@ -366,29 +377,51 @@ composite_type (tree t1, tree t2) && TREE_VALUE (p1) != TREE_VALUE (p2)) { tree memb; + tree mv2 = TREE_VALUE (p2); + if (mv2 && mv2 != error_mark_node + && TREE_CODE (mv2) != ARRAY_TYPE) + mv2 = TYPE_MAIN_VARIANT (mv2); for (memb = TYPE_FIELDS (TREE_VALUE (p1)); memb; memb = TREE_CHAIN (memb)) - if (comptypes (TREE_TYPE (memb), TREE_VALUE (p2))) - { - TREE_VALUE (n) = TREE_VALUE (p2); - if (pedantic) - pedwarn ("function types not truly compatible in ISO C"); - goto parm_done; - } + { + tree mv3 = TREE_TYPE (memb); + if (mv3 && mv3 != error_mark_node + && TREE_CODE (mv3) != ARRAY_TYPE) + mv3 = TYPE_MAIN_VARIANT (mv3); + if (comptypes (mv3, mv2)) + { + TREE_VALUE (n) = composite_type (TREE_TYPE (memb), + TREE_VALUE (p2)); + if (pedantic) + pedwarn ("function types not truly compatible in ISO C"); + goto parm_done; + } + } } if (TREE_CODE (TREE_VALUE (p2)) == UNION_TYPE && TREE_VALUE (p2) != TREE_VALUE (p1)) { tree memb; + tree mv1 = TREE_VALUE (p1); + if (mv1 && mv1 != error_mark_node + && TREE_CODE (mv1) != ARRAY_TYPE) + mv1 = TYPE_MAIN_VARIANT (mv1); for (memb = TYPE_FIELDS (TREE_VALUE (p2)); memb; memb = TREE_CHAIN (memb)) - if (comptypes (TREE_TYPE (memb), TREE_VALUE (p1))) - { - TREE_VALUE (n) = TREE_VALUE (p1); - if (pedantic) - pedwarn ("function types not truly compatible in ISO C"); - goto parm_done; - } + { + tree mv3 = TREE_TYPE (memb); + if (mv3 && mv3 != error_mark_node + && TREE_CODE (mv3) != ARRAY_TYPE) + mv3 = TYPE_MAIN_VARIANT (mv3); + if (comptypes (mv3, mv1)) + { + TREE_VALUE (n) = composite_type (TREE_TYPE (memb), + TREE_VALUE (p1)); + if (pedantic) + pedwarn ("function types not truly compatible in ISO C"); + goto parm_done; + } + } } TREE_VALUE (n) = composite_type (TREE_VALUE (p1), TREE_VALUE (p2)); parm_done: ; @@ -416,8 +449,8 @@ static tree common_pointer_type (tree t1, tree t2) { tree attributes; - tree pointed_to_1; - tree pointed_to_2; + tree pointed_to_1, mv1; + tree pointed_to_2, mv2; tree target; /* Save time if the two types are the same. */ @@ -437,11 +470,15 @@ common_pointer_type (tree t1, tree t2) 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)); + qualifiers of the two types' targets. Do not lose qualifiers on + array element types by taking the TYPE_MAIN_VARIANT. */ + mv1 = pointed_to_1 = TREE_TYPE (t1); + mv2 = pointed_to_2 = TREE_TYPE (t2); + if (TREE_CODE (mv1) != ARRAY_TYPE) + mv1 = TYPE_MAIN_VARIANT (pointed_to_1); + if (TREE_CODE (mv2) != ARRAY_TYPE) + mv2 = TYPE_MAIN_VARIANT (pointed_to_2); + target = composite_type (mv1, mv2); t1 = build_pointer_type (c_build_qualified_type (target, TYPE_QUALS (pointed_to_1) | @@ -457,8 +494,8 @@ common_pointer_type (tree t1, tree t2) 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) +static tree +c_common_type (tree t1, tree t2) { enum tree_code code1; enum tree_code code2; @@ -509,7 +546,7 @@ common_type (tree t1, tree t2) { tree subtype1 = code1 == COMPLEX_TYPE ? TREE_TYPE (t1) : t1; tree subtype2 = code2 == COMPLEX_TYPE ? TREE_TYPE (t2) : t2; - tree subtype = common_type (subtype1, subtype2); + tree subtype = c_common_type (subtype1, subtype2); if (code1 == COMPLEX_TYPE && TREE_TYPE (t1) == subtype) return t1; @@ -579,6 +616,18 @@ common_type (tree t1, tree t2) return t2; } +/* Wrapper around c_common_type that is used by c-common.c. ENUMERAL_TYPEs + are allowed here and are converted to their compatible integer types. */ +tree +common_type (tree t1, tree t2) +{ + 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); + return c_common_type (t1, 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. */ @@ -633,7 +682,8 @@ comptypes (tree type1, tree type2) definition. Note that we already checked for equality of the type qualifiers (just above). */ - if (TYPE_MAIN_VARIANT (t1) == TYPE_MAIN_VARIANT (t2)) + if (TREE_CODE (t1) != ARRAY_TYPE + && TYPE_MAIN_VARIANT (t1) == TYPE_MAIN_VARIANT (t2)) return 1; /* 1 if no need for warning yet, 2 if warning cause has been seen. */ @@ -650,6 +700,10 @@ comptypes (tree type1, tree type2) protocol qualifiers may be involved. */ if (c_dialect_objc () && (val = objc_comptypes (t1, t2, 0)) >= 0) break; + /* Do not remove mode or aliasing information. */ + if (TYPE_MODE (t1) != TYPE_MODE (t2) + || TYPE_REF_CAN_ALIAS_ALL (t1) != TYPE_REF_CAN_ALIAS_ALL (t2)) + break; val = (TREE_TYPE (t1) == TREE_TYPE (t2) ? 1 : comptypes (TREE_TYPE (t1), TREE_TYPE (t2))); break; @@ -731,13 +785,21 @@ static int comp_target_types (tree ttl, tree ttr, int reflexive) { int val; + tree mvl, mvr; /* Give objc_comptypes a crack at letting these types through. */ if ((val = objc_comptypes (ttl, ttr, reflexive)) >= 0) return val; - val = comptypes (TYPE_MAIN_VARIANT (TREE_TYPE (ttl)), - TYPE_MAIN_VARIANT (TREE_TYPE (ttr))); + /* Do not lose qualifiers on element types of array types that are + pointer targets by taking their TYPE_MAIN_VARIANT. */ + mvl = TREE_TYPE (ttl); + mvr = TREE_TYPE (ttr); + if (TREE_CODE (mvl) != ARRAY_TYPE) + mvl = TYPE_MAIN_VARIANT (mvl); + if (TREE_CODE (mvr) != ARRAY_TYPE) + mvr = TYPE_MAIN_VARIANT (mvr); + val = comptypes (mvl, mvr); if (val == 2 && pedantic) pedwarn ("types are not quite compatible"); @@ -1039,62 +1101,80 @@ type_lists_compatible_p (tree args1, tree args2) while (1) { + tree a1, mv1, a2, mv2; if (args1 == 0 && args2 == 0) return val; /* If one list is shorter than the other, they fail to match. */ if (args1 == 0 || args2 == 0) return 0; + mv1 = a1 = TREE_VALUE (args1); + mv2 = a2 = TREE_VALUE (args2); + if (mv1 && mv1 != error_mark_node && TREE_CODE (mv1) != ARRAY_TYPE) + mv1 = TYPE_MAIN_VARIANT (mv1); + if (mv2 && mv2 != error_mark_node && TREE_CODE (mv2) != ARRAY_TYPE) + mv2 = TYPE_MAIN_VARIANT (mv2); /* A null pointer instead of a type means there is supposed to be an argument but nothing is specified about what type it has. So match anything that self-promotes. */ - if (TREE_VALUE (args1) == 0) + if (a1 == 0) { - if (c_type_promotes_to (TREE_VALUE (args2)) != TREE_VALUE (args2)) + if (c_type_promotes_to (a2) != a2) return 0; } - else if (TREE_VALUE (args2) == 0) + else if (a2 == 0) { - if (c_type_promotes_to (TREE_VALUE (args1)) != TREE_VALUE (args1)) + if (c_type_promotes_to (a1) != a1) return 0; } /* If one of the lists has an error marker, ignore this arg. */ - else if (TREE_CODE (TREE_VALUE (args1)) == ERROR_MARK - || TREE_CODE (TREE_VALUE (args2)) == ERROR_MARK) + else if (TREE_CODE (a1) == ERROR_MARK + || TREE_CODE (a2) == ERROR_MARK) ; - else if (!(newval = comptypes (TYPE_MAIN_VARIANT (TREE_VALUE (args1)), - TYPE_MAIN_VARIANT (TREE_VALUE (args2))))) + else if (!(newval = comptypes (mv1, mv2))) { /* Allow wait (union {union wait *u; int *i} *) and wait (union wait *) to be compatible. */ - if (TREE_CODE (TREE_VALUE (args1)) == UNION_TYPE - && (TYPE_NAME (TREE_VALUE (args1)) == 0 - || TYPE_TRANSPARENT_UNION (TREE_VALUE (args1))) - && TREE_CODE (TYPE_SIZE (TREE_VALUE (args1))) == INTEGER_CST - && tree_int_cst_equal (TYPE_SIZE (TREE_VALUE (args1)), - TYPE_SIZE (TREE_VALUE (args2)))) + if (TREE_CODE (a1) == UNION_TYPE + && (TYPE_NAME (a1) == 0 + || TYPE_TRANSPARENT_UNION (a1)) + && TREE_CODE (TYPE_SIZE (a1)) == INTEGER_CST + && tree_int_cst_equal (TYPE_SIZE (a1), + TYPE_SIZE (a2))) { tree memb; - for (memb = TYPE_FIELDS (TREE_VALUE (args1)); + for (memb = TYPE_FIELDS (a1); memb; memb = TREE_CHAIN (memb)) - if (comptypes (TREE_TYPE (memb), TREE_VALUE (args2))) - break; + { + tree mv3 = TREE_TYPE (memb); + if (mv3 && mv3 != error_mark_node + && TREE_CODE (mv3) != ARRAY_TYPE) + mv3 = TYPE_MAIN_VARIANT (mv3); + if (comptypes (mv3, mv2)) + break; + } if (memb == 0) return 0; } - else if (TREE_CODE (TREE_VALUE (args2)) == UNION_TYPE - && (TYPE_NAME (TREE_VALUE (args2)) == 0 - || TYPE_TRANSPARENT_UNION (TREE_VALUE (args2))) - && TREE_CODE (TYPE_SIZE (TREE_VALUE (args2))) == INTEGER_CST - && tree_int_cst_equal (TYPE_SIZE (TREE_VALUE (args2)), - TYPE_SIZE (TREE_VALUE (args1)))) + else if (TREE_CODE (a2) == UNION_TYPE + && (TYPE_NAME (a2) == 0 + || TYPE_TRANSPARENT_UNION (a2)) + && TREE_CODE (TYPE_SIZE (a2)) == INTEGER_CST + && tree_int_cst_equal (TYPE_SIZE (a2), + TYPE_SIZE (a1))) { tree memb; - for (memb = TYPE_FIELDS (TREE_VALUE (args2)); + for (memb = TYPE_FIELDS (a2); memb; memb = TREE_CHAIN (memb)) - if (comptypes (TREE_TYPE (memb), TREE_VALUE (args1))) - break; + { + tree mv3 = TREE_TYPE (memb); + if (mv3 && mv3 != error_mark_node + && TREE_CODE (mv3) != ARRAY_TYPE) + mv3 = TYPE_MAIN_VARIANT (mv3); + if (comptypes (mv3, mv1)) + break; + } if (memb == 0) return 0; } @@ -1113,7 +1193,7 @@ type_lists_compatible_p (tree args1, tree args2) /* Compute the size to increment a pointer by. */ -tree +static tree c_size_in_bytes (tree type) { enum tree_code code = TREE_CODE (type); @@ -1274,47 +1354,17 @@ default_function_array_conversion (tree exp) return exp; } -/* Perform default promotions for C data used in expressions. - Arrays and functions are converted to pointers; - enumeral types or short or char, to int. - In addition, manifest constants symbols are replaced by their values. */ + +/* EXP is an expression of integer type. Apply the integer promotions + to it and return the promoted value. */ tree -default_conversion (tree exp) +perform_integral_promotions (tree exp) { - tree orig_exp; tree type = TREE_TYPE (exp); enum tree_code code = TREE_CODE (type); - if (code == FUNCTION_TYPE || code == ARRAY_TYPE) - return default_function_array_conversion (exp); - - /* Constants can be used directly unless they're not loadable. */ - if (TREE_CODE (exp) == CONST_DECL) - exp = DECL_INITIAL (exp); - - /* Replace a nonvolatile const static variable with its value unless - it is an array, in which case we must be sure that taking the - address of the array produces consistent results. */ - else if (optimize && TREE_CODE (exp) == VAR_DECL && code != ARRAY_TYPE) - { - exp = decl_constant_value_for_broken_optimization (exp); - type = TREE_TYPE (exp); - } - - /* Strip NON_LVALUE_EXPRs and no-op conversions, since we aren't using as - an lvalue. - - Do not use STRIP_NOPS here! It will remove conversions from pointer - to integer and cause infinite recursion. */ - orig_exp = exp; - while (TREE_CODE (exp) == NON_LVALUE_EXPR - || (TREE_CODE (exp) == NOP_EXPR - && TREE_TYPE (TREE_OPERAND (exp, 0)) == TREE_TYPE (exp))) - exp = TREE_OPERAND (exp, 0); - - if (TREE_NO_WARNING (orig_exp)) - TREE_NO_WARNING (exp) = 1; + gcc_assert (INTEGRAL_TYPE_P (type)); /* Normally convert enums to int, but convert wide enums to something wider. */ @@ -1329,6 +1379,8 @@ default_conversion (tree exp) return convert (type, exp); } + /* ??? This should no longer be needed now bit-fields have their + proper types. */ if (TREE_CODE (exp) == COMPONENT_REF && DECL_C_BIT_FIELD (TREE_OPERAND (exp, 1)) /* If it's thinner than an int, promote it like a @@ -1347,6 +1399,48 @@ default_conversion (tree exp) return convert (integer_type_node, exp); } + return exp; +} + + +/* Perform default promotions for C data used in expressions. + Arrays and functions are converted to pointers; + enumeral types or short or char, to int. + In addition, manifest constants symbols are replaced by their values. */ + +tree +default_conversion (tree exp) +{ + tree orig_exp; + tree type = TREE_TYPE (exp); + enum tree_code code = TREE_CODE (type); + + if (code == FUNCTION_TYPE || code == ARRAY_TYPE) + return default_function_array_conversion (exp); + + /* Constants can be used directly unless they're not loadable. */ + if (TREE_CODE (exp) == CONST_DECL) + exp = DECL_INITIAL (exp); + + /* Replace a nonvolatile const static variable with its value unless + it is an array, in which case we must be sure that taking the + address of the array produces consistent results. */ + else if (optimize && TREE_CODE (exp) == VAR_DECL && code != ARRAY_TYPE) + { + exp = decl_constant_value_for_broken_optimization (exp); + type = TREE_TYPE (exp); + } + + /* Strip no-op conversions. */ + orig_exp = exp; + STRIP_TYPE_NOPS (exp); + + if (TREE_NO_WARNING (orig_exp)) + TREE_NO_WARNING (exp) = 1; + + if (INTEGRAL_TYPE_P (type)) + return perform_integral_promotions (exp); + if (code == VOID_TYPE) { error ("void value not ignored as it ought to be"); @@ -1375,7 +1469,7 @@ lookup_field (tree decl, tree component) find the element. Otherwise, do a linear search. TYPE_LANG_SPECIFIC will always be set for structures which have many elements. */ - if (TYPE_LANG_SPECIFIC (type)) + if (TYPE_LANG_SPECIFIC (type) && TYPE_LANG_SPECIFIC (type)->s) { int bot, top, half; tree *field_array = &TYPE_LANG_SPECIFIC (type)->s->elts[0]; @@ -1478,8 +1572,7 @@ build_component_ref (tree datum, tree component) if (!field) { - error ("%qT has no member named %qs", type, - IDENTIFIER_POINTER (component)); + error ("%qT has no member named %qE", type, component); return error_mark_node; } @@ -1514,8 +1607,8 @@ build_component_ref (tree datum, tree component) return ref; } else if (code != ERROR_MARK) - error ("request for member %qs in something not a structure or union", - IDENTIFIER_POINTER (component)); + error ("request for member %qE in something not a structure or union", + component); return error_mark_node; } @@ -1539,7 +1632,12 @@ build_indirect_ref (tree ptr, const char *errorstring) else { tree t = TREE_TYPE (type); - tree ref = build1 (INDIRECT_REF, TYPE_MAIN_VARIANT (t), pointer); + tree mvt = t; + tree ref; + + if (TREE_CODE (mvt) != ARRAY_TYPE) + mvt = TYPE_MAIN_VARIANT (mvt); + ref = build1 (INDIRECT_REF, mvt, pointer); if (!COMPLETE_OR_VOID_TYPE_P (t) && TREE_CODE (t) != ARRAY_TYPE) { @@ -1580,39 +1678,58 @@ build_indirect_ref (tree ptr, const char *errorstring) tree build_array_ref (tree array, tree index) { - if (index == 0) - { - error ("subscript missing in array reference"); - return error_mark_node; - } - + bool swapped = false; if (TREE_TYPE (array) == error_mark_node || TREE_TYPE (index) == error_mark_node) return error_mark_node; - if (TREE_CODE (TREE_TYPE (array)) == ARRAY_TYPE) + if (TREE_CODE (TREE_TYPE (array)) != ARRAY_TYPE + && TREE_CODE (TREE_TYPE (array)) != POINTER_TYPE) { - tree rval, type; - - /* Subscripting with type char is likely to lose - on a machine where chars are signed. - So warn on any machine, but optionally. - Don't warn for unsigned char since that type is safe. - Don't warn for signed char because anyone who uses that - must have done so deliberately. */ - if (warn_char_subscripts - && TYPE_MAIN_VARIANT (TREE_TYPE (index)) == char_type_node) - warning ("array subscript has type %"); - - /* Apply default promotions *after* noticing character types. */ - index = default_conversion (index); - - /* Require integer *after* promotion, for sake of enums. */ - if (TREE_CODE (TREE_TYPE (index)) != INTEGER_TYPE) + tree temp; + if (TREE_CODE (TREE_TYPE (index)) != ARRAY_TYPE + && TREE_CODE (TREE_TYPE (index)) != POINTER_TYPE) { - error ("array subscript is not an integer"); + error ("subscripted value is neither array nor pointer"); return error_mark_node; } + temp = array; + array = index; + index = temp; + swapped = true; + } + + if (!INTEGRAL_TYPE_P (TREE_TYPE (index))) + { + error ("array subscript is not an integer"); + return error_mark_node; + } + + if (TREE_CODE (TREE_TYPE (TREE_TYPE (array))) == FUNCTION_TYPE) + { + error ("subscripted value is pointer to function"); + return error_mark_node; + } + + /* Subscripting with type char is likely to lose on a machine where + chars are signed. So warn on any machine, but optionally. Don't + warn for unsigned char since that type is safe. Don't warn for + signed char because anyone who uses that must have done so + deliberately. ??? Existing practice has also been to warn only + when the char index is syntactically the index, not for + char[array]. */ + if (warn_char_subscripts && !swapped + && TYPE_MAIN_VARIANT (TREE_TYPE (index)) == char_type_node) + warning ("array subscript has type %"); + + /* Apply default promotions *after* noticing character types. */ + index = default_conversion (index); + + gcc_assert (TREE_CODE (TREE_TYPE (index)) == INTEGER_TYPE); + + if (TREE_CODE (TREE_TYPE (array)) == ARRAY_TYPE) + { + tree rval, type; /* An array that is indexed by a non-constant cannot be stored in a register; we must be able to do @@ -1648,7 +1765,9 @@ build_array_ref (tree array, tree index) pedwarn ("ISO C90 forbids subscripting non-lvalue array"); } - type = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (array))); + type = TREE_TYPE (TREE_TYPE (array)); + if (TREE_CODE (type) != ARRAY_TYPE) + type = TYPE_MAIN_VARIANT (type); 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. */ @@ -1667,72 +1786,36 @@ build_array_ref (tree array, tree index) | TREE_THIS_VOLATILE (array)); return require_complete_type (fold (rval)); } + else + { + tree ar = default_conversion (array); - { - tree ar = default_conversion (array); - tree ind = default_conversion (index); - - /* Do the same warning check as above, but only on the part that's - syntactically the index and only if it is also semantically - the 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 %"); - - /* Put the integer in IND to simplify error checking. */ - if (TREE_CODE (TREE_TYPE (ar)) == INTEGER_TYPE) - { - tree temp = ar; - ar = ind; - ind = temp; - } + if (ar == error_mark_node) + return ar; - if (ar == error_mark_node) - return ar; + gcc_assert (TREE_CODE (TREE_TYPE (ar)) == POINTER_TYPE); + gcc_assert (TREE_CODE (TREE_TYPE (TREE_TYPE (ar))) != FUNCTION_TYPE); - if (TREE_CODE (TREE_TYPE (ar)) != POINTER_TYPE - || TREE_CODE (TREE_TYPE (TREE_TYPE (ar))) == FUNCTION_TYPE) - { - error ("subscripted value is neither array nor pointer"); - return error_mark_node; - } - if (TREE_CODE (TREE_TYPE (ind)) != INTEGER_TYPE) - { - error ("array subscript is not an integer"); - return error_mark_node; - } - - return build_indirect_ref (build_binary_op (PLUS_EXPR, ar, ind, 0), - "array indexing"); - } + return build_indirect_ref (build_binary_op (PLUS_EXPR, ar, index, 0), + "array indexing"); + } } /* Build an external reference to identifier ID. FUN indicates - whether this will be used for a function call. */ + whether this will be used for a function call. LOC is the source + location of the identifier. */ tree -build_external_ref (tree id, int fun) +build_external_ref (tree id, int fun, location_t loc) { tree ref; tree decl = lookup_name (id); - tree objc_ivar = objc_lookup_ivar (id); + + /* In Objective-C, an instance variable (ivar) may be preferred to + whatever lookup_name() found. */ + decl = objc_lookup_ivar (decl, id); if (decl && decl != error_mark_node) - { - /* Properly declared variable or function reference. */ - if (!objc_ivar) - ref = decl; - else if (decl != objc_ivar && !DECL_FILE_SCOPE_P (decl)) - { - warning ("local declaration of %qs hides instance variable", - IDENTIFIER_POINTER (id)); - ref = decl; - } - else - ref = objc_ivar; - } - else if (objc_ivar) - ref = objc_ivar; + ref = decl; else if (fun) /* Implicit function declaration. */ ref = implicitly_declare (id); @@ -1742,7 +1825,7 @@ build_external_ref (tree id, int fun) return error_mark_node; else { - undeclared_variable (id); + undeclared_variable (id, loc); return error_mark_node; } @@ -1805,7 +1888,7 @@ static struct maybe_used_decl *maybe_used_decls; a VLA type or the operand of typeof is a variably modified type. */ -void +static void record_maybe_used_decl (tree decl) { struct maybe_used_decl *t = XOBNEW (&parser_obstack, struct maybe_used_decl); @@ -1976,7 +2059,10 @@ 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. */ @@ -2005,7 +2091,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. @@ -2014,7 +2101,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. @@ -2022,11 +2110,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. */ @@ -2037,22 +2135,23 @@ 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; + const char *invalid_func_diag; if (type == void_type_node) { - if (name) - error ("too many arguments to function %qs", - IDENTIFIER_POINTER (name)); - else - error ("too many arguments to function"); + error ("too many arguments to function %qE", function); break; } - /* 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. */ - if (TREE_CODE (val) == NON_LVALUE_EXPR) - val = TREE_OPERAND (val, 0); + if (selector && argnum > 2) + { + rname = selector; + argnum -= 2; + } + + STRIP_TYPE_NOPS (val); val = default_function_array_conversion (val); @@ -2063,7 +2162,7 @@ convert_arguments (tree typelist, tree values, tree name, tree fundecl) /* Formal parm type is specified by a function prototype. */ tree parmval; - if (!COMPLETE_TYPE_P (type)) + if (type == error_mark_node || !COMPLETE_TYPE_P (type)) { error ("type of formal parameter %d is incomplete", parmnum + 1); parmval = val; @@ -2078,22 +2177,34 @@ convert_arguments (tree typelist, tree values, tree name, tree fundecl) 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. */ @@ -2103,9 +2214,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 % rather than " - "% 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 @@ -2123,7 +2234,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 @@ -2136,11 +2248,6 @@ convert_arguments (tree typelist, tree values, tree name, tree fundecl) /* Change in signedness doesn't matter if a constant value is unaffected. */ ; - /* Likewise for a constant in a NOP_EXPR. */ - else if (TREE_CODE (val) == NOP_EXPR - && TREE_CODE (TREE_OPERAND (val, 0)) == INTEGER_CST - && int_fits_type_p (TREE_OPERAND (val, 0), type)) - ; /* If the value is extended from a narrower unsigned type, it doesn't matter whether we pass it as signed or unsigned; the value @@ -2149,15 +2256,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) @@ -2171,6 +2280,12 @@ convert_arguments (tree typelist, tree values, tree name, tree fundecl) < TYPE_PRECISION (double_type_node))) /* Convert `float' to `double'. */ result = tree_cons (NULL_TREE, convert (double_type_node, val), result); + else if ((invalid_func_diag = + targetm.calls.invalid_arg_for_unprototyped_fn (typelist, fundecl, val))) + { + error (invalid_func_diag); + return error_mark_node; + } else /* Convert `short' and `char' to full-size `int'. */ result = tree_cons (NULL_TREE, default_conversion (val), result); @@ -2181,11 +2296,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 %qs", - 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); @@ -2451,6 +2563,8 @@ build_unary_op (enum tree_code code, tree xarg, int flag) break; case TRUTH_NOT_EXPR: + /* ??? Why do most validation here but that for non-lvalue arrays + in c_objc_common_truthvalue_conversion? */ if (typecode != INTEGER_TYPE && typecode != REAL_TYPE && typecode != POINTER_TYPE && typecode != COMPLEX_TYPE @@ -2460,7 +2574,7 @@ build_unary_op (enum tree_code code, tree xarg, int flag) error ("wrong type argument to unary exclamation mark"); return error_mark_node; } - arg = lang_hooks.truthvalue_conversion (arg); + arg = c_objc_common_truthvalue_conversion (arg); return invert_truthvalue (arg); case NOP_EXPR: @@ -2622,13 +2736,8 @@ build_unary_op (enum tree_code code, tree xarg, int flag) if (!c_mark_addressable (arg)) return error_mark_node; - 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; - } + gcc_assert (TREE_CODE (arg) != COMPONENT_REF + || !DECL_C_BIT_FIELD (TREE_OPERAND (arg, 1))); argtype = build_pointer_type (argtype); @@ -2660,7 +2769,7 @@ build_unary_op (enum tree_code code, tree xarg, int flag) Lvalues can be assigned, unless their type has TYPE_READONLY. Lvalues can have their address taken, unless they have C_DECL_REGISTER. */ -int +static int lvalue_p (tree ref) { enum tree_code code = TREE_CODE (ref); @@ -2692,43 +2801,6 @@ lvalue_p (tree ref) return 0; } } - -/* Return nonzero if REF is an lvalue valid for this language; - otherwise, print an error message and return zero. USE says - how the lvalue is being used and so selects the error message. */ - -static int -lvalue_or_else (tree ref, enum lvalue_use use) -{ - int win = lvalue_p (ref); - - 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; -} - /* Give an error for storing in something that is 'const'. */ @@ -2747,21 +2819,37 @@ readonly_error (tree arg, enum lvalue_use use) if (TYPE_READONLY (TREE_TYPE (TREE_OPERAND (arg, 0)))) readonly_error (TREE_OPERAND (arg, 0), use); else - 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)))); + error (READONLY_MSG (N_("assignment of read-only member %qD"), + N_("increment of read-only member %qD"), + N_("decrement of read-only member %qD")), + TREE_OPERAND (arg, 1)); } else if (TREE_CODE (arg) == VAR_DECL) - 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))); + error (READONLY_MSG (N_("assignment of read-only variable %qD"), + N_("increment of read-only variable %qD"), + N_("decrement of read-only variable %qD")), + arg); else error (READONLY_MSG (N_("assignment of read-only location"), N_("increment of read-only location"), N_("decrement of read-only location"))); } + + +/* Return nonzero if REF is an lvalue valid for this language; + otherwise, print an error message and return zero. USE says + how the lvalue is being used and so selects the error message. */ + +static int +lvalue_or_else (tree ref, enum lvalue_use use) +{ + int win = lvalue_p (ref); + + if (!win) + lvalue_error (use); + + return win; +} /* Mark EXP saying that we need to be able to take the address of it; it should not be allocated in a register. @@ -2778,8 +2866,8 @@ c_mark_addressable (tree exp) case COMPONENT_REF: if (DECL_C_BIT_FIELD (TREE_OPERAND (x, 1))) { - error ("cannot take address of bit-field %qs", - IDENTIFIER_POINTER (DECL_NAME (TREE_OPERAND (x, 1)))); + error + ("cannot take address of bit-field %qD", TREE_OPERAND (x, 1)); return false; } @@ -2806,24 +2894,19 @@ c_mark_addressable (tree exp) { if (TREE_PUBLIC (x) || TREE_STATIC (x) || DECL_EXTERNAL (x)) { - error ("global register variable %qs used in nested function", - IDENTIFIER_POINTER (DECL_NAME (x))); + error + ("global register variable %qD used in nested function", x); return false; } - pedwarn ("register variable %qs used in nested function", - IDENTIFIER_POINTER (DECL_NAME (x))); + pedwarn ("register variable %qD used in nested function", x); } else if (C_DECL_REGISTER (x)) { if (TREE_PUBLIC (x) || TREE_STATIC (x) || DECL_EXTERNAL (x)) - { - error ("address of global register variable %qs requested", - IDENTIFIER_POINTER (DECL_NAME (x))); - return false; - } - - pedwarn ("address of register variable %qs requested", - IDENTIFIER_POINTER (DECL_NAME (x))); + error ("address of global register variable %qD requested", x); + else + error ("address of register variable %qD requested", x); + return false; } /* drops in */ @@ -2847,8 +2930,6 @@ build_conditional_expr (tree ifexp, tree op1, tree op2) tree result_type = NULL; tree orig_op1 = op1, orig_op2 = op2; - ifexp = lang_hooks.truthvalue_conversion (default_conversion (ifexp)); - /* Promote both alternatives. */ if (TREE_CODE (TREE_TYPE (op1)) != VOID_TYPE) @@ -2888,7 +2969,7 @@ build_conditional_expr (tree ifexp, tree op1, tree op2) && (code2 == INTEGER_TYPE || code2 == REAL_TYPE || code2 == COMPLEX_TYPE)) { - result_type = common_type (type1, type2); + result_type = c_common_type (type1, type2); /* If -Wsign-compare, warn here if type1 and type2 have different signedness. We'll promote the signed to unsigned @@ -3014,10 +3095,6 @@ build_compound_expr (tree expr1, tree expr2) /* Convert arrays and functions to pointers. */ expr2 = default_function_array_conversion (expr2); - /* Don't let (0, 0) be null pointer constant. */ - if (integer_zerop (expr2)) - expr2 = non_lvalue (expr2); - if (!TREE_SIDE_EFFECTS (expr1)) { /* The left-hand operand of a comma expression is like an expression @@ -3238,9 +3315,6 @@ build_c_cast (tree type, tree expr) pedwarn ("ISO C forbids conversion of object pointer to function pointer type"); ovalue = value; - /* Replace a nonvolatile const static variable with its value. */ - if (optimize && TREE_CODE (value) == VAR_DECL) - value = decl_constant_value (value); value = convert (type, value); /* Ignore any integer overflow caused by the cast. */ @@ -3260,12 +3334,6 @@ build_c_cast (tree type, tree expr) } } - /* 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); @@ -3311,11 +3379,7 @@ build_modify_expr (tree lhs, enum tree_code modifycode, tree rhs) if (TREE_CODE (lhs) == ERROR_MARK || TREE_CODE (rhs) == ERROR_MARK) return error_mark_node; - /* Strip NON_LVALUE_EXPRs since we aren't using as an lvalue. */ - /* Do not use STRIP_NOPS here. We do not want an enumerator - whose value is 0 to count as a null pointer constant. */ - if (TREE_CODE (rhs) == NON_LVALUE_EXPR) - rhs = TREE_OPERAND (rhs, 0); + STRIP_TYPE_NOPS (rhs); newrhs = rhs; @@ -3362,7 +3426,7 @@ 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; @@ -3379,7 +3443,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); } @@ -3388,27 +3452,68 @@ 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; + } + } - /* Strip NON_LVALUE_EXPRs since we aren't using as an lvalue. */ - /* Do not use STRIP_NOPS here. We do not want an enumerator - whose value is 0 to count as a null pointer constant. */ - if (TREE_CODE (rhs) == NON_LVALUE_EXPR) - rhs = TREE_OPERAND (rhs, 0); + /* 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_TYPE_NOPS (rhs); if (TREE_CODE (TREE_TYPE (rhs)) == ARRAY_TYPE || TREE_CODE (TREE_TYPE (rhs)) == FUNCTION_TYPE) @@ -3435,6 +3540,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; } @@ -3479,7 +3589,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; @@ -3554,13 +3665,27 @@ 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)) @@ -3576,9 +3701,15 @@ convert_for_assignment (tree type, tree rhs, const char *errtype, { tree ttl = TREE_TYPE (type); tree ttr = TREE_TYPE (rhstype); + tree mvl = ttl; + tree mvr = ttr; bool is_opaque_pointer; int target_cmp = 0; /* Cache comp_target_types () result. */ + if (TREE_CODE (mvl) != ARRAY_TYPE) + mvl = TYPE_MAIN_VARIANT (mvl); + if (TREE_CODE (mvr) != ARRAY_TYPE) + mvr = TYPE_MAIN_VARIANT (mvr); /* Opaque pointers are treated like void pointers. */ is_opaque_pointer = (targetm.vector_opaque_p (type) || targetm.vector_opaque_p (rhstype)) @@ -3591,8 +3722,8 @@ convert_for_assignment (tree type, tree rhs, const char *errtype, if (VOID_TYPE_P (ttl) || VOID_TYPE_P (ttr) || (target_cmp = comp_target_types (type, rhstype, 0)) || is_opaque_pointer - || (c_common_unsigned_type (TYPE_MAIN_VARIANT (ttl)) - == c_common_unsigned_type (TYPE_MAIN_VARIANT (ttr)))) + || (c_common_unsigned_type (mvl) + == c_common_unsigned_type (mvr))) { if (pedantic && ((VOID_TYPE_P (ttl) && TREE_CODE (ttr) == FUNCTION_TYPE) @@ -3602,26 +3733,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 %", - 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 - warn_for_assignment ("pointer targets in %s differ in signedness", - errtype, funname, parmnum); + else if (warn_pointer_sign) + 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) @@ -3631,17 +3780,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; } @@ -3656,39 +3818,52 @@ convert_for_assignment (tree type, tree rhs, const char *errtype, && 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); + 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 %qs", - parmnum - 2, IDENTIFIER_POINTER (selector)); - else - error ("incompatible type for argument %d of %qs", - 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; } @@ -3709,56 +3884,14 @@ c_convert_parm_for_inlining (tree parm, tree value, tree fn, int argnum) 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, 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; - } - gcc_assert (argnum > 0); - if (function) - { - /* Function name is known; supply it. */ - const char *const argstring = _("passing arg %d of '%s'"); - new_opname = (char *) 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 = (char *) 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. @@ -3822,8 +3955,7 @@ store_init_value (tree decl, tree init) { tree inside_init = init; - if (TREE_CODE (init) == NON_LVALUE_EXPR) - inside_init = TREE_OPERAND (init, 0); + STRIP_TYPE_NOPS (inside_init); inside_init = fold (inside_init); if (TREE_CODE (inside_init) == COMPOUND_LITERAL_EXPR) @@ -4043,11 +4175,7 @@ digest_init (tree type, tree init, bool strict_string, int require_constant) || TREE_TYPE (init) == error_mark_node) return error_mark_node; - /* Strip NON_LVALUE_EXPRs since we aren't using as an lvalue. */ - /* Do not use STRIP_NOPS here. We do not want an enumerator - whose value is 0 to count as a null pointer constant. */ - if (TREE_CODE (init) == NON_LVALUE_EXPR) - inside_init = TREE_OPERAND (init, 0); + STRIP_TYPE_NOPS (inside_init); inside_init = fold (inside_init); @@ -4121,18 +4249,32 @@ digest_init (tree type, tree init, bool strict_string, int require_constant) /* 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))) - return inside_init; - else - return build_vector (type, CONSTRUCTOR_ELTS (inside_init)); - } + 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))) + return inside_init; + + if (TREE_CODE (inside_init) == CONSTRUCTOR) + { + tree link; + + /* Iterate through elements and check if all constructor + elements are *_CSTs. */ + for (link = CONSTRUCTOR_ELTS (inside_init); + link; + link = TREE_CHAIN (link)) + if (! CONSTANT_CLASS_P (TREE_VALUE (link))) + break; + + if (link == NULL) + return build_vector (type, CONSTRUCTOR_ELTS (inside_init)); + } + } /* Any type can be initialized from an expression of the same type, optionally with braces. */ @@ -4226,7 +4368,7 @@ digest_init (tree type, tree init, bool strict_string, 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); /* Check to see if we have already given an error message. */ @@ -4328,9 +4470,6 @@ static struct init_node *constructor_pending_elts; /* The SPELLING_DEPTH of this constructor. */ 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. */ - /* DECL node for which an initializer is being read. 0 means we are reading a constructor expression such as (struct foo) {...}. */ @@ -4382,7 +4521,7 @@ struct constructor_stack char designated; }; -struct constructor_stack *constructor_stack; +static struct constructor_stack *constructor_stack; /* This stack represents designators from some range designator up to the last designator in the list. */ @@ -4397,7 +4536,7 @@ struct constructor_range_stack tree fields; }; -struct constructor_range_stack *constructor_range_stack; +static struct constructor_range_stack *constructor_range_stack; /* This stack records separate initializers that are nested. Nested initializers can't happen in ANSI C, but GNU C allows them @@ -4418,7 +4557,7 @@ struct initializer_stack char require_constant_elements; }; -struct initializer_stack *initializer_stack; +static struct initializer_stack *initializer_stack; /* Prepare to parse and output the initializer for variable DECL. */ @@ -4445,7 +4584,7 @@ start_init (tree decl, tree asmspec_tree ATTRIBUTE_UNUSED, int top_level) constructor_designated = 0; constructor_top_level = top_level; - if (decl != 0) + if (decl != 0 && decl != error_mark_node) { require_constant_value = TREE_STATIC (decl); require_constant_elements @@ -4598,7 +4737,10 @@ really_start_incremental_init (tree type) TYPE_MIN_VALUE (TYPE_DOMAIN (constructor_type))); } else - constructor_index = bitsize_zero_node; + { + constructor_index = bitsize_zero_node; + constructor_max_index = NULL_TREE; + } constructor_unfilled_index = constructor_index; } @@ -4802,7 +4944,8 @@ push_init_level (int implicit) } else { - warning_init ("braces around scalar initializer"); + if (constructor_type != error_mark_node) + warning_init ("braces around scalar initializer"); constructor_fields = constructor_type; constructor_unfilled_fields = constructor_type; } @@ -5001,12 +5144,6 @@ set_designator (int array) return 0; } - if (constructor_no_implicit) - { - error_init ("initialization designators may not nest"); - return 1; - } - switch (TREE_CODE (constructor_type)) { case RECORD_TYPE: @@ -5080,21 +5217,6 @@ set_init_index (tree first, tree last) return; } - while ((TREE_CODE (first) == NOP_EXPR - || TREE_CODE (first) == CONVERT_EXPR - || TREE_CODE (first) == NON_LVALUE_EXPR) - && (TYPE_MODE (TREE_TYPE (first)) - == TYPE_MODE (TREE_TYPE (TREE_OPERAND (first, 0))))) - first = TREE_OPERAND (first, 0); - - if (last) - while ((TREE_CODE (last) == NOP_EXPR - || TREE_CODE (last) == CONVERT_EXPR - || TREE_CODE (last) == NON_LVALUE_EXPR) - && (TYPE_MODE (TREE_TYPE (last)) - == TYPE_MODE (TREE_TYPE (TREE_OPERAND (last, 0))))) - last = TREE_OPERAND (last, 0); - if (TREE_CODE (first) != INTEGER_CST) error_init ("nonconstant array index in initializer"); else if (last != 0 && TREE_CODE (last) != INTEGER_CST) @@ -5165,8 +5287,7 @@ set_init_label (tree fieldname) } if (tail == 0) - error ("unknown field %qs specified in initializer", - IDENTIFIER_POINTER (fieldname)); + error ("unknown field %qE specified in initializer", fieldname); else { constructor_fields = tail; @@ -5582,7 +5703,7 @@ static void output_init_element (tree value, bool strict_string, tree type, tree field, int pending) { - if (type == error_mark_node) + if (type == error_mark_node || value == error_mark_node) { constructor_erroneous = 1; return; @@ -5977,7 +6098,7 @@ process_init_element (struct c_expr 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.value != 0 && !constructor_no_implicit + else if (value.value != 0 && value.value != error_mark_node && TYPE_MAIN_VARIANT (TREE_TYPE (value.value)) != fieldtype && (fieldcode == RECORD_TYPE || fieldcode == ARRAY_TYPE @@ -6065,7 +6186,7 @@ process_init_element (struct c_expr 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.value != 0 && !constructor_no_implicit + else if (value.value != 0 && value.value != error_mark_node && TYPE_MAIN_VARIANT (TREE_TYPE (value.value)) != fieldtype && (fieldcode == RECORD_TYPE || fieldcode == ARRAY_TYPE @@ -6105,7 +6226,7 @@ process_init_element (struct c_expr 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.value != 0 && !constructor_no_implicit + else if (value.value != 0 && value.value != error_mark_node && TYPE_MAIN_VARIANT (TREE_TYPE (value.value)) != elttype && (eltcode == RECORD_TYPE || eltcode == ARRAY_TYPE @@ -6170,7 +6291,8 @@ process_init_element (struct c_expr value) /* Handle the sole element allowed in a braced initializer for a scalar variable. */ - else if (constructor_fields == 0) + else if (constructor_type != error_mark_node + && constructor_fields == 0) { pedwarn_init ("excess elements in scalar initializer"); break; @@ -6262,47 +6384,80 @@ build_asm_expr (tree string, tree outputs, tree inputs, tree clobbers, tree args; int i; const char *constraint; + const char **oconstraints; bool allows_mem, allows_reg, is_inout; - int ninputs; - int noutputs; + int ninputs, noutputs; ninputs = list_length (inputs); noutputs = list_length (outputs); + oconstraints = (const char **) alloca (noutputs * sizeof (const char *)); + + string = resolve_asm_operand_names (string, outputs, inputs); /* Remove output conversions that change the type but not the mode. */ for (i = 0, tail = outputs; tail; ++i, tail = TREE_CHAIN (tail)) { tree output = TREE_VALUE (tail); + + /* ??? Really, this should not be here. Users should be using a + proper lvalue, dammit. But there's a long history of using casts + in the output operands. In cases like longlong.h, this becomes a + primitive form of typechecking -- if the cast can be removed, then + the output operand had a type of the proper width; otherwise we'll + get an error. Gross, but ... */ STRIP_NOPS (output); - TREE_VALUE (tail) = output; - lvalue_or_else (output, lv_asm); + + if (!lvalue_or_else (output, lv_asm)) + output = error_mark_node; constraint = TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (tail))); + oconstraints[i] = constraint; - if (!parse_output_constraint (&constraint, i, ninputs, noutputs, - &allows_mem, &allows_reg, &is_inout)) - { - /* By marking this operand as erroneous, we will not try - to process this operand again in expand_asm_operands. */ - TREE_VALUE (tail) = error_mark_node; - continue; - } + if (parse_output_constraint (&constraint, i, ninputs, noutputs, + &allows_mem, &allows_reg, &is_inout)) + { + /* If the operand is going to end up in memory, + mark it addressable. */ + if (!allows_reg && !c_mark_addressable (output)) + output = error_mark_node; + } + else + output = error_mark_node; - /* If the operand is a DECL that is going to end up in - memory, assume it is addressable. This is a bit more - conservative than it would ideally be; the exact test is - buried deep in expand_asm_operands and depends on the - DECL_RTL for the OPERAND -- which we don't have at this - point. */ - if (!allows_reg && DECL_P (output)) - c_mark_addressable (output); + TREE_VALUE (tail) = output; } /* Perform default conversions on array and function inputs. Don't do this for other types as it would screw up operands expected to be in memory. */ - for (tail = inputs; tail; tail = TREE_CHAIN (tail)) - TREE_VALUE (tail) = default_function_array_conversion (TREE_VALUE (tail)); + for (i = 0, tail = inputs; tail; ++i, tail = TREE_CHAIN (tail)) + { + tree input; + + constraint = TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (tail))); + input = TREE_VALUE (tail); + + input = default_function_array_conversion (input); + + if (parse_input_constraint (&constraint, i, ninputs, noutputs, 0, + oconstraints, &allows_mem, &allows_reg)) + { + /* If the operand is going to end up in memory, + mark it addressable. */ + if (!allows_reg && allows_mem) + { + /* Strip the nops as we allow this case. FIXME, this really + should be rejected or made deprecated. */ + STRIP_NOPS (input); + if (!c_mark_addressable (input)) + input = error_mark_node; + } + } + else + input = error_mark_node; + + TREE_VALUE (tail) = input; + } args = build_stmt (ASM_EXPR, string, outputs, inputs, clobbers); @@ -6312,6 +6467,7 @@ build_asm_expr (tree string, tree outputs, tree inputs, tree clobbers, ASM_VOLATILE_P (args) = 1; ASM_INPUT_P (args) = 1; } + return args; } @@ -6324,6 +6480,23 @@ c_finish_goto_label (tree label) if (!decl) return NULL_TREE; + if (C_DECL_UNJUMPABLE_STMT_EXPR (decl)) + { + error ("jump into statement expression"); + return NULL_TREE; + } + + if (!C_DECL_UNDEFINABLE_STMT_EXPR (decl)) + { + /* No jump from outside this statement expression context, so + record that there is a jump from within this context. */ + struct c_label_list *nlist; + nlist = XOBNEW (&parser_obstack, struct c_label_list); + nlist->next = label_context_stack->labels_used; + nlist->label = decl; + label_context_stack->labels_used = nlist; + } + TREE_USED (decl) = 1; return add_stmt (build1 (GOTO_EXPR, void_type_node, decl)); } @@ -6366,7 +6539,7 @@ c_finish_return (tree retval) } 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; @@ -6450,6 +6623,11 @@ struct c_switch { of the GNU case range extension. */ splay_tree cases; + /* Number of nested statement expressions within this switch + statement; if nonzero, case and default labels may not + appear. */ + unsigned int blocked_stmt_expr; + /* The next node on the stack. */ struct c_switch *next; }; @@ -6482,6 +6660,7 @@ c_start_case (tree exp) { error ("switch quantity not an integer"); exp = integer_zero_node; + orig_type = error_mark_node; } else { @@ -6500,10 +6679,10 @@ c_start_case (tree exp) /* Add this new SWITCH_STMT to the stack. */ cs = XNEW (struct c_switch); - cs->switch_stmt = build_stmt ((enum tree_code) SWITCH_STMT, exp, NULL_TREE, - orig_type); + cs->switch_stmt = build_stmt (SWITCH_STMT, exp, NULL_TREE, orig_type); cs->orig_type = orig_type; cs->cases = splay_tree_new (case_compare, NULL, NULL); + cs->blocked_stmt_expr = 0; cs->next = c_switch_stack; c_switch_stack = cs; @@ -6517,15 +6696,24 @@ do_case (tree low_value, tree high_value) { tree label = NULL_TREE; - if (c_switch_stack) + if (c_switch_stack && !c_switch_stack->blocked_stmt_expr) { label = c_add_case_label (c_switch_stack->cases, - SWITCH_COND (c_switch_stack->switch_stmt), + SWITCH_STMT_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 (c_switch_stack && c_switch_stack->blocked_stmt_expr) + { + if (low_value) + error ("case label in statement expression not containing " + "enclosing switch statement"); + else + error ("% label in statement expression not containing " + "enclosing switch statement"); + } else if (low_value) error ("case label not within a switch statement"); else @@ -6541,7 +6729,9 @@ c_finish_case (tree body) { struct c_switch *cs = c_switch_stack; - SWITCH_BODY (cs->switch_stmt) = body; + SWITCH_STMT_BODY (cs->switch_stmt) = body; + + gcc_assert (!cs->blocked_stmt_expr); /* Emit warnings as needed. */ c_do_switch_warnings (cs->cases, cs->switch_stmt); @@ -6634,10 +6824,17 @@ c_finish_loop (location_t start_locus, tree cond, tree incr, tree body, { 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) + /* If the condition is zero don't generate a loop construct. */ + if (cond && integer_zerop (cond)) + { + if (cond_is_first) + { + t = build_and_jump (&blab); + SET_EXPR_LOCATION (t, start_locus); + add_stmt (t); + } + } + else { tree top = build1 (LABEL_EXPR, void_type_node, NULL_TREE); @@ -6646,7 +6843,7 @@ c_finish_loop (location_t start_locus, tree cond, tree incr, tree body, then we just build a jump back to the top. */ exit = build_and_jump (&LABEL_EXPR_LABEL (top)); - if (cond) + if (cond && !integer_nonzerop (cond)) { /* Canonicalize the loop condition to the end. This means generating a branch to the loop condition. Reuse the @@ -6693,10 +6890,23 @@ c_finish_loop (location_t start_locus, tree cond, tree incr, tree body, tree c_finish_bc_stmt (tree *label_p, bool is_break) { + bool skip; tree label = *label_p; + /* In switch statements break is sometimes stylistically used after + a return statement. This can lead to spurious warnings about + control reaching the end of a non-void function when it is + inlined. Note that we are calling block_may_fallthru with + language specific tree nodes; this works because + block_may_fallthru returns true when given something it does not + understand. */ + skip = !block_may_fallthru (cur_stmt_list); + if (!label) - *label_p = label = create_artificial_label (); + { + if (!skip) + *label_p = label = create_artificial_label (); + } else if (TREE_CODE (label) != LABEL_DECL) { if (is_break) @@ -6706,6 +6916,9 @@ c_finish_bc_stmt (tree *label_p, bool is_break) return NULL_TREE; } + if (skip) + return NULL_TREE; + return add_stmt (build1 (GOTO_EXPR, void_type_node, label)); } @@ -6786,12 +6999,30 @@ tree c_begin_stmt_expr (void) { tree ret; + struct c_label_context *nstack; + struct c_label_list *glist; /* 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); + if (c_switch_stack) + { + c_switch_stack->blocked_stmt_expr++; + gcc_assert (c_switch_stack->blocked_stmt_expr != 0); + } + for (glist = label_context_stack->labels_used; + glist != NULL; + glist = glist->next) + { + C_DECL_UNDEFINABLE_STMT_EXPR (glist->label) = 1; + } + nstack = XOBNEW (&parser_obstack, struct c_label_context); + nstack->labels_def = NULL; + nstack->labels_used = NULL; + nstack->next = label_context_stack; + label_context_stack = nstack; /* Mark the current statement list as belonging to a statement list. */ STATEMENT_LIST_STMT_EXPR (ret) = 1; @@ -6804,8 +7035,36 @@ c_finish_stmt_expr (tree body) { tree last, type, tmp, val; tree *last_p; + struct c_label_list *dlist, *glist, *glist_prev = NULL; body = c_end_compound_stmt (body, true); + if (c_switch_stack) + { + gcc_assert (c_switch_stack->blocked_stmt_expr != 0); + c_switch_stack->blocked_stmt_expr--; + } + /* It is no longer possible to jump to labels defined within this + statement expression. */ + for (dlist = label_context_stack->labels_def; + dlist != NULL; + dlist = dlist->next) + { + C_DECL_UNJUMPABLE_STMT_EXPR (dlist->label) = 1; + } + /* It is again possible to define labels with a goto just outside + this statement expression. */ + for (glist = label_context_stack->next->labels_used; + glist != NULL; + glist = glist->next) + { + C_DECL_UNDEFINABLE_STMT_EXPR (glist->label) = 0; + glist_prev = glist; + } + if (glist_prev != NULL) + glist_prev->next = label_context_stack->labels_used; + else + label_context_stack->next->labels_used = label_context_stack->labels_used; + label_context_stack = label_context_stack->next; /* Locate the last statement in BODY. See c_end_compound_stmt about always returning a BIND_EXPR. */ @@ -7139,8 +7398,8 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1, but that does not mean the operands should be converted to ints! */ result_type = integer_type_node; - op0 = lang_hooks.truthvalue_conversion (op0); - op1 = lang_hooks.truthvalue_conversion (op1); + op0 = c_common_truthvalue_conversion (op0); + op1 = c_common_truthvalue_conversion (op1); converted = 1; } break; @@ -7200,29 +7459,6 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1, } break; - case RROTATE_EXPR: - case LROTATE_EXPR: - if (code0 == INTEGER_TYPE && code1 == INTEGER_TYPE) - { - if (TREE_CODE (op1) == INTEGER_CST && skip_evaluation == 0) - { - if (tree_int_cst_sgn (op1) < 0) - warning ("shift count is negative"); - else if (compare_tree_int (op1, TYPE_PRECISION (type0)) >= 0) - warning ("shift count >= width of type"); - } - - /* Use the type of the value to be shifted. */ - result_type = type0; - /* Convert the shift-count to an integer, regardless of size - of value being shifted. */ - if (TYPE_MAIN_VARIANT (TREE_TYPE (op1)) != integer_type_node) - op1 = convert (integer_type_node, op1); - /* Avoid converting op1 to result_type later. */ - converted = 1; - } - break; - case EQ_EXPR: case NE_EXPR: if (warn_float_equal && (code0 == REAL_TYPE || code1 == REAL_TYPE)) @@ -7284,28 +7520,6 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1, } break; - case MAX_EXPR: - case MIN_EXPR: - if ((code0 == INTEGER_TYPE || code0 == REAL_TYPE) - && (code1 == INTEGER_TYPE || code1 == REAL_TYPE)) - shorten = 1; - else if (code0 == POINTER_TYPE && code1 == POINTER_TYPE) - { - if (comp_target_types (type0, type1, 1)) - { - 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"); - } - else - { - result_type = ptr_type_node; - pedwarn ("comparison of distinct pointer types lacks a cast"); - } - } - break; - case LE_EXPR: case GE_EXPR: case LT_EXPR: @@ -7358,25 +7572,8 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1, } break; - case UNORDERED_EXPR: - case ORDERED_EXPR: - case UNLT_EXPR: - case UNLE_EXPR: - case UNGT_EXPR: - case UNGE_EXPR: - case UNEQ_EXPR: - case LTGT_EXPR: - build_type = integer_type_node; - if (code0 != REAL_TYPE || code1 != REAL_TYPE) - { - error ("unordered comparison on non-floating point argument"); - return error_mark_node; - } - common = 1; - break; - default: - break; + gcc_unreachable (); } if (code0 == ERROR_MARK || code1 == ERROR_MARK) @@ -7391,7 +7588,7 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1, int none_complex = (code0 != COMPLEX_TYPE && code1 != COMPLEX_TYPE); if (shorten || common || short_compare) - result_type = common_type (type0, type1); + result_type = c_common_type (type0, type1); /* For certain operations (which identify themselves by shorten != 0) if both args were extended from the same smaller type, @@ -7449,7 +7646,7 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1, && (unsigned0 || !uns)) result_type = c_common_signed_or_unsigned_type - (unsigned0, common_type (TREE_TYPE (arg0), TREE_TYPE (arg1))); + (unsigned0, c_common_type (TREE_TYPE (arg0), TREE_TYPE (arg1))); else if (TREE_CODE (arg0) == INTEGER_CST && (unsigned1 || !uns) && (TYPE_PRECISION (TREE_TYPE (arg1)) @@ -7682,3 +7879,34 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1, return result; } } + + +/* Convert EXPR to be a truth-value, validating its type for this + purpose. Passes EXPR to default_function_array_conversion. */ + +tree +c_objc_common_truthvalue_conversion (tree expr) +{ + expr = default_function_array_conversion (expr); + switch (TREE_CODE (TREE_TYPE (expr))) + { + case ARRAY_TYPE: + error ("used array that cannot be converted to pointer where scalar is required"); + return error_mark_node; + + case RECORD_TYPE: + error ("used struct type value where scalar is required"); + return error_mark_node; + + case UNION_TYPE: + error ("used union type value where scalar is required"); + return error_mark_node; + + default: + break; + } + + /* ??? Should we also give an error for void and vectors rather than + leaving those to give errors later? */ + return c_common_truthvalue_conversion (expr); +}