@@ -9236,9 +9236,10 @@ c_parser_conditional_expression (c_parser *parser, struct c_expr *after,
}
else
{
- cond.value
- = c_objc_common_truthvalue_conversion
- (cond_loc, default_conversion (cond.value));
+ /* Vector conditions see no default or truthvalue conversion. */
+ if (!VECTOR_INTEGER_TYPE_P (TREE_TYPE (cond.value)))
+ cond.value = c_objc_common_truthvalue_conversion
+ (cond_loc, default_conversion (cond.value));
c_inhibit_evaluation_warnings += cond.value == truthvalue_false_node;
exp1 = c_parser_expression_conv (parser);
mark_exp_read (exp1.value);
@@ -5990,6 +5990,50 @@ build_conditional_expr (location_t colon_loc, tree ifexp, bool ifexp_bcp,
TYPE_MAIN_VARIANT (type2)))
result_type = composite_type (TYPE_MAIN_VARIANT (type1),
TYPE_MAIN_VARIANT (type2));
+ else if (VECTOR_TYPE_P (TREE_TYPE (ifexp))
+ && ((gnu_vector_type_p (type1) && code2 != VECTOR_TYPE)
+ || (gnu_vector_type_p (type2) && code1 != VECTOR_TYPE)))
+ {
+ enum stv_conv convert_flag = scalar_to_vector (colon_loc, VEC_COND_EXPR,
+ orig_op1, orig_op2, true);
+ switch (convert_flag)
+ {
+ case stv_error:
+ return error_mark_node;
+ case stv_firstarg:
+ {
+ bool maybe_const = true;
+ tree sc;
+ sc = c_fully_fold (op1, false, &maybe_const);
+ sc = save_expr (sc);
+ sc = convert (TREE_TYPE (type2), sc);
+ op1 = build_vector_from_val (type2, sc);
+ if (!maybe_const)
+ op1 = c_wrap_maybe_const (op1, true);
+ type1 = TREE_TYPE (op1);
+ code1 = TREE_CODE (type1);
+ result_type = type2;
+ break;
+ }
+ case stv_secondarg:
+ {
+ bool maybe_const = true;
+ tree sc;
+ sc = c_fully_fold (op2, false, &maybe_const);
+ sc = save_expr (sc);
+ sc = convert (TREE_TYPE (type1), sc);
+ op2 = build_vector_from_val (type1, sc);
+ if (!maybe_const)
+ op2 = c_wrap_maybe_const (op2, true);
+ type2 = TREE_TYPE (op2);
+ code2 = TREE_CODE (type2);
+ result_type = type1;
+ break;
+ }
+ default:
+ break;
+ }
+ }
if (!result_type)
{
@@ -6036,18 +6080,31 @@ build_conditional_expr (location_t colon_loc, tree ifexp, bool ifexp_bcp,
&& !TREE_OVERFLOW (orig_op2)));
}
- /* Need to convert condition operand into a vector mask. */
- if (VECTOR_TYPE_P (TREE_TYPE (ifexp)))
+ if (VECTOR_INTEGER_TYPE_P (TREE_TYPE (ifexp)))
{
+ /* Need to convert condition operand into a vector mask. */
tree vectype = TREE_TYPE (ifexp);
- tree elem_type = TREE_TYPE (vectype);
- tree zero = build_int_cst (elem_type, 0);
- tree zero_vec = build_vector_from_val (vectype, zero);
+ tree zero_vec = build_zero_cst (vectype);
tree cmp_type = truth_type_for (vectype);
ifexp = build2 (NE_EXPR, cmp_type, ifexp, zero_vec);
- }
- if (int_const || (ifexp_bcp && TREE_CODE (ifexp) == INTEGER_CST))
+ if (!VECTOR_TYPE_P (type1)
+ || !VECTOR_TYPE_P (type2)
+ || !VECTOR_TYPE_P (result_type)
+ || type1 != type2
+ || maybe_ne (TYPE_VECTOR_SUBPARTS (result_type),
+ TYPE_VECTOR_SUBPARTS (type1))
+ || TYPE_SIZE (result_type) != TYPE_SIZE (type1))
+ {
+ error_at (op1_loc,
+ "incompatible vector types in conditional expression: "
+ "%qT, %qT and %qT", vectype, type1, type2);
+ return error_mark_node;
+ }
+
+ ret = build3_loc (colon_loc, VEC_COND_EXPR, result_type, ifexp, op1, op2);
+ }
+ else if (int_const || (ifexp_bcp && TREE_CODE (ifexp) == INTEGER_CST))
ret = fold_build3_loc (colon_loc, COND_EXPR, result_type, ifexp, op1, op2);
else
{
similarity index 100%
rename from gcc/testsuite/g++.dg/ext/pr56790-1.C
rename to gcc/testsuite/c-c++-common/pr56790-1.c
similarity index 100%
rename from gcc/testsuite/g++.dg/opt/vectcond-1.C
rename to gcc/testsuite/c-c++-common/vectcond-1.c
new file mode 100644
@@ -0,0 +1,33 @@
+/* { dg-do compile } */
+
+typedef double vec __attribute__((vector_size(2*sizeof(double))));
+typedef signed char vec2 __attribute__((vector_size(16)));
+typedef unsigned char vec2u __attribute__((vector_size(16)));
+
+void f (vec *x, vec *y, vec *z)
+{
+ *x = (*y < *z) ? *x : *y;
+}
+
+void g (vec *x, vec *y, vec *z)
+{
+ *x = (*y < *z) ? *x : 42;
+}
+
+void h (vec *x, vec *y, vec *z)
+{
+ *x = (*y < *z) ? 3. : *y;
+}
+
+void i2 (vec2 *x, vec2 *y, vec2u *z)
+{
+ *x = *y ? *x : *y;
+ *y = *z ? *x : *y;
+}
+
+void j (vec2 *x, vec2 *y, vec2 *z, vec *t)
+{
+ *x = (*y < *z) ? *x : 4.2; /* { dg-error "" } */
+ *y = (*x < *z) ? 2.5 : *y; /* { dg-error "" } */
+ *t = *t ? *t : *t; /* { dg-error "" } */
+}
similarity index 100%
rename from gcc/testsuite/g++.dg/ext/vector21.C
rename to gcc/testsuite/c-c++-common/vector21.c
similarity index 100%
rename from gcc/testsuite/g++.dg/ext/vector22.C
rename to gcc/testsuite/c-c++-common/vector22.c
similarity index 100%
rename from gcc/testsuite/g++.dg/ext/vector35.C
rename to gcc/testsuite/c-c++-common/vector35.c
@@ -4,38 +4,14 @@ typedef double vec __attribute__((vector_size(2*sizeof(double))));
typedef signed char vec2 __attribute__((vector_size(16)));
typedef unsigned char vec2u __attribute__((vector_size(16)));
-void f (vec *x, vec *y, vec *z)
-{
- *x = (*y < *z) ? *x : *y;
-}
-
-void g (vec *x, vec *y, vec *z)
-{
- *x = (*y < *z) ? *x : 42;
-}
-
-void h (vec *x, vec *y, vec *z)
-{
- *x = (*y < *z) ? 3. : *y;
-}
-
void i1 (vec *x, vec *y, vec *z)
{
auto c = *y < *z;
*x = c ? *x : *y;
}
-void i2 (vec2 *x, vec2 *y, vec2u *z)
-{
- *x = *y ? *x : *y;
- *y = *z ? *x : *y;
-}
-
void j (vec2 *x, vec2 *y, vec2 *z, vec *t)
{
- *x = (*y < *z) ? *x : 4.2; /* { dg-error "" } */
- *y = (*x < *z) ? 2.5 : *y; /* { dg-error "" } */
- *t = *t ? *t : *t; /* { dg-error "" } */
*z = (*x < *z) ? '1' : '0';
}
@@ -48,4 +24,3 @@ void l (vec2 *v, double x)
{
k (v, x);
}
-
new file mode 100644
@@ -0,0 +1,10 @@
+/* { dg-do compile } */
+/* { dg-options "-std=gnu23" } */
+
+typedef double vec __attribute__((vector_size(2*sizeof(double))));
+
+void i1 (vec *x, vec *y, vec *z)
+{
+ auto c = *y < *z;
+ *x = c ? *x : *y;
+}