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. 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. 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 each other. 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. 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> 145 void dependent_cond(Cond C) { 146 (void)(C ? 1 : 2); 147 } 148 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); 154 } 155 156 template <typename Cond, typename LHS, typename RHS> 157 void all_dependent(Cond C, LHS L, RHS R) { 158 (void)(C ? L : R); 159 } 160 161 // Check dependent cases. 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 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