Mercurial > hg > CbC > CbC_gcc
diff gcc/c-typeck.c @ 69:1b10fe6932e1
merge 69
author | Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp> |
---|---|
date | Sun, 21 Aug 2011 07:53:12 +0900 |
parents | 326d9e06c2e3 f6334be47118 |
children | b81903832de2 |
line wrap: on
line diff
--- a/gcc/c-typeck.c Tue Dec 14 03:58:33 2010 +0900 +++ b/gcc/c-typeck.c Sun Aug 21 07:53:12 2011 +0900 @@ -1,6 +1,6 @@ /* 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, 2008, 2009 + 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. This file is part of GCC. @@ -29,25 +29,22 @@ #include "system.h" #include "coretypes.h" #include "tm.h" -#include "rtl.h" #include "tree.h" #include "langhooks.h" #include "c-tree.h" #include "c-lang.h" -#include "tm_p.h" #include "flags.h" #include "output.h" -#include "expr.h" -#include "toplev.h" #include "intl.h" -#include "ggc.h" #include "target.h" #include "tree-iterator.h" +#include "bitmap.h" #include "gimple.h" #include "tree-flow.h" #ifndef noCbC #include "cbc-tree.h" #endif +#include "c-family/c-objc.h" /* Possible cases of implicit bad conversions. Used to select diagnostic messages in convert_for_assignment. */ @@ -58,13 +55,6 @@ ic_return }; -/* Whether we are building a boolean conversion inside - convert_for_assignment, or some other late binary operation. If - build_binary_op is called (from code shared with C++) in this case, - then the operands have already been folded and the result will not - be folded again, so C_MAYBE_CONST_EXPR should not be generated. */ -bool in_late_binary_op; - /* The level of nesting inside "__alignof__". */ int in_alignof; @@ -83,10 +73,12 @@ static bool null_pointer_constant_p (const_tree); static tree qualify_type (tree, tree); -static int tagged_types_tu_compatible_p (const_tree, const_tree, bool *); +static int tagged_types_tu_compatible_p (const_tree, const_tree, bool *, + bool *); static int comp_target_types (location_t, tree, tree); -static int function_types_compatible_p (const_tree, const_tree, bool *); -static int type_lists_compatible_p (const_tree, const_tree, bool *); +static int function_types_compatible_p (const_tree, const_tree, bool *, + bool *); +static int type_lists_compatible_p (const_tree, const_tree, bool *, bool *); static tree lookup_field (tree, tree); static int convert_arguments (tree, VEC(tree,gc) *, VEC(tree,gc) *, tree, tree); @@ -100,19 +92,19 @@ static char *print_spelling (char *); static void warning_init (int, const char *); static tree digest_init (location_t, tree, tree, tree, bool, bool, int); -static void output_init_element (tree, 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, 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 void output_init_element (tree, tree, bool, tree, tree, int, bool, + struct obstack *); +static void output_pending_init_elements (int, struct obstack *); +static int set_designator (int, struct obstack *); +static void push_range_stack (tree, struct obstack *); +static void add_pending_init (tree, tree, tree, bool, struct obstack *); +static void set_nonincremental_init (struct obstack *); +static void set_nonincremental_init_from_string (tree, struct obstack *); +static tree find_init_member (tree, struct obstack *); static void readonly_warning (tree, enum lvalue_use); -static int lvalue_or_else (const_tree, enum lvalue_use); +static int lvalue_or_else (location_t, const_tree, enum lvalue_use); static void record_maybe_used_decl (tree); -static int comptypes_internal (const_tree, const_tree, bool *); +static int comptypes_internal (const_tree, const_tree, bool *, bool *); /* Return true if EXP is a null pointer constant, false otherwise. */ @@ -493,139 +485,138 @@ #ifndef noCbC int is_code_segment = CbC_IS_CODE_SEGMENT(t1); #endif - tree valtype = composite_type (TREE_TYPE (t1), TREE_TYPE (t2)); - tree p1 = TYPE_ARG_TYPES (t1); - tree p2 = TYPE_ARG_TYPES (t2); - int len; - tree newargs, n; - int i; - - /* Save space: see if the result is identical to one of the args. */ - if (valtype == TREE_TYPE (t1) && !TYPE_ARG_TYPES (t2)) - return build_type_attribute_variant (t1, attributes); - if (valtype == TREE_TYPE (t2) && !TYPE_ARG_TYPES (t1)) - return build_type_attribute_variant (t2, attributes); - - /* Simple way if one arg fails to specify argument types. */ - if (TYPE_ARG_TYPES (t1) == 0) - { + tree valtype = composite_type (TREE_TYPE (t1), TREE_TYPE (t2)); + tree p1 = TYPE_ARG_TYPES (t1); + tree p2 = TYPE_ARG_TYPES (t2); + int len; + tree newargs, n; + int i; + + /* Save space: see if the result is identical to one of the args. */ + if (valtype == TREE_TYPE (t1) && !TYPE_ARG_TYPES (t2)) + return build_type_attribute_variant (t1, attributes); + if (valtype == TREE_TYPE (t2) && !TYPE_ARG_TYPES (t1)) + return build_type_attribute_variant (t2, attributes); + + /* Simple way if one arg fails to specify argument types. */ + if (TYPE_ARG_TYPES (t1) == 0) + { #ifndef noCbC if (is_code_segment) t1 = build_code_segment_type (valtype, TYPE_ARG_TYPES (t2)); else #endif - t1 = build_function_type (valtype, TYPE_ARG_TYPES (t2)); - t1 = build_type_attribute_variant (t1, attributes); - return qualify_type (t1, t2); - } - if (TYPE_ARG_TYPES (t2) == 0) - { + t1 = build_function_type (valtype, TYPE_ARG_TYPES (t2)); + t1 = build_type_attribute_variant (t1, attributes); + return qualify_type (t1, t2); + } + if (TYPE_ARG_TYPES (t2) == 0) + { #ifndef noCbC if (is_code_segment) t1 = build_code_segment_type (valtype, TYPE_ARG_TYPES (t1)); else #endif - t1 = build_function_type (valtype, TYPE_ARG_TYPES (t1)); - t1 = build_type_attribute_variant (t1, attributes); - return qualify_type (t1, t2); - } - - /* If both args specify argument types, we must merge the two - lists, argument by argument. */ - /* Tell global_bindings_p to return false so that variable_size - doesn't die on VLAs in parameter types. */ - c_override_global_bindings_to_false = true; - - len = list_length (p1); - newargs = 0; - - for (i = 0; i < len; i++) - newargs = tree_cons (NULL_TREE, NULL_TREE, newargs); - - n = newargs; - - for (; p1; - p1 = TREE_CHAIN (p1), p2 = TREE_CHAIN (p2), n = TREE_CHAIN (n)) - { - /* A null type means arg type is not specified. - Take whatever the other function type has. */ - if (TREE_VALUE (p1) == 0) - { - TREE_VALUE (n) = TREE_VALUE (p2); - goto parm_done; - } - if (TREE_VALUE (p2) == 0) - { - TREE_VALUE (n) = TREE_VALUE (p1); - goto parm_done; - } - - /* Given wait (union {union wait *u; int *i} *) - and wait (union wait *), - prefer union wait * as type of parm. */ - if (TREE_CODE (TREE_VALUE (p1)) == UNION_TYPE - && TREE_VALUE (p1) != TREE_VALUE (p2)) - { - tree memb; - tree mv2 = TREE_VALUE (p2); - if (mv2 && mv2 != error_mark_node - && TREE_CODE (mv2) != ARRAY_TYPE) - mv2 = TYPE_MAIN_VARIANT (mv2); - for (memb = TYPE_FIELDS (TREE_VALUE (p1)); - memb; memb = TREE_CHAIN (memb)) - { - tree mv3 = TREE_TYPE (memb); - if (mv3 && mv3 != error_mark_node - && TREE_CODE (mv3) != ARRAY_TYPE) - mv3 = TYPE_MAIN_VARIANT (mv3); - if (comptypes (mv3, mv2)) - { - TREE_VALUE (n) = composite_type (TREE_TYPE (memb), - TREE_VALUE (p2)); - pedwarn (input_location, OPT_pedantic, - "function types not truly compatible in ISO C"); - goto parm_done; - } - } - } - if (TREE_CODE (TREE_VALUE (p2)) == UNION_TYPE - && TREE_VALUE (p2) != TREE_VALUE (p1)) - { - tree memb; - tree mv1 = TREE_VALUE (p1); - if (mv1 && mv1 != error_mark_node - && TREE_CODE (mv1) != ARRAY_TYPE) - mv1 = TYPE_MAIN_VARIANT (mv1); - for (memb = TYPE_FIELDS (TREE_VALUE (p2)); - memb; memb = TREE_CHAIN (memb)) - { - tree mv3 = TREE_TYPE (memb); - if (mv3 && mv3 != error_mark_node - && TREE_CODE (mv3) != ARRAY_TYPE) - mv3 = TYPE_MAIN_VARIANT (mv3); - if (comptypes (mv3, mv1)) - { - TREE_VALUE (n) = composite_type (TREE_TYPE (memb), - TREE_VALUE (p1)); - pedwarn (input_location, OPT_pedantic, - "function types not truly compatible in ISO C"); - goto parm_done; - } - } - } - TREE_VALUE (n) = composite_type (TREE_VALUE (p1), TREE_VALUE (p2)); - parm_done: ; - } - - c_override_global_bindings_to_false = false; + t1 = build_function_type (valtype, TYPE_ARG_TYPES (t1)); + t1 = build_type_attribute_variant (t1, attributes); + return qualify_type (t1, t2); + } + + /* If both args specify argument types, we must merge the two + lists, argument by argument. */ + /* Tell global_bindings_p to return false so that variable_size + doesn't die on VLAs in parameter types. */ + c_override_global_bindings_to_false = true; + + len = list_length (p1); + newargs = 0; + + for (i = 0; i < len; i++) + newargs = tree_cons (NULL_TREE, NULL_TREE, newargs); + + n = newargs; + + for (; p1; + p1 = TREE_CHAIN (p1), p2 = TREE_CHAIN (p2), n = TREE_CHAIN (n)) + { + /* A null type means arg type is not specified. + Take whatever the other function type has. */ + if (TREE_VALUE (p1) == 0) + { + TREE_VALUE (n) = TREE_VALUE (p2); + goto parm_done; + } + if (TREE_VALUE (p2) == 0) + { + TREE_VALUE (n) = TREE_VALUE (p1); + goto parm_done; + } + + /* Given wait (union {union wait *u; int *i} *) + and wait (union wait *), + prefer union wait * as type of parm. */ + if (TREE_CODE (TREE_VALUE (p1)) == UNION_TYPE + && TREE_VALUE (p1) != TREE_VALUE (p2)) + { + tree memb; + tree mv2 = TREE_VALUE (p2); + if (mv2 && mv2 != error_mark_node + && TREE_CODE (mv2) != ARRAY_TYPE) + mv2 = TYPE_MAIN_VARIANT (mv2); + for (memb = TYPE_FIELDS (TREE_VALUE (p1)); + memb; memb = DECL_CHAIN (memb)) + { + tree mv3 = TREE_TYPE (memb); + if (mv3 && mv3 != error_mark_node + && TREE_CODE (mv3) != ARRAY_TYPE) + mv3 = TYPE_MAIN_VARIANT (mv3); + if (comptypes (mv3, mv2)) + { + TREE_VALUE (n) = composite_type (TREE_TYPE (memb), + TREE_VALUE (p2)); + pedwarn (input_location, OPT_pedantic, + "function types not truly compatible in ISO C"); + goto parm_done; + } + } + } + if (TREE_CODE (TREE_VALUE (p2)) == UNION_TYPE + && TREE_VALUE (p2) != TREE_VALUE (p1)) + { + tree memb; + tree mv1 = TREE_VALUE (p1); + if (mv1 && mv1 != error_mark_node + && TREE_CODE (mv1) != ARRAY_TYPE) + mv1 = TYPE_MAIN_VARIANT (mv1); + for (memb = TYPE_FIELDS (TREE_VALUE (p2)); + memb; memb = DECL_CHAIN (memb)) + { + tree mv3 = TREE_TYPE (memb); + if (mv3 && mv3 != error_mark_node + && TREE_CODE (mv3) != ARRAY_TYPE) + mv3 = TYPE_MAIN_VARIANT (mv3); + if (comptypes (mv3, mv1)) + { + TREE_VALUE (n) = composite_type (TREE_TYPE (memb), + TREE_VALUE (p1)); + pedwarn (input_location, OPT_pedantic, + "function types not truly compatible in ISO C"); + goto parm_done; + } + } + } + TREE_VALUE (n) = composite_type (TREE_VALUE (p1), TREE_VALUE (p2)); + parm_done: ; + } + + c_override_global_bindings_to_false = false; #ifndef noCbC if (is_code_segment) t1 = build_code_segment_type (valtype, newargs); else #endif - t1 = build_function_type (valtype, newargs); - t1 = qualify_type (t1, t2); - /* ... falls through ... */ + t1 = build_function_type (valtype, newargs); + t1 = qualify_type (t1, t2); + /* ... falls through ... */ } - default: return build_type_attribute_variant (t1, attributes); } @@ -994,7 +985,7 @@ const struct tagged_tu_seen_cache * tagged_tu_seen_base1 = tagged_tu_seen_base; int val; - val = comptypes_internal (type1, type2, NULL); + val = comptypes_internal (type1, type2, NULL, NULL); free_all_tagged_tu_seen_up_to (tagged_tu_seen_base1); return val; @@ -1009,7 +1000,23 @@ const struct tagged_tu_seen_cache * tagged_tu_seen_base1 = tagged_tu_seen_base; int val; - val = comptypes_internal (type1, type2, enum_and_int_p); + val = comptypes_internal (type1, type2, enum_and_int_p, NULL); + free_all_tagged_tu_seen_up_to (tagged_tu_seen_base1); + + return val; +} + +/* Like comptypes, but if it returns nonzero for different types, it + sets *DIFFERENT_TYPES_P to true. */ + +int +comptypes_check_different_types (tree type1, tree type2, + bool *different_types_p) +{ + const struct tagged_tu_seen_cache * tagged_tu_seen_base1 = tagged_tu_seen_base; + int val; + + val = comptypes_internal (type1, type2, NULL, different_types_p); free_all_tagged_tu_seen_up_to (tagged_tu_seen_base1); return val; @@ -1020,11 +1027,17 @@ but a warning may be needed if you use them together. If ENUM_AND_INT_P is not NULL, and one type is an enum and the other a compatible integer type, then this sets *ENUM_AND_INT_P to true; - *ENUM_AND_INT_P is never set to false. This differs from - comptypes, in that we don't free the seen types. */ + *ENUM_AND_INT_P is never set to false. If DIFFERENT_TYPES_P is not + NULL, and the types are compatible but different enough not to be + permitted in C1X typedef redeclarations, then this sets + *DIFFERENT_TYPES_P to true; *DIFFERENT_TYPES_P is never set to + false, but may or may not be set if the types are incompatible. + This differs from comptypes, in that we don't free the seen + types. */ static int -comptypes_internal (const_tree type1, const_tree type2, bool *enum_and_int_p) +comptypes_internal (const_tree type1, const_tree type2, bool *enum_and_int_p, + bool *different_types_p) { const_tree t1 = type1; const_tree t2 = type2; @@ -1036,17 +1049,6 @@ || TREE_CODE (t1) == ERROR_MARK || TREE_CODE (t2) == ERROR_MARK) return 1; - /* If either type is the internal version of sizetype, return the - language version. */ - if (TREE_CODE (t1) == INTEGER_TYPE && TYPE_IS_SIZETYPE (t1) - && TYPE_ORIG_SIZE_TYPE (t1)) - t1 = TYPE_ORIG_SIZE_TYPE (t1); - - if (TREE_CODE (t2) == INTEGER_TYPE && TYPE_IS_SIZETYPE (t2) - && TYPE_ORIG_SIZE_TYPE (t2)) - t2 = TYPE_ORIG_SIZE_TYPE (t2); - - /* Enumerated types are compatible with integer types, but this is not transitive: two enumerated types in the same translation unit are compatible with each other only if they are the same type. */ @@ -1054,14 +1056,24 @@ if (TREE_CODE (t1) == ENUMERAL_TYPE && TREE_CODE (t2) != ENUMERAL_TYPE) { t1 = c_common_type_for_size (TYPE_PRECISION (t1), TYPE_UNSIGNED (t1)); - if (enum_and_int_p != NULL && TREE_CODE (t2) != VOID_TYPE) - *enum_and_int_p = true; + if (TREE_CODE (t2) != VOID_TYPE) + { + if (enum_and_int_p != NULL) + *enum_and_int_p = true; + if (different_types_p != NULL) + *different_types_p = true; + } } else if (TREE_CODE (t2) == ENUMERAL_TYPE && TREE_CODE (t1) != ENUMERAL_TYPE) { t2 = c_common_type_for_size (TYPE_PRECISION (t2), TYPE_UNSIGNED (t2)); - if (enum_and_int_p != NULL && TREE_CODE (t1) != VOID_TYPE) - *enum_and_int_p = true; + if (TREE_CODE (t1) != VOID_TYPE) + { + if (enum_and_int_p != NULL) + *enum_and_int_p = true; + if (different_types_p != NULL) + *different_types_p = true; + } } if (t1 == t2) @@ -1100,78 +1112,88 @@ || TYPE_REF_CAN_ALIAS_ALL (t1) != TYPE_REF_CAN_ALIAS_ALL (t2)) break; val = (TREE_TYPE (t1) == TREE_TYPE (t2) - ? 1 : comptypes_internal (TREE_TYPE (t1), TREE_TYPE (t2), - enum_and_int_p)); + ? 1 : comptypes_internal (TREE_TYPE (t1), TREE_TYPE (t2), + enum_and_int_p, different_types_p)); break; case FUNCTION_TYPE: - val = function_types_compatible_p (t1, t2, enum_and_int_p); + val = function_types_compatible_p (t1, t2, enum_and_int_p, + different_types_p); break; case ARRAY_TYPE: { - tree d1 = TYPE_DOMAIN (t1); - tree d2 = TYPE_DOMAIN (t2); - bool d1_variable, d2_variable; - bool d1_zero, d2_zero; - val = 1; - - /* Target types must match incl. qualifiers. */ - if (TREE_TYPE (t1) != TREE_TYPE (t2) - && 0 == (val = comptypes_internal (TREE_TYPE (t1), TREE_TYPE (t2), - enum_and_int_p))) - return 0; - - /* Sizes must match unless one is missing or variable. */ - if (d1 == 0 || d2 == 0 || d1 == d2) - break; - - d1_zero = !TYPE_MAX_VALUE (d1); - d2_zero = !TYPE_MAX_VALUE (d2); - - d1_variable = (!d1_zero - && (TREE_CODE (TYPE_MIN_VALUE (d1)) != INTEGER_CST - || TREE_CODE (TYPE_MAX_VALUE (d1)) != INTEGER_CST)); - d2_variable = (!d2_zero - && (TREE_CODE (TYPE_MIN_VALUE (d2)) != INTEGER_CST - || TREE_CODE (TYPE_MAX_VALUE (d2)) != INTEGER_CST)); - d1_variable = d1_variable || (d1_zero && c_vla_type_p (t1)); - d2_variable = d2_variable || (d2_zero && c_vla_type_p (t2)); - - if (d1_variable || d2_variable) - break; - if (d1_zero && d2_zero) - break; - if (d1_zero || d2_zero - || !tree_int_cst_equal (TYPE_MIN_VALUE (d1), TYPE_MIN_VALUE (d2)) - || !tree_int_cst_equal (TYPE_MAX_VALUE (d1), TYPE_MAX_VALUE (d2))) - val = 0; - - break; + tree d1 = TYPE_DOMAIN (t1); + tree d2 = TYPE_DOMAIN (t2); + bool d1_variable, d2_variable; + bool d1_zero, d2_zero; + val = 1; + + /* Target types must match incl. qualifiers. */ + if (TREE_TYPE (t1) != TREE_TYPE (t2) + && 0 == (val = comptypes_internal (TREE_TYPE (t1), TREE_TYPE (t2), + enum_and_int_p, + different_types_p))) + return 0; + + if (different_types_p != NULL + && (d1 == 0) != (d2 == 0)) + *different_types_p = true; + /* Sizes must match unless one is missing or variable. */ + if (d1 == 0 || d2 == 0 || d1 == d2) + break; + + d1_zero = !TYPE_MAX_VALUE (d1); + d2_zero = !TYPE_MAX_VALUE (d2); + + d1_variable = (!d1_zero + && (TREE_CODE (TYPE_MIN_VALUE (d1)) != INTEGER_CST + || TREE_CODE (TYPE_MAX_VALUE (d1)) != INTEGER_CST)); + d2_variable = (!d2_zero + && (TREE_CODE (TYPE_MIN_VALUE (d2)) != INTEGER_CST + || TREE_CODE (TYPE_MAX_VALUE (d2)) != INTEGER_CST)); + d1_variable = d1_variable || (d1_zero && c_vla_type_p (t1)); + d2_variable = d2_variable || (d2_zero && c_vla_type_p (t2)); + + if (different_types_p != NULL + && d1_variable != d2_variable) + *different_types_p = true; + if (d1_variable || d2_variable) + break; + if (d1_zero && d2_zero) + break; + if (d1_zero || d2_zero + || !tree_int_cst_equal (TYPE_MIN_VALUE (d1), TYPE_MIN_VALUE (d2)) + || !tree_int_cst_equal (TYPE_MAX_VALUE (d1), TYPE_MAX_VALUE (d2))) + val = 0; + + break; } case ENUMERAL_TYPE: case RECORD_TYPE: case UNION_TYPE: if (val != 1 && !same_translation_unit_p (t1, t2)) - { - tree a1 = TYPE_ATTRIBUTES (t1); - tree a2 = TYPE_ATTRIBUTES (t2); - - if (! attribute_list_contained (a1, a2) - && ! attribute_list_contained (a2, a1)) - break; - - if (attrval != 2) - return tagged_types_tu_compatible_p (t1, t2, enum_and_int_p); - val = tagged_types_tu_compatible_p (t1, t2, enum_and_int_p); - } + { + tree a1 = TYPE_ATTRIBUTES (t1); + tree a2 = TYPE_ATTRIBUTES (t2); + + if (! attribute_list_contained (a1, a2) + && ! attribute_list_contained (a2, a1)) + break; + + if (attrval != 2) + return tagged_types_tu_compatible_p (t1, t2, enum_and_int_p, + different_types_p); + val = tagged_types_tu_compatible_p (t1, t2, enum_and_int_p, + different_types_p); + } break; case VECTOR_TYPE: val = (TYPE_VECTOR_SUBPARTS (t1) == TYPE_VECTOR_SUBPARTS (t2) - && comptypes_internal (TREE_TYPE (t1), TREE_TYPE (t2), - enum_and_int_p)); + && comptypes_internal (TREE_TYPE (t1), TREE_TYPE (t2), + enum_and_int_p, different_types_p)); break; default: @@ -1303,11 +1325,12 @@ compatible. If the two types are not the same (which has been checked earlier), this can only happen when multiple translation units are being compiled. See C99 6.2.7 paragraph 1 for the exact - rules. ENUM_AND_INT_P is as in comptypes_internal. */ + rules. ENUM_AND_INT_P and DIFFERENT_TYPES_P are as in + comptypes_internal. */ static int tagged_types_tu_compatible_p (const_tree t1, const_tree t2, - bool *enum_and_int_p) + bool *enum_and_int_p, bool *different_types_p) { tree s1, s2; bool needs_warning = false; @@ -1402,117 +1425,117 @@ case UNION_TYPE: { - struct tagged_tu_seen_cache *tu = alloc_tagged_tu_seen_cache (t1, t2); - if (list_length (TYPE_FIELDS (t1)) != list_length (TYPE_FIELDS (t2))) - { - tu->val = 0; - return 0; - } - - /* Speed up the common case where the fields are in the same order. */ - for (s1 = TYPE_FIELDS (t1), s2 = TYPE_FIELDS (t2); s1 && s2; - s1 = TREE_CHAIN (s1), s2 = TREE_CHAIN (s2)) - { - int result; - - if (DECL_NAME (s1) != DECL_NAME (s2)) - break; - result = comptypes_internal (TREE_TYPE (s1), TREE_TYPE (s2), - enum_and_int_p); - - if (result != 1 && !DECL_NAME (s1)) - break; - if (result == 0) - { - tu->val = 0; - return 0; - } - if (result == 2) - needs_warning = true; - - if (TREE_CODE (s1) == FIELD_DECL - && simple_cst_equal (DECL_FIELD_BIT_OFFSET (s1), - DECL_FIELD_BIT_OFFSET (s2)) != 1) - { - tu->val = 0; - return 0; - } - } - if (!s1 && !s2) - { - tu->val = needs_warning ? 2 : 1; - return tu->val; - } - - for (s1 = TYPE_FIELDS (t1); s1; s1 = TREE_CHAIN (s1)) - { - bool ok = false; - - 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), - enum_and_int_p); - - if (result != 1 && !DECL_NAME (s1)) - continue; - if (result == 0) - { - tu->val = 0; - return 0; - } - if (result == 2) - needs_warning = true; - - if (TREE_CODE (s1) == FIELD_DECL - && simple_cst_equal (DECL_FIELD_BIT_OFFSET (s1), - DECL_FIELD_BIT_OFFSET (s2)) != 1) - break; - - ok = true; - break; - } - if (!ok) - { - tu->val = 0; - return 0; - } - } - tu->val = needs_warning ? 2 : 10; - return tu->val; + struct tagged_tu_seen_cache *tu = alloc_tagged_tu_seen_cache (t1, t2); + if (list_length (TYPE_FIELDS (t1)) != list_length (TYPE_FIELDS (t2))) + { + tu->val = 0; + return 0; + } + + /* Speed up the common case where the fields are in the same order. */ + for (s1 = TYPE_FIELDS (t1), s2 = TYPE_FIELDS (t2); s1 && s2; + s1 = DECL_CHAIN (s1), s2 = DECL_CHAIN (s2)) + { + int result; + + if (DECL_NAME (s1) != DECL_NAME (s2)) + break; + result = comptypes_internal (TREE_TYPE (s1), TREE_TYPE (s2), + enum_and_int_p, different_types_p); + + if (result != 1 && !DECL_NAME (s1)) + break; + if (result == 0) + { + tu->val = 0; + return 0; + } + if (result == 2) + needs_warning = true; + + if (TREE_CODE (s1) == FIELD_DECL + && simple_cst_equal (DECL_FIELD_BIT_OFFSET (s1), + DECL_FIELD_BIT_OFFSET (s2)) != 1) + { + tu->val = 0; + return 0; + } + } + if (!s1 && !s2) + { + tu->val = needs_warning ? 2 : 1; + return tu->val; + } + + for (s1 = TYPE_FIELDS (t1); s1; s1 = DECL_CHAIN (s1)) + { + bool ok = false; + + for (s2 = TYPE_FIELDS (t2); s2; s2 = DECL_CHAIN (s2)) + if (DECL_NAME (s1) == DECL_NAME (s2)) + { + int result; + + result = comptypes_internal (TREE_TYPE (s1), TREE_TYPE (s2), + enum_and_int_p, + different_types_p); + + if (result != 1 && !DECL_NAME (s1)) + continue; + if (result == 0) + { + tu->val = 0; + return 0; + } + if (result == 2) + needs_warning = true; + + if (TREE_CODE (s1) == FIELD_DECL + && simple_cst_equal (DECL_FIELD_BIT_OFFSET (s1), + DECL_FIELD_BIT_OFFSET (s2)) != 1) + break; + + ok = true; + break; + } + if (!ok) + { + tu->val = 0; + return 0; + } + } + tu->val = needs_warning ? 2 : 10; + return tu->val; } case RECORD_TYPE: { - struct tagged_tu_seen_cache *tu = alloc_tagged_tu_seen_cache (t1, t2); - - for (s1 = TYPE_FIELDS (t1), s2 = TYPE_FIELDS (t2); - s1 && s2; - s1 = TREE_CHAIN (s1), s2 = TREE_CHAIN (s2)) - { - int result; - if (TREE_CODE (s1) != TREE_CODE (s2) - || DECL_NAME (s1) != DECL_NAME (s2)) - break; - result = comptypes_internal (TREE_TYPE (s1), TREE_TYPE (s2), - enum_and_int_p); - if (result == 0) - break; - if (result == 2) - needs_warning = true; - - if (TREE_CODE (s1) == FIELD_DECL - && simple_cst_equal (DECL_FIELD_BIT_OFFSET (s1), - DECL_FIELD_BIT_OFFSET (s2)) != 1) - break; - } - if (s1 && s2) - tu->val = 0; - else - tu->val = needs_warning ? 2 : 1; - return tu->val; + struct tagged_tu_seen_cache *tu = alloc_tagged_tu_seen_cache (t1, t2); + + for (s1 = TYPE_FIELDS (t1), s2 = TYPE_FIELDS (t2); + s1 && s2; + s1 = DECL_CHAIN (s1), s2 = DECL_CHAIN (s2)) + { + int result; + if (TREE_CODE (s1) != TREE_CODE (s2) + || DECL_NAME (s1) != DECL_NAME (s2)) + break; + result = comptypes_internal (TREE_TYPE (s1), TREE_TYPE (s2), + enum_and_int_p, different_types_p); + if (result == 0) + break; + if (result == 2) + needs_warning = true; + if (TREE_CODE (s1) == FIELD_DECL + && simple_cst_equal (DECL_FIELD_BIT_OFFSET (s1), + DECL_FIELD_BIT_OFFSET (s2)) != 1) + break; + } + if (s1 && s2) + tu->val = 0; + else + tu->val = needs_warning ? 2 : 1; + return tu->val; } default: @@ -1526,11 +1549,11 @@ Otherwise, if one type specifies only the number of arguments, the other must specify that number of self-promoting arg types. Otherwise, the argument types must match. - ENUM_AND_INT_P is as in comptypes_internal. */ + ENUM_AND_INT_P and DIFFERENT_TYPES_P are as in comptypes_internal. */ static int function_types_compatible_p (const_tree f1, const_tree f2, - bool *enum_and_int_p) + bool *enum_and_int_p, bool *different_types_p) { tree args1, args2; /* 1 if no need for warning yet, 2 if warning cause has been seen. */ @@ -1550,14 +1573,18 @@ TYPE_QUALS (ret1) & ~TYPE_QUAL_VOLATILE); if (TYPE_VOLATILE (ret2)) ret2 = build_qualified_type (TYPE_MAIN_VARIANT (ret2), - TYPE_QUALS (ret2) & ~TYPE_QUAL_VOLATILE); - val = comptypes_internal (ret1, ret2, enum_and_int_p); + TYPE_QUALS (ret2) & ~TYPE_QUAL_VOLATILE); + val = comptypes_internal (ret1, ret2, enum_and_int_p, different_types_p); if (val == 0) return 0; args1 = TYPE_ARG_TYPES (f1); args2 = TYPE_ARG_TYPES (f2); + if (different_types_p != NULL + && (args1 == 0) != (args2 == 0)) + *different_types_p = true; + /* An unspecified parmlist matches any specified parmlist whose argument types don't need default promotions. */ @@ -1569,9 +1596,9 @@ compare that with the other type's arglist. If they don't match, ask for a warning (but no error). */ if (TYPE_ACTUAL_ARG_TYPES (f1) - && 1 != type_lists_compatible_p (args2, TYPE_ACTUAL_ARG_TYPES (f1), - enum_and_int_p)) - val = 2; + && 1 != type_lists_compatible_p (args2, TYPE_ACTUAL_ARG_TYPES (f1), + enum_and_int_p, different_types_p)) + val = 2; return val; } if (args2 == 0) @@ -1579,24 +1606,26 @@ if (!self_promoting_args_p (args1)) return 0; if (TYPE_ACTUAL_ARG_TYPES (f2) - && 1 != type_lists_compatible_p (args1, TYPE_ACTUAL_ARG_TYPES (f2), - enum_and_int_p)) - val = 2; + && 1 != type_lists_compatible_p (args1, TYPE_ACTUAL_ARG_TYPES (f2), + enum_and_int_p, different_types_p)) + val = 2; return val; } /* Both types have argument lists: compare them and propagate results. */ - val1 = type_lists_compatible_p (args1, args2, enum_and_int_p); + val1 = type_lists_compatible_p (args1, args2, enum_and_int_p, + different_types_p); return val1 != 1 ? val1 : val; } /* Check two lists of types for compatibility, returning 0 for incompatible, 1 for compatible, or 2 for compatible with - warning. ENUM_AND_INT_P is as in comptypes_internal. */ + warning. ENUM_AND_INT_P and DIFFERENT_TYPES_P are as in + comptypes_internal. */ static int type_lists_compatible_p (const_tree args1, const_tree args2, - bool *enum_and_int_p) + bool *enum_and_int_p, bool *different_types_p) { /* 1 if no need for warning yet, 2 if warning cause has been seen. */ int val = 1; @@ -1618,9 +1647,12 @@ if (mv2 && mv2 != error_mark_node && TREE_CODE (mv2) != ARRAY_TYPE) mv2 = TYPE_MAIN_VARIANT (mv2); /* A null pointer instead of a type - means there is supposed to be an argument - but nothing is specified about what type it has. - So match anything that self-promotes. */ + means there is supposed to be an argument + but nothing is specified about what type it has. + So match anything that self-promotes. */ + if (different_types_p != NULL + && (a1 == 0) != (a2 == 0)) + *different_types_p = true; if (a1 == 0) { if (c_type_promotes_to (a2) != a2) @@ -1633,57 +1665,62 @@ } /* If one of the lists has an error marker, ignore this arg. */ else if (TREE_CODE (a1) == ERROR_MARK - || TREE_CODE (a2) == ERROR_MARK) - ; - else if (!(newval = comptypes_internal (mv1, mv2, enum_and_int_p))) - { - /* Allow wait (union {union wait *u; int *i} *) - and wait (union wait *) to be compatible. */ - if (TREE_CODE (a1) == UNION_TYPE - && (TYPE_NAME (a1) == 0 - || TYPE_TRANSPARENT_UNION (a1)) - && TREE_CODE (TYPE_SIZE (a1)) == INTEGER_CST - && tree_int_cst_equal (TYPE_SIZE (a1), - TYPE_SIZE (a2))) - { - tree memb; - for (memb = TYPE_FIELDS (a1); - memb; memb = TREE_CHAIN (memb)) - { - tree mv3 = TREE_TYPE (memb); - if (mv3 && mv3 != error_mark_node - && TREE_CODE (mv3) != ARRAY_TYPE) - mv3 = TYPE_MAIN_VARIANT (mv3); - if (comptypes_internal (mv3, mv2, enum_and_int_p)) - break; - } - if (memb == 0) - return 0; - } - else if (TREE_CODE (a2) == UNION_TYPE - && (TYPE_NAME (a2) == 0 - || TYPE_TRANSPARENT_UNION (a2)) - && TREE_CODE (TYPE_SIZE (a2)) == INTEGER_CST - && tree_int_cst_equal (TYPE_SIZE (a2), - TYPE_SIZE (a1))) - { - tree memb; - for (memb = TYPE_FIELDS (a2); - memb; memb = TREE_CHAIN (memb)) - { - tree mv3 = TREE_TYPE (memb); - if (mv3 && mv3 != error_mark_node - && TREE_CODE (mv3) != ARRAY_TYPE) - mv3 = TYPE_MAIN_VARIANT (mv3); - if (comptypes_internal (mv3, mv1, enum_and_int_p)) - break; - } - if (memb == 0) - return 0; - } - else - return 0; - } + || TREE_CODE (a2) == ERROR_MARK) + ; + else if (!(newval = comptypes_internal (mv1, mv2, enum_and_int_p, + different_types_p))) + { + if (different_types_p != NULL) + *different_types_p = true; + /* Allow wait (union {union wait *u; int *i} *) + and wait (union wait *) to be compatible. */ + if (TREE_CODE (a1) == UNION_TYPE + && (TYPE_NAME (a1) == 0 + || TYPE_TRANSPARENT_AGGR (a1)) + && TREE_CODE (TYPE_SIZE (a1)) == INTEGER_CST + && tree_int_cst_equal (TYPE_SIZE (a1), + TYPE_SIZE (a2))) + { + tree memb; + for (memb = TYPE_FIELDS (a1); + memb; memb = DECL_CHAIN (memb)) + { + tree mv3 = TREE_TYPE (memb); + if (mv3 && mv3 != error_mark_node + && TREE_CODE (mv3) != ARRAY_TYPE) + mv3 = TYPE_MAIN_VARIANT (mv3); + if (comptypes_internal (mv3, mv2, enum_and_int_p, + different_types_p)) + break; + } + if (memb == 0) + return 0; + } + else if (TREE_CODE (a2) == UNION_TYPE + && (TYPE_NAME (a2) == 0 + || TYPE_TRANSPARENT_AGGR (a2)) + && TREE_CODE (TYPE_SIZE (a2)) == INTEGER_CST + && tree_int_cst_equal (TYPE_SIZE (a2), + TYPE_SIZE (a1))) + { + tree memb; + for (memb = TYPE_FIELDS (a2); + memb; memb = DECL_CHAIN (memb)) + { + tree mv3 = TREE_TYPE (memb); + if (mv3 && mv3 != error_mark_node + && TREE_CODE (mv3) != ARRAY_TYPE) + mv3 = TYPE_MAIN_VARIANT (mv3); + if (comptypes_internal (mv3, mv1, enum_and_int_p, + different_types_p)) + break; + } + if (memb == 0) + return 0; + } + else + return 0; + } /* comptypes said ok, but record if it said to warn. */ if (newval > val) @@ -1782,6 +1819,36 @@ return build_unary_op (loc, ADDR_EXPR, exp, 0); } +/* Mark EXP as read, not just set, for set but not used -Wunused + warning purposes. */ + +void +mark_exp_read (tree exp) +{ + switch (TREE_CODE (exp)) + { + case VAR_DECL: + case PARM_DECL: + DECL_READ_P (exp) = 1; + break; + case ARRAY_REF: + case COMPONENT_REF: + case MODIFY_EXPR: + case REALPART_EXPR: + case IMAGPART_EXPR: + CASE_CONVERT: + case ADDR_EXPR: + mark_exp_read (TREE_OPERAND (exp, 0)); + break; + case COMPOUND_EXPR: + case C_MAYBE_CONST_EXPR: + mark_exp_read (TREE_OPERAND (exp, 1)); + break; + default: + break; + } +} + /* Perform the default conversion of arrays and functions to pointers. Return the result of converting EXP. For any other expression, just return EXP. @@ -1837,6 +1904,12 @@ return exp; } +struct c_expr +default_function_array_read_conversion (location_t loc, struct c_expr exp) +{ + mark_exp_read (exp.value); + return default_function_array_conversion (loc, exp); +} /* EXP is an expression of integer type. Apply the integer promotions to it and return the promoted value. */ @@ -1898,6 +1971,8 @@ enum tree_code code = TREE_CODE (type); tree promoted_type; + mark_exp_read (exp); + /* Functions and arrays have been converted during parsing. */ gcc_assert (code != FUNCTION_TYPE); if (code == ARRAY_TYPE) @@ -1934,7 +2009,7 @@ return exp; } -/* Look up COMPONENT in a structure or union DECL. +/* Look up COMPONENT in a structure or union TYPE. If the component name is not found, returns NULL_TREE. Otherwise, the return value is a TREE_LIST, with each TREE_VALUE a FIELD_DECL @@ -1944,9 +2019,8 @@ unions, the list steps down the chain to the component. */ static tree -lookup_field (tree decl, tree component) -{ - tree type = TREE_TYPE (decl); +lookup_field (tree type, tree component) +{ tree field; /* If TYPE_LANG_SPECIFIC is set, then it is a sorted array of pointers @@ -1963,41 +2037,52 @@ bot = 0; top = TYPE_LANG_SPECIFIC (type)->s->len; while (top - bot > 1) - { - half = (top - bot + 1) >> 1; - field = field_array[bot+half]; - - if (DECL_NAME (field) == NULL_TREE) - { - /* Step through all anon unions in linear fashion. */ - while (DECL_NAME (field_array[bot]) == NULL_TREE) - { - field = field_array[bot++]; - if (TREE_CODE (TREE_TYPE (field)) == RECORD_TYPE - || TREE_CODE (TREE_TYPE (field)) == UNION_TYPE) - { - tree anon = lookup_field (field, component); - - if (anon) - return tree_cons (NULL_TREE, field, anon); - } - } - - /* Entire record is only anon unions. */ - if (bot > top) - return NULL_TREE; - - /* Restart the binary search, with new lower bound. */ - continue; - } - - if (DECL_NAME (field) == component) - break; - if (DECL_NAME (field) < component) - bot += half; - else - top = bot + half; - } + { + half = (top - bot + 1) >> 1; + field = field_array[bot+half]; + + if (DECL_NAME (field) == NULL_TREE) + { + /* Step through all anon unions in linear fashion. */ + while (DECL_NAME (field_array[bot]) == NULL_TREE) + { + field = field_array[bot++]; + if (TREE_CODE (TREE_TYPE (field)) == RECORD_TYPE + || TREE_CODE (TREE_TYPE (field)) == UNION_TYPE) + { + tree anon = lookup_field (TREE_TYPE (field), component); + + if (anon) + return tree_cons (NULL_TREE, field, anon); + + /* The Plan 9 compiler permits referring + directly to an anonymous struct/union field + using a typedef name. */ + if (flag_plan9_extensions + && TYPE_NAME (TREE_TYPE (field)) != NULL_TREE + && (TREE_CODE (TYPE_NAME (TREE_TYPE (field))) + == TYPE_DECL) + && (DECL_NAME (TYPE_NAME (TREE_TYPE (field))) + == component)) + break; + } + } + + /* Entire record is only anon unions. */ + if (bot > top) + return NULL_TREE; + + /* Restart the binary search, with new lower bound. */ + continue; + } + + if (DECL_NAME (field) == component) + break; + if (DECL_NAME (field) < component) + bot += half; + else + top = bot + half; + } if (DECL_NAME (field_array[bot]) == component) field = field_array[bot]; @@ -2006,21 +2091,31 @@ } else { - for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field)) - { - if (DECL_NAME (field) == NULL_TREE - && (TREE_CODE (TREE_TYPE (field)) == RECORD_TYPE - || TREE_CODE (TREE_TYPE (field)) == UNION_TYPE)) - { - tree anon = lookup_field (field, component); - - if (anon) - return tree_cons (NULL_TREE, field, anon); - } - - if (DECL_NAME (field) == component) - break; - } + for (field = TYPE_FIELDS (type); field; field = DECL_CHAIN (field)) + { + if (DECL_NAME (field) == NULL_TREE + && (TREE_CODE (TREE_TYPE (field)) == RECORD_TYPE + || TREE_CODE (TREE_TYPE (field)) == UNION_TYPE)) + { + tree anon = lookup_field (TREE_TYPE (field), component); + + if (anon) + return tree_cons (NULL_TREE, field, anon); + + /* The Plan 9 compiler permits referring directly to an + anonymous struct/union field using a typedef + name. */ + if (flag_plan9_extensions + && TYPE_NAME (TREE_TYPE (field)) != NULL_TREE + && TREE_CODE (TYPE_NAME (TREE_TYPE (field))) == TYPE_DECL + && (DECL_NAME (TYPE_NAME (TREE_TYPE (field))) + == component)) + break; + } + + if (DECL_NAME (field) == component) + break; + } if (field == NULL_TREE) return NULL_TREE; @@ -2045,6 +2140,11 @@ if (!objc_is_public (datum, component)) return error_mark_node; + /* Detect Objective-C property syntax object.property. */ + if (c_dialect_objc () + && (ref = objc_maybe_build_component_ref (datum, component))) + return ref; + /* See if there is a field or component with name COMPONENT. */ if (code == RECORD_TYPE || code == UNION_TYPE) @@ -2055,7 +2155,7 @@ return error_mark_node; } - field = lookup_field (datum, component); + field = lookup_field (type, component); if (!field) { @@ -2184,26 +2284,8 @@ } } else if (TREE_CODE (pointer) != ERROR_MARK) - switch (errstring) - { - case RO_ARRAY_INDEXING: - error_at (loc, - "invalid type argument of array indexing (have %qT)", - type); - break; - case RO_UNARY_STAR: - error_at (loc, - "invalid type argument of unary %<*%> (have %qT)", - type); - break; - case RO_ARROW: - error_at (loc, - "invalid type argument of %<->%> (have %qT)", - type); - break; - default: - gcc_unreachable (); - } + invalid_indirection_error (loc, type, errstring); + return error_mark_node; } @@ -2216,6 +2298,9 @@ arrays that are not lvalues (for example, members of structures returned by functions). + For vector types, allow vector[i] but not i[vector], and create + *(((type*)&vectortype) + i) for the expression. + LOC is the location to use for the returned expression. */ tree @@ -2228,15 +2313,19 @@ return error_mark_node; if (TREE_CODE (TREE_TYPE (array)) != ARRAY_TYPE - && TREE_CODE (TREE_TYPE (array)) != POINTER_TYPE) + && TREE_CODE (TREE_TYPE (array)) != POINTER_TYPE + /* Allow vector[index] but not index[vector]. */ + && TREE_CODE (TREE_TYPE (array)) != VECTOR_TYPE) { tree temp; if (TREE_CODE (TREE_TYPE (index)) != ARRAY_TYPE - && TREE_CODE (TREE_TYPE (index)) != POINTER_TYPE) - { - error_at (loc, "subscripted value is neither array nor pointer"); - return error_mark_node; - } + && TREE_CODE (TREE_TYPE (index)) != POINTER_TYPE) + { + error_at (loc, + "subscripted value is neither array nor pointer nor vector"); + + return error_mark_node; + } temp = array; array = index; index = temp; @@ -2264,6 +2353,27 @@ index = default_conversion (index); gcc_assert (TREE_CODE (TREE_TYPE (index)) == INTEGER_TYPE); + + /* For vector[index], convert the vector to a + pointer of the underlying type. */ + if (TREE_CODE (TREE_TYPE (array)) == VECTOR_TYPE) + { + tree type = TREE_TYPE (array); + tree type1; + + if (TREE_CODE (index) == INTEGER_CST) + if (!host_integerp (index, 1) + || ((unsigned HOST_WIDE_INT) tree_low_cst (index, 1) + >= TYPE_VECTOR_SUBPARTS (TREE_TYPE (array)))) + warning_at (loc, OPT_Warray_bounds, "index value is out of bound"); + + c_common_mark_addressable_vec (array); + type = build_qualified_type (TREE_TYPE (type), TYPE_QUALS (type)); + type = build_pointer_type (type); + type1 = build_pointer_type (TREE_TYPE (array)); + array = build1 (ADDR_EXPR, type1, array); + array = convert (type, array); + } if (TREE_CODE (TREE_TYPE (array)) == ARRAY_TYPE) { @@ -2699,19 +2809,19 @@ return trap; } else - { - tree rhs; - - if (AGGREGATE_TYPE_P (return_type)) - rhs = build_compound_literal (loc, return_type, - build_constructor (return_type, 0), - false); - else - rhs = fold_convert_loc (loc, return_type, integer_zero_node); - - return require_complete_type (build2 (COMPOUND_EXPR, return_type, - trap, rhs)); - } + { + tree rhs; + + if (AGGREGATE_TYPE_P (return_type)) + rhs = build_compound_literal (loc, return_type, + build_constructor (return_type, 0), + false); + else + rhs = build_zero_cst (return_type); + + return require_complete_type (build2 (COMPOUND_EXPR, return_type, + trap, rhs)); + } } argarray = VEC_address (tree, params); @@ -2836,10 +2946,18 @@ tree parmval; if (type == void_type_node) - { - error ("too many arguments to function %qE", function); - return parmnum; - } + { + if (selector) + error_at (input_location, + "too many arguments to method %qE", selector); + else + error_at (input_location, + "too many arguments to function %qE", function); + + if (fundecl && !DECL_BUILT_IN (fundecl)) + inform (DECL_SOURCE_LOCATION (fundecl), "declared here"); + return parmnum; + } if (selector && argnum > 2) { @@ -3025,16 +3143,23 @@ } } else if (TREE_CODE (valtype) == REAL_TYPE - && (TYPE_PRECISION (valtype) - < TYPE_PRECISION (double_type_node)) - && !DECIMAL_FLOAT_MODE_P (TYPE_MODE (valtype))) + && (TYPE_PRECISION (valtype) + < TYPE_PRECISION (double_type_node)) + && !DECIMAL_FLOAT_MODE_P (TYPE_MODE (valtype))) { - if (type_generic) - parmval = val; - else - /* Convert `float' to `double'. */ - parmval = convert (double_type_node, val); - } + if (type_generic) + parmval = val; + else + { + /* Convert `float' to `double'. */ + if (warn_double_promotion && !c_inhibit_evaluation_warnings) + warning (OPT_Wdouble_promotion, + "implicit conversion from %qT to %qT when passing " + "argument to function", + valtype, double_type_node); + parmval = convert (double_type_node, val); + } + } else if (excess_precision && !type_generic) /* A "double" argument with excess precision being passed without a prototype or in variable arguments. */ @@ -3067,7 +3192,10 @@ if (typetail != 0 && TREE_VALUE (typetail) != void_type_node) #endif { - error ("too few arguments to function %qE", function); + error_at (input_location, + "too few arguments to function %qE", function); + if (fundecl && !DECL_BUILT_IN (fundecl)) + inform (DECL_SOURCE_LOCATION (fundecl), "declared here"); return -1; } @@ -3435,26 +3563,10 @@ goto return_build_unary_op; case REALPART_EXPR: - if (TREE_CODE (arg) == COMPLEX_CST) - ret = TREE_REALPART (arg); - else if (TREE_CODE (TREE_TYPE (arg)) == COMPLEX_TYPE) - ret = fold_build1_loc (location, - REALPART_EXPR, TREE_TYPE (TREE_TYPE (arg)), arg); - else - ret = arg; - if (eptype && TREE_CODE (eptype) == COMPLEX_TYPE) - eptype = TREE_TYPE (eptype); - goto return_build_unary_op; - case IMAGPART_EXPR: - if (TREE_CODE (arg) == COMPLEX_CST) - ret = TREE_IMAGPART (arg); - else if (TREE_CODE (TREE_TYPE (arg)) == COMPLEX_TYPE) - ret = fold_build1_loc (location, - IMAGPART_EXPR, TREE_TYPE (TREE_TYPE (arg)), arg); - else - ret = omit_one_operand_loc (location, TREE_TYPE (arg), - integer_zero_node, arg); + ret = build_real_imag_expr (location, code, arg); + if (ret == error_mark_node) + return error_mark_node; if (eptype && TREE_CODE (eptype) == COMPLEX_TYPE) eptype = TREE_TYPE (eptype); goto return_build_unary_op; @@ -3477,12 +3589,15 @@ goto return_build_unary_op; } - /* Complain about anything that is not a true lvalue. */ - if (!lvalue_or_else (arg, ((code == PREINCREMENT_EXPR - || code == POSTINCREMENT_EXPR) - ? lv_increment - : lv_decrement))) - return error_mark_node; + /* Complain about anything that is not a true lvalue. In + Objective-C, skip this check for property_refs. */ + if (!objc_is_property_ref (arg) + && !lvalue_or_else (location, + arg, ((code == PREINCREMENT_EXPR + || code == POSTINCREMENT_EXPR) + ? lv_increment + : lv_decrement))) + return error_mark_node; if (warn_cxx_compat && TREE_CODE (TREE_TYPE (arg)) == ENUMERAL_TYPE) { @@ -3531,88 +3646,95 @@ } { - tree inc; - - argtype = TREE_TYPE (arg); - - /* Compute the increment. */ - - if (typecode == POINTER_TYPE) - { - /* If pointer target is an undefined struct, - we just cannot know how to do the arithmetic. */ - if (!COMPLETE_OR_VOID_TYPE_P (TREE_TYPE (argtype))) - { - if (code == PREINCREMENT_EXPR || code == POSTINCREMENT_EXPR) - error_at (location, - "increment of pointer to unknown structure"); - else - error_at (location, - "decrement of pointer to unknown structure"); - } - else if (TREE_CODE (TREE_TYPE (argtype)) == FUNCTION_TYPE - || TREE_CODE (TREE_TYPE (argtype)) == VOID_TYPE) - { - if (code == PREINCREMENT_EXPR || code == POSTINCREMENT_EXPR) - pedwarn (location, pedantic ? OPT_pedantic : OPT_Wpointer_arith, - "wrong type argument to increment"); - else - pedwarn (location, pedantic ? OPT_pedantic : OPT_Wpointer_arith, - "wrong type argument to decrement"); - } - - inc = c_size_in_bytes (TREE_TYPE (argtype)); - inc = fold_convert_loc (location, 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); - } - - /* Report a read-only lvalue. */ - if (TYPE_READONLY (argtype)) - { - readonly_error (arg, - ((code == PREINCREMENT_EXPR - || code == POSTINCREMENT_EXPR) - ? lv_increment : lv_decrement)); - return error_mark_node; - } - else if (TREE_READONLY (arg)) - readonly_warning (arg, - ((code == PREINCREMENT_EXPR - || code == POSTINCREMENT_EXPR) - ? lv_increment : lv_decrement)); - - if (TREE_CODE (TREE_TYPE (arg)) == BOOLEAN_TYPE) - val = boolean_increment (code, arg); - else - val = build2 (code, TREE_TYPE (arg), arg, inc); - TREE_SIDE_EFFECTS (val) = 1; - if (TREE_CODE (val) != code) - TREE_NO_WARNING (val) = 1; - ret = val; - goto return_build_unary_op; + tree inc; + + argtype = TREE_TYPE (arg); + + /* Compute the increment. */ + + if (typecode == POINTER_TYPE) + { + /* If pointer target is an undefined struct, + we just cannot know how to do the arithmetic. */ + if (!COMPLETE_OR_VOID_TYPE_P (TREE_TYPE (argtype))) + { + if (code == PREINCREMENT_EXPR || code == POSTINCREMENT_EXPR) + error_at (location, + "increment of pointer to unknown structure"); + else + error_at (location, + "decrement of pointer to unknown structure"); + } + else if (TREE_CODE (TREE_TYPE (argtype)) == FUNCTION_TYPE + || TREE_CODE (TREE_TYPE (argtype)) == VOID_TYPE) + { + if (code == PREINCREMENT_EXPR || code == POSTINCREMENT_EXPR) + pedwarn (location, pedantic ? OPT_pedantic : OPT_Wpointer_arith, + "wrong type argument to increment"); + else + pedwarn (location, pedantic ? OPT_pedantic : OPT_Wpointer_arith, + "wrong type argument to decrement"); + } + + inc = c_size_in_bytes (TREE_TYPE (argtype)); + inc = fold_convert_loc (location, 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); + } + + /* If 'arg' is an Objective-C PROPERTY_REF expression, then we + need to ask Objective-C to build the increment or decrement + expression for it. */ + if (objc_is_property_ref (arg)) + return objc_build_incr_expr_for_property_ref (location, code, + arg, inc); + + /* Report a read-only lvalue. */ + if (TYPE_READONLY (argtype)) + { + readonly_error (arg, + ((code == PREINCREMENT_EXPR + || code == POSTINCREMENT_EXPR) + ? lv_increment : lv_decrement)); + return error_mark_node; + } + else if (TREE_READONLY (arg)) + readonly_warning (arg, + ((code == PREINCREMENT_EXPR + || code == POSTINCREMENT_EXPR) + ? lv_increment : lv_decrement)); + + if (TREE_CODE (TREE_TYPE (arg)) == BOOLEAN_TYPE) + val = boolean_increment (code, arg); + else + val = build2 (code, TREE_TYPE (arg), arg, inc); + TREE_SIDE_EFFECTS (val) = 1; + if (TREE_CODE (val) != code) + TREE_NO_WARNING (val) = 1; + ret = val; + goto return_build_unary_op; } case ADDR_EXPR: @@ -3654,8 +3776,8 @@ /* Anything not already handled and not a true memory reference or a non-lvalue array is an error. */ else if (typecode != FUNCTION_TYPE && !flag - && !lvalue_or_else (arg, lv_addressof)) - return error_mark_node; + && !lvalue_or_else (location, arg, lv_addressof)) + return error_mark_node; /* Move address operations inside C_MAYBE_CONST_EXPR to simplify folding later. */ @@ -3675,14 +3797,24 @@ argtype = TREE_TYPE (arg); /* If the lvalue is const or volatile, merge that into the type - to which the address will point. Note that you can't get a - restricted pointer by taking the address of something, so we - only have to deal with `const' and `volatile' here. */ + to which the address will point. This should only be needed + for function types. */ if ((DECL_P (arg) || REFERENCE_CLASS_P (arg)) - && (TREE_READONLY (arg) || TREE_THIS_VOLATILE (arg))) - argtype = c_build_type_variant (argtype, - TREE_READONLY (arg), - TREE_THIS_VOLATILE (arg)); + && (TREE_READONLY (arg) || TREE_THIS_VOLATILE (arg))) + { + int orig_quals = TYPE_QUALS (strip_array_types (argtype)); + int quals = orig_quals; + + if (TREE_READONLY (arg)) + quals |= TYPE_QUAL_CONST; + if (TREE_THIS_VOLATILE (arg)) + quals |= TYPE_QUAL_VOLATILE; + + gcc_assert (quals == orig_quals + || TREE_CODE (argtype) == FUNCTION_TYPE); + + argtype = c_build_qualified_type (argtype, quals); + } if (!c_mark_addressable (arg)) return error_mark_node; @@ -3775,44 +3907,6 @@ return 0; } } - -/* Give an error for storing in something that is 'const'. */ - -static void -readonly_error (tree arg, enum lvalue_use use) -{ - gcc_assert (use == lv_assign || use == lv_increment || use == lv_decrement - || use == lv_asm); - /* Using this macro rather than (for example) arrays of messages - ensures that all the format strings are checked at compile - time. */ -#define READONLY_MSG(A, I, D, AS) (use == lv_assign ? (A) \ - : (use == lv_increment ? (I) \ - : (use == lv_decrement ? (D) : (AS)))) - if (TREE_CODE (arg) == COMPONENT_REF) - { - if (TYPE_READONLY (TREE_TYPE (TREE_OPERAND (arg, 0)))) - readonly_error (TREE_OPERAND (arg, 0), use); - else - error (READONLY_MSG (G_("assignment of read-only member %qD"), - G_("increment of read-only member %qD"), - G_("decrement of read-only member %qD"), - G_("read-only member %qD used as %<asm%> output")), - TREE_OPERAND (arg, 1)); - } - else if (TREE_CODE (arg) == VAR_DECL) - error (READONLY_MSG (G_("assignment of read-only variable %qD"), - G_("increment of read-only variable %qD"), - G_("decrement of read-only variable %qD"), - G_("read-only variable %qD used as %<asm%> output")), - arg); - else - 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 %<asm%> output")), - arg); -} /* Give a warning for storing in something that is read-only in GCC terms but not const in ISO C terms. */ @@ -3840,15 +3934,16 @@ /* Return nonzero if REF is an lvalue valid for this language; otherwise, print an error message and return zero. USE says - how the lvalue is being used and so selects the error message. */ + how the lvalue is being used and so selects the error message. + LOCATION is the location at which any error should be reported. */ static int -lvalue_or_else (const_tree ref, enum lvalue_use use) +lvalue_or_else (location_t loc, const_tree ref, enum lvalue_use use) { int win = lvalue_p (ref); if (!win) - lvalue_error (use); + lvalue_error (loc, use); return win; } @@ -3920,6 +4015,34 @@ } } +/* Convert EXPR to TYPE, warning about conversion problems with + constants. SEMANTIC_TYPE is the type this conversion would use + without excess precision. If SEMANTIC_TYPE is NULL, this function + is equivalent to convert_and_check. This function is a wrapper that + handles conversions that may be different than + the usual ones because of excess precision. */ + +static tree +ep_convert_and_check (tree type, tree expr, tree semantic_type) +{ + if (TREE_TYPE (expr) == type) + return expr; + + if (!semantic_type) + return convert_and_check (type, expr); + + if (TREE_CODE (TREE_TYPE (expr)) == INTEGER_TYPE + && TREE_TYPE (expr) != semantic_type) + { + /* For integers, we need to check the real conversion, not + the conversion to the excess precision type. */ + expr = convert_and_check (semantic_type, expr); + } + /* Result type is the excess precision type, which should be + large enough, so do not check. */ + return convert (type, expr); +} + /* Build and return a conditional expression IFEXP ? OP1 : OP2. If IFEXP_BCP then the condition is a call to __builtin_constant_p, and if folded to an integer constant then the unselected half may @@ -3936,12 +4059,11 @@ enum tree_code code1; enum tree_code code2; tree result_type = NULL; - tree ep_result_type = NULL; + tree semantic_result_type = NULL; tree orig_op1 = op1, orig_op2 = op2; bool int_const, op1_int_operands, op2_int_operands, int_operands; bool ifexp_int_operands; tree ret; - bool objc_ok; op1_int_operands = EXPR_INT_CONST_OPERANDS (orig_op1); if (op1_int_operands) @@ -3978,8 +4100,6 @@ return error_mark_node; } - objc_ok = objc_compare_types (type1, type2, -3, NULL_TREE); - if ((TREE_CODE (op1) == EXCESS_PRECISION_EXPR || TREE_CODE (op2) == EXCESS_PRECISION_EXPR) && (code1 == INTEGER_TYPE || code1 == REAL_TYPE @@ -3987,7 +4107,7 @@ && (code2 == INTEGER_TYPE || code2 == REAL_TYPE || code2 == COMPLEX_TYPE)) { - ep_result_type = c_common_type (type1, type2); + semantic_result_type = c_common_type (type1, type2); if (TREE_CODE (op1) == EXCESS_PRECISION_EXPR) { op1 = TREE_OPERAND (op1, 0); @@ -4031,6 +4151,10 @@ || code2 == COMPLEX_TYPE)) { result_type = c_common_type (type1, type2); + do_warn_double_promotion (result_type, type1, type2, + "implicit conversion from %qT to %qT to " + "match other result of conditional", + colon_loc); /* If -Wsign-compare, warn here if type1 and type2 have different signedness. We'll promote the signed to unsigned @@ -4133,24 +4257,26 @@ TREE_TYPE (type2))); } else if (VOID_TYPE_P (TREE_TYPE (type2))) - { - if (TREE_CODE (TREE_TYPE (type1)) == FUNCTION_TYPE) - pedwarn (colon_loc, OPT_pedantic, - "ISO C forbids conditional expr between " - "%<void *%> and function pointer"); - result_type = build_pointer_type (qualify_type (TREE_TYPE (type2), - TREE_TYPE (type1))); - } + { + if (TREE_CODE (TREE_TYPE (type1)) == FUNCTION_TYPE) + pedwarn (colon_loc, OPT_pedantic, + "ISO C forbids conditional expr between " + "%<void *%> and function pointer"); + result_type = build_pointer_type (qualify_type (TREE_TYPE (type2), + TREE_TYPE (type1))); + } + /* Objective-C pointer comparisons are a bit more lenient. */ + else if (objc_have_common_type (type1, type2, -3, NULL_TREE)) + result_type = objc_common_type (type1, type2); else - { - int qual = ENCODE_QUAL_ADDR_SPACE (as_common); - - if (!objc_ok) - pedwarn (colon_loc, 0, - "pointer type mismatch in conditional expression"); - result_type = build_pointer_type - (build_qualified_type (void_type_node, qual)); - } + { + int qual = ENCODE_QUAL_ADDR_SPACE (as_common); + + pedwarn (colon_loc, 0, + "pointer type mismatch in conditional expression"); + result_type = build_pointer_type + (build_qualified_type (void_type_node, qual)); + } } else if (code1 == POINTER_TYPE && code2 == INTEGER_TYPE) { @@ -4192,10 +4318,8 @@ TYPE_READONLY (type1) || TYPE_READONLY (type2), TYPE_VOLATILE (type1) || TYPE_VOLATILE (type2)); - if (result_type != type1) - op1 = convert_and_check (result_type, op1); - if (result_type != type2) - op2 = convert_and_check (result_type, op2); + op1 = ep_convert_and_check (result_type, op1, semantic_result_type); + op2 = ep_convert_and_check (result_type, op2, semantic_result_type); if (ifexp_bcp && ifexp == truthvalue_true_node) { @@ -4227,8 +4351,8 @@ if (int_operands) ret = note_integer_operands (ret); } - if (ep_result_type) - ret = build1 (EXCESS_PRECISION_EXPR, ep_result_type, ret); + if (semantic_result_type) + ret = build1 (EXCESS_PRECISION_EXPR, semantic_result_type, ret); protected_set_expr_location (ret, colon_loc); return ret; @@ -4307,12 +4431,13 @@ /* Issue -Wcast-qual warnings when appropriate. TYPE is the type to which we are casting. OTYPE is the type of the expression being - cast. Both TYPE and OTYPE are pointer types. -Wcast-qual appeared - on the command line. Named address space qualifiers are not handled - here, because they result in different warnings. */ + cast. Both TYPE and OTYPE are pointer types. LOC is the location + of the cast. -Wcast-qual appeared on the command line. Named + address space qualifiers are not handled here, because they result + in different warnings. */ static void -handle_warn_cast_qual (tree type, tree otype) +handle_warn_cast_qual (location_t loc, tree type, tree otype) { tree in_type = type; tree in_otype = otype; @@ -4345,13 +4470,15 @@ && TREE_CODE (in_otype) == POINTER_TYPE); if (added) - warning (OPT_Wcast_qual, "cast adds new qualifiers to function type"); + warning_at (loc, OPT_Wcast_qual, + "cast adds %q#v qualifier to function type", added); if (discarded) /* There are qualifiers present in IN_OTYPE that are not present in IN_TYPE. */ - warning (OPT_Wcast_qual, - "cast discards qualifiers from pointer target type"); + warning_at (loc, OPT_Wcast_qual, + "cast discards %q#v qualifier from pointer target type", + discarded); if (added || discarded) return; @@ -4382,13 +4509,14 @@ in_type = TREE_TYPE (in_type); in_otype = TREE_TYPE (in_otype); if ((TYPE_QUALS (in_type) &~ TYPE_QUALS (in_otype)) != 0 - && !is_const) - { - warning (OPT_Wcast_qual, - ("new qualifiers in middle of multi-level non-const cast " - "are unsafe")); - break; - } + && !is_const) + { + warning_at (loc, OPT_Wcast_qual, + "to be safe all intermediate pointers in cast from " + "%qT to %qT must be %<const%> qualified", + otype, type); + break; + } if (is_const) is_const = TYPE_READONLY (in_type); } @@ -4449,23 +4577,27 @@ { tree field; - for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field)) - if (TREE_TYPE (field) != error_mark_node - && comptypes (TYPE_MAIN_VARIANT (TREE_TYPE (field)), - TYPE_MAIN_VARIANT (TREE_TYPE (value)))) - break; + for (field = TYPE_FIELDS (type); field; field = DECL_CHAIN (field)) + 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; - - pedwarn (loc, OPT_pedantic, "ISO C forbids casts to union type"); - t = digest_init (loc, type, - build_constructor_single (type, field, value), - NULL_TREE, false, true, 0); - TREE_CONSTANT (t) = TREE_CONSTANT (value); - return t; - } + { + tree t; + bool maybe_const = true; + + pedwarn (loc, OPT_pedantic, "ISO C forbids casts to union type"); + t = c_fully_fold (value, false, &maybe_const); + t = build_constructor_single (type, field, t); + if (!maybe_const) + t = c_wrap_maybe_const (t, true); + t = digest_init (loc, type, t, + NULL_TREE, false, true, 0); + TREE_CONSTANT (t) = TREE_CONSTANT (value); + return t; + } error_at (loc, "cast to union type from type not present in union"); return error_mark_node; } @@ -4484,9 +4616,9 @@ /* Optionally warn about potentially worrisome casts. */ if (warn_cast_qual - && TREE_CODE (type) == POINTER_TYPE - && TREE_CODE (otype) == POINTER_TYPE) - handle_warn_cast_qual (type, otype); + && TREE_CODE (type) == POINTER_TYPE + && TREE_CODE (otype) == POINTER_TYPE) + handle_warn_cast_qual (loc, type, otype); /* Warn about conversions between pointers to disjoint address spaces. */ @@ -4658,8 +4790,9 @@ if (CAN_HAVE_LOCATION_P (ret) && !EXPR_HAS_LOCATION (ret)) SET_EXPR_LOCATION (ret, loc); - /* C++ does not permits types to be defined in a cast. */ - if (warn_cxx_compat && type_name->specs->tag_defined_p) + /* C++ does not permits types to be defined in a cast, but it + allows references to incomplete types. */ + if (warn_cxx_compat && type_name->specs->typespec_kind == ctsk_tagdef) warning_at (loc, OPT_Wc___compat, "defining a type in a cast is invalid in C++"); @@ -4697,7 +4830,8 @@ if (TREE_CODE (lhs) == ERROR_MARK || TREE_CODE (rhs) == ERROR_MARK) return error_mark_node; - if (!lvalue_or_else (lhs, lv_assign)) + /* For ObjC properties, defer this check. */ + if (!objc_is_property_ref (lhs) && !lvalue_or_else (location, lhs, lv_assign)) return error_mark_node; if (TREE_CODE (rhs) == EXCESS_PRECISION_EXPR) @@ -4738,6 +4872,19 @@ rhs_origtype = NULL_TREE; } + if (c_dialect_objc ()) + { + /* Check if we are modifying an Objective-C property reference; + if so, we need to generate setter calls. */ + result = objc_maybe_build_modify_expr (lhs, newrhs); + if (result) + return result; + + /* Else, do the check that we postponed for Objective-C. */ + if (!lvalue_or_else (location, lhs, lv_assign)) + return error_mark_node; + } + /* Give an error for storing in something that is 'const'. */ if (TYPE_READONLY (lhstype) @@ -4833,6 +4980,106 @@ return result; } +/* Return whether STRUCT_TYPE has an anonymous field with type TYPE. + This is used to implement -fplan9-extensions. */ + +static bool +find_anonymous_field_with_type (tree struct_type, tree type) +{ + tree field; + bool found; + + gcc_assert (TREE_CODE (struct_type) == RECORD_TYPE + || TREE_CODE (struct_type) == UNION_TYPE); + found = false; + for (field = TYPE_FIELDS (struct_type); + field != NULL_TREE; + field = TREE_CHAIN (field)) + { + if (DECL_NAME (field) == NULL + && comptypes (type, TYPE_MAIN_VARIANT (TREE_TYPE (field)))) + { + if (found) + return false; + found = true; + } + else if (DECL_NAME (field) == NULL + && (TREE_CODE (TREE_TYPE (field)) == RECORD_TYPE + || TREE_CODE (TREE_TYPE (field)) == UNION_TYPE) + && find_anonymous_field_with_type (TREE_TYPE (field), type)) + { + if (found) + return false; + found = true; + } + } + return found; +} + +/* RHS is an expression whose type is pointer to struct. If there is + an anonymous field in RHS with type TYPE, then return a pointer to + that field in RHS. This is used with -fplan9-extensions. This + returns NULL if no conversion could be found. */ + +static tree +convert_to_anonymous_field (location_t location, tree type, tree rhs) +{ + tree rhs_struct_type, lhs_main_type; + tree field, found_field; + bool found_sub_field; + tree ret; + + gcc_assert (POINTER_TYPE_P (TREE_TYPE (rhs))); + rhs_struct_type = TREE_TYPE (TREE_TYPE (rhs)); + gcc_assert (TREE_CODE (rhs_struct_type) == RECORD_TYPE + || TREE_CODE (rhs_struct_type) == UNION_TYPE); + + gcc_assert (POINTER_TYPE_P (type)); + lhs_main_type = TYPE_MAIN_VARIANT (TREE_TYPE (type)); + + found_field = NULL_TREE; + found_sub_field = false; + for (field = TYPE_FIELDS (rhs_struct_type); + field != NULL_TREE; + field = TREE_CHAIN (field)) + { + if (DECL_NAME (field) != NULL_TREE + || (TREE_CODE (TREE_TYPE (field)) != RECORD_TYPE + && TREE_CODE (TREE_TYPE (field)) != UNION_TYPE)) + continue; + if (comptypes (lhs_main_type, TYPE_MAIN_VARIANT (TREE_TYPE (field)))) + { + if (found_field != NULL_TREE) + return NULL_TREE; + found_field = field; + } + else if (find_anonymous_field_with_type (TREE_TYPE (field), + lhs_main_type)) + { + if (found_field != NULL_TREE) + return NULL_TREE; + found_field = field; + found_sub_field = true; + } + } + + if (found_field == NULL_TREE) + return NULL_TREE; + + ret = fold_build3_loc (location, COMPONENT_REF, TREE_TYPE (found_field), + build_fold_indirect_ref (rhs), found_field, + NULL_TREE); + ret = build_fold_addr_expr_loc (location, ret); + + if (found_sub_field) + { + ret = convert_to_anonymous_field (location, type, ret); + gcc_assert (ret != NULL_TREE); + } + + return ret; +} + /* Convert value RHS to type TYPE as preparation for an assignment to an lvalue of type TYPE. If ORIGTYPE is not NULL_TREE, it is the original type of RHS; this differs from TREE_TYPE (RHS) for enum @@ -4898,7 +5145,7 @@ pedwarn (LOCATION, OPT, AS); \ break; \ case ic_init: \ - pedwarn (LOCATION, OPT, IN); \ + pedwarn_init (LOCATION, OPT, IN); \ break; \ case ic_return: \ pedwarn (LOCATION, OPT, RE); \ @@ -4908,6 +5155,36 @@ } \ } while (0) + /* This macro is used to emit diagnostics to ensure that all format + strings are complete sentences, visible to gettext and checked at + compile time. It is the same as WARN_FOR_ASSIGNMENT but with an + extra parameter to enumerate qualifiers. */ + +#define WARN_FOR_QUALIFIERS(LOCATION, OPT, AR, AS, IN, RE, QUALS) \ + do { \ + switch (errtype) \ + { \ + case ic_argpass: \ + if (pedwarn (LOCATION, OPT, AR, parmnum, rname, QUALS)) \ + 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, QUALS); \ + break; \ + case ic_init: \ + pedwarn (LOCATION, OPT, IN, QUALS); \ + break; \ + case ic_return: \ + pedwarn (LOCATION, OPT, RE, QUALS); \ + break; \ + default: \ + gcc_unreachable (); \ + } \ + } while (0) + if (TREE_CODE (rhs) == EXCESS_PRECISION_EXPR) rhs = TREE_OPERAND (rhs, 0); @@ -5025,11 +5302,11 @@ { tree ret; bool save = in_late_binary_op; - if (codel == BOOLEAN_TYPE) - in_late_binary_op = true; + if (codel == BOOLEAN_TYPE || codel == COMPLEX_TYPE) + in_late_binary_op = true; ret = convert_and_check (type, orig_rhs); - if (codel == BOOLEAN_TYPE) - in_late_binary_op = save; + if (codel == BOOLEAN_TYPE || codel == COMPLEX_TYPE) + in_late_binary_op = save; return ret; } @@ -5039,116 +5316,118 @@ && comptypes (type, rhstype)) return convert_and_check (type, rhs); - /* Conversion to a transparent union from its member types. + /* Conversion to a transparent union or record from its member types. This applies only to function arguments. */ - if (codel == UNION_TYPE && TYPE_TRANSPARENT_UNION (type) + if (((codel == UNION_TYPE || codel == RECORD_TYPE) + && TYPE_TRANSPARENT_AGGR (type)) && errtype == ic_argpass) { tree memb, marginal_memb = NULL_TREE; - for (memb = TYPE_FIELDS (type); memb ; memb = TREE_CHAIN (memb)) - { - tree memb_type = TREE_TYPE (memb); - - if (comptypes (TYPE_MAIN_VARIANT (memb_type), - TYPE_MAIN_VARIANT (rhstype))) - break; - - if (TREE_CODE (memb_type) != POINTER_TYPE) - continue; - - if (coder == POINTER_TYPE) - { - tree ttl = TREE_TYPE (memb_type); - tree ttr = TREE_TYPE (rhstype); - - /* Any non-function converts to a [const][volatile] void * - and vice versa; otherwise, targets must be the same. - Meanwhile, the lhs target must have all the qualifiers of - the rhs. */ - if (VOID_TYPE_P (ttl) || VOID_TYPE_P (ttr) - || comp_target_types (location, memb_type, rhstype)) - { - /* If this type won't generate any warnings, use it. */ - if (TYPE_QUALS (ttl) == TYPE_QUALS (ttr) - || ((TREE_CODE (ttr) == FUNCTION_TYPE - && TREE_CODE (ttl) == FUNCTION_TYPE) - ? ((TYPE_QUALS (ttl) | TYPE_QUALS (ttr)) - == TYPE_QUALS (ttr)) - : ((TYPE_QUALS (ttl) | TYPE_QUALS (ttr)) - == TYPE_QUALS (ttl)))) - break; - - /* Keep looking for a better type, but remember this one. */ - if (!marginal_memb) - marginal_memb = memb; - } - } - - /* Can convert integer zero to any pointer type. */ - if (null_pointer_constant) - { - rhs = null_pointer_node; - break; - } - } + for (memb = TYPE_FIELDS (type); memb ; memb = DECL_CHAIN (memb)) + { + tree memb_type = TREE_TYPE (memb); + + if (comptypes (TYPE_MAIN_VARIANT (memb_type), + TYPE_MAIN_VARIANT (rhstype))) + break; + + if (TREE_CODE (memb_type) != POINTER_TYPE) + continue; + + if (coder == POINTER_TYPE) + { + tree ttl = TREE_TYPE (memb_type); + tree ttr = TREE_TYPE (rhstype); + + /* Any non-function converts to a [const][volatile] void * + and vice versa; otherwise, targets must be the same. + Meanwhile, the lhs target must have all the qualifiers of + the rhs. */ + if (VOID_TYPE_P (ttl) || VOID_TYPE_P (ttr) + || comp_target_types (location, memb_type, rhstype)) + { + /* If this type won't generate any warnings, use it. */ + if (TYPE_QUALS (ttl) == TYPE_QUALS (ttr) + || ((TREE_CODE (ttr) == FUNCTION_TYPE + && TREE_CODE (ttl) == FUNCTION_TYPE) + ? ((TYPE_QUALS (ttl) | TYPE_QUALS (ttr)) + == TYPE_QUALS (ttr)) + : ((TYPE_QUALS (ttl) | TYPE_QUALS (ttr)) + == TYPE_QUALS (ttl)))) + break; + + /* Keep looking for a better type, but remember this one. */ + if (!marginal_memb) + marginal_memb = memb; + } + } + + /* Can convert integer zero to any pointer type. */ + if (null_pointer_constant) + { + rhs = null_pointer_node; + break; + } + } if (memb || marginal_memb) - { - if (!memb) - { - /* We have only a marginally acceptable member type; - it needs a warning. */ - tree ttl = TREE_TYPE (TREE_TYPE (marginal_memb)); - tree ttr = TREE_TYPE (rhstype); - - /* Const and volatile mean something different for function - types, so the usual warnings are not appropriate. */ - if (TREE_CODE (ttr) == FUNCTION_TYPE - && TREE_CODE (ttl) == FUNCTION_TYPE) - { - /* Because const and volatile on functions are - restrictions that say the function will not do - certain things, it is okay to use a const or volatile - function where an ordinary one is wanted, but not - vice-versa. */ - if (TYPE_QUALS_NO_ADDR_SPACE (ttl) - & ~TYPE_QUALS_NO_ADDR_SPACE (ttr)) - WARN_FOR_ASSIGNMENT (location, 0, - G_("passing argument %d of %qE " - "makes qualified function " - "pointer from unqualified"), - G_("assignment makes qualified " - "function pointer from " - "unqualified"), - G_("initialization makes qualified " - "function pointer from " - "unqualified"), - G_("return makes qualified function " - "pointer from unqualified")); - } - else if (TYPE_QUALS_NO_ADDR_SPACE (ttr) - & ~TYPE_QUALS_NO_ADDR_SPACE (ttl)) - WARN_FOR_ASSIGNMENT (location, 0, - G_("passing argument %d of %qE discards " - "qualifiers from pointer target type"), - G_("assignment discards qualifiers " - "from pointer target type"), - G_("initialization discards qualifiers " - "from pointer target type"), - G_("return discards qualifiers from " - "pointer target type")); - - memb = marginal_memb; - } - - if (!fundecl || !DECL_IN_SYSTEM_HEADER (fundecl)) - pedwarn (location, OPT_pedantic, - "ISO C prohibits argument conversion to union type"); - - rhs = fold_convert_loc (location, TREE_TYPE (memb), rhs); - return build_constructor_single (type, memb, rhs); - } + { + if (!memb) + { + /* We have only a marginally acceptable member type; + it needs a warning. */ + tree ttl = TREE_TYPE (TREE_TYPE (marginal_memb)); + tree ttr = TREE_TYPE (rhstype); + + /* Const and volatile mean something different for function + types, so the usual warnings are not appropriate. */ + if (TREE_CODE (ttr) == FUNCTION_TYPE + && TREE_CODE (ttl) == FUNCTION_TYPE) + { + /* Because const and volatile on functions are + restrictions that say the function will not do + certain things, it is okay to use a const or volatile + function where an ordinary one is wanted, but not + vice-versa. */ + if (TYPE_QUALS_NO_ADDR_SPACE (ttl) + & ~TYPE_QUALS_NO_ADDR_SPACE (ttr)) + WARN_FOR_QUALIFIERS (location, 0, + G_("passing argument %d of %qE " + "makes %q#v qualified function " + "pointer from unqualified"), + G_("assignment makes %q#v qualified " + "function pointer from " + "unqualified"), + G_("initialization makes %q#v qualified " + "function pointer from " + "unqualified"), + G_("return makes %q#v qualified function " + "pointer from unqualified"), + TYPE_QUALS (ttl) & ~TYPE_QUALS (ttr)); + } + else if (TYPE_QUALS_NO_ADDR_SPACE (ttr) + & ~TYPE_QUALS_NO_ADDR_SPACE (ttl)) + WARN_FOR_QUALIFIERS (location, 0, + G_("passing argument %d of %qE discards " + "%qv qualifier from pointer target type"), + G_("assignment discards %qv qualifier " + "from pointer target type"), + G_("initialization discards %qv qualifier " + "from pointer target type"), + G_("return discards %qv qualifier from " + "pointer target type"), + TYPE_QUALS (ttr) & ~TYPE_QUALS (ttl)); + memb = marginal_memb; + } + + if (!fundecl || !DECL_IN_SYSTEM_HEADER (fundecl)) + pedwarn (location, OPT_pedantic, + "ISO C prohibits argument conversion to union type"); + + rhs = fold_convert_loc (location, TREE_TYPE (memb), rhs); + return build_constructor_single (type, memb, rhs); + } } /* Conversions among pointers */ @@ -5171,6 +5450,25 @@ /* Opaque pointers are treated like void pointers. */ is_opaque_pointer = vector_targets_convertible_p (ttl, ttr); + /* The Plan 9 compiler permits a pointer to a struct to be + automatically converted into a pointer to an anonymous field + within the struct. */ + if (flag_plan9_extensions + && (TREE_CODE (mvl) == RECORD_TYPE || TREE_CODE(mvl) == UNION_TYPE) + && (TREE_CODE (mvr) == RECORD_TYPE || TREE_CODE(mvr) == UNION_TYPE) + && mvl != mvr) + { + tree new_rhs = convert_to_anonymous_field (location, type, rhs); + if (new_rhs != NULL_TREE) + { + rhs = new_rhs; + rhstype = TREE_TYPE (rhs); + coder = TREE_CODE (rhstype); + ttr = TREE_TYPE (rhstype); + mvr = TYPE_MAIN_VARIANT (ttr); + } + } + /* C++ does not allow the implicit conversion void* -> T*. However, for the purpose of reducing the number of false positives, we tolerate the special case of @@ -5250,87 +5548,85 @@ and vice versa; otherwise, targets must be the same. Meanwhile, the lhs target must have all the qualifiers of the rhs. */ if (VOID_TYPE_P (ttl) || VOID_TYPE_P (ttr) - || (target_cmp = comp_target_types (location, type, rhstype)) - || is_opaque_pointer - || (c_common_unsigned_type (mvl) - == c_common_unsigned_type (mvr))) - { - if (pedantic - && ((VOID_TYPE_P (ttl) && TREE_CODE (ttr) == FUNCTION_TYPE) - || - (VOID_TYPE_P (ttr) - && !null_pointer_constant - && TREE_CODE (ttl) == FUNCTION_TYPE))) - WARN_FOR_ASSIGNMENT (location, OPT_pedantic, - G_("ISO C forbids passing argument %d of " - "%qE between function pointer " - "and %<void *%>"), - G_("ISO C forbids assignment between " - "function pointer and %<void *%>"), - G_("ISO C forbids initialization between " - "function pointer and %<void *%>"), - G_("ISO C forbids return between function " - "pointer and %<void *%>")); - /* Const and volatile mean something different for function types, - so the usual warnings are not appropriate. */ - else if (TREE_CODE (ttr) != FUNCTION_TYPE - && TREE_CODE (ttl) != FUNCTION_TYPE) - { - if (TYPE_QUALS_NO_ADDR_SPACE (ttr) - & ~TYPE_QUALS_NO_ADDR_SPACE (ttl)) - { - /* Types differing only by the presence of the 'volatile' - qualifier are acceptable if the 'volatile' has been added - in by the Objective-C EH machinery. */ - if (!objc_type_quals_match (ttl, ttr)) - WARN_FOR_ASSIGNMENT (location, 0, - G_("passing argument %d of %qE discards " - "qualifiers from pointer target type"), - G_("assignment discards qualifiers " - "from pointer target type"), - G_("initialization discards qualifiers " - "from pointer target type"), - G_("return discards qualifiers from " - "pointer target type")); - } - /* If this is not a case of ignoring a mismatch in signedness, - no warning. */ - else if (VOID_TYPE_P (ttl) || VOID_TYPE_P (ttr) - || target_cmp) - ; - /* If there is a mismatch, do warn. */ - else if (warn_pointer_sign) - WARN_FOR_ASSIGNMENT (location, OPT_Wpointer_sign, - G_("pointer targets in passing argument " - "%d of %qE differ in signedness"), - G_("pointer targets in assignment " - "differ in signedness"), - G_("pointer targets in initialization " - "differ in signedness"), - G_("pointer targets in return differ " - "in signedness")); - } - else if (TREE_CODE (ttl) == FUNCTION_TYPE - && TREE_CODE (ttr) == FUNCTION_TYPE) - { - /* Because const and volatile on functions are restrictions - that say the function will not do certain things, - it is okay to use a const or volatile function - where an ordinary one is wanted, but not vice-versa. */ - if (TYPE_QUALS_NO_ADDR_SPACE (ttl) - & ~TYPE_QUALS_NO_ADDR_SPACE (ttr)) - WARN_FOR_ASSIGNMENT (location, 0, - G_("passing argument %d of %qE makes " - "qualified function pointer " - "from unqualified"), - G_("assignment makes qualified function " - "pointer from unqualified"), - G_("initialization makes qualified " - "function pointer from unqualified"), - G_("return makes qualified function " - "pointer from unqualified")); - } - } + || (target_cmp = comp_target_types (location, type, rhstype)) + || is_opaque_pointer + || (c_common_unsigned_type (mvl) + == c_common_unsigned_type (mvr))) + { + if (pedantic + && ((VOID_TYPE_P (ttl) && TREE_CODE (ttr) == FUNCTION_TYPE) + || + (VOID_TYPE_P (ttr) + && !null_pointer_constant + && TREE_CODE (ttl) == FUNCTION_TYPE))) + WARN_FOR_ASSIGNMENT (location, OPT_pedantic, + G_("ISO C forbids passing argument %d of " + "%qE between function pointer " + "and %<void *%>"), + G_("ISO C forbids assignment between " + "function pointer and %<void *%>"), + G_("ISO C forbids initialization between " + "function pointer and %<void *%>"), + G_("ISO C forbids return between function " + "pointer and %<void *%>")); + /* Const and volatile mean something different for function types, + so the usual warnings are not appropriate. */ + else if (TREE_CODE (ttr) != FUNCTION_TYPE + && TREE_CODE (ttl) != FUNCTION_TYPE) + { + if (TYPE_QUALS_NO_ADDR_SPACE (ttr) + & ~TYPE_QUALS_NO_ADDR_SPACE (ttl)) + { + WARN_FOR_QUALIFIERS (location, 0, + G_("passing argument %d of %qE discards " + "%qv qualifier from pointer target type"), + G_("assignment discards %qv qualifier " + "from pointer target type"), + G_("initialization discards %qv qualifier " + "from pointer target type"), + G_("return discards %qv qualifier from " + "pointer target type"), + TYPE_QUALS (ttr) & ~TYPE_QUALS (ttl)); + } + /* If this is not a case of ignoring a mismatch in signedness, + no warning. */ + else if (VOID_TYPE_P (ttl) || VOID_TYPE_P (ttr) + || target_cmp) + ; + /* If there is a mismatch, do warn. */ + else if (warn_pointer_sign) + WARN_FOR_ASSIGNMENT (location, OPT_Wpointer_sign, + G_("pointer targets in passing argument " + "%d of %qE differ in signedness"), + G_("pointer targets in assignment " + "differ in signedness"), + G_("pointer targets in initialization " + "differ in signedness"), + G_("pointer targets in return differ " + "in signedness")); + } + else if (TREE_CODE (ttl) == FUNCTION_TYPE + && TREE_CODE (ttr) == FUNCTION_TYPE) + { + /* Because const and volatile on functions are restrictions + that say the function will not do certain things, + it is okay to use a const or volatile function + where an ordinary one is wanted, but not vice-versa. */ + if (TYPE_QUALS_NO_ADDR_SPACE (ttl) + & ~TYPE_QUALS_NO_ADDR_SPACE (ttr)) + WARN_FOR_QUALIFIERS (location, 0, + G_("passing argument %d of %qE makes " + "%q#v qualified function pointer " + "from unqualified"), + G_("assignment makes %q#v qualified function " + "pointer from unqualified"), + G_("initialization makes %q#v qualified " + "function pointer from unqualified"), + G_("return makes %q#v qualified function " + "pointer from unqualified"), + TYPE_QUALS (ttl) & ~TYPE_QUALS (ttr)); + } + } else /* Avoid warning about the volatile ObjC EH puts on decls. */ if (!objc_ok) @@ -5637,15 +5933,16 @@ } /* Issue an error message for a bad initializer component. - MSGID identifies the message. + GMSGID identifies the message. The component name is taken from the spelling stack. */ void -error_init (const char *msgid) +error_init (const char *gmsgid) { char *ofwhat; - error ("%s", _(msgid)); + /* The gmsgid may be a format string with %< and %>. */ + error (gmsgid); ofwhat = print_spelling ((char *) alloca (spelling_length () + 1)); if (*ofwhat) error ("(near initialization for %qs)", ofwhat); @@ -5653,15 +5950,16 @@ /* 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 + it is unconditionally given. GMSGID identifies the message. The component name is taken from the spelling stack. */ void -pedwarn_init (location_t location, int opt, const char *msgid) +pedwarn_init (location_t location, int opt, const char *gmsgid) { char *ofwhat; - - pedwarn (location, opt, "%s", _(msgid)); + + /* The gmsgid may be a format string with %< and %>. */ + pedwarn (location, opt, gmsgid); ofwhat = print_spelling ((char *) alloca (spelling_length () + 1)); if (*ofwhat) pedwarn (location, opt, "(near initialization for %qs)", ofwhat); @@ -5670,15 +5968,16 @@ /* 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 + controls this warning. GMSGID identifies the message. The component name is taken from the spelling stack. */ static void -warning_init (int opt, const char *msgid) +warning_init (int opt, const char *gmsgid) { char *ofwhat; - warning (opt, "%s", _(msgid)); + /* The gmsgid may be a format string with %< and %>. */ + warning (opt, gmsgid); ofwhat = print_spelling ((char *) alloca (spelling_length () + 1)); if (*ofwhat) warning (opt, "(near initialization for %qs)", ofwhat); @@ -6329,8 +6628,8 @@ constructor_fields = TYPE_FIELDS (constructor_type); /* Skip any nameless bit fields at the beginning. */ while (constructor_fields != 0 && DECL_C_BIT_FIELD (constructor_fields) - && DECL_NAME (constructor_fields) == 0) - constructor_fields = TREE_CHAIN (constructor_fields); + && DECL_NAME (constructor_fields) == 0) + constructor_fields = DECL_CHAIN (constructor_fields); constructor_unfilled_fields = constructor_fields; constructor_bit_index = bitsize_zero_node; @@ -6338,26 +6637,26 @@ else if (TREE_CODE (constructor_type) == ARRAY_TYPE) { if (TYPE_DOMAIN (constructor_type)) - { - constructor_max_index - = TYPE_MAX_VALUE (TYPE_DOMAIN (constructor_type)); - - /* Detect non-empty initializations of zero-length arrays. */ - if (constructor_max_index == NULL_TREE - && TYPE_SIZE (constructor_type)) - constructor_max_index = build_int_cst (NULL_TREE, -1); - - /* constructor_max_index needs to be an INTEGER_CST. Attempts - to initialize VLAs will cause a proper error; avoid tree - checking errors as well by setting a safe value. */ - if (constructor_max_index - && TREE_CODE (constructor_max_index) != INTEGER_CST) - constructor_max_index = build_int_cst (NULL_TREE, -1); - - constructor_index - = convert (bitsizetype, - TYPE_MIN_VALUE (TYPE_DOMAIN (constructor_type))); - } + { + constructor_max_index + = TYPE_MAX_VALUE (TYPE_DOMAIN (constructor_type)); + + /* Detect non-empty initializations of zero-length arrays. */ + if (constructor_max_index == NULL_TREE + && TYPE_SIZE (constructor_type)) + constructor_max_index = integer_minus_one_node; + + /* constructor_max_index needs to be an INTEGER_CST. Attempts + to initialize VLAs will cause a proper error; avoid tree + checking errors as well by setting a safe value. */ + if (constructor_max_index + && TREE_CODE (constructor_max_index) != INTEGER_CST) + constructor_max_index = integer_minus_one_node; + + constructor_index + = convert (bitsizetype, + TYPE_MIN_VALUE (TYPE_DOMAIN (constructor_type))); + } else { constructor_index = bitsize_zero_node; @@ -6388,7 +6687,7 @@ IMPLICIT is 1 (or 2 if the push is because of designator list). */ void -push_init_level (int implicit) +push_init_level (int implicit, struct obstack * braced_init_obstack) { struct constructor_stack *p; tree value = NULL_TREE; @@ -6402,19 +6701,21 @@ if (implicit != 1) { while (constructor_stack->implicit) - { - if ((TREE_CODE (constructor_type) == RECORD_TYPE - || TREE_CODE (constructor_type) == UNION_TYPE) - && constructor_fields == 0) - process_init_element (pop_init_level (1), 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), true); - else - break; - } + { + if ((TREE_CODE (constructor_type) == RECORD_TYPE + || TREE_CODE (constructor_type) == UNION_TYPE) + && constructor_fields == 0) + process_init_element (pop_init_level (1, braced_init_obstack), + true, braced_init_obstack); + 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, braced_init_obstack), + true, braced_init_obstack); + else + break; + } } /* Unless this is an explicit brace, we need to preserve previous @@ -6422,11 +6723,11 @@ if (implicit) { if ((TREE_CODE (constructor_type) == RECORD_TYPE - || TREE_CODE (constructor_type) == UNION_TYPE) - && constructor_fields) - value = find_init_member (constructor_fields); + || TREE_CODE (constructor_type) == UNION_TYPE) + && constructor_fields) + value = find_init_member (constructor_fields, braced_init_obstack); else if (TREE_CODE (constructor_type) == ARRAY_TYPE) - value = find_init_member (constructor_index); + value = find_init_member (constructor_index, braced_init_obstack); } p = XNEW (struct constructor_stack); @@ -6510,9 +6811,9 @@ constructor_nonconst = CONSTRUCTOR_NON_CONST (value); constructor_elements = CONSTRUCTOR_ELTS (value); if (!VEC_empty (constructor_elt, constructor_elements) - && (TREE_CODE (constructor_type) == RECORD_TYPE - || TREE_CODE (constructor_type) == ARRAY_TYPE)) - set_nonincremental_init (); + && (TREE_CODE (constructor_type) == RECORD_TYPE + || TREE_CODE (constructor_type) == ARRAY_TYPE)) + set_nonincremental_init (braced_init_obstack); } if (implicit == 1 && warn_missing_braces && !missing_braces_mentioned) @@ -6527,8 +6828,8 @@ constructor_fields = TYPE_FIELDS (constructor_type); /* Skip any nameless bit fields at the beginning. */ while (constructor_fields != 0 && DECL_C_BIT_FIELD (constructor_fields) - && DECL_NAME (constructor_fields) == 0) - constructor_fields = TREE_CHAIN (constructor_fields); + && DECL_NAME (constructor_fields) == 0) + constructor_fields = DECL_CHAIN (constructor_fields); constructor_unfilled_fields = constructor_fields; constructor_bit_index = bitsize_zero_node; @@ -6544,37 +6845,37 @@ else if (TREE_CODE (constructor_type) == ARRAY_TYPE) { if (TYPE_DOMAIN (constructor_type)) - { - constructor_max_index - = TYPE_MAX_VALUE (TYPE_DOMAIN (constructor_type)); - - /* Detect non-empty initializations of zero-length arrays. */ - if (constructor_max_index == NULL_TREE - && TYPE_SIZE (constructor_type)) - constructor_max_index = build_int_cst (NULL_TREE, -1); - - /* constructor_max_index needs to be an INTEGER_CST. Attempts - to initialize VLAs will cause a proper error; avoid tree - checking errors as well by setting a safe value. */ - if (constructor_max_index - && TREE_CODE (constructor_max_index) != INTEGER_CST) - constructor_max_index = build_int_cst (NULL_TREE, -1); - - constructor_index - = convert (bitsizetype, - TYPE_MIN_VALUE (TYPE_DOMAIN (constructor_type))); - } + { + constructor_max_index + = TYPE_MAX_VALUE (TYPE_DOMAIN (constructor_type)); + + /* Detect non-empty initializations of zero-length arrays. */ + if (constructor_max_index == NULL_TREE + && TYPE_SIZE (constructor_type)) + constructor_max_index = integer_minus_one_node; + + /* constructor_max_index needs to be an INTEGER_CST. Attempts + to initialize VLAs will cause a proper error; avoid tree + checking errors as well by setting a safe value. */ + if (constructor_max_index + && TREE_CODE (constructor_max_index) != INTEGER_CST) + constructor_max_index = integer_minus_one_node; + + constructor_index + = convert (bitsizetype, + TYPE_MIN_VALUE (TYPE_DOMAIN (constructor_type))); + } else constructor_index = bitsize_zero_node; constructor_unfilled_index = constructor_index; if (value && TREE_CODE (value) == STRING_CST) - { - /* We need to split the char/wchar array into individual - characters, so that we don't have to special case it - everywhere. */ - set_nonincremental_init_from_string (value); - } + { + /* We need to split the char/wchar array into individual + characters, so that we don't have to special case it + everywhere. */ + set_nonincremental_init_from_string (value, braced_init_obstack); + } } else { @@ -6597,7 +6898,7 @@ Otherwise, return a CONSTRUCTOR expression as the value. */ struct c_expr -pop_init_level (int implicit) +pop_init_level (int implicit, struct obstack * braced_init_obstack) { struct constructor_stack *p; struct c_expr ret; @@ -6610,14 +6911,16 @@ /* 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), true); - + { + process_init_element (pop_init_level (1, braced_init_obstack), + true, braced_init_obstack); + } gcc_assert (!constructor_range_stack); } /* Now output all pending elements. */ constructor_incremental = 1; - output_pending_init_elements (1); + output_pending_init_elements (1, braced_init_obstack); p = constructor_stack; @@ -6633,21 +6936,22 @@ if (integer_zerop (constructor_unfilled_index)) constructor_type = NULL_TREE; else - { - gcc_assert (!TYPE_SIZE (constructor_type)); - - if (constructor_depth > 2) - error_init ("initialization of flexible array member in a nested context"); - 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. - Discard the initializer so that we do not die later. */ - if (TREE_CHAIN (constructor_fields) != NULL_TREE) - constructor_type = NULL_TREE; - } + { + gcc_assert (!TYPE_SIZE (constructor_type)); + + if (constructor_depth > 2) + error_init ("initialization of flexible array member in a nested context"); + 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. + Discard the initializer so that we do not die later. */ + if (DECL_CHAIN (constructor_fields) != NULL_TREE) + constructor_type = NULL_TREE; + } } /* Warn when some struct elements are implicitly initialized to zero. */ @@ -6656,18 +6960,18 @@ && TREE_CODE (constructor_type) == RECORD_TYPE && constructor_unfilled_fields) { - /* Do not warn for flexible array members or zero-length arrays. */ - while (constructor_unfilled_fields - && (!DECL_SIZE (constructor_unfilled_fields) - || integer_zerop (DECL_SIZE (constructor_unfilled_fields)))) - constructor_unfilled_fields = TREE_CHAIN (constructor_unfilled_fields); - - /* Do not warn if this level of the initializer uses member - designators; it is likely to be deliberate. */ - if (constructor_unfilled_fields && !constructor_designated) - { - push_member_name (constructor_unfilled_fields); - warning_init (OPT_Wmissing_field_initializers, + /* Do not warn for flexible array members or zero-length arrays. */ + while (constructor_unfilled_fields + && (!DECL_SIZE (constructor_unfilled_fields) + || integer_zerop (DECL_SIZE (constructor_unfilled_fields)))) + constructor_unfilled_fields = DECL_CHAIN (constructor_unfilled_fields); + + /* Do not warn if this level of the initializer uses member + designators; it is likely to be deliberate. */ + if (constructor_unfilled_fields && !constructor_designated) + { + push_member_name (constructor_unfilled_fields); + warning_init (OPT_Wmissing_field_initializers, "missing initializer"); RESTORE_SPELLING_DEPTH (constructor_depth); } @@ -6758,7 +7062,7 @@ ARRAY argument is nonzero for array ranges. Returns zero for success. */ static int -set_designator (int array) +set_designator (int array, struct obstack * braced_init_obstack) { tree subtype; enum tree_code subcode; @@ -6780,7 +7084,10 @@ /* Designator list starts at the level of closest explicit braces. */ while (constructor_stack->implicit) - process_init_element (pop_init_level (1), true); + { + process_init_element (pop_init_level (1, braced_init_obstack), + true, braced_init_obstack); + } constructor_designated = 1; return 0; } @@ -6813,7 +7120,7 @@ } constructor_designated = 1; - push_init_level (2); + push_init_level (2, braced_init_obstack); return 0; } @@ -6822,11 +7129,13 @@ NULL_TREE if there is no range designator at this level. */ static void -push_range_stack (tree range_end) +push_range_stack (tree range_end, struct obstack * braced_init_obstack) { struct constructor_range_stack *p; - p = GGC_NEW (struct constructor_range_stack); + p = (struct constructor_range_stack *) + obstack_alloc (braced_init_obstack, + sizeof (struct constructor_range_stack)); p->prev = constructor_range_stack; p->next = 0; p->fields = constructor_fields; @@ -6844,9 +7153,10 @@ of indices, running from FIRST through LAST. */ void -set_init_index (tree first, tree last) -{ - if (set_designator (1)) +set_init_index (tree first, tree last, + struct obstack * braced_init_obstack) +{ + if (set_designator (1, braced_init_obstack)) return; designator_erroneous = 1; @@ -6918,18 +7228,18 @@ designator_depth++; designator_erroneous = 0; if (constructor_range_stack || last) - push_range_stack (last); + push_range_stack (last, braced_init_obstack); } } /* Within a struct initializer, specify the next field to be initialized. */ void -set_init_label (tree fieldname) -{ - tree tail; - - if (set_designator (0)) +set_init_label (tree fieldname, struct obstack * braced_init_obstack) +{ + tree field; + + if (set_designator (0, braced_init_obstack)) return; designator_erroneous = 1; @@ -6941,25 +7251,29 @@ return; } - for (tail = TYPE_FIELDS (constructor_type); tail; - tail = TREE_CHAIN (tail)) - { - if (DECL_NAME (tail) == fieldname) - break; - } - - if (tail == 0) + field = lookup_field (constructor_type, fieldname); + + if (field == 0) error ("unknown field %qE specified in initializer", fieldname); - else - { - constructor_fields = tail; - designator_depth++; - designator_erroneous = 0; - if (constructor_range_stack) - push_range_stack (NULL_TREE); - } -} - + else + do + { + constructor_fields = TREE_VALUE (field); + designator_depth++; + designator_erroneous = 0; + if (constructor_range_stack) + push_range_stack (NULL_TREE, braced_init_obstack); + field = TREE_CHAIN (field); + if (field) + { + if (set_designator (0, braced_init_obstack)) + return; + } + } + while (field != NULL_TREE); + +} + /* 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. If ORIGTYPE is not @@ -6971,7 +7285,8 @@ existing initializer. */ static void -add_pending_init (tree purpose, tree value, tree origtype, bool implicit) +add_pending_init (tree purpose, tree value, tree origtype, bool implicit, + struct obstack * braced_init_obstack) { struct init_node *p, **q, *r; @@ -7030,7 +7345,8 @@ } } - r = GGC_NEW (struct init_node); + r = (struct init_node *) obstack_alloc (braced_init_obstack, + sizeof (struct init_node)); r->purpose = purpose; r->value = value; r->origtype = origtype; @@ -7199,7 +7515,7 @@ /* Build AVL tree from a sorted chain. */ static void -set_nonincremental_init (void) +set_nonincremental_init (struct obstack * braced_init_obstack) { unsigned HOST_WIDE_INT ix; tree index, value; @@ -7209,7 +7525,10 @@ return; FOR_EACH_CONSTRUCTOR_ELT (constructor_elements, ix, index, value) - add_pending_init (index, value, NULL_TREE, false); + { + add_pending_init (index, value, NULL_TREE, false, + braced_init_obstack); + } constructor_elements = 0; if (TREE_CODE (constructor_type) == RECORD_TYPE) { @@ -7236,7 +7555,8 @@ /* Build AVL tree from a string constant. */ static void -set_nonincremental_init_from_string (tree str) +set_nonincremental_init_from_string (tree str, + struct obstack * braced_init_obstack) { tree value, purpose, type; HOST_WIDE_INT val[2]; @@ -7299,7 +7619,8 @@ } value = build_int_cst_wide (type, val[1], val[0]); - add_pending_init (purpose, value, NULL_TREE, false); + add_pending_init (purpose, value, NULL_TREE, false, + braced_init_obstack); } constructor_incremental = 0; @@ -7309,15 +7630,15 @@ not initialized yet. */ static tree -find_init_member (tree field) +find_init_member (tree field, struct obstack * braced_init_obstack) { struct init_node *p; if (TREE_CODE (constructor_type) == ARRAY_TYPE) { if (constructor_incremental - && tree_int_cst_lt (field, constructor_unfilled_index)) - set_nonincremental_init (); + && tree_int_cst_lt (field, constructor_unfilled_index)) + set_nonincremental_init (braced_init_obstack); p = constructor_pending_elts; while (p) @@ -7335,10 +7656,10 @@ tree bitpos = bit_position (field); if (constructor_incremental - && (!constructor_unfilled_fields - || tree_int_cst_lt (bitpos, - bit_position (constructor_unfilled_fields)))) - set_nonincremental_init (); + && (!constructor_unfilled_fields + || tree_int_cst_lt (bitpos, + bit_position (constructor_unfilled_fields)))) + set_nonincremental_init (braced_init_obstack); p = constructor_pending_elts; while (p) @@ -7382,7 +7703,8 @@ static void output_init_element (tree value, tree origtype, bool strict_string, tree type, - tree field, int pending, bool implicit) + tree field, int pending, bool implicit, + struct obstack * braced_init_obstack) { tree semantic_type = NULL_TREE; constructor_elt *celt; @@ -7473,10 +7795,10 @@ don't do anything other than checking the initializer. */ if (field && (TREE_TYPE (field) == error_mark_node - || (COMPLETE_TYPE_P (TREE_TYPE (field)) - && integer_zerop (TYPE_SIZE (TREE_TYPE (field))) - && (TREE_CODE (constructor_type) == ARRAY_TYPE - || TREE_CHAIN (field))))) + || (COMPLETE_TYPE_P (TREE_TYPE (field)) + && integer_zerop (TYPE_SIZE (TREE_TYPE (field))) + && (TREE_CODE (constructor_type) == ARRAY_TYPE + || DECL_CHAIN (field))))) return; if (semantic_type) @@ -7498,10 +7820,11 @@ || !tree_int_cst_equal (field, constructor_unfilled_index))) { if (constructor_incremental - && tree_int_cst_lt (field, constructor_unfilled_index)) - set_nonincremental_init (); - - add_pending_init (field, value, origtype, implicit); + && tree_int_cst_lt (field, constructor_unfilled_index)) + set_nonincremental_init (braced_init_obstack); + + add_pending_init (field, value, origtype, implicit, + braced_init_obstack); return; } else if (TREE_CODE (constructor_type) == RECORD_TYPE @@ -7512,22 +7835,23 @@ no matter which field is specified, it can be initialized right away since it starts at the beginning of the union. */ if (constructor_incremental) - { - if (!constructor_unfilled_fields) - set_nonincremental_init (); - else - { - tree bitpos, unfillpos; - - bitpos = bit_position (field); - unfillpos = bit_position (constructor_unfilled_fields); - - if (tree_int_cst_lt (bitpos, unfillpos)) - set_nonincremental_init (); - } - } - - add_pending_init (field, value, origtype, implicit); + { + if (!constructor_unfilled_fields) + set_nonincremental_init (braced_init_obstack); + else + { + tree bitpos, unfillpos; + + bitpos = bit_position (field); + unfillpos = bit_position (constructor_unfilled_fields); + + if (tree_int_cst_lt (bitpos, unfillpos)) + set_nonincremental_init (braced_init_obstack); + } + } + + add_pending_init (field, value, origtype, implicit, + braced_init_obstack); return; } else if (TREE_CODE (constructor_type) == UNION_TYPE @@ -7562,21 +7886,21 @@ else if (TREE_CODE (constructor_type) == RECORD_TYPE) { constructor_unfilled_fields - = TREE_CHAIN (constructor_unfilled_fields); + = DECL_CHAIN (constructor_unfilled_fields); /* Skip any nameless bit fields. */ while (constructor_unfilled_fields != 0 - && DECL_C_BIT_FIELD (constructor_unfilled_fields) - && DECL_NAME (constructor_unfilled_fields) == 0) - constructor_unfilled_fields = - TREE_CHAIN (constructor_unfilled_fields); + && DECL_C_BIT_FIELD (constructor_unfilled_fields) + && DECL_NAME (constructor_unfilled_fields) == 0) + constructor_unfilled_fields = + DECL_CHAIN (constructor_unfilled_fields); } else if (TREE_CODE (constructor_type) == UNION_TYPE) constructor_unfilled_fields = 0; /* Now output any pending elements which have become next. */ if (pending) - output_pending_init_elements (0); + output_pending_init_elements (0, braced_init_obstack); } /* Output any pending elements which have become next. @@ -7589,9 +7913,8 @@ If ALL is 1, we output space as necessary so that we can output all the pending elements. */ - static void -output_pending_init_elements (int all) +output_pending_init_elements (int all, struct obstack * braced_init_obstack) { struct init_node *elt = constructor_pending_elts; tree next; @@ -7607,102 +7930,104 @@ while (elt) { if (TREE_CODE (constructor_type) == ARRAY_TYPE) - { - if (tree_int_cst_equal (elt->purpose, - constructor_unfilled_index)) - output_init_element (elt->value, elt->origtype, true, - TREE_TYPE (constructor_type), - constructor_unfilled_index, 0, false); - else if (tree_int_cst_lt (constructor_unfilled_index, - elt->purpose)) - { - /* Advance to the next smaller node. */ - if (elt->left) - elt = elt->left; - else - { - /* We have reached the smallest node bigger than the - current unfilled index. Fill the space first. */ - next = elt->purpose; - break; - } - } - else - { - /* Advance to the next bigger node. */ - if (elt->right) - elt = elt->right; - else - { - /* We have reached the biggest node in a subtree. Find - the parent of it, which is the next bigger node. */ - while (elt->parent && elt->parent->right == elt) - elt = elt->parent; - elt = elt->parent; - if (elt && tree_int_cst_lt (constructor_unfilled_index, - elt->purpose)) - { - next = elt->purpose; - break; - } - } - } - } + { + if (tree_int_cst_equal (elt->purpose, + constructor_unfilled_index)) + output_init_element (elt->value, elt->origtype, true, + TREE_TYPE (constructor_type), + constructor_unfilled_index, 0, false, + braced_init_obstack); + else if (tree_int_cst_lt (constructor_unfilled_index, + elt->purpose)) + { + /* Advance to the next smaller node. */ + if (elt->left) + elt = elt->left; + else + { + /* We have reached the smallest node bigger than the + current unfilled index. Fill the space first. */ + next = elt->purpose; + break; + } + } + else + { + /* Advance to the next bigger node. */ + if (elt->right) + elt = elt->right; + else + { + /* We have reached the biggest node in a subtree. Find + the parent of it, which is the next bigger node. */ + while (elt->parent && elt->parent->right == elt) + elt = elt->parent; + elt = elt->parent; + if (elt && tree_int_cst_lt (constructor_unfilled_index, + elt->purpose)) + { + next = elt->purpose; + break; + } + } + } + } else if (TREE_CODE (constructor_type) == RECORD_TYPE - || TREE_CODE (constructor_type) == UNION_TYPE) - { - tree ctor_unfilled_bitpos, elt_bitpos; - - /* If the current record is complete we are done. */ - if (constructor_unfilled_fields == 0) - break; - - ctor_unfilled_bitpos = bit_position (constructor_unfilled_fields); - elt_bitpos = bit_position (elt->purpose); - /* We can't compare fields here because there might be empty - fields in between. */ - if (tree_int_cst_equal (elt_bitpos, ctor_unfilled_bitpos)) - { - constructor_unfilled_fields = elt->purpose; - output_init_element (elt->value, elt->origtype, true, - TREE_TYPE (elt->purpose), - elt->purpose, 0, false); - } - else if (tree_int_cst_lt (ctor_unfilled_bitpos, elt_bitpos)) - { - /* Advance to the next smaller node. */ - if (elt->left) - elt = elt->left; - else - { - /* We have reached the smallest node bigger than the - current unfilled field. Fill the space first. */ - next = elt->purpose; - break; - } - } - else - { - /* Advance to the next bigger node. */ - if (elt->right) - elt = elt->right; - else - { - /* We have reached the biggest node in a subtree. Find - the parent of it, which is the next bigger node. */ - while (elt->parent && elt->parent->right == elt) - elt = elt->parent; - elt = elt->parent; - if (elt - && (tree_int_cst_lt (ctor_unfilled_bitpos, - bit_position (elt->purpose)))) - { - next = elt->purpose; - break; - } - } - } - } + || TREE_CODE (constructor_type) == UNION_TYPE) + { + tree ctor_unfilled_bitpos, elt_bitpos; + + /* If the current record is complete we are done. */ + if (constructor_unfilled_fields == 0) + break; + + ctor_unfilled_bitpos = bit_position (constructor_unfilled_fields); + elt_bitpos = bit_position (elt->purpose); + /* We can't compare fields here because there might be empty + fields in between. */ + if (tree_int_cst_equal (elt_bitpos, ctor_unfilled_bitpos)) + { + constructor_unfilled_fields = elt->purpose; + output_init_element (elt->value, elt->origtype, true, + TREE_TYPE (elt->purpose), + elt->purpose, 0, false, + braced_init_obstack); + } + else if (tree_int_cst_lt (ctor_unfilled_bitpos, elt_bitpos)) + { + /* Advance to the next smaller node. */ + if (elt->left) + elt = elt->left; + else + { + /* We have reached the smallest node bigger than the + current unfilled field. Fill the space first. */ + next = elt->purpose; + break; + } + } + else + { + /* Advance to the next bigger node. */ + if (elt->right) + elt = elt->right; + else + { + /* We have reached the biggest node in a subtree. Find + the parent of it, which is the next bigger node. */ + while (elt->parent && elt->parent->right == elt) + elt = elt->parent; + elt = elt->parent; + if (elt + && (tree_int_cst_lt (ctor_unfilled_bitpos, + bit_position (elt->purpose)))) + { + next = elt->purpose; + break; + } + } + } + } } /* Ordinarily return, but not if we want to output all @@ -7737,7 +8062,8 @@ existing initializer. */ void -process_init_element (struct c_expr value, bool implicit) +process_init_element (struct c_expr value, bool implicit, + struct obstack * braced_init_obstack) { tree orig_value = value.value; int string_flag = orig_value != 0 && TREE_CODE (orig_value) == STRING_CST; @@ -7776,15 +8102,17 @@ while (constructor_stack->implicit) { if ((TREE_CODE (constructor_type) == RECORD_TYPE - || TREE_CODE (constructor_type) == UNION_TYPE) - && constructor_fields == 0) - process_init_element (pop_init_level (1), true); + || TREE_CODE (constructor_type) == UNION_TYPE) + && constructor_fields == 0) + process_init_element (pop_init_level (1, braced_init_obstack), + true, braced_init_obstack); else if ((TREE_CODE (constructor_type) == ARRAY_TYPE - || TREE_CODE (constructor_type) == VECTOR_TYPE) - && (constructor_max_index == 0 - || tree_int_cst_lt (constructor_max_index, - constructor_index))) - process_init_element (pop_init_level (1), true); + || TREE_CODE (constructor_type) == VECTOR_TYPE) + && (constructor_max_index == 0 + || tree_int_cst_lt (constructor_max_index, + constructor_index))) + process_init_element (pop_init_level (1, braced_init_obstack), + true, braced_init_obstack); else break; } @@ -7814,244 +8142,248 @@ while (1) { if (TREE_CODE (constructor_type) == RECORD_TYPE) - { - tree fieldtype; - enum tree_code fieldcode; - - if (constructor_fields == 0) - { - pedwarn_init (input_location, 0, - "excess elements in struct initializer"); - break; - } - - fieldtype = TREE_TYPE (constructor_fields); - if (fieldtype != error_mark_node) - fieldtype = TYPE_MAIN_VARIANT (fieldtype); - fieldcode = TREE_CODE (fieldtype); - - /* Error for non-static initialization of a flexible array member. */ - if (fieldcode == ARRAY_TYPE - && !require_constant_value - && TYPE_SIZE (fieldtype) == NULL_TREE - && TREE_CHAIN (constructor_fields) == NULL_TREE) - { - error_init ("non-static initialization of a flexible array member"); - break; - } - - /* Accept a string constant to initialize a subarray. */ - if (value.value != 0 - && fieldcode == ARRAY_TYPE - && INTEGRAL_TYPE_P (TREE_TYPE (fieldtype)) - && string_flag) - value.value = orig_value; - /* Otherwise, if we have come to a subaggregate, - and we don't have an element of its type, push into it. */ - else if (value.value != 0 - && value.value != error_mark_node - && TYPE_MAIN_VARIANT (TREE_TYPE (value.value)) != fieldtype - && (fieldcode == RECORD_TYPE || fieldcode == ARRAY_TYPE - || fieldcode == UNION_TYPE || fieldcode == VECTOR_TYPE)) - { - push_init_level (1); - continue; - } - - if (value.value) - { - push_member_name (constructor_fields); - output_init_element (value.value, value.original_type, - strict_string, fieldtype, - constructor_fields, 1, implicit); - RESTORE_SPELLING_DEPTH (constructor_depth); - } - else - /* Do the bookkeeping for an element that was - directly output as a constructor. */ - { - /* For a record, keep track of end position of last field. */ - if (DECL_SIZE (constructor_fields)) - constructor_bit_index - = size_binop_loc (input_location, PLUS_EXPR, - bit_position (constructor_fields), - DECL_SIZE (constructor_fields)); - - /* If the current field was the first one not yet written out, - it isn't now, so update. */ - if (constructor_unfilled_fields == constructor_fields) - { - constructor_unfilled_fields = TREE_CHAIN (constructor_fields); - /* Skip any nameless bit fields. */ - while (constructor_unfilled_fields != 0 - && DECL_C_BIT_FIELD (constructor_unfilled_fields) - && DECL_NAME (constructor_unfilled_fields) == 0) - constructor_unfilled_fields = - TREE_CHAIN (constructor_unfilled_fields); - } - } - - constructor_fields = TREE_CHAIN (constructor_fields); - /* Skip any nameless bit fields at the beginning. */ - while (constructor_fields != 0 - && DECL_C_BIT_FIELD (constructor_fields) - && DECL_NAME (constructor_fields) == 0) - constructor_fields = TREE_CHAIN (constructor_fields); - } + { + tree fieldtype; + enum tree_code fieldcode; + + if (constructor_fields == 0) + { + pedwarn_init (input_location, 0, + "excess elements in struct initializer"); + break; + } + + fieldtype = TREE_TYPE (constructor_fields); + if (fieldtype != error_mark_node) + fieldtype = TYPE_MAIN_VARIANT (fieldtype); + fieldcode = TREE_CODE (fieldtype); + + /* Error for non-static initialization of a flexible array member. */ + if (fieldcode == ARRAY_TYPE + && !require_constant_value + && TYPE_SIZE (fieldtype) == NULL_TREE + && DECL_CHAIN (constructor_fields) == NULL_TREE) + { + error_init ("non-static initialization of a flexible array member"); + break; + } + + /* Accept a string constant to initialize a subarray. */ + if (value.value != 0 + && fieldcode == ARRAY_TYPE + && INTEGRAL_TYPE_P (TREE_TYPE (fieldtype)) + && string_flag) + value.value = orig_value; + /* Otherwise, if we have come to a subaggregate, + and we don't have an element of its type, push into it. */ + else if (value.value != 0 + && value.value != error_mark_node + && TYPE_MAIN_VARIANT (TREE_TYPE (value.value)) != fieldtype + && (fieldcode == RECORD_TYPE || fieldcode == ARRAY_TYPE + || fieldcode == UNION_TYPE || fieldcode == VECTOR_TYPE)) + { + push_init_level (1, braced_init_obstack); + continue; + } + + if (value.value) + { + push_member_name (constructor_fields); + output_init_element (value.value, value.original_type, + strict_string, fieldtype, + constructor_fields, 1, implicit, + braced_init_obstack); + RESTORE_SPELLING_DEPTH (constructor_depth); + } + else + /* Do the bookkeeping for an element that was + directly output as a constructor. */ + { + /* For a record, keep track of end position of last field. */ + if (DECL_SIZE (constructor_fields)) + constructor_bit_index + = size_binop_loc (input_location, PLUS_EXPR, + bit_position (constructor_fields), + DECL_SIZE (constructor_fields)); + + /* If the current field was the first one not yet written out, + it isn't now, so update. */ + if (constructor_unfilled_fields == constructor_fields) + { + constructor_unfilled_fields = DECL_CHAIN (constructor_fields); + /* Skip any nameless bit fields. */ + while (constructor_unfilled_fields != 0 + && DECL_C_BIT_FIELD (constructor_unfilled_fields) + && DECL_NAME (constructor_unfilled_fields) == 0) + constructor_unfilled_fields = + DECL_CHAIN (constructor_unfilled_fields); + } + } + + constructor_fields = DECL_CHAIN (constructor_fields); + /* Skip any nameless bit fields at the beginning. */ + while (constructor_fields != 0 + && DECL_C_BIT_FIELD (constructor_fields) + && DECL_NAME (constructor_fields) == 0) + constructor_fields = DECL_CHAIN (constructor_fields); + } else if (TREE_CODE (constructor_type) == UNION_TYPE) - { - tree fieldtype; - enum tree_code fieldcode; - - if (constructor_fields == 0) - { - pedwarn_init (input_location, 0, - "excess elements in union initializer"); - break; - } - - fieldtype = TREE_TYPE (constructor_fields); - if (fieldtype != error_mark_node) - fieldtype = TYPE_MAIN_VARIANT (fieldtype); - fieldcode = TREE_CODE (fieldtype); - - /* Warn that traditional C rejects initialization of unions. - We skip the warning if the value is zero. This is done - under the assumption that the zero initializer in user - code appears conditioned on e.g. __STDC__ to avoid - "missing initializer" warnings and relies on default - initialization to zero in the traditional C case. - We also skip the warning if the initializer is designated, - again on the assumption that this must be conditional on - __STDC__ anyway (and we've already complained about the - member-designator already). */ - if (!in_system_header && !constructor_designated - && !(value.value && (integer_zerop (value.value) - || real_zerop (value.value)))) - warning (OPT_Wtraditional, "traditional C rejects initialization " - "of unions"); - - /* Accept a string constant to initialize a subarray. */ - if (value.value != 0 - && fieldcode == ARRAY_TYPE - && INTEGRAL_TYPE_P (TREE_TYPE (fieldtype)) - && string_flag) - value.value = orig_value; - /* Otherwise, if we have come to a subaggregate, - and we don't have an element of its type, push into it. */ - else if (value.value != 0 - && value.value != error_mark_node - && TYPE_MAIN_VARIANT (TREE_TYPE (value.value)) != fieldtype - && (fieldcode == RECORD_TYPE || fieldcode == ARRAY_TYPE - || fieldcode == UNION_TYPE || fieldcode == VECTOR_TYPE)) - { - push_init_level (1); - continue; - } - - if (value.value) - { - push_member_name (constructor_fields); - output_init_element (value.value, value.original_type, - strict_string, fieldtype, - constructor_fields, 1, implicit); - RESTORE_SPELLING_DEPTH (constructor_depth); - } - else - /* Do the bookkeeping for an element that was - directly output as a constructor. */ - { - constructor_bit_index = DECL_SIZE (constructor_fields); - constructor_unfilled_fields = TREE_CHAIN (constructor_fields); - } - - constructor_fields = 0; - } + { + tree fieldtype; + enum tree_code fieldcode; + + if (constructor_fields == 0) + { + pedwarn_init (input_location, 0, + "excess elements in union initializer"); + break; + } + + fieldtype = TREE_TYPE (constructor_fields); + if (fieldtype != error_mark_node) + fieldtype = TYPE_MAIN_VARIANT (fieldtype); + fieldcode = TREE_CODE (fieldtype); + + /* Warn that traditional C rejects initialization of unions. + We skip the warning if the value is zero. This is done + under the assumption that the zero initializer in user + code appears conditioned on e.g. __STDC__ to avoid + "missing initializer" warnings and relies on default + initialization to zero in the traditional C case. + We also skip the warning if the initializer is designated, + again on the assumption that this must be conditional on + __STDC__ anyway (and we've already complained about the + member-designator already). */ + if (!in_system_header && !constructor_designated + && !(value.value && (integer_zerop (value.value) + || real_zerop (value.value)))) + warning (OPT_Wtraditional, "traditional C rejects initialization " + "of unions"); + + /* Accept a string constant to initialize a subarray. */ + if (value.value != 0 + && fieldcode == ARRAY_TYPE + && INTEGRAL_TYPE_P (TREE_TYPE (fieldtype)) + && string_flag) + value.value = orig_value; + /* Otherwise, if we have come to a subaggregate, + and we don't have an element of its type, push into it. */ + else if (value.value != 0 + && value.value != error_mark_node + && TYPE_MAIN_VARIANT (TREE_TYPE (value.value)) != fieldtype + && (fieldcode == RECORD_TYPE || fieldcode == ARRAY_TYPE + || fieldcode == UNION_TYPE || fieldcode == VECTOR_TYPE)) + { + push_init_level (1, braced_init_obstack); + continue; + } + + if (value.value) + { + push_member_name (constructor_fields); + output_init_element (value.value, value.original_type, + strict_string, fieldtype, + constructor_fields, 1, implicit, + braced_init_obstack); + RESTORE_SPELLING_DEPTH (constructor_depth); + } + else + /* Do the bookkeeping for an element that was + directly output as a constructor. */ + { + constructor_bit_index = DECL_SIZE (constructor_fields); + constructor_unfilled_fields = DECL_CHAIN (constructor_fields); + } + + constructor_fields = 0; + } else if (TREE_CODE (constructor_type) == ARRAY_TYPE) - { - tree elttype = TYPE_MAIN_VARIANT (TREE_TYPE (constructor_type)); - enum tree_code eltcode = TREE_CODE (elttype); - - /* Accept a string constant to initialize a subarray. */ - if (value.value != 0 - && eltcode == ARRAY_TYPE - && INTEGRAL_TYPE_P (TREE_TYPE (elttype)) - && string_flag) - value.value = orig_value; - /* Otherwise, if we have come to a subaggregate, - and we don't have an element of its type, push into it. */ - else if (value.value != 0 - && value.value != error_mark_node - && TYPE_MAIN_VARIANT (TREE_TYPE (value.value)) != elttype - && (eltcode == RECORD_TYPE || eltcode == ARRAY_TYPE - || eltcode == UNION_TYPE || eltcode == VECTOR_TYPE)) - { - push_init_level (1); - continue; - } - - if (constructor_max_index != 0 - && (tree_int_cst_lt (constructor_max_index, constructor_index) - || integer_all_onesp (constructor_max_index))) - { - pedwarn_init (input_location, 0, - "excess elements in array initializer"); - break; - } - - /* Now output the actual element. */ - if (value.value) - { - push_array_bounds (tree_low_cst (constructor_index, 1)); - output_init_element (value.value, value.original_type, - strict_string, elttype, - constructor_index, 1, implicit); - RESTORE_SPELLING_DEPTH (constructor_depth); - } - - constructor_index - = size_binop_loc (input_location, PLUS_EXPR, - constructor_index, bitsize_one_node); - - if (!value.value) - /* If we are doing the bookkeeping for an element that was - directly output as a constructor, we must update - constructor_unfilled_index. */ - constructor_unfilled_index = constructor_index; - } + { + tree elttype = TYPE_MAIN_VARIANT (TREE_TYPE (constructor_type)); + enum tree_code eltcode = TREE_CODE (elttype); + + /* Accept a string constant to initialize a subarray. */ + if (value.value != 0 + && eltcode == ARRAY_TYPE + && INTEGRAL_TYPE_P (TREE_TYPE (elttype)) + && string_flag) + value.value = orig_value; + /* Otherwise, if we have come to a subaggregate, + and we don't have an element of its type, push into it. */ + else if (value.value != 0 + && value.value != error_mark_node + && TYPE_MAIN_VARIANT (TREE_TYPE (value.value)) != elttype + && (eltcode == RECORD_TYPE || eltcode == ARRAY_TYPE + || eltcode == UNION_TYPE || eltcode == VECTOR_TYPE)) + { + push_init_level (1, braced_init_obstack); + continue; + } + + if (constructor_max_index != 0 + && (tree_int_cst_lt (constructor_max_index, constructor_index) + || integer_all_onesp (constructor_max_index))) + { + pedwarn_init (input_location, 0, + "excess elements in array initializer"); + break; + } + + /* Now output the actual element. */ + if (value.value) + { + push_array_bounds (tree_low_cst (constructor_index, 1)); + output_init_element (value.value, value.original_type, + strict_string, elttype, + constructor_index, 1, implicit, + braced_init_obstack); + RESTORE_SPELLING_DEPTH (constructor_depth); + } + + constructor_index + = size_binop_loc (input_location, PLUS_EXPR, + constructor_index, bitsize_one_node); + + if (!value.value) + /* If we are doing the bookkeeping for an element that was + directly output as a constructor, we must update + constructor_unfilled_index. */ + constructor_unfilled_index = constructor_index; + } else if (TREE_CODE (constructor_type) == VECTOR_TYPE) - { - tree elttype = TYPE_MAIN_VARIANT (TREE_TYPE (constructor_type)); - - /* Do a basic check of initializer size. Note that vectors - always have a fixed size derived from their type. */ - if (tree_int_cst_lt (constructor_max_index, constructor_index)) - { - pedwarn_init (input_location, 0, - "excess elements in vector initializer"); - break; - } - - /* Now output the actual element. */ - if (value.value) - { - if (TREE_CODE (value.value) == VECTOR_CST) - elttype = TYPE_MAIN_VARIANT (constructor_type); - output_init_element (value.value, value.original_type, - strict_string, elttype, - constructor_index, 1, implicit); - } - - constructor_index - = size_binop_loc (input_location, - PLUS_EXPR, constructor_index, bitsize_one_node); - - if (!value.value) - /* If we are doing the bookkeeping for an element that was - directly output as a constructor, we must update - constructor_unfilled_index. */ - constructor_unfilled_index = constructor_index; - } + { + tree elttype = TYPE_MAIN_VARIANT (TREE_TYPE (constructor_type)); + + /* Do a basic check of initializer size. Note that vectors + always have a fixed size derived from their type. */ + if (tree_int_cst_lt (constructor_max_index, constructor_index)) + { + pedwarn_init (input_location, 0, + "excess elements in vector initializer"); + break; + } + + /* Now output the actual element. */ + if (value.value) + { + if (TREE_CODE (value.value) == VECTOR_CST) + elttype = TYPE_MAIN_VARIANT (constructor_type); + output_init_element (value.value, value.original_type, + strict_string, elttype, + constructor_index, 1, implicit, + braced_init_obstack); + } + + constructor_index + = size_binop_loc (input_location, + PLUS_EXPR, constructor_index, bitsize_one_node); + + if (!value.value) + /* If we are doing the bookkeeping for an element that was + directly output as a constructor, we must update + constructor_unfilled_index. */ + constructor_unfilled_index = constructor_index; + } /* Handle the sole element allowed in a braced initializer for a scalar variable. */ @@ -8063,63 +8395,67 @@ break; } else - { - if (value.value) - output_init_element (value.value, value.original_type, - strict_string, constructor_type, - NULL_TREE, 1, implicit); - constructor_fields = 0; - } + { + if (value.value) + output_init_element (value.value, value.original_type, + strict_string, constructor_type, + NULL_TREE, 1, implicit, + braced_init_obstack); + constructor_fields = 0; + } /* Handle range initializers either at this level or anywhere higher in the designator stack. */ if (constructor_range_stack) - { - struct constructor_range_stack *p, *range_stack; - int finish = 0; - - range_stack = constructor_range_stack; - constructor_range_stack = 0; - while (constructor_stack != range_stack->stack) - { - gcc_assert (constructor_stack->implicit); - 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), true); - } - - p->index = size_binop_loc (input_location, - PLUS_EXPR, p->index, bitsize_one_node); - if (tree_int_cst_equal (p->index, p->range_end) && !p->prev) - finish = 1; - - while (1) - { - constructor_index = p->index; - constructor_fields = p->fields; - if (finish && p->range_end && p->index == p->range_start) - { - finish = 0; - p->prev = 0; - } - p = p->next; - if (!p) - break; - push_init_level (2); - p->stack = constructor_stack; - if (p->range_end && tree_int_cst_equal (p->index, p->range_end)) - p->index = p->range_start; - } - - if (!finish) - constructor_range_stack = range_stack; - continue; - } + { + struct constructor_range_stack *p, *range_stack; + int finish = 0; + + range_stack = constructor_range_stack; + constructor_range_stack = 0; + while (constructor_stack != range_stack->stack) + { + gcc_assert (constructor_stack->implicit); + process_init_element (pop_init_level (1, + braced_init_obstack), + true, braced_init_obstack); + } + 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, braced_init_obstack), + true, braced_init_obstack); + } + + p->index = size_binop_loc (input_location, + PLUS_EXPR, p->index, bitsize_one_node); + if (tree_int_cst_equal (p->index, p->range_end) && !p->prev) + finish = 1; + + while (1) + { + constructor_index = p->index; + constructor_fields = p->fields; + if (finish && p->range_end && p->index == p->range_start) + { + finish = 0; + p->prev = 0; + } + p = p->next; + if (!p) + break; + push_init_level (2, braced_init_obstack); + p->stack = constructor_stack; + if (p->range_end && tree_int_cst_equal (p->index, p->range_end)) + p->index = p->range_start; + } + + if (!finish) + constructor_range_stack = range_stack; + continue; + } break; } @@ -8174,8 +8510,8 @@ get an error. Gross, but ... */ STRIP_NOPS (output); - if (!lvalue_or_else (output, lv_asm)) - output = error_mark_node; + if (!lvalue_or_else (loc, output, lv_asm)) + output = error_mark_node; if (output != error_mark_node && (TREE_READONLY (output) @@ -8761,6 +9097,8 @@ tree c_process_expr_stmt (location_t loc, tree expr) { + tree exprv; + if (!expr) return NULL_TREE; @@ -8781,6 +9119,12 @@ && warn_unused_value) emit_side_effect_warnings (loc, expr); + exprv = expr; + while (TREE_CODE (exprv) == COMPOUND_EXPR) + exprv = TREE_OPERAND (exprv, 1); + if (DECL_P (exprv) || handled_component_p (exprv)) + mark_exp_read (exprv); + /* If the expression is not of a type to which we cannot assign a line number, wrap the thing in a no-op NOP_EXPR. */ if (DECL_P (expr) || CONSTANT_CLASS_P (expr)) @@ -9041,7 +9385,7 @@ /* When the computation is in excess precision, the type of the final EXCESS_PRECISION_EXPR. */ - tree real_result_type = NULL; + tree semantic_result_type = NULL; /* Nonzero means operands have already been type-converted in whatever way is necessary. @@ -9083,6 +9427,10 @@ precision. */ bool may_need_excess_precision; + /* True means this is a boolean operation that converts both its + operands to truth-values. */ + bool boolean_op = false; + if (location == UNKNOWN_LOCATION) location = input_location; @@ -9297,20 +9645,21 @@ case TRUTH_OR_EXPR: case TRUTH_XOR_EXPR: if ((code0 == INTEGER_TYPE || code0 == POINTER_TYPE - || code0 == REAL_TYPE || code0 == COMPLEX_TYPE - || code0 == FIXED_POINT_TYPE) - && (code1 == INTEGER_TYPE || code1 == POINTER_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 (location, op0); - op1 = c_common_truthvalue_conversion (location, op1); - converted = 1; - } + || code0 == REAL_TYPE || code0 == COMPLEX_TYPE + || code0 == FIXED_POINT_TYPE) + && (code1 == INTEGER_TYPE || code1 == POINTER_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 (location, op0); + op1 = c_common_truthvalue_conversion (location, op1); + converted = 1; + boolean_op = true; + } if (code == TRUTH_ANDIF_EXPR) { int_const_or_overflow = (int_operands @@ -9340,72 +9689,102 @@ Also set SHORT_SHIFT if shifting rightward. */ case RSHIFT_EXPR: - if ((code0 == INTEGER_TYPE || code0 == FIXED_POINT_TYPE) - && code1 == INTEGER_TYPE) - { - if (TREE_CODE (op1) == INTEGER_CST) - { - if (tree_int_cst_sgn (op1) < 0) - { - int_const = false; - if (c_inhibit_evaluation_warnings == 0) - warning (0, "right shift count is negative"); - } - else + if (code0 == VECTOR_TYPE && code1 == INTEGER_TYPE + && TREE_CODE (TREE_TYPE (type0)) == INTEGER_TYPE) { - if (!integer_zerop (op1)) - short_shift = 1; - - if (compare_tree_int (op1, TYPE_PRECISION (type0)) >= 0) - { - int_const = false; - if (c_inhibit_evaluation_warnings == 0) - warning (0, "right shift count >= width of type"); - } - } + result_type = type0; + converted = 1; } - - /* Use the type of the value to be shifted. */ - result_type = type0; - /* Convert the shift-count to an integer, regardless of size - of value being shifted. */ - if (TYPE_MAIN_VARIANT (TREE_TYPE (op1)) != integer_type_node) - op1 = convert (integer_type_node, op1); - /* Avoid converting op1 to result_type later. */ - converted = 1; - } + else if (code0 == VECTOR_TYPE && code1 == VECTOR_TYPE + && TREE_CODE (TREE_TYPE (type0)) == INTEGER_TYPE + && TREE_CODE (TREE_TYPE (type1)) == INTEGER_TYPE + && TYPE_VECTOR_SUBPARTS (type0) == TYPE_VECTOR_SUBPARTS (type1)) + { + result_type = type0; + converted = 1; + } + else if ((code0 == INTEGER_TYPE || code0 == FIXED_POINT_TYPE) + && code1 == INTEGER_TYPE) + { + if (TREE_CODE (op1) == INTEGER_CST) + { + if (tree_int_cst_sgn (op1) < 0) + { + int_const = false; + if (c_inhibit_evaluation_warnings == 0) + warning (0, "right shift count is negative"); + } + else + { + if (!integer_zerop (op1)) + short_shift = 1; + + if (compare_tree_int (op1, TYPE_PRECISION (type0)) >= 0) + { + int_const = false; + if (c_inhibit_evaluation_warnings == 0) + warning (0, "right shift count >= width of type"); + } + } + } + + /* Use the type of the value to be shifted. */ + result_type = type0; + /* Convert the non vector shift-count to an integer, regardless + of size of value being shifted. */ + if (TREE_CODE (TREE_TYPE (op1)) != VECTOR_TYPE + && TYPE_MAIN_VARIANT (TREE_TYPE (op1)) != integer_type_node) + op1 = convert (integer_type_node, op1); + /* Avoid converting op1 to result_type later. */ + converted = 1; + } break; case LSHIFT_EXPR: - if ((code0 == INTEGER_TYPE || code0 == FIXED_POINT_TYPE) - && code1 == INTEGER_TYPE) - { - if (TREE_CODE (op1) == INTEGER_CST) - { - if (tree_int_cst_sgn (op1) < 0) - { - int_const = false; - if (c_inhibit_evaluation_warnings == 0) - warning (0, "left shift count is negative"); - } - - else if (compare_tree_int (op1, TYPE_PRECISION (type0)) >= 0) + if (code0 == VECTOR_TYPE && code1 == INTEGER_TYPE + && TREE_CODE (TREE_TYPE (type0)) == INTEGER_TYPE) { - int_const = false; - if (c_inhibit_evaluation_warnings == 0) - warning (0, "left shift count >= width of type"); - } + result_type = type0; + converted = 1; } - - /* Use the type of the value to be shifted. */ - result_type = type0; - /* Convert the shift-count to an integer, regardless of size - of value being shifted. */ - if (TYPE_MAIN_VARIANT (TREE_TYPE (op1)) != integer_type_node) - op1 = convert (integer_type_node, op1); - /* Avoid converting op1 to result_type later. */ - converted = 1; - } + else if (code0 == VECTOR_TYPE && code1 == VECTOR_TYPE + && TREE_CODE (TREE_TYPE (type0)) == INTEGER_TYPE + && TREE_CODE (TREE_TYPE (type1)) == INTEGER_TYPE + && TYPE_VECTOR_SUBPARTS (type0) == TYPE_VECTOR_SUBPARTS (type1)) + { + result_type = type0; + converted = 1; + } + else if ((code0 == INTEGER_TYPE || code0 == FIXED_POINT_TYPE) + && code1 == INTEGER_TYPE) + { + if (TREE_CODE (op1) == INTEGER_CST) + { + if (tree_int_cst_sgn (op1) < 0) + { + int_const = false; + if (c_inhibit_evaluation_warnings == 0) + warning (0, "left shift count is negative"); + } + + else if (compare_tree_int (op1, TYPE_PRECISION (type0)) >= 0) + { + int_const = false; + if (c_inhibit_evaluation_warnings == 0) + warning (0, "left shift count >= width of type"); + } + } + + /* Use the type of the value to be shifted. */ + result_type = type0; + /* Convert the non vector shift-count to an integer, regardless + of size of value being shifted. */ + if (TREE_CODE (TREE_TYPE (op1)) != VECTOR_TYPE + && TYPE_MAIN_VARIANT (TREE_TYPE (op1)) != integer_type_node) + op1 = convert (integer_type_node, op1); + /* Avoid converting op1 to result_type later. */ + converted = 1; + } break; case EQ_EXPR: @@ -9418,76 +9797,94 @@ but don't convert the args to int! */ build_type = integer_type_node; if ((code0 == INTEGER_TYPE || code0 == REAL_TYPE - || code0 == FIXED_POINT_TYPE || code0 == COMPLEX_TYPE) - && (code1 == INTEGER_TYPE || code1 == REAL_TYPE - || code1 == FIXED_POINT_TYPE || code1 == COMPLEX_TYPE)) - short_compare = 1; + || code0 == FIXED_POINT_TYPE || code0 == COMPLEX_TYPE) + && (code1 == INTEGER_TYPE || code1 == REAL_TYPE + || code1 == FIXED_POINT_TYPE || code1 == COMPLEX_TYPE)) + short_compare = 1; + else if (code0 == POINTER_TYPE && null_pointer_constant_p (orig_op1)) + { + if (TREE_CODE (op0) == ADDR_EXPR + && decl_with_nonnull_addr_p (TREE_OPERAND (op0, 0))) + { + if (code == EQ_EXPR) + warning_at (location, + OPT_Waddress, + "the comparison will always evaluate as %<false%> " + "for the address of %qD will never be NULL", + TREE_OPERAND (op0, 0)); + else + warning_at (location, + OPT_Waddress, + "the comparison will always evaluate as %<true%> " + "for 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))) + { + if (code == EQ_EXPR) + warning_at (location, + OPT_Waddress, + "the comparison will always evaluate as %<false%> " + "for the address of %qD will never be NULL", + TREE_OPERAND (op1, 0)); + else + warning_at (location, + OPT_Waddress, + "the comparison will always evaluate as %<true%> " + "for the address of %qD will never be NULL", + TREE_OPERAND (op1, 0)); + } + result_type = type1; + } else if (code0 == POINTER_TYPE && code1 == POINTER_TYPE) - { - tree tt0 = TREE_TYPE (type0); - tree tt1 = TREE_TYPE (type1); - addr_space_t as0 = TYPE_ADDR_SPACE (tt0); - addr_space_t as1 = TYPE_ADDR_SPACE (tt1); - addr_space_t as_common = ADDR_SPACE_GENERIC; - - /* Anything compares with void *. void * compares with anything. - Otherwise, the targets must be compatible - and both must be object or both incomplete. */ - if (comp_target_types (location, type0, type1)) - result_type = common_pointer_type (type0, type1); - else if (null_pointer_constant_p (orig_op0)) - result_type = type1; - else if (null_pointer_constant_p (orig_op1)) - result_type = type0; - else if (!addr_space_superset (as0, as1, &as_common)) - { - error_at (location, "comparison of pointers to " - "disjoint address spaces"); - return error_mark_node; - } - else if (VOID_TYPE_P (tt0)) - { - if (pedantic && TREE_CODE (tt1) == FUNCTION_TYPE) - pedwarn (location, OPT_pedantic, "ISO C forbids " - "comparison of %<void *%> with function pointer"); - } - else if (VOID_TYPE_P (tt1)) - { - if (pedantic && TREE_CODE (tt0) == FUNCTION_TYPE) - pedwarn (location, OPT_pedantic, "ISO C forbids " - "comparison of %<void *%> with function pointer"); - } - else - /* Avoid warning about the volatile ObjC EH puts on decls. */ - if (!objc_ok) - pedwarn (location, 0, - "comparison of distinct pointer types lacks a cast"); - - if (result_type == NULL_TREE) - { - int qual = ENCODE_QUAL_ADDR_SPACE (as_common); - result_type = build_pointer_type - (build_qualified_type (void_type_node, qual)); - } - } - else if (code0 == POINTER_TYPE && null_pointer_constant_p (orig_op1)) - { - if (TREE_CODE (op0) == ADDR_EXPR - && decl_with_nonnull_addr_p (TREE_OPERAND (op0, 0))) - warning_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_at (location, - OPT_Waddress, "the address of %qD will never be NULL", - TREE_OPERAND (op1, 0)); - result_type = type1; - } + { + tree tt0 = TREE_TYPE (type0); + tree tt1 = TREE_TYPE (type1); + addr_space_t as0 = TYPE_ADDR_SPACE (tt0); + addr_space_t as1 = TYPE_ADDR_SPACE (tt1); + addr_space_t as_common = ADDR_SPACE_GENERIC; + + /* Anything compares with void *. void * compares with anything. + Otherwise, the targets must be compatible + and both must be object or both incomplete. */ + if (comp_target_types (location, type0, type1)) + result_type = common_pointer_type (type0, type1); + else if (!addr_space_superset (as0, as1, &as_common)) + { + error_at (location, "comparison of pointers to " + "disjoint address spaces"); + return error_mark_node; + } + else if (VOID_TYPE_P (tt0)) + { + if (pedantic && TREE_CODE (tt1) == FUNCTION_TYPE) + pedwarn (location, OPT_pedantic, "ISO C forbids " + "comparison of %<void *%> with function pointer"); + } + else if (VOID_TYPE_P (tt1)) + { + if (pedantic && TREE_CODE (tt0) == FUNCTION_TYPE) + pedwarn (location, OPT_pedantic, "ISO C forbids " + "comparison of %<void *%> with function pointer"); + } + else + /* Avoid warning about the volatile ObjC EH puts on decls. */ + if (!objc_ok) + pedwarn (location, 0, + "comparison of distinct pointer types lacks a cast"); + + if (result_type == NULL_TREE) + { + int qual = ENCODE_QUAL_ADDR_SPACE (as_common); + result_type = build_pointer_type + (build_qualified_type (void_type_node, qual)); + } + } else if (code0 == POINTER_TYPE && code1 == INTEGER_TYPE) { result_type = type0; @@ -9511,53 +9908,62 @@ || code1 == FIXED_POINT_TYPE)) short_compare = 1; else if (code0 == POINTER_TYPE && code1 == POINTER_TYPE) - { - addr_space_t as0 = TYPE_ADDR_SPACE (TREE_TYPE (type0)); - addr_space_t as1 = TYPE_ADDR_SPACE (TREE_TYPE (type1)); - addr_space_t as_common; - - if (comp_target_types (location, type0, type1)) - { - result_type = common_pointer_type (type0, type1); - if (!COMPLETE_TYPE_P (TREE_TYPE (type0)) - != !COMPLETE_TYPE_P (TREE_TYPE (type1))) - 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 if (!addr_space_superset (as0, as1, &as_common)) - { - error_at (location, "comparison of pointers to " - "disjoint address spaces"); - return error_mark_node; - } - else - { - int qual = ENCODE_QUAL_ADDR_SPACE (as_common); - result_type = build_pointer_type - (build_qualified_type (void_type_node, qual)); - pedwarn (location, 0, - "comparison of distinct pointer types lacks a cast"); - } - } + { + addr_space_t as0 = TYPE_ADDR_SPACE (TREE_TYPE (type0)); + addr_space_t as1 = TYPE_ADDR_SPACE (TREE_TYPE (type1)); + addr_space_t as_common; + + if (comp_target_types (location, type0, type1)) + { + result_type = common_pointer_type (type0, type1); + if (!COMPLETE_TYPE_P (TREE_TYPE (type0)) + != !COMPLETE_TYPE_P (TREE_TYPE (type1))) + 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 if (null_pointer_constant_p (orig_op0) + || null_pointer_constant_p (orig_op1)) + warning_at (location, OPT_Wextra, + "ordered comparison of pointer with null pointer"); + + } + else if (!addr_space_superset (as0, as1, &as_common)) + { + error_at (location, "comparison of pointers to " + "disjoint address spaces"); + return error_mark_node; + } + else + { + int qual = ENCODE_QUAL_ADDR_SPACE (as_common); + result_type = build_pointer_type + (build_qualified_type (void_type_node, qual)); + 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) - 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"); - } + { + result_type = type0; + 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; - pedwarn (location, OPT_pedantic, - "ordered comparison of pointer with integer zero"); - } + { + result_type = type1; + 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 (code0 == POINTER_TYPE && code1 == INTEGER_TYPE) { result_type = type0; @@ -9597,94 +10003,99 @@ int none_complex = (!first_complex && !second_complex); if (shorten || common || short_compare) - { - result_type = c_common_type (type0, type1); - if (result_type == error_mark_node) - return error_mark_node; - } + { + result_type = c_common_type (type0, type1); + do_warn_double_promotion (result_type, type0, type1, + "implicit conversion from %qT to %qT " + "to match other operand of binary " + "expression", + location); + if (result_type == error_mark_node) + return error_mark_node; + } if (first_complex != second_complex - && (code == PLUS_EXPR - || code == MINUS_EXPR - || code == MULT_EXPR - || (code == TRUNC_DIV_EXPR && first_complex)) - && TREE_CODE (TREE_TYPE (result_type)) == REAL_TYPE - && flag_signed_zeros) - { - /* An operation on mixed real/complex operands must be - handled specially, but the language-independent code can - more easily optimize the plain complex arithmetic if - -fno-signed-zeros. */ - tree real_type = TREE_TYPE (result_type); - tree real, imag; - if (type0 != orig_type0 || type1 != orig_type1) - { - gcc_assert (may_need_excess_precision && common); - real_result_type = c_common_type (orig_type0, orig_type1); - } - if (first_complex) - { - if (TREE_TYPE (op0) != result_type) - op0 = convert_and_check (result_type, op0); - if (TREE_TYPE (op1) != real_type) - op1 = convert_and_check (real_type, op1); - } - else - { - if (TREE_TYPE (op0) != real_type) - op0 = convert_and_check (real_type, op0); - if (TREE_TYPE (op1) != result_type) - op1 = convert_and_check (result_type, op1); - } - if (TREE_CODE (op0) == ERROR_MARK || TREE_CODE (op1) == ERROR_MARK) - return error_mark_node; - if (first_complex) - { - op0 = c_save_expr (op0); - real = build_unary_op (EXPR_LOCATION (orig_op0), REALPART_EXPR, - op0, 1); - imag = build_unary_op (EXPR_LOCATION (orig_op0), IMAGPART_EXPR, - op0, 1); - switch (code) - { - case MULT_EXPR: - case TRUNC_DIV_EXPR: - imag = build2 (resultcode, real_type, imag, op1); - /* Fall through. */ - case PLUS_EXPR: - case MINUS_EXPR: - real = build2 (resultcode, real_type, real, op1); - break; - default: - gcc_unreachable(); - } - } - else - { - op1 = c_save_expr (op1); - real = build_unary_op (EXPR_LOCATION (orig_op1), REALPART_EXPR, - op1, 1); - imag = build_unary_op (EXPR_LOCATION (orig_op1), IMAGPART_EXPR, - op1, 1); - switch (code) - { - case MULT_EXPR: - imag = build2 (resultcode, real_type, op0, imag); - /* Fall through. */ - case PLUS_EXPR: - real = build2 (resultcode, real_type, op0, real); - break; - case MINUS_EXPR: - real = build2 (resultcode, real_type, op0, real); - imag = build1 (NEGATE_EXPR, real_type, imag); - break; - default: - gcc_unreachable(); - } - } - ret = build2 (COMPLEX_EXPR, result_type, real, imag); - goto return_build_binary_op; - } + && (code == PLUS_EXPR + || code == MINUS_EXPR + || code == MULT_EXPR + || (code == TRUNC_DIV_EXPR && first_complex)) + && TREE_CODE (TREE_TYPE (result_type)) == REAL_TYPE + && flag_signed_zeros) + { + /* An operation on mixed real/complex operands must be + handled specially, but the language-independent code can + more easily optimize the plain complex arithmetic if + -fno-signed-zeros. */ + tree real_type = TREE_TYPE (result_type); + tree real, imag; + if (type0 != orig_type0 || type1 != orig_type1) + { + gcc_assert (may_need_excess_precision && common); + semantic_result_type = c_common_type (orig_type0, orig_type1); + } + if (first_complex) + { + if (TREE_TYPE (op0) != result_type) + op0 = convert_and_check (result_type, op0); + if (TREE_TYPE (op1) != real_type) + op1 = convert_and_check (real_type, op1); + } + else + { + if (TREE_TYPE (op0) != real_type) + op0 = convert_and_check (real_type, op0); + if (TREE_TYPE (op1) != result_type) + op1 = convert_and_check (result_type, op1); + } + if (TREE_CODE (op0) == ERROR_MARK || TREE_CODE (op1) == ERROR_MARK) + return error_mark_node; + if (first_complex) + { + op0 = c_save_expr (op0); + real = build_unary_op (EXPR_LOCATION (orig_op0), REALPART_EXPR, + op0, 1); + imag = build_unary_op (EXPR_LOCATION (orig_op0), IMAGPART_EXPR, + op0, 1); + switch (code) + { + case MULT_EXPR: + case TRUNC_DIV_EXPR: + imag = build2 (resultcode, real_type, imag, op1); + /* Fall through. */ + case PLUS_EXPR: + case MINUS_EXPR: + real = build2 (resultcode, real_type, real, op1); + break; + default: + gcc_unreachable(); + } + } + else + { + op1 = c_save_expr (op1); + real = build_unary_op (EXPR_LOCATION (orig_op1), REALPART_EXPR, + op1, 1); + imag = build_unary_op (EXPR_LOCATION (orig_op1), IMAGPART_EXPR, + op1, 1); + switch (code) + { + case MULT_EXPR: + imag = build2 (resultcode, real_type, op0, imag); + /* Fall through. */ + case PLUS_EXPR: + real = build2 (resultcode, real_type, op0, real); + break; + case MINUS_EXPR: + real = build2 (resultcode, real_type, op0, real); + imag = build1 (NEGATE_EXPR, real_type, imag); + break; + default: + gcc_unreachable(); + } + } + ret = build2 (COMPLEX_EXPR, result_type, real, imag); + goto return_build_binary_op; + } /* For certain operations (which identify themselves by shorten != 0) if both args were extended from the same smaller type, @@ -9817,12 +10228,21 @@ return error_mark_node; } + if (build_type == NULL_TREE) + { + build_type = result_type; + if ((type0 != orig_type0 || type1 != orig_type1) + && !boolean_op) + { + gcc_assert (may_need_excess_precision && common); + semantic_result_type = c_common_type (orig_type0, orig_type1); + } + } + if (!converted) { - if (TREE_TYPE (op0) != result_type) - op0 = convert_and_check (result_type, op0); - if (TREE_TYPE (op1) != result_type) - op1 = convert_and_check (result_type, op1); + op0 = ep_convert_and_check (result_type, op0, semantic_result_type); + op1 = ep_convert_and_check (result_type, op1, semantic_result_type); /* This can happen if one operand has a vector type, and the other has a different type. */ @@ -9830,16 +10250,6 @@ return error_mark_node; } - if (build_type == NULL_TREE) - { - build_type = result_type; - if (type0 != orig_type0 || type1 != orig_type1) - { - gcc_assert (may_need_excess_precision && common); - real_result_type = c_common_type (orig_type0, orig_type1); - } - } - /* Treat expressions in initializers specially as they can't trap. */ if (int_const_or_overflow) ret = (require_constant_value @@ -9860,8 +10270,8 @@ else if (TREE_CODE (ret) != INTEGER_CST && int_operands && !in_late_binary_op) ret = note_integer_operands (ret); - if (real_result_type) - ret = build1 (EXCESS_PRECISION_EXPR, real_result_type, ret); + if (semantic_result_type) + ret = build1 (EXCESS_PRECISION_EXPR, semantic_result_type, ret); protected_set_expr_location (ret, location); return ret; } @@ -9889,6 +10299,10 @@ error_at (location, "used union type value where scalar is required"); return error_mark_node; + case VOID_TYPE: + error_at (location, "void value not ignored as it ought to be"); + return error_mark_node; + case FUNCTION_TYPE: gcc_unreachable (); @@ -9901,8 +10315,8 @@ if (int_operands) expr = remove_c_maybe_const_expr (expr); - /* ??? Should we also give an error for void and vectors rather than - leaving those to give errors later? */ + /* ??? Should we also give an error for vectors rather than leaving + those to give errors later? */ expr = c_common_truthvalue_conversion (location, expr); if (TREE_CODE (expr) == INTEGER_CST && int_operands && !int_const)