X-Git-Url: http://git.sourceforge.jp/view?p=pf3gnuchains%2Fgcc-fork.git;a=blobdiff_plain;f=gcc%2Fc-typeck.c;h=955bfd959f81c3f8993e577e52fc02432dd3c7fa;hp=25a280a6d54efd8f8d9a15a170b3cb14773409ce;hb=d6f5f982f614172cc4d23c8372a4eb4b8266d18b;hpb=380c66974cee2bb4a5281c8c11f3632bb21118e5 diff --git a/gcc/c-typeck.c b/gcc/c-typeck.c index 25a280a6d54..955bfd959f8 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); 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); @@ -89,7 +90,6 @@ static tree convert_for_assignment (tree, tree, enum impl_conv, tree, tree, static tree valid_compound_expr_initializer (tree, tree); static void push_string (const char *); static void push_member_name (tree); -static void push_array_bounds (int); static int spelling_length (void); static char *print_spelling (char *); static void warning_init (const char *); @@ -106,7 +106,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.) */ @@ -205,8 +236,8 @@ c_type_promotes_to (tree type) { /* Preserve unsignedness if not really getting any wider. */ if (TYPE_UNSIGNED (type) - && (TYPE_PRECISION (type) == TYPE_PRECISION (integer_type_node))) - return unsigned_type_node; + && (TYPE_PRECISION (type) == TYPE_PRECISION (integer_type_node))) + return unsigned_type_node; return integer_type_node; } @@ -222,6 +253,17 @@ qualify_type (tree type, tree like) return c_build_qualified_type (type, TYPE_QUALS (type) | TYPE_QUALS (like)); } + +/* Return true iff the given tree T is a variable length array. */ + +bool +c_vla_type_p (tree t) +{ + if (TREE_CODE (t) == ARRAY_TYPE + && C_TYPE_VARIABLE_SIZE (t)) + return true; + return false; +} /* Return the composite type of two compatible types. @@ -282,21 +324,39 @@ 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)); + d1_variable = d1_variable || (d1_zero && c_vla_type_p (t1)); + d2_variable = d2_variable || (d2_zero && c_vla_type_p (t2)); + /* 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)) return build_type_attribute_variant (t1, attributes); if (elt == TREE_TYPE (t2) && !TYPE_DOMAIN (t2) && !TYPE_DOMAIN (t1)) return build_type_attribute_variant (t2, attributes); - + /* Merge the element types, and have a size if either arg has one. We may have qualifiers on the element types. To set up TYPE_MAIN_VARIANT correctly, we need to form the @@ -305,11 +365,29 @@ 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); } + case ENUMERAL_TYPE: + case RECORD_TYPE: + case UNION_TYPE: + if (attributes != NULL) + { + /* Try harder not to create a new aggregate type. */ + if (attribute_list_equal (TYPE_ATTRIBUTES (t1), attributes)) + return t1; + if (attribute_list_equal (TYPE_ATTRIBUTES (t2), attributes)) + return t2; + } + return build_type_attribute_variant (t1, attributes); + case FUNCTION_TYPE: /* Function types: prefer the one that specified arg types. If both do, merge the arg types. Also merge the return types. */ @@ -465,7 +543,7 @@ common_pointer_type (tree t1, tree t2) return t1; gcc_assert (TREE_CODE (t1) == POINTER_TYPE - && TREE_CODE (t2) == POINTER_TYPE); + && TREE_CODE (t2) == POINTER_TYPE); /* Merge the attributes. */ attributes = targetm.merge_type_attributes (t1, t2); @@ -531,6 +609,29 @@ c_common_type (tree t1, tree t2) gcc_assert (code2 == VECTOR_TYPE || code2 == COMPLEX_TYPE || code2 == REAL_TYPE || code2 == INTEGER_TYPE); + /* When one operand is a decimal float type, the other operand cannot be + a generic float type or a complex type. We also disallow vector types + here. */ + if ((DECIMAL_FLOAT_TYPE_P (t1) || DECIMAL_FLOAT_TYPE_P (t2)) + && !(DECIMAL_FLOAT_TYPE_P (t1) && DECIMAL_FLOAT_TYPE_P (t2))) + { + if (code1 == VECTOR_TYPE || code2 == VECTOR_TYPE) + { + error ("can%'t mix operands of decimal float and vector types"); + return error_mark_node; + } + if (code1 == COMPLEX_TYPE || code2 == COMPLEX_TYPE) + { + error ("can%'t mix operands of decimal float and complex types"); + return error_mark_node; + } + if (code1 == REAL_TYPE && code2 == REAL_TYPE) + { + error ("can%'t mix operands of decimal float and other float types"); + return error_mark_node; + } + } + /* If one type is a vector type, return that type. (How the usual arithmetic conversions apply to the vector types extension is not precisely specified.) */ @@ -565,6 +666,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)) @@ -586,7 +703,7 @@ c_common_type (tree t1, tree t2) if (TYPE_UNSIGNED (t1) || TYPE_UNSIGNED (t2)) return long_long_unsigned_type_node; else - return long_long_integer_type_node; + return long_long_integer_type_node; } if (TYPE_MAIN_VARIANT (t1) == long_unsigned_type_node @@ -617,7 +734,8 @@ c_common_type (tree t1, tree t2) return t2; } -/* Wrapper around c_common_type that is used by c-common.c. ENUMERAL_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. */ @@ -642,7 +760,7 @@ common_type (tree t1, tree t2) 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. */ @@ -650,6 +768,23 @@ 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; @@ -716,7 +851,7 @@ comptypes (tree type1, tree type2) || 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: @@ -733,7 +868,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. */ @@ -749,6 +884,8 @@ comptypes (tree type1, tree type2) d2_variable = (!d2_zero && (TREE_CODE (TYPE_MIN_VALUE (d2)) != INTEGER_CST || TREE_CODE (TYPE_MAX_VALUE (d2)) != INTEGER_CST)); + d1_variable = d1_variable || (d1_zero && c_vla_type_p (t1)); + d2_variable = d2_variable || (d2_zero && c_vla_type_p (t2)); if (d1_variable || d2_variable) break; @@ -759,19 +896,30 @@ comptypes (tree type1, tree type2) || !tree_int_cst_equal (TYPE_MAX_VALUE (d1), TYPE_MAX_VALUE (d2))) val = 0; - break; + break; } 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); + { + tree a1 = TYPE_ATTRIBUTES (t1); + tree a2 = TYPE_ATTRIBUTES (t2); + + if (! attribute_list_contained (a1, a2) + && ! attribute_list_contained (a2, a1)) + break; + + 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: @@ -840,21 +988,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 @@ -896,73 +1071,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); - /* 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; + if (tv1 == tv2) + { + 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; - } + 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) + { + tu->val = 0; + return 0; + } + } - if (tv1 == NULL_TREE && tv2 == NULL_TREE) - return 1; - if (tv1 == NULL_TREE || tv2 == NULL_TREE) - return 0; + if (tv1 == NULL_TREE && tv2 == NULL_TREE) + { + return 1; + } + if (tv1 == NULL_TREE || tv2 == NULL_TREE) + { + 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; @@ -974,21 +1199,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; @@ -998,7 +1221,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) @@ -1009,10 +1232,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: @@ -1049,7 +1273,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; @@ -1065,7 +1289,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; @@ -1130,7 +1354,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. */ @@ -1149,7 +1373,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) @@ -1170,7 +1394,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) @@ -1260,103 +1484,117 @@ decl_constant_value_for_broken_optimization (tree decl) return ret; } - -/* Perform the default conversion of arrays and functions to pointers. - Return the result of converting EXP. For any other expression, just - return EXP. */ - +/* 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; } @@ -1410,8 +1648,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 @@ -1421,8 +1658,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) @@ -1590,11 +1829,17 @@ build_component_ref (tree datum, tree component) do { tree subdatum = TREE_VALUE (field); + int quals; + tree subtype; if (TREE_TYPE (subdatum) == error_mark_node) return error_mark_node; - ref = build3 (COMPONENT_REF, TREE_TYPE (subdatum), datum, subdatum, + quals = TYPE_QUALS (strip_array_types (TREE_TYPE (subdatum))); + quals |= TYPE_QUALS (TREE_TYPE (datum)); + subtype = c_build_qualified_type (TREE_TYPE (subdatum), quals); + + ref = build3 (COMPONENT_REF, subtype, datum, subdatum, NULL_TREE); if (TREE_READONLY (datum) || TREE_READONLY (subdatum)) TREE_READONLY (ref) = 1; @@ -1714,16 +1959,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); @@ -1773,7 +2012,7 @@ build_array_ref (tree array, tree index) type = TYPE_MAIN_VARIANT (type); rval = build4 (ARRAY_REF, type, array, index, NULL_TREE, NULL_TREE); /* Array ref is const/volatile if the array elements are - or if the array is. */ + or if the array is. */ TREE_READONLY (rval) |= (TYPE_READONLY (TREE_TYPE (TREE_TYPE (array))) | TREE_READONLY (array)); @@ -1854,6 +2093,7 @@ build_external_ref (tree id, int fun, location_t loc) if (TREE_CODE (ref) == CONST_DECL) { + used_types_insert (TREE_TYPE (ref)); ref = DECL_INITIAL (ref); TREE_CONSTANT (ref) = 1; TREE_INVARIANT (ref) = 1; @@ -1869,6 +2109,17 @@ build_external_ref (tree id, int fun, location_t loc) if (context != 0 && context != current_function_decl) DECL_NONLOCAL (ref) = 1; } + /* C99 6.7.4p3: An inline definition of a function with external + linkage ... shall not contain a reference to an identifier with + internal linkage. */ + else if (current_function_decl != 0 + && DECL_DECLARED_INLINE_P (current_function_decl) + && DECL_EXTERNAL (current_function_decl) + && VAR_OR_FUNCTION_DECL_P (ref) + && (TREE_CODE (ref) != VAR_DECL || TREE_STATIC (ref)) + && ! TREE_PUBLIC (ref)) + pedwarn ("%H%qD is static but used in inline function %qD " + "which is not static", &loc, ref, current_function_decl); return ref; } @@ -1942,6 +2193,11 @@ c_expr_sizeof_expr (struct c_expr expr) { ret.value = c_sizeof (TREE_TYPE (expr.value)); ret.original_code = ERROR_MARK; + if (c_vla_type_p (TREE_TYPE (expr.value))) + { + /* sizeof is evaluated when given a vla (C99 6.5.3.4p2). */ + ret.value = build2 (COMPOUND_EXPR, TREE_TYPE (ret.value), expr.value, ret.value); + } pop_maybe_used (C_TYPE_VARIABLE_SIZE (TREE_TYPE (expr.value))); } return ret; @@ -1958,7 +2214,8 @@ c_expr_sizeof_type (struct c_type_name *t) type = groktypename (t); ret.value = c_sizeof (type); ret.original_code = ERROR_MARK; - pop_maybe_used (C_TYPE_VARIABLE_SIZE (type)); + pop_maybe_used (type != error_mark_node + ? C_TYPE_VARIABLE_SIZE (type) : false); return ret; } @@ -1990,18 +2247,10 @@ build_function_call (tree function, tree params) 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. */ @@ -2030,7 +2279,8 @@ build_function_call (tree function, tree params) 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. */ - if (TREE_CODE (function) == NOP_EXPR + 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))) @@ -2056,10 +2306,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); } @@ -2076,15 +2325,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 @@ -2092,7 +2339,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; @@ -2163,8 +2411,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) @@ -2181,7 +2427,7 @@ convert_arguments (tree typelist, tree values, tree function, tree fundecl) { /* Optionally warn about conversions that differ from the default conversions. */ - if (warn_conversion || warn_traditional) + if (warn_traditional_conversion || warn_traditional) { unsigned int formal_prec = TYPE_PRECISION (type); @@ -2223,15 +2469,42 @@ 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 - -Wconversion, not with -Wtraditional. */ - else if (warn_conversion && INTEGRAL_TYPE_P (type) + -Wtraditional-conversion, not with -Wtraditional. */ + else if (warn_traditional_conversion && INTEGRAL_TYPE_P (type) && INTEGRAL_TYPE_P (TREE_TYPE (val))) { tree would_have_been = default_conversion (val); @@ -2244,8 +2517,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_Wtraditional_conversion, "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 @@ -2266,11 +2540,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_Wtraditional_conversion, "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_Wtraditional_conversion, "passing argument %d of %qE " + "as signed due to prototype", argnum, rname); } } @@ -2286,15 +2561,16 @@ convert_arguments (tree typelist, tree values, tree function, tree fundecl) result = tree_cons (NULL_TREE, parmval, result); } else if (TREE_CODE (TREE_TYPE (val)) == REAL_TYPE - && (TYPE_PRECISION (TREE_TYPE (val)) - < TYPE_PRECISION (double_type_node))) + && (TYPE_PRECISION (TREE_TYPE (val)) + < 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 = - targetm.calls.invalid_arg_for_unprototyped_fn (typelist, fundecl, val))) + else if ((invalid_func_diag = + targetm.calls.invalid_arg_for_unprototyped_fn (typelist, fundecl, val))) { error (invalid_func_diag); - return error_mark_node; + return error_mark_node; } else /* Convert `short' and `char' to full-size `int'. */ @@ -2353,67 +2629,22 @@ parser_build_binary_op (enum tree_code code, struct c_expr arg1, /* Check for cases such as x+y< output")), TREE_OPERAND (arg, 1)); } else if (TREE_CODE (arg) == VAR_DECL) 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_("decrement of read-only variable %qD"), + G_("read-only variable %qD used as % output")), arg); else error (READONLY_MSG (G_("assignment of read-only location"), G_("increment of read-only location"), - G_("decrement of read-only location"))); + G_("decrement of read-only location"), + G_("read-only location used as % output"))); } @@ -2991,9 +3246,9 @@ build_conditional_expr (tree ifexp, tree op1, tree op2) result_type = TYPE_MAIN_VARIANT (type1); } else if ((code1 == INTEGER_TYPE || code1 == REAL_TYPE - || code1 == COMPLEX_TYPE) - && (code2 == INTEGER_TYPE || code2 == REAL_TYPE - || code2 == COMPLEX_TYPE)) + || code1 == COMPLEX_TYPE) + && (code2 == INTEGER_TYPE || code2 == REAL_TYPE + || code2 == COMPLEX_TYPE)) { result_type = c_common_type (type1, type2); @@ -3035,11 +3290,9 @@ build_conditional_expr (tree ifexp, tree op1, tree op2) { 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))) { @@ -3065,7 +3318,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 { @@ -3075,7 +3328,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 { @@ -3115,22 +3368,21 @@ 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 + 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) { if (VOID_TYPE_P (TREE_TYPE (expr1)) - && TREE_CODE (expr1) == CONVERT_EXPR) + && (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)) == 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"); @@ -3144,6 +3396,9 @@ build_compound_expr (tree expr1, tree expr2) else if (warn_unused_value) warn_if_unused_value (expr1, input_location); + if (expr2 == error_mark_node) + return error_mark_node; + return build2 (COMPOUND_EXPR, TREE_TYPE (expr2), expr1, expr2); } @@ -3189,7 +3444,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)), @@ -3203,8 +3457,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); @@ -3217,14 +3470,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. */ @@ -3270,7 +3518,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 @@ -3281,52 +3529,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 @@ -3343,8 +3573,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; @@ -3353,17 +3582,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)); } } @@ -3390,7 +3621,6 @@ c_cast_expr (struct c_type_name *type_name, tree expr) return build_c_cast (type, expr); } - /* Build an assignment expression of lvalue LHS from value RHS. MODIFYCODE is the code for a binary operator that we use @@ -3412,6 +3642,9 @@ build_modify_expr (tree lhs, enum tree_code modifycode, tree rhs) if (TREE_CODE (lhs) == ERROR_MARK || TREE_CODE (rhs) == ERROR_MARK) return error_mark_node; + if (!lvalue_or_else (lhs, lv_assign)) + return error_mark_node; + STRIP_TYPE_NOPS (rhs); newrhs = rhs; @@ -3425,16 +3658,16 @@ build_modify_expr (tree lhs, enum tree_code modifycode, tree rhs) newrhs = build_binary_op (modifycode, lhs, rhs, 1); } - if (!lvalue_or_else (lhs, lv_assign)) - return error_mark_node; - /* Give an error for storing in something that is 'const'. */ if (TREE_READONLY (lhs) || TYPE_READONLY (lhstype) || ((TREE_CODE (lhstype) == RECORD_TYPE || TREE_CODE (lhstype) == UNION_TYPE) && C_TYPE_FIELDS_READONLY (lhstype))) - readonly_error (lhs, 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'. @@ -3557,10 +3790,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); @@ -3639,7 +3870,7 @@ convert_for_assignment (tree type, tree rhs, enum impl_conv errtype, } /* Some types can interconvert without explicit casts. */ else if (codel == VECTOR_TYPE && coder == VECTOR_TYPE - && vector_types_convertible_p (type, TREE_TYPE (rhs))) + && vector_types_convertible_p (type, TREE_TYPE (rhs))) return convert (type, rhs); /* Arithmetic types all interconvert, and enum is treated like int. */ else if ((codel == INTEGER_TYPE || codel == REAL_TYPE @@ -3655,13 +3886,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))) @@ -3693,28 +3922,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 @@ -3749,12 +3976,14 @@ convert_for_assignment (tree type, tree rhs, enum impl_conv errtype, "from pointer target type"), 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); } } @@ -3775,9 +4004,54 @@ convert_for_assignment (tree type, tree rhs, enum impl_conv errtype, mvr = TYPE_MAIN_VARIANT (mvr); /* Opaque pointers are treated like void pointers. */ is_opaque_pointer = (targetm.vector_opaque_p (type) - || targetm.vector_opaque_p (rhstype)) - && TREE_CODE (ttl) == VECTOR_TYPE - && TREE_CODE (ttr) == VECTOR_TYPE; + || 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. @@ -3792,9 +4066,7 @@ 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 (G_("ISO C forbids passing argument %d of " "%qE between function pointer " @@ -3884,12 +4156,7 @@ 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)))) + if (!null_pointer_constant_p (rhs)) WARN_FOR_ASSIGNMENT (G_("passing argument %d of %qE makes " "pointer from integer without a cast"), G_("assignment makes pointer from integer " @@ -3941,7 +4208,7 @@ convert_for_assignment (tree type, tree rhs, enum impl_conv errtype, } /* Convert VALUE for assignment into inlined parameter PARM. ARGNUM - is used for error and waring reporting and indicates which argument + is used for error and warning reporting and indicates which argument is being processed. */ tree @@ -3949,9 +4216,15 @@ c_convert_parm_for_inlining (tree parm, tree value, tree fn, int argnum) { tree ret, type; - /* If FN was prototyped, the value has been converted already - in convert_arguments. */ - if (!value || TYPE_ARG_TYPES (TREE_TYPE (fn))) + /* If FN was prototyped at the call site, the value has been converted + already in convert_arguments. + However, we might see a prototype now that was not in place when + the function call was seen, so check that the VALUE actually matches + PARM before taking an early exit. */ + if (!value + || (TYPE_ARG_TYPES (TREE_TYPE (fn)) + && (TYPE_MAIN_VARIANT (TREE_TYPE (parm)) + == TYPE_MAIN_VARIANT (TREE_TYPE (value))))) return value; type = TREE_TYPE (parm); @@ -4010,15 +4283,16 @@ 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; /* ANSI wants warnings about out-of-range constant initializers. */ STRIP_TYPE_NOPS (value); - constant_expression_warning (value); + if (TREE_STATIC (decl)) constant_expression_warning (value); /* Check if we need to set array size from compound literal size. */ if (TREE_CODE (type) == ARRAY_TYPE @@ -4032,16 +4306,18 @@ store_init_value (tree decl, tree init) if (TREE_CODE (inside_init) == COMPOUND_LITERAL_EXPR) { - tree decl = COMPOUND_LITERAL_EXPR_DECL (inside_init); + tree cldecl = COMPOUND_LITERAL_EXPR_DECL (inside_init); - if (TYPE_DOMAIN (TREE_TYPE (decl))) + if (TYPE_DOMAIN (TREE_TYPE (cldecl))) { /* For int foo[] = (int [3]){1}; we need to set array size now since later on array initializer will be just the brace enclosed list of the compound literal. */ - TYPE_DOMAIN (type) = TYPE_DOMAIN (TREE_TYPE (decl)); + type = build_distinct_type_copy (TYPE_MAIN_VARIANT (type)); + TREE_TYPE (decl) = type; + TYPE_DOMAIN (type) = TYPE_DOMAIN (TREE_TYPE (cldecl)); layout_type (type); - layout_decl (decl, 0); + layout_decl (cldecl, 0); } } } @@ -4057,7 +4333,7 @@ struct spelling int kind; union { - int i; + unsigned HOST_WIDE_INT i; const char *s; } u; }; @@ -4117,7 +4393,7 @@ push_member_name (tree decl) /* Push an array bounds on the stack. Printed as [BOUNDS]. */ static void -push_array_bounds (int bounds) +push_array_bounds (unsigned HOST_WIDE_INT bounds) { PUSH_SPELLING (SPELLING_BOUNDS, bounds, u.i); } @@ -4152,7 +4428,7 @@ print_spelling (char *buffer) for (p = spelling_base; p < spelling; p++) if (p->kind == SPELLING_BOUNDS) { - sprintf (d, "[%d]", p->u.i); + sprintf (d, "[" HOST_WIDE_INT_PRINT_UNSIGNED "]", p->u.i); d += strlen (d); } else @@ -4243,6 +4519,7 @@ digest_init (tree type, tree init, bool strict_string, int require_constant) tree inside_init = init; if (type == error_mark_node + || !init || init == error_mark_node || TREE_TYPE (init) == error_mark_node) return error_mark_node; @@ -4333,18 +4610,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)); } } @@ -4361,34 +4642,36 @@ 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 conversion. */ inside_init = convert (type, inside_init); - if (require_constant && !flag_isoc99 + if (require_constant + && (code == VECTOR_TYPE || !flag_isoc99) && TREE_CODE (inside_init) == COMPOUND_LITERAL_EXPR) { /* As an extension, allow initializing objects with static storage duration with compound literals (which are then treated just as - the brace enclosed list they contain). */ + the brace enclosed list they contain). Also allow this for + vectors, as we can only assign them with compound literals. */ tree decl = COMPOUND_LITERAL_EXPR_DECL (inside_init); inside_init = DECL_INITIAL (decl); } @@ -4427,6 +4710,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; } @@ -4436,9 +4723,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); @@ -4505,7 +4793,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. */ @@ -4557,7 +4845,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 @@ -4576,7 +4864,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; @@ -4620,7 +4908,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; @@ -4637,7 +4925,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; @@ -4771,7 +5059,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) @@ -4821,7 +5109,7 @@ really_start_incremental_init (tree type) /* Vectors are like simple fixed-size arrays. */ constructor_max_index = build_int_cst (NULL_TREE, TYPE_VECTOR_SUBPARTS (constructor_type) - 1); - constructor_index = convert (bitsizetype, bitsize_zero_node); + constructor_index = bitsize_zero_node; constructor_unfilled_index = constructor_index; } else @@ -4915,7 +5203,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 @@ -4938,7 +5226,7 @@ push_init_level (int implicit) else if (TREE_CODE (constructor_type) == ARRAY_TYPE) { constructor_type = TREE_TYPE (constructor_type); - push_array_bounds (tree_low_cst (constructor_index, 0)); + push_array_bounds (tree_low_cst (constructor_index, 1)); constructor_depth++; } @@ -4955,7 +5243,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 (); @@ -5080,7 +5368,7 @@ pop_init_level (int implicit) else { gcc_assert (!TYPE_SIZE (constructor_type)); - + if (constructor_depth > 2) error_init ("initialization of flexible array member in a nested context"); else if (pedantic) @@ -5130,19 +5418,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 { @@ -5151,7 +5439,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) @@ -5181,15 +5469,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; } @@ -5209,7 +5490,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) @@ -5288,7 +5569,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)))) @@ -5334,7 +5615,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); } @@ -5350,7 +5631,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) @@ -5372,7 +5653,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); } @@ -5403,6 +5684,8 @@ add_pending_init (tree purpose, tree value) { if (TREE_SIDE_EFFECTS (p->value)) warning_init ("initialized field with side-effects overwritten"); + else if (warn_override_init) + warning_init ("initialized field overwritten"); p->value = value; return; } @@ -5424,6 +5707,8 @@ add_pending_init (tree purpose, tree value) { if (TREE_SIDE_EFFECTS (p->value)) warning_init ("initialized field with side-effects overwritten"); + else if (warn_override_init) + warning_init ("initialized field overwritten"); p->value = value; return; } @@ -5600,14 +5885,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) { @@ -5696,7 +5982,7 @@ set_nonincremental_init_from_string (tree str) else if (bitpos == HOST_BITS_PER_WIDE_INT) { if (val[1] < 0) - val[0] = -1; + val[0] = -1; } else if (val[0] & (((HOST_WIDE_INT) 1) << (bitpos - 1 - HOST_BITS_PER_WIDE_INT))) @@ -5759,9 +6045,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; } @@ -5783,19 +6070,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) @@ -5886,10 +6176,13 @@ 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"); + else if (warn_override_init) + warning_init ("initialized field overwritten"); /* We can have just one union field set. */ constructor_elements = 0; @@ -5898,10 +6191,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) @@ -6087,7 +6379,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"}; */ @@ -6098,7 +6390,7 @@ process_init_element (struct c_expr value) && integer_zerop (constructor_unfilled_index)) { if (constructor_stack->replacement_value.value) - error_init ("excess elements in char array initializer"); + error_init ("excess elements in char array initializer"); constructor_stack->replacement_value = value; return; } @@ -6201,10 +6493,10 @@ process_init_element (struct c_expr value) { /* For a record, keep track of end position of last field. */ if (DECL_SIZE (constructor_fields)) - constructor_bit_index + constructor_bit_index = size_binop (PLUS_EXPR, - bit_position (constructor_fields), - DECL_SIZE (constructor_fields)); + bit_position (constructor_fields), + DECL_SIZE (constructor_fields)); /* If the current field was the first one not yet written out, it isn't now, so update. */ @@ -6253,10 +6545,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 @@ -6327,7 +6620,7 @@ process_init_element (struct c_expr value) /* Now output the actual element. */ if (value.value) { - push_array_bounds (tree_low_cst (constructor_index, 0)); + push_array_bounds (tree_low_cst (constructor_index, 1)); output_init_element (value.value, strict_string, elttype, constructor_index, 1); RESTORE_SPELLING_DEPTH (constructor_depth); @@ -6346,8 +6639,8 @@ process_init_element (struct c_expr value) { tree elttype = TYPE_MAIN_VARIANT (TREE_TYPE (constructor_type)); - /* Do a basic check of initializer size. Note that vectors - always have a fixed size derived from their type. */ + /* Do a basic check of initializer size. Note that vectors + always have a fixed size derived from their type. */ if (tree_int_cst_lt (constructor_max_index, constructor_index)) { pedwarn_init ("excess elements in vector initializer"); @@ -6490,6 +6783,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; @@ -6502,14 +6803,11 @@ build_asm_expr (tree string, tree outputs, tree inputs, tree clobbers, output = error_mark_node; } else - output = error_mark_node; + output = error_mark_node; 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; @@ -6517,8 +6815,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)) { @@ -6541,12 +6837,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; } @@ -6616,7 +6910,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"); @@ -6626,8 +6921,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) { @@ -6683,7 +6981,7 @@ c_finish_return (tree retval) inner = TREE_OPERAND (inner, 0); while (REFERENCE_CLASS_P (inner) - && TREE_CODE (inner) != INDIRECT_REF) + && TREE_CODE (inner) != INDIRECT_REF) inner = TREE_OPERAND (inner, 0); if (DECL_P (inner) @@ -6703,7 +7001,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 { @@ -6749,34 +7049,33 @@ struct c_switch *c_switch_stack; tree c_start_case (tree exp) { - enum tree_code code; - tree type, orig_type = error_mark_node; + tree orig_type = error_mark_node; struct c_switch *cs; if (exp != error_mark_node) { - code = TREE_CODE (TREE_TYPE (exp)); orig_type = TREE_TYPE (exp); - if (!INTEGRAL_TYPE_P (orig_type) - && code != ERROR_MARK) + if (!INTEGRAL_TYPE_P (orig_type)) { - error ("switch quantity not an integer"); + if (orig_type != error_mark_node) + { + error ("switch quantity not an integer"); + orig_type = error_mark_node; + } exp = integer_zero_node; - orig_type = error_mark_node; } else { - type = TYPE_MAIN_VARIANT (TREE_TYPE (exp)); + tree type = TYPE_MAIN_VARIANT (orig_type); - 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); } } @@ -6907,31 +7206,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); } @@ -6961,42 +7243,41 @@ c_finish_loop (location_t start_locus, tree cond, tree incr, tree body, else { tree top = build1 (LABEL_EXPR, void_type_node, NULL_TREE); - + /* If we have an exit condition, then we build an IF with gotos either - out of the loop, or to the top of it. If there's no exit condition, - then we just build a jump back to the top. */ + out of the loop, or to the top of it. If there's no exit condition, + then we just build a jump back to the top. */ exit = build_and_jump (&LABEL_EXPR_LABEL (top)); - + if (cond && !integer_nonzerop (cond)) - { - /* Canonicalize the loop condition to the end. This means - generating a branch to the loop condition. Reuse the - continue label, if possible. */ - if (cond_is_first) - { - if (incr || !clab) - { - entry = build1 (LABEL_EXPR, void_type_node, NULL_TREE); - t = build_and_jump (&LABEL_EXPR_LABEL (entry)); - } - else - t = build1 (GOTO_EXPR, void_type_node, clab); + { + /* Canonicalize the loop condition to the end. This means + generating a branch to the loop condition. Reuse the + continue label, if possible. */ + if (cond_is_first) + { + if (incr || !clab) + { + entry = build1 (LABEL_EXPR, void_type_node, NULL_TREE); + t = build_and_jump (&LABEL_EXPR_LABEL (entry)); + } + else + t = build1 (GOTO_EXPR, void_type_node, clab); SET_EXPR_LOCATION (t, start_locus); - add_stmt (t); - } - + add_stmt (t); + } + 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); + SET_EXPR_LOCATION (exit, start_locus); else - SET_EXPR_LOCATION (exit, input_location); - } - + SET_EXPR_LOCATION (exit, input_location); + } + add_stmt (top); } - + if (body) add_stmt (body); if (clab) @@ -7031,13 +7312,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"); + 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) @@ -7072,13 +7364,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); @@ -7099,7 +7384,7 @@ c_process_expr_stmt (tree expr) if (DECL_P (expr) || CONSTANT_CLASS_P (expr)) expr = build1 (NOP_EXPR, TREE_TYPE (expr), expr); - if (EXPR_P (expr)) + if (CAN_HAVE_LOCATION_P (expr)) SET_EXPR_LOCATION (expr, input_location); return expr; @@ -7233,7 +7518,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 (CAN_HAVE_LOCATION_P (last)) + TREE_NO_WARNING (last) = 1; + return last; + } /* Extract the type of said expression. */ type = TREE_TYPE (last); @@ -7272,6 +7563,11 @@ c_begin_vm_scope (unsigned int scope) struct c_label_list *glist; gcc_assert (scope > 0); + + /* At file_scope, we don't have to do any processing. */ + if (label_context_stack_vm == NULL) + return; + if (c_switch_stack && !c_switch_stack->blocked_vm) c_switch_stack->blocked_vm = scope; for (glist = label_context_stack_vm->labels_used; @@ -7415,6 +7711,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, @@ -7490,6 +7787,13 @@ 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) @@ -7536,12 +7840,14 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1, && (code1 == INTEGER_TYPE || code1 == REAL_TYPE || code1 == COMPLEX_TYPE || code1 == VECTOR_TYPE)) { + 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 @@ -7684,14 +7990,14 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1, { /* 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"); @@ -7704,12 +8010,28 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1, 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)) + && (TREE_CODE (TREE_OPERAND (op0, 0)) == PARM_DECL + || TREE_CODE (TREE_OPERAND (op0, 0)) == LABEL_DECL + || !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)) + && (TREE_CODE (TREE_OPERAND (op1, 0)) == PARM_DECL + || TREE_CODE (TREE_OPERAND (op1, 0)) == LABEL_DECL + || !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; @@ -7748,15 +8070,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) @@ -7781,6 +8101,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) && @@ -7806,12 +8135,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 @@ -7848,7 +8200,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)) @@ -7944,9 +8296,9 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1, all the values of the unsigned type. */ if (!TYPE_UNSIGNED (result_type)) /* OK */; - /* Do not warn if both operands are the same signedness. */ - else if (op0_signed == op1_signed) - /* OK */; + /* Do not warn if both operands are the same signedness. */ + else if (op0_signed == op1_signed) + /* OK */; else { tree sop, uop; @@ -8056,9 +8408,9 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1, if (!converted) { if (TREE_TYPE (op0) != result_type) - op0 = convert (result_type, op0); + op0 = convert_and_check (result_type, op0); if (TREE_TYPE (op1) != result_type) - op1 = convert (result_type, op1); + op1 = convert_and_check (result_type, op1); /* This can happen if one operand has a vector type, and the other has a different type. */ @@ -8070,11 +8422,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); @@ -8084,12 +8437,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: @@ -8104,6 +8456,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; } @@ -8112,3 +8467,268 @@ 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; +}