Mercurial > hg > CbC > CbC_gcc
diff gcc/c-typeck.c @ 67:f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
author | nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp> |
---|---|
date | Tue, 22 Mar 2011 17:18:12 +0900 |
parents | b7f97abdc517 |
children | 1b10fe6932e1 |
line wrap: on
line diff
--- a/gcc/c-typeck.c Tue May 25 18:58:51 2010 +0900 +++ b/gcc/c-typeck.c Tue Mar 22 17:18:12 2011 +0900 @@ -1,6 +1,6 @@ /* Build expressions with type checking for C compiler. Copyright (C) 1987, 1988, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, - 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 + 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. This file is part of GCC. @@ -35,12 +35,12 @@ #include "c-lang.h" #include "flags.h" #include "output.h" -#include "expr.h" -#include "toplev.h" #include "intl.h" #include "target.h" #include "tree-iterator.h" -#include "tree-flow.h" +#include "bitmap.h" +#include "gimple.h" +#include "c-family/c-objc.h" /* Possible cases of implicit bad conversions. Used to select diagnostic messages in convert_for_assignment. */ @@ -51,13 +51,6 @@ ic_return }; -/* Whether we are building a boolean conversion inside - convert_for_assignment, or some other late binary operation. If - build_binary_op is called (from code shared with C++) in this case, - then the operands have already been folded and the result will not - be folded again, so C_MAYBE_CONST_EXPR should not be generated. */ -bool in_late_binary_op; - /* The level of nesting inside "__alignof__". */ int in_alignof; @@ -76,10 +69,12 @@ static bool null_pointer_constant_p (const_tree); static tree qualify_type (tree, tree); -static int tagged_types_tu_compatible_p (const_tree, const_tree, bool *); +static int tagged_types_tu_compatible_p (const_tree, const_tree, bool *, + bool *); static int comp_target_types (location_t, tree, tree); -static int function_types_compatible_p (const_tree, const_tree, bool *); -static int type_lists_compatible_p (const_tree, const_tree, bool *); +static int function_types_compatible_p (const_tree, const_tree, bool *, + bool *); +static int type_lists_compatible_p (const_tree, const_tree, bool *, bool *); static tree lookup_field (tree, tree); static int convert_arguments (tree, VEC(tree,gc) *, VEC(tree,gc) *, tree, tree); @@ -102,11 +97,10 @@ 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_error (tree, enum lvalue_use); 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. */ @@ -553,7 +547,7 @@ && 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 @@ -578,7 +572,7 @@ && 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 @@ -972,7 +966,7 @@ const struct tagged_tu_seen_cache * tagged_tu_seen_base1 = tagged_tu_seen_base; int val; - val = comptypes_internal (type1, type2, NULL); + val = comptypes_internal (type1, type2, NULL, NULL); free_all_tagged_tu_seen_up_to (tagged_tu_seen_base1); return val; @@ -987,7 +981,23 @@ const struct tagged_tu_seen_cache * tagged_tu_seen_base1 = tagged_tu_seen_base; int val; - val = comptypes_internal (type1, type2, enum_and_int_p); + val = comptypes_internal (type1, type2, enum_and_int_p, NULL); + free_all_tagged_tu_seen_up_to (tagged_tu_seen_base1); + + return val; +} + +/* Like comptypes, but if it returns nonzero for different types, it + sets *DIFFERENT_TYPES_P to true. */ + +int +comptypes_check_different_types (tree type1, tree type2, + bool *different_types_p) +{ + const struct tagged_tu_seen_cache * tagged_tu_seen_base1 = tagged_tu_seen_base; + int val; + + val = comptypes_internal (type1, type2, NULL, different_types_p); free_all_tagged_tu_seen_up_to (tagged_tu_seen_base1); return val; @@ -998,11 +1008,17 @@ but a warning may be needed if you use them together. If ENUM_AND_INT_P is not NULL, and one type is an enum and the other a compatible integer type, then this sets *ENUM_AND_INT_P to true; - *ENUM_AND_INT_P is never set to false. This differs from - comptypes, in that we don't free the seen types. */ + *ENUM_AND_INT_P is never set to false. If DIFFERENT_TYPES_P is not + NULL, and the types are compatible but different enough not to be + permitted in C1X typedef redeclarations, then this sets + *DIFFERENT_TYPES_P to true; *DIFFERENT_TYPES_P is never set to + false, but may or may not be set if the types are incompatible. + This differs from comptypes, in that we don't free the seen + types. */ static int -comptypes_internal (const_tree type1, const_tree type2, bool *enum_and_int_p) +comptypes_internal (const_tree type1, const_tree type2, bool *enum_and_int_p, + bool *different_types_p) { const_tree t1 = type1; const_tree t2 = type2; @@ -1014,17 +1030,6 @@ || TREE_CODE (t1) == ERROR_MARK || TREE_CODE (t2) == ERROR_MARK) return 1; - /* If either type is the internal version of sizetype, return the - language version. */ - if (TREE_CODE (t1) == INTEGER_TYPE && TYPE_IS_SIZETYPE (t1) - && TYPE_ORIG_SIZE_TYPE (t1)) - t1 = TYPE_ORIG_SIZE_TYPE (t1); - - if (TREE_CODE (t2) == INTEGER_TYPE && TYPE_IS_SIZETYPE (t2) - && TYPE_ORIG_SIZE_TYPE (t2)) - t2 = TYPE_ORIG_SIZE_TYPE (t2); - - /* Enumerated types are compatible with integer types, but this is not transitive: two enumerated types in the same translation unit are compatible with each other only if they are the same type. */ @@ -1032,14 +1037,24 @@ if (TREE_CODE (t1) == ENUMERAL_TYPE && TREE_CODE (t2) != ENUMERAL_TYPE) { t1 = c_common_type_for_size (TYPE_PRECISION (t1), TYPE_UNSIGNED (t1)); - if (enum_and_int_p != NULL && TREE_CODE (t2) != VOID_TYPE) - *enum_and_int_p = true; + if (TREE_CODE (t2) != VOID_TYPE) + { + if (enum_and_int_p != NULL) + *enum_and_int_p = true; + if (different_types_p != NULL) + *different_types_p = true; + } } else if (TREE_CODE (t2) == ENUMERAL_TYPE && TREE_CODE (t1) != ENUMERAL_TYPE) { t2 = c_common_type_for_size (TYPE_PRECISION (t2), TYPE_UNSIGNED (t2)); - if (enum_and_int_p != NULL && TREE_CODE (t1) != VOID_TYPE) - *enum_and_int_p = true; + if (TREE_CODE (t1) != VOID_TYPE) + { + if (enum_and_int_p != NULL) + *enum_and_int_p = true; + if (different_types_p != NULL) + *different_types_p = true; + } } if (t1 == t2) @@ -1079,11 +1094,12 @@ 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: @@ -1097,9 +1113,13 @@ /* 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; @@ -1116,6 +1136,9 @@ 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) @@ -1141,15 +1164,17 @@ 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: @@ -1281,11 +1306,12 @@ compatible. If the two types are not the same (which has been checked earlier), this can only happen when multiple translation units are being compiled. See C99 6.2.7 paragraph 1 for the exact - rules. ENUM_AND_INT_P is as in comptypes_internal. */ + rules. ENUM_AND_INT_P and DIFFERENT_TYPES_P are as in + comptypes_internal. */ static int tagged_types_tu_compatible_p (const_tree t1, const_tree t2, - bool *enum_and_int_p) + bool *enum_and_int_p, bool *different_types_p) { tree s1, s2; bool needs_warning = false; @@ -1389,14 +1415,14 @@ /* 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; @@ -1422,17 +1448,18 @@ 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; @@ -1468,14 +1495,14 @@ 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) @@ -1504,11 +1531,11 @@ Otherwise, if one type specifies only the number of arguments, the other must specify that number of self-promoting arg types. Otherwise, the argument types must match. - ENUM_AND_INT_P is as in comptypes_internal. */ + ENUM_AND_INT_P and DIFFERENT_TYPES_P are as in comptypes_internal. */ static int function_types_compatible_p (const_tree f1, const_tree f2, - bool *enum_and_int_p) + bool *enum_and_int_p, bool *different_types_p) { tree args1, args2; /* 1 if no need for warning yet, 2 if warning cause has been seen. */ @@ -1529,13 +1556,17 @@ 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. */ @@ -1548,7 +1579,7 @@ 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; } @@ -1558,23 +1589,25 @@ 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; @@ -1599,6 +1632,9 @@ 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) @@ -1613,8 +1649,11 @@ 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 @@ -1626,13 +1665,14 @@ { 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) @@ -1647,13 +1687,14 @@ { 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) @@ -1782,6 +1823,7 @@ 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: @@ -1994,6 +2036,17 @@ 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; } } @@ -2020,7 +2073,7 @@ } 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 @@ -2030,6 +2083,16 @@ 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) @@ -2059,6 +2122,11 @@ if (!objc_is_public (datum, component)) return error_mark_node; + /* Detect Objective-C property syntax object.property. */ + if (c_dialect_objc () + && (ref = objc_maybe_build_component_ref (datum, component))) + return ref; + /* See if there is a field or component with name COMPONENT. */ if (code == RECORD_TYPE || code == UNION_TYPE) @@ -2198,26 +2266,8 @@ } } else if (TREE_CODE (pointer) != ERROR_MARK) - switch (errstring) - { - case RO_ARRAY_INDEXING: - error_at (loc, - "invalid type argument of array indexing (have %qT)", - type); - break; - case RO_UNARY_STAR: - error_at (loc, - "invalid type argument of unary %<*%> (have %qT)", - type); - break; - case RO_ARROW: - error_at (loc, - "invalid type argument of %<->%> (have %qT)", - type); - break; - default: - gcc_unreachable (); - } + invalid_indirection_error (loc, type, errstring); + return error_mark_node; } @@ -2230,6 +2280,9 @@ arrays that are not lvalues (for example, members of structures returned by functions). + For vector types, allow vector[i] but not i[vector], and create + *(((type*)&vectortype) + i) for the expression. + LOC is the location to use for the returned expression. */ tree @@ -2242,13 +2295,17 @@ 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; @@ -2278,6 +2335,27 @@ index = default_conversion (index); gcc_assert (TREE_CODE (TREE_TYPE (index)) == INTEGER_TYPE); + + /* For vector[index], convert the vector to a + pointer of the underlying type. */ + if (TREE_CODE (TREE_TYPE (array)) == VECTOR_TYPE) + { + tree type = TREE_TYPE (array); + tree type1; + + if (TREE_CODE (index) == INTEGER_CST) + if (!host_integerp (index, 1) + || ((unsigned HOST_WIDE_INT) tree_low_cst (index, 1) + >= TYPE_VECTOR_SUBPARTS (TREE_TYPE (array)))) + warning_at (loc, OPT_Warray_bounds, "index value is out of bound"); + + c_common_mark_addressable_vec (array); + type = build_qualified_type (TREE_TYPE (type), TYPE_QUALS (type)); + type = build_pointer_type (type); + type1 = build_pointer_type (TREE_TYPE (array)); + array = build1 (ADDR_EXPR, type1, array); + array = convert (type, array); + } if (TREE_CODE (TREE_TYPE (array)) == ARRAY_TYPE) { @@ -2717,7 +2795,7 @@ 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)); @@ -2847,8 +2925,13 @@ if (type == void_type_node) { - error_at (input_location, - "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; @@ -3045,8 +3128,15 @@ 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 @@ -3445,26 +3535,10 @@ goto return_build_unary_op; case REALPART_EXPR: - if (TREE_CODE (arg) == COMPLEX_CST) - ret = TREE_REALPART (arg); - else if (TREE_CODE (TREE_TYPE (arg)) == COMPLEX_TYPE) - ret = fold_build1_loc (location, - REALPART_EXPR, TREE_TYPE (TREE_TYPE (arg)), arg); - else - ret = arg; - if (eptype && TREE_CODE (eptype) == COMPLEX_TYPE) - eptype = TREE_TYPE (eptype); - goto return_build_unary_op; - case IMAGPART_EXPR: - if (TREE_CODE (arg) == COMPLEX_CST) - ret = TREE_IMAGPART (arg); - else if (TREE_CODE (TREE_TYPE (arg)) == COMPLEX_TYPE) - ret = fold_build1_loc (location, - IMAGPART_EXPR, TREE_TYPE (TREE_TYPE (arg)), arg); - else - ret = omit_one_operand_loc (location, TREE_TYPE (arg), - integer_zero_node, arg); + ret = build_real_imag_expr (location, code, arg); + if (ret == error_mark_node) + return error_mark_node; if (eptype && TREE_CODE (eptype) == COMPLEX_TYPE) eptype = TREE_TYPE (eptype); goto return_build_unary_op; @@ -3487,11 +3561,14 @@ 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) @@ -3599,6 +3676,13 @@ 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)) { @@ -3664,7 +3748,7 @@ /* 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 @@ -3685,14 +3769,24 @@ argtype = TREE_TYPE (arg); /* If the lvalue is const or volatile, merge that into the type - to which the address will point. Note that you can't get a - restricted pointer by taking the address of something, so we - only have to deal with `const' and `volatile' here. */ + to which the address will point. This should only be needed + for function types. */ if ((DECL_P (arg) || REFERENCE_CLASS_P (arg)) && (TREE_READONLY (arg) || TREE_THIS_VOLATILE (arg))) - argtype = c_build_type_variant (argtype, - TREE_READONLY (arg), - TREE_THIS_VOLATILE (arg)); + { + int orig_quals = TYPE_QUALS (strip_array_types (argtype)); + int quals = orig_quals; + + if (TREE_READONLY (arg)) + quals |= TYPE_QUAL_CONST; + if (TREE_THIS_VOLATILE (arg)) + quals |= TYPE_QUAL_VOLATILE; + + gcc_assert (quals == orig_quals + || TREE_CODE (argtype) == FUNCTION_TYPE); + + argtype = c_build_qualified_type (argtype, quals); + } if (!c_mark_addressable (arg)) return error_mark_node; @@ -3786,44 +3880,6 @@ } } -/* Give an error for storing in something that is 'const'. */ - -static void -readonly_error (tree arg, enum lvalue_use use) -{ - gcc_assert (use == lv_assign || use == lv_increment || use == lv_decrement - || use == lv_asm); - /* Using this macro rather than (for example) arrays of messages - ensures that all the format strings are checked at compile - time. */ -#define READONLY_MSG(A, I, D, AS) (use == lv_assign ? (A) \ - : (use == lv_increment ? (I) \ - : (use == lv_decrement ? (D) : (AS)))) - if (TREE_CODE (arg) == COMPONENT_REF) - { - if (TYPE_READONLY (TREE_TYPE (TREE_OPERAND (arg, 0)))) - readonly_error (TREE_OPERAND (arg, 0), use); - else - error (READONLY_MSG (G_("assignment of read-only member %qD"), - G_("increment of read-only member %qD"), - G_("decrement of read-only member %qD"), - G_("read-only member %qD used as %<asm%> output")), - TREE_OPERAND (arg, 1)); - } - else if (TREE_CODE (arg) == VAR_DECL) - error (READONLY_MSG (G_("assignment of read-only variable %qD"), - G_("increment of read-only variable %qD"), - G_("decrement of read-only variable %qD"), - G_("read-only variable %qD used as %<asm%> output")), - arg); - else - error (READONLY_MSG (G_("assignment of read-only location %qE"), - G_("increment of read-only location %qE"), - G_("decrement of read-only location %qE"), - G_("read-only location %qE used as %<asm%> output")), - arg); -} - /* Give a warning for storing in something that is read-only in GCC terms but not const in ISO C terms. */ @@ -3850,15 +3906,16 @@ /* Return nonzero if REF is an lvalue valid for this language; otherwise, print an error message and return zero. USE says - how the lvalue is being used and so selects the error message. */ + how the lvalue is being used and so selects the error message. + LOCATION is the location at which any error should be reported. */ static int -lvalue_or_else (const_tree ref, enum lvalue_use use) +lvalue_or_else (location_t loc, const_tree ref, enum lvalue_use use) { int win = lvalue_p (ref); if (!win) - lvalue_error (use); + lvalue_error (loc, use); return win; } @@ -3979,7 +4036,6 @@ 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) @@ -4016,8 +4072,6 @@ return error_mark_node; } - objc_ok = objc_compare_types (type1, type2, -3, NULL_TREE); - if ((TREE_CODE (op1) == EXCESS_PRECISION_EXPR || TREE_CODE (op2) == EXCESS_PRECISION_EXPR) && (code1 == INTEGER_TYPE || code1 == REAL_TYPE @@ -4069,6 +4123,10 @@ || code2 == COMPLEX_TYPE)) { result_type = c_common_type (type1, type2); + do_warn_double_promotion (result_type, type1, type2, + "implicit conversion from %qT to %qT to " + "match other result of conditional", + colon_loc); /* If -Wsign-compare, warn here if type1 and type2 have different signedness. We'll promote the signed to unsigned @@ -4179,13 +4237,15 @@ result_type = build_pointer_type (qualify_type (TREE_TYPE (type2), TREE_TYPE (type1))); } + /* Objective-C pointer comparisons are a bit more lenient. */ + else if (objc_have_common_type (type1, type2, -3, NULL_TREE)) + result_type = objc_common_type (type1, type2); else { int qual = ENCODE_QUAL_ADDR_SPACE (as_common); - if (!objc_ok) - pedwarn (colon_loc, 0, - "pointer type mismatch in conditional expression"); + pedwarn (colon_loc, 0, + "pointer type mismatch in conditional expression"); result_type = build_pointer_type (build_qualified_type (void_type_node, qual)); } @@ -4343,12 +4403,13 @@ /* Issue -Wcast-qual warnings when appropriate. TYPE is the type to which we are casting. OTYPE is the type of the expression being - cast. Both TYPE and OTYPE are pointer types. -Wcast-qual appeared - on the command line. Named address space qualifiers are not handled - here, because they result in different warnings. */ + cast. Both TYPE and OTYPE are pointer types. LOC is the location + of the cast. -Wcast-qual appeared on the command line. Named + address space qualifiers are not handled here, because they result + in different warnings. */ static void -handle_warn_cast_qual (tree type, tree otype) +handle_warn_cast_qual (location_t loc, tree type, tree otype) { tree in_type = type; tree in_otype = otype; @@ -4381,13 +4442,15 @@ && TREE_CODE (in_otype) == POINTER_TYPE); if (added) - warning (OPT_Wcast_qual, "cast adds new qualifiers to function type"); + warning_at (loc, OPT_Wcast_qual, + "cast adds %q#v qualifier to function type", added); if (discarded) /* There are qualifiers present in IN_OTYPE that are not present in IN_TYPE. */ - warning (OPT_Wcast_qual, - "cast discards qualifiers from pointer target type"); + warning_at (loc, OPT_Wcast_qual, + "cast discards %q#v qualifier from pointer target type", + discarded); if (added || discarded) return; @@ -4420,9 +4483,10 @@ 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 %<const%> qualified", + otype, type); break; } if (is_const) @@ -4485,7 +4549,7 @@ { 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)))) @@ -4526,7 +4590,7 @@ 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. */ @@ -4698,8 +4762,9 @@ if (CAN_HAVE_LOCATION_P (ret) && !EXPR_HAS_LOCATION (ret)) SET_EXPR_LOCATION (ret, loc); - /* C++ does not permits types to be defined in a cast. */ - if (warn_cxx_compat && type_name->specs->tag_defined_p) + /* C++ does not permits types to be defined in a cast, but it + allows references to incomplete types. */ + if (warn_cxx_compat && type_name->specs->typespec_kind == ctsk_tagdef) warning_at (loc, OPT_Wc___compat, "defining a type in a cast is invalid in C++"); @@ -4737,7 +4802,8 @@ if (TREE_CODE (lhs) == ERROR_MARK || TREE_CODE (rhs) == ERROR_MARK) return error_mark_node; - if (!lvalue_or_else (lhs, lv_assign)) + /* For ObjC properties, defer this check. */ + if (!objc_is_property_ref (lhs) && !lvalue_or_else (location, lhs, lv_assign)) return error_mark_node; if (TREE_CODE (rhs) == EXCESS_PRECISION_EXPR) @@ -4778,6 +4844,19 @@ rhs_origtype = NULL_TREE; } + if (c_dialect_objc ()) + { + /* Check if we are modifying an Objective-C property reference; + if so, we need to generate setter calls. */ + result = objc_maybe_build_modify_expr (lhs, newrhs); + if (result) + return result; + + /* Else, do the check that we postponed for Objective-C. */ + if (!lvalue_or_else (location, lhs, lv_assign)) + return error_mark_node; + } + /* Give an error for storing in something that is 'const'. */ if (TYPE_READONLY (lhstype) @@ -4873,6 +4952,106 @@ return result; } +/* Return whether STRUCT_TYPE has an anonymous field with type TYPE. + This is used to implement -fplan9-extensions. */ + +static bool +find_anonymous_field_with_type (tree struct_type, tree type) +{ + tree field; + bool found; + + gcc_assert (TREE_CODE (struct_type) == RECORD_TYPE + || TREE_CODE (struct_type) == UNION_TYPE); + found = false; + for (field = TYPE_FIELDS (struct_type); + field != NULL_TREE; + field = TREE_CHAIN (field)) + { + if (DECL_NAME (field) == NULL + && comptypes (type, TYPE_MAIN_VARIANT (TREE_TYPE (field)))) + { + if (found) + return false; + found = true; + } + else if (DECL_NAME (field) == NULL + && (TREE_CODE (TREE_TYPE (field)) == RECORD_TYPE + || TREE_CODE (TREE_TYPE (field)) == UNION_TYPE) + && find_anonymous_field_with_type (TREE_TYPE (field), type)) + { + if (found) + return false; + found = true; + } + } + return found; +} + +/* RHS is an expression whose type is pointer to struct. If there is + an anonymous field in RHS with type TYPE, then return a pointer to + that field in RHS. This is used with -fplan9-extensions. This + returns NULL if no conversion could be found. */ + +static tree +convert_to_anonymous_field (location_t location, tree type, tree rhs) +{ + tree rhs_struct_type, lhs_main_type; + tree field, found_field; + bool found_sub_field; + tree ret; + + gcc_assert (POINTER_TYPE_P (TREE_TYPE (rhs))); + rhs_struct_type = TREE_TYPE (TREE_TYPE (rhs)); + gcc_assert (TREE_CODE (rhs_struct_type) == RECORD_TYPE + || TREE_CODE (rhs_struct_type) == UNION_TYPE); + + gcc_assert (POINTER_TYPE_P (type)); + lhs_main_type = TYPE_MAIN_VARIANT (TREE_TYPE (type)); + + found_field = NULL_TREE; + found_sub_field = false; + for (field = TYPE_FIELDS (rhs_struct_type); + field != NULL_TREE; + field = TREE_CHAIN (field)) + { + if (DECL_NAME (field) != NULL_TREE + || (TREE_CODE (TREE_TYPE (field)) != RECORD_TYPE + && TREE_CODE (TREE_TYPE (field)) != UNION_TYPE)) + continue; + if (comptypes (lhs_main_type, TYPE_MAIN_VARIANT (TREE_TYPE (field)))) + { + if (found_field != NULL_TREE) + return NULL_TREE; + found_field = field; + } + else if (find_anonymous_field_with_type (TREE_TYPE (field), + lhs_main_type)) + { + if (found_field != NULL_TREE) + return NULL_TREE; + found_field = field; + found_sub_field = true; + } + } + + if (found_field == NULL_TREE) + return NULL_TREE; + + ret = fold_build3_loc (location, COMPONENT_REF, TREE_TYPE (found_field), + build_fold_indirect_ref (rhs), found_field, + NULL_TREE); + ret = build_fold_addr_expr_loc (location, ret); + + if (found_sub_field) + { + ret = convert_to_anonymous_field (location, type, ret); + gcc_assert (ret != NULL_TREE); + } + + return ret; +} + /* Convert value RHS to type TYPE as preparation for an assignment to an lvalue of type TYPE. If ORIGTYPE is not NULL_TREE, it is the original type of RHS; this differs from TREE_TYPE (RHS) for enum @@ -4938,7 +5117,7 @@ pedwarn (LOCATION, OPT, AS); \ break; \ case ic_init: \ - pedwarn (LOCATION, OPT, IN); \ + pedwarn_init (LOCATION, OPT, IN); \ break; \ case ic_return: \ pedwarn (LOCATION, OPT, RE); \ @@ -4948,6 +5127,36 @@ } \ } while (0) + /* This macro is used to emit diagnostics to ensure that all format + strings are complete sentences, visible to gettext and checked at + compile time. It is the same as WARN_FOR_ASSIGNMENT but with an + extra parameter to enumerate qualifiers. */ + +#define WARN_FOR_QUALIFIERS(LOCATION, OPT, AR, AS, IN, RE, QUALS) \ + do { \ + switch (errtype) \ + { \ + case ic_argpass: \ + if (pedwarn (LOCATION, OPT, AR, parmnum, rname, QUALS)) \ + inform ((fundecl && !DECL_IS_BUILTIN (fundecl)) \ + ? DECL_SOURCE_LOCATION (fundecl) : LOCATION, \ + "expected %qT but argument is of type %qT", \ + type, rhstype); \ + break; \ + case ic_assign: \ + pedwarn (LOCATION, OPT, AS, QUALS); \ + break; \ + case ic_init: \ + pedwarn (LOCATION, OPT, IN, QUALS); \ + break; \ + case ic_return: \ + pedwarn (LOCATION, OPT, RE, QUALS); \ + break; \ + default: \ + gcc_unreachable (); \ + } \ + } while (0) + if (TREE_CODE (rhs) == EXCESS_PRECISION_EXPR) rhs = TREE_OPERAND (rhs, 0); @@ -5065,10 +5274,10 @@ { 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; } @@ -5087,7 +5296,7 @@ { 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); @@ -5155,30 +5364,32 @@ vice-versa. */ if (TYPE_QUALS_NO_ADDR_SPACE (ttl) & ~TYPE_QUALS_NO_ADDR_SPACE (ttr)) - WARN_FOR_ASSIGNMENT (location, 0, + 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_NO_ADDR_SPACE (ttr) & ~TYPE_QUALS_NO_ADDR_SPACE (ttl)) - WARN_FOR_ASSIGNMENT (location, 0, + 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; } @@ -5212,6 +5423,25 @@ /* Opaque pointers are treated like void pointers. */ is_opaque_pointer = vector_targets_convertible_p (ttl, ttr); + /* The Plan 9 compiler permits a pointer to a struct to be + automatically converted into a pointer to an anonymous field + within the struct. */ + if (flag_plan9_extensions + && (TREE_CODE (mvl) == RECORD_TYPE || TREE_CODE(mvl) == UNION_TYPE) + && (TREE_CODE (mvr) == RECORD_TYPE || TREE_CODE(mvr) == UNION_TYPE) + && mvl != mvr) + { + tree new_rhs = convert_to_anonymous_field (location, type, rhs); + if (new_rhs != NULL_TREE) + { + rhs = new_rhs; + rhstype = TREE_TYPE (rhs); + coder = TREE_CODE (rhstype); + ttr = TREE_TYPE (rhstype); + mvr = TYPE_MAIN_VARIANT (ttr); + } + } + /* C++ does not allow the implicit conversion void* -> T*. However, for the purpose of reducing the number of false positives, we tolerate the special case of @@ -5320,19 +5550,16 @@ 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. */ @@ -5360,16 +5587,17 @@ where an ordinary one is wanted, but not vice-versa. */ if (TYPE_QUALS_NO_ADDR_SPACE (ttl) & ~TYPE_QUALS_NO_ADDR_SPACE (ttr)) - WARN_FOR_ASSIGNMENT (location, 0, + 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 @@ -5678,15 +5906,16 @@ } /* Issue an error message for a bad initializer component. - MSGID identifies the message. + GMSGID identifies the message. The component name is taken from the spelling stack. */ void -error_init (const char *msgid) +error_init (const char *gmsgid) { char *ofwhat; - error ("%s", _(msgid)); + /* The gmsgid may be a format string with %< and %>. */ + error (gmsgid); ofwhat = print_spelling ((char *) alloca (spelling_length () + 1)); if (*ofwhat) error ("(near initialization for %qs)", ofwhat); @@ -5694,15 +5923,16 @@ /* Issue a pedantic warning for a bad initializer component. OPT is the option OPT_* (from options.h) controlling this warning or 0 if - it is unconditionally given. MSGID identifies the message. The + it is unconditionally given. GMSGID identifies the message. The component name is taken from the spelling stack. */ void -pedwarn_init (location_t location, int opt, const char *msgid) +pedwarn_init (location_t location, int opt, const char *gmsgid) { char *ofwhat; - - pedwarn (location, opt, "%s", _(msgid)); + + /* The gmsgid may be a format string with %< and %>. */ + pedwarn (location, opt, gmsgid); ofwhat = print_spelling ((char *) alloca (spelling_length () + 1)); if (*ofwhat) pedwarn (location, opt, "(near initialization for %qs)", ofwhat); @@ -5711,15 +5941,16 @@ /* Issue a warning for a bad initializer component. OPT is the OPT_W* value corresponding to the warning option that - controls this warning. MSGID identifies the message. The + controls this warning. GMSGID identifies the message. The component name is taken from the spelling stack. */ static void -warning_init (int opt, const char *msgid) +warning_init (int opt, const char *gmsgid) { char *ofwhat; - warning (opt, "%s", _(msgid)); + /* The gmsgid may be a format string with %< and %>. */ + warning (opt, gmsgid); ofwhat = print_spelling ((char *) alloca (spelling_length () + 1)); if (*ofwhat) warning (opt, "(near initialization for %qs)", ofwhat); @@ -6371,7 +6602,7 @@ /* 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; @@ -6386,14 +6617,14 @@ /* 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, @@ -6571,7 +6802,7 @@ /* 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; @@ -6594,14 +6825,14 @@ /* 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, @@ -6690,7 +6921,7 @@ /* 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; } } @@ -6705,7 +6936,7 @@ while (constructor_unfilled_fields && (!DECL_SIZE (constructor_unfilled_fields) || integer_zerop (DECL_SIZE (constructor_unfilled_fields)))) - constructor_unfilled_fields = TREE_CHAIN (constructor_unfilled_fields); + constructor_unfilled_fields = DECL_CHAIN (constructor_unfilled_fields); /* Do not warn if this level of the initializer uses member designators; it is likely to be deliberate. */ @@ -7538,7 +7769,7 @@ || (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) @@ -7626,14 +7857,14 @@ 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; @@ -7902,7 +8133,7 @@ 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; @@ -7950,22 +8181,22 @@ 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) { @@ -8032,7 +8263,7 @@ 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; @@ -8250,7 +8481,7 @@ 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 @@ -9167,6 +9398,10 @@ precision. */ bool may_need_excess_precision; + /* True means this is a boolean operation that converts both its + operands to truth-values. */ + bool boolean_op = false; + if (location == UNKNOWN_LOCATION) location = input_location; @@ -9394,6 +9629,7 @@ op0 = c_common_truthvalue_conversion (location, op0); op1 = c_common_truthvalue_conversion (location, op1); converted = 1; + boolean_op = true; } if (code == TRUTH_ANDIF_EXPR) { @@ -9424,7 +9660,21 @@ 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) @@ -9451,9 +9701,10 @@ /* 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; @@ -9461,7 +9712,21 @@ 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) @@ -9483,9 +9748,10 @@ /* 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; @@ -9710,6 +9976,11 @@ 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; } @@ -9931,7 +10202,8 @@ if (build_type == NULL_TREE) { build_type = result_type; - if (type0 != orig_type0 || type1 != orig_type1) + 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); @@ -9998,6 +10270,10 @@ error_at (location, "used union type value where scalar is required"); return error_mark_node; + case VOID_TYPE: + error_at (location, "void value not ignored as it ought to be"); + return error_mark_node; + case FUNCTION_TYPE: gcc_unreachable (); @@ -10010,8 +10286,8 @@ if (int_operands) expr = remove_c_maybe_const_expr (expr); - /* ??? Should we also give an error for void and vectors rather than - leaving those to give errors later? */ + /* ??? Should we also give an error for vectors rather than leaving + those to give errors later? */ expr = c_common_truthvalue_conversion (location, expr); if (TREE_CODE (expr) == INTEGER_CST && int_operands && !int_const)