1fc8d3766SFlorian Hahn // RUN: %clang_cc1 -triple x86_64-linux-pc -fsyntax-only -verify -fexceptions -fcxx-exceptions %s -std=c++17
2fc8d3766SFlorian Hahn // Note that this test depends on the size of long-long to be different from
3fc8d3766SFlorian Hahn // int, so it specifies a triple.
4fc8d3766SFlorian Hahn
5fc8d3766SFlorian Hahn using FourShorts = short __attribute__((__vector_size__(8)));
6fc8d3766SFlorian Hahn using TwoInts = int __attribute__((__vector_size__(8)));
7fc8d3766SFlorian Hahn using TwoUInts = unsigned __attribute__((__vector_size__(8)));
8fc8d3766SFlorian Hahn using FourInts = int __attribute__((__vector_size__(16)));
9fc8d3766SFlorian Hahn using FourUInts = unsigned __attribute__((__vector_size__(16)));
10fc8d3766SFlorian Hahn using TwoLongLong = long long __attribute__((__vector_size__(16)));
11fc8d3766SFlorian Hahn using FourLongLong = long long __attribute__((__vector_size__(32)));
12fc8d3766SFlorian Hahn using TwoFloats = float __attribute__((__vector_size__(8)));
13fc8d3766SFlorian Hahn using FourFloats = float __attribute__((__vector_size__(16)));
14fc8d3766SFlorian Hahn using TwoDoubles = double __attribute__((__vector_size__(16)));
15fc8d3766SFlorian Hahn using FourDoubles = double __attribute__((__vector_size__(32)));
16*0aab3441SSimon Moll using EightBools = bool __attribute__((ext_vector_type(8)));
17fc8d3766SFlorian Hahn
18fc8d3766SFlorian Hahn FourShorts four_shorts;
19fc8d3766SFlorian Hahn TwoInts two_ints;
20fc8d3766SFlorian Hahn TwoUInts two_uints;
21fc8d3766SFlorian Hahn FourInts four_ints;
22fc8d3766SFlorian Hahn FourUInts four_uints;
23fc8d3766SFlorian Hahn TwoLongLong two_ll;
24fc8d3766SFlorian Hahn FourLongLong four_ll;
25fc8d3766SFlorian Hahn TwoFloats two_floats;
26fc8d3766SFlorian Hahn FourFloats four_floats;
27fc8d3766SFlorian Hahn TwoDoubles two_doubles;
28fc8d3766SFlorian Hahn FourDoubles four_doubles;
29*0aab3441SSimon Moll EightBools eight_bools;
30*0aab3441SSimon Moll EightBools other_eight_bools;
31fc8d3766SFlorian Hahn
32fc8d3766SFlorian Hahn enum E {};
33fc8d3766SFlorian Hahn enum class SE {};
34fc8d3766SFlorian Hahn E e;
35fc8d3766SFlorian Hahn SE se;
36fc8d3766SFlorian Hahn
37fc8d3766SFlorian Hahn // Check the rules of the condition of the conditional operator.
Condition()38fc8d3766SFlorian Hahn void Condition() {
39fc8d3766SFlorian Hahn // Only int types are allowed here, the rest should fail to convert to bool.
40fc8d3766SFlorian Hahn (void)(four_floats ? 1 : 1); // expected-error {{is not contextually convertible to 'bool'}}}
41fc8d3766SFlorian Hahn (void)(two_doubles ? 1 : 1); // expected-error {{is not contextually convertible to 'bool'}}}
42fc8d3766SFlorian Hahn }
43fc8d3766SFlorian Hahn
44fc8d3766SFlorian Hahn // Check the rules of the LHS/RHS of the conditional operator.
Operands()45fc8d3766SFlorian Hahn void Operands() {
46fc8d3766SFlorian Hahn (void)(four_ints ? four_ints : throw 1); // expected-error {{GNU vector conditional operand cannot be a throw expression}}
47fc8d3766SFlorian Hahn (void)(four_ints ? throw 1 : four_ints); // expected-error {{GNU vector conditional operand cannot be a throw expression}}
48fc8d3766SFlorian Hahn (void)(four_ints ?: throw 1); // expected-error {{GNU vector conditional operand cannot be a throw expression}}
49fc8d3766SFlorian Hahn (void)(four_ints ? (void)1 : four_ints); // expected-error {{GNU vector conditional operand cannot be void}}
50fc8d3766SFlorian Hahn (void)(four_ints ?: (void)1); // expected-error {{GNU vector conditional operand cannot be void}}
51fc8d3766SFlorian Hahn
52fc8d3766SFlorian Hahn // Vector types must be the same element size as the condition.
53fc8d3766SFlorian Hahn (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}}
54fc8d3766SFlorian Hahn (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}}
55fc8d3766SFlorian Hahn (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}}
56fc8d3766SFlorian Hahn (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}}
57fc8d3766SFlorian Hahn (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)}}
58fc8d3766SFlorian Hahn (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)}}
59fc8d3766SFlorian Hahn
60fc8d3766SFlorian Hahn // Scalars are promoted, but must be the same element size.
61fc8d3766SFlorian Hahn (void)(four_ints ? 3.0f : 3.0); // expected-error {{vector condition type 'FourInts' (vector of 4 'int' values) and result type '__attribute__((__vector_size__(4 * sizeof(double)))) double' (vector of 4 'double' values) do not have elements of the same size}}
62fc8d3766SFlorian Hahn (void)(four_ints ? 5ll : 5); // expected-error {{vector condition type 'FourInts' (vector of 4 'int' values) and result type '__attribute__((__vector_size__(4 * sizeof(long long)))) long long' (vector of 4 'long long' values) do not have elements of the same size}}
63fc8d3766SFlorian Hahn (void)(four_ints ?: 3.0); // expected-error {{cannot convert between scalar type 'double' and vector type 'FourInts' (vector of 4 'int' values) as implicit conversion would cause truncation}}
64fc8d3766SFlorian Hahn (void)(four_ints ?: 5ll); // We allow this despite GCc not allowing this since we support integral->vector-integral conversions despite integer rank.
65fc8d3766SFlorian Hahn
66fc8d3766SFlorian Hahn // This one would be allowed in GCC, but we don't allow vectors of enum. Also,
67fc8d3766SFlorian Hahn // the error message isn't perfect, since it is only going to be a problem
68fc8d3766SFlorian Hahn // when both sides are an enum, otherwise it'll be promoted to whatever type
69fc8d3766SFlorian Hahn // the other side causes.
70fc8d3766SFlorian Hahn (void)(four_ints ? e : e); // expected-error {{enumeration type 'E' is not allowed in a vector conditional}}
71fc8d3766SFlorian Hahn (void)(four_ints ? se : se); // expected-error {{enumeration type 'SE' is not allowed in a vector conditional}}
72fc8d3766SFlorian Hahn (void)(four_shorts ? (short)5 : (unsigned short)5); // expected-error {{vector condition type 'FourShorts' (vector of 4 'short' values) and result type '__attribute__((__vector_size__(4 * sizeof(int)))) int' (vector of 4 'int' values) do not have elements of the same size}}
73fc8d3766SFlorian Hahn
74fc8d3766SFlorian Hahn // They must also be convertible.
75fc8d3766SFlorian Hahn (void)(four_ints ? 3.0f : 5u);
76fc8d3766SFlorian Hahn (void)(four_ints ? 3.0f : 5);
77fc8d3766SFlorian Hahn unsigned us = 5u;
78fc8d3766SFlorian Hahn int sint = 5;
79fc8d3766SFlorian Hahn short shrt = 5;
80fc8d3766SFlorian Hahn unsigned short uss = 5u;
81fc8d3766SFlorian Hahn // The following 2 error in GCC for truncation errors, but it seems
82fc8d3766SFlorian Hahn // unimportant and inconsistent to enforce that rule.
83fc8d3766SFlorian Hahn (void)(four_ints ? 3.0f : us);
84fc8d3766SFlorian Hahn (void)(four_ints ? 3.0f : sint);
85fc8d3766SFlorian Hahn
86fc8d3766SFlorian Hahn // Test promotion:
87fc8d3766SFlorian Hahn (void)(four_shorts ? uss : shrt); // expected-error {{vector condition type 'FourShorts' (vector of 4 'short' values) and result type '__attribute__((__vector_size__(4 * sizeof(int)))) int' (vector of 4 'int' values) do not have elements of the same size}}
88fc8d3766SFlorian Hahn (void)(four_shorts ? shrt : shrt); // should be fine.
89fc8d3766SFlorian Hahn (void)(four_ints ? uss : shrt); // should be fine, since they get promoted to int.
90fc8d3766SFlorian Hahn (void)(four_ints ? shrt : shrt); //expected-error {{vector condition type 'FourInts' (vector of 4 'int' values) and result type '__attribute__((__vector_size__(4 * sizeof(short)))) short' (vector of 4 'short' values) do not have elements of the same size}}
91fc8d3766SFlorian Hahn
92fc8d3766SFlorian Hahn // Vectors must be the same type as eachother.
93fc8d3766SFlorian Hahn (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))}}
94fc8d3766SFlorian Hahn (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))}}
95fc8d3766SFlorian Hahn (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))}}
96fc8d3766SFlorian Hahn
97fc8d3766SFlorian Hahn // GCC rejects these, but our lax vector conversions don't seem to have a problem with them. Allow conversion of the float to an int as an extension.
98fc8d3766SFlorian Hahn (void)(four_ints ? four_uints : 3.0f);
99fc8d3766SFlorian Hahn (void)(four_ints ? four_ints : 3.0f);
100fc8d3766SFlorian Hahn
101*0aab3441SSimon Moll // Allow conditional select on bool vectors.
102*0aab3441SSimon Moll (void)(eight_bools ? eight_bools : other_eight_bools);
103*0aab3441SSimon Moll
104fc8d3766SFlorian Hahn // When there is a vector and a scalar, conversions must be legal.
105fc8d3766SFlorian Hahn (void)(four_ints ? four_floats : 3); // should work, ints can convert to floats.
106fc8d3766SFlorian Hahn (void)(four_ints ? four_uints : e); // expected-error {{cannot convert between scalar type 'E' and vector type 'FourUInts'}}
107fc8d3766SFlorian Hahn (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'}}
108fc8d3766SFlorian Hahn // GCC permits this, but our conversion rules reject this for truncation.
109fc8d3766SFlorian Hahn (void)(two_ints ? two_ints : us); // expected-error {{cannot convert between scalar type 'unsigned int' and vector type 'TwoInts'}}
110fc8d3766SFlorian Hahn (void)(four_shorts ? four_shorts : uss); // expected-error {{cannot convert between scalar type 'unsigned short' and vector type 'FourShorts'}}
111fc8d3766SFlorian Hahn (void)(four_ints ? four_floats : us); // expected-error {{cannot convert between scalar type 'unsigned int' and vector type 'FourFloats'}}
112fc8d3766SFlorian Hahn (void)(four_ints ? four_floats : sint); // expected-error {{cannot convert between scalar type 'int' and vector type 'FourFloats'}}
113fc8d3766SFlorian Hahn }
114fc8d3766SFlorian Hahn
115fc8d3766SFlorian Hahn template <typename T1, typename T2>
116fc8d3766SFlorian Hahn struct is_same {
117fc8d3766SFlorian Hahn static constexpr bool value = false;
118fc8d3766SFlorian Hahn };
119fc8d3766SFlorian Hahn template <typename T>
120fc8d3766SFlorian Hahn struct is_same<T, T> {
121fc8d3766SFlorian Hahn static constexpr bool value = true;
122fc8d3766SFlorian Hahn };
123fc8d3766SFlorian Hahn template <typename T1, typename T2>
124fc8d3766SFlorian Hahn constexpr bool is_same_v = is_same<T1, T2>::value;
125fc8d3766SFlorian Hahn template <typename T>
126fc8d3766SFlorian Hahn T &&declval();
127fc8d3766SFlorian Hahn
128fc8d3766SFlorian Hahn // Check the result types when given two vector types.
ResultTypes()129fc8d3766SFlorian Hahn void ResultTypes() {
130fc8d3766SFlorian Hahn // Vectors must be the same, but result is the type of the LHS/RHS.
131fc8d3766SFlorian Hahn static_assert(is_same_v<TwoInts, decltype(declval<TwoInts>() ? declval<TwoInts>() : declval<TwoInts>())>);
132fc8d3766SFlorian Hahn static_assert(is_same_v<TwoFloats, decltype(declval<TwoInts>() ? declval<TwoFloats>() : declval<TwoFloats>())>);
133fc8d3766SFlorian Hahn
134fc8d3766SFlorian Hahn // When both are scalars, converts to vectors of common type.
135fc8d3766SFlorian Hahn static_assert(is_same_v<TwoUInts, decltype(declval<TwoInts>() ? declval<int>() : declval<unsigned int>())>);
136fc8d3766SFlorian Hahn
137fc8d3766SFlorian Hahn // Constant is allowed since it doesn't truncate, and should promote to float.
138fc8d3766SFlorian Hahn static_assert(is_same_v<TwoFloats, decltype(declval<TwoInts>() ? declval<float>() : 5u)>);
139fc8d3766SFlorian Hahn static_assert(is_same_v<TwoFloats, decltype(declval<TwoInts>() ? 5 : declval<float>())>);
140fc8d3766SFlorian Hahn
141fc8d3766SFlorian Hahn // when only 1 is a scalar, it should convert to a compatible type.
142fc8d3766SFlorian Hahn static_assert(is_same_v<TwoFloats, decltype(declval<TwoInts>() ? declval<TwoFloats>() : declval<float>())>);
143fc8d3766SFlorian Hahn static_assert(is_same_v<TwoInts, decltype(declval<TwoInts>() ? declval<TwoInts>() : declval<int>())>);
144fc8d3766SFlorian Hahn static_assert(is_same_v<TwoFloats, decltype(declval<TwoInts>() ? declval<TwoFloats>() : 5)>);
145fc8d3766SFlorian Hahn
146fc8d3766SFlorian Hahn // 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.
147fc8d3766SFlorian Hahn static_assert(is_same_v<TwoInts, decltype(declval<TwoInts>() ?: declval<TwoInts>())>);
148fc8d3766SFlorian Hahn static_assert(is_same_v<TwoInts, decltype(declval<TwoInts>() ?: declval<int>())>);
149fc8d3766SFlorian Hahn }
150fc8d3766SFlorian Hahn
151fc8d3766SFlorian Hahn template <typename Cond>
dependent_cond(Cond C)152fc8d3766SFlorian Hahn void dependent_cond(Cond C) {
153fc8d3766SFlorian Hahn (void)(C ? 1 : 2);
154fc8d3766SFlorian Hahn }
155fc8d3766SFlorian Hahn
156fc8d3766SFlorian Hahn template <typename Operand>
dependent_operand(Operand C)157fc8d3766SFlorian Hahn void dependent_operand(Operand C) {
158fc8d3766SFlorian Hahn (void)(two_ints ? 1 : C);
159fc8d3766SFlorian Hahn (void)(two_ints ? C : 1);
160fc8d3766SFlorian Hahn (void)(two_ints ? C : C);
161fc8d3766SFlorian Hahn }
162fc8d3766SFlorian Hahn
163fc8d3766SFlorian Hahn template <typename Cond, typename LHS, typename RHS>
all_dependent(Cond C,LHS L,RHS R)164fc8d3766SFlorian Hahn void all_dependent(Cond C, LHS L, RHS R) {
165fc8d3766SFlorian Hahn (void)(C ? L : R);
166fc8d3766SFlorian Hahn }
167fc8d3766SFlorian Hahn
168fc8d3766SFlorian Hahn // Check dependent cases.
Templates()169fc8d3766SFlorian Hahn void Templates() {
170fc8d3766SFlorian Hahn dependent_cond(two_ints);
171fc8d3766SFlorian Hahn dependent_operand(two_floats);
172*0aab3441SSimon Moll // expected-error@165 {{vector operands to the vector conditional must be the same type ('__attribute__((__vector_size__(4 * sizeof(unsigned int)))) unsigned int' (vector of 4 'unsigned int' values) and '__attribute__((__vector_size__(4 * sizeof(double)))) double' (vector of 4 'double' values))}}}
173fc8d3766SFlorian Hahn all_dependent(four_ints, four_uints, four_doubles); // expected-note {{in instantiation of}}
174fc8d3766SFlorian Hahn
175*0aab3441SSimon Moll // expected-error@165 {{vector operands to the vector conditional must be the same type ('__attribute__((__vector_size__(4 * sizeof(unsigned int)))) unsigned int' (vector of 4 'unsigned int' values) and '__attribute__((__vector_size__(2 * sizeof(unsigned int)))) unsigned int' (vector of 2 'unsigned int' values))}}}
176fc8d3766SFlorian Hahn all_dependent(four_ints, four_uints, two_uints); // expected-note {{in instantiation of}}
177fc8d3766SFlorian Hahn all_dependent(four_ints, four_uints, four_uints);
178fc8d3766SFlorian Hahn }
179