1 // RUN: %clang_cc1 -triple x86_64-linux-pc -fsyntax-only -verify -fexceptions -fcxx-exceptions %s -std=c++17
2 // Note that this test depends on the size of long-long to be different from
3 // int, so it specifies a triple.
5 using FourShorts
= short __attribute__((ext_vector_type(4)));
6 using TwoInts
= int __attribute__((ext_vector_type(2)));
7 using TwoUInts
= unsigned __attribute__((ext_vector_type(2)));
8 using FourInts
= int __attribute__((ext_vector_type(4)));
9 using FourUInts
= unsigned __attribute__((ext_vector_type(4)));
10 using TwoLongLong
= long long __attribute__((ext_vector_type(2)));
11 using FourLongLong
= long long __attribute__((ext_vector_type(4)));
12 using TwoFloats
= float __attribute__((ext_vector_type(2)));
13 using FourFloats
= float __attribute__((ext_vector_type(4)));
14 using TwoDoubles
= double __attribute__((ext_vector_type(2)));
15 using FourDoubles
= double __attribute__((ext_vector_type(4)));
17 FourShorts four_shorts
;
25 FourFloats four_floats
;
26 TwoDoubles two_doubles
;
27 FourDoubles four_doubles
;
34 // Check the rules of the condition of the conditional operator.
36 // Only int types are allowed here, the rest should fail to convert to bool.
37 (void)(four_floats
? 1 : 1); // expected-error {{is not contextually convertible to 'bool'}}}
38 (void)(two_doubles
? 1 : 1); // expected-error {{is not contextually convertible to 'bool'}}}
41 // Check the rules of the LHS/RHS of the conditional operator.
43 (void)(four_ints
? four_ints
: throw 1); // expected-error {{GNU vector conditional operand cannot be a throw expression}}
44 (void)(four_ints
? throw 1 : four_ints
); // expected-error {{GNU vector conditional operand cannot be a throw expression}}
45 (void)(four_ints
?: throw 1); // expected-error {{GNU vector conditional operand cannot be a throw expression}}
46 (void)(four_ints
? (void)1 : four_ints
); // expected-error {{GNU vector conditional operand cannot be void}}
47 (void)(four_ints
?: (void)1); // expected-error {{GNU vector conditional operand cannot be void}}
49 // Vector types must be the same element size as the condition.
50 (void)(four_ints
? two_ll
: two_ll
); // expected-error {{vector condition type 'FourInts' (vector of 4 'int' values) and result type 'TwoLongLong' (vector of 2 'long long' values) do not have the same number of elements}}
51 (void)(four_ints
? four_ll
: four_ll
); // expected-error {{vector condition type 'FourInts' (vector of 4 'int' values) and result type 'FourLongLong' (vector of 4 'long long' values) do not have elements of the same size}}
52 (void)(four_ints
? two_doubles
: two_doubles
); // expected-error {{vector condition type 'FourInts' (vector of 4 'int' values) and result type 'TwoDoubles' (vector of 2 'double' values) do not have the same number of elements}}
53 (void)(four_ints
? four_doubles
: four_doubles
); // expected-error {{vector condition type 'FourInts' (vector of 4 'int' values) and result type 'FourDoubles' (vector of 4 'double' values) do not have elements of the same size}}
54 (void)(four_ints
?: two_ints
); // expected-error {{vector operands to the vector conditional must be the same type ('FourInts' (vector of 4 'int' values) and 'TwoInts' (vector of 2 'int' values)}}
55 (void)(four_ints
?: four_doubles
); // expected-error {{vector operands to the vector conditional must be the same type ('FourInts' (vector of 4 'int' values) and 'FourDoubles' (vector of 4 'double' values)}}
57 // Scalars are promoted, but must be the same element size.
58 (void)(four_ints
? 3.0f
: 3.0); // expected-error {{vector condition type 'FourInts' (vector of 4 'int' values) and result type 'double __attribute__((ext_vector_type(4)))' (vector of 4 'double' values) do not have elements of the same size}}
59 (void)(four_ints
? 5ll : 5); // expected-error {{vector condition type 'FourInts' (vector of 4 'int' values) and result type 'long long __attribute__((ext_vector_type(4)))' (vector of 4 'long long' values) do not have elements of the same size}}
60 (void)(four_ints
?: 3.0); // expected-error {{annot convert between vector values of different size ('FourInts' (vector of 4 'int' values) and 'double')}}
61 (void)(four_ints
?: 5ll); // We allow this despite GCc not allowing this since we support integral->vector-integral conversions despite integer rank.
63 // This one would be allowed in GCC, but we don't allow vectors of enum. Also,
64 // the error message isn't perfect, since it is only going to be a problem
65 // when both sides are an enum, otherwise it'll be promoted to whatever type
66 // the other side causes.
67 (void)(four_ints
? e
: e
); // expected-error {{enumeration type 'E' is not allowed in a vector conditional}}
68 (void)(four_ints
? se
: se
); // expected-error {{enumeration type 'SE' is not allowed in a vector conditional}}
69 (void)(four_shorts
? (short)5 : (unsigned short)5); // expected-error {{vector condition type 'FourShorts' (vector of 4 'short' values) and result type 'int __attribute__((ext_vector_type(4)))' (vector of 4 'int' values) do not have elements of the same size}}
71 // They must also be convertible.
72 (void)(four_ints
? 3.0f
: 5u);
73 (void)(four_ints
? 3.0f
: 5);
77 unsigned short uss
= 5u;
78 // The following 2 error in GCC for truncation errors, but it seems
79 // unimportant and inconsistent to enforce that rule.
80 (void)(four_ints
? 3.0f
: us
);
81 (void)(four_ints
? 3.0f
: sint
);
84 (void)(four_shorts
? uss
: shrt
); // expected-error {{vector condition type 'FourShorts' (vector of 4 'short' values) and result type 'int __attribute__((ext_vector_type(4)))' (vector of 4 'int' values) do not have elements of the same size}}
85 (void)(four_shorts
? shrt
: shrt
); // should be fine.
86 (void)(four_ints
? uss
: shrt
); // should be fine, since they get promoted to int.
87 (void)(four_ints
? shrt
: shrt
); // expected-error {{vector condition type 'FourInts' (vector of 4 'int' values) and result type 'short __attribute__((ext_vector_type(4)))' (vector of 4 'short' values) do not have elements of the same size}}
89 // Vectors must be the same type as eachother.
90 (void)(four_ints
? four_uints
: four_floats
); // expected-error {{vector operands to the vector conditional must be the same type ('FourUInts' (vector of 4 'unsigned int' values) and 'FourFloats' (vector of 4 'float' values))}}
91 (void)(four_ints
? four_uints
: four_ints
); // expected-error {{vector operands to the vector conditional must be the same type ('FourUInts' (vector of 4 'unsigned int' values) and 'FourInts' (vector of 4 'int' values))}}
92 (void)(four_ints
? four_ints
: four_uints
); // expected-error {{vector operands to the vector conditional must be the same type ('FourInts' (vector of 4 'int' values) and 'FourUInts' (vector of 4 'unsigned int' values))}}
94 (void)(four_ints
? four_uints
: 3.0f
); // expected-error {{cannot convert between vector values of different size ('FourUInts' (vector of 4 'unsigned int' values) and 'float')}}
95 (void)(four_ints
? four_ints
: 3.0f
); // expected-error {{cannot convert between vector values of different size ('FourInts' (vector of 4 'int' values) and 'float')}}
97 // When there is a vector and a scalar, conversions must be legal.
98 (void)(four_ints
? four_floats
: 3); // should work, ints can convert to floats.
99 (void)(four_ints
? four_uints
: e
); // expected-error {{cannot convert between vector values of different size ('FourUInts' (vector of 4 'unsigned int' values) and 'E')}}
100 (void)(four_ints
? four_uints
: se
); // expected-error {{cannot convert between vector and non-scalar values ('FourUInts' (vector of 4 'unsigned int' values) and 'SE'}}
102 (void)(two_ints
? two_ints
: us
);
103 (void)(four_shorts
? four_shorts
: uss
);
104 (void)(four_ints
? four_floats
: us
);
105 (void)(four_ints
? four_floats
: sint
);
108 template <typename T1
, typename T2
>
110 static constexpr bool value
= false;
112 template <typename T
>
113 struct is_same
<T
, T
> {
114 static constexpr bool value
= true;
116 template <typename T1
, typename T2
>
117 constexpr bool is_same_v
= is_same
<T1
, T2
>::value
;
118 template <typename T
>
121 // Check the result types when given two vector types.
123 // Vectors must be the same, but result is the type of the LHS/RHS.
124 static_assert(is_same_v
<TwoInts
, decltype(declval
<TwoInts
>() ? declval
<TwoInts
>() : declval
<TwoInts
>())>);
125 static_assert(is_same_v
<TwoFloats
, decltype(declval
<TwoInts
>() ? declval
<TwoFloats
>() : declval
<TwoFloats
>())>);
127 // When both are scalars, converts to vectors of common type.
128 static_assert(is_same_v
<TwoUInts
, decltype(declval
<TwoInts
>() ? declval
<int>() : declval
<unsigned int>())>);
130 // Constant is allowed since it doesn't truncate, and should promote to float.
131 static_assert(is_same_v
<TwoFloats
, decltype(declval
<TwoInts
>() ? declval
<float>() : 5u)>);
132 static_assert(is_same_v
<TwoFloats
, decltype(declval
<TwoInts
>() ? 5 : declval
<float>())>);
134 // when only 1 is a scalar, it should convert to a compatible type.
135 static_assert(is_same_v
<TwoFloats
, decltype(declval
<TwoInts
>() ? declval
<TwoFloats
>() : declval
<float>())>);
136 static_assert(is_same_v
<TwoInts
, decltype(declval
<TwoInts
>() ? declval
<TwoInts
>() : declval
<int>())>);
137 static_assert(is_same_v
<TwoFloats
, decltype(declval
<TwoInts
>() ? declval
<TwoFloats
>() : 5)>);
139 // For the Binary conditional operator, the result type is either the vector on the RHS (that fits the rules on size/count), or the scalar extended to the correct count.
140 static_assert(is_same_v
<TwoInts
, decltype(declval
<TwoInts
>() ?: declval
<TwoInts
>())>);
141 static_assert(is_same_v
<TwoInts
, decltype(declval
<TwoInts
>() ?: declval
<int>())>);
144 template <typename Cond
>
145 void dependent_cond(Cond C
) {
149 template <typename Operand
>
150 void dependent_operand(Operand C
) {
151 (void)(two_ints
? 1 : C
);
152 (void)(two_ints
? C
: 1);
153 (void)(two_ints
? C
: C
);
156 template <typename Cond
, typename LHS
, typename RHS
>
157 void all_dependent(Cond C
, LHS L
, RHS R
) {
161 // Check dependent cases.
163 dependent_cond(two_ints
);
164 dependent_operand(two_floats
);
165 // expected-error@158 {{vector operands to the vector conditional must be the same type ('unsigned int __attribute__((ext_vector_type(4)))' (vector of 4 'unsigned int' values) and 'double __attribute__((ext_vector_type(4)))' (vector of 4 'double' values))}}}
166 all_dependent(four_ints
, four_uints
, four_doubles
); // expected-note {{in instantiation of}}
168 // expected-error@158 {{vector operands to the vector conditional must be the same type ('unsigned int __attribute__((ext_vector_type(4)))' (vector of 4 'unsigned int' values) and 'unsigned int __attribute__((ext_vector_type(2)))' (vector of 2 'unsigned int' values))}}}
169 all_dependent(four_ints
, four_uints
, two_uints
); // expected-note {{in instantiation of}}
170 all_dependent(four_ints
, four_uints
, four_uints
);
173 using FourShortsVS
= short __attribute__((__vector_size__(8)));
175 void mix_vector_types() {
177 (vs
== 1 ? four_shorts
: four_shorts
);
178 // expected-error@-1 {{cannot mix vectors and extended vectors in a vector conditional}}
180 (four_shorts
== 1 ? vs
: vs
);
181 // expected-error@-1 {{cannot mix vectors and extended vectors in a vector conditional}}
183 (four_shorts
== 1 ? four_shorts
: vs
);
184 // expected-error@-1 {{vector operands to the vector conditional must be the same type ('FourShorts' (vector of 4 'short' values) and 'FourShortsVS' (vector of 4 'short' values))}}
186 (four_shorts
== 1 ? vs
: four_shorts
);
187 // expected-error@-1 {{cannot mix vectors and extended vectors in a vector conditional}}
189 (vs
== 1 ? vs
: four_shorts
);
190 // expected-error@-1 {{vector operands to the vector conditional must be the same type ('FourShortsVS' (vector of 4 'short' values) and 'FourShorts' (vector of 4 'short' values))}}
192 (vs
== 1 ? four_shorts
: vs
);
193 // expected-error@-1 {{cannot mix vectors and extended vectors in a vector conditional}}