X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=gcc%2Fc-typeck.c;h=8119e7f17b126e27d816cb37520840c4210a0d3a;hb=59c0753dd31ebc72074a9650182896e0c6f5647a;hp=eb7909ed7690f9fab7b7c5182c18530bfe696734;hpb=13b22d3a861a9d82fe3b70e5cb11ca5c2a9d4c98;p=gcc.git diff --git a/gcc/c-typeck.c b/gcc/c-typeck.c index eb7909ed769..8119e7f17b1 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. @@ -74,6 +75,7 @@ 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); @@ -88,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 *); @@ -105,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.) */ @@ -204,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; } @@ -221,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. @@ -288,7 +331,7 @@ composite_type (tree t1, tree t2) /* 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); @@ -298,6 +341,8 @@ composite_type (tree t1, tree t2) 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) @@ -306,12 +351,12 @@ composite_type (tree t1, tree 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 @@ -330,6 +375,19 @@ composite_type (tree t1, tree t2) 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. */ @@ -485,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); @@ -551,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.) */ @@ -585,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)) @@ -606,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 @@ -637,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. */ @@ -662,13 +760,30 @@ 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. */ 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; @@ -736,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: @@ -753,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. */ @@ -769,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; @@ -779,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: @@ -860,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 @@ -916,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; @@ -994,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; @@ -1018,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) @@ -1029,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: @@ -1069,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; @@ -1150,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. */ @@ -1169,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) @@ -1190,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) @@ -1356,7 +1560,8 @@ default_function_array_conversion (struct c_expr exp) bool lvalue_array_p; while ((TREE_CODE (exp.value) == NON_LVALUE_EXPR - || TREE_CODE (exp.value) == NOP_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) @@ -1624,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; @@ -1748,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 (!swapped - && TYPE_MAIN_VARIANT (TREE_TYPE (index)) == char_type_node) - warning (OPT_Wchar_subscripts, "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); @@ -1807,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)); @@ -1888,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; @@ -1903,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; } @@ -1976,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; @@ -1992,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; } @@ -2056,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))) @@ -2084,7 +2308,7 @@ build_function_call (tree function, tree params) rhs = build_compound_literal (return_type, 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); } @@ -2104,13 +2328,10 @@ build_function_call (tree function, tree params) check_function_arguments (TYPE_ATTRIBUTES (fntype), coerced_params, TYPE_ARG_TYPES (fntype)); - result = build3 (CALL_EXPR, TREE_TYPE (fntype), - function, coerced_params, NULL_TREE); - TREE_SIDE_EFFECTS (result) = 1; - 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 @@ -2118,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; @@ -2205,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); @@ -2247,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); @@ -2268,7 +2517,7 @@ 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 (OPT_Wconversion, "passing argument %d of %qE " + 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)) @@ -2291,11 +2540,11 @@ convert_arguments (tree typelist, tree values, tree function, tree fundecl) && TYPE_UNSIGNED (TREE_TYPE (val))) ; else if (TYPE_UNSIGNED (type)) - warning (OPT_Wconversion, "passing argument %d of %qE " + warning (OPT_Wtraditional_conversion, "passing argument %d of %qE " "as unsigned due to prototype", argnum, rname); else - warning (OPT_Wconversion, "passing argument %d of %qE " + warning (OPT_Wtraditional_conversion, "passing argument %d of %qE " "as signed due to prototype", argnum, rname); } } @@ -2312,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'. */ @@ -2351,7 +2601,10 @@ parser_build_unary_op (enum tree_code code, struct c_expr arg) result.original_code = ERROR_MARK; result.value = build_unary_op (code, arg.value, 0); - overflow_warning (result.value); + + if (TREE_OVERFLOW_P (result.value) && !TREE_OVERFLOW_P (arg.value)) + overflow_warning (result.value); + return result; } @@ -2379,77 +2632,26 @@ 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"))); } @@ -3031,9 +3252,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); @@ -3075,11 +3296,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))) { @@ -3105,7 +3324,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 { @@ -3115,7 +3334,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 { @@ -3158,16 +3377,18 @@ build_compound_expr (tree expr1, tree 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"); @@ -3181,6 +3402,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); } @@ -3316,8 +3540,12 @@ build_c_cast (tree type, tree expr) if (TREE_CODE (type) == INTEGER_TYPE && TREE_CODE (otype) == POINTER_TYPE - && TYPE_PRECISION (type) != TYPE_PRECISION (otype) - && !TREE_CONSTANT (value)) + && 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"); @@ -3334,33 +3562,7 @@ build_c_cast (tree type, tree expr) warning (OPT_Wint_to_pointer_cast, "cast to pointer from integer " "of different size"); - if (flag_strict_aliasing && warn_strict_aliasing - && TREE_CODE (type) == POINTER_TYPE - && TREE_CODE (otype) == POINTER_TYPE - && TREE_CODE (expr) == ADDR_EXPR - && (DECL_P (TREE_OPERAND (expr, 0)) - || TREE_CODE (TREE_OPERAND (expr, 0)) == COMPONENT_REF) - && !VOID_TYPE_P (TREE_TYPE (type))) - { - /* Casting the address of an object to non void pointer. Warn - if the cast breaks type based aliasing. */ - if (!COMPLETE_TYPE_P (TREE_TYPE (type))) - warning (OPT_Wstrict_aliasing, "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 (OPT_Wstrict_aliasing, "dereferencing type-punned " - "pointer will break strict-aliasing rules"); - else if (warn_strict_aliasing > 1 - && !alias_sets_might_conflict_p (set1, set2)) - warning (OPT_Wstrict_aliasing, "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 @@ -3377,8 +3579,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; @@ -3387,16 +3588,19 @@ build_c_cast (tree type, tree expr) /* Ignore any integer overflow caused by the cast. */ if (TREE_CODE (value) == INTEGER_CST) { - /* If OVALUE had overflow set, then so will VALUE, so it - is safe to overwrite. */ - if (CONSTANT_CLASS_P (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); - /* Similarly, constant_overflow cannot have become cleared. */ TREE_CONSTANT_OVERFLOW (value) = TREE_CONSTANT_OVERFLOW (ovalue); } - else - TREE_OVERFLOW (value) = 0; + 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)); } } @@ -3423,7 +3627,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 @@ -3445,6 +3648,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; @@ -3458,16 +3664,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'. @@ -3627,10 +3833,7 @@ convert_for_assignment (tree type, tree rhs, enum impl_conv errtype, } if (TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (rhstype)) - { - overflow_warning (rhs); - return rhs; - } + return rhs; if (coder == VOID_TYPE) { @@ -3670,7 +3873,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 @@ -3686,13 +3889,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))) @@ -3724,28 +3925,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 @@ -3780,12 +3979,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 && (!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); } } @@ -3806,26 +4007,26 @@ 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 + for the purpose of reducing the number of false positives, we + tolerate the special case of - int *p = NULL; + int *p = NULL; - where NULL is typically defined in C to be '(void *) 0'. */ + 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); + 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: @@ -3854,7 +4055,7 @@ convert_for_assignment (tree type, tree rhs, enum impl_conv errtype, gcc_unreachable (); } } - + /* Any non-function converts to a [const][volatile] void * and vice versa; otherwise, targets must be the same. Meanwhile, the lhs target must have all the qualifiers of the rhs. */ @@ -3868,9 +4069,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 " @@ -3960,12 +4159,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 " @@ -4017,7 +4211,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 @@ -4025,9 +4219,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); @@ -4095,7 +4295,8 @@ store_init_value (tree decl, tree init) /* 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 @@ -4109,16 +4310,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); } } } @@ -4134,7 +4337,7 @@ struct spelling int kind; union { - int i; + unsigned HOST_WIDE_INT i; const char *s; } u; }; @@ -4194,7 +4397,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); } @@ -4229,7 +4432,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 @@ -4320,6 +4523,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; @@ -4464,12 +4668,14 @@ digest_init (tree type, tree init, bool strict_string, int require_constant) 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); } @@ -4643,7 +4849,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 @@ -4723,7 +4929,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; @@ -4857,7 +5063,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) @@ -4907,7 +5113,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 @@ -5001,7 +5207,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 @@ -5024,7 +5230,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++; } @@ -5166,7 +5372,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) @@ -5267,15 +5473,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; } @@ -5295,7 +5494,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) @@ -5374,7 +5573,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)))) @@ -5420,7 +5619,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); } @@ -5436,7 +5635,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) @@ -5458,7 +5657,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); } @@ -5489,6 +5688,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; } @@ -5510,6 +5711,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; } @@ -5783,7 +5986,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))) @@ -5982,6 +6185,8 @@ output_init_element (tree value, bool strict_string, tree type, tree field, 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; @@ -6178,7 +6383,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"}; */ @@ -6189,7 +6394,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; } @@ -6292,10 +6497,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. */ @@ -6419,7 +6624,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); @@ -6438,8 +6643,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"); @@ -6582,6 +6787,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; @@ -6594,7 +6807,7 @@ 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; } @@ -6628,12 +6841,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; } @@ -6703,7 +6914,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"); @@ -6713,8 +6925,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) { @@ -6770,7 +6985,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) @@ -6790,7 +7005,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 { @@ -6836,25 +7053,25 @@ 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 (!in_system_header && (type == long_integer_type_node @@ -6863,7 +7080,6 @@ c_start_case (tree exp) "converted to % in ISO C"); exp = default_conversion (exp); - type = TREE_TYPE (exp); } } @@ -6999,25 +7215,7 @@ c_finish_if_stmt (location_t if_locus, tree cond, tree then_block, &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, void_type_node, cond, then_block, else_block); SET_EXPR_LOCATION (stmt, if_locus); @@ -7049,42 +7247,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) @@ -7119,13 +7316,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) @@ -7180,7 +7388,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; @@ -7314,7 +7522,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); @@ -7353,6 +7567,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; @@ -7775,14 +7994,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"); @@ -7795,12 +8014,22 @@ 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_with_nonnull_addr_p (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_with_nonnull_addr_p (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; @@ -7839,15 +8068,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) @@ -7906,12 +8133,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 @@ -7948,7 +8198,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)) @@ -8044,9 +8294,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; @@ -8156,9 +8406,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. */ @@ -8170,11 +8420,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); @@ -8235,3 +8486,247 @@ c_expr_to_decl (tree expr, bool *tc ATTRIBUTE_UNUSED, 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; +}