X-Git-Url: http://git.sourceforge.jp/view?a=blobdiff_plain;f=gcc%2Fc-typeck.c;h=e7528a715ba4f2172555afa454cfbfd8e60153f2;hb=d5301cf2d5a3834c2e17642503f504cc5e2ab248;hp=09e9ca730394e49722bd71a8e1eba6733cf18517;hpb=93be21c016d4d35bbc03ac44c8be7077868afff1;p=pf3gnuchains%2Fgcc-fork.git diff --git a/gcc/c-typeck.c b/gcc/c-typeck.c index 09e9ca73039..e7528a715ba 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, 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 @@ along with GCC; see the file COPYING3. If not see #include "c-lang.h" #include "flags.h" #include "output.h" -#include "toplev.h" #include "intl.h" #include "target.h" #include "tree-iterator.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,6 +51,14 @@ enum impl_conv { ic_return }; +/* 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; @@ -97,9 +105,8 @@ 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_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 *, bool *); @@ -508,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; @@ -593,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 ... */ @@ -1080,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. */ @@ -2267,26 +2270,8 @@ build_indirect_ref (location_t loc, tree ptr, ref_operator errstring) } } 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; } @@ -2322,7 +2307,7 @@ build_array_ref (location_t loc, tree array, tree index) if (TREE_CODE (TREE_TYPE (index)) != ARRAY_TYPE && TREE_CODE (TREE_TYPE (index)) != POINTER_TYPE) { - error_at (loc, + error_at (loc, "subscripted value is neither array nor pointer nor vector"); return error_mark_node; @@ -2354,8 +2339,8 @@ build_array_ref (location_t loc, tree array, tree index) index = default_conversion (index); gcc_assert (TREE_CODE (TREE_TYPE (index)) == INTEGER_TYPE); - - /* For vector[index], convert the vector to a + + /* For vector[index], convert the vector to a pointer of the underlying type. */ if (TREE_CODE (TREE_TYPE (array)) == VECTOR_TYPE) { @@ -2363,11 +2348,11 @@ build_array_ref (location_t loc, tree array, tree index) tree type1; if (TREE_CODE (index) == INTEGER_CST) - if (!host_integerp (index, 1) - || ((unsigned HOST_WIDE_INT) tree_low_cst (index, 1) + 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); @@ -2831,8 +2816,7 @@ 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)) @@ -2861,6 +2845,98 @@ build_function_call_vec (location_t loc, tree function, VEC(tree,gc) *params, } return require_complete_type (result); } + +/* Build a VEC_SHUFFLE_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_shuffle_expr (location_t loc, tree v0, tree v1, tree mask) +{ + tree vec_shuffle; + 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_SHUFFLE_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; + + vec_shuffle = build3 (VEC_SHUFFLE_EXPR, TREE_TYPE (v0), v0, v1, mask); + + if (!wrap) + vec_shuffle = c_wrap_maybe_const (vec_shuffle, true); + + return vec_shuffle; +} /* Convert the argument expressions in the vector VALUES to the types in the list TYPELIST. @@ -3183,7 +3259,7 @@ convert_arguments (tree typelist, VEC(tree,gc) *values, if (typetail != 0 && TREE_VALUE (typetail) != void_type_node) { - error_at (input_location, + error_at (input_location, "too few arguments to function %qE", function); if (fundecl && !DECL_BUILT_IN (fundecl)) inform (DECL_SOURCE_LOCATION (fundecl), "declared here"); @@ -3582,8 +3658,9 @@ build_unary_op (location_t location, /* 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 (arg, ((code == PREINCREMENT_EXPR + if (!objc_is_property_ref (arg) + && !lvalue_or_else (location, + arg, ((code == PREINCREMENT_EXPR || code == POSTINCREMENT_EXPR) ? lv_increment : lv_decrement))) @@ -3667,7 +3744,7 @@ build_unary_op (location_t location, } 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))) { @@ -3698,7 +3775,7 @@ build_unary_op (location_t location, 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, + return objc_build_incr_expr_for_property_ref (location, code, arg, inc); /* Report a read-only lvalue. */ @@ -3755,18 +3832,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 @@ -3787,10 +3858,11 @@ 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. This should only be needed + 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))) + && (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; @@ -3800,9 +3872,6 @@ build_unary_op (location_t location, 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); } @@ -3820,11 +3889,10 @@ 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; + tree op0 = 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_build_pointer_plus_loc (location, op1, op0); goto return_build_unary_op; } @@ -3898,44 +3966,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. */ @@ -3962,15 +3992,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; } @@ -4858,7 +4889,7 @@ build_modify_expr (location_t location, tree lhs, tree lhs_origtype, return error_mark_node; /* For ObjC properties, defer this check. */ - if (!objc_is_property_ref (lhs) && !lvalue_or_else (lhs, lv_assign)) + if (!objc_is_property_ref (lhs) && !lvalue_or_else (location, lhs, lv_assign)) return error_mark_node; if (TREE_CODE (rhs) == EXCESS_PRECISION_EXPR) @@ -4908,7 +4939,7 @@ build_modify_expr (location_t location, tree lhs, tree lhs_origtype, return result; /* Else, do the check that we postponed for Objective-C. */ - if (!lvalue_or_else (lhs, lv_assign)) + if (!lvalue_or_else (location, lhs, lv_assign)) return error_mark_node; } @@ -5329,10 +5360,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; } @@ -5605,20 +5636,16 @@ convert_for_assignment (location_t location, tree type, tree rhs, 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_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)); + 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. */ @@ -5832,11 +5859,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)); } } } @@ -5989,7 +6018,7 @@ void pedwarn_init (location_t location, int opt, const char *gmsgid) { char *ofwhat; - + /* The gmsgid may be a format string with %< and %>. */ pedwarn (location, opt, gmsgid); ofwhat = print_spelling ((char *) alloca (spelling_length () + 1)); @@ -6701,7 +6730,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; } @@ -6870,8 +6899,8 @@ push_init_level (int implicit, struct obstack * braced_init_obstack) { /* 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) @@ -6991,15 +7020,23 @@ pop_init_level (int implicit, struct obstack * braced_init_obstack) && 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 = DECL_CHAIN (constructor_unfilled_fields); - /* Do not warn if this level of the initializer uses member - designators; it is likely to be deliberate. */ - if (constructor_unfilled_fields && !constructor_designated) + 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, @@ -8540,7 +8577,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 @@ -8561,6 +8598,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; @@ -8587,7 +8631,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; @@ -9152,7 +9201,11 @@ c_process_expr_stmt (location_t loc, tree expr) exprv = expr; while (TREE_CODE (exprv) == COMPOUND_EXPR) exprv = TREE_OPERAND (exprv, 1); - if (DECL_P (exprv) || handled_component_p (exprv)) + 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 @@ -9343,7 +9396,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) { @@ -9374,6 +9427,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. @@ -9485,7 +9620,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); @@ -9557,6 +9695,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: @@ -9819,6 +10002,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, @@ -9858,7 +10066,7 @@ build_binary_op (location_t location, enum tree_code code, { if (code == EQ_EXPR) warning_at (location, - OPT_Waddress, + OPT_Waddress, "the comparison will always evaluate as % " "for the address of %qD will never be NULL", TREE_OPERAND (op1, 0)); @@ -9931,6 +10139,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) @@ -10090,6 +10323,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: @@ -10110,6 +10344,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: @@ -10235,7 +10470,7 @@ 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 = c_wrap_maybe_const (op0, !op0_maybe_const); @@ -10329,9 +10564,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; } @@ -10341,8 +10584,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) @@ -10496,6 +10739,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 = "&"; @@ -10612,6 +10857,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; @@ -10641,6 +10888,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: