X-Git-Url: http://git.sourceforge.jp/view?a=blobdiff_plain;f=gcc%2Fc-typeck.c;h=a9220810c2f3f06d7191ac22b5704c56a8c138ca;hb=ea98cbe0776812106b9ab0ec50843ec96abe9a17;hp=2150238ec6e1abc5c445b5c28d520eb15a2fafa4;hpb=2840aae48b06eb49ec47d256709b91cf44948f4e;p=pf3gnuchains%2Fgcc-fork.git diff --git a/gcc/c-typeck.c b/gcc/c-typeck.c index 2150238ec6e..a9220810c2f 100644 --- a/gcc/c-typeck.c +++ b/gcc/c-typeck.c @@ -1,12 +1,13 @@ /* 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, 2007 + Free Software Foundation, Inc. This file is part of GCC. GCC is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free -Software Foundation; either version 2, or (at your option) any later +Software Foundation; either version 3, or (at your option) any later version. GCC is distributed in the hope that it will be useful, but WITHOUT ANY @@ -15,9 +16,8 @@ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 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, 51 Franklin Street, Fifth Floor, Boston, MA -02110-1301, USA. */ +along with GCC; see the file COPYING3. If not see +. */ /* This file is part of the C front end. @@ -74,21 +74,21 @@ static int missing_braces_mentioned; static int require_constant_value; static int require_constant_elements; +static bool null_pointer_constant_p (const_tree); static tree qualify_type (tree, tree); -static int tagged_types_tu_compatible_p (tree, tree); +static int tagged_types_tu_compatible_p (const_tree, const_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 int function_types_compatible_p (const_tree, const_tree); +static int type_lists_compatible_p (const_tree, const_tree); static tree decl_constant_value_for_broken_optimization (tree); static tree lookup_field (tree, tree); -static tree convert_arguments (tree, tree, tree, tree); +static int convert_arguments (int, tree *, tree, tree, tree, tree); static tree pointer_diff (tree, tree); static tree convert_for_assignment (tree, tree, enum impl_conv, tree, tree, int); 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 *); @@ -102,16 +102,33 @@ static void set_nonincremental_init (void); static void set_nonincremental_init_from_string (tree); static tree find_init_member (tree); static void readonly_error (tree, enum lvalue_use); -static int lvalue_or_else (tree, enum lvalue_use); -static int lvalue_p (tree); +static int lvalue_or_else (const_tree, enum lvalue_use); +static int lvalue_p (const_tree); static void record_maybe_used_decl (tree); -static int comptypes_internal (tree, tree); +static int comptypes_internal (const_tree, const_tree); + +/* Return true if EXP is a null pointer constant, false otherwise. */ + +static bool +null_pointer_constant_p (const_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_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; + const_tree t1; + const_tree t2; /* The return value of tagged_types_tu_compatible_p if we had seen these two types already. */ int val; @@ -144,7 +161,7 @@ require_complete_type (tree value) and TYPE is the type that was invalid. */ void -c_incomplete_type_error (tree value, tree type) +c_incomplete_type_error (const_tree value, const_tree type) { const char *type_code_string; @@ -218,8 +235,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; } @@ -235,6 +252,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 (const_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. @@ -302,7 +330,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); @@ -312,6 +340,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) @@ -320,12 +350,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 @@ -344,6 +374,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. */ @@ -499,7 +542,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); @@ -561,9 +604,34 @@ c_common_type (tree t1, tree t2) code2 = TREE_CODE (t2); gcc_assert (code1 == VECTOR_TYPE || code1 == COMPLEX_TYPE - || code1 == REAL_TYPE || code1 == INTEGER_TYPE); + || code1 == FIXED_POINT_TYPE || code1 == REAL_TYPE + || code1 == INTEGER_TYPE); gcc_assert (code2 == VECTOR_TYPE || code2 == COMPLEX_TYPE - || code2 == REAL_TYPE || code2 == INTEGER_TYPE); + || code2 == FIXED_POINT_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 @@ -599,6 +667,107 @@ 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; + } + + /* Deal with fixed-point types. */ + if (code1 == FIXED_POINT_TYPE || code2 == FIXED_POINT_TYPE) + { + unsigned int unsignedp = 0, satp = 0; + enum machine_mode m1, m2; + unsigned int fbit1, ibit1, fbit2, ibit2, max_fbit, max_ibit; + + m1 = TYPE_MODE (t1); + m2 = TYPE_MODE (t2); + + /* If one input type is saturating, the result type is saturating. */ + if (TYPE_SATURATING (t1) || TYPE_SATURATING (t2)) + satp = 1; + + /* If both fixed-point types are unsigned, the result type is unsigned. + When mixing fixed-point and integer types, follow the sign of the + fixed-point type. + Otherwise, the result type is signed. */ + if ((TYPE_UNSIGNED (t1) && TYPE_UNSIGNED (t2) + && code1 == FIXED_POINT_TYPE && code2 == FIXED_POINT_TYPE) + || (code1 == FIXED_POINT_TYPE && code2 != FIXED_POINT_TYPE + && TYPE_UNSIGNED (t1)) + || (code1 != FIXED_POINT_TYPE && code2 == FIXED_POINT_TYPE + && TYPE_UNSIGNED (t2))) + unsignedp = 1; + + /* The result type is signed. */ + if (unsignedp == 0) + { + /* If the input type is unsigned, we need to convert to the + signed type. */ + if (code1 == FIXED_POINT_TYPE && TYPE_UNSIGNED (t1)) + { + unsigned char mclass = 0; + if (GET_MODE_CLASS (m1) == MODE_UFRACT) + mclass = MODE_FRACT; + else if (GET_MODE_CLASS (m1) == MODE_UACCUM) + mclass = MODE_ACCUM; + else + gcc_unreachable (); + m1 = mode_for_size (GET_MODE_PRECISION (m1), mclass, 0); + } + if (code2 == FIXED_POINT_TYPE && TYPE_UNSIGNED (t2)) + { + unsigned char mclass = 0; + if (GET_MODE_CLASS (m2) == MODE_UFRACT) + mclass = MODE_FRACT; + else if (GET_MODE_CLASS (m2) == MODE_UACCUM) + mclass = MODE_ACCUM; + else + gcc_unreachable (); + m2 = mode_for_size (GET_MODE_PRECISION (m2), mclass, 0); + } + } + + if (code1 == FIXED_POINT_TYPE) + { + fbit1 = GET_MODE_FBIT (m1); + ibit1 = GET_MODE_IBIT (m1); + } + else + { + fbit1 = 0; + /* Signed integers need to subtract one sign bit. */ + ibit1 = TYPE_PRECISION (t1) - (!TYPE_UNSIGNED (t1)); + } + + if (code2 == FIXED_POINT_TYPE) + { + fbit2 = GET_MODE_FBIT (m2); + ibit2 = GET_MODE_IBIT (m2); + } + else + { + fbit2 = 0; + /* Signed integers need to subtract one sign bit. */ + ibit2 = TYPE_PRECISION (t2) - (!TYPE_UNSIGNED (t2)); + } + + max_ibit = ibit1 >= ibit2 ? ibit1 : ibit2; + max_fbit = fbit1 >= fbit2 ? fbit1 : fbit2; + return c_common_fixed_point_type_for_size (max_ibit, max_fbit, unsignedp, + satp); + } + /* Both real or both integers; use the one with greater precision. */ if (TYPE_PRECISION (t1) > TYPE_PRECISION (t2)) @@ -620,7 +789,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 @@ -690,19 +859,20 @@ comptypes (tree type1, tree type2) 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) +comptypes_internal (const_tree type1, const_tree type2) { - tree t1 = type1; - tree t2 = type2; + const_tree t1 = type1; + const_tree t2 = type2; int attrval, val; /* Suppress errors caused by previously reported errors. */ @@ -800,6 +970,8 @@ comptypes_internal (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; @@ -810,14 +982,21 @@ comptypes_internal (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)) - { + { + 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); @@ -866,7 +1045,7 @@ comp_target_types (tree ttl, tree ttr) being parsed, so if two trees have context chains ending in null, they're in the same translation unit. */ int -same_translation_unit_p (tree t1, tree t2) +same_translation_unit_p (const_tree t1, const_tree t2) { while (t1 && TREE_CODE (t1) != TRANSLATION_UNIT_DECL) switch (TREE_CODE_CLASS (TREE_CODE (t1))) @@ -898,15 +1077,15 @@ same_translation_unit_p (tree t1, tree t2) /* Allocate the seen two types, assuming that they are compatible. */ static struct tagged_tu_seen_cache * -alloc_tagged_tu_seen_cache (tree t1, tree t2) +alloc_tagged_tu_seen_cache (const_tree t1, const_tree t2) { - struct tagged_tu_seen_cache *tu = xmalloc (sizeof (struct tagged_tu_seen_cache)); + 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 @@ -931,9 +1110,10 @@ 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; + const struct tagged_tu_seen_cache *const tu1 + = (const struct tagged_tu_seen_cache *) tu; tu = tu1->next; - free (tu1); + free (CONST_CAST (struct tagged_tu_seen_cache *, tu1)); } tagged_tu_seen_base = tu_til; } @@ -945,7 +1125,7 @@ free_all_tagged_tu_seen_up_to (const struct tagged_tu_seen_cache *tu_til) rules. */ static int -tagged_types_tu_compatible_p (tree t1, tree t2) +tagged_types_tu_compatible_p (const_tree t1, const_tree t2) { tree s1, s2; bool needs_warning = false; @@ -989,31 +1169,31 @@ tagged_types_tu_compatible_p (tree t1, tree t2) 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) + 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) + 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; + tu->val = 0; return 0; } - } + } - if (tv1 == NULL_TREE && tv2 == NULL_TREE) + if (tv1 == NULL_TREE && tv2 == NULL_TREE) { return 1; } - if (tv1 == NULL_TREE || tv2 == NULL_TREE) + if (tv1 == NULL_TREE || tv2 == NULL_TREE) { tu->val = 0; return 0; @@ -1046,16 +1226,16 @@ tagged_types_tu_compatible_p (tree t1, tree t2) 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)) + || DECL_NAME (s1) != DECL_NAME (s2)) break; result = comptypes_internal (TREE_TYPE (s1), TREE_TYPE (s2)); if (result == 0) @@ -1118,7 +1298,7 @@ tagged_types_tu_compatible_p (tree t1, tree t2) case RECORD_TYPE: { - struct tagged_tu_seen_cache *tu = alloc_tagged_tu_seen_cache (t1, t2); + struct tagged_tu_seen_cache *tu = alloc_tagged_tu_seen_cache (t1, t2); for (s1 = TYPE_FIELDS (t1), s2 = TYPE_FIELDS (t2); s1 && s2; @@ -1159,7 +1339,7 @@ tagged_types_tu_compatible_p (tree t1, tree t2) Otherwise, the argument types must match. */ static int -function_types_compatible_p (tree f1, tree f2) +function_types_compatible_p (const_tree f1, const_tree f2) { tree args1, args2; /* 1 if no need for warning yet, 2 if warning cause has been seen. */ @@ -1222,7 +1402,7 @@ function_types_compatible_p (tree f1, tree f2) or 2 for compatible with warning. */ static int -type_lists_compatible_p (tree args1, tree args2) +type_lists_compatible_p (const_tree args1, const_tree args2) { /* 1 if no need for warning yet, 2 if warning cause has been seen. */ int val = 1; @@ -1323,7 +1503,7 @@ type_lists_compatible_p (tree args1, tree args2) /* Compute the size to increment a pointer by. */ static tree -c_size_in_bytes (tree type) +c_size_in_bytes (const_tree type) { enum tree_code code = TREE_CODE (type); @@ -1467,7 +1647,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) @@ -1735,11 +1916,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; @@ -1776,6 +1963,19 @@ build_indirect_ref (tree ptr, const char *errorstring) if (TREE_CODE (type) == POINTER_TYPE) { + if (TREE_CODE (pointer) == CONVERT_EXPR + || TREE_CODE (pointer) == NOP_EXPR + || TREE_CODE (pointer) == VIEW_CONVERT_EXPR) + { + /* If a warning is issued, mark it to avoid duplicates from + the backend. This only needs to be done at + warn_strict_aliasing > 2. */ + if (warn_strict_aliasing > 2) + if (strict_aliasing_warning (TREE_TYPE (TREE_OPERAND (pointer, 0)), + type, TREE_OPERAND (pointer, 0))) + TREE_NO_WARNING (pointer) = 1; + } + if (TREE_CODE (pointer) == ADDR_EXPR && (TREE_TYPE (TREE_OPERAND (pointer, 0)) == TREE_TYPE (type))) @@ -1810,7 +2010,7 @@ build_indirect_ref (tree ptr, const char *errorstring) } } else if (TREE_CODE (pointer) != ERROR_MARK) - error ("invalid type argument of %qs", errorstring); + error ("invalid type argument of %qs (have %qT)", errorstring, type); return error_mark_node; } @@ -1912,7 +2112,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)); @@ -1977,9 +2177,13 @@ build_external_ref (tree id, int fun, location_t loc) if (TREE_DEPRECATED (ref)) warn_deprecated_use (ref); - if (!skip_evaluation) - assemble_external (ref); - TREE_USED (ref) = 1; + /* Recursive call does not count as usage. */ + if (ref != current_function_decl) + { + if (!skip_evaluation) + assemble_external (ref); + TREE_USED (ref) = 1; + } if (TREE_CODE (ref) == FUNCTION_DECL && !in_alignof) { @@ -1993,6 +2197,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; @@ -2008,6 +2213,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; } @@ -2081,6 +2297,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; @@ -2097,7 +2318,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; } @@ -2110,9 +2332,11 @@ tree build_function_call (tree function, tree params) { tree fntype, fundecl = 0; - tree coerced_params; tree name = NULL_TREE, result; tree tem; + int nargs; + tree *argarray; + /* Strip NON_LVALUE_EXPRs, etc., since we aren't using as an lvalue. */ STRIP_TYPE_NOPS (function); @@ -2161,7 +2385,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))) @@ -2189,7 +2414,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); } @@ -2198,30 +2423,30 @@ build_function_call (tree function, tree params) /* Convert the parameters to the types declared in the function prototype, or apply default promotions. */ - coerced_params - = convert_arguments (TYPE_ARG_TYPES (fntype), params, function, fundecl); - - if (coerced_params == error_mark_node) + nargs = list_length (params); + argarray = (tree *) alloca (nargs * sizeof (tree)); + nargs = convert_arguments (nargs, argarray, TYPE_ARG_TYPES (fntype), + params, function, fundecl); + if (nargs < 0) return error_mark_node; /* Check that the arguments to the function are valid. */ - check_function_arguments (TYPE_ATTRIBUTES (fntype), coerced_params, + check_function_arguments (TYPE_ATTRIBUTES (fntype), nargs, argarray, TYPE_ARG_TYPES (fntype)); if (require_constant_value) { - result = fold_build3_initializer (CALL_EXPR, TREE_TYPE (fntype), - function, coerced_params, NULL_TREE); - + result = fold_build_call_array_initializer (TREE_TYPE (fntype), + function, nargs, argarray); if (TREE_CONSTANT (result) && (name == NULL_TREE || strncmp (IDENTIFIER_POINTER (name), "__builtin_", 10) != 0)) pedwarn_init ("initializer element is not constant"); } else - result = fold_build3 (CALL_EXPR, TREE_TYPE (fntype), - function, coerced_params, NULL_TREE); + result = fold_build_call_array (TREE_TYPE (fntype), + function, nargs, argarray); if (VOID_TYPE_P (TREE_TYPE (result))) return result; @@ -2229,9 +2454,8 @@ build_function_call (tree function, tree params) } /* Convert the argument expressions in the list VALUES - to the types in the list TYPELIST. The result is a list of converted - argument expressions, unless there are too few arguments in which - case it is error_mark_node. + to the types in the list TYPELIST. The resulting arguments are + stored in the array ARGARRAY which has size NARGS. If TYPELIST is exhausted, or when an element has NULL as its type, perform the default conversions. @@ -2245,15 +2469,20 @@ build_function_call (tree function, tree params) This is also where warnings about wrong number of args are generated. - Both VALUES and the returned value are chains of TREE_LIST nodes - with the elements of the list in the TREE_VALUE slots of those nodes. */ + VALUES is a chain of TREE_LIST nodes with the elements of the list + in the TREE_VALUE slots of those nodes. -static tree -convert_arguments (tree typelist, tree values, tree function, tree fundecl) + Returns the actual number of arguments processed (which may be less + than NARGS in some error situations), or -1 on failure. */ + +static int +convert_arguments (int nargs, tree *argarray, + tree typelist, tree values, tree function, tree fundecl) { tree typetail, valtail; - tree result = NULL; int parmnum; + const bool type_generic = fundecl + && lookup_attribute ("type generic", TYPE_ATTRIBUTES(TREE_TYPE (fundecl))); tree selector; /* Change pointer to function to the function itself for @@ -2266,7 +2495,7 @@ convert_arguments (tree typelist, tree values, tree function, tree fundecl) selector = objc_message_selector (); /* Scan the given expressions and types, producing individual - converted arguments and pushing them on RESULT in reverse order. */ + converted arguments and storing them in ARGARRAY. */ for (valtail = values, typetail = typelist, parmnum = 0; valtail; @@ -2281,7 +2510,7 @@ convert_arguments (tree typelist, tree values, tree function, tree fundecl) if (type == void_type_node) { error ("too many arguments to function %qE", function); - break; + return parmnum; } if (selector && argnum > 2) @@ -2308,7 +2537,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); @@ -2350,15 +2579,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); @@ -2371,7 +2627,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)) @@ -2394,11 +2650,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); } } @@ -2412,34 +2668,42 @@ convert_arguments (tree typelist, tree values, tree function, tree fundecl) && (TYPE_PRECISION (type) < TYPE_PRECISION (integer_type_node))) parmval = default_conversion (parmval); } - result = tree_cons (NULL_TREE, parmval, result); + argarray[parmnum] = parmval; } else if (TREE_CODE (TREE_TYPE (val)) == REAL_TYPE - && (TYPE_PRECISION (TREE_TYPE (val)) - < TYPE_PRECISION (double_type_node))) - /* Convert `float' to `double'. */ - result = tree_cons (NULL_TREE, convert (double_type_node, val), result); - else if ((invalid_func_diag = - targetm.calls.invalid_arg_for_unprototyped_fn (typelist, fundecl, val))) + && (TYPE_PRECISION (TREE_TYPE (val)) + < TYPE_PRECISION (double_type_node)) + && !DECIMAL_FLOAT_MODE_P (TYPE_MODE (TREE_TYPE (val)))) + { + if (type_generic) + argarray[parmnum] = val; + else + /* Convert `float' to `double'. */ + argarray[parmnum] = convert (double_type_node, 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 -1; } else /* Convert `short' and `char' to full-size `int'. */ - result = tree_cons (NULL_TREE, default_conversion (val), result); + argarray[parmnum] = default_conversion (val); if (typetail) typetail = TREE_CHAIN (typetail); } + gcc_assert (parmnum == nargs); + if (typetail != 0 && TREE_VALUE (typetail) != void_type_node) { error ("too few arguments to function %qE", function); - return error_mark_node; + return -1; } - return nreverse (result); + return parmnum; } /* This is the entry point used by the parser to build unary operators @@ -2454,7 +2718,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; } @@ -2482,77 +2749,27 @@ parser_build_binary_op (enum tree_code code, struct c_expr arg1, /* Check for cases such as x+y< 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_("read-only location used as % output"))); + error (READONLY_MSG (G_("assignment of read-only location %qE"), + G_("increment of read-only location %qE"), + G_("decrement of read-only location %qE"), + G_("read-only location %qE used as % output")), + arg); } @@ -3014,7 +3274,7 @@ readonly_error (tree arg, enum lvalue_use use) how the lvalue is being used and so selects the error message. */ static int -lvalue_or_else (tree ref, enum lvalue_use use) +lvalue_or_else (const_tree ref, enum lvalue_use use) { int win = lvalue_p (ref); @@ -3138,9 +3398,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); @@ -3156,6 +3416,8 @@ build_conditional_expr (tree ifexp, tree op1, tree op2) if (unsigned_op1 ^ unsigned_op2) { + bool ovf; + /* Do not warn if the result type is signed, since the signed type will only be chosen if it can represent all the values of the unsigned type. */ @@ -3164,8 +3426,10 @@ build_conditional_expr (tree ifexp, tree op1, tree op2) /* Do not warn if the signed quantity is an unsuffixed integer literal (or some static constant expression involving such literals) and it is non-negative. */ - else if ((unsigned_op2 && tree_expr_nonnegative_p (op1)) - || (unsigned_op1 && tree_expr_nonnegative_p (op2))) + else if ((unsigned_op2 + && tree_expr_nonnegative_warnv_p (op1, &ovf)) + || (unsigned_op1 + && tree_expr_nonnegative_warnv_p (op2, &ovf))) /* OK */; else warning (0, "signed and unsigned type in conditional expression"); @@ -3182,11 +3446,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))) { @@ -3212,7 +3474,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 { @@ -3222,7 +3484,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 { @@ -3265,19 +3527,22 @@ 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"); + warning (OPT_Wunused_value, + "left-hand operand of comma expression has no effect"); } } @@ -3288,6 +3553,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); } @@ -3398,12 +3666,12 @@ build_c_cast (tree type, tree expr) && TREE_CODE (in_otype) == POINTER_TYPE); if (added) - warning (0, "cast adds new qualifiers to function type"); + warning (OPT_Wcast_qual, "cast adds new qualifiers to function type"); if (discarded) /* There are qualifiers present in IN_OTYPE that are not present in IN_TYPE. */ - warning (0, "cast discards qualifiers from pointer target type"); + warning (OPT_Wcast_qual, "cast discards qualifiers from pointer target type"); } /* Warn about possible alignment problems. */ @@ -3423,8 +3691,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"); @@ -3441,33 +3713,8 @@ 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"); - } - } + if (warn_strict_aliasing <= 2) + strict_aliasing_warning (otype, type, expr); /* If pedantic, warn for conversions between function and object pointer types, except for converting a null pointer constant @@ -3484,8 +3731,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; @@ -3494,15 +3740,16 @@ build_c_cast (tree type, tree expr) /* Ignore any integer overflow caused by the cast. */ if (TREE_CODE (value) == INTEGER_CST) { - if (CONSTANT_CLASS_P (ovalue) - && (TREE_OVERFLOW (ovalue) || TREE_CONSTANT_OVERFLOW (ovalue))) + if (CONSTANT_CLASS_P (ovalue) && TREE_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); + if (!TREE_OVERFLOW (value)) + { + /* Avoid clobbering a shared constant. */ + value = copy_node (value); + TREE_OVERFLOW (value) = TREE_OVERFLOW (ovalue); + } } - else if (TREE_OVERFLOW (value) || TREE_CONSTANT_OVERFLOW (value)) + else if (TREE_OVERFLOW (value)) /* Reset VALUE's overflow flags, ensuring constant sharing. */ value = build_int_cst_wide (TREE_TYPE (value), TREE_INT_CST_LOW (value), @@ -3533,7 +3780,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 @@ -3555,6 +3801,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; @@ -3568,16 +3817,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'. @@ -3737,10 +3986,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) { @@ -3780,21 +4026,29 @@ 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), true)) return convert (type, rhs); /* Arithmetic types all interconvert, and enum is treated like int. */ else if ((codel == INTEGER_TYPE || codel == REAL_TYPE + || codel == FIXED_POINT_TYPE || codel == ENUMERAL_TYPE || codel == COMPLEX_TYPE || codel == BOOLEAN_TYPE) && (coder == INTEGER_TYPE || coder == REAL_TYPE + || coder == FIXED_POINT_TYPE || coder == ENUMERAL_TYPE || coder == COMPLEX_TYPE || coder == BOOLEAN_TYPE)) return convert_and_check (type, rhs); + /* Aggregates in different TUs might need conversion. */ + if ((codel == RECORD_TYPE || codel == UNION_TYPE) + && codel == coder + && comptypes (type, rhstype)) + return convert_and_check (type, rhs); + /* Conversion to a transparent union from its member types. This applies only to function arguments. */ - else if (codel == UNION_TYPE && TYPE_TRANSPARENT_UNION (type) - && (errtype == ic_argpass || errtype == ic_argpass_nonproto)) + if (codel == UNION_TYPE && TYPE_TRANSPARENT_UNION (type) + && (errtype == ic_argpass || errtype == ic_argpass_nonproto)) { tree memb, marginal_memb = NULL_TREE; @@ -3838,9 +4092,7 @@ convert_for_assignment (tree type, tree rhs, enum impl_conv errtype, } /* 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; @@ -3895,6 +4147,7 @@ convert_for_assignment (tree type, tree rhs, enum impl_conv errtype, if (pedantic && (!fundecl || !DECL_IN_SYSTEM_HEADER (fundecl))) pedwarn ("ISO C prohibits argument conversion to union type"); + rhs = fold_convert (TREE_TYPE (memb), rhs); return build_constructor_single (type, memb, rhs); } } @@ -3916,26 +4169,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: @@ -3964,7 +4217,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. */ @@ -3978,9 +4231,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 " @@ -4070,12 +4321,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 " @@ -4125,31 +4371,6 @@ convert_for_assignment (tree type, tree rhs, enum impl_conv errtype, return error_mark_node; } - -/* Convert VALUE for assignment into inlined parameter PARM. ARGNUM - is used for error and waring reporting and indicates which argument - is being processed. */ - -tree -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))) - return value; - - type = TREE_TYPE (parm); - ret = convert_for_assignment (type, value, - ic_argpass_nonproto, fn, - fn, argnum); - if (targetm.calls.promote_prototypes (TREE_TYPE (fn)) - && INTEGRAL_TYPE_P (type) - && (TYPE_PRECISION (type) < TYPE_PRECISION (integer_type_node))) - ret = default_conversion (ret); - return ret; -} /* If VALUE is a compound expr all of whose expressions are constant, then return its value. Otherwise, return error_mark_node. @@ -4205,7 +4426,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 @@ -4219,16 +4441,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); } } } @@ -4244,7 +4468,7 @@ struct spelling int kind; union { - int i; + unsigned HOST_WIDE_INT i; const char *s; } u; }; @@ -4304,7 +4528,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); } @@ -4339,7 +4563,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 @@ -4430,6 +4654,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; @@ -4510,7 +4735,7 @@ digest_init (tree type, tree init, bool strict_string, int require_constant) below and handle as a constructor. */ if (code == VECTOR_TYPE && TREE_CODE (TREE_TYPE (inside_init)) == VECTOR_TYPE - && vector_types_convertible_p (TREE_TYPE (inside_init), type) + && vector_types_convertible_p (TREE_TYPE (inside_init), type, true) && TREE_CONSTANT (inside_init)) { if (TREE_CODE (inside_init) == VECTOR_CST @@ -4574,12 +4799,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); } @@ -4627,9 +4854,9 @@ digest_init (tree type, tree init, bool strict_string, int require_constant) /* Handle scalar types, including conversions. */ - if (code == INTEGER_TYPE || code == REAL_TYPE || code == POINTER_TYPE - || code == ENUMERAL_TYPE || code == BOOLEAN_TYPE || code == COMPLEX_TYPE - || code == VECTOR_TYPE) + if (code == INTEGER_TYPE || code == REAL_TYPE || code == FIXED_POINT_TYPE + || code == POINTER_TYPE || code == ENUMERAL_TYPE || code == BOOLEAN_TYPE + || code == COMPLEX_TYPE || code == VECTOR_TYPE) { if (TREE_CODE (TREE_TYPE (init)) == ARRAY_TYPE && (TREE_CODE (init) == STRING_CST @@ -4833,7 +5060,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; @@ -5017,7 +5244,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 @@ -5134,7 +5361,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++; } @@ -5276,7 +5503,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) @@ -5377,15 +5604,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; } @@ -5599,6 +5819,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; } @@ -5620,6 +5842,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; } @@ -5893,7 +6117,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))) @@ -6092,6 +6316,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; @@ -6299,7 +6525,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; } @@ -6402,10 +6628,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. */ @@ -6529,7 +6755,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); @@ -6548,8 +6774,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"); @@ -6712,7 +6938,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; } @@ -6839,8 +7065,10 @@ c_finish_return (tree retval) else if (valtype == 0 || TREE_CODE (valtype) == VOID_TYPE) { current_function_returns_null = 1; - if (pedantic || TREE_CODE (TREE_TYPE (retval)) != VOID_TYPE) + if (TREE_CODE (TREE_TYPE (retval)) != VOID_TYPE) pedwarn ("% with a value, in function returning void"); + else if (pedantic) + pedwarn ("ISO C forbids % with expression, in function returning void"); } else { @@ -6890,7 +7118,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) @@ -6958,25 +7186,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 @@ -6985,7 +7213,6 @@ c_start_case (tree exp) "converted to % in ISO C"); exp = default_conversion (exp); - type = TREE_TYPE (exp); } } @@ -7121,36 +7348,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) - { - tree *inner_then = &then_block, *inner_else = &else_block; - - if (TREE_CODE (*inner_then) == STATEMENT_LIST - && STATEMENT_LIST_TAIL (*inner_then)) - inner_then = &STATEMENT_LIST_TAIL (*inner_then)->stmt; - if (*inner_else && TREE_CODE (*inner_else) == STATEMENT_LIST - && STATEMENT_LIST_TAIL (*inner_else)) - inner_else = &STATEMENT_LIST_TAIL (*inner_else)->stmt; - - if (TREE_CODE (*inner_then) == NOP_EXPR && !TREE_TYPE (*inner_then)) - { - if (!*inner_else) - warning (0, "%Hempty body in an if-statement", - EXPR_LOCUS (*inner_then)); - - *inner_then = alloc_stmt_list (); - } - if (*inner_else - && TREE_CODE (*inner_else) == NOP_EXPR - && !TREE_TYPE (*inner_else)) - { - warning (0, "%Hempty body in an else-statement", - EXPR_LOCUS (*inner_else)); - - *inner_else = alloc_stmt_list (); - } - } + empty_if_body_warning (then_block, else_block); stmt = build3 (COND_EXPR, void_type_node, cond, then_block, else_block); SET_EXPR_LOCATION (stmt, if_locus); @@ -7182,41 +7380,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 = fold_build3 (COND_EXPR, void_type_node, cond, exit, t); + 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) @@ -7251,13 +7449,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) @@ -7276,10 +7485,10 @@ emit_side_effect_warnings (tree expr) else if (!TREE_SIDE_EFFECTS (expr)) { if (!VOID_TYPE_P (TREE_TYPE (expr)) && !TREE_NO_WARNING (expr)) - warning (0, "%Hstatement with no effect", + warning (OPT_Wunused_value, "%Hstatement with no effect", EXPR_HAS_LOCATION (expr) ? EXPR_LOCUS (expr) : &input_location); } - else if (warn_unused_value) + else warn_if_unused_value (expr, input_location); } @@ -7304,7 +7513,7 @@ c_process_expr_stmt (tree expr) Warnings for statement expressions will be emitted later, once we figure out which is the result. */ if (!STATEMENT_LIST_STMT_EXPR (cur_stmt_list) - && (extra_warnings || warn_unused_value)) + && warn_unused_value) emit_side_effect_warnings (expr); /* If the expression is not of a type to which we cannot assign a line @@ -7312,7 +7521,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; @@ -7420,7 +7629,7 @@ c_finish_stmt_expr (tree body) /* If we're supposed to generate side effects warnings, process all of the statements except the last. */ - if (extra_warnings || warn_unused_value) + if (warn_unused_value) { for (i = tsi_start (last); !tsi_one_before_end_p (i); tsi_next (&i)) emit_side_effect_warnings (tsi_stmt (i)); @@ -7449,7 +7658,7 @@ c_finish_stmt_expr (tree body) { /* Do not warn if the return value of a statement expression is unused. */ - if (EXPR_P (last)) + if (CAN_HAVE_LOCATION_P (last)) TREE_NO_WARNING (last) = 1; return last; } @@ -7491,6 +7700,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; @@ -7753,14 +7967,13 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1, case FLOOR_DIV_EXPR: case ROUND_DIV_EXPR: case EXACT_DIV_EXPR: - /* Floating point division by zero is a legitimate way to obtain - infinities and NaNs. */ - if (skip_evaluation == 0 && integer_zerop (op1)) - warning (OPT_Wdiv_by_zero, "division by zero"); + warn_for_div_by_zero (op1); if ((code0 == INTEGER_TYPE || code0 == REAL_TYPE + || code0 == FIXED_POINT_TYPE || code0 == COMPLEX_TYPE || code0 == VECTOR_TYPE) && (code1 == INTEGER_TYPE || code1 == REAL_TYPE + || code1 == FIXED_POINT_TYPE || code1 == COMPLEX_TYPE || code1 == VECTOR_TYPE)) { enum tree_code tcode0 = code0, tcode1 = code1; @@ -7770,7 +7983,8 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1, if (code1 == COMPLEX_TYPE || code1 == VECTOR_TYPE) tcode1 = TREE_CODE (TREE_TYPE (TREE_TYPE (op1))); - if (!(tcode0 == INTEGER_TYPE && tcode1 == INTEGER_TYPE)) + if (!((tcode0 == INTEGER_TYPE && tcode1 == INTEGER_TYPE) + || (tcode0 == FIXED_POINT_TYPE && tcode1 == FIXED_POINT_TYPE))) resultcode = RDIV_EXPR; else /* Although it would be tempting to shorten always here, that @@ -7790,14 +8004,17 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1, case BIT_XOR_EXPR: if (code0 == INTEGER_TYPE && code1 == INTEGER_TYPE) shorten = -1; - else if (code0 == VECTOR_TYPE && code1 == VECTOR_TYPE) + /* Allow vector types which are not floating point types. */ + else if (code0 == VECTOR_TYPE + && code1 == VECTOR_TYPE + && !VECTOR_FLOAT_TYPE_P (type0) + && !VECTOR_FLOAT_TYPE_P (type1)) common = 1; break; case TRUNC_MOD_EXPR: case FLOOR_MOD_EXPR: - if (skip_evaluation == 0 && integer_zerop (op1)) - warning (OPT_Wdiv_by_zero, "division by zero"); + warn_for_div_by_zero (op1); if (code0 == INTEGER_TYPE && code1 == INTEGER_TYPE) { @@ -7818,9 +8035,11 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1, case TRUTH_OR_EXPR: case TRUTH_XOR_EXPR: if ((code0 == INTEGER_TYPE || code0 == POINTER_TYPE - || code0 == REAL_TYPE || code0 == COMPLEX_TYPE) + || code0 == REAL_TYPE || code0 == COMPLEX_TYPE + || code0 == FIXED_POINT_TYPE) && (code1 == INTEGER_TYPE || code1 == POINTER_TYPE - || code1 == REAL_TYPE || code1 == COMPLEX_TYPE)) + || code1 == REAL_TYPE || code1 == COMPLEX_TYPE + || code1 == FIXED_POINT_TYPE)) { /* Result of these operations is always an int, but that does not mean the operands should be @@ -7837,7 +8056,8 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1, Also set SHORT_SHIFT if shifting rightward. */ case RSHIFT_EXPR: - if (code0 == INTEGER_TYPE && code1 == INTEGER_TYPE) + if ((code0 == INTEGER_TYPE || code0 == FIXED_POINT_TYPE) + && code1 == INTEGER_TYPE) { if (TREE_CODE (op1) == INTEGER_CST && skip_evaluation == 0) { @@ -7865,7 +8085,8 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1, break; case LSHIFT_EXPR: - if (code0 == INTEGER_TYPE && code1 == INTEGER_TYPE) + if ((code0 == INTEGER_TYPE || code0 == FIXED_POINT_TYPE) + && code1 == INTEGER_TYPE) { if (TREE_CODE (op1) == INTEGER_CST && skip_evaluation == 0) { @@ -7896,9 +8117,9 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1, but don't convert the args to int! */ build_type = integer_type_node; if ((code0 == INTEGER_TYPE || code0 == REAL_TYPE - || code0 == COMPLEX_TYPE) + || code0 == FIXED_POINT_TYPE || code0 == COMPLEX_TYPE) && (code1 == INTEGER_TYPE || code1 == REAL_TYPE - || code1 == COMPLEX_TYPE)) + || code1 == FIXED_POINT_TYPE || code1 == COMPLEX_TYPE)) short_compare = 1; else if (code0 == POINTER_TYPE && code1 == POINTER_TYPE) { @@ -7913,14 +8134,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"); @@ -7933,12 +8154,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_Waddress, "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_Waddress, "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; @@ -7956,8 +8187,10 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1, case LT_EXPR: case GT_EXPR: build_type = integer_type_node; - if ((code0 == INTEGER_TYPE || code0 == REAL_TYPE) - && (code1 == INTEGER_TYPE || code1 == REAL_TYPE)) + if ((code0 == INTEGER_TYPE || code0 == REAL_TYPE + || code0 == FIXED_POINT_TYPE) + && (code1 == INTEGER_TYPE || code1 == REAL_TYPE + || code1 == FIXED_POINT_TYPE)) short_compare = 1; else if (code0 == POINTER_TYPE && code1 == POINTER_TYPE) { @@ -7977,15 +8210,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) @@ -8015,20 +8246,24 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1, || !same_scalar_type_ignoring_signedness (TREE_TYPE (type0), TREE_TYPE (type1)))) { - binary_op_error (code); + binary_op_error (code, type0, type1); return error_mark_node; } if ((code0 == INTEGER_TYPE || code0 == REAL_TYPE || code0 == COMPLEX_TYPE - || code0 == VECTOR_TYPE) + || code0 == FIXED_POINT_TYPE || code0 == VECTOR_TYPE) && (code1 == INTEGER_TYPE || code1 == REAL_TYPE || code1 == COMPLEX_TYPE - || code1 == VECTOR_TYPE)) + || code1 == FIXED_POINT_TYPE || code1 == VECTOR_TYPE)) { int none_complex = (code0 != COMPLEX_TYPE && code1 != COMPLEX_TYPE); if (shorten || common || short_compare) - result_type = c_common_type (type0, type1); + { + result_type = c_common_type (type0, type1); + if (result_type == error_mark_node) + return error_mark_node; + } /* For certain operations (which identify themselves by shorten != 0) if both args were extended from the same smaller type, @@ -8044,12 +8279,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 @@ -8093,8 +8351,9 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1, < TYPE_PRECISION (result_type)) && (type = c_common_signed_or_unsigned_type (unsigned1, - TREE_TYPE (arg1)), - int_fits_type_p (arg0, type))) + TREE_TYPE (arg1))) + && !POINTER_TYPE_P (type) + && int_fits_type_p (arg0, type)) result_type = type; else if (TREE_CODE (arg1) == INTEGER_CST && (unsigned0 || !uns) @@ -8102,8 +8361,9 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1, < TYPE_PRECISION (result_type)) && (type = c_common_signed_or_unsigned_type (unsigned0, - TREE_TYPE (arg0)), - int_fits_type_p (arg1, type))) + TREE_TYPE (arg0))) + && !POINTER_TYPE_P (type) + && int_fits_type_p (arg1, type)) result_type = type; } @@ -8182,12 +8442,13 @@ 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; + bool ovf; if (op0_signed) sop = xop0, uop = xop1; @@ -8199,7 +8460,7 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1, constant expression involving such literals or a conditional expression involving such literals) and it is non-negative. */ - if (tree_expr_nonnegative_p (sop)) + if (tree_expr_nonnegative_warnv_p (sop, &ovf)) /* OK */; /* Do not warn if the comparison is an equality operation, the unsigned quantity is an integral constant, and it @@ -8287,16 +8548,16 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1, if (!result_type) { - binary_op_error (code); + binary_op_error (code, TREE_TYPE (op0), TREE_TYPE (op1)); return error_mark_node; } 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. */ @@ -8374,3 +8635,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; +}