X-Git-Url: http://git.sourceforge.jp/view?a=blobdiff_plain;f=gcc%2Fc-typeck.c;h=25a280a6d54efd8f8d9a15a170b3cb14773409ce;hb=41b60827878f5f840120c95c52846ce0fe072c3f;hp=4cfd7ce35b5dc19bc7626cb8229ad3075e9a3362;hpb=fdf95cc9d51430d575013cc35f5475495dedb1db;p=pf3gnuchains%2Fgcc-fork.git diff --git a/gcc/c-typeck.c b/gcc/c-typeck.c index 4cfd7ce35b5..25a280a6d54 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,6 +43,17 @@ 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; @@ -53,6 +64,9 @@ int in_sizeof; /* The level of nesting inside "typeof". */ int in_typeof; +struct c_label_context_se *label_context_stack_se; +struct c_label_context_vm *label_context_stack_vm; + /* Nonzero if we've already printed a "missing braces around initializer" message within this initializer. */ static int missing_braces_mentioned; @@ -62,7 +76,7 @@ static int require_constant_elements; static tree qualify_type (tree, tree); static int tagged_types_tu_compatible_p (tree, tree); -static int comp_target_types (tree, tree, int); +static int comp_target_types (tree, tree); static int function_types_compatible_p (tree, tree); static int type_lists_compatible_p (tree, tree); static tree decl_constant_value_for_broken_optimization (tree); @@ -70,9 +84,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); @@ -89,7 +102,10 @@ static void add_pending_init (tree, tree); static void set_nonincremental_init (void); static void set_nonincremental_init_from_string (tree); static tree find_init_member (tree); -static int lvalue_or_else (tree, const char *); +static void readonly_error (tree, enum lvalue_use); +static int lvalue_or_else (tree, enum lvalue_use); +static int lvalue_p (tree); +static void record_maybe_used_decl (tree); /* Do `exp = require_complete_type (exp);' to make sure exp does not have an incomplete type. (That includes void types.) */ @@ -125,8 +141,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: @@ -169,12 +184,11 @@ c_incomplete_type_error (tree value, tree type) } if (TREE_CODE (TYPE_NAME (type)) == IDENTIFIER_NODE) - error ("invalid use of undefined type `%s %s'", - type_code_string, IDENTIFIER_POINTER (TYPE_NAME (type))); + error ("invalid use of undefined type %<%s %E%>", + type_code_string, TYPE_NAME (type)); else /* If this type has a typedef-name, the TYPE_NAME is a TYPE_DECL. */ - error ("invalid use of incomplete typedef `%s'", - IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type)))); + error ("invalid use of incomplete typedef %qD", TYPE_NAME (type)); } } @@ -266,7 +280,9 @@ composite_type (tree t1, tree t2) case ARRAY_TYPE: { tree elt = composite_type (TREE_TYPE (t1), TREE_TYPE (t2)); - + int quals; + tree unqual_elt; + /* We should not have any type quals on arrays at all. */ gcc_assert (!TYPE_QUALS (t1) && !TYPE_QUALS (t2)); @@ -281,8 +297,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); } @@ -298,9 +322,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. */ @@ -320,7 +344,7 @@ composite_type (tree t1, tree t2) /* If both args specify argument types, we must merge the two lists, argument by argument. */ /* Tell global_bindings_p to return false so that variable_size - doesn't abort on VLAs in parameter types. */ + doesn't die on VLAs in parameter types. */ c_override_global_bindings_to_false = true; len = list_length (p1); @@ -354,29 +378,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: ; @@ -404,8 +450,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. */ @@ -425,11 +471,15 @@ common_pointer_type (tree t1, tree t2) attributes = targetm.merge_type_attributes (t1, t2); /* Find the composite type of the target types, and combine the - qualifiers of the two types' targets. */ - pointed_to_1 = TREE_TYPE (t1); - pointed_to_2 = TREE_TYPE (t2); - target = composite_type (TYPE_MAIN_VARIANT (pointed_to_1), - TYPE_MAIN_VARIANT (pointed_to_2)); + qualifiers of the two types' targets. Do not lose qualifiers on + array element types by taking the TYPE_MAIN_VARIANT. */ + mv1 = pointed_to_1 = TREE_TYPE (t1); + mv2 = pointed_to_2 = TREE_TYPE (t2); + if (TREE_CODE (mv1) != ARRAY_TYPE) + mv1 = TYPE_MAIN_VARIANT (pointed_to_1); + if (TREE_CODE (mv2) != ARRAY_TYPE) + mv2 = TYPE_MAIN_VARIANT (pointed_to_2); + target = composite_type (mv1, mv2); t1 = build_pointer_type (c_build_qualified_type (target, TYPE_QUALS (pointed_to_1) | @@ -445,8 +495,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; @@ -497,7 +547,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; @@ -567,6 +617,32 @@ 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. + BOOLEAN_TYPEs are allowed here and return either boolean_type_node or + preferably a non-Boolean type as the common type. */ +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); + + /* If both types are BOOLEAN_TYPE, then return boolean_type_node. */ + if (TREE_CODE (t1) == BOOLEAN_TYPE + && TREE_CODE (t2) == BOOLEAN_TYPE) + return boolean_type_node; + + /* If either type is BOOLEAN_TYPE, then return the other. */ + if (TREE_CODE (t1) == BOOLEAN_TYPE) + return t2; + if (TREE_CODE (t2) == BOOLEAN_TYPE) + return t1; + + 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. */ @@ -621,11 +697,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. */ @@ -634,9 +711,9 @@ comptypes (tree type1, tree type2) switch (TREE_CODE (t1)) { case POINTER_TYPE: - /* We must give ObjC the first crack at comparing pointers, since - protocol qualifiers may be involved. */ - if (c_dialect_objc () && (val = objc_comptypes (t1, t2, 0)) >= 0) + /* 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))); @@ -663,13 +740,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)); @@ -678,20 +755,15 @@ 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; } - case RECORD_TYPE: - /* We are dealing with two distinct structs. In assorted Objective-C - corner cases, however, these can still be deemed equivalent. */ - if (c_dialect_objc () && objc_comptypes (t1, t2, 0) == 1) - val = 1; - case ENUMERAL_TYPE: + case RECORD_TYPE: case UNION_TYPE: if (val != 1 && !same_translation_unit_p (t1, t2)) val = tagged_types_tu_compatible_p (t1, t2); @@ -709,23 +781,23 @@ comptypes (tree type1, tree type2) } /* Return 1 if TTL and TTR are pointers to types that are equivalent, - ignoring their qualifiers. REFLEXIVE is only used by ObjC - set it - to 1 or 0 depending if the check of the pointer types is meant to - be reflexive or not (typically, assignments are not reflexive, - while comparisons are reflexive). -*/ + ignoring their qualifiers. */ static int -comp_target_types (tree ttl, tree ttr, int reflexive) +comp_target_types (tree ttl, tree ttr) { int val; - - /* 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))); + tree mvl, mvr; + + /* 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"); @@ -744,18 +816,24 @@ 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 */ + 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 */ + 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 (); } @@ -897,7 +975,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; @@ -964,7 +1042,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); @@ -987,7 +1065,7 @@ function_types_compatible_p (tree f1, tree f2) return 0; /* If one of these types comes from a non-prototype fn definition, compare that with the other type's arglist. - If they don't match, ask for a warning (but no error). */ + If they don't match, ask for a warning (0, but no error). */ if (TYPE_ACTUAL_ARG_TYPES (f1) && 1 != type_lists_compatible_p (args2, TYPE_ACTUAL_ARG_TYPES (f1))) val = 2; @@ -1021,62 +1099,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; } @@ -1095,7 +1191,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); @@ -1125,7 +1221,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 @@ -1150,10 +1246,18 @@ decl_constant_value (tree decl) static tree decl_constant_value_for_broken_optimization (tree decl) { + tree ret; + if (pedantic || DECL_MODE (decl) == BLKmode) return decl; - else - return decl_constant_value (decl); + + ret = decl_constant_value (decl); + /* Avoid unwanted tree sharing between the initializer and current + function's body where the tree can be modified e.g. by the + gimplifier. */ + if (ret != decl && TREE_STATIC (decl)) + ret = unshare_expr (ret); + return ret; } @@ -1200,7 +1304,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); @@ -1256,47 +1360,17 @@ default_function_array_conversion (tree exp) return exp; } -/* Perform default promotions for C data used in expressions. - Arrays and functions are converted to pointers; - enumeral types or short or char, to int. - In addition, manifest constants symbols are replaced by their values. */ + +/* EXP is an expression of integer type. Apply the integer promotions + to it and return the promoted value. */ tree -default_conversion (tree exp) +perform_integral_promotions (tree exp) { - tree orig_exp; tree type = TREE_TYPE (exp); enum tree_code code = TREE_CODE (type); - if (code == FUNCTION_TYPE || code == ARRAY_TYPE) - return default_function_array_conversion (exp); - - /* Constants can be used directly unless they're not loadable. */ - if (TREE_CODE (exp) == CONST_DECL) - exp = DECL_INITIAL (exp); - - /* Replace a nonvolatile const static variable with its value unless - it is an array, in which case we must be sure that taking the - address of the array produces consistent results. */ - else if (optimize && TREE_CODE (exp) == VAR_DECL && code != ARRAY_TYPE) - { - exp = decl_constant_value_for_broken_optimization (exp); - type = TREE_TYPE (exp); - } - - /* Strip NON_LVALUE_EXPRs and no-op conversions, since we aren't using as - an lvalue. - - Do not use STRIP_NOPS here! It will remove conversions from pointer - to integer and cause infinite recursion. */ - orig_exp = exp; - while (TREE_CODE (exp) == NON_LVALUE_EXPR - || (TREE_CODE (exp) == NOP_EXPR - && TREE_TYPE (TREE_OPERAND (exp, 0)) == TREE_TYPE (exp))) - exp = TREE_OPERAND (exp, 0); - - if (TREE_NO_WARNING (orig_exp)) - TREE_NO_WARNING (exp) = 1; + gcc_assert (INTEGRAL_TYPE_P (type)); /* Normally convert enums to int, but convert wide enums to something wider. */ @@ -1311,6 +1385,8 @@ default_conversion (tree exp) return convert (type, exp); } + /* ??? This should no longer be needed now bit-fields have their + proper types. */ if (TREE_CODE (exp) == COMPONENT_REF && DECL_C_BIT_FIELD (TREE_OPERAND (exp, 1)) /* If it's thinner than an int, promote it like a @@ -1329,6 +1405,48 @@ default_conversion (tree exp) return convert (integer_type_node, exp); } + return exp; +} + + +/* Perform default promotions for C data used in expressions. + Arrays and functions are converted to pointers; + enumeral types or short or char, to int. + In addition, manifest constants symbols are replaced by their values. */ + +tree +default_conversion (tree exp) +{ + tree orig_exp; + tree type = TREE_TYPE (exp); + enum tree_code code = TREE_CODE (type); + + if (code == FUNCTION_TYPE || code == ARRAY_TYPE) + return default_function_array_conversion (exp); + + /* Constants can be used directly unless they're not loadable. */ + if (TREE_CODE (exp) == CONST_DECL) + exp = DECL_INITIAL (exp); + + /* Replace a nonvolatile const static variable with its value unless + it is an array, in which case we must be sure that taking the + address of the array produces consistent results. */ + else if (optimize && TREE_CODE (exp) == VAR_DECL && code != ARRAY_TYPE) + { + exp = decl_constant_value_for_broken_optimization (exp); + type = TREE_TYPE (exp); + } + + /* Strip no-op conversions. */ + orig_exp = exp; + STRIP_TYPE_NOPS (exp); + + if (TREE_NO_WARNING (orig_exp)) + TREE_NO_WARNING (exp) = 1; + + if (INTEGRAL_TYPE_P (type)) + return perform_integral_promotions (exp); + if (code == VOID_TYPE) { error ("void value not ignored as it ought to be"); @@ -1357,7 +1475,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]; @@ -1446,26 +1564,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) @@ -1480,9 +1578,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; } @@ -1517,8 +1613,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; } @@ -1542,7 +1638,9 @@ 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 ref; + + ref = build1 (INDIRECT_REF, t, pointer); if (!COMPLETE_OR_VOID_TYPE_P (t) && TREE_CODE (t) != ARRAY_TYPE) { @@ -1550,7 +1648,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 (0, "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 @@ -1567,7 +1665,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; } @@ -1583,39 +1681,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 (0, "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 @@ -1634,7 +1751,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; @@ -1646,12 +1763,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. */ @@ -1670,72 +1789,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 = objc_lookup_ivar (id); + + /* In Objective-C, an instance variable (ivar) may be preferred to + whatever lookup_name() found. */ + decl = objc_lookup_ivar (decl, id); if (decl && decl != error_mark_node) - { - /* Properly declared variable or function reference. */ - if (!objc_ivar) - ref = decl; - else if (decl != objc_ivar && !DECL_FILE_SCOPE_P (decl)) - { - warning ("local declaration of `%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); @@ -1745,7 +1828,7 @@ build_external_ref (tree id, int fun) return error_mark_node; else { - undeclared_variable (id); + undeclared_variable (id, loc); return error_mark_node; } @@ -1808,7 +1891,7 @@ static struct maybe_used_decl *maybe_used_decls; a VLA type or the operand of typeof is a variably modified type. */ -void +static void record_maybe_used_decl (tree decl) { struct maybe_used_decl *t = XOBNEW (&parser_obstack, struct maybe_used_decl); @@ -1849,9 +1932,18 @@ struct c_expr c_expr_sizeof_expr (struct c_expr expr) { struct c_expr ret; - ret.value = c_sizeof (TREE_TYPE (expr.value)); - ret.original_code = ERROR_MARK; - pop_maybe_used (C_TYPE_VARIABLE_SIZE (TREE_TYPE (expr.value))); + 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; } @@ -1889,6 +1981,14 @@ build_function_call (tree function, tree params) /* Convert anything with function type to a pointer-to-function. */ if (TREE_CODE (function) == FUNCTION_DECL) { + /* Implement type-directed function overloading for builtins. + resolve_overloaded_builtin and targetm.resolve_overloaded_builtin + handle all the type checking. The result is a complete expression + that implements this function call. */ + tem = resolve_overloaded_builtin (function, params); + if (tem) + return tem; + name = DECL_NAME (function); /* Differs from default_conversion by not setting TREE_ADDRESSABLE @@ -1903,6 +2003,10 @@ build_function_call (tree function, tree params) else function = default_conversion (function); + /* For Objective-C, convert any calls via a cast to OBJC_TYPE_REF + expressions, like those used for ObjC messenger dispatches. */ + function = objc_rewrite_function_call (function, params); + fntype = TREE_TYPE (function); if (TREE_CODE (fntype) == ERROR_MARK) @@ -1911,7 +2015,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; } @@ -1925,16 +2029,11 @@ build_function_call (tree function, tree params) If it is not, replace the call by a trap, wrapped up in a compound expression if necessary. This has the nice side-effect to prevent the tree-inliner from generating invalid assignment trees which may - blow up in the RTL expander later. - - ??? 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 () - && TREE_CODE (function) == NOP_EXPR + blow up in the RTL expander later. */ + if (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], @@ -1943,7 +2042,7 @@ build_function_call (tree function, tree params) /* This situation leads to run-time undefined behavior. We can't, therefore, simply error unless we can prove that all possible executions of the program must execute the code. */ - warning ("function called through a non-compatible type"); + warning (0, "function called through a non-compatible type"); /* We can, however, treat "undefined" any way we please. Call abort to encourage the user to fix the program. */ @@ -1970,7 +2069,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. */ @@ -1999,7 +2101,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. @@ -2008,7 +2111,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. @@ -2016,11 +2120,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. */ @@ -2031,22 +2145,23 @@ convert_arguments (tree typelist, tree values, tree name, tree fundecl) { tree type = typetail ? TREE_VALUE (typetail) : 0; tree val = TREE_VALUE (valtail); + tree rname = function; + int argnum = parmnum + 1; + const char *invalid_func_diag; if (type == void_type_node) { - if (name) - error ("too many arguments to function `%s'", - IDENTIFIER_POINTER (name)); - else - error ("too many arguments to function"); + error ("too many arguments to function %qE", function); break; } - /* Strip NON_LVALUE_EXPRs since we aren't using as an lvalue. */ - /* Do not use STRIP_NOPS here! We do not want an enumerator with value 0 - to convert automatically to a pointer. */ - if (TREE_CODE (val) == NON_LVALUE_EXPR) - val = TREE_OPERAND (val, 0); + if (selector && argnum > 2) + { + rname = selector; + argnum -= 2; + } + + STRIP_TYPE_NOPS (val); val = default_function_array_conversion (val); @@ -2057,7 +2172,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; @@ -2072,22 +2187,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 (0, "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 (0, "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 (0, "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 (0, "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 (0, "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 (0, "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. */ @@ -2097,7 +2224,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 (0, "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 @@ -2115,7 +2244,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 (0, "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 @@ -2128,11 +2258,6 @@ convert_arguments (tree typelist, tree values, tree name, tree fundecl) /* Change in signedness doesn't matter if a constant value is unaffected. */ ; - /* Likewise for a constant in a NOP_EXPR. */ - else if (TREE_CODE (val) == NOP_EXPR - && TREE_CODE (TREE_OPERAND (val, 0)) == INTEGER_CST - && int_fits_type_p (TREE_OPERAND (val, 0), type)) - ; /* If the value is extended from a narrower unsigned type, it doesn't matter whether we pass it as signed or unsigned; the value @@ -2141,15 +2266,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 (0, "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 (0, "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) @@ -2163,6 +2290,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); @@ -2173,21 +2306,34 @@ 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); } -/* This is the entry point used by the parser - for binary operators in the input. - In addition to constructing the expression, - we check for operands that were written with other binary operators - in a way that is likely to confuse the user. */ +/* This is the entry point used by the parser to build unary operators + in the input. CODE, a tree_code, specifies the unary operator, and + ARG is the operand. For unary plus, the C parser currently uses + CONVERT_EXPR for code. */ + +struct c_expr +parser_build_unary_op (enum tree_code code, struct c_expr arg) +{ + struct c_expr result; + + result.original_code = ERROR_MARK; + result.value = build_unary_op (code, arg.value, 0); + overflow_warning (result.value); + return result; +} + +/* This is the entry point used by the parser to build binary operators + in the input. CODE, a tree_code, specifies the binary operator, and + ARG1 and ARG2 are the operands. In addition to constructing the + expression, we check for operands that were written with other binary + operators in a way that is likely to confuse the user. */ struct c_expr parser_build_binary_op (enum tree_code code, struct c_expr arg1, @@ -2212,14 +2358,14 @@ parser_build_binary_op (enum tree_code code, struct c_expr arg1, { if (code1 == PLUS_EXPR || code1 == MINUS_EXPR || code2 == PLUS_EXPR || code2 == MINUS_EXPR) - warning ("suggest parentheses around + or - inside shift"); + warning (0, "suggest parentheses around + or - inside shift"); } if (code == TRUTH_ORIF_EXPR) { if (code1 == TRUTH_ANDIF_EXPR || code2 == TRUTH_ANDIF_EXPR) - warning ("suggest parentheses around && within ||"); + warning (0, "suggest parentheses around && within ||"); } if (code == BIT_IOR_EXPR) @@ -2228,10 +2374,11 @@ parser_build_binary_op (enum tree_code code, struct c_expr arg1, || code1 == PLUS_EXPR || code1 == MINUS_EXPR || code2 == BIT_AND_EXPR || code2 == BIT_XOR_EXPR || code2 == PLUS_EXPR || code2 == MINUS_EXPR) - warning ("suggest parentheses around arithmetic in operand of |"); + warning (0, "suggest parentheses around arithmetic in operand of |"); /* Check cases like x|y==z */ - if (TREE_CODE_CLASS (code1) == '<' || TREE_CODE_CLASS (code2) == '<') - warning ("suggest parentheses around comparison in operand of |"); + if (TREE_CODE_CLASS (code1) == tcc_comparison + || TREE_CODE_CLASS (code2) == tcc_comparison) + warning (0, "suggest parentheses around comparison in operand of |"); } if (code == BIT_XOR_EXPR) @@ -2240,26 +2387,28 @@ parser_build_binary_op (enum tree_code code, struct c_expr arg1, || code1 == PLUS_EXPR || code1 == MINUS_EXPR || code2 == BIT_AND_EXPR || code2 == PLUS_EXPR || code2 == MINUS_EXPR) - warning ("suggest parentheses around arithmetic in operand of ^"); + warning (0, "suggest parentheses around arithmetic in operand of ^"); /* Check cases like x^y==z */ - if (TREE_CODE_CLASS (code1) == '<' || TREE_CODE_CLASS (code2) == '<') - warning ("suggest parentheses around comparison in operand of ^"); + if (TREE_CODE_CLASS (code1) == tcc_comparison + || TREE_CODE_CLASS (code2) == tcc_comparison) + warning (0, "suggest parentheses around comparison in operand of ^"); } if (code == BIT_AND_EXPR) { if (code1 == PLUS_EXPR || code1 == MINUS_EXPR || code2 == PLUS_EXPR || code2 == MINUS_EXPR) - warning ("suggest parentheses around + or - in operand of &"); + warning (0, "suggest parentheses around + or - in operand of &"); /* Check cases like x&y==z */ - if (TREE_CODE_CLASS (code1) == '<' || TREE_CODE_CLASS (code2) == '<') - warning ("suggest parentheses around comparison in operand of &"); + if (TREE_CODE_CLASS (code1) == tcc_comparison + || TREE_CODE_CLASS (code2) == tcc_comparison) + warning (0, "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) == '<')) - warning ("comparisons like X<=Y<=Z do not have their mathematical meaning"); + if (TREE_CODE_CLASS (code) == tcc_comparison + && (TREE_CODE_CLASS (code1) == tcc_comparison + || TREE_CODE_CLASS (code2) == tcc_comparison)) + warning (0, "comparisons like X<=Y<=Z do not have their mathematical meaning"); } @@ -2285,7 +2434,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"); } @@ -2406,7 +2555,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); } @@ -2440,6 +2589,8 @@ build_unary_op (enum tree_code code, tree xarg, int flag) break; case TRUTH_NOT_EXPR: + /* ??? Why do most validation here but that for non-lvalue arrays + in c_objc_common_truthvalue_conversion? */ if (typecode != INTEGER_TYPE && typecode != REAL_TYPE && typecode != POINTER_TYPE && typecode != COMPLEX_TYPE @@ -2449,7 +2600,7 @@ build_unary_op (enum tree_code code, tree xarg, int flag) error ("wrong type argument to unary exclamation mark"); return error_mark_node; } - arg = lang_hooks.truthvalue_conversion (arg); + arg = c_objc_common_truthvalue_conversion (arg); return invert_truthvalue (arg); case NOP_EXPR: @@ -2483,7 +2634,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); @@ -2545,8 +2697,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. */ @@ -2554,7 +2706,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); @@ -2591,7 +2743,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. */ @@ -2601,7 +2753,7 @@ 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), @@ -2610,15 +2762,18 @@ build_unary_op (enum tree_code code, tree xarg, int flag) if (!c_mark_addressable (arg)) return error_mark_node; - if (TREE_CODE (arg) == COMPONENT_REF - && DECL_C_BIT_FIELD (TREE_OPERAND (arg, 1))) - { - error ("attempt to take address of bit-field structure member `%D'", - TREE_OPERAND (arg, 1)); - return error_mark_node; - } + gcc_assert (TREE_CODE (arg) != COMPONENT_REF + || !DECL_C_BIT_FIELD (TREE_OPERAND (arg, 1))); argtype = build_pointer_type (argtype); + + /* ??? 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)); + val = build1 (ADDR_EXPR, argtype, arg); if (TREE_CODE (arg) == COMPOUND_LITERAL_EXPR) @@ -2640,7 +2795,7 @@ build_unary_op (enum tree_code code, tree xarg, int flag) Lvalues can be assigned, unless their type has TYPE_READONLY. Lvalues can have their address taken, unless they have C_DECL_REGISTER. */ -int +static int lvalue_p (tree ref) { enum tree_code code = TREE_CODE (ref); @@ -2672,40 +2827,54 @@ 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 (G_("assignment of read-only member %qD"), + G_("increment of read-only member %qD"), + G_("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 (G_("assignment of read-only variable %qD"), + G_("increment of read-only variable %qD"), + G_("decrement of read-only variable %qD")), + arg); else - error ("%s of read-only location", _(msgid)); + error (READONLY_MSG (G_("assignment of read-only location"), + G_("increment of read-only location"), + G_("decrement of read-only location"))); +} + + +/* Return nonzero if REF is an lvalue valid for this language; + otherwise, print an error message and return zero. USE says + how the lvalue is being used and so selects the error message. */ + +static int +lvalue_or_else (tree ref, enum lvalue_use use) +{ + int win = lvalue_p (ref); + + if (!win) + lvalue_error (use); + + return win; } /* Mark EXP saying that we need to be able to take the @@ -2723,8 +2892,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; } @@ -2751,24 +2920,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 */ @@ -2792,8 +2956,6 @@ build_conditional_expr (tree ifexp, tree op1, tree op2) tree result_type = NULL; tree orig_op1 = op1, orig_op2 = op2; - ifexp = lang_hooks.truthvalue_conversion (default_conversion (ifexp)); - /* Promote both alternatives. */ if (TREE_CODE (TREE_TYPE (op1)) != VOID_TYPE) @@ -2833,7 +2995,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 @@ -2850,7 +3012,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 @@ -2859,7 +3021,7 @@ build_conditional_expr (tree ifexp, tree op1, tree op2) || (unsigned_op1 && tree_expr_nonnegative_p (op2))) /* OK */; else - warning ("signed and unsigned type in conditional expression"); + warning (0, "signed and unsigned type in conditional expression"); } } } @@ -2871,7 +3033,7 @@ build_conditional_expr (tree ifexp, tree op1, tree op2) } else if (code1 == POINTER_TYPE && code2 == POINTER_TYPE) { - if (comp_target_types (type1, type2, 1)) + if (comp_target_types (type1, type2)) result_type = common_pointer_type (type1, type2); else if (integer_zerop (op1) && TREE_TYPE (type1) == void_type_node && TREE_CODE (orig_op1) != NOP_EXPR) @@ -2882,14 +3044,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))); } @@ -2901,7 +3065,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 { @@ -2942,10 +3106,7 @@ build_conditional_expr (tree ifexp, tree op1, tree op2) if (result_type != TREE_TYPE (op2)) op2 = convert_and_check (result_type, op2); - if (TREE_CODE (ifexp) == INTEGER_CST) - return non_lvalue (integer_zerop (ifexp) ? op2 : op1); - - return fold (build3 (COND_EXPR, result_type, ifexp, op1, op2)); + return fold_build3 (COND_EXPR, result_type, ifexp, op1, op2); } /* Return a compound expression that performs two expressions and @@ -2957,19 +3118,23 @@ 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 - && VOID_TYPE_P (TREE_TYPE (expr1)))) - warning ("left-hand operand of comma expression has no effect"); + if (warn_unused_value) + { + if (VOID_TYPE_P (TREE_TYPE (expr1)) + && TREE_CODE (expr1) == CONVERT_EXPR) + ; /* (void) a, b */ + else if (VOID_TYPE_P (TREE_TYPE (expr1)) + && TREE_CODE (expr1) == COMPOUND_EXPR + && TREE_CODE (TREE_OPERAND (expr1, 1)) == CONVERT_EXPR) + ; /* (void) a, (void) b, c */ + else + warning (0, "left-hand operand of comma expression has no effect"); + } } /* With -Wunused, we should also warn if the left-hand operand does have @@ -3096,12 +3261,12 @@ build_c_cast (tree type, tree expr) && TREE_CODE (in_otype) == POINTER_TYPE); if (added) - warning ("cast adds new qualifiers to function type"); + warning (0, "cast adds new qualifiers to function type"); if (discarded) /* There are qualifiers present in IN_OTYPE that are not present in IN_TYPE. */ - warning ("cast discards qualifiers from pointer target type"); + warning (0, "cast discards qualifiers from pointer target type"); } /* Warn about possible alignment problems. */ @@ -3116,25 +3281,28 @@ build_c_cast (tree type, tree expr) || TREE_CODE (TREE_TYPE (otype)) == RECORD_TYPE) && TYPE_MODE (TREE_TYPE (otype)) == VOIDmode) && TYPE_ALIGN (TREE_TYPE (type)) > TYPE_ALIGN (TREE_TYPE (otype))) - warning ("cast increases required alignment of target type"); + warning (0, "cast increases required alignment of target type"); - if (TREE_CODE (type) == INTEGER_TYPE + if (warn_pointer_to_int_cast + && TREE_CODE (type) == INTEGER_TYPE && TREE_CODE (otype) == POINTER_TYPE && TYPE_PRECISION (type) != TYPE_PRECISION (otype) && !TREE_CONSTANT (value)) - warning ("cast from pointer to integer of different size"); + warning (0, "cast from pointer to integer of different size"); if (warn_bad_function_cast && TREE_CODE (value) == CALL_EXPR && TREE_CODE (type) != TREE_CODE (otype)) - warning ("cast does not match function type"); + warning (0, "cast from function call of type %qT to non-matching " + "type %qT", otype, type); - if (TREE_CODE (type) == POINTER_TYPE + if (warn_int_to_pointer_cast + && TREE_CODE (type) == POINTER_TYPE && TREE_CODE (otype) == INTEGER_TYPE && TYPE_PRECISION (type) != TYPE_PRECISION (otype) /* Don't warn about converting any constant. */ && !TREE_CONSTANT (value)) - warning ("cast to pointer from integer of different size"); + warning (0, "cast to pointer from integer of different size"); if (TREE_CODE (type) == POINTER_TYPE && TREE_CODE (otype) == POINTER_TYPE @@ -3146,17 +3314,17 @@ build_c_cast (tree type, tree expr) /* Casting the address of a decl to non void pointer. Warn if the cast breaks type based aliasing. */ if (!COMPLETE_TYPE_P (TREE_TYPE (type))) - warning ("type-punning to incomplete type might break strict-aliasing rules"); + warning (0, "type-punning to incomplete type might break strict-aliasing rules"); else { HOST_WIDE_INT set1 = get_alias_set (TREE_TYPE (TREE_OPERAND (expr, 0))); HOST_WIDE_INT set2 = get_alias_set (TREE_TYPE (type)); if (!alias_sets_conflict_p (set1, set2)) - warning ("dereferencing type-punned pointer will break strict-aliasing rules"); + warning (0, "dereferencing type-punned pointer will break strict-aliasing rules"); else if (warn_strict_aliasing > 1 && !alias_sets_might_conflict_p (set1, set2)) - warning ("dereferencing type-punned pointer might break strict-aliasing rules"); + warning (0, "dereferencing type-punned pointer might break strict-aliasing rules"); } } @@ -3180,9 +3348,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. */ @@ -3195,19 +3360,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); @@ -3253,11 +3412,7 @@ build_modify_expr (tree lhs, enum tree_code modifycode, tree rhs) if (TREE_CODE (lhs) == ERROR_MARK || TREE_CODE (rhs) == ERROR_MARK) return error_mark_node; - /* Strip NON_LVALUE_EXPRs since we aren't using as an lvalue. */ - /* Do not use STRIP_NOPS here. We do not want an enumerator - whose value is 0 to count as a null pointer constant. */ - if (TREE_CODE (rhs) == NON_LVALUE_EXPR) - rhs = TREE_OPERAND (rhs, 0); + STRIP_TYPE_NOPS (rhs); newrhs = rhs; @@ -3270,16 +3425,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'. @@ -3304,12 +3459,20 @@ 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 */ + /* Emit ObjC write barrier, if necessary. */ + if (c_dialect_objc () && flag_objc_gc) + { + result = objc_generate_write_barrier (lhs, modifycode, newrhs); + if (result) + return result; + } + + /* Scan operands. */ result = build2 (MODIFY_EXPR, lhstype, lhs, newrhs); TREE_SIDE_EFFECTS (result) = 1; @@ -3321,7 +3484,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); } @@ -3330,27 +3493,69 @@ 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; + bool objc_ok = false; + + if (errtype == ic_argpass || errtype == ic_argpass_nonproto) + { + tree selector; + /* Change pointer to function to the function itself for + diagnostics. */ + if (TREE_CODE (function) == ADDR_EXPR + && TREE_CODE (TREE_OPERAND (function, 0)) == FUNCTION_DECL) + function = TREE_OPERAND (function, 0); + + /* Handle an ObjC selector specially for diagnostics. */ + selector = objc_message_selector (); + rname = function; + if (selector && parmnum > 2) + { + rname = selector; + parmnum -= 2; + } + } - /* Strip NON_LVALUE_EXPRs since we aren't using as an lvalue. */ - /* Do not use STRIP_NOPS here. We do not want an enumerator - whose value is 0 to count as a null pointer constant. */ - if (TREE_CODE (rhs) == NON_LVALUE_EXPR) - rhs = TREE_OPERAND (rhs, 0); + /* This macro is used to emit diagnostics to ensure that all format + strings are complete sentences, visible to gettext and checked at + compile time. */ +#define WARN_FOR_ASSIGNMENT(AR, AS, IN, RE) \ + do { \ + switch (errtype) \ + { \ + case ic_argpass: \ + pedwarn (AR, parmnum, rname); \ + break; \ + case ic_argpass_nonproto: \ + warning (0, AR, parmnum, rname); \ + break; \ + case ic_assign: \ + pedwarn (AS); \ + break; \ + case ic_init: \ + pedwarn (IN); \ + break; \ + case ic_return: \ + pedwarn (RE); \ + break; \ + default: \ + gcc_unreachable (); \ + } \ + } while (0) + + STRIP_TYPE_NOPS (rhs); if (TREE_CODE (TREE_TYPE (rhs)) == ARRAY_TYPE || TREE_CODE (TREE_TYPE (rhs)) == FUNCTION_TYPE) @@ -3364,19 +3569,45 @@ convert_for_assignment (tree type, tree rhs, const char *errtype, if (coder == ERROR_MARK) return error_mark_node; + if (c_dialect_objc ()) + { + int parmno; + + switch (errtype) + { + case ic_return: + parmno = 0; + break; + + case ic_assign: + parmno = -1; + break; + + case ic_init: + parmno = -2; + break; + + default: + parmno = parmnum; + break; + } + + objc_ok = objc_compare_types (type, rhstype, parmno, rname); + } + if (TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (rhstype)) { overflow_warning (rhs); - /* Check for Objective-C protocols. This will automatically - issue a warning if there are protocol violations. No need to - use the return value. */ - if (c_dialect_objc ()) - objc_comptypes (type, rhstype, 0); return rhs; } 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; } @@ -3407,7 +3638,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. */ @@ -3421,7 +3652,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; @@ -3448,7 +3680,7 @@ convert_for_assignment (tree type, tree rhs, const char *errtype, Meanwhile, the lhs target must have all the qualifiers of the rhs. */ if (VOID_TYPE_P (ttl) || VOID_TYPE_P (ttr) - || comp_target_types (memb_type, rhstype, 0)) + || comp_target_types (memb_type, rhstype)) { /* If this type won't generate any warnings, use it. */ if (TYPE_QUALS (ttl) == TYPE_QUALS (ttr) @@ -3461,7 +3693,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; } } @@ -3478,7 +3710,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. */ @@ -3496,16 +3728,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 (G_("passing argument %d of %qE " + "makes qualified function " + "pointer from unqualified"), + G_("assignment makes qualified " + "function pointer from " + "unqualified"), + G_("initialization makes qualified " + "function pointer from " + "unqualified"), + G_("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 (G_("passing argument %d of %qE discards " + "qualifiers from pointer target type"), + G_("assignment discards qualifiers " + "from pointer target type"), + G_("initialization discards qualifiers " + "from pointer target type"), + G_("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); @@ -3518,9 +3764,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)) @@ -3531,10 +3783,10 @@ convert_for_assignment (tree type, tree rhs, const char *errtype, and vice versa; otherwise, targets must be the same. Meanwhile, the lhs target must have all the qualifiers of the rhs. */ if (VOID_TYPE_P (ttl) || VOID_TYPE_P (ttr) - || (target_cmp = comp_target_types (type, rhstype, 0)) + || (target_cmp = comp_target_types (type, rhstype)) || 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) @@ -3544,25 +3796,50 @@ 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 (G_("ISO C forbids passing argument %d of " + "%qE between function pointer " + "and %"), + G_("ISO C forbids assignment between " + "function pointer and %"), + G_("ISO C forbids initialization between " + "function pointer and %"), + G_("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); + { + /* Types differing only by the presence of the 'volatile' + qualifier are acceptable if the 'volatile' has been added + in by the Objective-C EH machinery. */ + if (!objc_type_quals_match (ttl, ttr)) + WARN_FOR_ASSIGNMENT (G_("passing argument %d of %qE discards " + "qualifiers from pointer target type"), + G_("assignment discards qualifiers " + "from pointer target type"), + G_("initialization discards qualifiers " + "from pointer target type"), + G_("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 (G_("pointer targets in passing argument " + "%d of %qE differ in signedness"), + G_("pointer targets in assignment " + "differ in signedness"), + G_("pointer targets in initialization " + "differ in signedness"), + G_("pointer targets in return differ " + "in signedness")); } else if (TREE_CODE (ttl) == FUNCTION_TYPE && TREE_CODE (ttr) == FUNCTION_TYPE) @@ -3572,17 +3849,33 @@ 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 (G_("passing argument %d of %qE makes " + "qualified function pointer " + "from unqualified"), + G_("assignment makes qualified function " + "pointer from unqualified"), + G_("initialization makes qualified " + "function pointer from unqualified"), + G_("return makes qualified function " + "pointer from unqualified")); } } else - warn_for_assignment ("%s from incompatible pointer type", - errtype, funname, parmnum); + /* Avoid warning about the volatile ObjC EH puts on decls. */ + if (!objc_ok) + WARN_FOR_ASSIGNMENT (G_("passing argument %d of %qE from " + "incompatible pointer type"), + G_("assignment from incompatible pointer type"), + G_("initialization from incompatible " + "pointer type"), + G_("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; } @@ -3591,45 +3884,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 (G_("passing argument %d of %qE makes " + "pointer from integer without a cast"), + G_("assignment makes pointer from integer " + "without a cast"), + G_("initialization makes pointer from " + "integer without a cast"), + G_("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 (G_("passing argument %d of %qE makes integer " + "from pointer without a cast"), + G_("assignment makes integer from pointer " + "without a cast"), + G_("initialization makes integer from pointer " + "without a cast"), + G_("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; } @@ -3645,80 +3951,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. @@ -3766,8 +4011,8 @@ 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)) - warning ("traditional C rejects automatic aggregate initialization"); + && AGGREGATE_TYPE_P (TREE_TYPE (decl)) && !TREE_STATIC (decl)) + warning (0, "traditional C rejects automatic aggregate initialization"); DECL_INITIAL (decl) = value; @@ -3782,8 +4027,7 @@ store_init_value (tree decl, tree init) { tree inside_init = init; - if (TREE_CODE (init) == NON_LVALUE_EXPR) - inside_init = TREE_OPERAND (init, 0); + STRIP_TYPE_NOPS (inside_init); inside_init = fold (inside_init); if (TREE_CODE (inside_init) == COMPOUND_LITERAL_EXPR) @@ -3935,7 +4179,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. @@ -3950,7 +4194,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. @@ -3962,10 +4206,10 @@ warning_init (const char *msgid) { char *ofwhat; - warning ("%s", _(msgid)); + warning (0, "%s", _(msgid)); ofwhat = print_spelling ((char *) alloca (spelling_length () + 1)); if (*ofwhat) - warning ("(near initialization for `%s')", ofwhat); + warning (0, "(near initialization for %qs)", ofwhat); } /* If TYPE is an array type and EXPR is a parenthesized string @@ -4003,11 +4247,7 @@ digest_init (tree type, tree init, bool strict_string, int require_constant) || TREE_TYPE (init) == error_mark_node) return error_mark_node; - /* Strip NON_LVALUE_EXPRs since we aren't using as an lvalue. */ - /* Do not use STRIP_NOPS here. We do not want an enumerator - whose value is 0 to count as a null pointer constant. */ - if (TREE_CODE (init) == NON_LVALUE_EXPR) - inside_init = TREE_OPERAND (init, 0); + STRIP_TYPE_NOPS (inside_init); inside_init = fold (inside_init); @@ -4081,17 +4321,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. */ @@ -4185,10 +4440,13 @@ 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; @@ -4284,17 +4542,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; @@ -4341,7 +4593,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. */ @@ -4356,7 +4608,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 @@ -4366,7 +4618,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; @@ -4378,22 +4629,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; @@ -4407,11 +4653,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 @@ -4463,7 +4708,6 @@ finish_init (void) 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; @@ -4565,7 +4809,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; } @@ -4597,19 +4844,27 @@ push_init_level (int implicit) tree value = NULL_TREE; /* If we've exhausted any levels that didn't have braces, - pop them now. */ - while (constructor_stack->implicit) + pop them now. If implicit == 1, this will have been done in + process_init_element; do not repeat it here because in the case + of excess initializers for an empty aggregate this leads to an + infinite cycle of popping a level and immediately recreating + it. */ + if (implicit != 1) { - if ((TREE_CODE (constructor_type) == RECORD_TYPE - || TREE_CODE (constructor_type) == UNION_TYPE) - && constructor_fields == 0) - process_init_element (pop_init_level (1)); - else if (TREE_CODE (constructor_type) == ARRAY_TYPE - && constructor_max_index - && tree_int_cst_lt (constructor_max_index, constructor_index)) - process_init_element (pop_init_level (1)); - else - break; + while (constructor_stack->implicit) + { + if ((TREE_CODE (constructor_type) == RECORD_TYPE + || TREE_CODE (constructor_type) == UNION_TYPE) + && constructor_fields == 0) + process_init_element (pop_init_level (1)); + else if (TREE_CODE (constructor_type) == ARRAY_TYPE + && constructor_max_index + && tree_int_cst_lt (constructor_max_index, + constructor_index)) + process_init_element (pop_init_level (1)); + else + break; + } } /* Unless this is an explicit brace, we need to preserve previous @@ -4769,7 +5024,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; } @@ -4815,7 +5071,7 @@ 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. */ @@ -4832,7 +5088,7 @@ pop_init_level (int implicit) /* We have already issued an error message for the existence of a flexible array member not at the end of the structure. - Discard the initializer so that we do not abort later. */ + Discard the initializer so that we do not die later. */ if (TREE_CHAIN (constructor_fields) != NULL_TREE) constructor_type = NULL_TREE; } @@ -4846,7 +5102,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); @@ -4968,12 +5224,6 @@ set_designator (int array) return 0; } - if (constructor_no_implicit) - { - error_init ("initialization designators may not nest"); - return 1; - } - switch (TREE_CODE (constructor_type)) { case RECORD_TYPE: @@ -5047,21 +5297,6 @@ set_init_index (tree first, tree last) return; } - while ((TREE_CODE (first) == NOP_EXPR - || TREE_CODE (first) == CONVERT_EXPR - || TREE_CODE (first) == NON_LVALUE_EXPR) - && (TYPE_MODE (TREE_TYPE (first)) - == TYPE_MODE (TREE_TYPE (TREE_OPERAND (first, 0))))) - first = TREE_OPERAND (first, 0); - - if (last) - while ((TREE_CODE (last) == NOP_EXPR - || TREE_CODE (last) == CONVERT_EXPR - || TREE_CODE (last) == NON_LVALUE_EXPR) - && (TYPE_MODE (TREE_TYPE (last)) - == TYPE_MODE (TREE_TYPE (TREE_OPERAND (last, 0))))) - last = TREE_OPERAND (last, 0); - if (TREE_CODE (first) != INTEGER_CST) error_init ("nonconstant array index in initializer"); else if (last != 0 && TREE_CODE (last) != INTEGER_CST) @@ -5132,8 +5367,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; @@ -5549,7 +5783,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; @@ -5821,7 +6055,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 @@ -5944,7 +6178,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 @@ -6022,7 +6256,7 @@ process_init_element (struct c_expr value) if (warn_traditional && !in_system_header && !constructor_designated && !(value.value && (integer_zerop (value.value) || real_zerop (value.value)))) - warning ("traditional C rejects initialization of unions"); + warning (0, "traditional C rejects initialization of unions"); /* Accept a string constant to initialize a subarray. */ if (value.value != 0 @@ -6032,7 +6266,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 @@ -6072,7 +6306,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 @@ -6137,7 +6371,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; @@ -6229,47 +6464,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); @@ -6279,6 +6547,7 @@ build_asm_expr (tree string, tree outputs, tree inputs, tree clobbers, ASM_VOLATILE_P (args) = 1; ASM_INPUT_P (args) = 1; } + return args; } @@ -6291,6 +6560,41 @@ c_finish_goto_label (tree label) if (!decl) return NULL_TREE; + if (C_DECL_UNJUMPABLE_STMT_EXPR (decl)) + { + error ("jump into statement expression"); + return NULL_TREE; + } + + if (C_DECL_UNJUMPABLE_VM (decl)) + { + error ("jump into scope of identifier with variably modified type"); + return NULL_TREE; + } + + if (!C_DECL_UNDEFINABLE_STMT_EXPR (decl)) + { + /* No jump from outside this statement expression context, so + record that there is a jump from within this context. */ + struct c_label_list *nlist; + nlist = XOBNEW (&parser_obstack, struct c_label_list); + nlist->next = label_context_stack_se->labels_used; + nlist->label = decl; + label_context_stack_se->labels_used = nlist; + } + + if (!C_DECL_UNDEFINABLE_VM (decl)) + { + /* No jump from outside this context context of identifiers with + variably modified type, so record that there is a jump from + within this context. */ + struct c_label_list *nlist; + nlist = XOBNEW (&parser_obstack, struct c_label_list); + nlist->next = label_context_stack_vm->labels_used; + nlist->label = decl; + label_context_stack_vm->labels_used = nlist; + } + TREE_USED (decl) = 1; return add_stmt (build1 (GOTO_EXPR, void_type_node, decl)); } @@ -6301,7 +6605,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)); } @@ -6315,24 +6619,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 (0, "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; @@ -6361,7 +6666,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)) @@ -6377,15 +6682,15 @@ 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"); + warning (0, "function returns address of local variable"); break; default: @@ -6402,10 +6707,10 @@ c_finish_return (tree retval) } struct c_switch { - /* The SWITCH_STMT being built. */ - tree switch_stmt; + /* The SWITCH_EXPR being built. */ + tree switch_expr; - /* 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; @@ -6416,6 +6721,16 @@ struct c_switch { of the GNU case range extension. */ splay_tree cases; + /* Number of nested statement expressions within this switch + statement; if nonzero, case and default labels may not + appear. */ + unsigned int blocked_stmt_expr; + + /* Scope of outermost declarations of identifiers with variably + modified type within this switch statement; if nonzero, case and + default labels may not appear. */ + unsigned int blocked_vm; + /* The next node on the stack. */ struct c_switch *next; }; @@ -6429,7 +6744,7 @@ struct c_switch { struct c_switch *c_switch_stack; /* Start a C switch statement, testing expression EXP. Return the new - SWITCH_STMT. */ + SWITCH_EXPR. */ tree c_start_case (tree exp) @@ -6443,11 +6758,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 { @@ -6456,23 +6772,25 @@ 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 (0, "% switch expression not converted to " + "% in ISO C"); exp = default_conversion (exp); type = TREE_TYPE (exp); } } - /* Add this new SWITCH_STMT to the stack. */ + /* Add this new SWITCH_EXPR 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_expr = build3 (SWITCH_EXPR, orig_type, exp, NULL_TREE, NULL_TREE); cs->orig_type = orig_type; cs->cases = splay_tree_new (case_compare, NULL, NULL); + cs->blocked_stmt_expr = 0; + cs->blocked_vm = 0; cs->next = c_switch_stack; c_switch_stack = cs; - return add_stmt (cs->switch_stmt); + return add_stmt (cs->switch_expr); } /* Process a case label. */ @@ -6482,19 +6800,38 @@ do_case (tree low_value, tree high_value) { tree label = NULL_TREE; - if (c_switch_stack) + if (c_switch_stack && !c_switch_stack->blocked_stmt_expr + && !c_switch_stack->blocked_vm) { label = c_add_case_label (c_switch_stack->cases, - SWITCH_COND (c_switch_stack->switch_stmt), + SWITCH_COND (c_switch_stack->switch_expr), c_switch_stack->orig_type, low_value, high_value); if (label == error_mark_node) label = NULL_TREE; } + else if (c_switch_stack && c_switch_stack->blocked_stmt_expr) + { + if (low_value) + error ("case label in statement expression not containing " + "enclosing switch statement"); + else + error ("% label in statement expression not containing " + "enclosing switch statement"); + } + else if (c_switch_stack && c_switch_stack->blocked_vm) + { + if (low_value) + error ("case label in scope of identifier with variably modified " + "type not containing enclosing switch statement"); + else + error ("% label in scope of identifier with variably " + "modified type not containing enclosing switch statement"); + } 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; } @@ -6505,11 +6842,23 @@ void c_finish_case (tree body) { struct c_switch *cs = c_switch_stack; + location_t switch_location; + + SWITCH_BODY (cs->switch_expr) = body; - SWITCH_BODY (cs->switch_stmt) = body; + /* We must not be within a statement expression nested in the switch + at this point; we might, however, be within the scope of an + identifier with variably modified type nested in the switch. */ + gcc_assert (!cs->blocked_stmt_expr); /* Emit warnings as needed. */ - c_do_switch_warnings (cs->cases, cs->switch_stmt); + if (EXPR_HAS_LOCATION (cs->switch_expr)) + switch_location = EXPR_LOCATION (cs->switch_expr); + else + switch_location = input_location; + c_do_switch_warnings (cs->cases, switch_location, + TREE_TYPE (cs->switch_expr), + SWITCH_COND (cs->switch_expr)); /* Pop the stack. */ c_switch_stack = cs->next; @@ -6558,7 +6907,7 @@ c_finish_if_stmt (location_t if_locus, tree cond, tree then_block, found: if (COND_EXPR_ELSE (inner_if)) - warning ("%Hsuggest explicit braces to avoid ambiguous `else'", + warning (0, "%Hsuggest explicit braces to avoid ambiguous %", &if_locus); } @@ -6568,7 +6917,7 @@ c_finish_if_stmt (location_t if_locus, tree cond, tree then_block, if (TREE_CODE (then_block) == NOP_EXPR && !TREE_TYPE (then_block)) { if (!else_block) - warning ("%Hempty body in an if-statement", + warning (0, "%Hempty body in an if-statement", EXPR_LOCUS (then_block)); then_block = alloc_stmt_list (); } @@ -6576,7 +6925,7 @@ c_finish_if_stmt (location_t if_locus, tree cond, tree then_block, && TREE_CODE (else_block) == NOP_EXPR && !TREE_TYPE (else_block)) { - warning ("%Hempty body in an else-statement", + warning (0, "%Hempty body in an else-statement", EXPR_LOCUS (else_block)); else_block = alloc_stmt_list (); } @@ -6599,10 +6948,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); @@ -6611,7 +6967,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 @@ -6658,10 +7014,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) @@ -6671,6 +7040,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)); } @@ -6684,7 +7056,7 @@ emit_side_effect_warnings (tree expr) else if (!TREE_SIDE_EFFECTS (expr)) { if (!VOID_TYPE_P (TREE_TYPE (expr)) && !TREE_NO_WARNING (expr)) - warning ("%Hstatement with no effect", + warning (0, "%Hstatement with no effect", EXPR_HAS_LOCATION (expr) ? EXPR_LOCUS (expr) : &input_location); } else if (warn_unused_value) @@ -6724,7 +7096,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)) @@ -6751,12 +7123,30 @@ tree c_begin_stmt_expr (void) { tree ret; + struct c_label_context_se *nstack; + struct c_label_list *glist; /* We must force a BLOCK for this level so that, if it is not expanded later, there is a way to turn off the entire subtree of blocks that are contained in it. */ keep_next_level (); ret = c_begin_compound_stmt (true); + if (c_switch_stack) + { + c_switch_stack->blocked_stmt_expr++; + gcc_assert (c_switch_stack->blocked_stmt_expr != 0); + } + for (glist = label_context_stack_se->labels_used; + glist != NULL; + glist = glist->next) + { + C_DECL_UNDEFINABLE_STMT_EXPR (glist->label) = 1; + } + nstack = XOBNEW (&parser_obstack, struct c_label_context_se); + nstack->labels_def = NULL; + nstack->labels_used = NULL; + nstack->next = label_context_stack_se; + label_context_stack_se = nstack; /* Mark the current statement list as belonging to a statement list. */ STATEMENT_LIST_STMT_EXPR (ret) = 1; @@ -6769,8 +7159,37 @@ c_finish_stmt_expr (tree body) { tree last, type, tmp, val; tree *last_p; + struct c_label_list *dlist, *glist, *glist_prev = NULL; body = c_end_compound_stmt (body, true); + if (c_switch_stack) + { + gcc_assert (c_switch_stack->blocked_stmt_expr != 0); + c_switch_stack->blocked_stmt_expr--; + } + /* It is no longer possible to jump to labels defined within this + statement expression. */ + for (dlist = label_context_stack_se->labels_def; + dlist != NULL; + dlist = dlist->next) + { + C_DECL_UNJUMPABLE_STMT_EXPR (dlist->label) = 1; + } + /* It is again possible to define labels with a goto just outside + this statement expression. */ + for (glist = label_context_stack_se->next->labels_used; + glist != NULL; + glist = glist->next) + { + C_DECL_UNDEFINABLE_STMT_EXPR (glist->label) = 0; + glist_prev = glist; + } + if (glist_prev != NULL) + glist_prev->next = label_context_stack_se->labels_used; + else + label_context_stack_se->next->labels_used + = label_context_stack_se->labels_used; + label_context_stack_se = label_context_stack_se->next; /* Locate the last statement in BODY. See c_end_compound_stmt about always returning a BIND_EXPR. */ @@ -6841,6 +7260,75 @@ c_finish_stmt_expr (tree body) return build4 (TARGET_EXPR, type, tmp, body, NULL_TREE, NULL_TREE); } + +/* Begin the scope of an identifier of variably modified type, scope + number SCOPE. Jumping from outside this scope to inside it is not + permitted. */ + +void +c_begin_vm_scope (unsigned int scope) +{ + struct c_label_context_vm *nstack; + struct c_label_list *glist; + + gcc_assert (scope > 0); + if (c_switch_stack && !c_switch_stack->blocked_vm) + c_switch_stack->blocked_vm = scope; + for (glist = label_context_stack_vm->labels_used; + glist != NULL; + glist = glist->next) + { + C_DECL_UNDEFINABLE_VM (glist->label) = 1; + } + nstack = XOBNEW (&parser_obstack, struct c_label_context_vm); + nstack->labels_def = NULL; + nstack->labels_used = NULL; + nstack->scope = scope; + nstack->next = label_context_stack_vm; + label_context_stack_vm = nstack; +} + +/* End a scope which may contain identifiers of variably modified + type, scope number SCOPE. */ + +void +c_end_vm_scope (unsigned int scope) +{ + if (label_context_stack_vm == NULL) + return; + if (c_switch_stack && c_switch_stack->blocked_vm == scope) + c_switch_stack->blocked_vm = 0; + /* We may have a number of nested scopes of identifiers with + variably modified type, all at this depth. Pop each in turn. */ + while (label_context_stack_vm->scope == scope) + { + struct c_label_list *dlist, *glist, *glist_prev = NULL; + + /* It is no longer possible to jump to labels defined within this + scope. */ + for (dlist = label_context_stack_vm->labels_def; + dlist != NULL; + dlist = dlist->next) + { + C_DECL_UNJUMPABLE_VM (dlist->label) = 1; + } + /* It is again possible to define labels with a goto just outside + this scope. */ + for (glist = label_context_stack_vm->next->labels_used; + glist != NULL; + glist = glist->next) + { + C_DECL_UNDEFINABLE_VM (glist->label) = 0; + glist_prev = glist; + } + if (glist_prev != NULL) + glist_prev->next = label_context_stack_vm->labels_used; + else + label_context_stack_vm->next->labels_used + = label_context_stack_vm->labels_used; + label_context_stack_vm = label_context_stack_vm->next; + } +} /* Begin and end compound statements. This is as simple as pushing and popping new statement lists from the tree. */ @@ -6970,6 +7458,9 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1, /* Nonzero means set RESULT_TYPE to the common type of the args. */ int common = 0; + /* True means types are compatible as far as ObjC is concerned. */ + bool objc_ok; + if (convert_p) { op0 = default_conversion (orig_op0); @@ -6999,6 +7490,8 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1, if (code0 == ERROR_MARK || code1 == ERROR_MARK) return error_mark_node; + objc_ok = objc_compare_types (type0, type1, -3, NULL_TREE); + switch (code) { case PLUS_EXPR: @@ -7015,7 +7508,7 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1, /* Subtraction of two similar pointers. We must subtract them as integers, then divide by object size. */ if (code0 == POINTER_TYPE && code1 == POINTER_TYPE - && comp_target_types (type0, type1, 1)) + && comp_target_types (type0, type1)) return pointer_diff (op0, op1); /* Handle pointer minus int. Just like pointer plus int. */ else if (code0 == POINTER_TYPE && code1 == INTEGER_TYPE) @@ -7035,8 +7528,8 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1, case EXACT_DIV_EXPR: /* Floating point division by zero is a legitimate way to obtain infinities and NaNs. */ - if (warn_div_by_zero && skip_evaluation == 0 && integer_zerop (op1)) - warning ("division by zero"); + if (skip_evaluation == 0 && integer_zerop (op1)) + warning (OPT_Wdiv_by_zero, "division by zero"); if ((code0 == INTEGER_TYPE || code0 == REAL_TYPE || code0 == COMPLEX_TYPE || code0 == VECTOR_TYPE) @@ -7058,7 +7551,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; @@ -7074,8 +7567,8 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1, case TRUNC_MOD_EXPR: case FLOOR_MOD_EXPR: - if (warn_div_by_zero && skip_evaluation == 0 && integer_zerop (op1)) - warning ("division by zero"); + if (skip_evaluation == 0 && integer_zerop (op1)) + warning (OPT_Wdiv_by_zero, "division by zero"); if (code0 == INTEGER_TYPE && code1 == INTEGER_TYPE) { @@ -7085,7 +7578,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; @@ -7104,8 +7597,8 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1, but that does not mean the operands should be converted to ints! */ result_type = integer_type_node; - op0 = lang_hooks.truthvalue_conversion (op0); - op1 = lang_hooks.truthvalue_conversion (op1); + op0 = c_common_truthvalue_conversion (op0); + op1 = c_common_truthvalue_conversion (op1); converted = 1; } break; @@ -7120,14 +7613,14 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1, if (TREE_CODE (op1) == INTEGER_CST && skip_evaluation == 0) { if (tree_int_cst_sgn (op1) < 0) - warning ("right shift count is negative"); + warning (0, "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) - warning ("right shift count >= width of type"); + warning (0, "right shift count >= width of type"); } } @@ -7148,33 +7641,10 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1, if (TREE_CODE (op1) == INTEGER_CST && skip_evaluation == 0) { if (tree_int_cst_sgn (op1) < 0) - warning ("left shift count is negative"); + warning (0, "left shift count is negative"); else if (compare_tree_int (op1, TYPE_PRECISION (type0)) >= 0) - warning ("left 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 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"); + warning (0, "left shift count >= width of type"); } /* Use the type of the value to be shifted. */ @@ -7190,8 +7660,9 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1, case EQ_EXPR: case NE_EXPR: - if (warn_float_equal && (code0 == REAL_TYPE || code1 == REAL_TYPE)) - warning ("comparing floating point with == or != is unsafe"); + if (code0 == REAL_TYPE || code1 == REAL_TYPE) + warning (OPT_Wfloat_equal, + "comparing floating point with == or != is unsafe"); /* Result of comparison is always int, but don't convert the args to int! */ build_type = integer_type_node; @@ -7207,7 +7678,7 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1, /* Anything compares with void *. void * compares with anything. Otherwise, the targets must be compatible and both must be object or both incomplete. */ - if (comp_target_types (type0, type1, 1)) + if (comp_target_types (type0, type1)) result_type = common_pointer_type (type0, type1); else if (VOID_TYPE_P (tt0)) { @@ -7215,16 +7686,20 @@ 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"); + /* Avoid warning about the volatile ObjC EH puts on decls. */ + if (!objc_ok) + pedwarn ("comparison of distinct pointer types lacks a cast"); if (result_type == NULL_TREE) result_type = ptr_type_node; @@ -7247,28 +7722,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: @@ -7279,7 +7732,7 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1, short_compare = 1; else if (code0 == POINTER_TYPE && code1 == POINTER_TYPE) { - if (comp_target_types (type0, type1, 1)) + if (comp_target_types (type0, type1)) { result_type = common_pointer_type (type0, type1); if (!COMPLETE_TYPE_P (TREE_TYPE (type0)) @@ -7321,25 +7774,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) @@ -7354,7 +7790,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, @@ -7412,7 +7848,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)) @@ -7486,8 +7922,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); @@ -7506,7 +7942,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) @@ -7541,11 +7977,11 @@ 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 - warning ("comparison between signed and unsigned"); + warning (0, "comparison between signed and unsigned"); } /* Warn if two unsigned values are being compared in a size @@ -7589,9 +8025,9 @@ 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"); + warning (0, "comparison of promoted ~unsigned with constant"); } } else if (unsignedp0 && unsignedp1 @@ -7599,7 +8035,7 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1, < TYPE_PRECISION (result_type)) && (TYPE_PRECISION (TREE_TYPE (primop1)) < TYPE_PRECISION (result_type))) - warning ("comparison of promoted ~unsigned with unsigned"); + warning (0, "comparison of promoted ~unsigned with unsigned"); } } } @@ -7617,7 +8053,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); @@ -7645,3 +8081,34 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1, return result; } } + + +/* Convert EXPR to be a truth-value, validating its type for this + purpose. Passes EXPR to default_function_array_conversion. */ + +tree +c_objc_common_truthvalue_conversion (tree expr) +{ + expr = default_function_array_conversion (expr); + switch (TREE_CODE (TREE_TYPE (expr))) + { + case ARRAY_TYPE: + error ("used array that cannot be converted to pointer where scalar is required"); + return error_mark_node; + + case RECORD_TYPE: + error ("used struct type value where scalar is required"); + return error_mark_node; + + case UNION_TYPE: + error ("used union type value where scalar is required"); + return error_mark_node; + + default: + break; + } + + /* ??? Should we also give an error for void and vectors rather than + leaving those to give errors later? */ + return c_common_truthvalue_conversion (expr); +}