X-Git-Url: http://git.sourceforge.jp/view?a=blobdiff_plain;f=gcc%2Fc-typeck.c;h=35c8d232878353824b00d6b8faf2f6ba3fcd0459;hb=331ff97b3de0cf566c5c940732001deb5ccd270a;hp=2b1e965117bd2f4f5ca787c06a244ca037f6d57f;hpb=e6fa0ea601965ab7a19c55ca870bdb2cdebaf324;p=pf3gnuchains%2Fgcc-fork.git diff --git a/gcc/c-typeck.c b/gcc/c-typeck.c index 2b1e965117b..35c8d232878 100644 --- a/gcc/c-typeck.c +++ b/gcc/c-typeck.c @@ -1,13 +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, 2006, 2007 + 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 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 @@ -16,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. @@ -43,14 +42,13 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA #include "ggc.h" #include "target.h" #include "tree-iterator.h" -#include "tree-gimple.h" +#include "gimple.h" #include "tree-flow.h" /* Possible cases of implicit bad conversions. Used to select diagnostic messages in convert_for_assignment. */ enum impl_conv { ic_argpass, - ic_argpass_nonproto, ic_assign, ic_init, ic_return @@ -75,12 +73,12 @@ static int missing_braces_mentioned; static int require_constant_value; static int require_constant_elements; -static bool null_pointer_constant_p (tree); +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 int convert_arguments (int, tree *, tree, tree, tree, tree); @@ -92,26 +90,26 @@ static void push_string (const char *); static void push_member_name (tree); static int spelling_length (void); static char *print_spelling (char *); -static void warning_init (const char *); +static void warning_init (int, const char *); static tree digest_init (tree, tree, bool, int); -static void output_init_element (tree, bool, tree, tree, int); +static void output_init_element (tree, bool, tree, tree, int, bool); static void output_pending_init_elements (int); static int set_designator (int); static void push_range_stack (tree); -static void add_pending_init (tree, tree); +static void add_pending_init (tree, tree, bool); 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 (tree expr) +null_pointer_constant_p (const_tree expr) { /* This should really operate on c_expr structures, but they aren't yet available everywhere required. */ @@ -128,8 +126,8 @@ null_pointer_constant_p (tree expr) 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; @@ -162,7 +160,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; @@ -257,7 +255,7 @@ qualify_type (tree type, tree like) /* Return true iff the given tree T is a variable length array. */ bool -c_vla_type_p (tree t) +c_vla_type_p (const_tree t) { if (TREE_CODE (t) == ARRAY_TYPE && C_TYPE_VARIABLE_SIZE (t)) @@ -471,8 +469,8 @@ composite_type (tree t1, tree t2) { TREE_VALUE (n) = composite_type (TREE_TYPE (memb), TREE_VALUE (p2)); - if (pedantic) - pedwarn ("function types not truly compatible in ISO C"); + pedwarn (input_location, OPT_pedantic, + "function types not truly compatible in ISO C"); goto parm_done; } } @@ -496,8 +494,8 @@ composite_type (tree t1, tree t2) { TREE_VALUE (n) = composite_type (TREE_TYPE (memb), TREE_VALUE (p1)); - if (pedantic) - pedwarn ("function types not truly compatible in ISO C"); + pedwarn (input_location, OPT_pedantic, + "function types not truly compatible in ISO C"); goto parm_done; } } @@ -531,6 +529,7 @@ common_pointer_type (tree t1, tree t2) tree pointed_to_1, mv1; tree pointed_to_2, mv2; tree target; + unsigned target_quals; /* Save time if the two types are the same. */ @@ -558,10 +557,15 @@ common_pointer_type (tree t1, tree t2) if (TREE_CODE (mv2) != ARRAY_TYPE) mv2 = TYPE_MAIN_VARIANT (pointed_to_2); target = composite_type (mv1, mv2); - t1 = build_pointer_type (c_build_qualified_type - (target, - TYPE_QUALS (pointed_to_1) | - TYPE_QUALS (pointed_to_2))); + + /* For function types do not merge const qualifiers, but drop them + if used inconsistently. The middle-end uses these to mark const + and noreturn functions. */ + if (TREE_CODE (pointed_to_1) == FUNCTION_TYPE) + target_quals = TYPE_QUALS (pointed_to_1) & TYPE_QUALS (pointed_to_2); + else + target_quals = TYPE_QUALS (pointed_to_1) | TYPE_QUALS (pointed_to_2); + t1 = build_pointer_type (c_build_qualified_type (target, target_quals)); return build_type_attribute_variant (t1, attributes); } @@ -605,9 +609,11 @@ 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 @@ -682,6 +688,91 @@ c_common_type (tree t1, tree t2) 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)) + { + enum mode_class mclass = (enum mode_class) 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)) + { + enum mode_class mclass = (enum mode_class) 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)) @@ -783,10 +874,10 @@ comptypes (tree type1, tree type2) 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. */ @@ -947,8 +1038,8 @@ comp_target_types (tree ttl, tree ttr) mvr = TYPE_MAIN_VARIANT (mvr); val = comptypes (mvl, mvr); - if (val == 2 && pedantic) - pedwarn ("types are not quite compatible"); + if (val == 2) + pedwarn (input_location, OPT_pedantic, "types are not quite compatible"); return val; } @@ -959,7 +1050,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))) @@ -991,7 +1082,7 @@ 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 = XNEW (struct tagged_tu_seen_cache); tu->next = tagged_tu_seen_base; @@ -1024,9 +1115,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; } @@ -1038,7 +1130,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; @@ -1146,11 +1238,12 @@ tagged_types_tu_compatible_p (tree t1, tree t2) { int result; - - if (DECL_NAME (s1) == NULL - || DECL_NAME (s1) != DECL_NAME (s2)) + if (DECL_NAME (s1) != DECL_NAME (s2)) break; result = comptypes_internal (TREE_TYPE (s1), TREE_TYPE (s2)); + + if (result != 1 && !DECL_NAME (s1)) + break; if (result == 0) { tu->val = 0; @@ -1177,28 +1270,31 @@ tagged_types_tu_compatible_p (tree t1, tree t2) { bool ok = false; - 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_internal (TREE_TYPE (s1), TREE_TYPE (s2)); - if (result == 0) - { - tu->val = 0; - return 0; - } - if (result == 2) - needs_warning = true; + for (s2 = TYPE_FIELDS (t2); s2; s2 = TREE_CHAIN (s2)) + if (DECL_NAME (s1) == DECL_NAME (s2)) + { + int result; - if (TREE_CODE (s1) == FIELD_DECL - && simple_cst_equal (DECL_FIELD_BIT_OFFSET (s1), - DECL_FIELD_BIT_OFFSET (s2)) != 1) - break; + result = comptypes_internal (TREE_TYPE (s1), TREE_TYPE (s2)); + + if (result != 1 && !DECL_NAME (s1)) + continue; + if (result == 0) + { + tu->val = 0; + return 0; + } + if (result == 2) + needs_warning = true; - ok = true; + if (TREE_CODE (s1) == FIELD_DECL + && simple_cst_equal (DECL_FIELD_BIT_OFFSET (s1), + DECL_FIELD_BIT_OFFSET (s2)) != 1) break; - } + + ok = true; + break; + } if (!ok) { tu->val = 0; @@ -1252,7 +1348,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. */ @@ -1266,7 +1362,7 @@ function_types_compatible_p (tree f1, tree f2) /* 'volatile' qualifiers on a function's return type used to mean the function is noreturn. */ if (TYPE_VOLATILE (ret1) != TYPE_VOLATILE (ret2)) - pedwarn ("function return types not compatible due to %"); + pedwarn (input_location, 0, "function return types not compatible due to %"); if (TYPE_VOLATILE (ret1)) ret1 = build_qualified_type (TYPE_MAIN_VARIANT (ret1), TYPE_QUALS (ret1) & ~TYPE_QUAL_VOLATILE); @@ -1315,7 +1411,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; @@ -1416,7 +1512,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); @@ -1521,7 +1617,7 @@ array_to_pointer_conversion (tree exp) /* This way is better for a COMPONENT_REF since it can simplify the offset for a component. */ - adr = build_unary_op (ADDR_EXPR, exp, 1); + adr = build_unary_op (EXPR_LOCATION (exp), ADDR_EXPR, exp, 1); return convert (ptrtype, adr); } @@ -1538,7 +1634,7 @@ function_to_pointer_conversion (tree exp) if (TREE_NO_WARNING (orig_exp)) TREE_NO_WARNING (exp) = 1; - return build_unary_op (ADDR_EXPR, exp, 0); + return build_unary_op (EXPR_LOCATION (exp), ADDR_EXPR, exp, 0); } /* Perform the default conversion of arrays and functions to pointers. @@ -1560,8 +1656,7 @@ 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) == CONVERT_EXPR) + || CONVERT_EXPR_P (exp.value)) && TREE_TYPE (TREE_OPERAND (exp.value, 0)) == type) { if (TREE_CODE (exp.value) == NON_LVALUE_EXPR) @@ -1683,14 +1778,19 @@ default_conversion (tree exp) if (TREE_NO_WARNING (orig_exp)) TREE_NO_WARNING (exp) = 1; - if (INTEGRAL_TYPE_P (type)) - return perform_integral_promotions (exp); - if (code == VOID_TYPE) { error ("void value not ignored as it ought to be"); return error_mark_node; } + + exp = require_complete_type (exp); + if (exp == error_mark_node) + return error_mark_node; + + if (INTEGRAL_TYPE_P (type)) + return perform_integral_promotions (exp); + return exp; } @@ -1866,18 +1966,20 @@ build_component_ref (tree datum, tree component) /* Given an expression PTR for a pointer, return an expression for the value pointed to. - ERRORSTRING is the name of the operator to appear in error messages. */ + ERRORSTRING is the name of the operator to appear in error messages. + + LOC is the location to use for the generated tree. */ tree -build_indirect_ref (tree ptr, const char *errorstring) +build_indirect_ref (location_t loc, tree ptr, const char *errorstring) { tree pointer = default_conversion (ptr); tree type = TREE_TYPE (pointer); + tree ref; if (TREE_CODE (type) == POINTER_TYPE) { - if (TREE_CODE (pointer) == CONVERT_EXPR - || TREE_CODE (pointer) == NOP_EXPR + if (CONVERT_EXPR_P (pointer) || TREE_CODE (pointer) == VIEW_CONVERT_EXPR) { /* If a warning is issued, mark it to avoid duplicates from @@ -1892,21 +1994,24 @@ build_indirect_ref (tree ptr, const char *errorstring) if (TREE_CODE (pointer) == ADDR_EXPR && (TREE_TYPE (TREE_OPERAND (pointer, 0)) == TREE_TYPE (type))) - return TREE_OPERAND (pointer, 0); + { + ref = TREE_OPERAND (pointer, 0); + protected_set_expr_location (ref, loc); + return ref; + } else { tree t = TREE_TYPE (type); - tree ref; ref = build1 (INDIRECT_REF, t, pointer); if (!COMPLETE_OR_VOID_TYPE_P (t) && TREE_CODE (t) != ARRAY_TYPE) { - error ("dereferencing pointer to incomplete type"); + error_at (loc, "dereferencing pointer to incomplete type"); return error_mark_node; } if (VOID_TYPE_P (t) && skip_evaluation == 0) - warning (0, "dereferencing % pointer"); + warning_at (loc, 0, "dereferencing % pointer"); /* We *must* set TREE_READONLY when dereferencing a pointer to const, so that we get the proper error message if the result is used @@ -1919,11 +2024,13 @@ build_indirect_ref (tree ptr, const char *errorstring) TREE_SIDE_EFFECTS (ref) = TYPE_VOLATILE (t) || TREE_SIDE_EFFECTS (pointer); TREE_THIS_VOLATILE (ref) = TYPE_VOLATILE (t); + protected_set_expr_location (ref, loc); return ref; } } else if (TREE_CODE (pointer) != ERROR_MARK) - error ("invalid type argument of %qs", errorstring); + error_at (loc, + "invalid type argument of %qs (have %qT)", errorstring, type); return error_mark_node; } @@ -1934,11 +2041,14 @@ build_indirect_ref (tree ptr, const char *errorstring) If A is a variable or a member, we generate a primitive ARRAY_REF. This avoids forcing the array out of registers, and can work on arrays that are not lvalues (for example, members of structures returned - by functions). */ + by functions). + + LOC is the location to use for the returned expression. */ tree -build_array_ref (tree array, tree index) +build_array_ref (tree array, tree index, location_t loc) { + tree ret; bool swapped = false; if (TREE_TYPE (array) == error_mark_node || TREE_TYPE (index) == error_mark_node) @@ -1951,7 +2061,7 @@ build_array_ref (tree array, tree index) if (TREE_CODE (TREE_TYPE (index)) != ARRAY_TYPE && TREE_CODE (TREE_TYPE (index)) != POINTER_TYPE) { - error ("subscripted value is neither array nor pointer"); + error_at (loc, "subscripted value is neither array nor pointer"); return error_mark_node; } temp = array; @@ -1962,13 +2072,13 @@ build_array_ref (tree array, tree index) if (!INTEGRAL_TYPE_P (TREE_TYPE (index))) { - error ("array subscript is not an integer"); + error_at (loc, "array subscript is not an integer"); return error_mark_node; } if (TREE_CODE (TREE_TYPE (TREE_TYPE (array))) == FUNCTION_TYPE) { - error ("subscripted value is pointer to function"); + error_at (loc, "subscripted value is pointer to function"); return error_mark_node; } @@ -2015,14 +2125,14 @@ build_array_ref (tree array, tree index) while (TREE_CODE (foo) == COMPONENT_REF) foo = TREE_OPERAND (foo, 0); if (TREE_CODE (foo) == VAR_DECL && C_DECL_REGISTER (foo)) - pedwarn ("ISO C forbids subscripting % array"); + pedwarn (loc, OPT_pedantic, + "ISO C forbids subscripting % array"); else if (!flag_isoc99 && !lvalue_p (foo)) - pedwarn ("ISO C90 forbids subscripting non-lvalue array"); + pedwarn (loc, OPT_pedantic, + "ISO C90 forbids subscripting non-lvalue array"); } type = TREE_TYPE (TREE_TYPE (array)); - if (TREE_CODE (type) != ARRAY_TYPE) - type = TYPE_MAIN_VARIANT (type); rval = build4 (ARRAY_REF, type, array, index, NULL_TREE, NULL_TREE); /* Array ref is const/volatile if the array elements are or if the array is. */ @@ -2039,7 +2149,9 @@ build_array_ref (tree array, tree index) in an inline function. Hope it doesn't break something else. */ | TREE_THIS_VOLATILE (array)); - return require_complete_type (fold (rval)); + ret = require_complete_type (fold (rval)); + protected_set_expr_location (ret, loc); + return ret; } else { @@ -2051,8 +2163,9 @@ build_array_ref (tree array, tree index) gcc_assert (TREE_CODE (TREE_TYPE (ar)) == POINTER_TYPE); gcc_assert (TREE_CODE (TREE_TYPE (TREE_TYPE (ar))) != FUNCTION_TYPE); - return build_indirect_ref (build_binary_op (PLUS_EXPR, ar, index, 0), - "array indexing"); + return build_indirect_ref + (loc, build_binary_op (loc, PLUS_EXPR, ar, index, 0), + "array indexing"); } } @@ -2090,9 +2203,11 @@ 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) + { + TREE_USED (ref) = 1; + } if (TREE_CODE (ref) == FUNCTION_DECL && !in_alignof) { @@ -2109,7 +2224,6 @@ build_external_ref (tree id, int fun, location_t loc) used_types_insert (TREE_TYPE (ref)); ref = DECL_INITIAL (ref); TREE_CONSTANT (ref) = 1; - TREE_INVARIANT (ref) = 1; } else if (current_function_decl != 0 && !DECL_FILE_SCOPE_P (current_function_decl) @@ -2130,9 +2244,10 @@ build_external_ref (tree id, int fun, location_t loc) && 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); + && ! TREE_PUBLIC (ref) + && DECL_CONTEXT (ref) != current_function_decl) + pedwarn (loc, 0, "%qD is static but used in inline function %qD " + "which is not static", ref, current_function_decl); return ref; } @@ -2294,8 +2409,7 @@ 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 - || TREE_CODE (function) == CONVERT_EXPR) + if (CONVERT_EXPR_P (function) && TREE_CODE (tem = TREE_OPERAND (function, 0)) == ADDR_EXPR && TREE_CODE (tem = TREE_OPERAND (tem, 0)) == FUNCTION_DECL && !comptypes (fntype, TREE_TYPE (tem))) @@ -2307,11 +2421,10 @@ build_function_call (tree function, tree params) /* This situation leads to run-time undefined behavior. We can't, therefore, simply error unless we can prove that all possible executions of the program must execute the code. */ - warning (0, "function called through a non-compatible type"); - - /* We can, however, treat "undefined" any way we please. - Call abort to encourage the user to fix the program. */ - inform ("if this code is reached, the program will abort"); + if (warning (0, "function called through a non-compatible type")) + /* We can, however, treat "undefined" any way we please. + Call abort to encourage the user to fix the program. */ + inform (input_location, "if this code is reached, the program will abort"); if (VOID_TYPE_P (return_type)) return trap; @@ -2339,8 +2452,14 @@ build_function_call (tree function, tree params) if (nargs < 0) return error_mark_node; - /* Check that the arguments to the function are valid. */ + /* Check that arguments to builtin functions match the expectations. */ + if (fundecl + && DECL_BUILT_IN (fundecl) + && DECL_BUILT_IN_CLASS (fundecl) == BUILT_IN_NORMAL + && !check_builtin_function_arguments (fundecl, nargs, argarray)) + return error_mark_node; + /* Check that the arguments to the function are valid. */ check_function_arguments (TYPE_ATTRIBUTES (fntype), nargs, argarray, TYPE_ARG_TYPES (fntype)); @@ -2351,7 +2470,7 @@ build_function_call (tree function, tree params) if (TREE_CONSTANT (result) && (name == NULL_TREE || strncmp (IDENTIFIER_POINTER (name), "__builtin_", 10) != 0)) - pedwarn_init ("initializer element is not constant"); + pedwarn_init (input_location, 0, "initializer element is not constant"); } else result = fold_build_call_array (TREE_TYPE (fntype), @@ -2390,6 +2509,8 @@ convert_arguments (int nargs, tree *argarray, { tree typetail, valtail; 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 @@ -2581,8 +2702,13 @@ convert_arguments (int nargs, tree *argarray, && (TYPE_PRECISION (TREE_TYPE (val)) < TYPE_PRECISION (double_type_node)) && !DECIMAL_FLOAT_MODE_P (TYPE_MODE (TREE_TYPE (val)))) - /* Convert `float' to `double'. */ - argarray[parmnum] = convert (double_type_node, 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))) { @@ -2611,15 +2737,18 @@ convert_arguments (int nargs, tree *argarray, /* This is the entry point used by the parser to build unary operators in the input. CODE, a tree_code, specifies the unary operator, and ARG is the operand. For unary plus, the C parser currently uses - CONVERT_EXPR for code. */ + CONVERT_EXPR for code. + + LOC is the location to use for the tree generated. +*/ struct c_expr -parser_build_unary_op (enum tree_code code, struct c_expr arg) +parser_build_unary_op (enum tree_code code, struct c_expr arg, location_t loc) { struct c_expr result; - result.original_code = ERROR_MARK; - result.value = build_unary_op (code, arg.value, 0); + result.value = build_unary_op (loc, code, arg.value, 0); + result.original_code = code; if (TREE_OVERFLOW_P (result.value) && !TREE_OVERFLOW_P (arg.value)) overflow_warning (result.value); @@ -2631,29 +2760,35 @@ parser_build_unary_op (enum tree_code code, struct c_expr arg) in the input. CODE, a tree_code, specifies the binary operator, and ARG1 and ARG2 are the operands. In addition to constructing the expression, we check for operands that were written with other binary - operators in a way that is likely to confuse the user. */ + operators in a way that is likely to confuse the user. + + LOCATION is the location of the binary operator. */ struct c_expr -parser_build_binary_op (enum tree_code code, struct c_expr arg1, - struct c_expr arg2) +parser_build_binary_op (location_t location, enum tree_code code, + struct c_expr arg1, struct c_expr arg2) { struct c_expr result; enum tree_code code1 = arg1.original_code; enum tree_code code2 = arg2.original_code; - result.value = build_binary_op (code, arg1.value, arg2.value, 1); + result.value = build_binary_op (location, code, + arg1.value, arg2.value, 1); result.original_code = code; if (TREE_CODE (result.value) == ERROR_MARK) return result; + if (location != UNKNOWN_LOCATION) + protected_set_expr_location (result.value, location); + /* Check for cases such as x+y< used in subtraction"); - if (TREE_CODE (target_type) == FUNCTION_TYPE) - pedwarn ("pointer to a function used in subtraction"); - } + if (TREE_CODE (target_type) == VOID_TYPE) + pedwarn (input_location, pedantic ? OPT_pedantic : OPT_Wpointer_arith, + "pointer of type % used in subtraction"); + if (TREE_CODE (target_type) == FUNCTION_TYPE) + pedwarn (input_location, pedantic ? OPT_pedantic : OPT_Wpointer_arith, + "pointer to a function used in subtraction"); /* If the conversion to ptrdiff_type does anything like widening or converting a partial to an integral mode, we get a convert_expression @@ -2704,13 +2838,13 @@ pointer_diff (tree op0, tree op1) different mode in place.) So first try to find a common term here 'by hand'; we want to cover at least the cases that occur in legal static initializers. */ - if ((TREE_CODE (op0) == NOP_EXPR || TREE_CODE (op0) == CONVERT_EXPR) + if (CONVERT_EXPR_P (op0) && (TYPE_PRECISION (TREE_TYPE (op0)) == TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (op0, 0))))) con0 = TREE_OPERAND (op0, 0); else con0 = op0; - if ((TREE_CODE (op1) == NOP_EXPR || TREE_CODE (op1) == CONVERT_EXPR) + if (CONVERT_EXPR_P (op1) && (TYPE_PRECISION (TREE_TYPE (op1)) == TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (op1, 0))))) con1 = TREE_OPERAND (op1, 0); @@ -2745,7 +2879,8 @@ pointer_diff (tree op0, tree op1) Do not do default conversions on the minus operator in case restype is a short type. */ - op0 = build_binary_op (MINUS_EXPR, convert (restype, op0), + op0 = build_binary_op (input_location, + MINUS_EXPR, convert (restype, op0), convert (restype, op1), 0); /* This generates an error if op1 is pointer to incomplete type. */ if (!COMPLETE_OR_VOID_TYPE_P (TREE_TYPE (TREE_TYPE (orig_op1)))) @@ -2765,19 +2900,27 @@ pointer_diff (tree op0, tree op1) the default promotions (such as from short to int). For ADDR_EXPR, the default promotions are not applied; FLAG nonzero allows non-lvalues; this is only used to handle conversion of non-lvalue - arrays to pointers in C99. */ + arrays to pointers in C99. + + LOCATION is the location of the operator. */ tree -build_unary_op (enum tree_code code, tree xarg, int flag) +build_unary_op (location_t location, + enum tree_code code, tree xarg, int flag) { /* No default_conversion here. It causes trouble for ADDR_EXPR. */ tree arg = xarg; tree argtype = 0; - enum tree_code typecode = TREE_CODE (TREE_TYPE (arg)); + enum tree_code typecode; tree val; + tree ret = error_mark_node; int noconvert = flag; const char *invalid_op_diag; + if (code != ADDR_EXPR) + arg = require_complete_type (arg); + + typecode = TREE_CODE (TREE_TYPE (arg)); if (typecode == ERROR_MARK) return error_mark_node; if (typecode == ENUMERAL_TYPE || typecode == BOOLEAN_TYPE) @@ -2786,7 +2929,7 @@ build_unary_op (enum tree_code code, tree xarg, int flag) if ((invalid_op_diag = targetm.invalid_unary_op (code, TREE_TYPE (xarg)))) { - error (invalid_op_diag); + error_at (location, invalid_op_diag); return error_mark_node; } @@ -2797,10 +2940,10 @@ build_unary_op (enum tree_code code, tree xarg, int flag) is enough to prevent anybody from looking inside for associativity, but won't generate any code. */ if (!(typecode == INTEGER_TYPE || typecode == REAL_TYPE - || typecode == COMPLEX_TYPE + || typecode == FIXED_POINT_TYPE || typecode == COMPLEX_TYPE || typecode == VECTOR_TYPE)) { - error ("wrong type argument to unary plus"); + error_at (location, "wrong type argument to unary plus"); return error_mark_node; } else if (!noconvert) @@ -2810,10 +2953,10 @@ build_unary_op (enum tree_code code, tree xarg, int flag) case NEGATE_EXPR: if (!(typecode == INTEGER_TYPE || typecode == REAL_TYPE - || typecode == COMPLEX_TYPE + || typecode == FIXED_POINT_TYPE || typecode == COMPLEX_TYPE || typecode == VECTOR_TYPE)) { - error ("wrong type argument to unary minus"); + error_at (location, "wrong type argument to unary minus"); return error_mark_node; } else if (!noconvert) @@ -2821,7 +2964,10 @@ build_unary_op (enum tree_code code, tree xarg, int flag) break; case BIT_NOT_EXPR: - if (typecode == INTEGER_TYPE || typecode == VECTOR_TYPE) + /* ~ works on integer types and non float vectors. */ + if (typecode == INTEGER_TYPE + || (typecode == VECTOR_TYPE + && !VECTOR_FLOAT_TYPE_P (TREE_TYPE (arg)))) { if (!noconvert) arg = default_conversion (arg); @@ -2829,14 +2975,14 @@ build_unary_op (enum tree_code code, tree xarg, int flag) else if (typecode == COMPLEX_TYPE) { code = CONJ_EXPR; - if (pedantic) - pedwarn ("ISO C does not support %<~%> for complex conjugation"); + pedwarn (location, OPT_pedantic, + "ISO C does not support %<~%> for complex conjugation"); if (!noconvert) arg = default_conversion (arg); } else { - error ("wrong type argument to bit-complement"); + error_at (location, "wrong type argument to bit-complement"); return error_mark_node; } break; @@ -2844,7 +2990,7 @@ build_unary_op (enum tree_code code, tree xarg, int flag) case ABS_EXPR: if (!(typecode == INTEGER_TYPE || typecode == REAL_TYPE)) { - error ("wrong type argument to abs"); + error_at (location, "wrong type argument to abs"); return error_mark_node; } else if (!noconvert) @@ -2856,7 +3002,7 @@ build_unary_op (enum tree_code code, tree xarg, int flag) if (!(typecode == INTEGER_TYPE || typecode == REAL_TYPE || typecode == COMPLEX_TYPE)) { - error ("wrong type argument to conjugation"); + error_at (location, "wrong type argument to conjugation"); return error_mark_node; } else if (!noconvert) @@ -2864,31 +3010,35 @@ build_unary_op (enum tree_code code, tree xarg, int flag) break; case TRUTH_NOT_EXPR: - if (typecode != INTEGER_TYPE + if (typecode != INTEGER_TYPE && typecode != FIXED_POINT_TYPE && typecode != REAL_TYPE && typecode != POINTER_TYPE && typecode != COMPLEX_TYPE) { - error ("wrong type argument to unary exclamation mark"); + error_at (location, + "wrong type argument to unary exclamation mark"); return error_mark_node; } - arg = c_objc_common_truthvalue_conversion (arg); - return invert_truthvalue (arg); + arg = c_objc_common_truthvalue_conversion (location, arg); + ret = invert_truthvalue (arg); + goto return_build_unary_op; case REALPART_EXPR: if (TREE_CODE (arg) == COMPLEX_CST) - return TREE_REALPART (arg); + ret = TREE_REALPART (arg); else if (TREE_CODE (TREE_TYPE (arg)) == COMPLEX_TYPE) - return fold_build1 (REALPART_EXPR, TREE_TYPE (TREE_TYPE (arg)), arg); + ret = fold_build1 (REALPART_EXPR, TREE_TYPE (TREE_TYPE (arg)), arg); else - return arg; + ret = arg; + goto return_build_unary_op; case IMAGPART_EXPR: if (TREE_CODE (arg) == COMPLEX_CST) - return TREE_IMAGPART (arg); + ret = TREE_IMAGPART (arg); else if (TREE_CODE (TREE_TYPE (arg)) == COMPLEX_TYPE) - return fold_build1 (IMAGPART_EXPR, TREE_TYPE (TREE_TYPE (arg)), arg); + ret = fold_build1 (IMAGPART_EXPR, TREE_TYPE (TREE_TYPE (arg)), arg); else - return convert (TREE_TYPE (arg), integer_zero_node); + ret = omit_one_operand (TREE_TYPE (arg), integer_zero_node, arg); + goto return_build_unary_op; case PREINCREMENT_EXPR: case POSTINCREMENT_EXPR: @@ -2901,35 +3051,36 @@ build_unary_op (enum tree_code code, tree xarg, int flag) { tree real, imag; - if (pedantic) - pedwarn ("ISO C does not support %<++%> and %<--%>" - " on complex types"); + pedwarn (location, OPT_pedantic, + "ISO C does not support %<++%> and %<--%> on complex types"); arg = stabilize_reference (arg); - real = build_unary_op (REALPART_EXPR, arg, 1); - imag = build_unary_op (IMAGPART_EXPR, arg, 1); - return build2 (COMPLEX_EXPR, TREE_TYPE (arg), - build_unary_op (code, real, 1), imag); + real = build_unary_op (EXPR_LOCATION (arg), REALPART_EXPR, arg, 1); + imag = build_unary_op (EXPR_LOCATION (arg), IMAGPART_EXPR, arg, 1); + real = build_unary_op (EXPR_LOCATION (arg), code, real, 1); + if (real == error_mark_node || imag == error_mark_node) + return error_mark_node; + ret = build2 (COMPLEX_EXPR, TREE_TYPE (arg), + real, imag); + goto return_build_unary_op; } /* Report invalid types. */ - if (typecode != POINTER_TYPE + if (typecode != POINTER_TYPE && typecode != FIXED_POINT_TYPE && typecode != INTEGER_TYPE && typecode != REAL_TYPE) { if (code == PREINCREMENT_EXPR || code == POSTINCREMENT_EXPR) - error ("wrong type argument to increment"); + error_at (location, "wrong type argument to increment"); else - error ("wrong type argument to decrement"); + error_at (location, "wrong type argument to decrement"); return error_mark_node; } { tree inc; - tree result_type = TREE_TYPE (arg); - arg = get_unwidened (arg, 0); argtype = TREE_TYPE (arg); /* Compute the increment. */ @@ -2938,29 +3089,53 @@ build_unary_op (enum tree_code code, tree xarg, int flag) { /* If pointer target is an undefined struct, we just cannot know how to do the arithmetic. */ - if (!COMPLETE_OR_VOID_TYPE_P (TREE_TYPE (result_type))) + if (!COMPLETE_OR_VOID_TYPE_P (TREE_TYPE (argtype))) { if (code == PREINCREMENT_EXPR || code == POSTINCREMENT_EXPR) - error ("increment of pointer to unknown structure"); + error_at (location, + "increment of pointer to unknown structure"); else - error ("decrement of pointer to unknown structure"); + error_at (location, + "decrement of pointer to unknown structure"); } - else if ((pedantic || warn_pointer_arith) - && (TREE_CODE (TREE_TYPE (result_type)) == FUNCTION_TYPE - || TREE_CODE (TREE_TYPE (result_type)) == VOID_TYPE)) + else if (TREE_CODE (TREE_TYPE (argtype)) == FUNCTION_TYPE + || TREE_CODE (TREE_TYPE (argtype)) == VOID_TYPE) { if (code == PREINCREMENT_EXPR || code == POSTINCREMENT_EXPR) - pedwarn ("wrong type argument to increment"); + pedwarn (location, pedantic ? OPT_pedantic : OPT_Wpointer_arith, + "wrong type argument to increment"); else - pedwarn ("wrong type argument to decrement"); + pedwarn (location, pedantic ? OPT_pedantic : OPT_Wpointer_arith, + "wrong type argument to decrement"); } - inc = c_size_in_bytes (TREE_TYPE (result_type)); + inc = c_size_in_bytes (TREE_TYPE (argtype)); + inc = fold_convert (sizetype, inc); + } + else if (FRACT_MODE_P (TYPE_MODE (argtype))) + { + /* For signed fract types, we invert ++ to -- or + -- to ++, and change inc from 1 to -1, because + it is not possible to represent 1 in signed fract constants. + For unsigned fract types, the result always overflows and + we get an undefined (original) or the maximum value. */ + if (code == PREINCREMENT_EXPR) + code = PREDECREMENT_EXPR; + else if (code == PREDECREMENT_EXPR) + code = PREINCREMENT_EXPR; + else if (code == POSTINCREMENT_EXPR) + code = POSTDECREMENT_EXPR; + else /* code == POSTDECREMENT_EXPR */ + code = POSTINCREMENT_EXPR; + + inc = integer_minus_one_node; + inc = convert (argtype, inc); } else - inc = integer_one_node; - - inc = convert (argtype, inc); + { + inc = integer_one_node; + inc = convert (argtype, inc); + } /* Complain about anything else that is not a true lvalue. */ if (!lvalue_or_else (arg, ((code == PREINCREMENT_EXPR @@ -2984,10 +3159,10 @@ build_unary_op (enum tree_code code, tree xarg, int flag) else val = build2 (code, TREE_TYPE (arg), arg, inc); TREE_SIDE_EFFECTS (val) = 1; - val = convert (result_type, val); if (TREE_CODE (val) != code) TREE_NO_WARNING (val) = 1; - return val; + ret = val; + goto return_build_unary_op; } case ADDR_EXPR: @@ -2999,7 +3174,8 @@ build_unary_op (enum tree_code code, tree xarg, int flag) /* Don't let this be an lvalue. */ if (lvalue_p (TREE_OPERAND (arg, 0))) return non_lvalue (TREE_OPERAND (arg, 0)); - return TREE_OPERAND (arg, 0); + ret = TREE_OPERAND (arg, 0); + goto return_build_unary_op; } /* For &x[y], return x+y */ @@ -3008,7 +3184,7 @@ build_unary_op (enum tree_code code, tree xarg, int flag) tree op0 = TREE_OPERAND (arg, 0); if (!c_mark_addressable (op0)) return error_mark_node; - return build_binary_op (PLUS_EXPR, + return build_binary_op (location, PLUS_EXPR, (TREE_CODE (TREE_TYPE (op0)) == ARRAY_TYPE ? array_to_pointer_conversion (op0) : op0), @@ -3048,15 +3224,17 @@ build_unary_op (enum tree_code code, tree xarg, int flag) if (val && TREE_CODE (val) == INDIRECT_REF && TREE_CONSTANT (TREE_OPERAND (val, 0))) { - tree op0 = fold_convert (argtype, fold_offsetof (arg, val)), op1; + tree op0 = fold_convert (sizetype, fold_offsetof (arg, val)), op1; op1 = fold_convert (argtype, TREE_OPERAND (val, 0)); - return fold_build2 (PLUS_EXPR, argtype, op0, op1); + ret = fold_build2 (POINTER_PLUS_EXPR, argtype, op1, op0); + goto return_build_unary_op; } val = build1 (ADDR_EXPR, argtype, arg); - return val; + ret = val; + goto return_build_unary_op; default: gcc_unreachable (); @@ -3064,8 +3242,12 @@ build_unary_op (enum tree_code code, tree xarg, int flag) if (argtype == 0) argtype = TREE_TYPE (arg); - return require_constant_value ? fold_build1_initializer (code, argtype, arg) - : fold_build1 (code, argtype, arg); + ret = require_constant_value ? fold_build1_initializer (code, argtype, arg) + : fold_build1 (code, argtype, arg); + return_build_unary_op: + gcc_assert (ret != error_mark_node); + protected_set_expr_location (ret, location); + return ret; } /* Return nonzero if REF is an lvalue valid for this language. @@ -3073,9 +3255,9 @@ build_unary_op (enum tree_code code, tree xarg, int flag) Lvalues can have their address taken, unless they have C_DECL_REGISTER. */ static int -lvalue_p (tree ref) +lvalue_p (const_tree ref) { - enum tree_code code = TREE_CODE (ref); + const enum tree_code code = TREE_CODE (ref); switch (code) { @@ -3136,10 +3318,11 @@ readonly_error (tree arg, enum lvalue_use use) 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_("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); } @@ -3148,7 +3331,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); @@ -3205,7 +3388,7 @@ c_mark_addressable (tree exp) ("global register variable %qD used in nested function", x); return false; } - pedwarn ("register variable %qD used in nested function", x); + pedwarn (input_location, 0, "register variable %qD used in nested function", x); } else if (C_DECL_REGISTER (x)) { @@ -3306,14 +3489,15 @@ build_conditional_expr (tree ifexp, tree op1, tree op2) && tree_expr_nonnegative_warnv_p (op2, &ovf))) /* OK */; else - warning (0, "signed and unsigned type in conditional expression"); + warning (OPT_Wsign_compare, "signed and unsigned type in conditional expression"); } } } else if (code1 == VOID_TYPE || code2 == VOID_TYPE) { - if (pedantic && (code1 != VOID_TYPE || code2 != VOID_TYPE)) - pedwarn ("ISO C forbids conditional expr with only one void side"); + if (code1 != VOID_TYPE || code2 != VOID_TYPE) + pedwarn (input_location, OPT_pedantic, + "ISO C forbids conditional expr with only one void side"); result_type = void_type_node; } else if (code1 == POINTER_TYPE && code2 == POINTER_TYPE) @@ -3326,30 +3510,34 @@ build_conditional_expr (tree ifexp, tree op1, tree op2) result_type = qualify_type (type1, type2); else if (VOID_TYPE_P (TREE_TYPE (type1))) { - if (pedantic && TREE_CODE (TREE_TYPE (type2)) == FUNCTION_TYPE) - pedwarn ("ISO C forbids conditional expr between " + if (TREE_CODE (TREE_TYPE (type2)) == FUNCTION_TYPE) + pedwarn (input_location, OPT_pedantic, + "ISO C forbids conditional expr between " "% and function pointer"); result_type = build_pointer_type (qualify_type (TREE_TYPE (type1), TREE_TYPE (type2))); } else if (VOID_TYPE_P (TREE_TYPE (type2))) { - if (pedantic && TREE_CODE (TREE_TYPE (type1)) == FUNCTION_TYPE) - pedwarn ("ISO C forbids conditional expr between " + if (TREE_CODE (TREE_TYPE (type1)) == FUNCTION_TYPE) + pedwarn (input_location, OPT_pedantic, + "ISO C forbids conditional expr between " "% and function pointer"); result_type = build_pointer_type (qualify_type (TREE_TYPE (type2), TREE_TYPE (type1))); } else { - pedwarn ("pointer type mismatch in conditional expression"); + pedwarn (input_location, 0, + "pointer type mismatch in conditional expression"); result_type = build_pointer_type (void_type_node); } } else if (code1 == POINTER_TYPE && code2 == INTEGER_TYPE) { if (!null_pointer_constant_p (orig_op2)) - pedwarn ("pointer/integer type mismatch in conditional expression"); + pedwarn (input_location, 0, + "pointer/integer type mismatch in conditional expression"); else { op2 = null_pointer_node; @@ -3359,7 +3547,8 @@ build_conditional_expr (tree ifexp, tree op1, tree op2) else if (code2 == POINTER_TYPE && code1 == INTEGER_TYPE) { if (!null_pointer_constant_p (orig_op1)) - pedwarn ("pointer/integer type mismatch in conditional expression"); + pedwarn (input_location, 0, + "pointer/integer type mismatch in conditional expression"); else { op1 = null_pointer_node; @@ -3401,18 +3590,16 @@ 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 -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) == NOP_EXPR - || TREE_CODE (expr1) == CONVERT_EXPR)) + && CONVERT_EXPR_P (expr1)) ; /* (void) a, b */ else if (VOID_TYPE_P (TREE_TYPE (expr1)) && TREE_CODE (expr1) == COMPOUND_EXPR - && (TREE_CODE (TREE_OPERAND (expr1, 1)) == CONVERT_EXPR - || TREE_CODE (TREE_OPERAND (expr1, 1)) == NOP_EXPR)) + && CONVERT_EXPR_P (TREE_OPERAND (expr1, 1))) ; /* (void) a, (void) b, c */ else warning (OPT_Wunused_value, @@ -3463,35 +3650,40 @@ build_c_cast (tree type, tree expr) return error_mark_node; } + if (!VOID_TYPE_P (type)) + { + value = require_complete_type (value); + if (value == error_mark_node) + return error_mark_node; + } + if (type == TYPE_MAIN_VARIANT (TREE_TYPE (value))) { - if (pedantic) - { - if (TREE_CODE (type) == RECORD_TYPE - || TREE_CODE (type) == UNION_TYPE) - pedwarn ("ISO C forbids casting nonscalar to the same type"); - } + if (TREE_CODE (type) == RECORD_TYPE + || TREE_CODE (type) == UNION_TYPE) + pedwarn (input_location, OPT_pedantic, + "ISO C forbids casting nonscalar to the same type"); } else if (TREE_CODE (type) == UNION_TYPE) { tree field; for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field)) - if (comptypes (TYPE_MAIN_VARIANT (TREE_TYPE (field)), - TYPE_MAIN_VARIANT (TREE_TYPE (value)))) + if (TREE_TYPE (field) != error_mark_node + && comptypes (TYPE_MAIN_VARIANT (TREE_TYPE (field)), + TYPE_MAIN_VARIANT (TREE_TYPE (value)))) break; if (field) { tree t; - if (pedantic) - pedwarn ("ISO C forbids casts to union type"); + pedwarn (input_location, OPT_pedantic, + "ISO C forbids casts to union type"); t = digest_init (type, build_constructor_single (type, field, value), true, 0); TREE_CONSTANT (t) = TREE_CONSTANT (value); - TREE_INVARIANT (t) = TREE_INVARIANT (value); return t; } error ("cast to union type from type not present in union"); @@ -3540,12 +3732,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. */ @@ -3598,7 +3790,8 @@ build_c_cast (tree type, tree expr) && TREE_CODE (otype) == POINTER_TYPE && TREE_CODE (TREE_TYPE (otype)) == FUNCTION_TYPE && TREE_CODE (TREE_TYPE (type)) != FUNCTION_TYPE) - pedwarn ("ISO C forbids conversion of function pointer to object pointer type"); + pedwarn (input_location, OPT_pedantic, "ISO C forbids " + "conversion of function pointer to object pointer type"); if (pedantic && TREE_CODE (type) == POINTER_TYPE @@ -3606,7 +3799,8 @@ build_c_cast (tree type, tree expr) && TREE_CODE (TREE_TYPE (type)) == FUNCTION_TYPE && TREE_CODE (TREE_TYPE (otype)) != FUNCTION_TYPE && !null_pointer_constant_p (value)) - pedwarn ("ISO C forbids conversion of object pointer to function pointer type"); + pedwarn (input_location, OPT_pedantic, "ISO C forbids " + "conversion of object pointer to function pointer type"); ovalue = value; value = convert (type, value); @@ -3658,10 +3852,13 @@ c_cast_expr (struct c_type_name *type_name, tree expr) /* Build an assignment expression of lvalue LHS from value RHS. MODIFYCODE is the code for a binary operator that we use to combine the old value of LHS with RHS to get the new value. - Or else MODIFYCODE is NOP_EXPR meaning do a simple assignment. */ + Or else MODIFYCODE is NOP_EXPR meaning do a simple assignment. + + LOCATION is the location of the MODIFYCODE operator. */ tree -build_modify_expr (tree lhs, enum tree_code modifycode, tree rhs) +build_modify_expr (location_t location, + tree lhs, enum tree_code modifycode, tree rhs) { tree result; tree newrhs; @@ -3688,7 +3885,8 @@ build_modify_expr (tree lhs, enum tree_code modifycode, tree rhs) if (modifycode != NOP_EXPR) { lhs = stabilize_reference (lhs); - newrhs = build_binary_op (modifycode, lhs, rhs, 1); + newrhs = build_binary_op (location, + modifycode, lhs, rhs, 1); } /* Give an error for storing in something that is 'const'. */ @@ -3735,13 +3933,17 @@ build_modify_expr (tree lhs, enum tree_code modifycode, tree rhs) { result = objc_generate_write_barrier (lhs, modifycode, newrhs); if (result) - return result; + { + protected_set_expr_location (result, location); + return result; + } } /* Scan operands. */ result = build2 (MODIFY_EXPR, lhstype, lhs, newrhs); TREE_SIDE_EFFECTS (result) = 1; + protected_set_expr_location (result, location); /* If we got the LHS in a different type for storing in, convert the result back to the nominal type of LHS @@ -3750,8 +3952,11 @@ build_modify_expr (tree lhs, enum tree_code modifycode, tree rhs) if (olhstype == TREE_TYPE (result)) return result; - return convert_for_assignment (olhstype, result, ic_assign, - NULL_TREE, NULL_TREE, 0); + + result = convert_for_assignment (olhstype, result, ic_assign, + NULL_TREE, NULL_TREE, 0); + protected_set_expr_location (result, location); + return result; } /* Convert value RHS to type TYPE as preparation for an assignment @@ -3775,7 +3980,7 @@ convert_for_assignment (tree type, tree rhs, enum impl_conv errtype, tree rname = NULL_TREE; bool objc_ok = false; - if (errtype == ic_argpass || errtype == ic_argpass_nonproto) + if (errtype == ic_argpass) { tree selector; /* Change pointer to function to the function itself for @@ -3797,28 +4002,29 @@ convert_for_assignment (tree type, tree rhs, enum impl_conv errtype, /* This macro is used to emit diagnostics to ensure that all format strings are complete sentences, visible to gettext and checked at compile time. */ -#define WARN_FOR_ASSIGNMENT(AR, AS, IN, RE) \ - do { \ - switch (errtype) \ - { \ - case ic_argpass: \ - pedwarn (AR, parmnum, rname); \ - break; \ - case ic_argpass_nonproto: \ - warning (0, AR, parmnum, rname); \ - break; \ - case ic_assign: \ - pedwarn (AS); \ - break; \ - case ic_init: \ - pedwarn (IN); \ - break; \ - case ic_return: \ - pedwarn (RE); \ - break; \ - default: \ - gcc_unreachable (); \ - } \ +#define WARN_FOR_ASSIGNMENT(LOCATION, OPT, AR, AS, IN, RE) \ + do { \ + switch (errtype) \ + { \ + case ic_argpass: \ + if (pedwarn (LOCATION, OPT, AR, parmnum, rname)) \ + inform ((fundecl && !DECL_IS_BUILTIN (fundecl)) \ + ? DECL_SOURCE_LOCATION (fundecl) : LOCATION, \ + "expected %qT but argument is of type %qT", \ + type, rhstype); \ + break; \ + case ic_assign: \ + pedwarn (LOCATION, OPT, AS); \ + break; \ + case ic_init: \ + pedwarn (LOCATION, OPT, IN); \ + break; \ + case ic_return: \ + pedwarn (LOCATION, OPT, RE); \ + break; \ + default: \ + gcc_unreachable (); \ + } \ } while (0) STRIP_TYPE_NOPS (rhs); @@ -3872,6 +4078,9 @@ convert_for_assignment (tree type, tree rhs, enum impl_conv errtype, error ("void value not ignored as it ought to be"); return error_mark_node; } + rhs = require_complete_type (rhs); + if (rhs == error_mark_node) + return error_mark_node; /* A type converts to a reference to it. This code doesn't fully support references, it's just for the special case of va_start and va_copy. */ @@ -3904,9 +4113,11 @@ convert_for_assignment (tree type, tree rhs, enum impl_conv errtype, 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); @@ -3920,7 +4131,7 @@ convert_for_assignment (tree type, tree rhs, enum impl_conv errtype, /* Conversion to a transparent union from its member types. This applies only to function arguments. */ if (codel == UNION_TYPE && TYPE_TRANSPARENT_UNION (type) - && (errtype == ic_argpass || errtype == ic_argpass_nonproto)) + && errtype == ic_argpass) { tree memb, marginal_memb = NULL_TREE; @@ -3991,7 +4202,8 @@ convert_for_assignment (tree type, tree rhs, enum impl_conv errtype, function where an ordinary one is wanted, but not vice-versa. */ if (TYPE_QUALS (ttl) & ~TYPE_QUALS (ttr)) - WARN_FOR_ASSIGNMENT (G_("passing argument %d of %qE " + WARN_FOR_ASSIGNMENT (input_location, 0, + G_("passing argument %d of %qE " "makes qualified function " "pointer from unqualified"), G_("assignment makes qualified " @@ -4004,7 +4216,8 @@ convert_for_assignment (tree type, tree rhs, enum impl_conv errtype, "pointer from unqualified")); } else if (TYPE_QUALS (ttr) & ~TYPE_QUALS (ttl)) - WARN_FOR_ASSIGNMENT (G_("passing argument %d of %qE discards " + WARN_FOR_ASSIGNMENT (input_location, 0, + G_("passing argument %d of %qE discards " "qualifiers from pointer target type"), G_("assignment discards qualifiers " "from pointer target type"), @@ -4016,9 +4229,11 @@ convert_for_assignment (tree type, tree rhs, enum impl_conv errtype, memb = marginal_memb; } - if (pedantic && (!fundecl || !DECL_IN_SYSTEM_HEADER (fundecl))) - pedwarn ("ISO C prohibits argument conversion to union type"); + if (!fundecl || !DECL_IN_SYSTEM_HEADER (fundecl)) + pedwarn (input_location, OPT_pedantic, + "ISO C prohibits argument conversion to union type"); + rhs = fold_convert (TREE_TYPE (memb), rhs); return build_constructor_single (type, memb, rhs); } } @@ -4039,10 +4254,7 @@ convert_for_assignment (tree type, tree rhs, enum impl_conv errtype, if (TREE_CODE (mvr) != ARRAY_TYPE) mvr = TYPE_MAIN_VARIANT (mvr); /* Opaque pointers are treated like void pointers. */ - is_opaque_pointer = (targetm.vector_opaque_p (type) - || targetm.vector_opaque_p (rhstype)) - && TREE_CODE (ttl) == VECTOR_TYPE - && TREE_CODE (ttr) == VECTOR_TYPE; + is_opaque_pointer = vector_targets_convertible_p (ttl, ttr); /* C++ does not allow the implicit conversion void* -> T*. However, for the purpose of reducing the number of false positives, we @@ -4063,7 +4275,6 @@ convert_for_assignment (tree type, tree rhs, enum impl_conv errtype, switch (errtype) { case ic_argpass: - case ic_argpass_nonproto: warning (OPT_Wmissing_format_attribute, "argument %d of %qE might be " "a candidate for a format attribute", @@ -4104,7 +4315,8 @@ convert_for_assignment (tree type, tree rhs, enum impl_conv errtype, (VOID_TYPE_P (ttr) && !null_pointer_constant_p (rhs) && TREE_CODE (ttl) == FUNCTION_TYPE))) - WARN_FOR_ASSIGNMENT (G_("ISO C forbids passing argument %d of " + WARN_FOR_ASSIGNMENT (input_location, OPT_pedantic, + G_("ISO C forbids passing argument %d of " "%qE between function pointer " "and %"), G_("ISO C forbids assignment between " @@ -4124,7 +4336,8 @@ convert_for_assignment (tree type, tree rhs, enum impl_conv errtype, qualifier are acceptable if the 'volatile' has been added in by the Objective-C EH machinery. */ if (!objc_type_quals_match (ttl, ttr)) - WARN_FOR_ASSIGNMENT (G_("passing argument %d of %qE discards " + WARN_FOR_ASSIGNMENT (input_location, 0, + G_("passing argument %d of %qE discards " "qualifiers from pointer target type"), G_("assignment discards qualifiers " "from pointer target type"), @@ -4140,7 +4353,8 @@ convert_for_assignment (tree type, tree rhs, enum impl_conv errtype, ; /* If there is a mismatch, do warn. */ else if (warn_pointer_sign) - WARN_FOR_ASSIGNMENT (G_("pointer targets in passing argument " + WARN_FOR_ASSIGNMENT (input_location, OPT_Wpointer_sign, + G_("pointer targets in passing argument " "%d of %qE differ in signedness"), G_("pointer targets in assignment " "differ in signedness"), @@ -4157,7 +4371,8 @@ convert_for_assignment (tree type, tree rhs, enum impl_conv errtype, it is okay to use a const or volatile function where an ordinary one is wanted, but not vice-versa. */ if (TYPE_QUALS (ttl) & ~TYPE_QUALS (ttr)) - WARN_FOR_ASSIGNMENT (G_("passing argument %d of %qE makes " + WARN_FOR_ASSIGNMENT (input_location, 0, + G_("passing argument %d of %qE makes " "qualified function pointer " "from unqualified"), G_("assignment makes qualified function " @@ -4171,7 +4386,8 @@ convert_for_assignment (tree type, tree rhs, enum impl_conv errtype, else /* Avoid warning about the volatile ObjC EH puts on decls. */ if (!objc_ok) - WARN_FOR_ASSIGNMENT (G_("passing argument %d of %qE from " + WARN_FOR_ASSIGNMENT (input_location, 0, + G_("passing argument %d of %qE from " "incompatible pointer type"), G_("assignment from incompatible pointer type"), G_("initialization from incompatible " @@ -4193,7 +4409,8 @@ convert_for_assignment (tree type, tree rhs, enum impl_conv errtype, or one that results from arithmetic, even including a cast to integer type. */ if (!null_pointer_constant_p (rhs)) - WARN_FOR_ASSIGNMENT (G_("passing argument %d of %qE makes " + WARN_FOR_ASSIGNMENT (input_location, 0, + G_("passing argument %d of %qE makes " "pointer from integer without a cast"), G_("assignment makes pointer from integer " "without a cast"), @@ -4206,7 +4423,8 @@ convert_for_assignment (tree type, tree rhs, enum impl_conv errtype, } else if (codel == INTEGER_TYPE && coder == POINTER_TYPE) { - WARN_FOR_ASSIGNMENT (G_("passing argument %d of %qE makes integer " + WARN_FOR_ASSIGNMENT (input_location, 0, + G_("passing argument %d of %qE makes integer " "from pointer without a cast"), G_("assignment makes integer from pointer " "without a cast"), @@ -4222,19 +4440,22 @@ convert_for_assignment (tree type, tree rhs, enum impl_conv errtype, switch (errtype) { case ic_argpass: - case ic_argpass_nonproto: - /* ??? This should not be an error when inlining calls to - unprototyped functions. */ error ("incompatible type for argument %d of %qE", parmnum, rname); + inform ((fundecl && !DECL_IS_BUILTIN (fundecl)) + ? DECL_SOURCE_LOCATION (fundecl) : input_location, + "expected %qT but argument is of type %qT", type, rhstype); break; case ic_assign: - error ("incompatible types in assignment"); + error ("incompatible types when assigning to type %qT from type %qT", + type, rhstype); break; case ic_init: - error ("incompatible types in initialization"); + error ("incompatible types when initializing type %qT using type %qT", + type, rhstype); break; case ic_return: - error ("incompatible types in return"); + error ("incompatible types when returning type %qT but %qT was expected", + rhstype, type); break; default: gcc_unreachable (); @@ -4242,37 +4463,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 warning 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 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); - 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. @@ -4495,34 +4685,37 @@ error_init (const char *msgid) error ("(near initialization for %qs)", ofwhat); } -/* Issue a pedantic warning for a bad initializer component. - MSGID identifies the message. - The component name is taken from the spelling stack. */ +/* Issue a pedantic warning for a bad initializer component. OPT is + the option OPT_* (from options.h) controlling this warning or 0 if + it is unconditionally given. MSGID identifies the message. The + component name is taken from the spelling stack. */ void -pedwarn_init (const char *msgid) +pedwarn_init (location_t location, int opt, const char *msgid) { char *ofwhat; - pedwarn ("%s", _(msgid)); + pedwarn (location, opt, "%s", _(msgid)); ofwhat = print_spelling ((char *) alloca (spelling_length () + 1)); if (*ofwhat) - pedwarn ("(near initialization for %qs)", ofwhat); + pedwarn (location, opt, "(near initialization for %qs)", ofwhat); } -/* Issue a warning for a bad initializer component. - MSGID identifies the message. - The component name is taken from the spelling stack. */ +/* Issue a warning for a bad initializer component. + + OPT is the OPT_W* value corresponding to the warning option that + controls this warning. MSGID identifies the message. The + component name is taken from the spelling stack. */ static void -warning_init (const char *msgid) +warning_init (int opt, const char *msgid) { char *ofwhat; - warning (0, "%s", _(msgid)); + warning (opt, "%s", _(msgid)); ofwhat = print_spelling ((char *) alloca (spelling_length () + 1)); if (*ofwhat) - warning (0, "(near initialization for %qs)", ofwhat); + warning (opt, "(near initialization for %qs)", ofwhat); } /* If TYPE is an array type and EXPR is a parenthesized string @@ -4536,7 +4729,8 @@ maybe_warn_string_init (tree type, struct c_expr expr) && TREE_CODE (type) == ARRAY_TYPE && TREE_CODE (expr.value) == STRING_CST && expr.original_code != STRING_CST) - pedwarn_init ("array initialized from parenthesized string constant"); + pedwarn_init (input_location, OPT_pedantic, + "array initialized from parenthesized string constant"); } /* Digest the parser output INIT as an initializer for type TYPE. @@ -4579,48 +4773,58 @@ digest_init (tree type, tree init, bool strict_string, int require_constant) || typ1 == signed_char_type_node || typ1 == unsigned_char_type_node); bool wchar_array = !!comptypes (typ1, wchar_type_node); - if (char_array || wchar_array) + bool char16_array = !!comptypes (typ1, char16_type_node); + bool char32_array = !!comptypes (typ1, char32_type_node); + + if (char_array || wchar_array || char16_array || char32_array) { struct c_expr expr; - bool char_string; + tree typ2 = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (inside_init))); expr.value = inside_init; expr.original_code = (strict_string ? STRING_CST : ERROR_MARK); maybe_warn_string_init (type, expr); - char_string - = (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (inside_init))) - == char_type_node); - if (comptypes (TYPE_MAIN_VARIANT (TREE_TYPE (inside_init)), TYPE_MAIN_VARIANT (type))) return inside_init; - if (!wchar_array && !char_string) + if (char_array) { - error_init ("char-array initialized from wide string"); - return error_mark_node; + if (typ2 != char_type_node) + { + error_init ("char-array initialized from wide string"); + return error_mark_node; + } } - if (char_string && !char_array) + else { - error_init ("wchar_t-array initialized from non-wide string"); - return error_mark_node; + if (typ2 == char_type_node) + { + error_init ("wide character array initialized from non-wide " + "string"); + return error_mark_node; + } + else if (!comptypes(typ1, typ2)) + { + error_init ("wide character array initialized from " + "incompatible wide string"); + return error_mark_node; + } } TREE_TYPE (inside_init) = type; if (TYPE_DOMAIN (type) != 0 && TYPE_SIZE (type) != 0 && TREE_CODE (TYPE_SIZE (type)) == INTEGER_CST - /* Subtract 1 (or sizeof (wchar_t)) + /* Subtract the size of a single (possibly wide) character because it's ok to ignore the terminating null char that is counted in the length of the constant. */ && 0 > compare_tree_int (TYPE_SIZE_UNIT (type), TREE_STRING_LENGTH (inside_init) - - ((TYPE_PRECISION (typ1) - != TYPE_PRECISION (char_type_node)) - ? (TYPE_PRECISION (wchar_type_node) - / BITS_PER_UNIT) - : 1))) - pedwarn_init ("initializer-string for array of chars is too long"); + - (TYPE_PRECISION (typ1) + / BITS_PER_UNIT))) + pedwarn_init (input_location, 0, + "initializer-string for array of chars is too long"); return inside_init; } @@ -4666,6 +4870,9 @@ digest_init (tree type, tree init, bool strict_string, int require_constant) } } + if (warn_sequence_point) + verify_sequence_points (inside_init); + /* Any type can be initialized from an expression of the same type, optionally with braces. */ @@ -4735,7 +4942,8 @@ digest_init (tree type, tree init, bool strict_string, int require_constant) if (inside_init == error_mark_node) error_init ("initializer element is not constant"); else - pedwarn_init ("initializer element is not constant"); + pedwarn_init (input_location, OPT_pedantic, + "initializer element is not constant"); if (flag_pedantic_errors) inside_init = error_mark_node; } @@ -4756,9 +4964,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 @@ -5181,12 +5389,12 @@ push_init_level (int implicit) if ((TREE_CODE (constructor_type) == RECORD_TYPE || TREE_CODE (constructor_type) == UNION_TYPE) && constructor_fields == 0) - process_init_element (pop_init_level (1)); + process_init_element (pop_init_level (1), true); else if (TREE_CODE (constructor_type) == ARRAY_TYPE && constructor_max_index && tree_int_cst_lt (constructor_max_index, constructor_index)) - process_init_element (pop_init_level (1)); + process_init_element (pop_init_level (1), true); else break; } @@ -5289,7 +5497,7 @@ push_init_level (int implicit) if (implicit == 1 && warn_missing_braces && !missing_braces_mentioned) { missing_braces_mentioned = 1; - warning_init ("missing braces around initializer"); + warning_init (OPT_Wmissing_braces, "missing braces around initializer"); } if (TREE_CODE (constructor_type) == RECORD_TYPE @@ -5350,7 +5558,7 @@ push_init_level (int implicit) else { if (constructor_type != error_mark_node) - warning_init ("braces around scalar initializer"); + warning_init (0, "braces around scalar initializer"); constructor_fields = constructor_type; constructor_unfilled_fields = constructor_type; } @@ -5380,7 +5588,7 @@ pop_init_level (int implicit) /* When we come to an explicit close brace, pop any inner levels that didn't have explicit braces. */ while (constructor_stack->implicit) - process_init_element (pop_init_level (1)); + process_init_element (pop_init_level (1), true); gcc_assert (!constructor_range_stack); } @@ -5408,8 +5616,9 @@ pop_init_level (int implicit) if (constructor_depth > 2) error_init ("initialization of flexible array member in a nested context"); - else if (pedantic) - pedwarn_init ("initialization of a flexible array member"); + else + pedwarn_init (input_location, OPT_pedantic, + "initialization of a flexible array member"); /* We have already issued an error message for the existence of a flexible array member not at the end of the structure. @@ -5436,7 +5645,8 @@ pop_init_level (int implicit) if (constructor_unfilled_fields && !constructor_designated) { push_member_name (constructor_unfilled_fields); - warning_init ("missing initializer"); + warning_init (OPT_Wmissing_field_initializers, + "missing initializer"); RESTORE_SPELLING_DEPTH (constructor_depth); } } @@ -5478,7 +5688,7 @@ pop_init_level (int implicit) ret.value = build_constructor (constructor_type, constructor_elements); if (constructor_constant) - TREE_CONSTANT (ret.value) = TREE_INVARIANT (ret.value) = 1; + TREE_CONSTANT (ret.value) = 1; if (constructor_constant && constructor_simple) TREE_STATIC (ret.value) = 1; } @@ -5537,7 +5747,7 @@ set_designator (int array) /* Designator list starts at the level of closest explicit braces. */ while (constructor_stack->implicit) - process_init_element (pop_init_level (1)); + process_init_element (pop_init_level (1), true); constructor_designated = 1; return 0; } @@ -5698,10 +5908,15 @@ set_init_label (tree fieldname) /* Add a new initializer to the tree of pending initializers. PURPOSE identifies the initializer, either array index or field in a structure. - VALUE is the value of that index or field. */ + VALUE is the value of that index or field. + + IMPLICIT is true if value comes from pop_init_level (1), + the new initializer has been merged with the existing one + and thus no warnings should be emitted about overriding an + existing initializer. */ static void -add_pending_init (tree purpose, tree value) +add_pending_init (tree purpose, tree value, bool implicit) { struct init_node *p, **q, *r; @@ -5719,10 +5934,13 @@ add_pending_init (tree purpose, tree value) q = &p->right; else { - if (TREE_SIDE_EFFECTS (p->value)) - warning_init ("initialized field with side-effects overwritten"); - else if (warn_override_init) - warning_init ("initialized field overwritten"); + if (!implicit) + { + if (TREE_SIDE_EFFECTS (p->value)) + warning_init (0, "initialized field with side-effects overwritten"); + else if (warn_override_init) + warning_init (OPT_Woverride_init, "initialized field overwritten"); + } p->value = value; return; } @@ -5742,10 +5960,13 @@ add_pending_init (tree purpose, tree value) q = &p->right; else { - if (TREE_SIDE_EFFECTS (p->value)) - warning_init ("initialized field with side-effects overwritten"); - else if (warn_override_init) - warning_init ("initialized field overwritten"); + if (!implicit) + { + if (TREE_SIDE_EFFECTS (p->value)) + warning_init (0, "initialized field with side-effects overwritten"); + else if (warn_override_init) + warning_init (OPT_Woverride_init, "initialized field overwritten"); + } p->value = value; return; } @@ -5930,7 +6151,7 @@ set_nonincremental_init (void) return; FOR_EACH_CONSTRUCTOR_ELT (constructor_elements, ix, index, value) - add_pending_init (index, value); + add_pending_init (index, value, false); constructor_elements = 0; if (TREE_CODE (constructor_type) == RECORD_TYPE) { @@ -5966,15 +6187,7 @@ set_nonincremental_init_from_string (tree str) gcc_assert (TREE_CODE (constructor_type) == ARRAY_TYPE); - if (TYPE_PRECISION (TREE_TYPE (TREE_TYPE (str))) - == TYPE_PRECISION (char_type_node)) - wchar_bytes = 1; - else - { - gcc_assert (TYPE_PRECISION (TREE_TYPE (TREE_TYPE (str))) - == TYPE_PRECISION (wchar_type_node)); - wchar_bytes = TYPE_PRECISION (wchar_type_node) / BITS_PER_UNIT; - } + wchar_bytes = TYPE_PRECISION (TREE_TYPE (TREE_TYPE (str))) / BITS_PER_UNIT; charwidth = TYPE_PRECISION (char_type_node); type = TREE_TYPE (constructor_type); p = TREE_STRING_POINTER (str); @@ -6028,7 +6241,7 @@ set_nonincremental_init_from_string (tree str) } value = build_int_cst_wide (type, val[1], val[0]); - add_pending_init (purpose, value); + add_pending_init (purpose, value, false); } constructor_incremental = 0; @@ -6101,11 +6314,16 @@ find_init_member (tree field) PENDING if non-nil means output pending elements that belong right after this element. (PENDING is normally 1; - it is 0 while outputting pending elements, to avoid recursion.) */ + it is 0 while outputting pending elements, to avoid recursion.) + + IMPLICIT is true if value comes from pop_init_level (1), + the new initializer has been merged with the existing one + and thus no warnings should be emitted about overriding an + existing initializer. */ static void output_init_element (tree value, bool strict_string, tree type, tree field, - int pending) + int pending, bool implicit) { constructor_elt *celt; @@ -6153,7 +6371,8 @@ output_init_element (tree value, bool strict_string, tree type, tree field, value = error_mark_node; } else if (require_constant_elements) - pedwarn ("initializer element is not computable at load time"); + pedwarn (input_location, 0, + "initializer element is not computable at load time"); } /* If this field is empty (and not at the end of structure), @@ -6183,7 +6402,7 @@ output_init_element (tree value, bool strict_string, tree type, tree field, && tree_int_cst_lt (field, constructor_unfilled_index)) set_nonincremental_init (); - add_pending_init (field, value); + add_pending_init (field, value, implicit); return; } else if (TREE_CODE (constructor_type) == RECORD_TYPE @@ -6209,17 +6428,21 @@ output_init_element (tree value, bool strict_string, tree type, tree field, } } - add_pending_init (field, value); + add_pending_init (field, value, implicit); return; } else if (TREE_CODE (constructor_type) == UNION_TYPE && !VEC_empty (constructor_elt, constructor_elements)) { - if (TREE_SIDE_EFFECTS (VEC_last (constructor_elt, - constructor_elements)->value)) - warning_init ("initialized field with side-effects overwritten"); - else if (warn_override_init) - warning_init ("initialized field overwritten"); + if (!implicit) + { + if (TREE_SIDE_EFFECTS (VEC_last (constructor_elt, + constructor_elements)->value)) + warning_init (0, + "initialized field with side-effects overwritten"); + else if (warn_override_init) + warning_init (OPT_Woverride_init, "initialized field overwritten"); + } /* We can have just one union field set. */ constructor_elements = 0; @@ -6290,7 +6513,7 @@ output_pending_init_elements (int all) constructor_unfilled_index)) output_init_element (elt->value, true, TREE_TYPE (constructor_type), - constructor_unfilled_index, 0); + constructor_unfilled_index, 0, false); else if (tree_int_cst_lt (constructor_unfilled_index, elt->purpose)) { @@ -6343,7 +6566,7 @@ output_pending_init_elements (int all) { constructor_unfilled_fields = elt->purpose; output_init_element (elt->value, true, TREE_TYPE (elt->purpose), - elt->purpose, 0); + elt->purpose, 0, false); } else if (tree_int_cst_lt (ctor_unfilled_bitpos, elt_bitpos)) { @@ -6406,10 +6629,15 @@ output_pending_init_elements (int all) to handle a partly-braced initializer. Once this has found the correct level for the new element, - it calls output_init_element. */ + it calls output_init_element. + + IMPLICIT is true if value comes from pop_init_level (1), + the new initializer has been merged with the existing one + and thus no warnings should be emitted about overriding an + existing initializer. */ void -process_init_element (struct c_expr value) +process_init_element (struct c_expr value, bool implicit) { tree orig_value = value.value; int string_flag = orig_value != 0 && TREE_CODE (orig_value) == STRING_CST; @@ -6450,12 +6678,12 @@ process_init_element (struct c_expr value) if ((TREE_CODE (constructor_type) == RECORD_TYPE || TREE_CODE (constructor_type) == UNION_TYPE) && constructor_fields == 0) - process_init_element (pop_init_level (1)); + process_init_element (pop_init_level (1), true); else if (TREE_CODE (constructor_type) == ARRAY_TYPE && (constructor_max_index == 0 || tree_int_cst_lt (constructor_max_index, constructor_index))) - process_init_element (pop_init_level (1)); + process_init_element (pop_init_level (1), true); else break; } @@ -6480,7 +6708,8 @@ process_init_element (struct c_expr value) if (constructor_fields == 0) { - pedwarn_init ("excess elements in struct initializer"); + pedwarn_init (input_location, 0, + "excess elements in struct initializer"); break; } @@ -6521,7 +6750,7 @@ process_init_element (struct c_expr value) { push_member_name (constructor_fields); output_init_element (value.value, strict_string, - fieldtype, constructor_fields, 1); + fieldtype, constructor_fields, 1, implicit); RESTORE_SPELLING_DEPTH (constructor_depth); } else @@ -6563,7 +6792,8 @@ process_init_element (struct c_expr value) if (constructor_fields == 0) { - pedwarn_init ("excess elements in union initializer"); + pedwarn_init (input_location, 0, + "excess elements in union initializer"); break; } @@ -6610,7 +6840,7 @@ process_init_element (struct c_expr value) { push_member_name (constructor_fields); output_init_element (value.value, strict_string, - fieldtype, constructor_fields, 1); + fieldtype, constructor_fields, 1, implicit); RESTORE_SPELLING_DEPTH (constructor_depth); } else @@ -6650,7 +6880,8 @@ process_init_element (struct c_expr value) && (tree_int_cst_lt (constructor_max_index, constructor_index) || integer_all_onesp (constructor_max_index))) { - pedwarn_init ("excess elements in array initializer"); + pedwarn_init (input_location, 0, + "excess elements in array initializer"); break; } @@ -6659,7 +6890,7 @@ process_init_element (struct c_expr value) { push_array_bounds (tree_low_cst (constructor_index, 1)); output_init_element (value.value, strict_string, - elttype, constructor_index, 1); + elttype, constructor_index, 1, implicit); RESTORE_SPELLING_DEPTH (constructor_depth); } @@ -6680,14 +6911,15 @@ process_init_element (struct c_expr value) 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"); + pedwarn_init (input_location, 0, + "excess elements in vector initializer"); break; } /* Now output the actual element. */ if (value.value) output_init_element (value.value, strict_string, - elttype, constructor_index, 1); + elttype, constructor_index, 1, implicit); constructor_index = size_binop (PLUS_EXPR, constructor_index, bitsize_one_node); @@ -6704,14 +6936,15 @@ process_init_element (struct c_expr value) else if (constructor_type != error_mark_node && constructor_fields == 0) { - pedwarn_init ("excess elements in scalar initializer"); + pedwarn_init (input_location, 0, + "excess elements in scalar initializer"); break; } else { if (value.value) output_init_element (value.value, strict_string, - constructor_type, NULL_TREE, 1); + constructor_type, NULL_TREE, 1, implicit); constructor_fields = 0; } @@ -6727,14 +6960,14 @@ process_init_element (struct c_expr value) while (constructor_stack != range_stack->stack) { gcc_assert (constructor_stack->implicit); - process_init_element (pop_init_level (1)); + process_init_element (pop_init_level (1), true); } for (p = range_stack; !p->range_end || tree_int_cst_equal (p->index, p->range_end); p = p->prev) { gcc_assert (constructor_stack->implicit); - process_init_element (pop_init_level (1)); + process_init_element (pop_init_level (1), true); } p->index = size_binop (PLUS_EXPR, p->index, bitsize_one_node); @@ -6935,8 +7168,7 @@ c_finish_goto_label (tree label) tree c_finish_goto_ptr (tree expr) { - if (pedantic) - pedwarn ("ISO C forbids %"); + pedwarn (input_location, OPT_pedantic, "ISO C forbids %"); expr = convert (ptr_type_node, expr); return add_stmt (build1 (GOTO_EXPR, void_type_node, expr)); } @@ -6959,7 +7191,8 @@ c_finish_return (tree retval) if ((warn_return_type || flag_isoc99) && valtype != 0 && TREE_CODE (valtype) != VOID_TYPE) { - pedwarn_c99 ("% with no value, in " + pedwarn_c99 (input_location, flag_isoc99 ? 0 : OPT_Wreturn_type, + "% with no value, in " "function returning non-void"); no_warning = true; } @@ -6968,9 +7201,11 @@ c_finish_return (tree retval) { current_function_returns_null = 1; 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"); + pedwarn (input_location, 0, + "% with a value, in function returning void"); + else + pedwarn (input_location, OPT_pedantic, "ISO C forbids " + "% with expression, in function returning void"); } else { @@ -6991,7 +7226,7 @@ c_finish_return (tree retval) { switch (TREE_CODE (inner)) { - case NOP_EXPR: case NON_LVALUE_EXPR: case CONVERT_EXPR: + CASE_CONVERT: case NON_LVALUE_EXPR: case PLUS_EXPR: inner = TREE_OPERAND (inner, 0); continue; @@ -7004,9 +7239,8 @@ c_finish_return (tree retval) tree op1 = TREE_OPERAND (inner, 1); while (!POINTER_TYPE_P (TREE_TYPE (op1)) - && (TREE_CODE (op1) == NOP_EXPR - || TREE_CODE (op1) == NON_LVALUE_EXPR - || TREE_CODE (op1) == CONVERT_EXPR)) + && (CONVERT_EXPR_P (op1) + || TREE_CODE (op1) == NON_LVALUE_EXPR)) op1 = TREE_OPERAND (op1, 0); if (POINTER_TYPE_P (TREE_TYPE (op1))) @@ -7038,6 +7272,9 @@ c_finish_return (tree retval) } retval = build2 (MODIFY_EXPR, TREE_TYPE (res), res, t); + + if (warn_sequence_point) + verify_sequence_points (retval); } ret_stmt = build_stmt (RETURN_EXPR, retval); @@ -7115,6 +7352,9 @@ c_start_case (tree exp) "converted to % in ISO C"); exp = default_conversion (exp); + + if (warn_sequence_point) + verify_sequence_points (exp); } } @@ -7250,8 +7490,6 @@ c_finish_if_stmt (location_t if_locus, tree cond, tree then_block, &if_locus); } - 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); add_stmt (stmt); @@ -7374,6 +7612,9 @@ c_finish_bc_stmt (tree *label_p, bool is_break) if (skip) return NULL_TREE; + if (!is_break) + add_stmt (build_predict_expr (PRED_CONTINUE, NOT_TAKEN)); + return add_stmt (build1 (GOTO_EXPR, void_type_node, label)); } @@ -7730,6 +7971,7 @@ push_cleanup (tree ARG_UNUSED (decl), tree cleanup, bool eh_only) /* Build a binary-operation expression without default conversions. CODE is the kind of expression to build. + LOCATION is the operator's location. This function differs from `build' in several ways: the data type of the result is computed and recorded in it, warnings are generated if arg data types are invalid, @@ -7744,12 +7986,13 @@ push_cleanup (tree ARG_UNUSED (decl), tree cleanup, bool eh_only) the arithmetic is to be done. */ tree -build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1, - int convert_p) +build_binary_op (location_t location, enum tree_code code, + tree orig_op0, tree orig_op1, int convert_p) { tree type0, type1; enum tree_code code0, code1; tree op0, op1; + tree ret = error_mark_node; const char *invalid_op_diag; /* Expression code to give to the expression when it is built. @@ -7797,6 +8040,9 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1, /* True means types are compatible as far as ObjC is concerned. */ bool objc_ok; + if (location == UNKNOWN_LOCATION) + location = input_location; + if (convert_p) { op0 = default_conversion (orig_op0); @@ -7829,7 +8075,7 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1, if ((invalid_op_diag = targetm.invalid_binary_op (code, type0, type1))) { - error (invalid_op_diag); + error_at (location, invalid_op_diag); return error_mark_node; } @@ -7840,9 +8086,15 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1, case PLUS_EXPR: /* Handle the pointer + int case. */ if (code0 == POINTER_TYPE && code1 == INTEGER_TYPE) - return pointer_int_sum (PLUS_EXPR, op0, op1); + { + ret = pointer_int_sum (PLUS_EXPR, op0, op1); + goto return_build_binary_op; + } else if (code1 == POINTER_TYPE && code0 == INTEGER_TYPE) - return pointer_int_sum (PLUS_EXPR, op1, op0); + { + ret = pointer_int_sum (PLUS_EXPR, op1, op0); + goto return_build_binary_op; + } else common = 1; break; @@ -7852,10 +8104,16 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1, We must subtract them as integers, then divide by object size. */ if (code0 == POINTER_TYPE && code1 == POINTER_TYPE && comp_target_types (type0, type1)) - return pointer_diff (op0, op1); + { + ret = pointer_diff (op0, op1); + goto return_build_binary_op; + } /* Handle pointer minus int. Just like pointer plus int. */ else if (code0 == POINTER_TYPE && code1 == INTEGER_TYPE) - return pointer_int_sum (MINUS_EXPR, op0, op1); + { + ret = pointer_int_sum (MINUS_EXPR, op0, op1); + goto return_build_binary_op; + } else common = 1; break; @@ -7869,11 +8127,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: - warn_for_div_by_zero (op1); + warn_for_div_by_zero (location, 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; @@ -7883,7 +8143,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 @@ -7903,13 +8164,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: - warn_for_div_by_zero (op1); + warn_for_div_by_zero (location, op1); if (code0 == INTEGER_TYPE && code1 == INTEGER_TYPE) { @@ -7930,16 +8195,18 @@ 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 converted to ints! */ result_type = integer_type_node; - op0 = c_common_truthvalue_conversion (op0); - op1 = c_common_truthvalue_conversion (op1); + op0 = c_common_truthvalue_conversion (location, op0); + op1 = c_common_truthvalue_conversion (location, op1); converted = 1; } break; @@ -7949,7 +8216,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) { @@ -7977,7 +8245,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) { @@ -8001,16 +8270,17 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1, case EQ_EXPR: case NE_EXPR: - if (code0 == REAL_TYPE || code1 == REAL_TYPE) - warning (OPT_Wfloat_equal, - "comparing floating point with == or != is unsafe"); + if (FLOAT_TYPE_P (type0) || FLOAT_TYPE_P (type1)) + warning_at (location, + OPT_Wfloat_equal, + "comparing floating point with == or != is unsafe"); /* Result of comparison is always int, but don't convert the args to int! */ build_type = integer_type_node; 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) { @@ -8027,20 +8297,21 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1, whose value is 0 but which isn't a valid null ptr const. */ if (pedantic && !null_pointer_constant_p (orig_op0) && TREE_CODE (tt1) == FUNCTION_TYPE) - pedwarn ("ISO C forbids comparison of %" - " with function pointer"); + pedwarn (location, OPT_pedantic, "ISO C forbids " + "comparison of % with function pointer"); } else if (VOID_TYPE_P (tt1)) { if (pedantic && !null_pointer_constant_p (orig_op1) && TREE_CODE (tt0) == FUNCTION_TYPE) - pedwarn ("ISO C forbids comparison of %" - " with function pointer"); + pedwarn (location, OPT_pedantic, "ISO C forbids " + "comparison of % with function pointer"); } else /* Avoid warning about the volatile ObjC EH puts on decls. */ if (!objc_ok) - pedwarn ("comparison of distinct pointer types lacks a cast"); + pedwarn (location, 0, + "comparison of distinct pointer types lacks a cast"); if (result_type == NULL_TREE) result_type = ptr_type_node; @@ -8049,27 +8320,29 @@ build_binary_op (enum tree_code code, tree orig_op0, tree 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)); + warning_at (location, + 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)); + warning_at (location, + 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; - pedwarn ("comparison between pointer and integer"); + pedwarn (location, 0, "comparison between pointer and integer"); } else if (code0 == INTEGER_TYPE && code1 == POINTER_TYPE) { result_type = type1; - pedwarn ("comparison between pointer and integer"); + pedwarn (location, 0, "comparison between pointer and integer"); } break; @@ -8078,8 +8351,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) { @@ -8088,38 +8363,44 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1, result_type = common_pointer_type (type0, type1); if (!COMPLETE_TYPE_P (TREE_TYPE (type0)) != !COMPLETE_TYPE_P (TREE_TYPE (type1))) - pedwarn ("comparison of complete and incomplete pointers"); - else if (pedantic - && TREE_CODE (TREE_TYPE (type0)) == FUNCTION_TYPE) - pedwarn ("ISO C forbids ordered comparisons of pointers to functions"); + pedwarn (location, 0, + "comparison of complete and incomplete pointers"); + else if (TREE_CODE (TREE_TYPE (type0)) == FUNCTION_TYPE) + pedwarn (location, OPT_pedantic, "ISO C forbids " + "ordered comparisons of pointers to functions"); } else { result_type = ptr_type_node; - pedwarn ("comparison of distinct pointer types lacks a cast"); + pedwarn (location, 0, + "comparison of distinct pointer types lacks a cast"); } } 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"); + if (pedantic) + pedwarn (location, OPT_pedantic, + "ordered comparison of pointer with integer zero"); + else if (extra_warnings) + warning_at (location, OPT_Wextra, + "ordered comparison of pointer with integer zero"); } else if (code1 == POINTER_TYPE && null_pointer_constant_p (orig_op0)) { result_type = type1; - if (pedantic) - pedwarn ("ordered comparison of pointer with integer zero"); + pedwarn (location, OPT_pedantic, + "ordered comparison of pointer with integer zero"); } else if (code0 == POINTER_TYPE && code1 == INTEGER_TYPE) { result_type = type0; - pedwarn ("comparison between pointer and integer"); + pedwarn (location, 0, "comparison between pointer and integer"); } else if (code0 == INTEGER_TYPE && code1 == POINTER_TYPE) { result_type = type1; - pedwarn ("comparison between pointer and integer"); + pedwarn (location, 0, "comparison between pointer and integer"); } break; @@ -8135,20 +8416,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 (location, 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, @@ -8163,91 +8448,9 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1, if (shorten && none_complex) { - int unsigned0, unsigned1; - 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 - but it *requires* conversion to FINAL_TYPE. */ - - if ((TYPE_PRECISION (TREE_TYPE (op0)) - == TYPE_PRECISION (TREE_TYPE (arg0))) - && TREE_TYPE (op0) != final_type) - unsigned0 = TYPE_UNSIGNED (TREE_TYPE (op0)); - if ((TYPE_PRECISION (TREE_TYPE (op1)) - == TYPE_PRECISION (TREE_TYPE (arg1))) - && TREE_TYPE (op1) != final_type) - unsigned1 = TYPE_UNSIGNED (TREE_TYPE (op1)); - - /* Now UNSIGNED0 is 1 if ARG0 zero-extends to FINAL_TYPE. */ - - /* For bitwise operations, signedness of nominal type - does not matter. Consider only how operands were extended. */ - if (shorten == -1) - uns = unsigned0; - - /* Note that in all three cases below we refrain from optimizing - an unsigned operation on sign-extended args. - That would not be valid. */ - - /* Both args variable: if both extended in same way - from same width, do it in that width. - Do it unsigned if args were zero-extended. */ - if ((TYPE_PRECISION (TREE_TYPE (arg0)) - < TYPE_PRECISION (result_type)) - && (TYPE_PRECISION (TREE_TYPE (arg1)) - == TYPE_PRECISION (TREE_TYPE (arg0))) - && unsigned0 == unsigned1 - && (unsigned0 || !uns)) - result_type - = c_common_signed_or_unsigned_type - (unsigned0, common_type (TREE_TYPE (arg0), TREE_TYPE (arg1))); - else if (TREE_CODE (arg0) == INTEGER_CST - && (unsigned1 || !uns) - && (TYPE_PRECISION (TREE_TYPE (arg1)) - < TYPE_PRECISION (result_type)) - && (type - = c_common_signed_or_unsigned_type (unsigned1, - TREE_TYPE (arg1)), - int_fits_type_p (arg0, type))) - result_type = type; - else if (TREE_CODE (arg1) == INTEGER_CST - && (unsigned0 || !uns) - && (TYPE_PRECISION (TREE_TYPE (arg0)) - < TYPE_PRECISION (result_type)) - && (type - = c_common_signed_or_unsigned_type (unsigned0, - TREE_TYPE (arg0)), - int_fits_type_p (arg1, type))) - result_type = type; + result_type = shorten_binary_op (result_type, op0, op1, + shorten == -1); } /* Shifts can be shortened if shifting right. */ @@ -8295,130 +8498,19 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1, = shorten_compare (&xop0, &xop1, &xresult_type, &xresultcode); if (val != 0) - return val; + { + ret = val; + goto return_build_binary_op; + } op0 = xop0, op1 = xop1; converted = 1; resultcode = xresultcode; - if (warn_sign_compare && skip_evaluation == 0) - { - int op0_signed = !TYPE_UNSIGNED (TREE_TYPE (orig_op0)); - int op1_signed = !TYPE_UNSIGNED (TREE_TYPE (orig_op1)); - int unsignedp0, unsignedp1; - tree primop0 = get_narrower (op0, &unsignedp0); - tree primop1 = get_narrower (op1, &unsignedp1); - - xop0 = orig_op0; - xop1 = orig_op1; - STRIP_TYPE_NOPS (xop0); - STRIP_TYPE_NOPS (xop1); - - /* Give warnings for comparisons between signed and unsigned - quantities that may fail. - - Do the checking based on the original operand trees, so that - casts will be considered, but default promotions won't be. - - Do not warn if the comparison is being done in a signed type, - since the signed type will only be chosen if it can represent - all the values of the unsigned type. */ - if (!TYPE_UNSIGNED (result_type)) - /* 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; - else - sop = xop1, uop = xop0; - - /* Do not warn if the signed quantity is an - unsuffixed integer literal (or some static - constant expression involving such literals or a - conditional expression involving such literals) - and it is non-negative. */ - 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 - would fit in the result if the result were signed. */ - else if (TREE_CODE (uop) == INTEGER_CST - && (resultcode == EQ_EXPR || resultcode == NE_EXPR) - && int_fits_type_p - (uop, c_common_signed_type (result_type))) - /* OK */; - /* Do not warn if the unsigned quantity is an enumeration - constant and its maximum value would fit in the result - if the result were signed. */ - else if (TREE_CODE (uop) == INTEGER_CST - && TREE_CODE (TREE_TYPE (uop)) == ENUMERAL_TYPE - && int_fits_type_p - (TYPE_MAX_VALUE (TREE_TYPE (uop)), - c_common_signed_type (result_type))) - /* OK */; - else - warning (0, "comparison between signed and unsigned"); - } - - /* Warn if two unsigned values are being compared in a size - larger than their original size, and one (and only one) is the - result of a `~' operator. This comparison will always fail. - - Also warn if one operand is a constant, and the constant - does not have all bits set that are set in the ~ operand - when it is extended. */ - - if ((TREE_CODE (primop0) == BIT_NOT_EXPR) - != (TREE_CODE (primop1) == BIT_NOT_EXPR)) - { - if (TREE_CODE (primop0) == BIT_NOT_EXPR) - primop0 = get_narrower (TREE_OPERAND (primop0, 0), - &unsignedp0); - else - primop1 = get_narrower (TREE_OPERAND (primop1, 0), - &unsignedp1); - - if (host_integerp (primop0, 0) || host_integerp (primop1, 0)) - { - tree primop; - HOST_WIDE_INT constant, mask; - int unsignedp, bits; - - if (host_integerp (primop0, 0)) - { - primop = primop1; - unsignedp = unsignedp1; - constant = tree_low_cst (primop0, 0); - } - else - { - primop = primop0; - unsignedp = unsignedp0; - constant = tree_low_cst (primop1, 0); - } - - bits = TYPE_PRECISION (TREE_TYPE (primop)); - if (bits < TYPE_PRECISION (result_type) - && bits < HOST_BITS_PER_WIDE_INT && unsignedp) - { - mask = (~(HOST_WIDE_INT) 0) << bits; - if ((mask & constant) != mask) - warning (0, "comparison of promoted ~unsigned with constant"); - } - } - else if (unsignedp0 && unsignedp1 - && (TYPE_PRECISION (TREE_TYPE (primop0)) - < TYPE_PRECISION (result_type)) - && (TYPE_PRECISION (TREE_TYPE (primop1)) - < TYPE_PRECISION (result_type))) - warning (0, "comparison of promoted ~unsigned with unsigned"); - } + if (warn_sign_compare && !skip_evaluation) + { + warn_for_sign_compare (location, orig_op0, orig_op1, op0, op1, + result_type, resultcode); } } } @@ -8431,7 +8523,7 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1, if (!result_type) { - binary_op_error (code); + binary_op_error (location, code, TREE_TYPE (op0), TREE_TYPE (op1)); return error_mark_node; } @@ -8451,39 +8543,40 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1, if (build_type == NULL_TREE) build_type = result_type; - { - /* Treat expressions in initializers specially as they can't trap. */ - 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); - return result; - } + /* Treat expressions in initializers specially as they can't trap. */ + ret = require_constant_value ? fold_build2_initializer (resultcode, + build_type, + op0, op1) + : fold_build2 (resultcode, build_type, + op0, op1); + if (final_type != 0) + ret = convert (final_type, ret); + + return_build_binary_op: + gcc_assert (ret != error_mark_node); + protected_set_expr_location (ret, location); + return ret; } /* Convert EXPR to be a truth-value, validating its type for this - purpose. */ + purpose. LOCATION is the source location for the expression. */ tree -c_objc_common_truthvalue_conversion (tree expr) +c_objc_common_truthvalue_conversion (location_t location, tree expr) { switch (TREE_CODE (TREE_TYPE (expr))) { case ARRAY_TYPE: - error ("used array that cannot be converted to pointer where scalar is required"); + error_at (location, "used array that cannot be converted to pointer where scalar is required"); return error_mark_node; case RECORD_TYPE: - error ("used struct type value where scalar is required"); + error_at (location, "used struct type value where scalar is required"); return error_mark_node; case UNION_TYPE: - error ("used union type value where scalar is required"); + error_at (location, "used union type value where scalar is required"); return error_mark_node; case FUNCTION_TYPE: @@ -8495,7 +8588,7 @@ c_objc_common_truthvalue_conversion (tree expr) /* ??? Should we also give an error for void and vectors rather than leaving those to give errors later? */ - return c_common_truthvalue_conversion (expr); + return c_common_truthvalue_conversion (location, expr); } @@ -8503,8 +8596,7 @@ c_objc_common_truthvalue_conversion (tree expr) required. */ tree -c_expr_to_decl (tree expr, bool *tc ATTRIBUTE_UNUSED, - bool *ti ATTRIBUTE_UNUSED, bool *se) +c_expr_to_decl (tree expr, bool *tc ATTRIBUTE_UNUSED, bool *se) { if (TREE_CODE (expr) == COMPOUND_LITERAL_EXPR) { @@ -8532,6 +8624,8 @@ c_begin_omp_parallel (void) return block; } +/* Generate OMP_PARALLEL, with CLAUSES and BLOCK as its compound statement. */ + tree c_finish_omp_parallel (tree clauses, tree block) { @@ -8547,6 +8641,36 @@ c_finish_omp_parallel (tree clauses, tree block) return add_stmt (stmt); } +/* Like c_begin_compound_stmt, except force the retention of the BLOCK. */ + +tree +c_begin_omp_task (void) +{ + tree block; + + keep_next_level (); + block = c_begin_compound_stmt (true); + + return block; +} + +/* Generate OMP_TASK, with CLAUSES and BLOCK as its compound statement. */ + +tree +c_finish_omp_task (tree clauses, tree block) +{ + tree stmt; + + block = c_end_compound_stmt (block, true); + + stmt = make_node (OMP_TASK); + TREE_TYPE (stmt) = void_type_node; + OMP_TASK_CLAUSES (stmt) = clauses; + OMP_TASK_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. */ @@ -8707,6 +8831,8 @@ c_finish_omp_clauses (tree clauses) case OMP_CLAUSE_NOWAIT: case OMP_CLAUSE_ORDERED: case OMP_CLAUSE_DEFAULT: + case OMP_CLAUSE_UNTIED: + case OMP_CLAUSE_COLLAPSE: pc = &OMP_CLAUSE_CHAIN (c); continue; @@ -8762,3 +8888,68 @@ c_finish_omp_clauses (tree clauses) bitmap_obstack_release (NULL); return clauses; } + +/* Make a variant type in the proper way for C/C++, propagating qualifiers + down to the element type of an array. */ + +tree +c_build_qualified_type (tree type, int type_quals) +{ + if (type == error_mark_node) + return type; + + if (TREE_CODE (type) == ARRAY_TYPE) + { + tree t; + tree element_type = c_build_qualified_type (TREE_TYPE (type), + type_quals); + + /* See if we already have an identically qualified type. */ + for (t = TYPE_MAIN_VARIANT (type); t; t = TYPE_NEXT_VARIANT (t)) + { + if (TYPE_QUALS (strip_array_types (t)) == type_quals + && TYPE_NAME (t) == TYPE_NAME (type) + && TYPE_CONTEXT (t) == TYPE_CONTEXT (type) + && attribute_list_equal (TYPE_ATTRIBUTES (t), + TYPE_ATTRIBUTES (type))) + break; + } + if (!t) + { + tree domain = TYPE_DOMAIN (type); + + t = build_variant_type_copy (type); + TREE_TYPE (t) = element_type; + + if (TYPE_STRUCTURAL_EQUALITY_P (element_type) + || (domain && TYPE_STRUCTURAL_EQUALITY_P (domain))) + SET_TYPE_STRUCTURAL_EQUALITY (t); + else if (TYPE_CANONICAL (element_type) != element_type + || (domain && TYPE_CANONICAL (domain) != domain)) + { + tree unqualified_canon + = build_array_type (TYPE_CANONICAL (element_type), + domain? TYPE_CANONICAL (domain) + : NULL_TREE); + TYPE_CANONICAL (t) + = c_build_qualified_type (unqualified_canon, type_quals); + } + else + TYPE_CANONICAL (t) = t; + } + return t; + } + + /* A restrict-qualified pointer type must be a pointer to object or + incomplete type. Note that the use of POINTER_TYPE_P also allows + REFERENCE_TYPEs, which is appropriate for C++. */ + if ((type_quals & TYPE_QUAL_RESTRICT) + && (!POINTER_TYPE_P (type) + || !C_TYPE_OBJECT_OR_INCOMPLETE_P (TREE_TYPE (type)))) + { + error ("invalid use of %"); + type_quals &= ~TYPE_QUAL_RESTRICT; + } + + return build_qualified_type (type, type_quals); +}