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.
4 
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)));
16 
17 FourShorts four_shorts;
18 TwoInts two_ints;
19 TwoUInts two_uints;
20 FourInts four_ints;
21 FourUInts four_uints;
22 TwoLongLong two_ll;
23 FourLongLong four_ll;
24 TwoFloats two_floats;
25 FourFloats four_floats;
26 TwoDoubles two_doubles;
27 FourDoubles four_doubles;
28 
29 enum E {};
30 enum class SE {};
31 E e;
32 SE se;
33 
34 // Check the rules of the condition of the conditional operator.
Condition()35 void Condition() {
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'}}}
39 }
40 
41 // Check the rules of the LHS/RHS of the conditional operator.
Operands()42 void Operands() {
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}}
48 
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)}}
56 
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.
62 
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}}
70 
71   // They must also be convertible.
72   (void)(four_ints ? 3.0f : 5u);
73   (void)(four_ints ? 3.0f : 5);
74   unsigned us = 5u;
75   int sint = 5;
76   short shrt = 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);
82 
83   // Test promotion:
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}}
88 
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))}}
93 
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')}}
96 
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'}}
101 
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);
106 }
107 
108 template <typename T1, typename T2>
109 struct is_same {
110   static constexpr bool value = false;
111 };
112 template <typename T>
113 struct is_same<T, T> {
114   static constexpr bool value = true;
115 };
116 template <typename T1, typename T2>
117 constexpr bool is_same_v = is_same<T1, T2>::value;
118 template <typename T>
119 T &&declval();
120 
121 // Check the result types when given two vector types.
ResultTypes()122 void ResultTypes() {
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>())>);
126 
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>())>);
129 
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>())>);
133 
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)>);
138 
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>())>);
142 }
143 
144 template <typename Cond>
dependent_cond(Cond C)145 void dependent_cond(Cond C) {
146   (void)(C ? 1 : 2);
147 }
148 
149 template <typename Operand>
dependent_operand(Operand C)150 void dependent_operand(Operand C) {
151   (void)(two_ints ? 1 : C);
152   (void)(two_ints ? C : 1);
153   (void)(two_ints ? C : C);
154 }
155 
156 template <typename Cond, typename LHS, typename RHS>
all_dependent(Cond C,LHS L,RHS R)157 void all_dependent(Cond C, LHS L, RHS R) {
158   (void)(C ? L : R);
159 }
160 
161 // Check dependent cases.
Templates()162 void Templates() {
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}}
167 
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);
171 }
172 
173 using FourShortsVS = short __attribute__((__vector_size__(8)));
174 
mix_vector_types()175 void mix_vector_types() {
176   FourShortsVS vs;
177   (vs == 1 ? four_shorts : four_shorts);
178   // expected-error@-1 {{cannot mix vectors and extended vectors in a vector conditional}}
179 
180   (four_shorts == 1 ? vs : vs);
181   // expected-error@-1 {{cannot mix vectors and extended vectors in a vector conditional}}
182 
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))}}
185 
186   (four_shorts == 1 ? vs : four_shorts);
187   // expected-error@-1 {{cannot mix vectors and extended vectors in a vector conditional}}
188 
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))}}
191 
192   (vs == 1 ? four_shorts : vs);
193   // expected-error@-1 {{cannot mix vectors and extended vectors in a vector conditional}}
194 }
195