X-Git-Url: http://git.sourceforge.jp/view?a=blobdiff_plain;f=gcc%2Fc-typeck.c;h=b696e5e38beb933c0ca32c26c0a80d38c3edb092;hb=b3f86a4f3fb7430f84442dcbb34db85625c7d44c;hp=42bebe3543cbc04a8bd091a9c7d604317ee7d1ef;hpb=389dd41bd043170e7dc7660304f14a5f16af3562;p=pf3gnuchains%2Fgcc-fork.git diff --git a/gcc/c-typeck.c b/gcc/c-typeck.c index 42bebe3543c..b696e5e38be 100644 --- a/gcc/c-typeck.c +++ b/gcc/c-typeck.c @@ -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,21 +29,18 @@ along with GCC; see the file COPYING3. If not see #include "system.h" #include "coretypes.h" #include "tm.h" -#include "rtl.h" #include "tree.h" #include "langhooks.h" #include "c-tree.h" -#include "tm_p.h" +#include "c-lang.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" +#include "c-family/c-objc.h" /* Possible cases of implicit bad conversions. Used to select diagnostic messages in convert_for_assignment. */ @@ -54,12 +51,13 @@ enum impl_conv { 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; +/* Possibe cases of scalar_to_vector conversion. */ +enum stv_conv { + stv_error, /* Error occured. */ + stv_nothing, /* Nothing happened. */ + stv_firstarg, /* First argument must be expanded. */ + stv_secondarg /* Second argument must be expanded. */ +}; /* The level of nesting inside "__alignof__". */ int in_alignof; @@ -79,10 +77,12 @@ static int require_constant_elements; static bool null_pointer_constant_p (const_tree); static tree qualify_type (tree, tree); -static int tagged_types_tu_compatible_p (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); @@ -96,19 +96,19 @@ static int spelling_length (void); 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. */ @@ -283,14 +283,55 @@ c_type_promotes_to (tree type) return type; } +/* Return true if between two named address spaces, whether there is a superset + named address space that encompasses both address spaces. If there is a + superset, return which address space is the superset. */ + +static bool +addr_space_superset (addr_space_t as1, addr_space_t as2, addr_space_t *common) +{ + if (as1 == as2) + { + *common = as1; + return true; + } + else if (targetm.addr_space.subset_p (as1, as2)) + { + *common = as2; + return true; + } + else if (targetm.addr_space.subset_p (as2, as1)) + { + *common = as1; + return true; + } + else + return false; +} + /* Return a variant of TYPE which has all the type qualifiers of LIKE as well as those of TYPE. */ static tree qualify_type (tree type, tree like) { + addr_space_t as_type = TYPE_ADDR_SPACE (type); + addr_space_t as_like = TYPE_ADDR_SPACE (like); + addr_space_t as_common; + + /* If the two named address spaces are different, determine the common + superset address space. If there isn't one, raise an error. */ + if (!addr_space_superset (as_type, as_like, &as_common)) + { + as_common = as_type; + error ("%qT and %qT are in disjoint named address spaces", + type, like); + } + return c_build_qualified_type (type, - TYPE_QUALS (type) | TYPE_QUALS (like)); + TYPE_QUALS_NO_ADDR_SPACE (type) + | TYPE_QUALS_NO_ADDR_SPACE (like) + | ENCODE_QUAL_ADDR_SPACE (as_common)); } /* Return true iff the given tree T is a variable length array. */ @@ -370,7 +411,8 @@ composite_type (tree t1, tree t2) bool t1_complete, t2_complete; /* We should not have any type quals on arrays at all. */ - gcc_assert (!TYPE_QUALS (t1) && !TYPE_QUALS (t2)); + gcc_assert (!TYPE_QUALS_NO_ADDR_SPACE (t1) + && !TYPE_QUALS_NO_ADDR_SPACE (t2)); t1_complete = COMPLETE_TYPE_P (t1); t2_complete = COMPLETE_TYPE_P (t2); @@ -473,9 +515,6 @@ composite_type (tree t1, tree 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; @@ -513,7 +552,7 @@ composite_type (tree t1, tree t2) && TREE_CODE (mv2) != ARRAY_TYPE) mv2 = TYPE_MAIN_VARIANT (mv2); for (memb = TYPE_FIELDS (TREE_VALUE (p1)); - memb; memb = TREE_CHAIN (memb)) + memb; memb = DECL_CHAIN (memb)) { tree mv3 = TREE_TYPE (memb); if (mv3 && mv3 != error_mark_node @@ -523,7 +562,7 @@ composite_type (tree t1, tree t2) { TREE_VALUE (n) = composite_type (TREE_TYPE (memb), TREE_VALUE (p2)); - pedwarn (input_location, OPT_pedantic, + pedwarn (input_location, OPT_pedantic, "function types not truly compatible in ISO C"); goto parm_done; } @@ -538,7 +577,7 @@ composite_type (tree t1, tree t2) && TREE_CODE (mv1) != ARRAY_TYPE) mv1 = TYPE_MAIN_VARIANT (mv1); for (memb = TYPE_FIELDS (TREE_VALUE (p2)); - memb; memb = TREE_CHAIN (memb)) + memb; memb = DECL_CHAIN (memb)) { tree mv3 = TREE_TYPE (memb); if (mv3 && mv3 != error_mark_node @@ -548,7 +587,7 @@ composite_type (tree t1, tree t2) { TREE_VALUE (n) = composite_type (TREE_TYPE (memb), TREE_VALUE (p1)); - pedwarn (input_location, OPT_pedantic, + pedwarn (input_location, OPT_pedantic, "function types not truly compatible in ISO C"); goto parm_done; } @@ -558,7 +597,6 @@ composite_type (tree t1, tree t2) parm_done: ; } - c_override_global_bindings_to_false = false; t1 = build_function_type (valtype, newargs); t1 = qualify_type (t1, t2); /* ... falls through ... */ @@ -584,6 +622,8 @@ common_pointer_type (tree t1, tree t2) tree pointed_to_2, mv2; tree target; unsigned target_quals; + addr_space_t as1, as2, as_common; + int quals1, quals2; /* Save time if the two types are the same. */ @@ -615,10 +655,24 @@ common_pointer_type (tree t1, tree t2) /* For function types do not merge const qualifiers, but drop them if used inconsistently. The middle-end uses these to mark const and noreturn functions. */ + quals1 = TYPE_QUALS_NO_ADDR_SPACE (pointed_to_1); + quals2 = TYPE_QUALS_NO_ADDR_SPACE (pointed_to_2); + if (TREE_CODE (pointed_to_1) == FUNCTION_TYPE) - target_quals = TYPE_QUALS (pointed_to_1) & TYPE_QUALS (pointed_to_2); + target_quals = (quals1 & quals2); else - target_quals = TYPE_QUALS (pointed_to_1) | TYPE_QUALS (pointed_to_2); + target_quals = (quals1 | quals2); + + /* If the two named address spaces are different, determine the common + superset address space. This is guaranteed to exist due to the + assumption that comp_target_type returned non-zero. */ + as1 = TYPE_ADDR_SPACE (pointed_to_1); + as2 = TYPE_ADDR_SPACE (pointed_to_2); + if (!addr_space_superset (as1, as2, &as_common)) + gcc_unreachable (); + + target_quals |= ENCODE_QUAL_ADDR_SPACE (as_common); + t1 = build_pointer_type (c_build_qualified_type (target, target_quals)); return build_type_attribute_variant (t1, attributes); } @@ -916,7 +970,7 @@ comptypes (tree type1, tree type2) const struct tagged_tu_seen_cache * tagged_tu_seen_base1 = tagged_tu_seen_base; int val; - val = comptypes_internal (type1, type2, NULL); + val = comptypes_internal (type1, type2, NULL, NULL); free_all_tagged_tu_seen_up_to (tagged_tu_seen_base1); return val; @@ -931,7 +985,23 @@ comptypes_check_enum_int (tree type1, tree type2, bool *enum_and_int_p) 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; @@ -942,11 +1012,17 @@ comptypes_check_enum_int (tree type1, tree type2, bool *enum_and_int_p) 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 C11 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; @@ -958,17 +1034,6 @@ comptypes_internal (const_tree type1, const_tree type2, bool *enum_and_int_p) || 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. */ @@ -976,14 +1041,24 @@ comptypes_internal (const_tree type1, const_tree type2, bool *enum_and_int_p) 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) @@ -1008,7 +1083,7 @@ comptypes_internal (const_tree type1, const_tree type2, bool *enum_and_int_p) return 1; /* 1 if no need for warning yet, 2 if warning cause has been seen. */ - if (!(attrval = targetm.comp_type_attributes (t1, t2))) + if (!(attrval = comp_type_attributes (t1, t2))) return 0; /* 1 if no need for warning yet, 2 if warning cause has been seen. */ @@ -1023,11 +1098,12 @@ comptypes_internal (const_tree type1, const_tree type2, bool *enum_and_int_p) break; val = (TREE_TYPE (t1) == TREE_TYPE (t2) ? 1 : comptypes_internal (TREE_TYPE (t1), TREE_TYPE (t2), - enum_and_int_p)); + 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: @@ -1041,9 +1117,13 @@ comptypes_internal (const_tree type1, const_tree type2, bool *enum_and_int_p) /* 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))) + 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; @@ -1060,6 +1140,9 @@ comptypes_internal (const_tree type1, const_tree type2, bool *enum_and_int_p) 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) @@ -1085,15 +1168,17 @@ comptypes_internal (const_tree type1, const_tree type2, bool *enum_and_int_p) 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); + 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)); + enum_and_int_p, different_types_p)); break; default: @@ -1102,20 +1187,28 @@ comptypes_internal (const_tree type1, const_tree type2, bool *enum_and_int_p) return attrval == 2 && val == 1 ? 2 : val; } -/* Return 1 if TTL and TTR are pointers to types that are equivalent, - ignoring their qualifiers. */ +/* Return 1 if TTL and TTR are pointers to types that are equivalent, ignoring + their qualifiers, except for named address spaces. If the pointers point to + different named addresses, then we must determine if one address space is a + subset of the other. */ static int comp_target_types (location_t location, tree ttl, tree ttr) { int val; - tree mvl, mvr; + tree mvl = TREE_TYPE (ttl); + tree mvr = TREE_TYPE (ttr); + addr_space_t asl = TYPE_ADDR_SPACE (mvl); + addr_space_t asr = TYPE_ADDR_SPACE (mvr); + addr_space_t as_common; bool enum_and_int_p; + /* Fail if pointers point to incompatible address spaces. */ + if (!addr_space_superset (asl, asr, &as_common)) + return 0; + /* Do not lose qualifiers on element types of array types that are pointer targets by taking their TYPE_MAIN_VARIANT. */ - mvl = TREE_TYPE (ttl); - mvr = TREE_TYPE (ttr); if (TREE_CODE (mvl) != ARRAY_TYPE) mvl = TYPE_MAIN_VARIANT (mvl); if (TREE_CODE (mvr) != ARRAY_TYPE) @@ -1217,11 +1310,12 @@ free_all_tagged_tu_seen_up_to (const struct tagged_tu_seen_cache *tu_til) 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; @@ -1325,14 +1419,14 @@ tagged_types_tu_compatible_p (const_tree t1, const_tree t2, /* 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)) + 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); + enum_and_int_p, different_types_p); if (result != 1 && !DECL_NAME (s1)) break; @@ -1358,17 +1452,18 @@ tagged_types_tu_compatible_p (const_tree t1, const_tree t2, return tu->val; } - for (s1 = TYPE_FIELDS (t1); s1; s1 = TREE_CHAIN (s1)) + for (s1 = TYPE_FIELDS (t1); s1; s1 = DECL_CHAIN (s1)) { bool ok = false; - for (s2 = TYPE_FIELDS (t2); s2; s2 = TREE_CHAIN (s2)) + 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); + enum_and_int_p, + different_types_p); if (result != 1 && !DECL_NAME (s1)) continue; @@ -1404,14 +1499,14 @@ tagged_types_tu_compatible_p (const_tree t1, const_tree t2, for (s1 = TYPE_FIELDS (t1), s2 = TYPE_FIELDS (t2); s1 && s2; - s1 = TREE_CHAIN (s1), s2 = TREE_CHAIN (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); + enum_and_int_p, different_types_p); if (result == 0) break; if (result == 2) @@ -1440,11 +1535,11 @@ tagged_types_tu_compatible_p (const_tree t1, const_tree t2, 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. */ @@ -1465,13 +1560,17 @@ function_types_compatible_p (const_tree f1, const_tree f2, 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); + 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. */ @@ -1484,7 +1583,7 @@ function_types_compatible_p (const_tree f1, const_tree f2, 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)) + enum_and_int_p, different_types_p)) val = 2; return val; } @@ -1494,23 +1593,25 @@ function_types_compatible_p (const_tree f1, const_tree f2, return 0; if (TYPE_ACTUAL_ARG_TYPES (f2) && 1 != type_lists_compatible_p (args1, TYPE_ACTUAL_ARG_TYPES (f2), - enum_and_int_p)) + 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; @@ -1535,6 +1636,9 @@ type_lists_compatible_p (const_tree args1, const_tree args2, 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) @@ -1549,26 +1653,30 @@ type_lists_compatible_p (const_tree args1, const_tree args2, else if (TREE_CODE (a1) == ERROR_MARK || TREE_CODE (a2) == ERROR_MARK) ; - else if (!(newval = comptypes_internal (mv1, mv2, enum_and_int_p))) + 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_UNION (a1)) + || 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 = TREE_CHAIN (memb)) + 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)) + if (comptypes_internal (mv3, mv2, enum_and_int_p, + different_types_p)) break; } if (memb == 0) @@ -1576,20 +1684,21 @@ type_lists_compatible_p (const_tree args1, const_tree args2, } else if (TREE_CODE (a2) == UNION_TYPE && (TYPE_NAME (a2) == 0 - || TYPE_TRANSPARENT_UNION (a2)) + || 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 = TREE_CHAIN (memb)) + 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)) + if (comptypes_internal (mv3, mv1, enum_and_int_p, + different_types_p)) break; } if (memb == 0) @@ -1696,6 +1805,36 @@ function_to_pointer_conversion (location_t loc, tree exp) 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. @@ -1751,6 +1890,12 @@ default_function_array_conversion (location_t loc, struct c_expr exp) 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. */ @@ -1812,6 +1957,8 @@ default_conversion (tree exp) 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) @@ -1848,7 +1995,7 @@ default_conversion (tree exp) 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 @@ -1858,9 +2005,8 @@ default_conversion (tree exp) unions, the list steps down the chain to the component. */ static tree -lookup_field (tree decl, tree component) +lookup_field (tree type, tree component) { - tree type = TREE_TYPE (decl); tree field; /* If TYPE_LANG_SPECIFIC is set, then it is a sorted array of pointers @@ -1890,10 +2036,21 @@ lookup_field (tree decl, tree component) if (TREE_CODE (TREE_TYPE (field)) == RECORD_TYPE || TREE_CODE (TREE_TYPE (field)) == UNION_TYPE) { - tree anon = lookup_field (field, component); + 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; } } @@ -1920,16 +2077,26 @@ lookup_field (tree decl, tree component) } else { - for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field)) + 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 (field, component); + 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) @@ -1959,6 +2126,11 @@ build_component_ref (location_t loc, tree datum, tree component) 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) @@ -1969,7 +2141,7 @@ build_component_ref (location_t loc, tree datum, tree component) return error_mark_node; } - field = lookup_field (datum, component); + field = lookup_field (type, component); if (!field) { @@ -2040,7 +2212,7 @@ build_component_ref (location_t loc, tree datum, tree component) LOC is the location to use for the generated tree. */ tree -build_indirect_ref (location_t loc, tree ptr, const char *errorstring) +build_indirect_ref (location_t loc, tree ptr, ref_operator errstring) { tree pointer = default_conversion (ptr); tree type = TREE_TYPE (pointer); @@ -2098,8 +2270,8 @@ build_indirect_ref (location_t loc, tree ptr, const char *errorstring) } } else if (TREE_CODE (pointer) != ERROR_MARK) - error_at (loc, - "invalid type argument of %qs (have %qT)", errorstring, type); + invalid_indirection_error (loc, type, errstring); + return error_mark_node; } @@ -2112,6 +2284,9 @@ build_indirect_ref (location_t loc, tree ptr, const char *errorstring) 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 @@ -2124,13 +2299,17 @@ build_array_ref (location_t loc, tree array, tree index) 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"); + error_at (loc, + "subscripted value is neither array nor pointer nor vector"); + return error_mark_node; } temp = array; @@ -2161,6 +2340,27 @@ build_array_ref (location_t loc, tree array, tree 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) { tree rval, type; @@ -2194,10 +2394,10 @@ build_array_ref (location_t loc, tree array, tree index) while (TREE_CODE (foo) == COMPONENT_REF) foo = TREE_OPERAND (foo, 0); if (TREE_CODE (foo) == VAR_DECL && C_DECL_REGISTER (foo)) - pedwarn (loc, OPT_pedantic, + pedwarn (loc, OPT_pedantic, "ISO C forbids subscripting % array"); else if (!flag_isoc99 && !lvalue_p (foo)) - pedwarn (loc, OPT_pedantic, + pedwarn (loc, OPT_pedantic, "ISO C90 forbids subscripting non-lvalue array"); } @@ -2234,7 +2434,7 @@ build_array_ref (location_t loc, tree array, tree index) return build_indirect_ref (loc, build_binary_op (loc, PLUS_EXPR, ar, index, 0), - "array indexing"); + RO_ARRAY_INDEXING); } } @@ -2280,7 +2480,7 @@ build_external_ref (location_t loc, tree id, int fun, tree *type) warn_deprecated_use (ref, NULL_TREE); /* Recursive call does not count as usage. */ - if (ref != current_function_decl) + if (ref != current_function_decl) { TREE_USED (ref) = 1; } @@ -2499,7 +2699,7 @@ build_function_call_vec (location_t loc, tree function, VEC(tree,gc) *params, tree tem; int nargs; tree *argarray; - + /* Strip NON_LVALUE_EXPRs, etc., since we aren't using as an lvalue. */ STRIP_TYPE_NOPS (function); @@ -2516,7 +2716,14 @@ build_function_call_vec (location_t loc, tree function, VEC(tree,gc) *params, return tem; name = DECL_NAME (function); + + if (flag_tm) + tm_malloc_replacement (function); fundecl = function; + /* Atomic functions have type checking/casting already done. They are + often rewritten and don't match the original parameter list. */ + if (name && !strncmp (IDENTIFIER_POINTER (name), "__atomic_", 9)) + origtypes = NULL; } if (TREE_CODE (TREE_TYPE (function)) == FUNCTION_TYPE) function = function_to_pointer_conversion (loc, function); @@ -2566,7 +2773,8 @@ build_function_call_vec (location_t loc, tree function, VEC(tree,gc) *params, && !comptypes (fntype, TREE_TYPE (tem))) { tree return_type = TREE_TYPE (fntype); - tree trap = build_function_call (loc, built_in_decls[BUILT_IN_TRAP], + tree trap = build_function_call (loc, + builtin_decl_explicit (BUILT_IN_TRAP), NULL_TREE); int i; @@ -2599,7 +2807,7 @@ build_function_call_vec (location_t loc, tree function, VEC(tree,gc) *params, build_constructor (return_type, 0), false); else - rhs = fold_convert_loc (loc, return_type, integer_zero_node); + rhs = build_zero_cst (return_type); return require_complete_type (build2 (COMPOUND_EXPR, return_type, trap, rhs)); @@ -2616,14 +2824,13 @@ build_function_call_vec (location_t loc, tree function, VEC(tree,gc) *params, return error_mark_node; /* Check that the arguments to the function are valid. */ - check_function_arguments (TYPE_ATTRIBUTES (fntype), nargs, argarray, - TYPE_ARG_TYPES (fntype)); + check_function_arguments (fntype, nargs, argarray); if (name != NULL_TREE && !strncmp (IDENTIFIER_POINTER (name), "__builtin_", 10)) { if (require_constant_value) - result = + result = fold_build_call_array_initializer_loc (loc, TREE_TYPE (fntype), function, nargs, argarray); else @@ -2646,6 +2853,98 @@ build_function_call_vec (location_t loc, tree function, VEC(tree,gc) *params, } return require_complete_type (result); } + +/* Build a VEC_PERM_EXPR if V0, V1 and MASK are not error_mark_nodes + and have vector types, V0 has the same type as V1, and the number of + elements of V0, V1, MASK is the same. + + In case V1 is a NULL_TREE it is assumed that __builtin_shuffle was + called with two arguments. In this case implementation passes the + first argument twice in order to share the same tree code. This fact + could enable the mask-values being twice the vector length. This is + an implementation accident and this semantics is not guaranteed to + the user. */ +tree +c_build_vec_perm_expr (location_t loc, tree v0, tree v1, tree mask) +{ + tree ret; + bool wrap = true; + bool maybe_const = false; + bool two_arguments = false; + + if (v1 == NULL_TREE) + { + two_arguments = true; + v1 = v0; + } + + if (v0 == error_mark_node || v1 == error_mark_node + || mask == error_mark_node) + return error_mark_node; + + if (TREE_CODE (TREE_TYPE (mask)) != VECTOR_TYPE + || TREE_CODE (TREE_TYPE (TREE_TYPE (mask))) != INTEGER_TYPE) + { + error_at (loc, "__builtin_shuffle last argument must " + "be an integer vector"); + return error_mark_node; + } + + if (TREE_CODE (TREE_TYPE (v0)) != VECTOR_TYPE + || TREE_CODE (TREE_TYPE (v1)) != VECTOR_TYPE) + { + error_at (loc, "__builtin_shuffle arguments must be vectors"); + return error_mark_node; + } + + if (TYPE_MAIN_VARIANT (TREE_TYPE (v0)) != TYPE_MAIN_VARIANT (TREE_TYPE (v1))) + { + error_at (loc, "__builtin_shuffle argument vectors must be of " + "the same type"); + return error_mark_node; + } + + if (TYPE_VECTOR_SUBPARTS (TREE_TYPE (v0)) + != TYPE_VECTOR_SUBPARTS (TREE_TYPE (mask)) + && TYPE_VECTOR_SUBPARTS (TREE_TYPE (v1)) + != TYPE_VECTOR_SUBPARTS (TREE_TYPE (mask))) + { + error_at (loc, "__builtin_shuffle number of elements of the " + "argument vector(s) and the mask vector should " + "be the same"); + return error_mark_node; + } + + if (GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (TREE_TYPE (v0)))) + != GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (TREE_TYPE (mask))))) + { + error_at (loc, "__builtin_shuffle argument vector(s) inner type " + "must have the same size as inner type of the mask"); + return error_mark_node; + } + + /* Avoid C_MAYBE_CONST_EXPRs inside VEC_PERM_EXPR. */ + v0 = c_fully_fold (v0, false, &maybe_const); + wrap &= maybe_const; + + if (two_arguments) + v1 = v0 = save_expr (v0); + else + { + v1 = c_fully_fold (v1, false, &maybe_const); + wrap &= maybe_const; + } + + mask = c_fully_fold (mask, false, &maybe_const); + wrap &= maybe_const; + + ret = build3_loc (loc, VEC_PERM_EXPR, TREE_TYPE (v0), v0, v1, mask); + + if (!wrap) + ret = c_wrap_maybe_const (ret, true); + + return ret; +} /* Convert the argument expressions in the vector VALUES to the types in the list TYPELIST. @@ -2672,6 +2971,7 @@ convert_arguments (tree typelist, VEC(tree,gc) *values, { tree typetail, val; unsigned int parmnum; + bool error_args = false; const bool type_generic = fundecl && lookup_attribute ("type generic", TYPE_ATTRIBUTES(TREE_TYPE (fundecl))); bool type_generic_remove_excess_precision = false; @@ -2728,7 +3028,15 @@ convert_arguments (tree typelist, VEC(tree,gc) *values, if (type == void_type_node) { - error ("too many arguments to function %qE", function); + 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; } @@ -2923,8 +3231,15 @@ convert_arguments (tree typelist, VEC(tree,gc) *values, if (type_generic) parmval = val; else - /* Convert `float' to `double'. */ - parmval = convert (double_type_node, val); + { + /* 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 @@ -2941,6 +3256,8 @@ convert_arguments (tree typelist, VEC(tree,gc) *values, parmval = default_conversion (val); VEC_replace (tree, values, parmnum, parmval); + if (parmval == error_mark_node) + error_args = true; if (typetail) typetail = TREE_CHAIN (typetail); @@ -2950,11 +3267,14 @@ convert_arguments (tree typelist, VEC(tree,gc) *values, if (typetail != 0 && TREE_VALUE (typetail) != void_type_node) { - 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; } - return parmnum; + return error_args ? -1 : (int) parmnum; } /* This is the entry point used by the parser to build unary operators @@ -3037,8 +3357,8 @@ parser_build_binary_op (location_t location, enum tree_code code, warning_at (location, OPT_Waddress, "comparison with string literal results in unspecified behavior"); - if (TREE_OVERFLOW_P (result.value) - && !TREE_OVERFLOW_P (arg1.value) + if (TREE_OVERFLOW_P (result.value) + && !TREE_OVERFLOW_P (arg1.value) && !TREE_OVERFLOW_P (arg2.value)) overflow_warning (location, result.value); @@ -3062,16 +3382,48 @@ static tree pointer_diff (location_t loc, tree op0, tree op1) { tree restype = ptrdiff_type_node; + tree result, inttype; + addr_space_t as0 = TYPE_ADDR_SPACE (TREE_TYPE (TREE_TYPE (op0))); + addr_space_t as1 = TYPE_ADDR_SPACE (TREE_TYPE (TREE_TYPE (op1))); tree target_type = TREE_TYPE (TREE_TYPE (op0)); tree con0, con1, lit0, lit1; tree orig_op1 = op1; + /* If the operands point into different address spaces, we need to + explicitly convert them to pointers into the common address space + before we can subtract the numerical address values. */ + if (as0 != as1) + { + addr_space_t as_common; + tree common_type; + + /* Determine the common superset address space. This is guaranteed + to exist because the caller verified that comp_target_types + returned non-zero. */ + if (!addr_space_superset (as0, as1, &as_common)) + gcc_unreachable (); + + common_type = common_pointer_type (TREE_TYPE (op0), TREE_TYPE (op1)); + op0 = convert (common_type, op0); + op1 = convert (common_type, op1); + } + + /* Determine integer type to perform computations in. This will usually + be the same as the result type (ptrdiff_t), but may need to be a wider + type if pointers for the address space are wider than ptrdiff_t. */ + if (TYPE_PRECISION (restype) < TYPE_PRECISION (TREE_TYPE (op0))) + inttype = lang_hooks.types.type_for_size + (TYPE_PRECISION (TREE_TYPE (op0)), 0); + else + inttype = restype; + + if (TREE_CODE (target_type) == VOID_TYPE) - pedwarn (loc, pedantic ? OPT_pedantic : OPT_Wpointer_arith, + pedwarn (loc, pedantic ? OPT_pedantic : OPT_Wpointer_arith, "pointer of type % used in subtraction"); if (TREE_CODE (target_type) == FUNCTION_TYPE) - pedwarn (loc, pedantic ? OPT_pedantic : OPT_Wpointer_arith, + pedwarn (loc, pedantic ? OPT_pedantic : OPT_Wpointer_arith, "pointer to a function used in subtraction"); /* If the conversion to ptrdiff_type does anything like widening or @@ -3124,8 +3476,8 @@ pointer_diff (location_t loc, tree op0, tree op1) in case restype is a short type. */ op0 = build_binary_op (loc, - MINUS_EXPR, convert (restype, op0), - convert (restype, op1), 0); + MINUS_EXPR, convert (inttype, op0), + convert (inttype, op1), 0); /* This generates an error if op1 is pointer to incomplete type. */ if (!COMPLETE_OR_VOID_TYPE_P (TREE_TYPE (TREE_TYPE (orig_op1)))) error_at (loc, "arithmetic on pointer to an incomplete type"); @@ -3134,8 +3486,11 @@ pointer_diff (location_t loc, tree op0, tree op1) op1 = c_size_in_bytes (target_type); /* Divide by the size, in easiest possible way. */ - return fold_build2_loc (loc, EXACT_DIV_EXPR, restype, - op0, convert (restype, op1)); + result = fold_build2_loc (loc, EXACT_DIV_EXPR, inttype, + op0, convert (inttype, op1)); + + /* Convert to final result type if necessary. */ + return convert (restype, result); } /* Construct and perhaps optimize a tree representation @@ -3232,7 +3587,7 @@ build_unary_op (location_t location, else if (typecode == COMPLEX_TYPE) { code = CONJ_EXPR; - pedwarn (location, OPT_pedantic, + pedwarn (location, OPT_pedantic, "ISO C does not support %<~%> for complex conjugation"); if (!noconvert) arg = default_conversion (arg); @@ -3283,26 +3638,10 @@ build_unary_op (location_t location, 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; @@ -3325,11 +3664,14 @@ build_unary_op (location_t location, 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))) + /* 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) @@ -3351,7 +3693,7 @@ build_unary_op (location_t location, { tree real, imag; - pedwarn (location, OPT_pedantic, + pedwarn (location, OPT_pedantic, "ISO C does not support %<++%> and %<--%> on complex types"); arg = stabilize_reference (arg); @@ -3402,15 +3744,15 @@ build_unary_op (location_t location, || TREE_CODE (TREE_TYPE (argtype)) == VOID_TYPE) { if (code == PREINCREMENT_EXPR || code == POSTINCREMENT_EXPR) - pedwarn (location, pedantic ? OPT_pedantic : OPT_Wpointer_arith, + pedwarn (location, pedantic ? OPT_pedantic : OPT_Wpointer_arith, "wrong type argument to increment"); else - pedwarn (location, pedantic ? OPT_pedantic : OPT_Wpointer_arith, + 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); + inc = convert_to_ptrofftype_loc (location, inc); } else if (FRACT_MODE_P (TYPE_MODE (argtype))) { @@ -3437,6 +3779,13 @@ build_unary_op (location_t location, 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)) { @@ -3491,18 +3840,12 @@ build_unary_op (location_t location, tree op0 = TREE_OPERAND (arg, 0); if (!c_mark_addressable (op0)) return error_mark_node; - return build_binary_op (location, PLUS_EXPR, - (TREE_CODE (TREE_TYPE (op0)) == ARRAY_TYPE - ? array_to_pointer_conversion (location, - op0) - : op0), - TREE_OPERAND (arg, 1), 1); } /* 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)) + && !lvalue_or_else (location, arg, lv_addressof)) return error_mark_node; /* Move address operations inside C_MAYBE_CONST_EXPR to simplify @@ -3523,14 +3866,22 @@ build_unary_op (location_t location, 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 is only 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)) + && TREE_CODE (argtype) == FUNCTION_TYPE) + { + 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; + + argtype = c_build_qualified_type (argtype, quals); + } if (!c_mark_addressable (arg)) return error_mark_node; @@ -3546,11 +3897,7 @@ build_unary_op (location_t location, if (val && TREE_CODE (val) == INDIRECT_REF && TREE_CONSTANT (TREE_OPERAND (val, 0))) { - tree op0 = fold_convert_loc (location, sizetype, - fold_offsetof (arg, val)), op1; - - op1 = fold_convert_loc (location, argtype, TREE_OPERAND (val, 0)); - ret = fold_build2_loc (location, POINTER_PLUS_EXPR, argtype, op1, op0); + ret = fold_convert_loc (location, argtype, fold_offsetof_1 (arg)); goto return_build_unary_op; } @@ -3624,44 +3971,6 @@ lvalue_p (const_tree ref) } } -/* 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 % 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 % 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 % output")), - arg); -} - /* Give a warning for storing in something that is read-only in GCC terms but not const in ISO C terms. */ @@ -3688,15 +3997,16 @@ readonly_warning (tree arg, enum lvalue_use use) /* 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; } @@ -3768,6 +4078,34 @@ c_mark_addressable (tree exp) } } +/* 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 @@ -3784,12 +4122,11 @@ build_conditional_expr (location_t colon_loc, tree ifexp, bool ifexp_bcp, 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) @@ -3826,8 +4163,6 @@ build_conditional_expr (location_t colon_loc, tree ifexp, bool ifexp_bcp, 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 @@ -3835,7 +4170,7 @@ build_conditional_expr (location_t colon_loc, tree ifexp, bool ifexp_bcp, && (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); @@ -3879,6 +4214,10 @@ build_conditional_expr (location_t colon_loc, tree ifexp, bool ifexp_bcp, || 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 @@ -3912,10 +4251,19 @@ build_conditional_expr (location_t colon_loc, tree ifexp, bool ifexp_bcp, that folding in this case even without warn_sign_compare to avoid warning options possibly affecting code generation. */ + c_inhibit_evaluation_warnings + += (ifexp == truthvalue_false_node); op1 = c_fully_fold (op1, require_constant_value, &op1_maybe_const); + c_inhibit_evaluation_warnings + -= (ifexp == truthvalue_false_node); + + c_inhibit_evaluation_warnings + += (ifexp == truthvalue_true_node); op2 = c_fully_fold (op2, require_constant_value, &op2_maybe_const); + c_inhibit_evaluation_warnings + -= (ifexp == truthvalue_true_node); if (warn_sign_compare) { @@ -3930,17 +4278,9 @@ build_conditional_expr (location_t colon_loc, tree ifexp, bool ifexp_bcp, "conditional expression")); } if (!op1_maybe_const || TREE_CODE (op1) != INTEGER_CST) - { - op1 = build2 (C_MAYBE_CONST_EXPR, TREE_TYPE (op1), - NULL, op1); - C_MAYBE_CONST_EXPR_NON_CONST (op1) = !op1_maybe_const; - } + op1 = c_wrap_maybe_const (op1, !op1_maybe_const); if (!op2_maybe_const || TREE_CODE (op2) != INTEGER_CST) - { - op2 = build2 (C_MAYBE_CONST_EXPR, TREE_TYPE (op2), - NULL, op2); - C_MAYBE_CONST_EXPR_NON_CONST (op2) = !op2_maybe_const; - } + op2 = c_wrap_maybe_const (op2, !op2_maybe_const); } } } @@ -3954,12 +4294,22 @@ build_conditional_expr (location_t colon_loc, tree ifexp, bool ifexp_bcp, } else if (code1 == POINTER_TYPE && code2 == POINTER_TYPE) { + addr_space_t as1 = TYPE_ADDR_SPACE (TREE_TYPE (type1)); + addr_space_t as2 = TYPE_ADDR_SPACE (TREE_TYPE (type2)); + addr_space_t as_common; + if (comp_target_types (colon_loc, type1, type2)) result_type = common_pointer_type (type1, type2); else if (null_pointer_constant_p (orig_op1)) - result_type = qualify_type (type2, type1); + result_type = type2; else if (null_pointer_constant_p (orig_op2)) - result_type = qualify_type (type1, type2); + result_type = type1; + else if (!addr_space_superset (as1, as2, &as_common)) + { + error_at (colon_loc, "pointers to disjoint address spaces " + "used in conditional expression"); + return error_mark_node; + } else if (VOID_TYPE_P (TREE_TYPE (type1))) { if (TREE_CODE (TREE_TYPE (type2)) == FUNCTION_TYPE) @@ -3978,12 +4328,17 @@ build_conditional_expr (location_t colon_loc, tree ifexp, bool ifexp_bcp, 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 { - if (!objc_ok) - pedwarn (colon_loc, 0, - "pointer type mismatch in conditional expression"); - result_type = build_pointer_type (void_type_node); + 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) @@ -4023,13 +4378,11 @@ build_conditional_expr (location_t colon_loc, tree ifexp, bool ifexp_bcp, /* Merge const and volatile flags of the incoming types. */ result_type = build_type_variant (result_type, - TREE_READONLY (op1) || TREE_READONLY (op2), - TREE_THIS_VOLATILE (op1) || TREE_THIS_VOLATILE (op2)); + TYPE_READONLY (type1) || TYPE_READONLY (type2), + TYPE_VOLATILE (type1) || TYPE_VOLATILE (type2)); - if (result_type != TREE_TYPE (op1)) - op1 = convert_and_check (result_type, op1); - if (result_type != TREE_TYPE (op2)) - 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) { @@ -4061,8 +4414,8 @@ build_conditional_expr (location_t colon_loc, tree ifexp, bool ifexp_bcp, 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; @@ -4110,7 +4463,7 @@ build_compound_expr (location_t loc, tree expr1, tree expr2) && CONVERT_EXPR_P (TREE_OPERAND (expr1, 1))) ; /* (void) a, (void) b, c */ else - warning_at (loc, OPT_Wunused_value, + warning_at (loc, OPT_Wunused_value, "left-hand operand of comma expression has no effect"); } } @@ -4141,11 +4494,13 @@ build_compound_expr (location_t loc, tree expr1, tree expr2) /* 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. */ + 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; @@ -4168,21 +4523,25 @@ handle_warn_cast_qual (tree type, tree otype) taken away. */ if (TREE_CODE (in_otype) == FUNCTION_TYPE && TREE_CODE (in_type) == FUNCTION_TYPE) - added |= (TYPE_QUALS (in_type) & ~TYPE_QUALS (in_otype)); + added |= (TYPE_QUALS_NO_ADDR_SPACE (in_type) + & ~TYPE_QUALS_NO_ADDR_SPACE (in_otype)); else - discarded |= (TYPE_QUALS (in_otype) & ~TYPE_QUALS (in_type)); + discarded |= (TYPE_QUALS_NO_ADDR_SPACE (in_otype) + & ~TYPE_QUALS_NO_ADDR_SPACE (in_type)); } while (TREE_CODE (in_type) == POINTER_TYPE && 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; @@ -4215,9 +4574,10 @@ handle_warn_cast_qual (tree type, tree 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")); + warning_at (loc, OPT_Wcast_qual, + "to be safe all intermediate pointers in cast from " + "%qT to %qT must be % qualified", + otype, type); break; } if (is_const) @@ -4226,7 +4586,7 @@ handle_warn_cast_qual (tree type, tree otype) while (TREE_CODE (in_type) == POINTER_TYPE); } -/* Build an expression representing a cast to type TYPE of expression EXPR. +/* Build an expression representing a cast to type TYPE of expression EXPR. LOC is the location of the cast-- typically the open paren of the cast. */ tree @@ -4273,14 +4633,14 @@ build_c_cast (location_t loc, tree type, tree expr) { if (TREE_CODE (type) == RECORD_TYPE || TREE_CODE (type) == UNION_TYPE) - pedwarn (loc, OPT_pedantic, + pedwarn (loc, OPT_pedantic, "ISO C forbids casting nonscalar to the same type"); } else if (TREE_CODE (type) == UNION_TYPE) { tree field; - for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field)) + 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)))) @@ -4289,10 +4649,14 @@ build_c_cast (location_t loc, tree type, tree expr) if (field) { tree t; + bool maybe_const = true; pedwarn (loc, OPT_pedantic, "ISO C forbids casts to union type"); - t = digest_init (loc, type, - build_constructor_single (type, field, value), + 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; @@ -4317,7 +4681,37 @@ build_c_cast (location_t loc, tree type, tree expr) if (warn_cast_qual && TREE_CODE (type) == POINTER_TYPE && TREE_CODE (otype) == POINTER_TYPE) - handle_warn_cast_qual (type, otype); + handle_warn_cast_qual (loc, type, otype); + + /* Warn about conversions between pointers to disjoint + address spaces. */ + if (TREE_CODE (type) == POINTER_TYPE + && TREE_CODE (otype) == POINTER_TYPE + && !null_pointer_constant_p (value)) + { + addr_space_t as_to = TYPE_ADDR_SPACE (TREE_TYPE (type)); + addr_space_t as_from = TYPE_ADDR_SPACE (TREE_TYPE (otype)); + addr_space_t as_common; + + if (!addr_space_superset (as_to, as_from, &as_common)) + { + if (ADDR_SPACE_GENERIC_P (as_from)) + warning_at (loc, 0, "cast to %s address space pointer " + "from disjoint generic address space pointer", + c_addr_space_name (as_to)); + + else if (ADDR_SPACE_GENERIC_P (as_to)) + warning_at (loc, 0, "cast to generic address space pointer " + "from disjoint %s address space pointer", + c_addr_space_name (as_from)); + + else + warning_at (loc, 0, "cast to %s address space pointer " + "from disjoint %s address space pointer", + c_addr_space_name (as_to), + c_addr_space_name (as_from)); + } + } /* Warn about possible alignment problems. */ if (STRICT_ALIGNMENT @@ -4459,8 +4853,9 @@ c_cast_expr (location_t loc, struct c_type_name *type_name, tree expr) 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++"); @@ -4481,7 +4876,7 @@ c_cast_expr (location_t loc, struct c_type_name *type_name, tree expr) tree build_modify_expr (location_t location, tree lhs, tree lhs_origtype, - enum tree_code modifycode, + enum tree_code modifycode, location_t rhs_loc, tree rhs, tree rhs_origtype) { tree result; @@ -4498,7 +4893,8 @@ build_modify_expr (location_t location, tree lhs, tree lhs_origtype, 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) @@ -4539,6 +4935,19 @@ build_modify_expr (location_t location, tree lhs, tree lhs_origtype, 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) @@ -4634,6 +5043,106 @@ build_modify_expr (location_t location, tree lhs, tree lhs_origtype, 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 @@ -4699,7 +5208,7 @@ convert_for_assignment (location_t location, tree type, tree rhs, 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); \ @@ -4709,6 +5218,36 @@ convert_for_assignment (location_t location, tree type, tree rhs, } \ } 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); @@ -4826,10 +5365,10 @@ convert_for_assignment (location_t location, tree type, tree rhs, { tree ret; bool save = in_late_binary_op; - if (codel == BOOLEAN_TYPE) + if (codel == BOOLEAN_TYPE || codel == COMPLEX_TYPE) in_late_binary_op = true; ret = convert_and_check (type, orig_rhs); - if (codel == BOOLEAN_TYPE) + if (codel == BOOLEAN_TYPE || codel == COMPLEX_TYPE) in_late_binary_op = save; return ret; } @@ -4840,14 +5379,15 @@ convert_for_assignment (location_t location, tree type, tree rhs, && 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)) + for (memb = TYPE_FIELDS (type); memb ; memb = DECL_CHAIN (memb)) { tree memb_type = TREE_TYPE (memb); @@ -4913,36 +5453,40 @@ convert_for_assignment (location_t location, tree type, tree rhs, 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 (ttl) & ~TYPE_QUALS (ttr)) - WARN_FOR_ASSIGNMENT (location, 0, + 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 qualified function " + "makes %q#v qualified function " "pointer from unqualified"), - G_("assignment makes qualified " + G_("assignment makes %q#v qualified " "function pointer from " "unqualified"), - G_("initialization makes qualified " + G_("initialization makes %q#v qualified " "function pointer from " "unqualified"), - G_("return makes 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 (ttr) & ~TYPE_QUALS (ttl)) - WARN_FOR_ASSIGNMENT (location, 0, + 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 " - "qualifiers from pointer target type"), - G_("assignment discards qualifiers " + "%qv qualifier from pointer target type"), + G_("assignment discards %qv qualifier " "from pointer target type"), - G_("initialization discards qualifiers " + G_("initialization discards %qv qualifier " "from pointer target type"), - G_("return discards qualifiers 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, + pedwarn (location, OPT_pedantic, "ISO C prohibits argument conversion to union type"); rhs = fold_convert_loc (location, TREE_TYPE (memb), rhs); @@ -4960,6 +5504,8 @@ convert_for_assignment (location_t location, tree type, tree rhs, tree mvr = ttr; bool is_opaque_pointer; int target_cmp = 0; /* Cache comp_target_types () result. */ + addr_space_t asl; + addr_space_t asr; if (TREE_CODE (mvl) != ARRAY_TYPE) mvl = TYPE_MAIN_VARIANT (mvl); @@ -4968,6 +5514,25 @@ convert_for_assignment (location_t location, tree type, tree rhs, /* 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 @@ -4980,6 +5545,36 @@ convert_for_assignment (location_t location, tree type, tree rhs, "request for implicit conversion " "from %qT to %qT not permitted in C++", rhstype, type); + /* See if the pointers point to incompatible address spaces. */ + asl = TYPE_ADDR_SPACE (ttl); + asr = TYPE_ADDR_SPACE (ttr); + if (!null_pointer_constant_p (rhs) + && asr != asl && !targetm.addr_space.subset_p (asr, asl)) + { + switch (errtype) + { + case ic_argpass: + error_at (location, "passing argument %d of %qE from pointer to " + "non-enclosed address space", parmnum, rname); + break; + case ic_assign: + error_at (location, "assignment from pointer to " + "non-enclosed address space"); + break; + case ic_init: + error_at (location, "initialization from pointer to " + "non-enclosed address space"); + break; + case ic_return: + error_at (location, "return from pointer to " + "non-enclosed address space"); + break; + default: + gcc_unreachable (); + } + return error_mark_node; + } + /* Check if the right-hand side has a format attribute but the left-hand side doesn't. */ if (warn_missing_format_attribute @@ -5043,21 +5638,19 @@ convert_for_assignment (location_t location, tree type, tree rhs, else if (TREE_CODE (ttr) != FUNCTION_TYPE && TREE_CODE (ttl) != FUNCTION_TYPE) { - if (TYPE_QUALS (ttr) & ~TYPE_QUALS (ttl)) + 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")); + 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. */ @@ -5083,17 +5676,19 @@ convert_for_assignment (location_t location, tree type, tree rhs, 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 (ttl) & ~TYPE_QUALS (ttr)) - WARN_FOR_ASSIGNMENT (location, 0, + 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 " - "qualified function pointer " + "%q#v qualified function pointer " "from unqualified"), - G_("assignment makes qualified function " + G_("assignment makes %q#v qualified function " "pointer from unqualified"), - G_("initialization makes qualified " + G_("initialization makes %q#v qualified " "function pointer from unqualified"), - G_("return makes qualified function " - "pointer from unqualified")); + G_("return makes %q#v qualified function " + "pointer from unqualified"), + TYPE_QUALS (ttl) & ~TYPE_QUALS (ttr)); } } else @@ -5247,7 +5842,7 @@ store_init_value (location_t init_loc, tree decl, tree init, tree origtype) /* ANSI wants warnings about out-of-range constant initializers. */ STRIP_TYPE_NOPS (value); - if (TREE_STATIC (decl)) + if (TREE_STATIC (decl)) constant_expression_warning (value); /* Check if we need to set array size from compound literal size. */ @@ -5269,11 +5864,13 @@ store_init_value (location_t init_loc, tree decl, tree init, tree origtype) /* For int foo[] = (int [3]){1}; we need to set array size now since later on array initializer will be just the brace enclosed list of the compound literal. */ + tree etype = strip_array_types (TREE_TYPE (decl)); type = build_distinct_type_copy (TYPE_MAIN_VARIANT (type)); - TREE_TYPE (decl) = type; TYPE_DOMAIN (type) = TYPE_DOMAIN (TREE_TYPE (cldecl)); layout_type (type); layout_decl (cldecl, 0); + TREE_TYPE (decl) + = c_build_qualified_type (type, TYPE_QUALS (etype)); } } } @@ -5402,15 +5999,16 @@ print_spelling (char *buffer) } /* 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); @@ -5418,32 +6016,34 @@ error_init (const char *msgid) /* 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); } -/* Issue a warning for a bad initializer component. +/* 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); @@ -5460,7 +6060,7 @@ maybe_warn_string_init (tree type, struct c_expr expr) && TREE_CODE (type) == ARRAY_TYPE && TREE_CODE (expr.value) == STRING_CST && expr.original_code != STRING_CST) - pedwarn_init (input_location, OPT_pedantic, + pedwarn_init (input_location, OPT_pedantic, "array initialized from parenthesized string constant"); } @@ -6095,7 +6695,7 @@ really_start_incremental_init (tree 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); + constructor_fields = DECL_CHAIN (constructor_fields); constructor_unfilled_fields = constructor_fields; constructor_bit_index = bitsize_zero_node; @@ -6110,14 +6710,14 @@ really_start_incremental_init (tree 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 = 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 = build_int_cst (NULL_TREE, -1); + constructor_max_index = integer_minus_one_node; constructor_index = convert (bitsizetype, @@ -6135,7 +6735,7 @@ really_start_incremental_init (tree type) { /* Vectors are like simple fixed-size arrays. */ constructor_max_index = - build_int_cst (NULL_TREE, TYPE_VECTOR_SUBPARTS (constructor_type) - 1); + bitsize_int (TYPE_VECTOR_SUBPARTS (constructor_type) - 1); constructor_index = bitsize_zero_node; constructor_unfilled_index = constructor_index; } @@ -6153,7 +6753,7 @@ really_start_incremental_init (tree type) 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; @@ -6171,12 +6771,14 @@ push_init_level (int implicit) if ((TREE_CODE (constructor_type) == RECORD_TYPE || TREE_CODE (constructor_type) == UNION_TYPE) && constructor_fields == 0) - process_init_element (pop_init_level (1), true); + 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), true); + process_init_element (pop_init_level (1, braced_init_obstack), + true, braced_init_obstack); else break; } @@ -6189,9 +6791,9 @@ push_init_level (int implicit) if ((TREE_CODE (constructor_type) == RECORD_TYPE || TREE_CODE (constructor_type) == UNION_TYPE) && constructor_fields) - value = find_init_member (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); @@ -6277,7 +6879,7 @@ push_init_level (int implicit) if (!VEC_empty (constructor_elt, constructor_elements) && (TREE_CODE (constructor_type) == RECORD_TYPE || TREE_CODE (constructor_type) == ARRAY_TYPE)) - set_nonincremental_init (); + set_nonincremental_init (braced_init_obstack); } if (implicit == 1 && warn_missing_braces && !missing_braces_mentioned) @@ -6293,7 +6895,7 @@ push_init_level (int implicit) /* 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); + constructor_fields = DECL_CHAIN (constructor_fields); constructor_unfilled_fields = constructor_fields; constructor_bit_index = bitsize_zero_node; @@ -6302,8 +6904,8 @@ push_init_level (int implicit) { /* Vectors are like simple fixed-size arrays. */ constructor_max_index = - build_int_cst (NULL_TREE, TYPE_VECTOR_SUBPARTS (constructor_type) - 1); - constructor_index = convert (bitsizetype, integer_zero_node); + bitsize_int (TYPE_VECTOR_SUBPARTS (constructor_type) - 1); + constructor_index = bitsize_int (0); constructor_unfilled_index = constructor_index; } else if (TREE_CODE (constructor_type) == ARRAY_TYPE) @@ -6316,14 +6918,14 @@ push_init_level (int implicit) /* 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 = 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 = build_int_cst (NULL_TREE, -1); + constructor_max_index = integer_minus_one_node; constructor_index = convert (bitsizetype, @@ -6338,7 +6940,7 @@ push_init_level (int implicit) /* 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); + set_nonincremental_init_from_string (value, braced_init_obstack); } } else @@ -6362,7 +6964,7 @@ push_init_level (int implicit) 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; @@ -6375,14 +6977,16 @@ pop_init_level (int implicit) /* When we come to an explicit close brace, pop any inner levels that didn't have explicit braces. */ while (constructor_stack->implicit) - process_init_element (pop_init_level (1), 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; @@ -6410,7 +7014,7 @@ pop_init_level (int implicit) /* 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) + if (DECL_CHAIN (constructor_fields) != NULL_TREE) constructor_type = NULL_TREE; } } @@ -6421,15 +7025,23 @@ pop_init_level (int implicit) && TREE_CODE (constructor_type) == RECORD_TYPE && constructor_unfilled_fields) { + bool constructor_zeroinit = + (VEC_length (constructor_elt, constructor_elements) == 1 + && integer_zerop + (VEC_index (constructor_elt, constructor_elements, 0)->value)); + /* 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) + constructor_unfilled_fields = DECL_CHAIN (constructor_unfilled_fields); + + if (constructor_unfilled_fields + /* Do not warn if this level of the initializer uses member + designators; it is likely to be deliberate. */ + && !constructor_designated + /* Do not warn about initializing with ` = {0}'. */ + && !constructor_zeroinit) { push_member_name (constructor_unfilled_fields); warning_init (OPT_Wmissing_field_initializers, @@ -6523,7 +7135,7 @@ pop_init_level (int implicit) 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; @@ -6545,7 +7157,10 @@ set_designator (int array) /* Designator list starts at the level of closest explicit braces. */ while (constructor_stack->implicit) - process_init_element (pop_init_level (1), true); + { + process_init_element (pop_init_level (1, braced_init_obstack), + true, braced_init_obstack); + } constructor_designated = 1; return 0; } @@ -6578,7 +7193,7 @@ set_designator (int array) } constructor_designated = 1; - push_init_level (2); + push_init_level (2, braced_init_obstack); return 0; } @@ -6587,11 +7202,13 @@ set_designator (int array) 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; @@ -6609,9 +7226,10 @@ push_range_stack (tree range_end) of indices, running from FIRST through LAST. */ void -set_init_index (tree first, tree last) +set_init_index (tree first, tree last, + struct obstack * braced_init_obstack) { - if (set_designator (1)) + if (set_designator (1, braced_init_obstack)) return; designator_erroneous = 1; @@ -6683,18 +7301,18 @@ set_init_index (tree first, tree last) 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) +set_init_label (tree fieldname, struct obstack * braced_init_obstack) { - tree tail; + tree field; - if (set_designator (0)) + if (set_designator (0, braced_init_obstack)) return; designator_erroneous = 1; @@ -6706,23 +7324,26 @@ set_init_label (tree fieldname) return; } - for (tail = TYPE_FIELDS (constructor_type); tail; - tail = TREE_CHAIN (tail)) - { - if (DECL_NAME (tail) == fieldname) - break; - } + field = lookup_field (constructor_type, fieldname); - if (tail == 0) + 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); - } + 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 @@ -6736,7 +7357,8 @@ set_init_label (tree fieldname) 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; @@ -6795,7 +7417,8 @@ add_pending_init (tree purpose, tree value, tree origtype, bool implicit) } } - 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; @@ -6964,7 +7587,7 @@ add_pending_init (tree purpose, tree value, tree origtype, bool implicit) /* 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; @@ -6974,7 +7597,10 @@ set_nonincremental_init (void) 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) { @@ -7001,7 +7627,8 @@ set_nonincremental_init (void) /* 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]; @@ -7064,7 +7691,8 @@ set_nonincremental_init_from_string (tree str) } 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; @@ -7074,7 +7702,7 @@ set_nonincremental_init_from_string (tree str) not initialized yet. */ static tree -find_init_member (tree field) +find_init_member (tree field, struct obstack * braced_init_obstack) { struct init_node *p; @@ -7082,7 +7710,7 @@ find_init_member (tree field) { if (constructor_incremental && tree_int_cst_lt (field, constructor_unfilled_index)) - set_nonincremental_init (); + set_nonincremental_init (braced_init_obstack); p = constructor_pending_elts; while (p) @@ -7103,7 +7731,7 @@ find_init_member (tree field) && (!constructor_unfilled_fields || tree_int_cst_lt (bitpos, bit_position (constructor_unfilled_fields)))) - set_nonincremental_init (); + set_nonincremental_init (braced_init_obstack); p = constructor_pending_elts; while (p) @@ -7147,7 +7775,8 @@ find_init_member (tree field) 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; @@ -7241,7 +7870,7 @@ output_init_element (tree value, tree origtype, bool strict_string, tree type, || (COMPLETE_TYPE_P (TREE_TYPE (field)) && integer_zerop (TYPE_SIZE (TREE_TYPE (field))) && (TREE_CODE (constructor_type) == ARRAY_TYPE - || TREE_CHAIN (field))))) + || DECL_CHAIN (field))))) return; if (semantic_type) @@ -7264,9 +7893,10 @@ output_init_element (tree value, tree origtype, bool strict_string, tree type, { if (constructor_incremental && tree_int_cst_lt (field, constructor_unfilled_index)) - set_nonincremental_init (); + set_nonincremental_init (braced_init_obstack); - add_pending_init (field, value, origtype, implicit); + add_pending_init (field, value, origtype, implicit, + braced_init_obstack); return; } else if (TREE_CODE (constructor_type) == RECORD_TYPE @@ -7279,7 +7909,7 @@ output_init_element (tree value, tree origtype, bool strict_string, tree type, if (constructor_incremental) { if (!constructor_unfilled_fields) - set_nonincremental_init (); + set_nonincremental_init (braced_init_obstack); else { tree bitpos, unfillpos; @@ -7288,11 +7918,12 @@ output_init_element (tree value, tree origtype, bool strict_string, tree type, unfillpos = bit_position (constructor_unfilled_fields); if (tree_int_cst_lt (bitpos, unfillpos)) - set_nonincremental_init (); + set_nonincremental_init (braced_init_obstack); } } - add_pending_init (field, value, origtype, implicit); + add_pending_init (field, value, origtype, implicit, + braced_init_obstack); return; } else if (TREE_CODE (constructor_type) == UNION_TYPE @@ -7327,21 +7958,21 @@ output_init_element (tree value, tree origtype, bool strict_string, tree type, 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_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. @@ -7354,9 +7985,8 @@ output_init_element (tree value, tree origtype, bool strict_string, tree type, 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; @@ -7377,7 +8007,8 @@ output_pending_init_elements (int all) constructor_unfilled_index)) output_init_element (elt->value, elt->origtype, true, TREE_TYPE (constructor_type), - constructor_unfilled_index, 0, false); + constructor_unfilled_index, 0, false, + braced_init_obstack); else if (tree_int_cst_lt (constructor_unfilled_index, elt->purpose)) { @@ -7431,7 +8062,8 @@ output_pending_init_elements (int all) constructor_unfilled_fields = elt->purpose; output_init_element (elt->value, elt->origtype, true, TREE_TYPE (elt->purpose), - elt->purpose, 0, false); + elt->purpose, 0, false, + braced_init_obstack); } else if (tree_int_cst_lt (ctor_unfilled_bitpos, elt_bitpos)) { @@ -7502,7 +8134,8 @@ output_pending_init_elements (int all) 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; @@ -7543,13 +8176,15 @@ process_init_element (struct c_expr value, bool 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); + 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); + process_init_element (pop_init_level (1, braced_init_obstack), + true, braced_init_obstack); else break; } @@ -7599,7 +8234,7 @@ process_init_element (struct c_expr value, bool implicit) if (fieldcode == ARRAY_TYPE && !require_constant_value && TYPE_SIZE (fieldtype) == NULL_TREE - && TREE_CHAIN (constructor_fields) == NULL_TREE) + && DECL_CHAIN (constructor_fields) == NULL_TREE) { error_init ("non-static initialization of a flexible array member"); break; @@ -7619,7 +8254,7 @@ process_init_element (struct c_expr value, bool implicit) && (fieldcode == RECORD_TYPE || fieldcode == ARRAY_TYPE || fieldcode == UNION_TYPE || fieldcode == VECTOR_TYPE)) { - push_init_level (1); + push_init_level (1, braced_init_obstack); continue; } @@ -7628,7 +8263,8 @@ process_init_element (struct c_expr value, bool implicit) push_member_name (constructor_fields); output_init_element (value.value, value.original_type, strict_string, fieldtype, - constructor_fields, 1, implicit); + constructor_fields, 1, implicit, + braced_init_obstack); RESTORE_SPELLING_DEPTH (constructor_depth); } else @@ -7646,22 +8282,22 @@ process_init_element (struct c_expr value, bool implicit) it isn't now, so update. */ if (constructor_unfilled_fields == constructor_fields) { - constructor_unfilled_fields = TREE_CHAIN (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 = - TREE_CHAIN (constructor_unfilled_fields); + DECL_CHAIN (constructor_unfilled_fields); } } - constructor_fields = TREE_CHAIN (constructor_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 = TREE_CHAIN (constructor_fields); + constructor_fields = DECL_CHAIN (constructor_fields); } else if (TREE_CODE (constructor_type) == UNION_TYPE) { @@ -7710,7 +8346,7 @@ process_init_element (struct c_expr value, bool implicit) && (fieldcode == RECORD_TYPE || fieldcode == ARRAY_TYPE || fieldcode == UNION_TYPE || fieldcode == VECTOR_TYPE)) { - push_init_level (1); + push_init_level (1, braced_init_obstack); continue; } @@ -7719,7 +8355,8 @@ process_init_element (struct c_expr value, bool implicit) push_member_name (constructor_fields); output_init_element (value.value, value.original_type, strict_string, fieldtype, - constructor_fields, 1, implicit); + constructor_fields, 1, implicit, + braced_init_obstack); RESTORE_SPELLING_DEPTH (constructor_depth); } else @@ -7727,7 +8364,7 @@ process_init_element (struct c_expr value, bool implicit) directly output as a constructor. */ { constructor_bit_index = DECL_SIZE (constructor_fields); - constructor_unfilled_fields = TREE_CHAIN (constructor_fields); + constructor_unfilled_fields = DECL_CHAIN (constructor_fields); } constructor_fields = 0; @@ -7751,7 +8388,7 @@ process_init_element (struct c_expr value, bool implicit) && (eltcode == RECORD_TYPE || eltcode == ARRAY_TYPE || eltcode == UNION_TYPE || eltcode == VECTOR_TYPE)) { - push_init_level (1); + push_init_level (1, braced_init_obstack); continue; } @@ -7770,7 +8407,8 @@ process_init_element (struct c_expr value, bool implicit) push_array_bounds (tree_low_cst (constructor_index, 1)); output_init_element (value.value, value.original_type, strict_string, elttype, - constructor_index, 1, implicit); + constructor_index, 1, implicit, + braced_init_obstack); RESTORE_SPELLING_DEPTH (constructor_depth); } @@ -7804,7 +8442,8 @@ process_init_element (struct c_expr value, bool implicit) elttype = TYPE_MAIN_VARIANT (constructor_type); output_init_element (value.value, value.original_type, strict_string, elttype, - constructor_index, 1, implicit); + constructor_index, 1, implicit, + braced_init_obstack); } constructor_index @@ -7832,7 +8471,8 @@ process_init_element (struct c_expr value, bool implicit) if (value.value) output_init_element (value.value, value.original_type, strict_string, constructor_type, - NULL_TREE, 1, implicit); + NULL_TREE, 1, implicit, + braced_init_obstack); constructor_fields = 0; } @@ -7848,14 +8488,17 @@ process_init_element (struct c_expr value, bool implicit) while (constructor_stack != range_stack->stack) { gcc_assert (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); } 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); + process_init_element (pop_init_level (1, braced_init_obstack), + true, braced_init_obstack); } p->index = size_binop_loc (input_location, @@ -7875,7 +8518,7 @@ process_init_element (struct c_expr value, bool implicit) p = p->next; if (!p) break; - push_init_level (2); + 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; @@ -7910,7 +8553,7 @@ build_asm_stmt (tree cv_qualifier, tree args) are subtly different. We use a ASM_EXPR node to represent this. */ tree build_asm_expr (location_t loc, tree string, tree outputs, tree inputs, - tree clobbers, bool simple) + tree clobbers, tree labels, bool simple) { tree tail; tree args; @@ -7924,7 +8567,7 @@ build_asm_expr (location_t loc, tree string, tree outputs, tree inputs, noutputs = list_length (outputs); oconstraints = (const char **) alloca (noutputs * sizeof (const char *)); - string = resolve_asm_operand_names (string, outputs, inputs); + string = resolve_asm_operand_names (string, outputs, inputs, labels); /* Remove output conversions that change the type but not the mode. */ for (i = 0, tail = outputs; tail; ++i, tail = TREE_CHAIN (tail)) @@ -7939,7 +8582,7 @@ build_asm_expr (location_t loc, tree string, tree outputs, tree inputs, get an error. Gross, but ... */ STRIP_NOPS (output); - if (!lvalue_or_else (output, lv_asm)) + if (!lvalue_or_else (loc, output, lv_asm)) output = error_mark_node; if (output != error_mark_node @@ -7960,6 +8603,13 @@ build_asm_expr (location_t loc, tree string, tree outputs, tree inputs, mark it addressable. */ if (!allows_reg && !c_mark_addressable (output)) output = error_mark_node; + if (!(!allows_reg && allows_mem) + && output != error_mark_node + && VOID_TYPE_P (TREE_TYPE (output))) + { + error_at (loc, "invalid use of void expression"); + output = error_mark_node; + } } else output = error_mark_node; @@ -7986,7 +8636,12 @@ build_asm_expr (location_t loc, tree string, tree outputs, tree inputs, STRIP_NOPS (input); if (!c_mark_addressable (input)) input = error_mark_node; - } + } + else if (input != error_mark_node && VOID_TYPE_P (TREE_TYPE (input))) + { + error_at (loc, "invalid use of void expression"); + input = error_mark_node; + } } else input = error_mark_node; @@ -7994,7 +8649,11 @@ build_asm_expr (location_t loc, tree string, tree outputs, tree inputs, TREE_VALUE (tail) = input; } - args = build_stmt (loc, ASM_EXPR, string, outputs, inputs, clobbers); + /* ASMs with labels cannot have outputs. This should have been + enforced by the parser. */ + gcc_assert (outputs == NULL || labels == NULL); + + args = build_stmt (loc, ASM_EXPR, string, outputs, inputs, clobbers, labels); /* asm statements without outputs, including simple ones, are treated as volatile. */ @@ -8072,7 +8731,7 @@ c_finish_return (location_t loc, tree retval, tree origtype) if ((warn_return_type || flag_isoc99) && valtype != 0 && TREE_CODE (valtype) != VOID_TYPE) { - pedwarn_c99 (loc, flag_isoc99 ? 0 : OPT_Wreturn_type, + pedwarn_c99 (loc, flag_isoc99 ? 0 : OPT_Wreturn_type, "% with no value, in " "function returning non-void"); no_warning = true; @@ -8082,9 +8741,9 @@ c_finish_return (location_t loc, tree retval, tree origtype) { current_function_returns_null = 1; if (TREE_CODE (TREE_TYPE (retval)) != VOID_TYPE) - pedwarn (loc, 0, + pedwarn (loc, 0, "% with a value, in function returning void"); - else + else pedwarn (loc, OPT_pedantic, "ISO C forbids " "% with expression, in function returning void"); } @@ -8522,6 +9181,8 @@ emit_side_effect_warnings (location_t loc, tree expr) tree c_process_expr_stmt (location_t loc, tree expr) { + tree exprv; + if (!expr) return NULL_TREE; @@ -8542,6 +9203,16 @@ c_process_expr_stmt (location_t loc, tree expr) && warn_unused_value) emit_side_effect_warnings (loc, expr); + exprv = expr; + while (TREE_CODE (exprv) == COMPOUND_EXPR) + exprv = TREE_OPERAND (exprv, 1); + while (CONVERT_EXPR_P (exprv)) + exprv = TREE_OPERAND (exprv, 0); + if (DECL_P (exprv) + || handled_component_p (exprv) + || TREE_CODE (exprv) == ADDR_EXPR) + 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)) @@ -8647,16 +9318,17 @@ c_finish_stmt_expr (location_t loc, tree body) goto continue_searching; } + if (last == error_mark_node) + return last; + /* In the case that the BIND_EXPR is not necessary, return the expression out from inside it. */ - if (last == error_mark_node - || (last == BIND_EXPR_BODY (body) - && BIND_EXPR_VARS (body) == NULL)) + if (last == BIND_EXPR_BODY (body) + && BIND_EXPR_VARS (body) == NULL) { /* Even if this looks constant, do not allow it in a constant expression. */ - last = build2 (C_MAYBE_CONST_EXPR, TREE_TYPE (last), NULL_TREE, last); - C_MAYBE_CONST_EXPR_NON_CONST (last) = 1; + last = c_wrap_maybe_const (last, true); /* Do not warn if the return value of a statement expression is unused. */ TREE_NO_WARNING (last) = 1; @@ -8729,7 +9401,7 @@ c_end_compound_stmt (location_t loc, tree stmt, bool do_scope) do the wrong thing for ({ { 1; } }) or ({ 1; { } }). In particular, STATEMENT_LISTs merge, and thus we can lose track of what statement was really last. */ - if (cur_stmt_list + if (building_stmt_list_p () && STATEMENT_LIST_STMT_EXPR (cur_stmt_list) && TREE_CODE (stmt) != BIND_EXPR) { @@ -8760,6 +9432,88 @@ push_cleanup (tree decl, tree cleanup, bool eh_only) TREE_OPERAND (stmt, 0) = list; STATEMENT_LIST_STMT_EXPR (list) = stmt_expr; } + +/* Convert scalar to vector for the range of operations. */ +static enum stv_conv +scalar_to_vector (location_t loc, enum tree_code code, tree op0, tree op1) +{ + tree type0 = TREE_TYPE (op0); + tree type1 = TREE_TYPE (op1); + bool integer_only_op = false; + enum stv_conv ret = stv_firstarg; + + gcc_assert (TREE_CODE (type0) == VECTOR_TYPE + || TREE_CODE (type1) == VECTOR_TYPE); + switch (code) + { + case RSHIFT_EXPR: + case LSHIFT_EXPR: + if (TREE_CODE (type0) == INTEGER_TYPE + && TREE_CODE (TREE_TYPE (type1)) == INTEGER_TYPE) + { + if (unsafe_conversion_p (TREE_TYPE (type1), op0, false)) + { + error_at (loc, "conversion of scalar to vector " + "involves truncation"); + return stv_error; + } + else + return stv_firstarg; + } + break; + + case BIT_IOR_EXPR: + case BIT_XOR_EXPR: + case BIT_AND_EXPR: + integer_only_op = true; + /* ... fall through ... */ + + case PLUS_EXPR: + case MINUS_EXPR: + case MULT_EXPR: + case TRUNC_DIV_EXPR: + case TRUNC_MOD_EXPR: + case RDIV_EXPR: + if (TREE_CODE (type0) == VECTOR_TYPE) + { + tree tmp; + ret = stv_secondarg; + /* Swap TYPE0 with TYPE1 and OP0 with OP1 */ + tmp = type0; type0 = type1; type1 = tmp; + tmp = op0; op0 = op1; op1 = tmp; + } + + if (TREE_CODE (type0) == INTEGER_TYPE + && TREE_CODE (TREE_TYPE (type1)) == INTEGER_TYPE) + { + if (unsafe_conversion_p (TREE_TYPE (type1), op0, false)) + { + error_at (loc, "conversion of scalar to vector " + "involves truncation"); + return stv_error; + } + return ret; + } + else if (!integer_only_op + /* Allow integer --> real conversion if safe. */ + && (TREE_CODE (type0) == REAL_TYPE + || TREE_CODE (type0) == INTEGER_TYPE) + && SCALAR_FLOAT_TYPE_P (TREE_TYPE (type1))) + { + if (unsafe_conversion_p (TREE_TYPE (type1), op0, false)) + { + error_at (loc, "conversion of scalar to vector " + "involves truncation"); + return stv_error; + } + return ret; + } + default: + break; + } + + return stv_nothing; +} /* Build a binary-operation expression without default conversions. CODE is the kind of expression to build. @@ -8801,7 +9555,7 @@ build_binary_op (location_t location, enum tree_code code, /* 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. @@ -8843,6 +9597,10 @@ build_binary_op (location_t location, enum tree_code code, 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; @@ -8867,7 +9625,10 @@ build_binary_op (location_t location, enum tree_code code, else int_const = int_const_or_overflow = false; - if (convert_p) + /* Do not apply default conversion in mixed vector/scalar expression. */ + if (convert_p + && !((TREE_CODE (TREE_TYPE (op0)) == VECTOR_TYPE) + != (TREE_CODE (TREE_TYPE (op1)) == VECTOR_TYPE))) { op0 = default_conversion (op0); op1 = default_conversion (op1); @@ -8939,6 +9700,51 @@ build_binary_op (location_t location, enum tree_code code, objc_ok = objc_compare_types (type0, type1, -3, NULL_TREE); + /* In case when one of the operands of the binary operation is + a vector and another is a scalar -- convert scalar to vector. */ + if ((code0 == VECTOR_TYPE) != (code1 == VECTOR_TYPE)) + { + enum stv_conv convert_flag = scalar_to_vector (location, code, op0, op1); + + switch (convert_flag) + { + case stv_error: + return error_mark_node; + case stv_firstarg: + { + bool maybe_const = true; + tree sc; + sc = c_fully_fold (op0, false, &maybe_const); + sc = save_expr (sc); + sc = convert (TREE_TYPE (type1), sc); + op0 = build_vector_from_val (type1, sc); + if (!maybe_const) + op0 = c_wrap_maybe_const (op0, true); + orig_type0 = type0 = TREE_TYPE (op0); + code0 = TREE_CODE (type0); + converted = 1; + break; + } + case stv_secondarg: + { + bool maybe_const = true; + tree sc; + sc = c_fully_fold (op1, false, &maybe_const); + sc = save_expr (sc); + sc = convert (TREE_TYPE (type0), sc); + op1 = build_vector_from_val (type0, sc); + if (!maybe_const) + op0 = c_wrap_maybe_const (op1, true); + orig_type1 = type1 = TREE_TYPE (op1); + code1 = TREE_CODE (type1); + converted = 1; + break; + } + default: + break; + } + } + switch (code) { case PLUS_EXPR: @@ -9070,6 +9876,7 @@ build_binary_op (location_t location, enum tree_code code, op0 = c_common_truthvalue_conversion (location, op0); op1 = c_common_truthvalue_conversion (location, op1); converted = 1; + boolean_op = true; } if (code == TRUTH_ANDIF_EXPR) { @@ -9100,7 +9907,21 @@ build_binary_op (location_t location, enum tree_code code, Also set SHORT_SHIFT if shifting rightward. */ case RSHIFT_EXPR: - if ((code0 == INTEGER_TYPE || code0 == FIXED_POINT_TYPE) + if (code0 == VECTOR_TYPE && code1 == INTEGER_TYPE + && TREE_CODE (TREE_TYPE (type0)) == INTEGER_TYPE) + { + result_type = type0; + 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) @@ -9127,9 +9948,10 @@ build_binary_op (location_t location, enum tree_code code, /* 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) + /* 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; @@ -9137,7 +9959,21 @@ build_binary_op (location_t location, enum tree_code code, break; case LSHIFT_EXPR: - if ((code0 == INTEGER_TYPE || code0 == FIXED_POINT_TYPE) + if (code0 == VECTOR_TYPE && code1 == INTEGER_TYPE + && TREE_CODE (TREE_TYPE (type0)) == INTEGER_TYPE) + { + result_type = type0; + 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) @@ -9159,9 +9995,10 @@ build_binary_op (location_t location, enum tree_code code, /* 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) + /* 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; @@ -9170,6 +10007,31 @@ build_binary_op (location_t location, enum tree_code code, case EQ_EXPR: case NE_EXPR: + if (code0 == VECTOR_TYPE && code1 == VECTOR_TYPE) + { + tree intt; + if (TREE_TYPE (type0) != TREE_TYPE (type1)) + { + error_at (location, "comparing vectors with different " + "element types"); + return error_mark_node; + } + + if (TYPE_VECTOR_SUBPARTS (type0) != TYPE_VECTOR_SUBPARTS (type1)) + { + error_at (location, "comparing vectors with different " + "number of elements"); + return error_mark_node; + } + + /* Always construct signed integer vector type. */ + intt = c_common_type_for_size (GET_MODE_BITSIZE + (TYPE_MODE (TREE_TYPE (type0))), 0); + result_type = build_opaque_vector_type (intt, + TYPE_VECTOR_SUBPARTS (type0)); + converted = 1; + break; + } if (FLOAT_TYPE_P (type0) || FLOAT_TYPE_P (type1)) warning_at (location, OPT_Wfloat_equal, @@ -9182,28 +10044,74 @@ build_binary_op (location_t location, enum tree_code code, && (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 % " + "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 % " + "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 % " + "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 % " + "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 (!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)) { - /* op0 != orig_op0 detects the case of something - whose value is 0 but which isn't a valid null ptr const. */ - if (pedantic && !null_pointer_constant_p (orig_op0) - && TREE_CODE (tt1) == FUNCTION_TYPE) + if (pedantic && TREE_CODE (tt1) == FUNCTION_TYPE) pedwarn (location, OPT_pedantic, "ISO C forbids " "comparison of % with function pointer"); } else if (VOID_TYPE_P (tt1)) { - if (pedantic && !null_pointer_constant_p (orig_op1) - && TREE_CODE (tt0) == FUNCTION_TYPE) + if (pedantic && TREE_CODE (tt0) == FUNCTION_TYPE) pedwarn (location, OPT_pedantic, "ISO C forbids " "comparison of % with function pointer"); } @@ -9214,25 +10122,11 @@ build_binary_op (location_t location, enum tree_code code, "comparison of distinct pointer types lacks a cast"); if (result_type == NULL_TREE) - result_type = ptr_type_node; - } - 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; + { + 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) { @@ -9250,6 +10144,31 @@ build_binary_op (location_t location, enum tree_code code, case GE_EXPR: case LT_EXPR: case GT_EXPR: + if (code0 == VECTOR_TYPE && code1 == VECTOR_TYPE) + { + tree intt; + if (TREE_TYPE (type0) != TREE_TYPE (type1)) + { + error_at (location, "comparing vectors with different " + "element types"); + return error_mark_node; + } + + if (TYPE_VECTOR_SUBPARTS (type0) != TYPE_VECTOR_SUBPARTS (type1)) + { + error_at (location, "comparing vectors with different " + "number of elements"); + return error_mark_node; + } + + /* Always construct signed integer vector type. */ + intt = c_common_type_for_size (GET_MODE_BITSIZE + (TYPE_MODE (TREE_TYPE (type0))), 0); + result_type = build_opaque_vector_type (intt, + TYPE_VECTOR_SUBPARTS (type0)); + converted = 1; + break; + } build_type = integer_type_node; if ((code0 == INTEGER_TYPE || code0 == REAL_TYPE || code0 == FIXED_POINT_TYPE) @@ -9258,6 +10177,10 @@ build_binary_op (location_t location, enum tree_code code, 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); @@ -9268,10 +10191,23 @@ build_binary_op (location_t location, enum tree_code code, 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 { - result_type = ptr_type_node; + 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"); } @@ -9280,17 +10216,21 @@ build_binary_op (location_t location, enum tree_code code, { result_type = type0; if (pedantic) - pedwarn (location, OPT_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"); + "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"); + 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) { @@ -9333,6 +10273,11 @@ build_binary_op (location_t location, enum tree_code code, if (shorten || common || short_compare) { 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; } @@ -9354,7 +10299,7 @@ build_binary_op (location_t location, enum tree_code code, if (type0 != orig_type0 || type1 != orig_type1) { gcc_assert (may_need_excess_precision && common); - real_result_type = c_common_type (orig_type0, orig_type1); + semantic_result_type = c_common_type (orig_type0, orig_type1); } if (first_complex) { @@ -9383,6 +10328,7 @@ build_binary_op (location_t location, enum tree_code code, { case MULT_EXPR: case TRUNC_DIV_EXPR: + op1 = c_save_expr (op1); imag = build2 (resultcode, real_type, imag, op1); /* Fall through. */ case PLUS_EXPR: @@ -9403,6 +10349,7 @@ build_binary_op (location_t location, enum tree_code code, switch (code) { case MULT_EXPR: + op0 = c_save_expr (op0); imag = build2 (resultcode, real_type, op0, imag); /* Fall through. */ case PLUS_EXPR: @@ -9434,7 +10381,7 @@ build_binary_op (location_t location, enum tree_code code, if (shorten && none_complex) { final_type = result_type; - result_type = shorten_binary_op (result_type, op0, op1, + result_type = shorten_binary_op (result_type, op0, op1, shorten == -1); } @@ -9451,6 +10398,7 @@ build_binary_op (location_t location, enum tree_code code, unsigned_arg = TYPE_UNSIGNED (TREE_TYPE (op0)); if (TYPE_PRECISION (TREE_TYPE (arg0)) < TYPE_PRECISION (result_type) + && tree_int_cst_sgn (op1) > 0 /* We can shorten only if the shift count is less than the number of bits in the smaller type size. */ && compare_tree_int (op1, TYPE_PRECISION (TREE_TYPE (arg0))) < 0 @@ -9509,10 +10457,12 @@ build_binary_op (location_t location, enum tree_code code, build_conditional_expr. This requires the "original" values to be folded, not just op0 and op1. */ + c_inhibit_evaluation_warnings++; op0 = c_fully_fold (op0, require_constant_value, &op0_maybe_const); op1 = c_fully_fold (op1, require_constant_value, &op1_maybe_const); + c_inhibit_evaluation_warnings--; orig_op0_folded = c_fully_fold (orig_op0, require_constant_value, NULL); @@ -9525,20 +10475,12 @@ build_binary_op (location_t location, enum tree_code code, warn_for_sign_compare (location, orig_op0_folded, orig_op1_folded, op0, op1, result_type, resultcode); - if (!in_late_binary_op) + if (!in_late_binary_op && !int_operands) { if (!op0_maybe_const || TREE_CODE (op0) != INTEGER_CST) - { - op0 = build2 (C_MAYBE_CONST_EXPR, TREE_TYPE (op0), - NULL, op0); - C_MAYBE_CONST_EXPR_NON_CONST (op0) = !op0_maybe_const; - } + op0 = c_wrap_maybe_const (op0, !op0_maybe_const); if (!op1_maybe_const || TREE_CODE (op1) != INTEGER_CST) - { - op1 = build2 (C_MAYBE_CONST_EXPR, TREE_TYPE (op1), - NULL, op1); - C_MAYBE_CONST_EXPR_NON_CONST (op1) = !op1_maybe_const; - } + op1 = c_wrap_maybe_const (op1, !op1_maybe_const); } } } @@ -9556,12 +10498,21 @@ build_binary_op (location_t location, enum tree_code code, 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. */ @@ -9569,16 +10520,6 @@ build_binary_op (location_t location, enum tree_code code, 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 @@ -9599,8 +10540,8 @@ build_binary_op (location_t location, enum tree_code code, 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; } @@ -9628,9 +10569,17 @@ c_objc_common_truthvalue_conversion (location_t location, tree expr) 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 (); + case VECTOR_TYPE: + error_at (location, "used vector type where scalar is required"); + return error_mark_node; + default: break; } @@ -9640,8 +10589,8 @@ c_objc_common_truthvalue_conversion (location_t location, tree expr) 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) @@ -9795,6 +10744,8 @@ c_finish_omp_clauses (tree clauses) case PLUS_EXPR: case MULT_EXPR: case MINUS_EXPR: + case MIN_EXPR: + case MAX_EXPR: break; case BIT_AND_EXPR: r_name = "&"; @@ -9911,6 +10862,8 @@ c_finish_omp_clauses (tree clauses) case OMP_CLAUSE_DEFAULT: case OMP_CLAUSE_UNTIED: case OMP_CLAUSE_COLLAPSE: + case OMP_CLAUSE_FINAL: + case OMP_CLAUSE_MERGEABLE: pc = &OMP_CLAUSE_CHAIN (c); continue; @@ -9940,6 +10893,10 @@ c_finish_omp_clauses (tree clauses) case OMP_CLAUSE_DEFAULT_UNSPECIFIED: break; case OMP_CLAUSE_DEFAULT_SHARED: + /* const vars may be specified in firstprivate clause. */ + if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE + && TREE_READONLY (t)) + break; share_name = "shared"; break; case OMP_CLAUSE_DEFAULT_PRIVATE: @@ -9968,6 +10925,19 @@ c_finish_omp_clauses (tree clauses) return clauses; } +/* Create a transaction node. */ + +tree +c_finish_transaction (location_t loc, tree block, int flags) +{ + tree stmt = build_stmt (loc, TRANSACTION_EXPR, block); + if (flags & TM_STMT_ATTR_OUTER) + TRANSACTION_EXPR_OUTER (stmt) = 1; + if (flags & TM_STMT_ATTR_RELAXED) + TRANSACTION_EXPR_RELAXED (stmt) = 1; + return add_stmt (stmt); +} + /* Make a variant type in the proper way for C/C++, propagating qualifiers down to the element type of an array. */ @@ -10006,11 +10976,11 @@ c_build_qualified_type (tree type, int type_quals) else if (TYPE_CANONICAL (element_type) != element_type || (domain && TYPE_CANONICAL (domain) != domain)) { - tree unqualified_canon + tree unqualified_canon = build_array_type (TYPE_CANONICAL (element_type), - domain? TYPE_CANONICAL (domain) + domain? TYPE_CANONICAL (domain) : NULL_TREE); - TYPE_CANONICAL (t) + TYPE_CANONICAL (t) = c_build_qualified_type (unqualified_canon, type_quals); } else