This backport contains 4 patchs from gcc main stream tree. The commit id of these patchs list as following in the order of time. 0001-AArch64-Fix-build-for-non-default-languages.patch 6ff0cdebb1bc281ba2374f3ecdbe358c4fa74093 0002-C-Opt-out-of-GNU-vector-extensions-for-built-in-SVE-.patch f486280c53be53136f0bb9b578f43dc6c9c5acea 0003-C-Add-a-target-hook-that-allows-targets-to-verify-ty.patch 65ef05d0b7fb429c5760189e638c441dc3da33f4 0004-AArch64-Run-general-SVE-ACLE-tests-for-C.patch 6da4c454acee4dac53c4c549fa1caeb73fe1f82b diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c index 2c10743b9..50423ec0f 100644 --- a/gcc/c-family/c-common.c +++ b/gcc/c-family/c-common.c @@ -1012,7 +1012,8 @@ c_build_vec_perm_expr (location_t loc, tree v0, tree v1, tree mask, || mask == error_mark_node) return error_mark_node; - if (!VECTOR_INTEGER_TYPE_P (TREE_TYPE (mask))) + if (!gnu_vector_type_p (TREE_TYPE (mask)) + || !VECTOR_INTEGER_TYPE_P (TREE_TYPE (mask))) { if (complain) error_at (loc, "%<__builtin_shuffle%> last argument must " @@ -1020,8 +1021,8 @@ c_build_vec_perm_expr (location_t loc, tree v0, tree v1, tree mask, return error_mark_node; } - if (!VECTOR_TYPE_P (TREE_TYPE (v0)) - || !VECTOR_TYPE_P (TREE_TYPE (v1))) + if (!gnu_vector_type_p (TREE_TYPE (v0)) + || !gnu_vector_type_p (TREE_TYPE (v1))) { if (complain) error_at (loc, "%<__builtin_shuffle%> arguments must be vectors"); @@ -1096,8 +1097,9 @@ c_build_vec_convert (location_t loc1, tree expr, location_t loc2, tree type, if (error_operand_p (expr)) return error_mark_node; - if (!VECTOR_INTEGER_TYPE_P (TREE_TYPE (expr)) - && !VECTOR_FLOAT_TYPE_P (TREE_TYPE (expr))) + if (!gnu_vector_type_p (TREE_TYPE (expr)) + || (!VECTOR_INTEGER_TYPE_P (TREE_TYPE (expr)) + && !VECTOR_FLOAT_TYPE_P (TREE_TYPE (expr)))) { if (complain) error_at (loc1, "%<__builtin_convertvector%> first argument must " @@ -1105,7 +1107,8 @@ c_build_vec_convert (location_t loc1, tree expr, location_t loc2, tree type, return error_mark_node; } - if (!VECTOR_INTEGER_TYPE_P (type) && !VECTOR_FLOAT_TYPE_P (type)) + if (!gnu_vector_type_p (type) + || (!VECTOR_INTEGER_TYPE_P (type) && !VECTOR_FLOAT_TYPE_P (type))) { if (complain) error_at (loc2, "%<__builtin_convertvector%> second argument must " @@ -3128,6 +3131,9 @@ pointer_int_sum (location_t loc, enum tree_code resultcode, return error_mark_node; size_exp = integer_one_node; } + else if (!verify_type_context (loc, TCTX_POINTER_ARITH, + TREE_TYPE (result_type))) + size_exp = integer_one_node; else size_exp = size_in_bytes_loc (loc, TREE_TYPE (result_type)); @@ -3673,6 +3679,13 @@ c_sizeof_or_alignof_type (location_t loc, "incomplete element type", op_name, type); return error_mark_node; } + else if (!verify_type_context (loc, is_sizeof ? TCTX_SIZEOF : TCTX_ALIGNOF, + type, !complain)) + { + if (!complain) + return error_mark_node; + value = size_one_node; + } else { if (is_sizeof) @@ -3705,7 +3718,10 @@ c_alignof_expr (location_t loc, tree expr) { tree t; - if (VAR_OR_FUNCTION_DECL_P (expr)) + if (!verify_type_context (loc, TCTX_ALIGNOF, TREE_TYPE (expr))) + t = size_one_node; + + else if (VAR_OR_FUNCTION_DECL_P (expr)) t = size_int (DECL_ALIGN_UNIT (expr)); else if (TREE_CODE (expr) == COMPONENT_REF @@ -7994,7 +8010,7 @@ convert_vector_to_array_for_subscript (location_t loc, tree *vecp, tree index) { bool ret = false; - if (VECTOR_TYPE_P (TREE_TYPE (*vecp))) + if (gnu_vector_type_p (TREE_TYPE (*vecp))) { tree type = TREE_TYPE (*vecp); @@ -8030,7 +8046,7 @@ scalar_to_vector (location_t loc, enum tree_code code, tree op0, tree op1, bool integer_only_op = false; enum stv_conv ret = stv_firstarg; - gcc_assert (VECTOR_TYPE_P (type0) || VECTOR_TYPE_P (type1)); + gcc_assert (gnu_vector_type_p (type0) || gnu_vector_type_p (type1)); switch (code) { /* Most GENERIC binary expressions require homogeneous arguments. @@ -8081,7 +8097,7 @@ scalar_to_vector (location_t loc, enum tree_code code, tree op0, tree op1, case LT_EXPR: case GT_EXPR: /* What about UNLT_EXPR? */ - if (VECTOR_TYPE_P (type0)) + if (gnu_vector_type_p (type0)) { ret = stv_secondarg; std::swap (type0, type1); diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h index 73ce7c5df..2a9008af4 100644 --- a/gcc/c-family/c-common.h +++ b/gcc/c-family/c-common.h @@ -756,6 +756,16 @@ extern bool done_lexing; #define C_TYPE_OBJECT_OR_INCOMPLETE_P(type) \ (!C_TYPE_FUNCTION_P (type)) +/* Return true if TYPE is a vector type that should be subject to the GNU + vector extensions (as opposed to a vector type that is used only for + the purposes of defining target-specific built-in functions). */ + +inline bool +gnu_vector_type_p (const_tree type) +{ + return TREE_CODE (type) == VECTOR_TYPE && !TYPE_INDIVISIBLE_P (type); +} + struct visibility_flags { unsigned inpragma : 1; /* True when in #pragma GCC visibility. */ diff --git a/gcc/c/c-convert.c b/gcc/c/c-convert.c index f0f846013..21b127d0d 100644 --- a/gcc/c/c-convert.c +++ b/gcc/c/c-convert.c @@ -147,8 +147,20 @@ convert (tree type, tree expr) goto maybe_fold; case VECTOR_TYPE: - ret = convert_to_vector (type, e); - goto maybe_fold; + if (gnu_vector_type_p (type) + || gnu_vector_type_p (TREE_TYPE (e)) + /* Allow conversions between compatible non-GNU vector types + when -flax-vector-conversions is passed. The whole purpose + of the option is to bend the normal type rules and accept + nonconforming code. */ + || (flag_lax_vector_conversions + && VECTOR_TYPE_P (TREE_TYPE (e)) + && vector_types_convertible_p (type, TREE_TYPE (e), false))) + { + ret = convert_to_vector (type, e); + goto maybe_fold; + } + break; case RECORD_TYPE: case UNION_TYPE: diff --git a/gcc/c/c-decl.c b/gcc/c/c-decl.c index 288dbe9d9..bf88d3c7d 100644 --- a/gcc/c/c-decl.c +++ b/gcc/c/c-decl.c @@ -4927,7 +4927,7 @@ start_decl (struct c_declarator *declarator, struct c_declspecs *declspecs, { /* A complete type is ok if size is fixed. */ - if (TREE_CODE (TYPE_SIZE (TREE_TYPE (decl))) != INTEGER_CST + if (!poly_int_tree_p (TYPE_SIZE (TREE_TYPE (decl))) || C_DECL_VARIABLE_SIZE (decl)) { error ("variable-sized object may not be initialized"); @@ -5210,6 +5210,15 @@ finish_decl (tree decl, location_t init_loc, tree init, complete_flexible_array_elts (DECL_INITIAL (decl)); + if (is_global_var (decl)) + { + type_context_kind context = (DECL_THREAD_LOCAL_P (decl) + ? TCTX_THREAD_STORAGE + : TCTX_STATIC_STORAGE); + if (!verify_type_context (input_location, context, TREE_TYPE (decl))) + TREE_TYPE (decl) = error_mark_node; + } + if (DECL_SIZE (decl) == NULL_TREE && TREE_TYPE (decl) != error_mark_node && COMPLETE_TYPE_P (TREE_TYPE (decl))) layout_decl (decl, 0); @@ -5239,7 +5248,9 @@ finish_decl (tree decl, location_t init_loc, tree init, && TREE_STATIC (decl)) incomplete_record_decls.safe_push (decl); - if (is_global_var (decl) && DECL_SIZE (decl) != NULL_TREE) + if (is_global_var (decl) + && DECL_SIZE (decl) != NULL_TREE + && TREE_TYPE (decl) != error_mark_node) { if (TREE_CODE (DECL_SIZE (decl)) == INTEGER_CST) constant_expression_warning (DECL_SIZE (decl)); @@ -5559,6 +5570,10 @@ build_compound_literal (location_t loc, tree type, tree init, bool non_const, return error_mark_node; } + if (TREE_STATIC (decl) + && !verify_type_context (loc, TCTX_STATIC_STORAGE, type)) + return error_mark_node; + stmt = build_stmt (DECL_SOURCE_LOCATION (decl), DECL_EXPR, decl); complit = build1 (COMPOUND_LITERAL_EXPR, type, stmt); TREE_SIDE_EFFECTS (complit) = 1; @@ -6227,6 +6242,12 @@ grokdeclarator (const struct c_declarator *declarator, if (type == error_mark_node) continue; + if (!verify_type_context (loc, TCTX_ARRAY_ELEMENT, type)) + { + type = error_mark_node; + continue; + } + /* If size was specified, set ITYPE to a range-type for that size. Otherwise, ITYPE remains null. finish_decl may figure it out from an initial value. */ @@ -7076,6 +7097,10 @@ grokdeclarator (const struct c_declarator *declarator, if (orig_qual_indirect == 0) orig_qual_type = NULL_TREE; } + if (type != error_mark_node + && !verify_type_context (loc, TCTX_FIELD, type)) + type = error_mark_node; + type = c_build_qualified_type (type, type_quals, orig_qual_type, orig_qual_indirect); decl = build_decl (declarator->id_loc, diff --git a/gcc/c/c-typeck.c b/gcc/c/c-typeck.c index 87f4178ec..f456a66fb 100644 --- a/gcc/c/c-typeck.c +++ b/gcc/c/c-typeck.c @@ -2609,7 +2609,7 @@ build_array_ref (location_t loc, tree array, tree index) if (TREE_CODE (TREE_TYPE (array)) != ARRAY_TYPE && TREE_CODE (TREE_TYPE (array)) != POINTER_TYPE /* Allow vector[index] but not index[vector]. */ - && !VECTOR_TYPE_P (TREE_TYPE (array))) + && !gnu_vector_type_p (TREE_TYPE (array))) { if (TREE_CODE (TREE_TYPE (index)) != ARRAY_TYPE && TREE_CODE (TREE_TYPE (index)) != POINTER_TYPE) @@ -3891,6 +3891,7 @@ pointer_diff (location_t loc, tree op0, tree op1, tree *instrument_expr) 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 orig_op0 = op0; tree orig_op1 = op1; /* If the operands point into different address spaces, we need to @@ -3961,6 +3962,10 @@ pointer_diff (location_t loc, tree op0, tree op1, tree *instrument_expr) /* 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"); + else if (verify_type_context (loc, TCTX_POINTER_ARITH, + TREE_TYPE (TREE_TYPE (orig_op0)))) + verify_type_context (loc, TCTX_POINTER_ARITH, + TREE_TYPE (TREE_TYPE (orig_op1))); op1 = c_size_in_bytes (target_type); @@ -4359,7 +4364,7 @@ build_unary_op (location_t location, enum tree_code code, tree xarg, associativity, but won't generate any code. */ if (!(typecode == INTEGER_TYPE || typecode == REAL_TYPE || typecode == FIXED_POINT_TYPE || typecode == COMPLEX_TYPE - || typecode == VECTOR_TYPE)) + || gnu_vector_type_p (TREE_TYPE (arg)))) { error_at (location, "wrong type argument to unary plus"); return error_mark_node; @@ -4372,7 +4377,7 @@ build_unary_op (location_t location, enum tree_code code, tree xarg, case NEGATE_EXPR: if (!(typecode == INTEGER_TYPE || typecode == REAL_TYPE || typecode == FIXED_POINT_TYPE || typecode == COMPLEX_TYPE - || typecode == VECTOR_TYPE)) + || gnu_vector_type_p (TREE_TYPE (arg)))) { error_at (location, "wrong type argument to unary minus"); return error_mark_node; @@ -4384,7 +4389,7 @@ build_unary_op (location_t location, enum tree_code code, tree xarg, case BIT_NOT_EXPR: /* ~ works on integer types and non float vectors. */ if (typecode == INTEGER_TYPE - || (typecode == VECTOR_TYPE + || (gnu_vector_type_p (TREE_TYPE (arg)) && !VECTOR_FLOAT_TYPE_P (TREE_TYPE (arg)))) { tree e = arg; @@ -4570,7 +4575,8 @@ build_unary_op (location_t location, enum tree_code code, tree xarg, if (typecode != POINTER_TYPE && typecode != FIXED_POINT_TYPE && typecode != INTEGER_TYPE && typecode != REAL_TYPE - && typecode != COMPLEX_TYPE && typecode != VECTOR_TYPE) + && typecode != COMPLEX_TYPE + && !gnu_vector_type_p (TREE_TYPE (arg))) { if (code == PREINCREMENT_EXPR || code == POSTINCREMENT_EXPR) error_at (location, "wrong type argument to increment"); @@ -4612,6 +4618,9 @@ build_unary_op (location_t location, enum tree_code code, tree xarg, pedwarn (location, OPT_Wpointer_arith, "wrong type argument to decrement"); } + else + verify_type_context (location, TCTX_POINTER_ARITH, + TREE_TYPE (argtype)); inc = c_size_in_bytes (TREE_TYPE (argtype)); inc = convert_to_ptrofftype_loc (location, inc); @@ -7854,7 +7863,7 @@ digest_init (location_t init_loc, tree type, tree init, tree origtype, TYPE_MAIN_VARIANT (type)) || (code == ARRAY_TYPE && comptypes (TREE_TYPE (inside_init), type)) - || (code == VECTOR_TYPE + || (gnu_vector_type_p (type) && comptypes (TREE_TYPE (inside_init), type)) || (code == POINTER_TYPE && TREE_CODE (TREE_TYPE (inside_init)) == ARRAY_TYPE @@ -8352,7 +8361,7 @@ really_start_incremental_init (tree type) constructor_unfilled_index = constructor_index; } - else if (VECTOR_TYPE_P (constructor_type)) + else if (gnu_vector_type_p (constructor_type)) { /* Vectors are like simple fixed-size arrays. */ constructor_max_index = @@ -8526,7 +8535,7 @@ push_init_level (location_t loc, int implicit, constructor_unfilled_fields = constructor_fields; constructor_bit_index = bitsize_zero_node; } - else if (VECTOR_TYPE_P (constructor_type)) + else if (gnu_vector_type_p (constructor_type)) { /* Vectors are like simple fixed-size arrays. */ constructor_max_index = @@ -8715,7 +8724,7 @@ pop_init_level (location_t loc, int implicit, ; else if (!RECORD_OR_UNION_TYPE_P (constructor_type) && TREE_CODE (constructor_type) != ARRAY_TYPE - && !VECTOR_TYPE_P (constructor_type)) + && !gnu_vector_type_p (constructor_type)) { /* A nonincremental scalar initializer--just return the element, after verifying there is just one. */ @@ -9941,7 +9950,7 @@ process_init_element (location_t loc, struct c_expr value, bool implicit, last_init_list_comma), true, braced_init_obstack); else if ((TREE_CODE (constructor_type) == ARRAY_TYPE - || VECTOR_TYPE_P (constructor_type)) + || gnu_vector_type_p (constructor_type)) && constructor_max_index && tree_int_cst_lt (constructor_max_index, constructor_index)) @@ -10042,7 +10051,8 @@ process_init_element (location_t loc, struct c_expr value, bool implicit, && value.value != error_mark_node && TYPE_MAIN_VARIANT (TREE_TYPE (value.value)) != fieldtype && (fieldcode == RECORD_TYPE || fieldcode == ARRAY_TYPE - || fieldcode == UNION_TYPE || fieldcode == VECTOR_TYPE)) + || fieldcode == UNION_TYPE + || gnu_vector_type_p (fieldtype))) { push_init_level (loc, 1, braced_init_obstack); continue; @@ -10133,7 +10143,8 @@ process_init_element (location_t loc, struct c_expr value, bool implicit, && value.value != error_mark_node && TYPE_MAIN_VARIANT (TREE_TYPE (value.value)) != fieldtype && (fieldcode == RECORD_TYPE || fieldcode == ARRAY_TYPE - || fieldcode == UNION_TYPE || fieldcode == VECTOR_TYPE)) + || fieldcode == UNION_TYPE + || gnu_vector_type_p (fieldtype))) { push_init_level (loc, 1, braced_init_obstack); continue; @@ -10175,7 +10186,8 @@ process_init_element (location_t loc, struct c_expr value, bool implicit, && value.value != error_mark_node && TYPE_MAIN_VARIANT (TREE_TYPE (value.value)) != elttype && (eltcode == RECORD_TYPE || eltcode == ARRAY_TYPE - || eltcode == UNION_TYPE || eltcode == VECTOR_TYPE)) + || eltcode == UNION_TYPE + || gnu_vector_type_p (elttype))) { push_init_level (loc, 1, braced_init_obstack); continue; @@ -10211,7 +10223,7 @@ process_init_element (location_t loc, struct c_expr value, bool implicit, constructor_unfilled_index. */ constructor_unfilled_index = constructor_index; } - else if (VECTOR_TYPE_P (constructor_type)) + else if (gnu_vector_type_p (constructor_type)) { tree elttype = TYPE_MAIN_VARIANT (TREE_TYPE (constructor_type)); @@ -11555,7 +11567,8 @@ build_binary_op (location_t location, enum tree_code code, /* 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)) + if ((gnu_vector_type_p (type0) && code1 != VECTOR_TYPE) + || (gnu_vector_type_p (type1) && code0 != VECTOR_TYPE)) { enum stv_conv convert_flag = scalar_to_vector (location, code, op0, op1, true); @@ -11650,10 +11663,12 @@ build_binary_op (location_t location, enum tree_code code, if ((code0 == INTEGER_TYPE || code0 == REAL_TYPE || code0 == FIXED_POINT_TYPE - || code0 == COMPLEX_TYPE || code0 == VECTOR_TYPE) + || code0 == COMPLEX_TYPE + || gnu_vector_type_p (type0)) && (code1 == INTEGER_TYPE || code1 == REAL_TYPE || code1 == FIXED_POINT_TYPE - || code1 == COMPLEX_TYPE || code1 == VECTOR_TYPE)) + || code1 == COMPLEX_TYPE + || gnu_vector_type_p (type1))) { enum tree_code tcode0 = code0, tcode1 = code1; @@ -11684,8 +11699,8 @@ build_binary_op (location_t location, enum tree_code code, if (code0 == INTEGER_TYPE && code1 == INTEGER_TYPE) shorten = -1; /* Allow vector types which are not floating point types. */ - else if (code0 == VECTOR_TYPE - && code1 == VECTOR_TYPE + else if (gnu_vector_type_p (type0) + && gnu_vector_type_p (type1) && !VECTOR_FLOAT_TYPE_P (type0) && !VECTOR_FLOAT_TYPE_P (type1)) common = 1; @@ -11696,7 +11711,8 @@ build_binary_op (location_t location, enum tree_code code, doing_div_or_mod = true; warn_for_div_by_zero (location, op1); - if (code0 == VECTOR_TYPE && code1 == VECTOR_TYPE + if (gnu_vector_type_p (type0) + && gnu_vector_type_p (type1) && TREE_CODE (TREE_TYPE (type0)) == INTEGER_TYPE && TREE_CODE (TREE_TYPE (type1)) == INTEGER_TYPE) common = 1; @@ -11775,7 +11791,8 @@ build_binary_op (location_t location, enum tree_code code, Also set SHORT_SHIFT if shifting rightward. */ case RSHIFT_EXPR: - if (code0 == VECTOR_TYPE && code1 == VECTOR_TYPE + if (gnu_vector_type_p (type0) + && gnu_vector_type_p (type1) && TREE_CODE (TREE_TYPE (type0)) == INTEGER_TYPE && TREE_CODE (TREE_TYPE (type1)) == INTEGER_TYPE && known_eq (TYPE_VECTOR_SUBPARTS (type0), @@ -11785,7 +11802,7 @@ build_binary_op (location_t location, enum tree_code code, converted = 1; } else if ((code0 == INTEGER_TYPE || code0 == FIXED_POINT_TYPE - || (code0 == VECTOR_TYPE + || (gnu_vector_type_p (type0) && TREE_CODE (TREE_TYPE (type0)) == INTEGER_TYPE)) && code1 == INTEGER_TYPE) { @@ -11834,7 +11851,8 @@ build_binary_op (location_t location, enum tree_code code, break; case LSHIFT_EXPR: - if (code0 == VECTOR_TYPE && code1 == VECTOR_TYPE + if (gnu_vector_type_p (type0) + && gnu_vector_type_p (type1) && TREE_CODE (TREE_TYPE (type0)) == INTEGER_TYPE && TREE_CODE (TREE_TYPE (type1)) == INTEGER_TYPE && known_eq (TYPE_VECTOR_SUBPARTS (type0), @@ -11844,7 +11862,7 @@ build_binary_op (location_t location, enum tree_code code, converted = 1; } else if ((code0 == INTEGER_TYPE || code0 == FIXED_POINT_TYPE - || (code0 == VECTOR_TYPE + || (gnu_vector_type_p (type0) && TREE_CODE (TREE_TYPE (type0)) == INTEGER_TYPE)) && code1 == INTEGER_TYPE) { @@ -11903,7 +11921,7 @@ build_binary_op (location_t location, enum tree_code code, case EQ_EXPR: case NE_EXPR: - if (code0 == VECTOR_TYPE && code1 == VECTOR_TYPE) + if (gnu_vector_type_p (type0) && gnu_vector_type_p (type1)) { tree intt; if (!vector_types_compatible_elements_p (type0, type1)) @@ -12071,7 +12089,7 @@ 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) + if (gnu_vector_type_p (type0) && gnu_vector_type_p (type1)) { tree intt; if (!vector_types_compatible_elements_p (type0, type1)) @@ -12218,7 +12236,8 @@ build_binary_op (location_t location, enum tree_code code, if (code0 == ERROR_MARK || code1 == ERROR_MARK) return error_mark_node; - if (code0 == VECTOR_TYPE && code1 == VECTOR_TYPE + if (gnu_vector_type_p (type0) + && gnu_vector_type_p (type1) && (!tree_int_cst_equal (TYPE_SIZE (type0), TYPE_SIZE (type1)) || !vector_types_compatible_elements_p (type0, type1))) { @@ -12233,10 +12252,12 @@ build_binary_op (location_t location, enum tree_code code, } if ((code0 == INTEGER_TYPE || code0 == REAL_TYPE || code0 == COMPLEX_TYPE - || code0 == FIXED_POINT_TYPE || code0 == VECTOR_TYPE) + || code0 == FIXED_POINT_TYPE + || gnu_vector_type_p (type0)) && (code1 == INTEGER_TYPE || code1 == REAL_TYPE || code1 == COMPLEX_TYPE - || code1 == FIXED_POINT_TYPE || code1 == VECTOR_TYPE)) + || code1 == FIXED_POINT_TYPE + || gnu_vector_type_p (type1))) { bool first_complex = (code0 == COMPLEX_TYPE); bool second_complex = (code1 == COMPLEX_TYPE); diff --git a/gcc/config/aarch64/aarch64-protos.h b/gcc/config/aarch64/aarch64-protos.h index a9123c858..51356da37 100644 --- a/gcc/config/aarch64/aarch64-protos.h +++ b/gcc/config/aarch64/aarch64-protos.h @@ -717,6 +717,9 @@ namespace aarch64_sve { tree, unsigned int, tree *); gimple *gimple_fold_builtin (unsigned int, gimple_stmt_iterator *, gcall *); rtx expand_builtin (unsigned int, tree, rtx); +#ifdef GCC_TARGET_H + bool verify_type_context (location_t, type_context_kind, const_tree, bool); +#endif } extern void aarch64_split_combinev16qi (rtx operands[3]); diff --git a/gcc/config/aarch64/aarch64-sve-builtins.cc b/gcc/config/aarch64/aarch64-sve-builtins.cc index f830d9294..10595a5ab 100644 --- a/gcc/config/aarch64/aarch64-sve-builtins.cc +++ b/gcc/config/aarch64/aarch64-sve-builtins.cc @@ -3248,8 +3248,10 @@ register_builtin_types () BITS_PER_SVE_VECTOR)); } vectype = build_distinct_type_copy (vectype); + gcc_assert (vectype == TYPE_MAIN_VARIANT (vectype)); SET_TYPE_STRUCTURAL_EQUALITY (vectype); TYPE_ARTIFICIAL (vectype) = 1; + TYPE_INDIVISIBLE_P (vectype) = 1; abi_vector_types[i] = vectype; lang_hooks.types.register_builtin_type (vectype, vector_types[i].abi_name); @@ -3490,8 +3492,7 @@ bool svbool_type_p (const_tree type) { tree abi_type = abi_vector_types[VECTOR_TYPE_svbool_t]; - return (type != error_mark_node - && TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (abi_type)); + return type != error_mark_node && TYPE_MAIN_VARIANT (type) == abi_type; } /* If TYPE is a built-in type defined by the SVE ABI, return the mangled name, @@ -3546,6 +3547,55 @@ builtin_type_p (const_tree type) return svbool_type_p (type) || nvectors_if_data_type (type) > 0; } +/* Implement TARGET_VERIFY_TYPE_CONTEXT for SVE types. */ +bool +verify_type_context (location_t loc, type_context_kind context, + const_tree type, bool silent_p) +{ + if (!builtin_type_p (type)) + return true; + + switch (context) + { + case TCTX_SIZEOF: + case TCTX_STATIC_STORAGE: + if (!silent_p) + error_at (loc, "SVE type %qT does not have a fixed size", type); + return false; + + case TCTX_ALIGNOF: + if (!silent_p) + error_at (loc, "SVE type %qT does not have a defined alignment", type); + return false; + + case TCTX_THREAD_STORAGE: + if (!silent_p) + error_at (loc, "variables of type %qT cannot have thread-local" + " storage duration", type); + return false; + + case TCTX_POINTER_ARITH: + if (!silent_p) + error_at (loc, "arithmetic on pointer to SVE type %qT", type); + return false; + + case TCTX_FIELD: + if (silent_p) + ; + else if (lang_GNU_CXX ()) + error_at (loc, "member variables cannot have SVE type %qT", type); + else + error_at (loc, "fields cannot have SVE type %qT", type); + return false; + + case TCTX_ARRAY_ELEMENT: + if (!silent_p) + error_at (loc, "array elements cannot have SVE type %qT", type); + return false; + } + gcc_unreachable (); +} + } using namespace aarch64_sve; diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c index 3486cca89..c2ab7af56 100644 --- a/gcc/config/aarch64/aarch64.c +++ b/gcc/config/aarch64/aarch64.c @@ -16201,6 +16201,15 @@ aarch64_mangle_type (const_tree type) return NULL; } +/* Implement TARGET_VERIFY_TYPE_CONTEXT. */ + +static bool +aarch64_verify_type_context (location_t loc, type_context_kind context, + const_tree type, bool silent_p) +{ + return aarch64_sve::verify_type_context (loc, context, type, silent_p); +} + /* Find the first rtx_insn before insn that will generate an assembly instruction. */ @@ -21967,6 +21976,9 @@ aarch64_libgcc_floating_mode_supported_p #undef TARGET_MANGLE_TYPE #define TARGET_MANGLE_TYPE aarch64_mangle_type +#undef TARGET_VERIFY_TYPE_CONTEXT +#define TARGET_VERIFY_TYPE_CONTEXT aarch64_verify_type_context + #undef TARGET_INVALID_CONVERSION #define TARGET_INVALID_CONVERSION aarch64_invalid_conversion diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi index 3f22bb1f6..220bbe7dd 100644 --- a/gcc/doc/tm.texi +++ b/gcc/doc/tm.texi @@ -11963,6 +11963,19 @@ conversion rules. This is currently used only by the C and C++ front ends. @end deftypefn +@deftypefn {Target Hook} bool TARGET_VERIFY_TYPE_CONTEXT (location_t @var{loc}, type_context_kind @var{context}, const_tree @var{type}, bool @var{silent_p}) +If defined, this hook returns false if there is a target-specific reason +why type @var{type} cannot be used in the source language context described +by @var{context}. When @var{silent_p} is false, the hook also reports an +error against @var{loc} for invalid uses of @var{type}. + +Calls to this hook should be made through the global function +@code{verify_type_context}, which makes the @var{silent_p} parameter +default to false and also handles @code{error_mark_node}. + +The default implementation always returns true. +@end deftypefn + @defmac OBJC_JBLEN This macro determines the size of the objective C jump buffer for the NeXT runtime. By default, OBJC_JBLEN is defined to an innocuous value. diff --git a/gcc/doc/tm.texi.in b/gcc/doc/tm.texi.in index 89cfb5253..a8cb42a6b 100644 --- a/gcc/doc/tm.texi.in +++ b/gcc/doc/tm.texi.in @@ -8095,6 +8095,8 @@ and scanf formatter settings. @hook TARGET_CONVERT_TO_TYPE +@hook TARGET_VERIFY_TYPE_CONTEXT + @defmac OBJC_JBLEN This macro determines the size of the objective C jump buffer for the NeXT runtime. By default, OBJC_JBLEN is defined to an innocuous value. diff --git a/gcc/target.def b/gcc/target.def index 05389cdd1..4e3dc341c 100644 --- a/gcc/target.def +++ b/gcc/target.def @@ -5234,6 +5234,22 @@ This is currently used only by the C and C++ front ends.", tree, (tree type, tree expr), hook_tree_tree_tree_null) +DEFHOOK +(verify_type_context, + "If defined, this hook returns false if there is a target-specific reason\n\ +why type @var{type} cannot be used in the source language context described\n\ +by @var{context}. When @var{silent_p} is false, the hook also reports an\n\ +error against @var{loc} for invalid uses of @var{type}.\n\ +\n\ +Calls to this hook should be made through the global function\n\ +@code{verify_type_context}, which makes the @var{silent_p} parameter\n\ +default to false and also handles @code{error_mark_node}.\n\ +\n\ +The default implementation always returns true.", + bool, (location_t loc, type_context_kind context, const_tree type, + bool silent_p), + NULL) + DEFHOOK (can_change_mode_class, "This hook returns true if it is possible to bitcast values held in\n\ diff --git a/gcc/target.h b/gcc/target.h index 964629669..3e6d34d34 100644 --- a/gcc/target.h +++ b/gcc/target.h @@ -219,6 +219,35 @@ typedef auto_vec auto_vector_modes; will choose the first mode that works. */ const unsigned int VECT_COMPARE_COSTS = 1U << 0; +/* The contexts in which the use of a type T can be checked by + TARGET_VERIFY_TYPE_CONTEXT. */ +enum type_context_kind { + /* Directly measuring the size of T. */ + TCTX_SIZEOF, + + /* Directly measuring the alignment of T. */ + TCTX_ALIGNOF, + + /* Creating objects of type T with static storage duration. */ + TCTX_STATIC_STORAGE, + + /* Creating objects of type T with thread-local storage duration. */ + TCTX_THREAD_STORAGE, + + /* Creating a field of type T. */ + TCTX_FIELD, + + /* Creating an array with elements of type T. */ + TCTX_ARRAY_ELEMENT, + + /* Adding to or subtracting from a pointer to T, or computing the + difference between two pointers when one of them is a pointer to T. */ + TCTX_POINTER_ARITH +}; + +extern bool verify_type_context (location_t, type_context_kind, const_tree, + bool = false); + /* The target structure. This holds all the backend hooks. */ #define DEFHOOKPOD(NAME, DOC, TYPE, INIT) TYPE NAME; #define DEFHOOK(NAME, DOC, TYPE, PARAMS, INIT) TYPE (* NAME) PARAMS; diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/aarch64-sve-acle.exp b/gcc/testsuite/gcc.target/aarch64/sve/acle/aarch64-sve-acle.exp index 34d9dfd43..1672ddfef 100644 --- a/gcc/testsuite/gcc.target/aarch64/sve/acle/aarch64-sve-acle.exp +++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/aarch64-sve-acle.exp @@ -45,9 +45,9 @@ if { [check_effective_target_aarch64_sve] } { } # Main loop. -# FIXME: This should include general/*.c too, but leave that until the -# C frontend allows initialization of SVE vectors. -set files [glob -nocomplain $srcdir/$subdir/general-c/*.c] +set files [glob -nocomplain \ + "$srcdir/$subdir/general/*.c" \ + "$srcdir/$subdir/general-c/*.c"] dg-runtest [lsort $files] "$sve_flags" $DEFAULT_CFLAGS # All done. diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/gnu_vectors_1.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/gnu_vectors_1.c new file mode 100644 index 000000000..c4596f7e9 --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/gnu_vectors_1.c @@ -0,0 +1,415 @@ +/* { dg-options "-msve-vector-bits=256" } */ + +#include + +typedef uint8_t gnu_uint8_t __attribute__ ((vector_size (32))); +typedef int8_t gnu_int8_t __attribute__ ((vector_size (32))); + +void +f (svuint8_t sve_u1, svint8_t sve_s1, + gnu_uint8_t gnu_u1, gnu_int8_t gnu_s1, int n, unsigned char uc) +{ + /* Initialization. */ + + svuint8_t init_sve_u1 = 0; /* { dg-error {incompatible types when initializing type 'svuint8_t' using type 'int'} } */ + svuint8_t init_sve_u2 = {}; /* { dg-error {empty scalar initializer} } */ + svuint8_t init_sve_u3 = { sve_u1 }; + svuint8_t init_sve_u4 = { gnu_u1 }; + svuint8_t init_sve_u5 = { sve_s1 }; /* { dg-error {incompatible types when initializing type 'svuint8_t' using type 'svint8_t'} } */ + svuint8_t init_sve_u6 = { gnu_s1 }; /* { dg-error {incompatible types when initializing type 'svuint8_t'} } */ + svuint8_t init_sve_u7 = { 0 }; /* { dg-error {incompatible types when initializing type 'svuint8_t' using type 'int'} } */ + svuint8_t init_sve_u8 = { sve_u1, sve_u1 }; /* { dg-warning {excess elements in scalar initializer} } */ + svuint8_t init_sve_u9 = { gnu_u1, gnu_u1 }; /* { dg-warning {excess elements in scalar initializer} } */ + + gnu_uint8_t init_gnu_u1 = 0; /* { dg-error {incompatible types when initializing type 'gnu_uint8_t'[^\n]* using type 'int'} } */ + gnu_uint8_t init_gnu_u2 = {}; + gnu_uint8_t init_gnu_u3 = { sve_u1 }; /* { dg-error {incompatible types when initializing type 'unsigned char'} } */ + gnu_uint8_t init_gnu_u4 = { gnu_u1 }; /* { dg-error {incompatible types when initializing type 'unsigned char'} } */ + gnu_uint8_t init_gnu_u5 = { sve_s1 }; /* { dg-error {incompatible types when initializing type 'unsigned char'} } */ + gnu_uint8_t init_gnu_u6 = { gnu_s1 }; /* { dg-error {incompatible types when initializing type 'unsigned char'} } */ + gnu_uint8_t init_gnu_u7 = { 0 }; + + /* Compound literals. */ + + (svuint8_t) {}; /* { dg-error {empty scalar initializer} } */ + (svuint8_t) { 0 }; /* { dg-error {incompatible types when initializing type 'svuint8_t' using type 'int'} } */ + (svuint8_t) { sve_u1 }; + (svuint8_t) { gnu_u1 }; + (svuint8_t) { sve_s1 }; /* { dg-error {incompatible types when initializing type 'svuint8_t' using type 'svint8_t'} } */ + (svuint8_t) { gnu_s1 }; /* { dg-error {incompatible types when initializing type 'svuint8_t'} } */ + + (gnu_uint8_t) {}; + (gnu_uint8_t) { 0 }; + (gnu_uint8_t) { sve_u1 }; /* { dg-error {incompatible types when initializing type 'unsigned char'} } */ + (gnu_uint8_t) { gnu_u1 }; /* { dg-error {incompatible types when initializing type 'unsigned char'} } */ + + /* Assignment. */ + + sve_u1 = 0; /* { dg-error {incompatible types when assigning to type 'svuint8_t' from type 'int'} } */ + sve_u1 = sve_u1; + sve_u1 = gnu_u1; + sve_u1 = sve_s1; /* { dg-error {incompatible types when assigning to type 'svuint8_t' from type 'svint8_t'} } */ + sve_u1 = gnu_s1; /* { dg-error {incompatible types when assigning to type 'svuint8_t' from type 'gnu_int8_t'} } */ + + gnu_u1 = 0; /* { dg-error {incompatible types when assigning to type 'gnu_uint8_t'[^\n]* from type 'int'} } */ + gnu_u1 = sve_u1; + gnu_u1 = gnu_u1; + gnu_u1 = sve_s1; /* { dg-error {incompatible types when assigning to type 'gnu_uint8_t'[^\n]* from type 'svint8_t'} } */ + gnu_u1 = gnu_s1; /* { dg-error {incompatible types when assigning to type 'gnu_uint8_t'[^\n]* from type 'gnu_int8_t'} } */ + + /* Casts. */ + + (void) sve_u1; + (svuint8_t) sve_u1; + (svuint8_t) gnu_u1; + (svuint8_t) 0; /* { dg-error {conversion to non-scalar type requested} } */ + (svuint8_t) n; /* { dg-error {conversion to non-scalar type requested} } */ + (svint8_t) sve_u1; /* { dg-error {conversion to non-scalar type requested} } */ + (svint8_t) gnu_u1; + + (void) gnu_u1; + (gnu_uint8_t) sve_u1; + (gnu_uint8_t) gnu_u1; + (gnu_uint8_t) 0; /* { dg-error {can't convert a value of type 'int' to vector type '[^']*' which has different size} } */ + (gnu_uint8_t) n; /* { dg-error {can't convert a value of type 'int' to vector type '[^']*' which has different size} } */ + (gnu_int8_t) sve_u1; + (gnu_int8_t) gnu_u1; + + /* Vector indexing. */ + + sve_u1[0]; /* { dg-error {subscripted value is neither array nor pointer} } */ + &sve_u1[0]; /* { dg-error {subscripted value is neither array nor pointer} } */ + + gnu_u1[0]; + &gnu_u1[0]; + + /* Unary operators. */ + + +sve_u1; /* { dg-error {wrong type argument to unary plus} } */ + -sve_u1; /* { dg-error {wrong type argument to unary minus} } */ + ~sve_u1; /* { dg-error {wrong type argument to bit-complement} } */ + !sve_u1; /* { dg-error {wrong type argument to unary exclamation mark} } */ + *sve_u1; /* { dg-error {invalid type argument of unary '\*'} } */ + __real sve_u1; /* { dg-error {wrong type argument to __real} } */ + __imag sve_u1; /* { dg-error {wrong type argument to __imag} } */ + ++sve_u1; /* { dg-error {wrong type argument to increment} } */ + --sve_u1; /* { dg-error {wrong type argument to decrement} } */ + sve_u1++; /* { dg-error {wrong type argument to increment} } */ + sve_u1--; /* { dg-error {wrong type argument to decrement} } */ + + +gnu_u1; + -gnu_u1; + ~gnu_u1; + !gnu_u1; /* { dg-error {wrong type argument to unary exclamation mark} } */ + *gnu_u1; /* { dg-error {invalid type argument of unary '\*'} } */ + __real gnu_u1; /* { dg-error {wrong type argument to __real} } */ + __imag gnu_u1; /* { dg-error {wrong type argument to __imag} } */ + ++gnu_u1; + --gnu_u1; + gnu_u1++; + gnu_u1--; + + /* Vector-vector binary arithmetic. */ + + sve_u1 + sve_u1; /* { dg-error {invalid operands to binary \+} } */ + sve_u1 - sve_u1; /* { dg-error {invalid operands to binary -} } */ + sve_u1 * sve_u1; /* { dg-error {invalid operands to binary \*} } */ + sve_u1 / sve_u1; /* { dg-error {invalid operands to binary /} } */ + sve_u1 % sve_u1; /* { dg-error {invalid operands to binary %} } */ + sve_u1 & sve_u1; /* { dg-error {invalid operands to binary \&} } */ + sve_u1 | sve_u1; /* { dg-error {invalid operands to binary \|} } */ + sve_u1 ^ sve_u1; /* { dg-error {invalid operands to binary \^} } */ + sve_u1 == sve_u1; /* { dg-error {invalid operands to binary ==} } */ + sve_u1 != sve_u1; /* { dg-error {invalid operands to binary !=} } */ + sve_u1 <= sve_u1; /* { dg-error {invalid operands to binary <=} } */ + sve_u1 < sve_u1; /* { dg-error {invalid operands to binary <} } */ + sve_u1 > sve_u1; /* { dg-error {invalid operands to binary >} } */ + sve_u1 >= sve_u1; /* { dg-error {invalid operands to binary >=} } */ + sve_u1 << sve_u1; /* { dg-error {invalid operands to binary <<} } */ + sve_u1 >> sve_u1; /* { dg-error {invalid operands to binary >>} } */ + sve_u1 && sve_u1; /* { dg-error {used vector type where scalar is required} } */ + sve_u1 || sve_u1; /* { dg-error {used vector type where scalar is required} } */ + + sve_u1 + gnu_u1; /* { dg-error {invalid operands to binary \+} } */ + sve_u1 - gnu_u1; /* { dg-error {invalid operands to binary -} } */ + sve_u1 * gnu_u1; /* { dg-error {invalid operands to binary \*} } */ + sve_u1 / gnu_u1; /* { dg-error {invalid operands to binary /} } */ + sve_u1 % gnu_u1; /* { dg-error {invalid operands to binary %} } */ + sve_u1 & gnu_u1; /* { dg-error {invalid operands to binary \&} } */ + sve_u1 | gnu_u1; /* { dg-error {invalid operands to binary \|} } */ + sve_u1 ^ gnu_u1; /* { dg-error {invalid operands to binary \^} } */ + sve_u1 == gnu_u1; /* { dg-error {invalid operands to binary ==} } */ + sve_u1 != gnu_u1; /* { dg-error {invalid operands to binary !=} } */ + sve_u1 <= gnu_u1; /* { dg-error {invalid operands to binary <=} } */ + sve_u1 < gnu_u1; /* { dg-error {invalid operands to binary <} } */ + sve_u1 > gnu_u1; /* { dg-error {invalid operands to binary >} } */ + sve_u1 >= gnu_u1; /* { dg-error {invalid operands to binary >=} } */ + sve_u1 << gnu_u1; /* { dg-error {invalid operands to binary <<} } */ + sve_u1 >> gnu_u1; /* { dg-error {invalid operands to binary >>} } */ + sve_u1 && gnu_u1; /* { dg-error {used vector type where scalar is required} } */ + sve_u1 || gnu_u1; /* { dg-error {used vector type where scalar is required} } */ + + gnu_u1 + sve_u1; /* { dg-error {invalid operands to binary \+} } */ + gnu_u1 - sve_u1; /* { dg-error {invalid operands to binary -} } */ + gnu_u1 * sve_u1; /* { dg-error {invalid operands to binary \*} } */ + gnu_u1 / sve_u1; /* { dg-error {invalid operands to binary /} } */ + gnu_u1 % sve_u1; /* { dg-error {invalid operands to binary %} } */ + gnu_u1 & sve_u1; /* { dg-error {invalid operands to binary \&} } */ + gnu_u1 | sve_u1; /* { dg-error {invalid operands to binary \|} } */ + gnu_u1 ^ sve_u1; /* { dg-error {invalid operands to binary \^} } */ + gnu_u1 == sve_u1; /* { dg-error {invalid operands to binary ==} } */ + gnu_u1 != sve_u1; /* { dg-error {invalid operands to binary !=} } */ + gnu_u1 <= sve_u1; /* { dg-error {invalid operands to binary <=} } */ + gnu_u1 < sve_u1; /* { dg-error {invalid operands to binary <} } */ + gnu_u1 > sve_u1; /* { dg-error {invalid operands to binary >} } */ + gnu_u1 >= sve_u1; /* { dg-error {invalid operands to binary >=} } */ + gnu_u1 << sve_u1; /* { dg-error {invalid operands to binary <<} } */ + gnu_u1 >> sve_u1; /* { dg-error {invalid operands to binary >>} } */ + gnu_u1 && sve_u1; /* { dg-error {used vector type where scalar is required} } */ + gnu_u1 || sve_u1; /* { dg-error {used vector type where scalar is required} } */ + + gnu_u1 + gnu_u1; + gnu_u1 - gnu_u1; + gnu_u1 * gnu_u1; + gnu_u1 / gnu_u1; + gnu_u1 % gnu_u1; + gnu_u1 & gnu_u1; + gnu_u1 | gnu_u1; + gnu_u1 ^ gnu_u1; + gnu_u1 == gnu_u1; + gnu_u1 != gnu_u1; + gnu_u1 <= gnu_u1; + gnu_u1 < gnu_u1; + gnu_u1 > gnu_u1; + gnu_u1 >= gnu_u1; + gnu_u1 << gnu_u1; + gnu_u1 >> gnu_u1; + gnu_u1 && gnu_u1; /* { dg-error {used vector type where scalar is required} } */ + gnu_u1 || gnu_u1; /* { dg-error {used vector type where scalar is required} } */ + + /* Vector-scalar binary arithmetic. */ + + sve_u1 + 2; /* { dg-error {invalid operands to binary \+} } */ + sve_u1 - 2; /* { dg-error {invalid operands to binary -} } */ + sve_u1 * 2; /* { dg-error {invalid operands to binary \*} } */ + sve_u1 / 2; /* { dg-error {invalid operands to binary /} } */ + sve_u1 % 2; /* { dg-error {invalid operands to binary %} } */ + sve_u1 & 2; /* { dg-error {invalid operands to binary \&} } */ + sve_u1 | 2; /* { dg-error {invalid operands to binary \|} } */ + sve_u1 ^ 2; /* { dg-error {invalid operands to binary \^} } */ + sve_u1 == 2; /* { dg-error {invalid operands to binary ==} } */ + sve_u1 != 2; /* { dg-error {invalid operands to binary !=} } */ + sve_u1 <= 2; /* { dg-error {invalid operands to binary <=} } */ + sve_u1 < 2; /* { dg-error {invalid operands to binary <} } */ + sve_u1 > 2; /* { dg-error {invalid operands to binary >} } */ + sve_u1 >= 2; /* { dg-error {invalid operands to binary >=} } */ + sve_u1 << 2; /* { dg-error {invalid operands to binary <<} } */ + sve_u1 >> 2; /* { dg-error {invalid operands to binary >>} } */ + sve_u1 && 2; /* { dg-error {used vector type where scalar is required} } */ + sve_u1 || 2; /* { dg-error {used vector type where scalar is required} } */ + + sve_u1 + uc; /* { dg-error {invalid operands to binary \+} } */ + sve_u1 - uc; /* { dg-error {invalid operands to binary -} } */ + sve_u1 * uc; /* { dg-error {invalid operands to binary \*} } */ + sve_u1 / uc; /* { dg-error {invalid operands to binary /} } */ + sve_u1 % uc; /* { dg-error {invalid operands to binary %} } */ + sve_u1 & uc; /* { dg-error {invalid operands to binary \&} } */ + sve_u1 | uc; /* { dg-error {invalid operands to binary \|} } */ + sve_u1 ^ uc; /* { dg-error {invalid operands to binary \^} } */ + sve_u1 == uc; /* { dg-error {invalid operands to binary ==} } */ + sve_u1 != uc; /* { dg-error {invalid operands to binary !=} } */ + sve_u1 <= uc; /* { dg-error {invalid operands to binary <=} } */ + sve_u1 < uc; /* { dg-error {invalid operands to binary <} } */ + sve_u1 > uc; /* { dg-error {invalid operands to binary >} } */ + sve_u1 >= uc; /* { dg-error {invalid operands to binary >=} } */ + sve_u1 << uc; /* { dg-error {invalid operands to binary <<} } */ + sve_u1 >> uc; /* { dg-error {invalid operands to binary >>} } */ + sve_u1 && uc; /* { dg-error {used vector type where scalar is required} } */ + sve_u1 || uc; /* { dg-error {used vector type where scalar is required} } */ + + gnu_u1 + 2; + gnu_u1 - 2; + gnu_u1 * 2; + gnu_u1 / 2; + gnu_u1 % 2; + gnu_u1 & 2; + gnu_u1 | 2; + gnu_u1 ^ 2; + gnu_u1 == 2; + gnu_u1 != 2; + gnu_u1 <= 2; + gnu_u1 < 2; + gnu_u1 > 2; + gnu_u1 >= 2; + gnu_u1 << 2; + gnu_u1 >> 2; + gnu_u1 && 2; /* { dg-error {used vector type where scalar is required} } */ + gnu_u1 || 2; /* { dg-error {used vector type where scalar is required} } */ + + gnu_u1 + uc; + gnu_u1 - uc; + gnu_u1 * uc; + gnu_u1 / uc; + gnu_u1 % uc; + gnu_u1 & uc; + gnu_u1 | uc; + gnu_u1 ^ uc; + gnu_u1 == uc; + gnu_u1 != uc; + gnu_u1 <= uc; + gnu_u1 < uc; + gnu_u1 > uc; + gnu_u1 >= uc; + gnu_u1 << uc; + gnu_u1 >> uc; + gnu_u1 && uc; /* { dg-error {used vector type where scalar is required} } */ + gnu_u1 || uc; /* { dg-error {used vector type where scalar is required} } */ + + /* Scalar-vector binary arithmetic. */ + + 3 + sve_u1; /* { dg-error {invalid operands to binary \+} } */ + 3 - sve_u1; /* { dg-error {invalid operands to binary -} } */ + 3 * sve_u1; /* { dg-error {invalid operands to binary \*} } */ + 3 / sve_u1; /* { dg-error {invalid operands to binary /} } */ + 3 % sve_u1; /* { dg-error {invalid operands to binary %} } */ + 3 & sve_u1; /* { dg-error {invalid operands to binary \&} } */ + 3 | sve_u1; /* { dg-error {invalid operands to binary \|} } */ + 3 ^ sve_u1; /* { dg-error {invalid operands to binary \^} } */ + 3 == sve_u1; /* { dg-error {invalid operands to binary ==} } */ + 3 != sve_u1; /* { dg-error {invalid operands to binary !=} } */ + 3 <= sve_u1; /* { dg-error {invalid operands to binary <=} } */ + 3 < sve_u1; /* { dg-error {invalid operands to binary <} } */ + 3 > sve_u1; /* { dg-error {invalid operands to binary >} } */ + 3 >= sve_u1; /* { dg-error {invalid operands to binary >=} } */ + 3 << sve_u1; /* { dg-error {invalid operands to binary <<} } */ + 3 >> sve_u1; /* { dg-error {invalid operands to binary >>} } */ + 3 && sve_u1; /* { dg-error {invalid operands to binary \&\&} } */ + 3 || sve_u1; /* { dg-error {invalid operands to binary \|\|} } */ + + 3 + gnu_u1; + 3 - gnu_u1; + 3 * gnu_u1; + 3 / gnu_u1; + 3 % gnu_u1; + 3 & gnu_u1; + 3 | gnu_u1; + 3 ^ gnu_u1; + 3 == gnu_u1; + 3 != gnu_u1; + 3 <= gnu_u1; + 3 < gnu_u1; + 3 > gnu_u1; + 3 >= gnu_u1; + 3 << gnu_u1; + 3 >> gnu_u1; + 3 && gnu_u1; /* { dg-error {invalid operands to binary \&\&} } */ + 3 || gnu_u1; /* { dg-error {invalid operands to binary \|\|} } */ + + /* Mismatched types. */ + + sve_u1 + sve_s1; /* { dg-error {invalid operands to binary \+} } */ + sve_u1 - sve_s1; /* { dg-error {invalid operands to binary -} } */ + sve_u1 * sve_s1; /* { dg-error {invalid operands to binary \*} } */ + sve_u1 / sve_s1; /* { dg-error {invalid operands to binary /} } */ + sve_u1 % sve_s1; /* { dg-error {invalid operands to binary %} } */ + sve_u1 & sve_s1; /* { dg-error {invalid operands to binary \&} } */ + sve_u1 | sve_s1; /* { dg-error {invalid operands to binary \|} } */ + sve_u1 ^ sve_s1; /* { dg-error {invalid operands to binary \^} } */ + sve_u1 == sve_s1; /* { dg-error {invalid operands to binary ==} } */ + sve_u1 != sve_s1; /* { dg-error {invalid operands to binary !=} } */ + sve_u1 <= sve_s1; /* { dg-error {invalid operands to binary <=} } */ + sve_u1 < sve_s1; /* { dg-error {invalid operands to binary <} } */ + sve_u1 > sve_s1; /* { dg-error {invalid operands to binary >} } */ + sve_u1 >= sve_s1; /* { dg-error {invalid operands to binary >=} } */ + sve_u1 << sve_s1; /* { dg-error {invalid operands to binary <<} } */ + sve_u1 >> sve_s1; /* { dg-error {invalid operands to binary >>} } */ + sve_u1 && sve_s1; /* { dg-error {used vector type where scalar is required} } */ + sve_u1 || sve_s1; /* { dg-error {used vector type where scalar is required} } */ + + sve_u1 + gnu_s1; /* { dg-error {invalid operands to binary \+} } */ + sve_u1 - gnu_s1; /* { dg-error {invalid operands to binary -} } */ + sve_u1 * gnu_s1; /* { dg-error {invalid operands to binary \*} } */ + sve_u1 / gnu_s1; /* { dg-error {invalid operands to binary /} } */ + sve_u1 % gnu_s1; /* { dg-error {invalid operands to binary %} } */ + sve_u1 & gnu_s1; /* { dg-error {invalid operands to binary \&} } */ + sve_u1 | gnu_s1; /* { dg-error {invalid operands to binary \|} } */ + sve_u1 ^ gnu_s1; /* { dg-error {invalid operands to binary \^} } */ + sve_u1 == gnu_s1; /* { dg-error {invalid operands to binary ==} } */ + sve_u1 != gnu_s1; /* { dg-error {invalid operands to binary !=} } */ + sve_u1 <= gnu_s1; /* { dg-error {invalid operands to binary <=} } */ + sve_u1 < gnu_s1; /* { dg-error {invalid operands to binary <} } */ + sve_u1 > gnu_s1; /* { dg-error {invalid operands to binary >} } */ + sve_u1 >= gnu_s1; /* { dg-error {invalid operands to binary >=} } */ + sve_u1 << gnu_s1; /* { dg-error {invalid operands to binary <<} } */ + sve_u1 >> gnu_s1; /* { dg-error {invalid operands to binary >>} } */ + sve_u1 && gnu_s1; /* { dg-error {used vector type where scalar is required} } */ + sve_u1 || gnu_s1; /* { dg-error {used vector type where scalar is required} } */ + + gnu_u1 + sve_s1; /* { dg-error {invalid operands to binary \+} } */ + gnu_u1 - sve_s1; /* { dg-error {invalid operands to binary -} } */ + gnu_u1 * sve_s1; /* { dg-error {invalid operands to binary \*} } */ + gnu_u1 / sve_s1; /* { dg-error {invalid operands to binary /} } */ + gnu_u1 % sve_s1; /* { dg-error {invalid operands to binary %} } */ + gnu_u1 & sve_s1; /* { dg-error {invalid operands to binary \&} } */ + gnu_u1 | sve_s1; /* { dg-error {invalid operands to binary \|} } */ + gnu_u1 ^ sve_s1; /* { dg-error {invalid operands to binary \^} } */ + gnu_u1 == sve_s1; /* { dg-error {invalid operands to binary ==} } */ + gnu_u1 != sve_s1; /* { dg-error {invalid operands to binary !=} } */ + gnu_u1 <= sve_s1; /* { dg-error {invalid operands to binary <=} } */ + gnu_u1 < sve_s1; /* { dg-error {invalid operands to binary <} } */ + gnu_u1 > sve_s1; /* { dg-error {invalid operands to binary >} } */ + gnu_u1 >= sve_s1; /* { dg-error {invalid operands to binary >=} } */ + gnu_u1 << sve_s1; /* { dg-error {invalid operands to binary <<} } */ + gnu_u1 >> sve_s1; /* { dg-error {invalid operands to binary >>} } */ + gnu_u1 && sve_s1; /* { dg-error {used vector type where scalar is required} } */ + gnu_u1 || sve_s1; /* { dg-error {used vector type where scalar is required} } */ + + gnu_u1 + gnu_s1; + gnu_u1 - gnu_s1; + gnu_u1 * gnu_s1; + gnu_u1 / gnu_s1; + gnu_u1 % gnu_s1; + gnu_u1 & gnu_s1; + gnu_u1 | gnu_s1; + gnu_u1 ^ gnu_s1; + gnu_u1 == gnu_s1; + gnu_u1 != gnu_s1; + gnu_u1 <= gnu_s1; + gnu_u1 < gnu_s1; + gnu_u1 > gnu_s1; + gnu_u1 >= gnu_s1; + gnu_u1 << gnu_s1; + gnu_u1 >> gnu_s1; + gnu_u1 && gnu_s1; /* { dg-error {used vector type where scalar is required} } */ + gnu_u1 || gnu_s1; /* { dg-error {used vector type where scalar is required} } */ + + /* Conditional expressions. */ + + uc ? sve_u1 : sve_u1; + uc ? gnu_u1 : sve_u1; /* { dg-error {type mismatch in conditional expression} } */ + uc ? sve_u1 : gnu_u1; /* { dg-error {type mismatch in conditional expression} } */ + uc ? gnu_u1 : gnu_u1; + + sve_u1 ? sve_u1 : sve_u1; /* { dg-error {used vector type where scalar is required} } */ + sve_u1 ? gnu_u1 : sve_u1; /* { dg-error {used vector type where scalar is required} } */ + sve_u1 ? sve_u1 : gnu_u1; /* { dg-error {used vector type where scalar is required} } */ + sve_u1 ? gnu_u1 : gnu_u1; /* { dg-error {used vector type where scalar is required} } */ + + gnu_u1 ? sve_u1 : sve_u1; /* { dg-error {used vector type where scalar is required} } */ + gnu_u1 ? gnu_u1 : sve_u1; /* { dg-error {used vector type where scalar is required} } */ + gnu_u1 ? sve_u1 : gnu_u1; /* { dg-error {used vector type where scalar is required} } */ + gnu_u1 ? gnu_u1 : gnu_u1; /* { dg-error {used vector type where scalar is required} } */ + + /* Vector built-ins. */ + + __builtin_shuffle (sve_u1, sve_u1, sve_u1); /* { dg-error {'__builtin_shuffle' last argument must be an integer vector} } */ + __builtin_shuffle (sve_u1, gnu_u1, gnu_u1); /* { dg-error {'__builtin_shuffle' arguments must be vectors} } */ + __builtin_shuffle (gnu_u1, sve_u1, gnu_u1); /* { dg-error {'__builtin_shuffle' arguments must be vectors} } */ + __builtin_shuffle (gnu_u1, gnu_u1, sve_u1); /* { dg-error {'__builtin_shuffle' last argument must be an integer vector} } */ + __builtin_shuffle (gnu_u1, gnu_u1, gnu_u1); + + __builtin_convertvector (sve_u1, svuint8_t); /* { dg-error {'__builtin_convertvector' first argument must be an integer or floating vector} } */ + __builtin_convertvector (gnu_u1, svuint8_t); /* { dg-error {'__builtin_convertvector' second argument must be an integer or floating vector type} } */ + __builtin_convertvector (sve_u1, gnu_uint8_t); /* { dg-error {'__builtin_convertvector' first argument must be an integer or floating vector} } */ + __builtin_convertvector (gnu_u1, gnu_uint8_t); +} diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/gnu_vectors_2.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/gnu_vectors_2.c new file mode 100644 index 000000000..61e6d2163 --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/gnu_vectors_2.c @@ -0,0 +1,415 @@ +/* { dg-options "-msve-vector-bits=256 -flax-vector-conversions" } */ + +#include + +typedef uint8_t gnu_uint8_t __attribute__ ((vector_size (32))); +typedef int8_t gnu_int8_t __attribute__ ((vector_size (32))); + +void +f (svuint8_t sve_u1, svint8_t sve_s1, + gnu_uint8_t gnu_u1, gnu_int8_t gnu_s1, int n, unsigned char uc) +{ + /* Initialization. */ + + svuint8_t init_sve_u1 = 0; /* { dg-error {incompatible types when initializing type 'svuint8_t' using type 'int'} } */ + svuint8_t init_sve_u2 = {}; /* { dg-error {empty scalar initializer} } */ + svuint8_t init_sve_u3 = { sve_u1 }; + svuint8_t init_sve_u4 = { gnu_u1 }; + svuint8_t init_sve_u5 = { sve_s1 }; + svuint8_t init_sve_u6 = { gnu_s1 }; + svuint8_t init_sve_u7 = { 0 }; /* { dg-error {incompatible types when initializing type 'svuint8_t' using type 'int'} } */ + svuint8_t init_sve_u8 = { sve_u1, sve_u1 }; /* { dg-warning {excess elements in scalar initializer} } */ + svuint8_t init_sve_u9 = { gnu_u1, gnu_u1 }; /* { dg-warning {excess elements in scalar initializer} } */ + + gnu_uint8_t init_gnu_u1 = 0; /* { dg-error {incompatible types when initializing type 'gnu_uint8_t'[^\n]* using type 'int'} } */ + gnu_uint8_t init_gnu_u2 = {}; + gnu_uint8_t init_gnu_u3 = { sve_u1 }; /* { dg-error {incompatible types when initializing type 'unsigned char'} } */ + gnu_uint8_t init_gnu_u4 = { gnu_u1 }; /* { dg-error {incompatible types when initializing type 'unsigned char'} } */ + gnu_uint8_t init_gnu_u5 = { sve_s1 }; /* { dg-error {incompatible types when initializing type 'unsigned char'} } */ + gnu_uint8_t init_gnu_u6 = { gnu_s1 }; /* { dg-error {incompatible types when initializing type 'unsigned char'} } */ + gnu_uint8_t init_gnu_u7 = { 0 }; + + /* Compound literals. */ + + (svuint8_t) {}; /* { dg-error {empty scalar initializer} } */ + (svuint8_t) { 0 }; /* { dg-error {incompatible types when initializing type 'svuint8_t' using type 'int'} } */ + (svuint8_t) { sve_u1 }; + (svuint8_t) { gnu_u1 }; + (svuint8_t) { sve_s1 }; + (svuint8_t) { gnu_s1 }; + + (gnu_uint8_t) {}; + (gnu_uint8_t) { 0 }; + (gnu_uint8_t) { sve_u1 }; /* { dg-error {incompatible types when initializing type 'unsigned char'} } */ + (gnu_uint8_t) { gnu_u1 }; /* { dg-error {incompatible types when initializing type 'unsigned char'} } */ + + /* Assignment. */ + + sve_u1 = 0; /* { dg-error {incompatible types when assigning to type 'svuint8_t' from type 'int'} } */ + sve_u1 = sve_u1; + sve_u1 = gnu_u1; + sve_u1 = sve_s1; + sve_u1 = gnu_s1; + + gnu_u1 = 0; /* { dg-error {incompatible types when assigning to type 'gnu_uint8_t'[^\n]* from type 'int'} } */ + gnu_u1 = sve_u1; + gnu_u1 = gnu_u1; + gnu_u1 = sve_s1; + gnu_u1 = gnu_s1; + + /* Casts. */ + + (void) sve_u1; + (svuint8_t) sve_u1; + (svuint8_t) gnu_u1; + (svuint8_t) 0; /* { dg-error {conversion to non-scalar type requested} } */ + (svuint8_t) n; /* { dg-error {conversion to non-scalar type requested} } */ + (svint8_t) sve_u1; + (svint8_t) gnu_u1; + + (void) gnu_u1; + (gnu_uint8_t) sve_u1; + (gnu_uint8_t) gnu_u1; + (gnu_uint8_t) 0; /* { dg-error {can't convert a value of type 'int' to vector type '[^']*' which has different size} } */ + (gnu_uint8_t) n; /* { dg-error {can't convert a value of type 'int' to vector type '[^']*' which has different size} } */ + (gnu_int8_t) sve_u1; + (gnu_int8_t) gnu_u1; + + /* Vector indexing. */ + + sve_u1[0]; /* { dg-error {subscripted value is neither array nor pointer} } */ + &sve_u1[0]; /* { dg-error {subscripted value is neither array nor pointer} } */ + + gnu_u1[0]; + &gnu_u1[0]; + + /* Unary operators. */ + + +sve_u1; /* { dg-error {wrong type argument to unary plus} } */ + -sve_u1; /* { dg-error {wrong type argument to unary minus} } */ + ~sve_u1; /* { dg-error {wrong type argument to bit-complement} } */ + !sve_u1; /* { dg-error {wrong type argument to unary exclamation mark} } */ + *sve_u1; /* { dg-error {invalid type argument of unary '\*'} } */ + __real sve_u1; /* { dg-error {wrong type argument to __real} } */ + __imag sve_u1; /* { dg-error {wrong type argument to __imag} } */ + ++sve_u1; /* { dg-error {wrong type argument to increment} } */ + --sve_u1; /* { dg-error {wrong type argument to decrement} } */ + sve_u1++; /* { dg-error {wrong type argument to increment} } */ + sve_u1--; /* { dg-error {wrong type argument to decrement} } */ + + +gnu_u1; + -gnu_u1; + ~gnu_u1; + !gnu_u1; /* { dg-error {wrong type argument to unary exclamation mark} } */ + *gnu_u1; /* { dg-error {invalid type argument of unary '\*'} } */ + __real gnu_u1; /* { dg-error {wrong type argument to __real} } */ + __imag gnu_u1; /* { dg-error {wrong type argument to __imag} } */ + ++gnu_u1; + --gnu_u1; + gnu_u1++; + gnu_u1--; + + /* Vector-vector binary arithmetic. */ + + sve_u1 + sve_u1; /* { dg-error {invalid operands to binary \+} } */ + sve_u1 - sve_u1; /* { dg-error {invalid operands to binary -} } */ + sve_u1 * sve_u1; /* { dg-error {invalid operands to binary \*} } */ + sve_u1 / sve_u1; /* { dg-error {invalid operands to binary /} } */ + sve_u1 % sve_u1; /* { dg-error {invalid operands to binary %} } */ + sve_u1 & sve_u1; /* { dg-error {invalid operands to binary \&} } */ + sve_u1 | sve_u1; /* { dg-error {invalid operands to binary \|} } */ + sve_u1 ^ sve_u1; /* { dg-error {invalid operands to binary \^} } */ + sve_u1 == sve_u1; /* { dg-error {invalid operands to binary ==} } */ + sve_u1 != sve_u1; /* { dg-error {invalid operands to binary !=} } */ + sve_u1 <= sve_u1; /* { dg-error {invalid operands to binary <=} } */ + sve_u1 < sve_u1; /* { dg-error {invalid operands to binary <} } */ + sve_u1 > sve_u1; /* { dg-error {invalid operands to binary >} } */ + sve_u1 >= sve_u1; /* { dg-error {invalid operands to binary >=} } */ + sve_u1 << sve_u1; /* { dg-error {invalid operands to binary <<} } */ + sve_u1 >> sve_u1; /* { dg-error {invalid operands to binary >>} } */ + sve_u1 && sve_u1; /* { dg-error {used vector type where scalar is required} } */ + sve_u1 || sve_u1; /* { dg-error {used vector type where scalar is required} } */ + + sve_u1 + gnu_u1; /* { dg-error {invalid operands to binary \+} } */ + sve_u1 - gnu_u1; /* { dg-error {invalid operands to binary -} } */ + sve_u1 * gnu_u1; /* { dg-error {invalid operands to binary \*} } */ + sve_u1 / gnu_u1; /* { dg-error {invalid operands to binary /} } */ + sve_u1 % gnu_u1; /* { dg-error {invalid operands to binary %} } */ + sve_u1 & gnu_u1; /* { dg-error {invalid operands to binary \&} } */ + sve_u1 | gnu_u1; /* { dg-error {invalid operands to binary \|} } */ + sve_u1 ^ gnu_u1; /* { dg-error {invalid operands to binary \^} } */ + sve_u1 == gnu_u1; /* { dg-error {invalid operands to binary ==} } */ + sve_u1 != gnu_u1; /* { dg-error {invalid operands to binary !=} } */ + sve_u1 <= gnu_u1; /* { dg-error {invalid operands to binary <=} } */ + sve_u1 < gnu_u1; /* { dg-error {invalid operands to binary <} } */ + sve_u1 > gnu_u1; /* { dg-error {invalid operands to binary >} } */ + sve_u1 >= gnu_u1; /* { dg-error {invalid operands to binary >=} } */ + sve_u1 << gnu_u1; /* { dg-error {invalid operands to binary <<} } */ + sve_u1 >> gnu_u1; /* { dg-error {invalid operands to binary >>} } */ + sve_u1 && gnu_u1; /* { dg-error {used vector type where scalar is required} } */ + sve_u1 || gnu_u1; /* { dg-error {used vector type where scalar is required} } */ + + gnu_u1 + sve_u1; /* { dg-error {invalid operands to binary \+} } */ + gnu_u1 - sve_u1; /* { dg-error {invalid operands to binary -} } */ + gnu_u1 * sve_u1; /* { dg-error {invalid operands to binary \*} } */ + gnu_u1 / sve_u1; /* { dg-error {invalid operands to binary /} } */ + gnu_u1 % sve_u1; /* { dg-error {invalid operands to binary %} } */ + gnu_u1 & sve_u1; /* { dg-error {invalid operands to binary \&} } */ + gnu_u1 | sve_u1; /* { dg-error {invalid operands to binary \|} } */ + gnu_u1 ^ sve_u1; /* { dg-error {invalid operands to binary \^} } */ + gnu_u1 == sve_u1; /* { dg-error {invalid operands to binary ==} } */ + gnu_u1 != sve_u1; /* { dg-error {invalid operands to binary !=} } */ + gnu_u1 <= sve_u1; /* { dg-error {invalid operands to binary <=} } */ + gnu_u1 < sve_u1; /* { dg-error {invalid operands to binary <} } */ + gnu_u1 > sve_u1; /* { dg-error {invalid operands to binary >} } */ + gnu_u1 >= sve_u1; /* { dg-error {invalid operands to binary >=} } */ + gnu_u1 << sve_u1; /* { dg-error {invalid operands to binary <<} } */ + gnu_u1 >> sve_u1; /* { dg-error {invalid operands to binary >>} } */ + gnu_u1 && sve_u1; /* { dg-error {used vector type where scalar is required} } */ + gnu_u1 || sve_u1; /* { dg-error {used vector type where scalar is required} } */ + + gnu_u1 + gnu_u1; + gnu_u1 - gnu_u1; + gnu_u1 * gnu_u1; + gnu_u1 / gnu_u1; + gnu_u1 % gnu_u1; + gnu_u1 & gnu_u1; + gnu_u1 | gnu_u1; + gnu_u1 ^ gnu_u1; + gnu_u1 == gnu_u1; + gnu_u1 != gnu_u1; + gnu_u1 <= gnu_u1; + gnu_u1 < gnu_u1; + gnu_u1 > gnu_u1; + gnu_u1 >= gnu_u1; + gnu_u1 << gnu_u1; + gnu_u1 >> gnu_u1; + gnu_u1 && gnu_u1; /* { dg-error {used vector type where scalar is required} } */ + gnu_u1 || gnu_u1; /* { dg-error {used vector type where scalar is required} } */ + + /* Vector-scalar binary arithmetic. */ + + sve_u1 + 2; /* { dg-error {invalid operands to binary \+} } */ + sve_u1 - 2; /* { dg-error {invalid operands to binary -} } */ + sve_u1 * 2; /* { dg-error {invalid operands to binary \*} } */ + sve_u1 / 2; /* { dg-error {invalid operands to binary /} } */ + sve_u1 % 2; /* { dg-error {invalid operands to binary %} } */ + sve_u1 & 2; /* { dg-error {invalid operands to binary \&} } */ + sve_u1 | 2; /* { dg-error {invalid operands to binary \|} } */ + sve_u1 ^ 2; /* { dg-error {invalid operands to binary \^} } */ + sve_u1 == 2; /* { dg-error {invalid operands to binary ==} } */ + sve_u1 != 2; /* { dg-error {invalid operands to binary !=} } */ + sve_u1 <= 2; /* { dg-error {invalid operands to binary <=} } */ + sve_u1 < 2; /* { dg-error {invalid operands to binary <} } */ + sve_u1 > 2; /* { dg-error {invalid operands to binary >} } */ + sve_u1 >= 2; /* { dg-error {invalid operands to binary >=} } */ + sve_u1 << 2; /* { dg-error {invalid operands to binary <<} } */ + sve_u1 >> 2; /* { dg-error {invalid operands to binary >>} } */ + sve_u1 && 2; /* { dg-error {used vector type where scalar is required} } */ + sve_u1 || 2; /* { dg-error {used vector type where scalar is required} } */ + + sve_u1 + uc; /* { dg-error {invalid operands to binary \+} } */ + sve_u1 - uc; /* { dg-error {invalid operands to binary -} } */ + sve_u1 * uc; /* { dg-error {invalid operands to binary \*} } */ + sve_u1 / uc; /* { dg-error {invalid operands to binary /} } */ + sve_u1 % uc; /* { dg-error {invalid operands to binary %} } */ + sve_u1 & uc; /* { dg-error {invalid operands to binary \&} } */ + sve_u1 | uc; /* { dg-error {invalid operands to binary \|} } */ + sve_u1 ^ uc; /* { dg-error {invalid operands to binary \^} } */ + sve_u1 == uc; /* { dg-error {invalid operands to binary ==} } */ + sve_u1 != uc; /* { dg-error {invalid operands to binary !=} } */ + sve_u1 <= uc; /* { dg-error {invalid operands to binary <=} } */ + sve_u1 < uc; /* { dg-error {invalid operands to binary <} } */ + sve_u1 > uc; /* { dg-error {invalid operands to binary >} } */ + sve_u1 >= uc; /* { dg-error {invalid operands to binary >=} } */ + sve_u1 << uc; /* { dg-error {invalid operands to binary <<} } */ + sve_u1 >> uc; /* { dg-error {invalid operands to binary >>} } */ + sve_u1 && uc; /* { dg-error {used vector type where scalar is required} } */ + sve_u1 || uc; /* { dg-error {used vector type where scalar is required} } */ + + gnu_u1 + 2; + gnu_u1 - 2; + gnu_u1 * 2; + gnu_u1 / 2; + gnu_u1 % 2; + gnu_u1 & 2; + gnu_u1 | 2; + gnu_u1 ^ 2; + gnu_u1 == 2; + gnu_u1 != 2; + gnu_u1 <= 2; + gnu_u1 < 2; + gnu_u1 > 2; + gnu_u1 >= 2; + gnu_u1 << 2; + gnu_u1 >> 2; + gnu_u1 && 2; /* { dg-error {used vector type where scalar is required} } */ + gnu_u1 || 2; /* { dg-error {used vector type where scalar is required} } */ + + gnu_u1 + uc; + gnu_u1 - uc; + gnu_u1 * uc; + gnu_u1 / uc; + gnu_u1 % uc; + gnu_u1 & uc; + gnu_u1 | uc; + gnu_u1 ^ uc; + gnu_u1 == uc; + gnu_u1 != uc; + gnu_u1 <= uc; + gnu_u1 < uc; + gnu_u1 > uc; + gnu_u1 >= uc; + gnu_u1 << uc; + gnu_u1 >> uc; + gnu_u1 && uc; /* { dg-error {used vector type where scalar is required} } */ + gnu_u1 || uc; /* { dg-error {used vector type where scalar is required} } */ + + /* Scalar-vector binary arithmetic. */ + + 3 + sve_u1; /* { dg-error {invalid operands to binary \+} } */ + 3 - sve_u1; /* { dg-error {invalid operands to binary -} } */ + 3 * sve_u1; /* { dg-error {invalid operands to binary \*} } */ + 3 / sve_u1; /* { dg-error {invalid operands to binary /} } */ + 3 % sve_u1; /* { dg-error {invalid operands to binary %} } */ + 3 & sve_u1; /* { dg-error {invalid operands to binary \&} } */ + 3 | sve_u1; /* { dg-error {invalid operands to binary \|} } */ + 3 ^ sve_u1; /* { dg-error {invalid operands to binary \^} } */ + 3 == sve_u1; /* { dg-error {invalid operands to binary ==} } */ + 3 != sve_u1; /* { dg-error {invalid operands to binary !=} } */ + 3 <= sve_u1; /* { dg-error {invalid operands to binary <=} } */ + 3 < sve_u1; /* { dg-error {invalid operands to binary <} } */ + 3 > sve_u1; /* { dg-error {invalid operands to binary >} } */ + 3 >= sve_u1; /* { dg-error {invalid operands to binary >=} } */ + 3 << sve_u1; /* { dg-error {invalid operands to binary <<} } */ + 3 >> sve_u1; /* { dg-error {invalid operands to binary >>} } */ + 3 && sve_u1; /* { dg-error {invalid operands to binary \&\&} } */ + 3 || sve_u1; /* { dg-error {invalid operands to binary \|\|} } */ + + 3 + gnu_u1; + 3 - gnu_u1; + 3 * gnu_u1; + 3 / gnu_u1; + 3 % gnu_u1; + 3 & gnu_u1; + 3 | gnu_u1; + 3 ^ gnu_u1; + 3 == gnu_u1; + 3 != gnu_u1; + 3 <= gnu_u1; + 3 < gnu_u1; + 3 > gnu_u1; + 3 >= gnu_u1; + 3 << gnu_u1; + 3 >> gnu_u1; + 3 && gnu_u1; /* { dg-error {invalid operands to binary \&\&} } */ + 3 || gnu_u1; /* { dg-error {invalid operands to binary \|\|} } */ + + /* Mismatched types. */ + + sve_u1 + sve_s1; /* { dg-error {invalid operands to binary \+} } */ + sve_u1 - sve_s1; /* { dg-error {invalid operands to binary -} } */ + sve_u1 * sve_s1; /* { dg-error {invalid operands to binary \*} } */ + sve_u1 / sve_s1; /* { dg-error {invalid operands to binary /} } */ + sve_u1 % sve_s1; /* { dg-error {invalid operands to binary %} } */ + sve_u1 & sve_s1; /* { dg-error {invalid operands to binary \&} } */ + sve_u1 | sve_s1; /* { dg-error {invalid operands to binary \|} } */ + sve_u1 ^ sve_s1; /* { dg-error {invalid operands to binary \^} } */ + sve_u1 == sve_s1; /* { dg-error {invalid operands to binary ==} } */ + sve_u1 != sve_s1; /* { dg-error {invalid operands to binary !=} } */ + sve_u1 <= sve_s1; /* { dg-error {invalid operands to binary <=} } */ + sve_u1 < sve_s1; /* { dg-error {invalid operands to binary <} } */ + sve_u1 > sve_s1; /* { dg-error {invalid operands to binary >} } */ + sve_u1 >= sve_s1; /* { dg-error {invalid operands to binary >=} } */ + sve_u1 << sve_s1; /* { dg-error {invalid operands to binary <<} } */ + sve_u1 >> sve_s1; /* { dg-error {invalid operands to binary >>} } */ + sve_u1 && sve_s1; /* { dg-error {used vector type where scalar is required} } */ + sve_u1 || sve_s1; /* { dg-error {used vector type where scalar is required} } */ + + sve_u1 + gnu_s1; /* { dg-error {invalid operands to binary \+} } */ + sve_u1 - gnu_s1; /* { dg-error {invalid operands to binary -} } */ + sve_u1 * gnu_s1; /* { dg-error {invalid operands to binary \*} } */ + sve_u1 / gnu_s1; /* { dg-error {invalid operands to binary /} } */ + sve_u1 % gnu_s1; /* { dg-error {invalid operands to binary %} } */ + sve_u1 & gnu_s1; /* { dg-error {invalid operands to binary \&} } */ + sve_u1 | gnu_s1; /* { dg-error {invalid operands to binary \|} } */ + sve_u1 ^ gnu_s1; /* { dg-error {invalid operands to binary \^} } */ + sve_u1 == gnu_s1; /* { dg-error {invalid operands to binary ==} } */ + sve_u1 != gnu_s1; /* { dg-error {invalid operands to binary !=} } */ + sve_u1 <= gnu_s1; /* { dg-error {invalid operands to binary <=} } */ + sve_u1 < gnu_s1; /* { dg-error {invalid operands to binary <} } */ + sve_u1 > gnu_s1; /* { dg-error {invalid operands to binary >} } */ + sve_u1 >= gnu_s1; /* { dg-error {invalid operands to binary >=} } */ + sve_u1 << gnu_s1; /* { dg-error {invalid operands to binary <<} } */ + sve_u1 >> gnu_s1; /* { dg-error {invalid operands to binary >>} } */ + sve_u1 && gnu_s1; /* { dg-error {used vector type where scalar is required} } */ + sve_u1 || gnu_s1; /* { dg-error {used vector type where scalar is required} } */ + + gnu_u1 + sve_s1; /* { dg-error {invalid operands to binary \+} } */ + gnu_u1 - sve_s1; /* { dg-error {invalid operands to binary -} } */ + gnu_u1 * sve_s1; /* { dg-error {invalid operands to binary \*} } */ + gnu_u1 / sve_s1; /* { dg-error {invalid operands to binary /} } */ + gnu_u1 % sve_s1; /* { dg-error {invalid operands to binary %} } */ + gnu_u1 & sve_s1; /* { dg-error {invalid operands to binary \&} } */ + gnu_u1 | sve_s1; /* { dg-error {invalid operands to binary \|} } */ + gnu_u1 ^ sve_s1; /* { dg-error {invalid operands to binary \^} } */ + gnu_u1 == sve_s1; /* { dg-error {invalid operands to binary ==} } */ + gnu_u1 != sve_s1; /* { dg-error {invalid operands to binary !=} } */ + gnu_u1 <= sve_s1; /* { dg-error {invalid operands to binary <=} } */ + gnu_u1 < sve_s1; /* { dg-error {invalid operands to binary <} } */ + gnu_u1 > sve_s1; /* { dg-error {invalid operands to binary >} } */ + gnu_u1 >= sve_s1; /* { dg-error {invalid operands to binary >=} } */ + gnu_u1 << sve_s1; /* { dg-error {invalid operands to binary <<} } */ + gnu_u1 >> sve_s1; /* { dg-error {invalid operands to binary >>} } */ + gnu_u1 && sve_s1; /* { dg-error {used vector type where scalar is required} } */ + gnu_u1 || sve_s1; /* { dg-error {used vector type where scalar is required} } */ + + gnu_u1 + gnu_s1; + gnu_u1 - gnu_s1; + gnu_u1 * gnu_s1; + gnu_u1 / gnu_s1; + gnu_u1 % gnu_s1; + gnu_u1 & gnu_s1; + gnu_u1 | gnu_s1; + gnu_u1 ^ gnu_s1; + gnu_u1 == gnu_s1; + gnu_u1 != gnu_s1; + gnu_u1 <= gnu_s1; + gnu_u1 < gnu_s1; + gnu_u1 > gnu_s1; + gnu_u1 >= gnu_s1; + gnu_u1 << gnu_s1; + gnu_u1 >> gnu_s1; + gnu_u1 && gnu_s1; /* { dg-error {used vector type where scalar is required} } */ + gnu_u1 || gnu_s1; /* { dg-error {used vector type where scalar is required} } */ + + /* Conditional expressions. */ + + uc ? sve_u1 : sve_u1; + uc ? gnu_u1 : sve_u1; /* { dg-error {type mismatch in conditional expression} } */ + uc ? sve_u1 : gnu_u1; /* { dg-error {type mismatch in conditional expression} } */ + uc ? gnu_u1 : gnu_u1; + + sve_u1 ? sve_u1 : sve_u1; /* { dg-error {used vector type where scalar is required} } */ + sve_u1 ? gnu_u1 : sve_u1; /* { dg-error {used vector type where scalar is required} } */ + sve_u1 ? sve_u1 : gnu_u1; /* { dg-error {used vector type where scalar is required} } */ + sve_u1 ? gnu_u1 : gnu_u1; /* { dg-error {used vector type where scalar is required} } */ + + gnu_u1 ? sve_u1 : sve_u1; /* { dg-error {used vector type where scalar is required} } */ + gnu_u1 ? gnu_u1 : sve_u1; /* { dg-error {used vector type where scalar is required} } */ + gnu_u1 ? sve_u1 : gnu_u1; /* { dg-error {used vector type where scalar is required} } */ + gnu_u1 ? gnu_u1 : gnu_u1; /* { dg-error {used vector type where scalar is required} } */ + + /* Vector built-ins. */ + + __builtin_shuffle (sve_u1, sve_u1, sve_u1); /* { dg-error {'__builtin_shuffle' last argument must be an integer vector} } */ + __builtin_shuffle (sve_u1, gnu_u1, gnu_u1); /* { dg-error {'__builtin_shuffle' arguments must be vectors} } */ + __builtin_shuffle (gnu_u1, sve_u1, gnu_u1); /* { dg-error {'__builtin_shuffle' arguments must be vectors} } */ + __builtin_shuffle (gnu_u1, gnu_u1, sve_u1); /* { dg-error {'__builtin_shuffle' last argument must be an integer vector} } */ + __builtin_shuffle (gnu_u1, gnu_u1, gnu_u1); + + __builtin_convertvector (sve_u1, svuint8_t); /* { dg-error {'__builtin_convertvector' first argument must be an integer or floating vector} } */ + __builtin_convertvector (gnu_u1, svuint8_t); /* { dg-error {'__builtin_convertvector' second argument must be an integer or floating vector type} } */ + __builtin_convertvector (sve_u1, gnu_uint8_t); /* { dg-error {'__builtin_convertvector' first argument must be an integer or floating vector} } */ + __builtin_convertvector (gnu_u1, gnu_uint8_t); +} diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/sizeless-1.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/sizeless-1.c new file mode 100644 index 000000000..ec892a3fc --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/sizeless-1.c @@ -0,0 +1,217 @@ +/* { dg-options "-std=gnu99" } */ + +#include + +typedef signed char int8x32_t __attribute__((__vector_size__ (32))); + +/* Sizeless objects with global scope. */ + +svint8_t global_sve_sc; /* { dg-error {SVE type 'svint8_t' does not have a fixed size} } */ +static svint8_t local_sve_sc; /* { dg-error {SVE type 'svint8_t' does not have a fixed size} } */ +extern svint8_t extern_sve_sc; /* { dg-error {SVE type 'svint8_t' does not have a fixed size} } */ +__thread svint8_t tls_sve_sc; /* { dg-error {variables of type 'svint8_t' cannot have thread-local storage duration} } */ +_Atomic svint8_t atomic_sve_sc; /* { dg-error {SVE type 'svint8_t' does not have a fixed size} } */ + +/* Sizeless arrays. */ + +typedef svint8_t array_type[2]; /* { dg-error {array elements cannot have SVE type 'svint8_t'} } */ +extern svint8_t extern_array[]; /* { dg-error {array elements cannot have SVE type 'svint8_t'} } */ + +/* Sizeless fields. */ + +struct struct1 { + svint8_t a; /* { dg-error {fields cannot have SVE type 'svint8_t'} } */ +}; + +union union1 { + svint8_t a; /* { dg-error {fields cannot have SVE type 'svint8_t'} } */ +}; + +/* Pointers to sizeless types. */ + +svint8_t *global_sve_sc_ptr; +svint8_t *invalid_sve_sc_ptr = &(svint8_t) { *global_sve_sc_ptr }; /* { dg-error {initializer element is not constant} } */ + /* { dg-error {SVE type 'svint8_t' does not have a fixed size} "" { target *-*-* } .-1 } */ + +/* Sizeless arguments and return values. */ + +void ext_consume_sve_sc (svint8_t); +void ext_consume_varargs (int, ...); +svint8_t ext_produce_sve_sc (); + +/* Main tests for statements and expressions. */ + +void +statements (int n) +{ + /* Local declarations. */ + + unsigned char va __attribute__((__vector_size__(2))); + svint8_t sve_sc1, sve_sc2; + _Atomic svint8_t atomic_sve_sc; + int8x32_t gnu_sc1; + svint16_t sve_sh1; + static svint8_t local_static_sve_sc; /* { dg-error {SVE type 'svint8_t' does not have a fixed size} } */ + + /* Layout queries. */ + + sizeof (svint8_t); /* { dg-error {SVE type 'svint8_t' does not have a fixed size} } */ + sizeof (sve_sc1); /* { dg-error {SVE type 'svint8_t' does not have a fixed size} } */ + sizeof (ext_produce_sve_sc ()); /* { dg-error {SVE type 'svint8_t' does not have a fixed size} } */ + _Alignof (svint8_t); /* { dg-error {SVE type 'svint8_t' does not have a defined alignment} } */ + _Alignof (sve_sc1); /* { dg-error {SVE type 'svint8_t' does not have a defined alignment} } */ + _Alignof (ext_produce_sve_sc ()); /* { dg-error {SVE type 'svint8_t' does not have a defined alignment} } */ + + /* Initialization. */ + + svint8_t init_sve_sc1 = sve_sc1; + svint8_t init_sve_sc2 = sve_sh1; /* { dg-error {incompatible types when initializing type 'svint8_t' using type 'svint16_t'} } */ + svint8_t init_sve_sc3 = {}; /* { dg-error {empty scalar initializer} } */ + + int initi_a = sve_sc1; /* { dg-error {incompatible types when initializing type 'int' using type 'svint8_t'} } */ + int initi_b = { sve_sc1 }; /* { dg-error {incompatible types when initializing type 'int' using type 'svint8_t'} } */ + + /* Compound literals. */ + + (svint8_t) {}; /* { dg-error {empty scalar initializer} } */ + (svint8_t) { sve_sc1 }; + + (int) { sve_sc1 }; /* { dg-error {incompatible types when initializing type 'int' using type 'svint8_t'} } */ + + /* Arrays. */ + + svint8_t array[2]; /* { dg-error {array elements cannot have SVE type 'svint8_t'} } */ + svint8_t zero_length_array[0]; /* { dg-error {array elements cannot have SVE type 'svint8_t'} } */ + svint8_t empty_init_array[] = {}; /* { dg-error {array elements cannot have SVE type 'svint8_t'} } */ + /* { dg-error {empty scalar initializer} "" { target *-*-* } .-1 } */ + typedef svint8_t vla_type[n]; /* { dg-error {array elements cannot have SVE type 'svint8_t'} } */ + + /* Assignment. */ + + n = sve_sc1; /* { dg-error {incompatible types when assigning to type 'int' from type 'svint8_t'} } */ + + sve_sc1 = 0; /* { dg-error {incompatible types when assigning to type 'svint8_t' from type 'int'} } */ + sve_sc1 = sve_sc2; + sve_sc1 = sve_sh1; /* { dg-error {incompatible types when assigning to type 'svint8_t' from type 'svint16_t'} } */ + + /* Casting. */ + + (void) sve_sc1; + (svint8_t) sve_sc1; + + /* Addressing and dereferencing. */ + + svint8_t *sve_sc_ptr = &sve_sc1; + int8x32_t *gnu_sc_ptr = &gnu_sc1; + sve_sc1 = *sve_sc_ptr; + + /* Pointer assignment. */ + + gnu_sc_ptr = sve_sc_ptr; /* { dg-warning {assignment to [^\n]* from incompatible pointer type} } */ + sve_sc_ptr = gnu_sc_ptr; /* { dg-warning {assignment to [^\n]* from incompatible pointer type} } */ + + /* Pointer arithmetic. */ + + ++sve_sc_ptr; /* { dg-error {arithmetic on pointer to SVE type 'svint8_t'} } */ + --sve_sc_ptr; /* { dg-error {arithmetic on pointer to SVE type 'svint8_t'} } */ + sve_sc_ptr++; /* { dg-error {arithmetic on pointer to SVE type 'svint8_t'} } */ + sve_sc_ptr--; /* { dg-error {arithmetic on pointer to SVE type 'svint8_t'} } */ + sve_sc_ptr += 0; /* { dg-error {arithmetic on pointer to SVE type 'svint8_t'} } */ + sve_sc_ptr += 1; /* { dg-error {arithmetic on pointer to SVE type 'svint8_t'} } */ + sve_sc_ptr -= 0; /* { dg-error {arithmetic on pointer to SVE type 'svint8_t'} } */ + sve_sc_ptr -= 1; /* { dg-error {arithmetic on pointer to SVE type 'svint8_t'} } */ + sve_sc_ptr - sve_sc_ptr; /* { dg-error {arithmetic on pointer to SVE type 'svint8_t'} } */ + gnu_sc_ptr - sve_sc_ptr; /* { dg-error {invalid operands to binary -} } */ + sve_sc_ptr - gnu_sc_ptr; /* { dg-error {invalid operands to binary -} } */ + sve_sc1 = sve_sc_ptr[0]; /* { dg-error {arithmetic on pointer to SVE type 'svint8_t'} } */ + sve_sc1 = sve_sc_ptr[1]; /* { dg-error {arithmetic on pointer to SVE type 'svint8_t'} } */ + + /* Pointer comparison. */ + + sve_sc_ptr == &sve_sc1; + sve_sc_ptr != &sve_sc1; + sve_sc_ptr < &sve_sc1; + sve_sc_ptr <= &sve_sc1; + sve_sc_ptr > &sve_sc1; + sve_sc_ptr >= &sve_sc1; + gnu_sc_ptr == sve_sc_ptr; /* { dg-warning {comparison of distinct pointer types lacks a cast} } */ + gnu_sc_ptr != sve_sc_ptr; /* { dg-warning {comparison of distinct pointer types lacks a cast} } */ + gnu_sc_ptr < sve_sc_ptr; /* { dg-warning {comparison of distinct pointer types lacks a cast} } */ + gnu_sc_ptr <= sve_sc_ptr; /* { dg-warning {comparison of distinct pointer types lacks a cast} } */ + gnu_sc_ptr > sve_sc_ptr; /* { dg-warning {comparison of distinct pointer types lacks a cast} } */ + gnu_sc_ptr >= sve_sc_ptr; /* { dg-warning {comparison of distinct pointer types lacks a cast} } */ + sve_sc_ptr == gnu_sc_ptr; /* { dg-warning {comparison of distinct pointer types lacks a cast} } */ + sve_sc_ptr != gnu_sc_ptr; /* { dg-warning {comparison of distinct pointer types lacks a cast} } */ + sve_sc_ptr < gnu_sc_ptr; /* { dg-warning {comparison of distinct pointer types lacks a cast} } */ + sve_sc_ptr <= gnu_sc_ptr; /* { dg-warning {comparison of distinct pointer types lacks a cast} } */ + sve_sc_ptr > gnu_sc_ptr; /* { dg-warning {comparison of distinct pointer types lacks a cast} } */ + sve_sc_ptr >= gnu_sc_ptr; /* { dg-warning {comparison of distinct pointer types lacks a cast} } */ + + /* Conditional expressions. */ + + 0 ? sve_sc1 : sve_sc1; + 0 ? sve_sc1 : sve_sh1; /* { dg-error {type mismatch in conditional expression} } */ + 0 ? sve_sc1 : 0; /* { dg-error {type mismatch in conditional expression} } */ + 0 ? 0 : sve_sc1; /* { dg-error {type mismatch in conditional expression} } */ + 0 ?: sve_sc1; /* { dg-error {type mismatch in conditional expression} } */ + 0 ? sve_sc_ptr : sve_sc_ptr; + 0 ? sve_sc_ptr : gnu_sc_ptr; /* { dg-warning {pointer type mismatch in conditional expression} } */ + 0 ? gnu_sc_ptr : sve_sc_ptr; /* { dg-warning {pointer type mismatch in conditional expression} } */ + + /* Generic associations. */ + + _Generic (sve_sc1, default: 100); + _Generic (1, svint8_t: 10, default: 20); + + /* Function arguments. */ + + ext_consume_sve_sc (sve_sc1); + ext_consume_sve_sc (sve_sh1); /* { dg-error {incompatible type for argument 1 of 'ext_consume_sve_sc'} } */ + ext_consume_varargs (sve_sc1); /* { dg-error {incompatible type for argument 1 of 'ext_consume_varargs'} } */ + ext_consume_varargs (1, sve_sc1); + + /* Function returns. */ + + ext_produce_sve_sc (); + sve_sc1 = ext_produce_sve_sc (); + sve_sh1 = ext_produce_sve_sc (); /* { dg-error {incompatible types when assigning to type 'svint16_t' from type 'svint8_t'} } */ + + /* Varargs processing. */ + + __builtin_va_list valist; + __builtin_va_arg (valist, svint8_t); + + /* Statement expressions. */ + + ({ sve_sc1; }); + ({ svint8_t another_sve_sc = *sve_sc_ptr; another_sve_sc; }); +} + +/* Function parameters in definitions. */ + +void +old_style (input_sve_sc) /* { dg-error {SVE type 'svint8_t' cannot be passed to an unprototyped function} } */ + svint8_t input_sve_sc; +{ + svint8_t sve_sc1 = input_sve_sc; +} + +void +new_style_param (svint8_t input_sve_sc) +{ + svint8_t sve_sc1 = input_sve_sc; +} + +/* Function return values in definitions. */ + +svint8_t +good_return_sve_sc (svint8_t param) +{ + return param; +} + +svint8_t +bad_return_sve_sc (svint16_t param) +{ + return param; /* { dg-error {incompatible types when returning type 'svint16_t' but 'svint8_t' was expected} } */ +} diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/sizeless-2.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/sizeless-2.c new file mode 100644 index 000000000..717439300 --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/sizeless-2.c @@ -0,0 +1,217 @@ +/* { dg-options "-std=gnu99 -msve-vector-bits=256" } */ + +#include + +typedef signed char int8x32_t __attribute__((__vector_size__ (32))); + +/* Sizeless objects with global scope. */ + +svint8_t global_sve_sc; /* { dg-error {SVE type 'svint8_t' does not have a fixed size} } */ +static svint8_t local_sve_sc; /* { dg-error {SVE type 'svint8_t' does not have a fixed size} } */ +extern svint8_t extern_sve_sc; /* { dg-error {SVE type 'svint8_t' does not have a fixed size} } */ +__thread svint8_t tls_sve_sc; /* { dg-error {variables of type 'svint8_t' cannot have thread-local storage duration} } */ +_Atomic svint8_t atomic_sve_sc; /* { dg-error {SVE type 'svint8_t' does not have a fixed size} } */ + +/* Sizeless arrays. */ + +typedef svint8_t array_type[2]; /* { dg-error {array elements cannot have SVE type 'svint8_t'} } */ +extern svint8_t extern_array[]; /* { dg-error {array elements cannot have SVE type 'svint8_t'} } */ + +/* Sizeless fields. */ + +struct struct1 { + svint8_t a; /* { dg-error {fields cannot have SVE type 'svint8_t'} } */ +}; + +union union1 { + svint8_t a; /* { dg-error {fields cannot have SVE type 'svint8_t'} } */ +}; + +/* Pointers to sizeless types. */ + +svint8_t *global_sve_sc_ptr; +svint8_t *invalid_sve_sc_ptr = &(svint8_t) { *global_sve_sc_ptr }; /* { dg-error {initializer element is not constant} } */ + /* { dg-error {SVE type 'svint8_t' does not have a fixed size} "" { target *-*-* } .-1 } */ + +/* Sizeless arguments and return values. */ + +void ext_consume_sve_sc (svint8_t); +void ext_consume_varargs (int, ...); +svint8_t ext_produce_sve_sc (); + +/* Main tests for statements and expressions. */ + +void +statements (int n) +{ + /* Local declarations. */ + + unsigned char va __attribute__((__vector_size__(2))); + svint8_t sve_sc1, sve_sc2; + _Atomic svint8_t atomic_sve_sc; + int8x32_t gnu_sc1; + svint16_t sve_sh1; + static svint8_t local_static_sve_sc; /* { dg-error {SVE type 'svint8_t' does not have a fixed size} } */ + + /* Layout queries. */ + + sizeof (svint8_t); /* { dg-error {SVE type 'svint8_t' does not have a fixed size} } */ + sizeof (sve_sc1); /* { dg-error {SVE type 'svint8_t' does not have a fixed size} } */ + sizeof (ext_produce_sve_sc ()); /* { dg-error {SVE type 'svint8_t' does not have a fixed size} } */ + _Alignof (svint8_t); /* { dg-error {SVE type 'svint8_t' does not have a defined alignment} } */ + _Alignof (sve_sc1); /* { dg-error {SVE type 'svint8_t' does not have a defined alignment} } */ + _Alignof (ext_produce_sve_sc ()); /* { dg-error {SVE type 'svint8_t' does not have a defined alignment} } */ + + /* Initialization. */ + + svint8_t init_sve_sc1 = sve_sc1; + svint8_t init_sve_sc2 = sve_sh1; /* { dg-error {incompatible types when initializing type 'svint8_t' using type 'svint16_t'} } */ + svint8_t init_sve_sc3 = {}; /* { dg-error {empty scalar initializer} } */ + + int initi_a = sve_sc1; /* { dg-error {incompatible types when initializing type 'int' using type 'svint8_t'} } */ + int initi_b = { sve_sc1 }; /* { dg-error {incompatible types when initializing type 'int' using type 'svint8_t'} } */ + + /* Compound literals. */ + + (svint8_t) {}; /* { dg-error {empty scalar initializer} } */ + (svint8_t) { sve_sc1 }; + + (int) { sve_sc1 }; /* { dg-error {incompatible types when initializing type 'int' using type 'svint8_t'} } */ + + /* Arrays. */ + + svint8_t array[2]; /* { dg-error {array elements cannot have SVE type 'svint8_t'} } */ + svint8_t zero_length_array[0]; /* { dg-error {array elements cannot have SVE type 'svint8_t'} } */ + svint8_t empty_init_array[] = {}; /* { dg-error {array elements cannot have SVE type 'svint8_t'} } */ + /* { dg-error {empty scalar initializer} "" { target *-*-* } .-1 } */ + typedef svint8_t vla_type[n]; /* { dg-error {array elements cannot have SVE type 'svint8_t'} } */ + + /* Assignment. */ + + n = sve_sc1; /* { dg-error {incompatible types when assigning to type 'int' from type 'svint8_t'} } */ + + sve_sc1 = 0; /* { dg-error {incompatible types when assigning to type 'svint8_t' from type 'int'} } */ + sve_sc1 = sve_sc2; + sve_sc1 = sve_sh1; /* { dg-error {incompatible types when assigning to type 'svint8_t' from type 'svint16_t'} } */ + + /* Casting. */ + + (void) sve_sc1; + (svint8_t) sve_sc1; + + /* Addressing and dereferencing. */ + + svint8_t *sve_sc_ptr = &sve_sc1; + int8x32_t *gnu_sc_ptr = &gnu_sc1; + sve_sc1 = *sve_sc_ptr; + + /* Pointer assignment. */ + + gnu_sc_ptr = sve_sc_ptr; + sve_sc_ptr = gnu_sc_ptr; + + /* Pointer arithmetic. */ + + ++sve_sc_ptr; /* { dg-error {arithmetic on pointer to SVE type 'svint8_t'} } */ + --sve_sc_ptr; /* { dg-error {arithmetic on pointer to SVE type 'svint8_t'} } */ + sve_sc_ptr++; /* { dg-error {arithmetic on pointer to SVE type 'svint8_t'} } */ + sve_sc_ptr--; /* { dg-error {arithmetic on pointer to SVE type 'svint8_t'} } */ + sve_sc_ptr += 0; /* { dg-error {arithmetic on pointer to SVE type 'svint8_t'} } */ + sve_sc_ptr += 1; /* { dg-error {arithmetic on pointer to SVE type 'svint8_t'} } */ + sve_sc_ptr -= 0; /* { dg-error {arithmetic on pointer to SVE type 'svint8_t'} } */ + sve_sc_ptr -= 1; /* { dg-error {arithmetic on pointer to SVE type 'svint8_t'} } */ + sve_sc_ptr - sve_sc_ptr; /* { dg-error {arithmetic on pointer to SVE type 'svint8_t'} } */ + gnu_sc_ptr - sve_sc_ptr; /* { dg-error {arithmetic on pointer to SVE type 'svint8_t'} } */ + sve_sc_ptr - gnu_sc_ptr; /* { dg-error {arithmetic on pointer to SVE type 'svint8_t'} } */ + sve_sc1 = sve_sc_ptr[0]; /* { dg-error {arithmetic on pointer to SVE type 'svint8_t'} } */ + sve_sc1 = sve_sc_ptr[1]; /* { dg-error {arithmetic on pointer to SVE type 'svint8_t'} } */ + + /* Pointer comparison. */ + + sve_sc_ptr == &sve_sc1; + sve_sc_ptr != &sve_sc1; + sve_sc_ptr < &sve_sc1; + sve_sc_ptr <= &sve_sc1; + sve_sc_ptr > &sve_sc1; + sve_sc_ptr >= &sve_sc1; + gnu_sc_ptr == sve_sc_ptr; + gnu_sc_ptr != sve_sc_ptr; + gnu_sc_ptr < sve_sc_ptr; + gnu_sc_ptr <= sve_sc_ptr; + gnu_sc_ptr > sve_sc_ptr; + gnu_sc_ptr >= sve_sc_ptr; + sve_sc_ptr == gnu_sc_ptr; + sve_sc_ptr != gnu_sc_ptr; + sve_sc_ptr < gnu_sc_ptr; + sve_sc_ptr <= gnu_sc_ptr; + sve_sc_ptr > gnu_sc_ptr; + sve_sc_ptr >= gnu_sc_ptr; + + /* Conditional expressions. */ + + 0 ? sve_sc1 : sve_sc1; + 0 ? sve_sc1 : sve_sh1; /* { dg-error {type mismatch in conditional expression} } */ + 0 ? sve_sc1 : 0; /* { dg-error {type mismatch in conditional expression} } */ + 0 ? 0 : sve_sc1; /* { dg-error {type mismatch in conditional expression} } */ + 0 ?: sve_sc1; /* { dg-error {type mismatch in conditional expression} } */ + 0 ? sve_sc_ptr : sve_sc_ptr; + 0 ? sve_sc_ptr : gnu_sc_ptr; + 0 ? gnu_sc_ptr : sve_sc_ptr; + + /* Generic associations. */ + + _Generic (sve_sc1, default: 100); + _Generic (1, svint8_t: 10, default: 20); + + /* Function arguments. */ + + ext_consume_sve_sc (sve_sc1); + ext_consume_sve_sc (sve_sh1); /* { dg-error {incompatible type for argument 1 of 'ext_consume_sve_sc'} } */ + ext_consume_varargs (sve_sc1); /* { dg-error {incompatible type for argument 1 of 'ext_consume_varargs'} } */ + ext_consume_varargs (1, sve_sc1); + + /* Function returns. */ + + ext_produce_sve_sc (); + sve_sc1 = ext_produce_sve_sc (); + sve_sh1 = ext_produce_sve_sc (); /* { dg-error {incompatible types when assigning to type 'svint16_t' from type 'svint8_t'} } */ + + /* Varargs processing. */ + + __builtin_va_list valist; + __builtin_va_arg (valist, svint8_t); + + /* Statement expressions. */ + + ({ sve_sc1; }); + ({ svint8_t another_sve_sc = *sve_sc_ptr; another_sve_sc; }); +} + +/* Function parameters in definitions. */ + +void +old_style (input_sve_sc) /* { dg-error {SVE type 'svint8_t' cannot be passed to an unprototyped function} } */ + svint8_t input_sve_sc; +{ + svint8_t sve_sc1 = input_sve_sc; +} + +void +new_style_param (svint8_t input_sve_sc) +{ + svint8_t sve_sc1 = input_sve_sc; +} + +/* Function return values in definitions. */ + +svint8_t +good_return_sve_sc (svint8_t param) +{ + return param; +} + +svint8_t +bad_return_sve_sc (svint16_t param) +{ + return param; /* { dg-error {incompatible types when returning type 'svint16_t' but 'svint8_t' was expected} } */ +} diff --git a/gcc/tree-core.h b/gcc/tree-core.h index 26b6f46ad..fca4abf2a 100644 --- a/gcc/tree-core.h +++ b/gcc/tree-core.h @@ -1585,7 +1585,8 @@ struct GTY(()) tree_type_common { unsigned warn_if_not_align : 6; unsigned typeless_storage : 1; unsigned empty_flag : 1; - unsigned spare : 17; + unsigned indivisible_p : 1; + unsigned spare : 16; alias_set_type alias_set; tree pointer_to; diff --git a/gcc/tree.c b/gcc/tree.c index 62607c63a..33e8dca2a 100644 --- a/gcc/tree.c +++ b/gcc/tree.c @@ -15146,6 +15146,21 @@ max_object_size (void) return TYPE_MAX_VALUE (ptrdiff_type_node); } +/* A wrapper around TARGET_VERIFY_TYPE_CONTEXT that makes the silent_p + parameter default to false and that weeds out error_mark_node. */ + +bool +verify_type_context (location_t loc, type_context_kind context, + const_tree type, bool silent_p) +{ + if (type == error_mark_node) + return true; + + gcc_assert (TYPE_P (type)); + return (!targetm.verify_type_context + || targetm.verify_type_context (loc, context, type, silent_p)); +} + #if CHECKING_P namespace selftest { diff --git a/gcc/tree.h b/gcc/tree.h index 356a9f544..97d18fc2b 100644 --- a/gcc/tree.h +++ b/gcc/tree.h @@ -704,6 +704,11 @@ extern void omp_clause_range_check_failed (const_tree, const char *, int, /* Used to indicate that this TYPE represents a compiler-generated entity. */ #define TYPE_ARTIFICIAL(NODE) (TYPE_CHECK (NODE)->base.nowarning_flag) +/* True if the type is indivisible at the source level, i.e. if its + component parts cannot be accessed directly. This is used to suppress + normal GNU extensions for target-specific vector types. */ +#define TYPE_INDIVISIBLE_P(NODE) (TYPE_CHECK (NODE)->type_common.indivisible_p) + /* In an IDENTIFIER_NODE, this means that assemble_name was called with this string as an argument. */ #define TREE_SYMBOL_REFERENCED(NODE) \