X-Git-Url: http://git.sourceforge.jp/view?a=blobdiff_plain;f=gcc%2Fc-typeck.c;h=73c120d16a30d0332f6da9237b447a7b96515613;hb=09d2b71abf963a21323283769a9fa81ac43ec71e;hp=cde90a763d30729b2ec777b93f69695332d3e90e;hpb=c3ceba8e8139354ec6e7fb9510bb3541d5baac23;p=pf3gnuchains%2Fgcc-fork.git diff --git a/gcc/c-typeck.c b/gcc/c-typeck.c index cde90a763d3..73c120d16a3 100644 --- a/gcc/c-typeck.c +++ b/gcc/c-typeck.c @@ -1,6 +1,7 @@ /* 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, 2005 Free Software Foundation, Inc. + 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006 + Free Software Foundation, Inc. This file is part of GCC. @@ -16,8 +17,8 @@ for more details. You should have received a copy of the GNU General Public License along with GCC; see the file COPYING. If not, write to the Free -Software Foundation, 59 Temple Place - Suite 330, Boston, MA -02111-1307, USA. */ +Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301, USA. */ /* This file is part of the C front end. @@ -74,13 +75,13 @@ static int missing_braces_mentioned; static int require_constant_value; static int require_constant_elements; +static bool null_pointer_constant_p (tree); 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); -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); @@ -106,7 +107,38 @@ 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); +static int comptypes_internal (tree, tree); +/* Return true if EXP is a null pointer constant, false otherwise. */ + +static bool +null_pointer_constant_p (tree expr) +{ + /* This should really operate on c_expr structures, but they aren't + yet available everywhere required. */ + tree type = TREE_TYPE (expr); + return (TREE_CODE (expr) == INTEGER_CST + && !TREE_CONSTANT_OVERFLOW (expr) + && integer_zerop (expr) + && (INTEGRAL_TYPE_P (type) + || (TREE_CODE (type) == POINTER_TYPE + && VOID_TYPE_P (TREE_TYPE (type)) + && TYPE_QUALS (TREE_TYPE (type)) == TYPE_UNQUALIFIED))); +} + /* This is a cache to hold if two types are compatible or not. */ + +struct tagged_tu_seen_cache { + const struct tagged_tu_seen_cache * next; + tree t1; + tree t2; + /* The return value of tagged_types_tu_compatible_p if we had seen + these two types already. */ + int val; +}; + +static const struct tagged_tu_seen_cache * tagged_tu_seen_base; +static void free_all_tagged_tu_seen_up_to (const struct tagged_tu_seen_cache *); + /* Do `exp = require_complete_type (exp);' to make sure exp does not have an incomplete type. (That includes void types.) */ @@ -282,14 +314,30 @@ composite_type (tree t1, tree t2) tree elt = composite_type (TREE_TYPE (t1), TREE_TYPE (t2)); int quals; tree unqual_elt; + tree d1 = TYPE_DOMAIN (t1); + tree d2 = TYPE_DOMAIN (t2); + bool d1_variable, d2_variable; + bool d1_zero, d2_zero; /* We should not have any type quals on arrays at all. */ gcc_assert (!TYPE_QUALS (t1) && !TYPE_QUALS (t2)); + d1_zero = d1 == 0 || !TYPE_MAX_VALUE (d1); + d2_zero = d2 == 0 || !TYPE_MAX_VALUE (d2); + + d1_variable = (!d1_zero + && (TREE_CODE (TYPE_MIN_VALUE (d1)) != INTEGER_CST + || TREE_CODE (TYPE_MAX_VALUE (d1)) != INTEGER_CST)); + d2_variable = (!d2_zero + && (TREE_CODE (TYPE_MIN_VALUE (d2)) != INTEGER_CST + || TREE_CODE (TYPE_MAX_VALUE (d2)) != INTEGER_CST)); + /* Save space: see if the result is identical to one of the args. */ - if (elt == TREE_TYPE (t1) && TYPE_DOMAIN (t1)) + if (elt == TREE_TYPE (t1) && TYPE_DOMAIN (t1) + && (d2_variable || d2_zero || !d1_variable)) return build_type_attribute_variant (t1, attributes); - if (elt == TREE_TYPE (t2) && TYPE_DOMAIN (t2)) + if (elt == TREE_TYPE (t2) && TYPE_DOMAIN (t2) + && (d1_variable || d1_zero || !d2_variable)) return build_type_attribute_variant (t2, attributes); if (elt == TREE_TYPE (t1) && !TYPE_DOMAIN (t2) && !TYPE_DOMAIN (t1)) @@ -305,7 +353,12 @@ composite_type (tree t1, tree t2) 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)); + TYPE_DOMAIN ((TYPE_DOMAIN (t1) + && (d2_variable + || d2_zero + || !d1_variable)) + ? t1 + : t2)); t1 = c_build_qualified_type (t1, quals); return build_type_attribute_variant (t1, attributes); } @@ -565,6 +618,22 @@ c_common_type (tree t1, tree t2) if (code2 == REAL_TYPE && code1 != REAL_TYPE) return t2; + /* If both are real and either are decimal floating point types, use + the decimal floating point type with the greater precision. */ + + if (code1 == REAL_TYPE && code2 == REAL_TYPE) + { + if (TYPE_MAIN_VARIANT (t1) == dfloat128_type_node + || TYPE_MAIN_VARIANT (t2) == dfloat128_type_node) + return dfloat128_type_node; + else if (TYPE_MAIN_VARIANT (t1) == dfloat64_type_node + || TYPE_MAIN_VARIANT (t2) == dfloat64_type_node) + return dfloat64_type_node; + else if (TYPE_MAIN_VARIANT (t1) == dfloat32_type_node + || TYPE_MAIN_VARIANT (t2) == dfloat32_type_node) + return dfloat32_type_node; + } + /* Both real or both integers; use the one with greater precision. */ if (TYPE_PRECISION (t1) > TYPE_PRECISION (t2)) @@ -617,8 +686,11 @@ c_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. */ +/* Wrapper around c_common_type that is used by c-common.c and other + front end optimizations that remove promotions. 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) { @@ -626,9 +698,21 @@ common_type (tree t1, tree t2) 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. */ @@ -636,6 +720,22 @@ common_type (tree t1, tree t2) int comptypes (tree type1, tree type2) { + const struct tagged_tu_seen_cache * tagged_tu_seen_base1 = tagged_tu_seen_base; + int val; + + val = comptypes_internal (type1, type2); + free_all_tagged_tu_seen_up_to (tagged_tu_seen_base1); + + return val; +} +/* 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. This + differs from comptypes, in that we don't free the seen types. */ + +static int +comptypes_internal (tree type1, tree type2) +{ tree t1 = type1; tree t2 = type2; int attrval, val; @@ -697,16 +797,12 @@ 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) - break; /* Do not remove mode or aliasing information. */ if (TYPE_MODE (t1) != TYPE_MODE (t2) || TYPE_REF_CAN_ALIAS_ALL (t1) != TYPE_REF_CAN_ALIAS_ALL (t2)) break; val = (TREE_TYPE (t1) == TREE_TYPE (t2) - ? 1 : comptypes (TREE_TYPE (t1), TREE_TYPE (t2))); + ? 1 : comptypes_internal (TREE_TYPE (t1), TREE_TYPE (t2))); break; case FUNCTION_TYPE: @@ -723,7 +819,7 @@ comptypes (tree type1, tree type2) /* Target types must match incl. qualifiers. */ if (TREE_TYPE (t1) != TREE_TYPE (t2) - && 0 == (val = comptypes (TREE_TYPE (t1), TREE_TYPE (t2)))) + && 0 == (val = comptypes_internal (TREE_TYPE (t1), TREE_TYPE (t2)))) return 0; /* Sizes must match unless one is missing or variable. */ @@ -752,21 +848,20 @@ comptypes (tree type1, tree type2) 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); + { + if (attrval != 2) + return tagged_types_tu_compatible_p (t1, t2); + val = tagged_types_tu_compatible_p (t1, t2); + } break; case VECTOR_TYPE: val = TYPE_VECTOR_SUBPARTS (t1) == TYPE_VECTOR_SUBPARTS (t2) - && comptypes (TREE_TYPE (t1), TREE_TYPE (t2)); + && comptypes_internal (TREE_TYPE (t1), TREE_TYPE (t2)); break; default: @@ -776,22 +871,14 @@ 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; tree mvl, mvr; - /* Give objc_comptypes a crack at letting these types through. */ - if ((val = objc_comptypes (ttl, ttr, reflexive)) >= 0) - return val; - /* Do not lose qualifiers on element types of array types that are pointer targets by taking their TYPE_MAIN_VARIANT. */ mvl = TREE_TYPE (ttl); @@ -843,21 +930,48 @@ same_translation_unit_p (tree t1, tree t2) return t1 == t2; } -/* The C standard says that two structures in different translation - units are compatible with each other only if the types of their - fields are compatible (among other things). So, consider two copies - of this structure: */ +/* Allocate the seen two types, assuming that they are compatible. */ -struct tagged_tu_seen { - const struct tagged_tu_seen * next; - tree t1; - tree t2; -}; +static struct tagged_tu_seen_cache * +alloc_tagged_tu_seen_cache (tree t1, tree t2) +{ + struct tagged_tu_seen_cache *tu = XNEW (struct tagged_tu_seen_cache); + tu->next = tagged_tu_seen_base; + tu->t1 = t1; + tu->t2 = t2; + + tagged_tu_seen_base = tu; + + /* The C standard says that two structures in different translation + units are compatible with each other only if the types of their + fields are compatible (among other things). We assume that they + are compatible until proven otherwise when building the cache. + An example where this can occur is: + struct a + { + struct a *next; + }; + If we are comparing this against a similar struct in another TU, + and did not assume they were compatible, we end up with an infinite + loop. */ + tu->val = 1; + return tu; +} -/* Can they be compatible with each other? We choose to break the - recursion by allowing those types to be compatible. */ +/* Free the seen types until we get to TU_TIL. */ -static const struct tagged_tu_seen * tagged_tu_seen_base; +static void +free_all_tagged_tu_seen_up_to (const struct tagged_tu_seen_cache *tu_til) +{ + const struct tagged_tu_seen_cache *tu = tagged_tu_seen_base; + while (tu != tu_til) + { + struct tagged_tu_seen_cache *tu1 = (struct tagged_tu_seen_cache*)tu; + tu = tu1->next; + free (tu1); + } + tagged_tu_seen_base = tu_til; +} /* Return 1 if two 'struct', 'union', or 'enum' types T1 and T2 are compatible. If the two types are not the same (which has been @@ -899,73 +1013,123 @@ tagged_types_tu_compatible_p (tree t1, tree t2) return 1; { - const struct tagged_tu_seen * tts_i; + const struct tagged_tu_seen_cache * tts_i; for (tts_i = tagged_tu_seen_base; tts_i != NULL; tts_i = tts_i->next) if (tts_i->t1 == t1 && tts_i->t2 == t2) - return 1; + return tts_i->val; } switch (TREE_CODE (t1)) { case ENUMERAL_TYPE: { - + struct tagged_tu_seen_cache *tu = alloc_tagged_tu_seen_cache (t1, t2); /* Speed up the case where the type values are in the same order. */ tree tv1 = TYPE_VALUES (t1); tree tv2 = TYPE_VALUES (t2); if (tv1 == tv2) - return 1; + { + return 1; + } for (;tv1 && tv2; tv1 = TREE_CHAIN (tv1), tv2 = TREE_CHAIN (tv2)) { if (TREE_PURPOSE (tv1) != TREE_PURPOSE (tv2)) break; if (simple_cst_equal (TREE_VALUE (tv1), TREE_VALUE (tv2)) != 1) - return 0; + { + tu->val = 0; + return 0; + } } if (tv1 == NULL_TREE && tv2 == NULL_TREE) - return 1; + { + return 1; + } if (tv1 == NULL_TREE || tv2 == NULL_TREE) - return 0; + { + tu->val = 0; + return 0; + } if (list_length (TYPE_VALUES (t1)) != list_length (TYPE_VALUES (t2))) - return 0; + { + tu->val = 0; + return 0; + } for (s1 = TYPE_VALUES (t1); s1; s1 = TREE_CHAIN (s1)) { s2 = purpose_member (TREE_PURPOSE (s1), TYPE_VALUES (t2)); if (s2 == NULL || simple_cst_equal (TREE_VALUE (s1), TREE_VALUE (s2)) != 1) - return 0; + { + tu->val = 0; + return 0; + } } return 1; } case UNION_TYPE: { + struct tagged_tu_seen_cache *tu = alloc_tagged_tu_seen_cache (t1, t2); if (list_length (TYPE_FIELDS (t1)) != list_length (TYPE_FIELDS (t2))) - return 0; + { + tu->val = 0; + return 0; + } + + /* Speed up the common case where the fields are in the same order. */ + for (s1 = TYPE_FIELDS (t1), s2 = TYPE_FIELDS (t2); s1 && s2; + s1 = TREE_CHAIN (s1), s2 = TREE_CHAIN (s2)) + { + int result; + + + if (DECL_NAME (s1) == NULL + || DECL_NAME (s1) != DECL_NAME (s2)) + break; + result = comptypes_internal (TREE_TYPE (s1), TREE_TYPE (s2)); + if (result == 0) + { + tu->val = 0; + return 0; + } + if (result == 2) + needs_warning = true; + + if (TREE_CODE (s1) == FIELD_DECL + && simple_cst_equal (DECL_FIELD_BIT_OFFSET (s1), + DECL_FIELD_BIT_OFFSET (s2)) != 1) + { + tu->val = 0; + return 0; + } + } + if (!s1 && !s2) + { + tu->val = needs_warning ? 2 : 1; + return tu->val; + } for (s1 = TYPE_FIELDS (t1); s1; s1 = TREE_CHAIN (s1)) { bool ok = false; - struct tagged_tu_seen tts; - - tts.next = tagged_tu_seen_base; - tts.t1 = t1; - tts.t2 = t2; - tagged_tu_seen_base = &tts; if (DECL_NAME (s1) != NULL) for (s2 = TYPE_FIELDS (t2); s2; s2 = TREE_CHAIN (s2)) if (DECL_NAME (s1) == DECL_NAME (s2)) { int result; - result = comptypes (TREE_TYPE (s1), TREE_TYPE (s2)); + result = comptypes_internal (TREE_TYPE (s1), TREE_TYPE (s2)); if (result == 0) - break; + { + tu->val = 0; + return 0; + } if (result == 2) needs_warning = true; @@ -977,21 +1141,19 @@ tagged_types_tu_compatible_p (tree t1, tree t2) ok = true; break; } - tagged_tu_seen_base = tts.next; if (!ok) - return 0; + { + tu->val = 0; + return 0; + } } - return needs_warning ? 2 : 1; + tu->val = needs_warning ? 2 : 10; + return tu->val; } case RECORD_TYPE: { - struct tagged_tu_seen tts; - - tts.next = tagged_tu_seen_base; - tts.t1 = t1; - tts.t2 = t2; - tagged_tu_seen_base = &tts; + struct tagged_tu_seen_cache *tu = alloc_tagged_tu_seen_cache (t1, t2); for (s1 = TYPE_FIELDS (t1), s2 = TYPE_FIELDS (t2); s1 && s2; @@ -1001,7 +1163,7 @@ tagged_types_tu_compatible_p (tree t1, tree t2) if (TREE_CODE (s1) != TREE_CODE (s2) || DECL_NAME (s1) != DECL_NAME (s2)) break; - result = comptypes (TREE_TYPE (s1), TREE_TYPE (s2)); + result = comptypes_internal (TREE_TYPE (s1), TREE_TYPE (s2)); if (result == 0) break; if (result == 2) @@ -1012,10 +1174,11 @@ tagged_types_tu_compatible_p (tree t1, tree t2) DECL_FIELD_BIT_OFFSET (s2)) != 1) break; } - tagged_tu_seen_base = tts.next; if (s1 && s2) - return 0; - return needs_warning ? 2 : 1; + tu->val = 0; + else + tu->val = needs_warning ? 2 : 1; + return tu->val; } default: @@ -1052,7 +1215,7 @@ function_types_compatible_p (tree f1, tree f2) if (TYPE_VOLATILE (ret2)) ret2 = build_qualified_type (TYPE_MAIN_VARIANT (ret2), TYPE_QUALS (ret2) & ~TYPE_QUAL_VOLATILE); - val = comptypes (ret1, ret2); + val = comptypes_internal (ret1, ret2); if (val == 0) return 0; @@ -1068,7 +1231,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 (0, but no error). */ + If they don't match, ask for a warning (but no error). */ if (TYPE_ACTUAL_ARG_TYPES (f1) && 1 != type_lists_compatible_p (args2, TYPE_ACTUAL_ARG_TYPES (f1))) val = 2; @@ -1133,7 +1296,7 @@ type_lists_compatible_p (tree args1, tree args2) else if (TREE_CODE (a1) == ERROR_MARK || TREE_CODE (a2) == ERROR_MARK) ; - else if (!(newval = comptypes (mv1, mv2))) + else if (!(newval = comptypes_internal (mv1, mv2))) { /* Allow wait (union {union wait *u; int *i} *) and wait (union wait *) to be compatible. */ @@ -1152,7 +1315,7 @@ type_lists_compatible_p (tree args1, tree args2) if (mv3 && mv3 != error_mark_node && TREE_CODE (mv3) != ARRAY_TYPE) mv3 = TYPE_MAIN_VARIANT (mv3); - if (comptypes (mv3, mv2)) + if (comptypes_internal (mv3, mv2)) break; } if (memb == 0) @@ -1173,7 +1336,7 @@ type_lists_compatible_p (tree args1, tree args2) if (mv3 && mv3 != error_mark_node && TREE_CODE (mv3) != ARRAY_TYPE) mv3 = TYPE_MAIN_VARIANT (mv3); - if (comptypes (mv3, mv1)) + if (comptypes_internal (mv3, mv1)) break; } if (memb == 0) @@ -1249,109 +1412,131 @@ 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); -} - -/* Perform the default conversion of arrays and functions to pointers. - Return the result of converting EXP. For any other expression, just - return EXP. */ + 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; +} +/* Convert the array expression EXP to a pointer. */ static tree -default_function_array_conversion (tree exp) +array_to_pointer_conversion (tree exp) { - tree orig_exp; + tree orig_exp = exp; tree type = TREE_TYPE (exp); - enum tree_code code = TREE_CODE (type); - int not_lvalue = 0; + tree adr; + tree restype = TREE_TYPE (type); + tree ptrtype; - /* Strip NON_LVALUE_EXPRs and no-op conversions, since we aren't using as - an lvalue. + gcc_assert (TREE_CODE (type) == ARRAY_TYPE); - Do not use STRIP_NOPS here! It will remove conversions from pointer - to integer and cause infinite recursion. */ - orig_exp = exp; - while (TREE_CODE (exp) == NON_LVALUE_EXPR - || (TREE_CODE (exp) == NOP_EXPR - && TREE_TYPE (TREE_OPERAND (exp, 0)) == TREE_TYPE (exp))) - { - if (TREE_CODE (exp) == NON_LVALUE_EXPR) - not_lvalue = 1; - exp = TREE_OPERAND (exp, 0); - } + STRIP_TYPE_NOPS (exp); if (TREE_NO_WARNING (orig_exp)) TREE_NO_WARNING (exp) = 1; - if (code == FUNCTION_TYPE) + ptrtype = build_pointer_type (restype); + + if (TREE_CODE (exp) == INDIRECT_REF) + return convert (ptrtype, TREE_OPERAND (exp, 0)); + + if (TREE_CODE (exp) == VAR_DECL) { - return build_unary_op (ADDR_EXPR, exp, 0); + /* We are making an ADDR_EXPR of ptrtype. This is a valid + ADDR_EXPR because it's the best way of representing what + happens in C when we take the address of an array and place + it in a pointer to the element type. */ + adr = build1 (ADDR_EXPR, ptrtype, exp); + if (!c_mark_addressable (exp)) + return error_mark_node; + TREE_SIDE_EFFECTS (adr) = 0; /* Default would be, same as EXP. */ + return adr; } - if (code == ARRAY_TYPE) - { - tree adr; - tree restype = TREE_TYPE (type); - tree ptrtype; - int constp = 0; - int volatilep = 0; - int lvalue_array_p; - if (REFERENCE_CLASS_P (exp) || DECL_P (exp)) - { - constp = TREE_READONLY (exp); - volatilep = TREE_THIS_VOLATILE (exp); - } + /* This way is better for a COMPONENT_REF since it can + simplify the offset for a component. */ + adr = build_unary_op (ADDR_EXPR, exp, 1); + return convert (ptrtype, adr); +} - if (TYPE_QUALS (type) || constp || volatilep) - restype - = c_build_qualified_type (restype, - TYPE_QUALS (type) - | (constp * TYPE_QUAL_CONST) - | (volatilep * TYPE_QUAL_VOLATILE)); +/* Convert the function expression EXP to a pointer. */ +static tree +function_to_pointer_conversion (tree exp) +{ + tree orig_exp = exp; - if (TREE_CODE (exp) == INDIRECT_REF) - return convert (build_pointer_type (restype), - TREE_OPERAND (exp, 0)); + gcc_assert (TREE_CODE (TREE_TYPE (exp)) == FUNCTION_TYPE); - if (TREE_CODE (exp) == COMPOUND_EXPR) - { - tree op1 = default_conversion (TREE_OPERAND (exp, 1)); - return build2 (COMPOUND_EXPR, TREE_TYPE (op1), - TREE_OPERAND (exp, 0), op1); - } + STRIP_TYPE_NOPS (exp); - lvalue_array_p = !not_lvalue && lvalue_p (exp); - if (!flag_isoc99 && !lvalue_array_p) - { - /* Before C99, non-lvalue arrays do not decay to pointers. - Normally, using such an array would be invalid; but it can - be used correctly inside sizeof or as a statement expression. - Thus, do not give an error here; an error will result later. */ - return exp; - } + if (TREE_NO_WARNING (orig_exp)) + TREE_NO_WARNING (exp) = 1; - ptrtype = build_pointer_type (restype); + return build_unary_op (ADDR_EXPR, exp, 0); +} - if (TREE_CODE (exp) == VAR_DECL) - { - /* We are making an ADDR_EXPR of ptrtype. This is a valid - ADDR_EXPR because it's the best way of representing what - happens in C when we take the address of an array and place - it in a pointer to the element type. */ - adr = build1 (ADDR_EXPR, ptrtype, exp); - if (!c_mark_addressable (exp)) - return error_mark_node; - TREE_SIDE_EFFECTS (adr) = 0; /* Default would be, same as EXP. */ - return adr; - } - /* This way is better for a COMPONENT_REF since it can - simplify the offset for a component. */ - adr = build_unary_op (ADDR_EXPR, exp, 1); - return convert (ptrtype, adr); +/* Perform the default conversion of arrays and functions to pointers. + Return the result of converting EXP. For any other expression, just + return EXP after removing NOPs. */ + +struct c_expr +default_function_array_conversion (struct c_expr exp) +{ + tree orig_exp = exp.value; + tree type = TREE_TYPE (exp.value); + enum tree_code code = TREE_CODE (type); + + switch (code) + { + case ARRAY_TYPE: + { + bool not_lvalue = false; + bool lvalue_array_p; + + while ((TREE_CODE (exp.value) == NON_LVALUE_EXPR + || TREE_CODE (exp.value) == NOP_EXPR + || TREE_CODE (exp.value) == CONVERT_EXPR) + && TREE_TYPE (TREE_OPERAND (exp.value, 0)) == type) + { + if (TREE_CODE (exp.value) == NON_LVALUE_EXPR) + not_lvalue = true; + exp.value = TREE_OPERAND (exp.value, 0); + } + + if (TREE_NO_WARNING (orig_exp)) + TREE_NO_WARNING (exp.value) = 1; + + lvalue_array_p = !not_lvalue && lvalue_p (exp.value); + if (!flag_isoc99 && !lvalue_array_p) + { + /* Before C99, non-lvalue arrays do not decay to pointers. + Normally, using such an array would be invalid; but it can + be used correctly inside sizeof or as a statement expression. + Thus, do not give an error here; an error will result later. */ + return exp; + } + + exp.value = array_to_pointer_conversion (exp.value); + } + break; + case FUNCTION_TYPE: + exp.value = function_to_pointer_conversion (exp.value); + break; + default: + STRIP_TYPE_NOPS (exp.value); + if (TREE_NO_WARNING (orig_exp)) + TREE_NO_WARNING (exp.value) = 1; + break; } + return exp; } @@ -1405,8 +1590,7 @@ perform_integral_promotions (tree 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. + Enumeral types or short or char are converted to int. In addition, manifest constants symbols are replaced by their values. */ tree @@ -1416,8 +1600,10 @@ default_conversion (tree 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); + /* Functions and arrays have been converted during parsing. */ + gcc_assert (code != FUNCTION_TYPE); + if (code == ARRAY_TYPE) + return exp; /* Constants can be used directly unless they're not loadable. */ if (TREE_CODE (exp) == CONST_DECL) @@ -1633,12 +1819,9 @@ build_indirect_ref (tree ptr, const char *errorstring) else { tree t = TREE_TYPE (type); - tree mvt = t; tree ref; - if (TREE_CODE (mvt) != ARRAY_TYPE) - mvt = TYPE_MAIN_VARIANT (mvt); - ref = build1 (INDIRECT_REF, mvt, pointer); + ref = build1 (INDIRECT_REF, t, pointer); if (!COMPLETE_OR_VOID_TYPE_P (t) && TREE_CODE (t) != ARRAY_TYPE) { @@ -1712,16 +1895,10 @@ build_array_ref (tree array, tree index) 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 %"); + /* ??? Existing practice has been to warn only when the char + index is syntactically the index, not for char[array]. */ + if (!swapped) + warn_array_subscript_with_type_char (index); /* Apply default promotions *after* noticing character types. */ index = default_conversion (index); @@ -1979,26 +2156,23 @@ build_function_call (tree function, tree params) /* Convert anything with function type to a pointer-to-function. */ if (TREE_CODE (function) == FUNCTION_DECL) { - if (DECL_BUILT_IN_CLASS (function) == BUILT_IN_NORMAL) - { - tem = resolve_overloaded_builtin (function, params); - if (tem) - return tem; - } + /* 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 - (because calling an inline function does not mean the function - needs to be separately compiled). */ - fntype = build_type_variant (TREE_TYPE (function), - TREE_READONLY (function), - TREE_THIS_VOLATILE (function)); fundecl = function; - function = build1 (ADDR_EXPR, build_pointer_type (fntype), function); } - else - function = default_conversion (function); + if (TREE_CODE (TREE_TYPE (function)) == FUNCTION_TYPE) + function = function_to_pointer_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); @@ -2022,13 +2196,9 @@ 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 (function) == CONVERT_EXPR) && TREE_CODE (tem = TREE_OPERAND (function, 0)) == ADDR_EXPR && TREE_CODE (tem = TREE_OPERAND (tem, 0)) == FUNCTION_DECL && !comptypes (fntype, TREE_TYPE (tem))) @@ -2054,10 +2224,9 @@ build_function_call (tree function, tree params) if (AGGREGATE_TYPE_P (return_type)) rhs = build_compound_literal (return_type, - build_constructor (return_type, - NULL_TREE)); + build_constructor (return_type, 0)); else - rhs = fold (build1 (NOP_EXPR, return_type, integer_zero_node)); + rhs = fold_convert (return_type, integer_zero_node); return build2 (COMPOUND_EXPR, return_type, trap, rhs); } @@ -2074,15 +2243,13 @@ build_function_call (tree function, tree params) /* Check that the arguments to the function are valid. */ - check_function_arguments (TYPE_ATTRIBUTES (fntype), coerced_params); - - result = build3 (CALL_EXPR, TREE_TYPE (fntype), - function, coerced_params, NULL_TREE); - TREE_SIDE_EFFECTS (result) = 1; + check_function_arguments (TYPE_ATTRIBUTES (fntype), coerced_params, + TYPE_ARG_TYPES (fntype)); if (require_constant_value) { - result = fold_initializer (result); + result = fold_build3_initializer (CALL_EXPR, TREE_TYPE (fntype), + function, coerced_params, NULL_TREE); if (TREE_CONSTANT (result) && (name == NULL_TREE @@ -2090,7 +2257,8 @@ build_function_call (tree function, tree params) pedwarn_init ("initializer element is not constant"); } else - result = fold (result); + result = fold_build3 (CALL_EXPR, TREE_TYPE (fntype), + function, coerced_params, NULL_TREE); if (VOID_TYPE_P (TREE_TYPE (result))) return result; @@ -2161,8 +2329,6 @@ convert_arguments (tree typelist, tree values, tree function, tree fundecl) STRIP_TYPE_NOPS (val); - val = default_function_array_conversion (val); - val = require_complete_type (val); if (type != 0) @@ -2221,10 +2387,37 @@ convert_arguments (tree typelist, tree values, tree function, 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)) + if (formal_prec == TYPE_PRECISION (float_type_node) + && type != dfloat32_type_node) warning (0, "passing argument %d of %qE as % " "rather than % due to prototype", argnum, rname); + + /* Warn if mismatch between argument and prototype + for decimal float types. Warn of conversions with + binary float types and of precision narrowing due to + prototype. */ + else if (type != TREE_TYPE (val) + && (type == dfloat32_type_node + || type == dfloat64_type_node + || type == dfloat128_type_node + || TREE_TYPE (val) == dfloat32_type_node + || TREE_TYPE (val) == dfloat64_type_node + || TREE_TYPE (val) == dfloat128_type_node) + && (formal_prec + <= TYPE_PRECISION (TREE_TYPE (val)) + || (type == dfloat128_type_node + && (TREE_TYPE (val) + != dfloat64_type_node + && (TREE_TYPE (val) + != dfloat32_type_node))) + || (type == dfloat64_type_node + && (TREE_TYPE (val) + != dfloat32_type_node)))) + warning (0, "passing argument %d of %qE as %qT " + "rather than %qT due to prototype", + argnum, rname, type, TREE_TYPE (val)); + } /* Detect integer changing in width or signedness. These warnings are only activated with @@ -2242,8 +2435,9 @@ convert_arguments (tree typelist, tree values, tree function, tree fundecl) and the actual arg is that enum type. */ ; else if (formal_prec != TYPE_PRECISION (type1)) - warning (0, "passing argument %d of %qE with different " - "width due to prototype", argnum, rname); + warning (OPT_Wconversion, "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 @@ -2264,11 +2458,12 @@ convert_arguments (tree typelist, tree values, tree function, tree fundecl) && TYPE_UNSIGNED (TREE_TYPE (val))) ; else if (TYPE_UNSIGNED (type)) - warning (0, "passing argument %d of %qE as unsigned " - "due to prototype", argnum, rname); + warning (OPT_Wconversion, "passing argument %d of %qE " + "as unsigned due to prototype", + argnum, rname); else - warning (0, "passing argument %d of %qE as signed " - "due to prototype", argnum, rname); + warning (OPT_Wconversion, "passing argument %d of %qE " + "as signed due to prototype", argnum, rname); } } @@ -2285,7 +2480,8 @@ convert_arguments (tree typelist, tree values, tree function, tree fundecl) } else if (TREE_CODE (TREE_TYPE (val)) == REAL_TYPE && (TYPE_PRECISION (TREE_TYPE (val)) - < TYPE_PRECISION (double_type_node))) + < TYPE_PRECISION (double_type_node)) + && !DECIMAL_FLOAT_MODE_P (TYPE_MODE (TREE_TYPE (val)))) /* Convert `float' to `double'. */ result = tree_cons (NULL_TREE, convert (double_type_node, val), result); else if ((invalid_func_diag = @@ -2311,11 +2507,27 @@ convert_arguments (tree typelist, tree values, tree function, tree fundecl) 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, @@ -2340,14 +2552,16 @@ 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 (0, "suggest parentheses around + or - inside shift"); + warning (OPT_Wparentheses, + "suggest parentheses around + or - inside shift"); } if (code == TRUTH_ORIF_EXPR) { if (code1 == TRUTH_ANDIF_EXPR || code2 == TRUTH_ANDIF_EXPR) - warning (0, "suggest parentheses around && within ||"); + warning (OPT_Wparentheses, + "suggest parentheses around && within ||"); } if (code == BIT_IOR_EXPR) @@ -2356,11 +2570,13 @@ 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 (0, "suggest parentheses around arithmetic in operand of |"); + warning (OPT_Wparentheses, + "suggest parentheses around arithmetic in operand of |"); /* Check cases like x|y==z */ if (TREE_CODE_CLASS (code1) == tcc_comparison || TREE_CODE_CLASS (code2) == tcc_comparison) - warning (0, "suggest parentheses around comparison in operand of |"); + warning (OPT_Wparentheses, + "suggest parentheses around comparison in operand of |"); } if (code == BIT_XOR_EXPR) @@ -2369,31 +2585,50 @@ 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 (0, "suggest parentheses around arithmetic in operand of ^"); + warning (OPT_Wparentheses, + "suggest parentheses around arithmetic in operand of ^"); /* Check cases like x^y==z */ if (TREE_CODE_CLASS (code1) == tcc_comparison || TREE_CODE_CLASS (code2) == tcc_comparison) - warning (0, "suggest parentheses around comparison in operand of ^"); + warning (OPT_Wparentheses, + "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 (0, "suggest parentheses around + or - in operand of &"); + warning (OPT_Wparentheses, + "suggest parentheses around + or - in operand of &"); /* Check cases like x&y==z */ if (TREE_CODE_CLASS (code1) == tcc_comparison || TREE_CODE_CLASS (code2) == tcc_comparison) - warning (0, "suggest parentheses around comparison in operand of &"); + warning (OPT_Wparentheses, + "suggest parentheses around comparison in operand of &"); } /* Similarly, check for cases like 1<=i<=10 that are probably errors. */ 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"); + warning (OPT_Wparentheses, "comparisons like X<=Y<=Z do not " + "have their mathematical meaning"); } + /* Warn about comparisons against string literals, with the exception + of testing for equality or inequality of a string literal with NULL. */ + if (code == EQ_EXPR || code == NE_EXPR) + { + if ((code1 == STRING_CST && !integer_zerop (arg2.value)) + || (code2 == STRING_CST && !integer_zerop (arg1.value))) + warning (OPT_Wstring_literal_comparison, + "comparison with string literal"); + } + else if (TREE_CODE_CLASS (code) == tcc_comparison + && (code1 == STRING_CST || code2 == STRING_CST)) + warning (OPT_Wstring_literal_comparison, + "comparison with string literal"); + unsigned_conversion_warning (result.value, arg1.value); unsigned_conversion_warning (result.value, arg2.value); overflow_warning (result.value); @@ -2429,8 +2664,18 @@ pointer_diff (tree op0, tree op1) different mode in place.) So first try to find a common term here 'by hand'; we want to cover at least the cases that occur in legal static initializers. */ - con0 = TREE_CODE (op0) == NOP_EXPR ? TREE_OPERAND (op0, 0) : op0; - con1 = TREE_CODE (op1) == NOP_EXPR ? TREE_OPERAND (op1, 0) : op1; + if ((TREE_CODE (op0) == NOP_EXPR || TREE_CODE (op0) == CONVERT_EXPR) + && (TYPE_PRECISION (TREE_TYPE (op0)) + == TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (op0, 0))))) + con0 = TREE_OPERAND (op0, 0); + else + con0 = op0; + if ((TREE_CODE (op1) == NOP_EXPR || TREE_CODE (op1) == CONVERT_EXPR) + && (TYPE_PRECISION (TREE_TYPE (op1)) + == TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (op1, 0))))) + con1 = TREE_OPERAND (op1, 0); + else + con1 = op1; if (TREE_CODE (con0) == PLUS_EXPR) { @@ -2470,7 +2715,7 @@ pointer_diff (tree op0, tree op1) op1 = c_size_in_bytes (target_type); /* Divide by the size, in easiest possible way. */ - return fold (build2 (EXACT_DIV_EXPR, restype, op0, convert (restype, op1))); + return fold_build2 (EXACT_DIV_EXPR, restype, op0, convert (restype, op1)); } /* Construct and perhaps optimize a tree representation @@ -2491,12 +2736,20 @@ build_unary_op (enum tree_code code, tree xarg, int flag) enum tree_code typecode = TREE_CODE (TREE_TYPE (arg)); tree val; int noconvert = flag; + const char *invalid_op_diag; if (typecode == ERROR_MARK) return error_mark_node; if (typecode == ENUMERAL_TYPE || typecode == BOOLEAN_TYPE) typecode = INTEGER_TYPE; + if ((invalid_op_diag + = targetm.invalid_unary_op (code, TREE_TYPE (xarg)))) + { + error (invalid_op_diag); + return error_mark_node; + } + switch (code) { case CONVERT_EXPR: @@ -2571,13 +2824,9 @@ 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 - /* These will convert to a pointer. */ - && typecode != ARRAY_TYPE && typecode != FUNCTION_TYPE) + && typecode != COMPLEX_TYPE) { error ("wrong type argument to unary exclamation mark"); return error_mark_node; @@ -2585,14 +2834,11 @@ build_unary_op (enum tree_code code, tree xarg, int flag) arg = c_objc_common_truthvalue_conversion (arg); return invert_truthvalue (arg); - case NOP_EXPR: - break; - case REALPART_EXPR: if (TREE_CODE (arg) == COMPLEX_CST) return TREE_REALPART (arg); else if (TREE_CODE (TREE_TYPE (arg)) == COMPLEX_TYPE) - return fold (build1 (REALPART_EXPR, TREE_TYPE (TREE_TYPE (arg)), arg)); + return fold_build1 (REALPART_EXPR, TREE_TYPE (TREE_TYPE (arg)), arg); else return arg; @@ -2600,7 +2846,7 @@ build_unary_op (enum tree_code code, tree xarg, int flag) if (TREE_CODE (arg) == COMPLEX_CST) return TREE_IMAGPART (arg); else if (TREE_CODE (TREE_TYPE (arg)) == COMPLEX_TYPE) - return fold (build1 (IMAGPART_EXPR, TREE_TYPE (TREE_TYPE (arg)), arg)); + return fold_build1 (IMAGPART_EXPR, TREE_TYPE (TREE_TYPE (arg)), arg); else return convert (TREE_TYPE (arg), integer_zero_node); @@ -2685,10 +2931,13 @@ build_unary_op (enum tree_code code, tree xarg, int flag) /* Report a read-only lvalue. */ if (TREE_READONLY (arg)) - readonly_error (arg, - ((code == PREINCREMENT_EXPR - || code == POSTINCREMENT_EXPR) - ? lv_increment : lv_decrement)); + { + readonly_error (arg, + ((code == PREINCREMENT_EXPR + || code == POSTINCREMENT_EXPR) + ? lv_increment : lv_decrement)); + return error_mark_node; + } if (TREE_CODE (TREE_TYPE (arg)) == BOOLEAN_TYPE) val = boolean_increment (code, arg); @@ -2716,9 +2965,13 @@ build_unary_op (enum tree_code code, tree xarg, int flag) /* For &x[y], return x+y */ if (TREE_CODE (arg) == ARRAY_REF) { - if (!c_mark_addressable (TREE_OPERAND (arg, 0))) + tree op0 = TREE_OPERAND (arg, 0); + if (!c_mark_addressable (op0)) return error_mark_node; - return build_binary_op (PLUS_EXPR, TREE_OPERAND (arg, 0), + return build_binary_op (PLUS_EXPR, + (TREE_CODE (TREE_TYPE (op0)) == ARRAY_TYPE + ? array_to_pointer_conversion (op0) + : op0), TREE_OPERAND (arg, 1), 1); } @@ -2753,24 +3006,26 @@ build_unary_op (enum tree_code code, tree xarg, int flag) 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)); + && TREE_CONSTANT (TREE_OPERAND (val, 0))) + { + tree op0 = fold_convert (argtype, fold_offsetof (arg)), op1; - val = build1 (ADDR_EXPR, argtype, arg); + op1 = fold_convert (argtype, TREE_OPERAND (val, 0)); + return fold_build2 (PLUS_EXPR, argtype, op0, op1); + } - if (TREE_CODE (arg) == COMPOUND_LITERAL_EXPR) - TREE_INVARIANT (val) = TREE_CONSTANT (val) = 1; + val = build1 (ADDR_EXPR, argtype, arg); return val; default: - break; + gcc_unreachable (); } if (argtype == 0) argtype = TREE_TYPE (arg); - val = build1 (code, argtype, arg); - return require_constant_value ? fold_initializer (val) : fold (val); + return require_constant_value ? fold_build1_initializer (code, argtype, arg) + : fold_build1 (code, argtype, arg); } /* Return nonzero if REF is an lvalue valid for this language. @@ -2815,32 +3070,36 @@ lvalue_p (tree ref) static void readonly_error (tree arg, enum lvalue_use use) { - gcc_assert (use == lv_assign || use == lv_increment || use == lv_decrement); + gcc_assert (use == lv_assign || use == lv_increment || use == lv_decrement + || use == lv_asm); /* 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))) +#define READONLY_MSG(A, I, D, AS) (use == lv_assign ? (A) \ + : (use == lv_increment ? (I) \ + : (use == lv_decrement ? (D) : (AS)))) if (TREE_CODE (arg) == COMPONENT_REF) { if (TYPE_READONLY (TREE_TYPE (TREE_OPERAND (arg, 0)))) readonly_error (TREE_OPERAND (arg, 0), use); else - error (READONLY_MSG (N_("assignment of read-only member %qD"), - N_("increment of read-only member %qD"), - N_("decrement of read-only member %qD")), + error (READONLY_MSG (G_("assignment of read-only member %qD"), + G_("increment of read-only member %qD"), + G_("decrement of read-only member %qD"), + G_("read-only member %qD used as % output")), TREE_OPERAND (arg, 1)); } else if (TREE_CODE (arg) == VAR_DECL) - error (READONLY_MSG (N_("assignment of read-only variable %qD"), - N_("increment of read-only variable %qD"), - N_("decrement of read-only variable %qD")), + error (READONLY_MSG (G_("assignment of read-only variable %qD"), + G_("increment of read-only variable %qD"), + G_("decrement of read-only variable %qD"), + G_("read-only variable %qD used as % output")), arg); else - error (READONLY_MSG (N_("assignment of read-only location"), - N_("increment of read-only location"), - N_("decrement of read-only location"))); + error (READONLY_MSG (G_("assignment of read-only location"), + G_("increment of read-only location"), + G_("decrement of read-only location"), + G_("read-only location used as % output"))); } @@ -3015,13 +3274,11 @@ 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) + else if (null_pointer_constant_p (orig_op1)) result_type = qualify_type (type2, type1); - else if (integer_zerop (op2) && TREE_TYPE (type2) == void_type_node - && TREE_CODE (orig_op2) != NOP_EXPR) + else if (null_pointer_constant_p (orig_op2)) result_type = qualify_type (type1, type2); else if (VOID_TYPE_P (TREE_TYPE (type1))) { @@ -3047,7 +3304,7 @@ build_conditional_expr (tree ifexp, tree op1, tree op2) } else if (code1 == POINTER_TYPE && code2 == INTEGER_TYPE) { - if (!integer_zerop (op2)) + if (!null_pointer_constant_p (orig_op2)) pedwarn ("pointer/integer type mismatch in conditional expression"); else { @@ -3057,7 +3314,7 @@ build_conditional_expr (tree ifexp, tree op1, tree op2) } else if (code2 == POINTER_TYPE && code1 == INTEGER_TYPE) { - if (!integer_zerop (op1)) + if (!null_pointer_constant_p (orig_op1)) pedwarn ("pointer/integer type mismatch in conditional expression"); else { @@ -3088,10 +3345,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 @@ -3100,18 +3354,25 @@ build_conditional_expr (tree ifexp, tree op1, tree op2) tree build_compound_expr (tree expr1, tree expr2) { - /* Convert arrays and functions to pointers. */ - expr2 = default_function_array_conversion (expr2); - 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 (0, "left-hand operand of comma expression has no effect"); + if (warn_unused_value) + { + if (VOID_TYPE_P (TREE_TYPE (expr1)) + && (TREE_CODE (expr1) == NOP_EXPR + || 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 + || TREE_CODE (TREE_OPERAND (expr1, 1)) == NOP_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 @@ -3166,7 +3427,6 @@ build_c_cast (tree type, tree expr) else if (TREE_CODE (type) == UNION_TYPE) { tree field; - value = default_function_array_conversion (value); for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field)) if (comptypes (TYPE_MAIN_VARIANT (TREE_TYPE (field)), @@ -3180,8 +3440,7 @@ build_c_cast (tree type, tree expr) if (pedantic) pedwarn ("ISO C forbids casts to union type"); t = digest_init (type, - build_constructor (type, - build_tree_list (field, value)), + build_constructor_single (type, field, value), true, 0); TREE_CONSTANT (t) = TREE_CONSTANT (value); TREE_INVARIANT (t) = TREE_INVARIANT (value); @@ -3194,14 +3453,9 @@ build_c_cast (tree type, tree expr) { tree otype, ovalue; - /* If casting to void, avoid the error that would come - from default_conversion in the case of a non-lvalue array. */ if (type == void_type_node) return build1 (CONVERT_EXPR, type, value); - /* Convert functions and arrays to pointers, - but don't convert any other types. */ - value = default_function_array_conversion (value); otype = TREE_TYPE (value); /* Optionally warn about potentially worrisome casts. */ @@ -3247,7 +3501,7 @@ build_c_cast (tree type, tree expr) } /* Warn about possible alignment problems. */ - if (STRICT_ALIGNMENT && warn_cast_align + if (STRICT_ALIGNMENT && TREE_CODE (type) == POINTER_TYPE && TREE_CODE (otype) == POINTER_TYPE && TREE_CODE (TREE_TYPE (otype)) != VOID_TYPE @@ -3258,52 +3512,34 @@ 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 (0, "cast increases required alignment of target type"); + warning (OPT_Wcast_align, + "cast increases required alignment of target type"); - if (warn_pointer_to_int_cast - && TREE_CODE (type) == INTEGER_TYPE + if (TREE_CODE (type) == INTEGER_TYPE && TREE_CODE (otype) == POINTER_TYPE - && TYPE_PRECISION (type) != TYPE_PRECISION (otype) - && !TREE_CONSTANT (value)) - warning (0, "cast from pointer to integer of different size"); - - if (warn_bad_function_cast - && TREE_CODE (value) == CALL_EXPR + && TYPE_PRECISION (type) != TYPE_PRECISION (otype)) + /* Unlike conversion of integers to pointers, where the + warning is disabled for converting constants because + of cases such as SIG_*, warn about converting constant + pointers to integers. In some cases it may cause unwanted + sign extension, and a warning is appropriate. */ + warning (OPT_Wpointer_to_int_cast, + "cast from pointer to integer of different size"); + + if (TREE_CODE (value) == CALL_EXPR && TREE_CODE (type) != TREE_CODE (otype)) - warning (0, "cast from function call of type %qT to non-matching " - "type %qT", otype, type); + warning (OPT_Wbad_function_cast, "cast from function call of type %qT " + "to non-matching type %qT", otype, type); - if (warn_int_to_pointer_cast - && TREE_CODE (type) == POINTER_TYPE + if (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 (0, "cast to pointer from integer of different size"); + warning (OPT_Wint_to_pointer_cast, "cast to pointer from integer " + "of different size"); - if (TREE_CODE (type) == POINTER_TYPE - && TREE_CODE (otype) == POINTER_TYPE - && TREE_CODE (expr) == ADDR_EXPR - && DECL_P (TREE_OPERAND (expr, 0)) - && flag_strict_aliasing && warn_strict_aliasing - && !VOID_TYPE_P (TREE_TYPE (type))) - { - /* 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 (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 (0, "dereferencing type-punned pointer will break strict-aliasing rules"); - else if (warn_strict_aliasing > 1 - && !alias_sets_might_conflict_p (set1, set2)) - warning (0, "dereferencing type-punned pointer might break strict-aliasing rules"); - } - } + strict_aliasing_warning (otype, type, expr); /* If pedantic, warn for conversions between function and object pointer types, except for converting a null pointer constant @@ -3320,8 +3556,7 @@ build_c_cast (tree type, tree expr) && TREE_CODE (otype) == POINTER_TYPE && TREE_CODE (TREE_TYPE (type)) == FUNCTION_TYPE && TREE_CODE (TREE_TYPE (otype)) != FUNCTION_TYPE - && !(integer_zerop (value) && TREE_TYPE (otype) == void_type_node - && TREE_CODE (expr) != NOP_EXPR)) + && !null_pointer_constant_p (value)) pedwarn ("ISO C forbids conversion of object pointer to function pointer type"); ovalue = value; @@ -3330,17 +3565,19 @@ build_c_cast (tree type, tree expr) /* Ignore any integer overflow caused by the cast. */ if (TREE_CODE (value) == INTEGER_CST) { - if (EXPR_P (ovalue)) - /* If OVALUE had overflow set, then so will VALUE, so it - is safe to overwrite. */ - TREE_OVERFLOW (value) = TREE_OVERFLOW (ovalue); - else - TREE_OVERFLOW (value) = 0; - - if (CONSTANT_CLASS_P (ovalue)) - /* Similarly, constant_overflow cannot have become - cleared. */ - TREE_CONSTANT_OVERFLOW (value) = TREE_CONSTANT_OVERFLOW (ovalue); + if (CONSTANT_CLASS_P (ovalue) + && (TREE_OVERFLOW (ovalue) || TREE_CONSTANT_OVERFLOW (ovalue))) + { + /* Avoid clobbering a shared constant. */ + value = copy_node (value); + TREE_OVERFLOW (value) = TREE_OVERFLOW (ovalue); + TREE_CONSTANT_OVERFLOW (value) = TREE_CONSTANT_OVERFLOW (ovalue); + } + else if (TREE_OVERFLOW (value) || TREE_CONSTANT_OVERFLOW (value)) + /* Reset VALUE's overflow flags, ensuring constant sharing. */ + value = build_int_cst_wide (TREE_TYPE (value), + TREE_INT_CST_LOW (value), + TREE_INT_CST_HIGH (value)); } } @@ -3411,7 +3648,10 @@ build_modify_expr (tree lhs, enum tree_code modifycode, tree rhs) || ((TREE_CODE (lhstype) == RECORD_TYPE || TREE_CODE (lhstype) == UNION_TYPE) && C_TYPE_FIELDS_READONLY (lhstype))) - readonly_error (lhs, lv_assign); + { + readonly_error (lhs, lv_assign); + return error_mark_node; + } /* If storing into a structure or union member, it has probably been given type `int'. @@ -3441,6 +3681,14 @@ build_modify_expr (tree lhs, enum tree_code modifycode, tree rhs) if (TREE_CODE (newrhs) == ERROR_MARK) return error_mark_node; + /* 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); @@ -3476,6 +3724,7 @@ convert_for_assignment (tree type, tree rhs, enum impl_conv errtype, tree rhstype; enum tree_code coder; tree rname = NULL_TREE; + bool objc_ok = false; if (errtype == ic_argpass || errtype == ic_argpass_nonproto) { @@ -3525,10 +3774,8 @@ convert_for_assignment (tree type, tree rhs, enum impl_conv errtype, STRIP_TYPE_NOPS (rhs); - if (TREE_CODE (TREE_TYPE (rhs)) == ARRAY_TYPE - || TREE_CODE (TREE_TYPE (rhs)) == FUNCTION_TYPE) - rhs = default_conversion (rhs); - else if (optimize && TREE_CODE (rhs) == VAR_DECL) + if (optimize && TREE_CODE (rhs) == VAR_DECL + && TREE_CODE (TREE_TYPE (rhs)) != ARRAY_TYPE) rhs = decl_constant_value_for_broken_optimization (rhs); rhstype = TREE_TYPE (rhs); @@ -3537,14 +3784,35 @@ convert_for_assignment (tree type, tree rhs, enum impl_conv 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; } @@ -3602,13 +3870,11 @@ convert_for_assignment (tree type, tree rhs, enum impl_conv 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; + tree memb, marginal_memb = NULL_TREE; - for (memb_types = TYPE_FIELDS (type); memb_types; - memb_types = TREE_CHAIN (memb_types)) + for (memb = TYPE_FIELDS (type); memb ; memb = TREE_CHAIN (memb)) { - tree memb_type = TREE_TYPE (memb_types); + tree memb_type = TREE_TYPE (memb); if (comptypes (TYPE_MAIN_VARIANT (memb_type), TYPE_MAIN_VARIANT (rhstype))) @@ -3627,7 +3893,7 @@ convert_for_assignment (tree type, tree rhs, enum impl_conv 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) @@ -3640,28 +3906,26 @@ convert_for_assignment (tree type, tree rhs, enum impl_conv errtype, break; /* Keep looking for a better type, but remember this one. */ - if (!marginal_memb_type) - marginal_memb_type = memb_type; + if (!marginal_memb) + marginal_memb = memb; } } /* Can convert integer zero to any pointer type. */ - if (integer_zerop (rhs) - || (TREE_CODE (rhs) == NOP_EXPR - && integer_zerop (TREE_OPERAND (rhs, 0)))) + if (null_pointer_constant_p (rhs)) { rhs = null_pointer_node; break; } } - if (memb_types || marginal_memb_type) + if (memb || marginal_memb) { - if (!memb_types) + if (!memb) { /* We have only a marginally acceptable member type; it needs a warning. */ - tree ttl = TREE_TYPE (marginal_memb_type); + tree ttl = TREE_TYPE (TREE_TYPE (marginal_memb)); tree ttr = TREE_TYPE (rhstype); /* Const and volatile mean something different for function @@ -3675,33 +3939,35 @@ convert_for_assignment (tree type, tree rhs, enum impl_conv errtype, function where an ordinary one is wanted, but not vice-versa. */ if (TYPE_QUALS (ttl) & ~TYPE_QUALS (ttr)) - WARN_FOR_ASSIGNMENT (N_("passing argument %d of %qE " + WARN_FOR_ASSIGNMENT (G_("passing argument %d of %qE " "makes qualified function " "pointer from unqualified"), - N_("assignment makes qualified " + G_("assignment makes qualified " "function pointer from " "unqualified"), - N_("initialization makes qualified " + G_("initialization makes qualified " "function pointer from " "unqualified"), - N_("return makes qualified function " + G_("return makes qualified function " "pointer from unqualified")); } else if (TYPE_QUALS (ttr) & ~TYPE_QUALS (ttl)) - WARN_FOR_ASSIGNMENT (N_("passing argument %d of %qE discards " + WARN_FOR_ASSIGNMENT (G_("passing argument %d of %qE discards " "qualifiers from pointer target type"), - N_("assignment discards qualifiers " + G_("assignment discards qualifiers " "from pointer target type"), - N_("initialization discards qualifiers " + G_("initialization discards qualifiers " "from pointer target type"), - N_("return discards qualifiers from " + G_("return discards qualifiers from " "pointer target type")); + + memb = marginal_memb; } - if (pedantic && !DECL_IN_SYSTEM_HEADER (fundecl)) + if (pedantic && (!fundecl || !DECL_IN_SYSTEM_HEADER (fundecl))) pedwarn ("ISO C prohibits argument conversion to union type"); - return build1 (NOP_EXPR, type, rhs); + return build_constructor_single (type, memb, rhs); } } @@ -3725,12 +3991,57 @@ convert_for_assignment (tree type, tree rhs, enum impl_conv errtype, || targetm.vector_opaque_p (rhstype)) && TREE_CODE (ttl) == VECTOR_TYPE && TREE_CODE (ttr) == VECTOR_TYPE; - + + /* C++ does not allow the implicit conversion void* -> T*. However, + for the purpose of reducing the number of false positives, we + tolerate the special case of + + int *p = NULL; + + where NULL is typically defined in C to be '(void *) 0'. */ + if (VOID_TYPE_P (ttr) && rhs != null_pointer_node && !VOID_TYPE_P (ttl)) + warning (OPT_Wc___compat, "request for implicit conversion from " + "%qT to %qT not permitted in C++", rhstype, type); + + /* Check if the right-hand side has a format attribute but the + left-hand side doesn't. */ + if (warn_missing_format_attribute + && check_missing_format_attribute (type, rhstype)) + { + switch (errtype) + { + case ic_argpass: + case ic_argpass_nonproto: + warning (OPT_Wmissing_format_attribute, + "argument %d of %qE might be " + "a candidate for a format attribute", + parmnum, rname); + break; + case ic_assign: + warning (OPT_Wmissing_format_attribute, + "assignment left-hand side might be " + "a candidate for a format attribute"); + break; + case ic_init: + warning (OPT_Wmissing_format_attribute, + "initialization left-hand side might be " + "a candidate for a format attribute"); + break; + case ic_return: + warning (OPT_Wmissing_format_attribute, + "return type might be " + "a candidate for a format attribute"); + break; + default: + gcc_unreachable (); + } + } + /* Any non-function converts to a [const][volatile] void * 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 (mvl) == c_common_unsigned_type (mvr))) @@ -3739,18 +4050,16 @@ convert_for_assignment (tree type, tree rhs, enum impl_conv errtype, && ((VOID_TYPE_P (ttl) && TREE_CODE (ttr) == FUNCTION_TYPE) || (VOID_TYPE_P (ttr) - /* Check TREE_CODE to catch cases like (void *) (char *) 0 - which are not ANSI null ptr constants. */ - && (!integer_zerop (rhs) || TREE_CODE (rhs) == NOP_EXPR) + && !null_pointer_constant_p (rhs) && TREE_CODE (ttl) == FUNCTION_TYPE))) - WARN_FOR_ASSIGNMENT (N_("ISO C forbids passing argument %d of " + WARN_FOR_ASSIGNMENT (G_("ISO C forbids passing argument %d of " "%qE between function pointer " "and %"), - N_("ISO C forbids assignment between " + G_("ISO C forbids assignment between " "function pointer and %"), - N_("ISO C forbids initialization between " + G_("ISO C forbids initialization between " "function pointer and %"), - N_("ISO C forbids return between function " + 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. */ @@ -3758,14 +4067,20 @@ convert_for_assignment (tree type, tree rhs, enum impl_conv errtype, && TREE_CODE (ttl) != FUNCTION_TYPE) { if (TYPE_QUALS (ttr) & ~TYPE_QUALS (ttl)) - WARN_FOR_ASSIGNMENT (N_("passing argument %d of %qE discards " - "qualifiers from pointer target type"), - N_("assignment discards qualifiers " - "from pointer target type"), - N_("initialization discards qualifiers " - "from pointer target type"), - N_("return discards qualifiers from " - "pointer target type")); + { + /* 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) @@ -3773,13 +4088,13 @@ convert_for_assignment (tree type, tree rhs, enum impl_conv errtype, ; /* If there is a mismatch, do warn. */ else if (warn_pointer_sign) - WARN_FOR_ASSIGNMENT (N_("pointer targets in passing argument " + WARN_FOR_ASSIGNMENT (G_("pointer targets in passing argument " "%d of %qE differ in signedness"), - N_("pointer targets in assignment " + G_("pointer targets in assignment " "differ in signedness"), - N_("pointer targets in initialization " + G_("pointer targets in initialization " "differ in signedness"), - N_("pointer targets in return differ " + G_("pointer targets in return differ " "in signedness")); } else if (TREE_CODE (ttl) == FUNCTION_TYPE @@ -3790,24 +4105,27 @@ convert_for_assignment (tree type, tree rhs, enum impl_conv 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 (N_("passing argument %d of %qE makes " + WARN_FOR_ASSIGNMENT (G_("passing argument %d of %qE makes " "qualified function pointer " "from unqualified"), - N_("assignment makes qualified function " + G_("assignment makes qualified function " "pointer from unqualified"), - N_("initialization makes qualified " + G_("initialization makes qualified " "function pointer from unqualified"), - N_("return makes qualified function " + G_("return makes qualified function " "pointer from unqualified")); } } else - WARN_FOR_ASSIGNMENT (N_("passing argument %d of %qE from " - "incompatible pointer type"), - N_("assignment from incompatible pointer type"), - N_("initialization from incompatible " - "pointer type"), - N_("return from incompatible pointer type")); + /* 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) @@ -3822,32 +4140,27 @@ convert_for_assignment (tree type, tree rhs, enum impl_conv 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)) - && - !(TREE_CODE (rhs) == NOP_EXPR - && TREE_CODE (TREE_TYPE (rhs)) == INTEGER_TYPE - && TREE_CODE (TREE_OPERAND (rhs, 0)) == INTEGER_CST - && integer_zerop (TREE_OPERAND (rhs, 0)))) - WARN_FOR_ASSIGNMENT (N_("passing argument %d of %qE makes " + if (!null_pointer_constant_p (rhs)) + WARN_FOR_ASSIGNMENT (G_("passing argument %d of %qE makes " "pointer from integer without a cast"), - N_("assignment makes pointer from integer " + G_("assignment makes pointer from integer " "without a cast"), - N_("initialization makes pointer from " + G_("initialization makes pointer from " "integer without a cast"), - N_("return makes pointer from integer " + G_("return makes pointer from integer " "without a cast")); return convert (type, rhs); } else if (codel == INTEGER_TYPE && coder == POINTER_TYPE) { - WARN_FOR_ASSIGNMENT (N_("passing argument %d of %qE makes integer " + WARN_FOR_ASSIGNMENT (G_("passing argument %d of %qE makes integer " "from pointer without a cast"), - N_("assignment makes integer from pointer " + G_("assignment makes integer from pointer " "without a cast"), - N_("initialization makes integer from pointer " + G_("initialization makes integer from pointer " "without a cast"), - N_("return makes integer from pointer " + G_("return makes integer from pointer " "without a cast")); return convert (type, rhs); } @@ -3948,9 +4261,10 @@ store_init_value (tree decl, tree init) /* Store the expression if valid; else report error. */ - if (warn_traditional && !in_system_header + if (!in_system_header && AGGREGATE_TYPE_P (TREE_TYPE (decl)) && !TREE_STATIC (decl)) - warning (0, "traditional C rejects automatic aggregate initialization"); + warning (OPT_Wtraditional, "traditional C rejects automatic " + "aggregate initialization"); DECL_INITIAL (decl) = value; @@ -4271,18 +4585,22 @@ digest_init (tree type, tree init, bool strict_string, int require_constant) if (TREE_CODE (inside_init) == CONSTRUCTOR) { - tree link; + unsigned HOST_WIDE_INT ix; + tree value; + bool constant_p = true; /* 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; + FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (inside_init), ix, value) + if (!CONSTANT_CLASS_P (value)) + { + constant_p = false; + break; + } - if (link == NULL) - return build_vector (type, CONSTRUCTOR_ELTS (inside_init)); + if (constant_p) + return build_vector_from_ctor (type, + CONSTRUCTOR_ELTS (inside_init)); } } @@ -4299,22 +4617,22 @@ digest_init (tree type, tree init, bool strict_string, int require_constant) || (code == POINTER_TYPE && TREE_CODE (TREE_TYPE (inside_init)) == ARRAY_TYPE && comptypes (TREE_TYPE (TREE_TYPE (inside_init)), - TREE_TYPE (type))) - || (code == POINTER_TYPE - && TREE_CODE (TREE_TYPE (inside_init)) == FUNCTION_TYPE - && comptypes (TREE_TYPE (inside_init), TREE_TYPE (type))))) { if (code == POINTER_TYPE) { - inside_init = default_function_array_conversion (inside_init); - if (TREE_CODE (TREE_TYPE (inside_init)) == ARRAY_TYPE) { - error_init ("invalid use of non-lvalue array"); - return error_mark_node; + if (TREE_CODE (inside_init) == STRING_CST + || TREE_CODE (inside_init) == COMPOUND_LITERAL_EXPR) + inside_init = array_to_pointer_conversion (inside_init); + else + { + error_init ("invalid use of non-lvalue array"); + return error_mark_node; + } } - } + } if (code == VECTOR_TYPE) /* Although the types are compatible, we may require a @@ -4365,6 +4683,10 @@ digest_init (tree type, tree init, bool strict_string, int require_constant) inside_init = error_mark_node; } + /* Added to enable additional -Wmissing-format-attribute warnings. */ + if (TREE_CODE (TREE_TYPE (inside_init)) == POINTER_TYPE) + inside_init = convert_for_assignment (type, inside_init, ic_init, NULL_TREE, + NULL_TREE, 0); return inside_init; } @@ -4374,9 +4696,10 @@ digest_init (tree type, tree init, bool strict_string, int require_constant) || code == ENUMERAL_TYPE || code == BOOLEAN_TYPE || code == COMPLEX_TYPE || code == VECTOR_TYPE) { - /* Note that convert_for_assignment calls default_conversion - for arrays and functions. We must not call it in the - case where inside_init is a null pointer constant. */ + if (TREE_CODE (TREE_TYPE (init)) == ARRAY_TYPE + && (TREE_CODE (init) == STRING_CST + || TREE_CODE (init) == COMPOUND_LITERAL_EXPR)) + init = array_to_pointer_conversion (init); inside_init = convert_for_assignment (type, init, ic_init, NULL_TREE, NULL_TREE, 0); @@ -4443,7 +4766,7 @@ static tree constructor_bit_index; /* If we are saving up the elements rather than allocating them, this is the list of elements so far (in reverse order, most recent first). */ -static tree constructor_elements; +static VEC(constructor_elt,gc) *constructor_elements; /* 1 if constructor should be incrementally stored into a constructor chain, 0 if all the elements should be kept in AVL tree. */ @@ -4495,7 +4818,7 @@ static int constructor_designated; static int designator_depth; /* Nonzero if there were diagnosed errors in this designator list. */ -static int designator_errorneous; +static int designator_erroneous; /* This stack has a level for each implicit or explicit level of @@ -4514,7 +4837,7 @@ struct constructor_stack tree unfilled_index; tree unfilled_fields; tree bit_index; - tree elements; + VEC(constructor_elt,gc) *elements; struct init_node *pending_elts; int offset; int depth; @@ -4558,7 +4881,7 @@ struct initializer_stack tree decl; struct constructor_stack *constructor_stack; struct constructor_range_stack *constructor_range_stack; - tree elements; + VEC(constructor_elt,gc) *elements; struct spelling *spelling; struct spelling *spelling_base; int spelling_size; @@ -4575,7 +4898,7 @@ void start_init (tree decl, tree asmspec_tree ATTRIBUTE_UNUSED, int top_level) { const char *locus; - struct initializer_stack *p = xmalloc (sizeof (struct initializer_stack)); + struct initializer_stack *p = XNEW (struct initializer_stack); p->decl = constructor_decl; p->require_constant_value = require_constant_value; @@ -4709,7 +5032,7 @@ really_start_incremental_init (tree type) constructor_incremental = 1; constructor_designated = 0; designator_depth = 0; - designator_errorneous = 0; + designator_erroneous = 0; if (TREE_CODE (constructor_type) == RECORD_TYPE || TREE_CODE (constructor_type) == UNION_TYPE) @@ -4782,19 +5105,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 @@ -4845,7 +5176,7 @@ push_init_level (int implicit) p->range_stack = constructor_range_stack; constructor_range_stack = 0; designator_depth = 0; - designator_errorneous = 0; + designator_erroneous = 0; } /* Don't die if an entire brace-pair level is superfluous @@ -4885,7 +5216,7 @@ push_init_level (int implicit) constructor_constant = TREE_CONSTANT (value); constructor_simple = TREE_STATIC (value); constructor_elements = CONSTRUCTOR_ELTS (value); - if (constructor_elements + if (!VEC_empty (constructor_elt, constructor_elements) && (TREE_CODE (constructor_type) == RECORD_TYPE || TREE_CODE (constructor_type) == ARRAY_TYPE)) set_nonincremental_init (); @@ -5060,19 +5391,19 @@ pop_init_level (int implicit) { /* A nonincremental scalar initializer--just return the element, after verifying there is just one. */ - if (constructor_elements == 0) + if (VEC_empty (constructor_elt,constructor_elements)) { if (!constructor_erroneous) error_init ("empty scalar initializer"); ret.value = error_mark_node; } - else if (TREE_CHAIN (constructor_elements) != 0) + else if (VEC_length (constructor_elt,constructor_elements) != 1) { error_init ("extra elements in scalar initializer"); - ret.value = TREE_VALUE (constructor_elements); + ret.value = VEC_index (constructor_elt,constructor_elements,0)->value; } else - ret.value = TREE_VALUE (constructor_elements); + ret.value = VEC_index (constructor_elt,constructor_elements,0)->value; } else { @@ -5081,7 +5412,7 @@ pop_init_level (int implicit) else { ret.value = build_constructor (constructor_type, - nreverse (constructor_elements)); + constructor_elements); if (constructor_constant) TREE_CONSTANT (ret.value) = TREE_INVARIANT (ret.value) = 1; if (constructor_constant && constructor_simple) @@ -5111,15 +5442,8 @@ pop_init_level (int implicit) constructor_stack = p->next; free (p); - if (ret.value == 0) - { - if (constructor_stack == 0) - { - ret.value = error_mark_node; - return ret; - } - return ret; - } + if (ret.value == 0 && constructor_stack == 0) + ret.value = error_mark_node; return ret; } @@ -5139,7 +5463,7 @@ set_designator (int array) /* If there were errors in this designator list already, bail out silently. */ - if (designator_errorneous) + if (designator_erroneous) return 1; if (!designator_depth) @@ -5218,7 +5542,7 @@ set_init_index (tree first, tree last) if (set_designator (1)) return; - designator_errorneous = 1; + designator_erroneous = 1; if (!INTEGRAL_TYPE_P (TREE_TYPE (first)) || (last && !INTEGRAL_TYPE_P (TREE_TYPE (last)))) @@ -5264,7 +5588,7 @@ set_init_index (tree first, tree last) } designator_depth++; - designator_errorneous = 0; + designator_erroneous = 0; if (constructor_range_stack || last) push_range_stack (last); } @@ -5280,7 +5604,7 @@ set_init_label (tree fieldname) if (set_designator (0)) return; - designator_errorneous = 1; + designator_erroneous = 1; if (TREE_CODE (constructor_type) != RECORD_TYPE && TREE_CODE (constructor_type) != UNION_TYPE) @@ -5302,7 +5626,7 @@ set_init_label (tree fieldname) { constructor_fields = tail; designator_depth++; - designator_errorneous = 0; + designator_erroneous = 0; if (constructor_range_stack) push_range_stack (NULL_TREE); } @@ -5530,14 +5854,15 @@ add_pending_init (tree purpose, tree value) static void set_nonincremental_init (void) { - tree chain; + unsigned HOST_WIDE_INT ix; + tree index, value; if (TREE_CODE (constructor_type) != RECORD_TYPE && TREE_CODE (constructor_type) != ARRAY_TYPE) return; - for (chain = constructor_elements; chain; chain = TREE_CHAIN (chain)) - add_pending_init (TREE_PURPOSE (chain), TREE_VALUE (chain)); + FOR_EACH_CONSTRUCTOR_ELT (constructor_elements, ix, index, value) + add_pending_init (index, value); constructor_elements = 0; if (TREE_CODE (constructor_type) == RECORD_TYPE) { @@ -5689,9 +6014,10 @@ find_init_member (tree field) } else if (TREE_CODE (constructor_type) == UNION_TYPE) { - if (constructor_elements - && TREE_PURPOSE (constructor_elements) == field) - return TREE_VALUE (constructor_elements); + if (!VEC_empty (constructor_elt, constructor_elements) + && (VEC_last (constructor_elt, constructor_elements)->index + == field)) + return VEC_last (constructor_elt, constructor_elements)->value; } return 0; } @@ -5713,19 +6039,22 @@ static void output_init_element (tree value, bool strict_string, tree type, tree field, int pending) { + constructor_elt *celt; + if (type == error_mark_node || value == error_mark_node) { constructor_erroneous = 1; return; } - if (TREE_CODE (TREE_TYPE (value)) == FUNCTION_TYPE - || (TREE_CODE (TREE_TYPE (value)) == ARRAY_TYPE - && !(TREE_CODE (value) == STRING_CST - && TREE_CODE (type) == ARRAY_TYPE - && INTEGRAL_TYPE_P (TREE_TYPE (type))) - && !comptypes (TYPE_MAIN_VARIANT (TREE_TYPE (value)), - TYPE_MAIN_VARIANT (type)))) - value = default_conversion (value); + if (TREE_CODE (TREE_TYPE (value)) == ARRAY_TYPE + && (TREE_CODE (value) == STRING_CST + || TREE_CODE (value) == COMPOUND_LITERAL_EXPR) + && !(TREE_CODE (value) == STRING_CST + && TREE_CODE (type) == ARRAY_TYPE + && INTEGRAL_TYPE_P (TREE_TYPE (type))) + && !comptypes (TYPE_MAIN_VARIANT (TREE_TYPE (value)), + TYPE_MAIN_VARIANT (type))) + value = array_to_pointer_conversion (value); if (TREE_CODE (value) == COMPOUND_LITERAL_EXPR && require_constant_value && !flag_isoc99 && pending) @@ -5816,9 +6145,10 @@ output_init_element (tree value, bool strict_string, tree type, tree field, return; } else if (TREE_CODE (constructor_type) == UNION_TYPE - && constructor_elements) + && !VEC_empty (constructor_elt, constructor_elements)) { - if (TREE_SIDE_EFFECTS (TREE_VALUE (constructor_elements))) + if (TREE_SIDE_EFFECTS (VEC_last (constructor_elt, + constructor_elements)->value)) warning_init ("initialized field with side-effects overwritten"); /* We can have just one union field set. */ @@ -5828,10 +6158,9 @@ output_init_element (tree value, bool strict_string, tree type, tree field, /* Otherwise, output this element either to constructor_elements or to the assembler file. */ - if (field && TREE_CODE (field) == INTEGER_CST) - field = copy_node (field); - constructor_elements - = tree_cons (field, value, constructor_elements); + celt = VEC_safe_push (constructor_elt, gc, constructor_elements, NULL); + celt->index = field; + celt->value = value; /* Advance the variable that indicates sequential elements output. */ if (TREE_CODE (constructor_type) == ARRAY_TYPE) @@ -6017,7 +6346,7 @@ process_init_element (struct c_expr value) bool strict_string = value.original_code == STRING_CST; designator_depth = 0; - designator_errorneous = 0; + designator_erroneous = 0; /* Handle superfluous braces around string cst as in char x[] = {"foo"}; */ @@ -6183,10 +6512,11 @@ process_init_element (struct c_expr value) again on the assumption that this must be conditional on __STDC__ anyway (and we've already complained about the member-designator already). */ - if (warn_traditional && !in_system_header && !constructor_designated + if (!in_system_header && !constructor_designated && !(value.value && (integer_zerop (value.value) || real_zerop (value.value)))) - warning (0, "traditional C rejects initialization of unions"); + warning (OPT_Wtraditional, "traditional C rejects initialization " + "of unions"); /* Accept a string constant to initialize a subarray. */ if (value.value != 0 @@ -6420,6 +6750,14 @@ build_asm_expr (tree string, tree outputs, tree inputs, tree clobbers, if (!lvalue_or_else (output, lv_asm)) output = error_mark_node; + if (output != error_mark_node + && (TREE_READONLY (output) + || TYPE_READONLY (TREE_TYPE (output)) + || ((TREE_CODE (TREE_TYPE (output)) == RECORD_TYPE + || TREE_CODE (TREE_TYPE (output)) == UNION_TYPE) + && C_TYPE_FIELDS_READONLY (TREE_TYPE (output))))) + readonly_error (output, lv_asm); + constraint = TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (tail))); oconstraints[i] = constraint; @@ -6437,9 +6775,6 @@ build_asm_expr (tree string, tree outputs, tree inputs, tree clobbers, 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 (i = 0, tail = inputs; tail; ++i, tail = TREE_CHAIN (tail)) { tree input; @@ -6447,8 +6782,6 @@ build_asm_expr (tree string, tree outputs, tree inputs, tree clobbers, 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)) { @@ -6471,12 +6804,10 @@ build_asm_expr (tree string, tree outputs, tree inputs, tree clobbers, args = build_stmt (ASM_EXPR, string, outputs, inputs, clobbers); - /* Simple asm statements are treated as volatile. */ - if (simple) - { - ASM_VOLATILE_P (args) = 1; - ASM_INPUT_P (args) = 1; - } + /* asm statements without outputs, including simple ones, are treated + as volatile. */ + ASM_INPUT_P (args) = simple; + ASM_VOLATILE_P (args) = (noutputs == 0); return args; } @@ -6546,7 +6877,8 @@ c_finish_goto_ptr (tree expr) tree c_finish_return (tree retval) { - tree valtype = TREE_TYPE (TREE_TYPE (current_function_decl)); + tree valtype = TREE_TYPE (TREE_TYPE (current_function_decl)), ret_stmt; + bool no_warning = false; if (TREE_THIS_VOLATILE (current_function_decl)) warning (0, "function declared % has a % statement"); @@ -6556,8 +6888,11 @@ c_finish_return (tree retval) current_function_returns_null = 1; if ((warn_return_type || flag_isoc99) && valtype != 0 && TREE_CODE (valtype) != VOID_TYPE) - pedwarn_c99 ("% with no value, in " - "function returning non-void"); + { + pedwarn_c99 ("% with no value, in " + "function returning non-void"); + no_warning = true; + } } else if (valtype == 0 || TREE_CODE (valtype) == VOID_TYPE) { @@ -6633,7 +6968,9 @@ c_finish_return (tree retval) retval = build2 (MODIFY_EXPR, TREE_TYPE (res), res, t); } - return add_stmt (build_stmt (RETURN_EXPR, retval)); + ret_stmt = build_stmt (RETURN_EXPR, retval); + TREE_NO_WARNING (ret_stmt) |= no_warning; + return add_stmt (ret_stmt); } struct c_switch { @@ -6699,11 +7036,11 @@ c_start_case (tree exp) { type = TYPE_MAIN_VARIANT (TREE_TYPE (exp)); - if (warn_traditional && !in_system_header + if (!in_system_header && (type == long_integer_type_node || type == long_unsigned_type_node)) - warning (0, "% switch expression not converted to " - "% in ISO C"); + warning (OPT_Wtraditional, "% switch expression not " + "converted to % in ISO C"); exp = default_conversion (exp); type = TREE_TYPE (exp); @@ -6837,31 +7174,14 @@ c_finish_if_stmt (location_t if_locus, tree cond, tree then_block, found: if (COND_EXPR_ELSE (inner_if)) - warning (0, "%Hsuggest explicit braces to avoid ambiguous %", + warning (OPT_Wparentheses, + "%Hsuggest explicit braces to avoid ambiguous %", &if_locus); } - /* Diagnose ";" via the special empty statement node that we create. */ - if (extra_warnings) - { - if (TREE_CODE (then_block) == NOP_EXPR && !TREE_TYPE (then_block)) - { - if (!else_block) - warning (0, "%Hempty body in an if-statement", - EXPR_LOCUS (then_block)); - then_block = alloc_stmt_list (); - } - if (else_block - && TREE_CODE (else_block) == NOP_EXPR - && !TREE_TYPE (else_block)) - { - warning (0, "%Hempty body in an else-statement", - EXPR_LOCUS (else_block)); - else_block = alloc_stmt_list (); - } - } + empty_body_warning (then_block, else_block); - stmt = build3 (COND_EXPR, NULL_TREE, cond, then_block, else_block); + stmt = build3 (COND_EXPR, void_type_node, cond, then_block, else_block); SET_EXPR_LOCATION (stmt, if_locus); add_stmt (stmt); } @@ -6916,8 +7236,7 @@ c_finish_loop (location_t start_locus, tree cond, tree incr, tree body, } t = build_and_jump (&blab); - exit = build3 (COND_EXPR, void_type_node, cond, exit, t); - exit = fold (exit); + exit = fold_build3 (COND_EXPR, void_type_node, cond, exit, t); if (cond_is_first) SET_EXPR_LOCATION (exit, start_locus); else @@ -6961,13 +7280,24 @@ c_finish_bc_stmt (tree *label_p, bool is_break) if (!skip) *label_p = label = create_artificial_label (); } - else if (TREE_CODE (label) != LABEL_DECL) + else if (TREE_CODE (label) == LABEL_DECL) + ; + else switch (TREE_INT_CST_LOW (label)) { + case 0: if (is_break) error ("break statement not within loop or switch"); else error ("continue statement not within a loop"); return NULL_TREE; + + case 1: + gcc_assert (is_break); + error ("break statement used with OpenMP for loop"); + return NULL_TREE; + + default: + gcc_unreachable (); } if (skip) @@ -7002,13 +7332,6 @@ c_process_expr_stmt (tree expr) if (!expr) return NULL_TREE; - /* Do default conversion if safe and possibly important, - in case within ({...}). */ - if ((TREE_CODE (TREE_TYPE (expr)) == ARRAY_TYPE - && (flag_isoc99 || lvalue_p (expr))) - || TREE_CODE (TREE_TYPE (expr)) == FUNCTION_TYPE) - expr = default_conversion (expr); - if (warn_sequence_point) verify_sequence_points (expr); @@ -7163,7 +7486,13 @@ c_finish_stmt_expr (tree body) if (last == error_mark_node || (last == BIND_EXPR_BODY (body) && BIND_EXPR_VARS (body) == NULL)) - return last; + { + /* Do not warn if the return value of a statement expression is + unused. */ + if (EXPR_P (last)) + TREE_NO_WARNING (last) = 1; + return last; + } /* Extract the type of said expression. */ type = TREE_TYPE (last); @@ -7345,6 +7674,7 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1, tree type0, type1; enum tree_code code0, code1; tree op0, op1; + const char *invalid_op_diag; /* Expression code to give to the expression when it is built. Normally this is CODE, which is what the caller asked for, @@ -7388,6 +7718,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); @@ -7417,6 +7750,15 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1, if (code0 == ERROR_MARK || code1 == ERROR_MARK) return error_mark_node; + if ((invalid_op_diag + = targetm.invalid_binary_op (code, type0, type1))) + { + error (invalid_op_diag); + return error_mark_node; + } + + objc_ok = objc_compare_types (type0, type1, -3, NULL_TREE); + switch (code) { case PLUS_EXPR: @@ -7433,7 +7775,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) @@ -7453,20 +7795,22 @@ 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 (0, "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) && (code1 == INTEGER_TYPE || code1 == REAL_TYPE || code1 == COMPLEX_TYPE || code1 == VECTOR_TYPE)) { + enum tree_code tcode0 = code0, tcode1 = code1; + if (code0 == COMPLEX_TYPE || code0 == VECTOR_TYPE) - code0 = TREE_CODE (TREE_TYPE (TREE_TYPE (op0))); + tcode0 = TREE_CODE (TREE_TYPE (TREE_TYPE (op0))); if (code1 == COMPLEX_TYPE || code1 == VECTOR_TYPE) - code1 = TREE_CODE (TREE_TYPE (TREE_TYPE (op1))); + tcode1 = TREE_CODE (TREE_TYPE (TREE_TYPE (op1))); - if (!(code0 == INTEGER_TYPE && code1 == INTEGER_TYPE)) + if (!(tcode0 == INTEGER_TYPE && tcode1 == INTEGER_TYPE)) resultcode = RDIV_EXPR; else /* Although it would be tempting to shorten always here, that @@ -7492,8 +7836,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 (0, "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) { @@ -7585,8 +7929,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 (0, "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; @@ -7602,36 +7947,50 @@ 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)) { /* op0 != orig_op0 detects the case of something whose value is 0 but which isn't a valid null ptr const. */ - if (pedantic && (!integer_zerop (op0) || op0 != orig_op0) + if (pedantic && !null_pointer_constant_p (orig_op0) && TREE_CODE (tt1) == FUNCTION_TYPE) pedwarn ("ISO C forbids comparison of %" " with function pointer"); } else if (VOID_TYPE_P (tt1)) { - if (pedantic && (!integer_zerop (op1) || op1 != orig_op1) + if (pedantic && !null_pointer_constant_p (orig_op1) && TREE_CODE (tt0) == FUNCTION_TYPE) 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; } - else if (code0 == POINTER_TYPE && TREE_CODE (op1) == INTEGER_CST - && integer_zerop (op1)) - result_type = type0; - else if (code1 == POINTER_TYPE && TREE_CODE (op0) == INTEGER_CST - && integer_zerop (op0)) - result_type = type1; + else if (code0 == POINTER_TYPE && null_pointer_constant_p (orig_op1)) + { + if (TREE_CODE (op0) == ADDR_EXPR + && DECL_P (TREE_OPERAND (op0, 0)) + && !DECL_WEAK (TREE_OPERAND (op0, 0))) + warning (OPT_Walways_true, "the address of %qD will never be NULL", + TREE_OPERAND (op0, 0)); + result_type = type0; + } + else if (code1 == POINTER_TYPE && null_pointer_constant_p (orig_op0)) + { + if (TREE_CODE (op1) == ADDR_EXPR + && DECL_P (TREE_OPERAND (op1, 0)) + && !DECL_WEAK (TREE_OPERAND (op1, 0))) + warning (OPT_Walways_true, "the address of %qD will never be NULL", + TREE_OPERAND (op1, 0)); + result_type = type1; + } else if (code0 == POINTER_TYPE && code1 == INTEGER_TYPE) { result_type = type0; @@ -7654,7 +8013,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)) @@ -7670,15 +8029,13 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1, pedwarn ("comparison of distinct pointer types lacks a cast"); } } - else if (code0 == POINTER_TYPE && TREE_CODE (op1) == INTEGER_CST - && integer_zerop (op1)) + else if (code0 == POINTER_TYPE && null_pointer_constant_p (orig_op1)) { result_type = type0; if (pedantic || extra_warnings) pedwarn ("ordered comparison of pointer with integer zero"); } - else if (code1 == POINTER_TYPE && TREE_CODE (op0) == INTEGER_CST - && integer_zerop (op0)) + else if (code1 == POINTER_TYPE && null_pointer_constant_p (orig_op0)) { result_type = type1; if (pedantic) @@ -7703,6 +8060,15 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1, if (code0 == ERROR_MARK || code1 == ERROR_MARK) return error_mark_node; + if (code0 == VECTOR_TYPE && code1 == VECTOR_TYPE + && (!tree_int_cst_equal (TYPE_SIZE (type0), TYPE_SIZE (type1)) + || !same_scalar_type_ignoring_signedness (TREE_TYPE (type0), + TREE_TYPE (type1)))) + { + binary_op_error (code); + return error_mark_node; + } + if ((code0 == INTEGER_TYPE || code0 == REAL_TYPE || code0 == COMPLEX_TYPE || code0 == VECTOR_TYPE) && @@ -7728,12 +8094,35 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1, if (shorten && none_complex) { int unsigned0, unsigned1; - tree arg0 = get_narrower (op0, &unsigned0); - tree arg1 = get_narrower (op1, &unsigned1); - /* UNS is 1 if the operation to be done is an unsigned one. */ - int uns = TYPE_UNSIGNED (result_type); + tree arg0, arg1; + int uns; tree type; + /* Cast OP0 and OP1 to RESULT_TYPE. Doing so prevents + excessive narrowing when we call get_narrower below. For + example, suppose that OP0 is of unsigned int extended + from signed char and that RESULT_TYPE is long long int. + If we explicitly cast OP0 to RESULT_TYPE, OP0 would look + like + + (long long int) (unsigned int) signed_char + + which get_narrower would narrow down to + + (unsigned int) signed char + + If we do not cast OP0 first, get_narrower would return + signed_char, which is inconsistent with the case of the + explicit cast. */ + op0 = convert (result_type, op0); + op1 = convert (result_type, op1); + + arg0 = get_narrower (op0, &unsigned0); + arg1 = get_narrower (op1, &unsigned1); + + /* UNS is 1 if the operation to be done is an unsigned one. */ + uns = TYPE_UNSIGNED (result_type); + final_type = result_type; /* Handle the case that OP0 (or OP1) does not *contain* a conversion @@ -7770,7 +8159,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, c_common_type (TREE_TYPE (arg0), TREE_TYPE (arg1))); + (unsigned0, common_type (TREE_TYPE (arg0), TREE_TYPE (arg1))); else if (TREE_CODE (arg0) == INTEGER_CST && (unsigned1 || !uns) && (TYPE_PRECISION (TREE_TYPE (arg1)) @@ -7992,11 +8381,12 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1, build_type = result_type; { - tree result = build2 (resultcode, build_type, op0, op1); - /* Treat expressions in initializers specially as they can't trap. */ - result = require_constant_value ? fold_initializer (result) - : fold (result); + tree result = require_constant_value ? fold_build2_initializer (resultcode, + build_type, + op0, op1) + : fold_build2 (resultcode, build_type, + op0, op1); if (final_type != 0) result = convert (final_type, result); @@ -8006,12 +8396,11 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1, /* Convert EXPR to be a truth-value, validating its type for this - purpose. Passes EXPR to default_function_array_conversion. */ + purpose. */ tree c_objc_common_truthvalue_conversion (tree expr) { - expr = default_function_array_conversion (expr); switch (TREE_CODE (TREE_TYPE (expr))) { case ARRAY_TYPE: @@ -8026,6 +8415,9 @@ c_objc_common_truthvalue_conversion (tree expr) error ("used union type value where scalar is required"); return error_mark_node; + case FUNCTION_TYPE: + gcc_unreachable (); + default: break; } @@ -8034,3 +8426,269 @@ c_objc_common_truthvalue_conversion (tree expr) leaving those to give errors later? */ return c_common_truthvalue_conversion (expr); } + + +/* Convert EXPR to a contained DECL, updating *TC, *TI and *SE as + required. */ + +tree +c_expr_to_decl (tree expr, bool *tc ATTRIBUTE_UNUSED, + bool *ti ATTRIBUTE_UNUSED, bool *se) +{ + if (TREE_CODE (expr) == COMPOUND_LITERAL_EXPR) + { + tree decl = COMPOUND_LITERAL_EXPR_DECL (expr); + /* Executing a compound literal inside a function reinitializes + it. */ + if (!TREE_STATIC (decl)) + *se = true; + return decl; + } + else + return expr; +} + + +/* Like c_begin_compound_stmt, except force the retention of the BLOCK. */ + +tree +c_begin_omp_parallel (void) +{ + tree block; + + keep_next_level (); + block = c_begin_compound_stmt (true); + + return block; +} + +tree +c_finish_omp_parallel (tree clauses, tree block) +{ + tree stmt; + + block = c_end_compound_stmt (block, true); + + stmt = make_node (OMP_PARALLEL); + TREE_TYPE (stmt) = void_type_node; + OMP_PARALLEL_CLAUSES (stmt) = clauses; + OMP_PARALLEL_BODY (stmt) = block; + + return add_stmt (stmt); +} + +/* For all elements of CLAUSES, validate them vs OpenMP constraints. + Remove any elements from the list that are invalid. */ + +tree +c_finish_omp_clauses (tree clauses) +{ + bitmap_head generic_head, firstprivate_head, lastprivate_head; + tree c, t, *pc = &clauses; + const char *name; + + bitmap_obstack_initialize (NULL); + bitmap_initialize (&generic_head, &bitmap_default_obstack); + bitmap_initialize (&firstprivate_head, &bitmap_default_obstack); + bitmap_initialize (&lastprivate_head, &bitmap_default_obstack); + + for (pc = &clauses, c = clauses; c ; c = *pc) + { + bool remove = false; + bool need_complete = false; + bool need_implicitly_determined = false; + + switch (OMP_CLAUSE_CODE (c)) + { + case OMP_CLAUSE_SHARED: + name = "shared"; + need_implicitly_determined = true; + goto check_dup_generic; + + case OMP_CLAUSE_PRIVATE: + name = "private"; + need_complete = true; + need_implicitly_determined = true; + goto check_dup_generic; + + case OMP_CLAUSE_REDUCTION: + name = "reduction"; + need_implicitly_determined = true; + t = OMP_CLAUSE_DECL (c); + if (AGGREGATE_TYPE_P (TREE_TYPE (t)) + || POINTER_TYPE_P (TREE_TYPE (t))) + { + error ("%qE has invalid type for %", t); + remove = true; + } + else if (FLOAT_TYPE_P (TREE_TYPE (t))) + { + enum tree_code r_code = OMP_CLAUSE_REDUCTION_CODE (c); + const char *r_name = NULL; + + switch (r_code) + { + case PLUS_EXPR: + case MULT_EXPR: + case MINUS_EXPR: + break; + case BIT_AND_EXPR: + r_name = "&"; + break; + case BIT_XOR_EXPR: + r_name = "^"; + break; + case BIT_IOR_EXPR: + r_name = "|"; + break; + case TRUTH_ANDIF_EXPR: + r_name = "&&"; + break; + case TRUTH_ORIF_EXPR: + r_name = "||"; + break; + default: + gcc_unreachable (); + } + if (r_name) + { + error ("%qE has invalid type for %", + t, r_name); + remove = true; + } + } + goto check_dup_generic; + + case OMP_CLAUSE_COPYPRIVATE: + name = "copyprivate"; + goto check_dup_generic; + + case OMP_CLAUSE_COPYIN: + name = "copyin"; + t = OMP_CLAUSE_DECL (c); + if (TREE_CODE (t) != VAR_DECL || !DECL_THREAD_LOCAL_P (t)) + { + error ("%qE must be % for %", t); + remove = true; + } + goto check_dup_generic; + + check_dup_generic: + t = OMP_CLAUSE_DECL (c); + if (TREE_CODE (t) != VAR_DECL && TREE_CODE (t) != PARM_DECL) + { + error ("%qE is not a variable in clause %qs", t, name); + remove = true; + } + else if (bitmap_bit_p (&generic_head, DECL_UID (t)) + || bitmap_bit_p (&firstprivate_head, DECL_UID (t)) + || bitmap_bit_p (&lastprivate_head, DECL_UID (t))) + { + error ("%qE appears more than once in data clauses", t); + remove = true; + } + else + bitmap_set_bit (&generic_head, DECL_UID (t)); + break; + + case OMP_CLAUSE_FIRSTPRIVATE: + name = "firstprivate"; + t = OMP_CLAUSE_DECL (c); + need_complete = true; + need_implicitly_determined = true; + if (TREE_CODE (t) != VAR_DECL && TREE_CODE (t) != PARM_DECL) + { + error ("%qE is not a variable in clause %", t); + remove = true; + } + else if (bitmap_bit_p (&generic_head, DECL_UID (t)) + || bitmap_bit_p (&firstprivate_head, DECL_UID (t))) + { + error ("%qE appears more than once in data clauses", t); + remove = true; + } + else + bitmap_set_bit (&firstprivate_head, DECL_UID (t)); + break; + + case OMP_CLAUSE_LASTPRIVATE: + name = "lastprivate"; + t = OMP_CLAUSE_DECL (c); + need_complete = true; + need_implicitly_determined = true; + if (TREE_CODE (t) != VAR_DECL && TREE_CODE (t) != PARM_DECL) + { + error ("%qE is not a variable in clause %", t); + remove = true; + } + else if (bitmap_bit_p (&generic_head, DECL_UID (t)) + || bitmap_bit_p (&lastprivate_head, DECL_UID (t))) + { + error ("%qE appears more than once in data clauses", t); + remove = true; + } + else + bitmap_set_bit (&lastprivate_head, DECL_UID (t)); + break; + + case OMP_CLAUSE_IF: + case OMP_CLAUSE_NUM_THREADS: + case OMP_CLAUSE_SCHEDULE: + case OMP_CLAUSE_NOWAIT: + case OMP_CLAUSE_ORDERED: + case OMP_CLAUSE_DEFAULT: + pc = &OMP_CLAUSE_CHAIN (c); + continue; + + default: + gcc_unreachable (); + } + + if (!remove) + { + t = OMP_CLAUSE_DECL (c); + + if (need_complete) + { + t = require_complete_type (t); + if (t == error_mark_node) + remove = true; + } + + if (need_implicitly_determined) + { + const char *share_name = NULL; + + if (TREE_CODE (t) == VAR_DECL && DECL_THREAD_LOCAL_P (t)) + share_name = "threadprivate"; + else switch (c_omp_predetermined_sharing (t)) + { + case OMP_CLAUSE_DEFAULT_UNSPECIFIED: + break; + case OMP_CLAUSE_DEFAULT_SHARED: + share_name = "shared"; + break; + case OMP_CLAUSE_DEFAULT_PRIVATE: + share_name = "private"; + break; + default: + gcc_unreachable (); + } + if (share_name) + { + error ("%qE is predetermined %qs for %qs", + t, share_name, name); + remove = true; + } + } + } + + if (remove) + *pc = OMP_CLAUSE_CHAIN (c); + else + pc = &OMP_CLAUSE_CHAIN (c); + } + + bitmap_obstack_release (NULL); + return clauses; +}