X-Git-Url: http://git.sourceforge.jp/view?a=blobdiff_plain;f=gcc%2Fc-typeck.c;h=6f2a6bcb2382118f0211e44fb0e4f09db7e71b98;hb=782858b8cb5960a958ff47f1fe62fd9896596002;hp=aa04ac0d24a76b23f2f3125c7b3cbb853d151743;hpb=af28855bc1af90aa53b5de0a91ef843dce967545;p=pf3gnuchains%2Fgcc-fork.git diff --git a/gcc/c-typeck.c b/gcc/c-typeck.c index aa04ac0d24a..6f2a6bcb238 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,7 +43,26 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA #include "target.h" #include "tree-iterator.h" #include "tree-gimple.h" +#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__". */ +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. */ @@ -62,9 +81,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); @@ -81,7 +99,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, const char *); +static void readonly_error (tree, enum lvalue_use); +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.) */ @@ -117,8 +136,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", - IDENTIFIER_POINTER (DECL_NAME (value))); + error ("%qD has an incomplete type", value); else { retry: @@ -157,16 +175,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'", - 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 `%s'", - IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type)))); + error ("invalid use of incomplete typedef %qD", TYPE_NAME (type)); } } @@ -240,8 +257,7 @@ composite_type (tree t1, tree t2) if (code2 == ENUMERAL_TYPE && code1 == INTEGER_TYPE) return t2; - if (code1 != code2) - abort (); + gcc_assert (code1 == code2); switch (code1) { @@ -259,10 +275,11 @@ 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. */ - if (TYPE_QUALS (t1) || TYPE_QUALS (t2)) - abort (); + 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)) @@ -275,8 +292,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); } @@ -292,9 +317,9 @@ composite_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. */ @@ -348,29 +373,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: ; @@ -398,8 +445,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. */ @@ -412,18 +459,22 @@ common_pointer_type (tree t1, tree t2) if (t2 == error_mark_node) return t1; - if (TREE_CODE (t1) != POINTER_TYPE || TREE_CODE (t2) != POINTER_TYPE) - abort (); + 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)); + 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) | @@ -439,8 +490,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; @@ -470,13 +521,10 @@ common_type (tree t1, tree t2) code1 = TREE_CODE (t1); code2 = TREE_CODE (t2); - if (code1 != VECTOR_TYPE && code1 != COMPLEX_TYPE - && code1 != REAL_TYPE && code1 != INTEGER_TYPE) - abort (); - - if (code2 != VECTOR_TYPE && code2 != COMPLEX_TYPE - && code2 != REAL_TYPE && code2 != INTEGER_TYPE) - abort (); + 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 @@ -494,7 +542,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; @@ -564,6 +612,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. */ @@ -618,11 +678,12 @@ 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. */ - 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. */ @@ -635,6 +696,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; @@ -660,13 +725,13 @@ comptypes (tree type1, tree type2) 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)); @@ -675,8 +740,8 @@ comptypes (tree type1, tree type2) 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; @@ -716,13 +781,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"); @@ -741,19 +814,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; @@ -894,7 +973,7 @@ tagged_types_tu_compatible_p (tree t1, tree t2) break; } tagged_tu_seen_base = tts.next; - if (! ok) + if (!ok) return 0; } return needs_warning ? 2 : 1; @@ -935,7 +1014,7 @@ tagged_types_tu_compatible_p (tree t1, tree t2) } default: - abort (); + gcc_unreachable (); } } @@ -961,7 +1040,7 @@ function_types_compatible_p (tree f1, tree f2) /* '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 `volatile'"); + 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); @@ -1018,62 +1097,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; } @@ -1092,7 +1189,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); @@ -1122,7 +1219,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 @@ -1197,7 +1294,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); @@ -1354,7 +1451,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]; @@ -1443,26 +1540,6 @@ build_component_ref (tree datum, tree component) if (!objc_is_public (datum, component)) return error_mark_node; - /* 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 build2 (COMPOUND_EXPR, TREE_TYPE (value), - TREE_OPERAND (datum, 0), non_lvalue (value)); - } - default: - break; - } - /* See if there is a field or component with name COMPONENT. */ if (code == RECORD_TYPE || code == UNION_TYPE) @@ -1477,9 +1554,7 @@ build_component_ref (tree datum, tree component) if (!field) { - error ("%s has no member named `%s'", - code == RECORD_TYPE ? "structure" : "union", - IDENTIFIER_POINTER (component)); + error ("%qT has no member named %qE", type, component); return error_mark_node; } @@ -1514,8 +1589,8 @@ 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", - IDENTIFIER_POINTER (component)); + error ("request for member %qE in something not a structure or union", + component); return error_mark_node; } @@ -1539,7 +1614,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) { @@ -1547,7 +1627,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 @@ -1564,7 +1644,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; } @@ -1580,39 +1660,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 `char'"); - - /* 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 @@ -1631,7 +1730,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; @@ -1643,12 +1742,14 @@ 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))); + 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 +1768,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 `char'"); - - /* 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; - 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; - } + gcc_assert (TREE_CODE (TREE_TYPE (ar)) == POINTER_TYPE); + gcc_assert (TREE_CODE (TREE_TYPE (TREE_TYPE (ar))) != FUNCTION_TYPE); - 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 = lookup_objc_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 `%s' 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 +1807,7 @@ build_external_ref (tree id, int fun) return error_mark_node; else { - undeclared_variable (id); + undeclared_variable (id, loc); return error_mark_node; } @@ -1756,6 +1821,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); @@ -1777,6 +1852,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. */ + +static 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. @@ -1818,7 +1982,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; } @@ -1837,11 +2001,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))) + && !comptypes (fntype, TREE_TYPE (tem))) { tree return_type = TREE_TYPE (fntype); tree trap = build_function_call (built_in_decls[BUILT_IN_TRAP], @@ -1877,7 +2041,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. */ @@ -1906,7 +2073,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. @@ -1915,7 +2083,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. @@ -1923,11 +2092,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. */ @@ -1938,17 +2117,22 @@ 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 `%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. */ @@ -1964,7 +2148,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; @@ -1979,22 +2163,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. */ @@ -2004,7 +2200,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 @@ -2022,7 +2220,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 @@ -2048,15 +2247,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) @@ -2070,6 +2271,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); @@ -2080,11 +2287,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); @@ -2137,7 +2341,8 @@ parser_build_binary_op (enum tree_code code, struct c_expr arg1, || code2 == PLUS_EXPR || code2 == MINUS_EXPR) warning ("suggest parentheses around arithmetic in operand of |"); /* Check cases like x|y==z */ - if (TREE_CODE_CLASS (code1) == '<' || TREE_CODE_CLASS (code2) == '<') + if (TREE_CODE_CLASS (code1) == tcc_comparison + || TREE_CODE_CLASS (code2) == tcc_comparison) warning ("suggest parentheses around comparison in operand of |"); } @@ -2149,7 +2354,8 @@ parser_build_binary_op (enum tree_code code, struct c_expr arg1, || code2 == PLUS_EXPR || code2 == MINUS_EXPR) warning ("suggest parentheses around arithmetic in operand of ^"); /* Check cases like x^y==z */ - if (TREE_CODE_CLASS (code1) == '<' || TREE_CODE_CLASS (code2) == '<') + if (TREE_CODE_CLASS (code1) == tcc_comparison + || TREE_CODE_CLASS (code2) == tcc_comparison) warning ("suggest parentheses around comparison in operand of ^"); } @@ -2159,13 +2365,14 @@ parser_build_binary_op (enum tree_code code, struct c_expr arg1, || code2 == PLUS_EXPR || code2 == MINUS_EXPR) warning ("suggest parentheses around + or - in operand of &"); /* Check cases like x&y==z */ - if (TREE_CODE_CLASS (code1) == '<' || TREE_CODE_CLASS (code2) == '<') + if (TREE_CODE_CLASS (code1) == tcc_comparison + || TREE_CODE_CLASS (code2) == tcc_comparison) warning ("suggest parentheses around comparison in operand of &"); } /* Similarly, check for cases like 1<=i<=10 that are probably errors. */ - if (TREE_CODE_CLASS (code) == '<' - && (TREE_CODE_CLASS (code1) == '<' - || TREE_CODE_CLASS (code2) == '<')) + if (TREE_CODE_CLASS (code) == tcc_comparison + && (TREE_CODE_CLASS (code1) == tcc_comparison + || TREE_CODE_CLASS (code2) == tcc_comparison)) warning ("comparisons like X<=Y<=Z do not have their mathematical meaning"); } @@ -2192,7 +2399,7 @@ pointer_diff (tree op0, tree op1) if (pedantic || warn_pointer_arith) { if (TREE_CODE (target_type) == VOID_TYPE) - pedwarn ("pointer of type `void *' used in subtraction"); + pedwarn ("pointer of type % used in subtraction"); if (TREE_CODE (target_type) == FUNCTION_TYPE) pedwarn ("pointer to a function used in subtraction"); } @@ -2313,7 +2520,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); } @@ -2390,7 +2597,8 @@ 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); @@ -2452,8 +2660,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. */ @@ -2461,7 +2669,7 @@ 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); @@ -2498,7 +2706,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. */ @@ -2508,50 +2716,33 @@ 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) - { - tree field = TREE_OPERAND (arg, 1); + gcc_assert (TREE_CODE (arg) != COMPONENT_REF + || !DECL_C_BIT_FIELD (TREE_OPERAND (arg, 1))); - addr = build_unary_op (ADDR_EXPR, TREE_OPERAND (arg, 0), flag); + argtype = build_pointer_type (argtype); - 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; - } + /* ??? 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)); - addr = fold (build2 (PLUS_EXPR, argtype, - convert (argtype, addr), - convert (argtype, byte_position (field)))); - - /* If the folded PLUS_EXPR is not a constant address, wrap - it in an ADDR_EXPR. */ - if (!TREE_CONSTANT (addr)) - addr = build1 (ADDR_EXPR, argtype, arg); - } - else - addr = build1 (ADDR_EXPR, argtype, arg); + val = build1 (ADDR_EXPR, argtype, arg); - if (TREE_CODE (arg) == COMPOUND_LITERAL_EXPR) - TREE_INVARIANT (addr) = TREE_CONSTANT (addr) = 1; + if (TREE_CODE (arg) == COMPOUND_LITERAL_EXPR) + TREE_INVARIANT (val) = TREE_CONSTANT (val) = 1; - return addr; - } + return val; default: break; @@ -2599,40 +2790,38 @@ 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. */ - -static int -lvalue_or_else (tree ref, const char *msgid) -{ - int win = lvalue_p (ref); - - if (! win) - error ("%s", msgid); - - 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), - 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 ("%s of read-only variable `%s'", _(msgid), - 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 ("%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 @@ -2650,8 +2839,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 `%s'", - IDENTIFIER_POINTER (DECL_NAME (TREE_OPERAND (x, 1)))); + error + ("cannot take address of bit-field %qD", TREE_OPERAND (x, 1)); return false; } @@ -2678,24 +2867,19 @@ c_mark_addressable (tree exp) { if (TREE_PUBLIC (x) || TREE_STATIC (x) || DECL_EXTERNAL (x)) { - error ("global register variable `%s' used in nested function", - IDENTIFIER_POINTER (DECL_NAME (x))); + error + ("global register variable %qD used in nested function", x); return false; } - pedwarn ("register variable `%s' 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 `%s' requested", - IDENTIFIER_POINTER (DECL_NAME (x))); - return false; - } - - pedwarn ("address of register variable `%s' 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 */ @@ -2760,7 +2944,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 @@ -2777,7 +2961,7 @@ 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 @@ -2809,14 +2993,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))); } @@ -2828,7 +3014,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 { @@ -2884,17 +3070,13 @@ 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)) + 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 (expr1) == CONVERT_EXPR + && !(TREE_CODE (expr1) == CONVERT_EXPR && VOID_TYPE_P (TREE_TYPE (expr1)))) warning ("left-hand operand of comma expression has no effect"); } @@ -3054,7 +3236,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 @@ -3107,9 +3290,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. */ @@ -3122,19 +3302,13 @@ build_c_cast (tree type, tree expr) else TREE_OVERFLOW (value) = 0; - if (TREE_CODE_CLASS (TREE_CODE (ovalue)) == 'c') + 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); @@ -3144,15 +3318,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); @@ -3196,16 +3371,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'. @@ -3230,12 +3405,12 @@ 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 = build2 (MODIFY_EXPR, lhstype, lhs, newrhs); TREE_SIDE_EFFECTS (result) = 1; @@ -3247,7 +3422,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); } @@ -3256,21 +3431,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 @@ -3303,6 +3523,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; } @@ -3333,7 +3558,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. */ @@ -3347,7 +3572,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; @@ -3387,7 +3613,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; } } @@ -3404,7 +3630,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. */ @@ -3422,16 +3648,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); @@ -3444,9 +3684,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)) @@ -3459,8 +3705,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) @@ -3470,25 +3716,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 - 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) @@ -3498,17 +3763,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; } @@ -3517,45 +3795,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; } @@ -3571,80 +3862,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 = (char *) 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 = (char *) 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 = (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. @@ -3663,8 +3893,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; @@ -3693,7 +3922,7 @@ store_init_value (tree decl, tree init) /* 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; @@ -3862,7 +4091,7 @@ error_init (const char *msgid) error ("%s", _(msgid)); 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. @@ -3877,7 +4106,7 @@ pedwarn_init (const char *msgid) pedwarn ("%s", _(msgid)); 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. @@ -3892,7 +4121,7 @@ warning_init (const char *msgid) warning ("%s", _(msgid)); 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 @@ -4008,17 +4237,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 - && 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. */ @@ -4092,16 +4336,8 @@ digest_init (tree type, tree init, bool strict_string, 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; @@ -4120,16 +4356,20 @@ 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); - 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; @@ -4218,17 +4458,11 @@ 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) {...}. */ 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; @@ -4275,7 +4509,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. */ @@ -4290,7 +4524,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 @@ -4300,7 +4534,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; @@ -4312,22 +4545,17 @@ 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. */ 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 = XNEW (struct initializer_stack); - const char *asmspec = 0; - - if (asmspec_tree) - asmspec = TREE_STRING_POINTER (asmspec_tree); + struct initializer_stack *p = xmalloc (sizeof (struct initializer_stack)); 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; @@ -4341,11 +4569,10 @@ 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; - if (decl != 0) + if (decl != 0 && decl != error_mark_node) { require_constant_value = TREE_STATIC (decl); require_constant_elements @@ -4391,14 +4618,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; @@ -4500,7 +4725,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; } @@ -4704,7 +4932,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; } @@ -4736,8 +4965,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. */ @@ -4751,14 +4979,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) @@ -4770,10 +5000,6 @@ 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. */ @@ -4784,7 +5010,7 @@ pop_init_level (int implicit) { /* 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); @@ -4889,14 +5115,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. */ @@ -4906,25 +5132,20 @@ set_designator (int array) return 0; } - if (constructor_no_implicit) - { - error_init ("initialization designators may not nest"); - return 1; - } - - if (TREE_CODE (constructor_type) == RECORD_TYPE - || TREE_CODE (constructor_type) == UNION_TYPE) + 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) @@ -5069,8 +5290,7 @@ set_init_label (tree fieldname) } if (tail == 0) - error ("unknown field `%s' specified in initializer", - IDENTIFIER_POINTER (fieldname)); + error ("unknown field %qE specified in initializer", fieldname); else { constructor_fields = tail; @@ -5344,18 +5564,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); @@ -5487,7 +5706,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; @@ -5515,21 +5734,23 @@ output_init_element (tree value, bool strict_string, tree type, tree field, 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. */ @@ -5757,7 +5978,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 @@ -5880,7 +6101,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 @@ -5968,7 +6189,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 @@ -6008,7 +6229,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 @@ -6073,7 +6294,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; @@ -6097,16 +6319,14 @@ process_init_element (struct c_expr 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)); } @@ -6167,47 +6387,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, "invalid lvalue in asm statement"); + + 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); @@ -6217,6 +6470,7 @@ build_asm_expr (tree string, tree outputs, tree inputs, tree clobbers, ASM_VOLATILE_P (args) = 1; ASM_INPUT_P (args) = 1; } + return args; } @@ -6239,7 +6493,7 @@ tree c_finish_goto_ptr (tree expr) { if (pedantic) - pedwarn ("ISO C forbids `goto *expr;'"); + pedwarn ("ISO C forbids %"); expr = convert (ptr_type_node, expr); return add_stmt (build1 (GOTO_EXPR, void_type_node, expr)); } @@ -6253,24 +6507,25 @@ 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; @@ -6299,7 +6554,7 @@ c_finish_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)) @@ -6315,13 +6570,13 @@ c_finish_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; @@ -6343,7 +6598,7 @@ struct c_switch { /* The SWITCH_STMT being built. */ tree switch_stmt; - /* The original type of the testing expression, ie. before the + /* The original type of the testing expression, i.e. before the default conversion is applied. */ tree orig_type; @@ -6381,11 +6636,12 @@ 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"); exp = integer_zero_node; + orig_type = error_mark_node; } else { @@ -6394,7 +6650,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); @@ -6403,8 +6660,7 @@ 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->next = c_switch_stack; @@ -6423,7 +6679,7 @@ do_case (tree low_value, tree high_value) if (c_switch_stack) { 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) @@ -6432,7 +6688,7 @@ do_case (tree low_value, tree high_value) 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; } @@ -6444,7 +6700,7 @@ 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; /* Emit warnings as needed. */ c_do_switch_warnings (cs->cases, cs->switch_stmt); @@ -6491,12 +6747,12 @@ c_finish_if_stmt (location_t if_locus, tree cond, tree then_block, inner_if = TREE_OPERAND (inner_if, 0); break; default: - abort (); + gcc_unreachable (); } found: if (COND_EXPR_ELSE (inner_if)) - warning ("%Hsuggest explicit braces to avoid ambiguous `else'", + warning ("%Hsuggest explicit braces to avoid ambiguous %", &if_locus); } @@ -6537,10 +6793,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); @@ -6549,7 +6812,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 @@ -6596,10 +6859,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) @@ -6609,6 +6885,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)); } @@ -6662,7 +6941,7 @@ c_process_expr_stmt (tree 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) || TREE_CODE_CLASS (TREE_CODE (expr)) == 'c') + if (DECL_P (expr) || CONSTANT_CLASS_P (expr)) expr = build1 (NOP_EXPR, TREE_TYPE (expr), expr); if (EXPR_P (expr)) @@ -6996,7 +7275,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; @@ -7023,7 +7302,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; @@ -7061,7 +7340,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) @@ -7103,29 +7382,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)) @@ -7153,13 +7409,15 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1, 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"); @@ -7185,28 +7443,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: @@ -7259,25 +7495,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) @@ -7292,7 +7511,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, @@ -7350,7 +7569,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)) @@ -7424,8 +7643,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); @@ -7444,7 +7663,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) @@ -7479,7 +7698,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 @@ -7527,7 +7746,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"); } @@ -7555,7 +7774,7 @@ 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);