1 // RUN: %clang_cc1 %s -fenable-matrix -pedantic -std=c++11 -verify -triple=x86_64-apple-darwin9
2 
3 typedef float sx5x10_t __attribute__((matrix_type(5, 10)));
4 
5 template <typename EltTy, unsigned Rows, unsigned Columns>
6 struct MyMatrix {
7   using matrix_t = EltTy __attribute__((matrix_type(Rows, Columns)));
8 
9   matrix_t value;
10 };
11 
12 template <typename EltTy0, unsigned R0, unsigned C0, typename EltTy1, unsigned R1, unsigned C1, typename EltTy2, unsigned R2, unsigned C2>
add(MyMatrix<EltTy0,R0,C0> & A,MyMatrix<EltTy1,R1,C1> & B)13 typename MyMatrix<EltTy2, R2, C2>::matrix_t add(MyMatrix<EltTy0, R0, C0> &A, MyMatrix<EltTy1, R1, C1> &B) {
14   char *v1 = A.value + B.value;
15   // expected-error@-1 {{cannot initialize a variable of type 'char *' with an rvalue of type 'MyMatrix<unsigned int, 2, 2>::matrix_t' (aka 'unsigned int __attribute__((matrix_type(2, 2)))')}}
16   // expected-error@-2 {{invalid operands to binary expression ('MyMatrix<unsigned int, 3, 3>::matrix_t' (aka 'unsigned int __attribute__((matrix_type(3, 3)))') and 'MyMatrix<float, 2, 2>::matrix_t' (aka 'float __attribute__((matrix_type(2, 2)))'))}}
17   // expected-error@-3 {{invalid operands to binary expression ('MyMatrix<unsigned int, 2, 2>::matrix_t' (aka 'unsigned int __attribute__((matrix_type(2, 2)))') and 'MyMatrix<unsigned int, 3, 3>::matrix_t' (aka 'unsigned int __attribute__((matrix_type(3, 3)))'))}}
18 
19   return A.value + B.value;
20   // expected-error@-1 {{invalid operands to binary expression ('MyMatrix<unsigned int, 3, 3>::matrix_t' (aka 'unsigned int __attribute__((matrix_type(3, 3)))') and 'MyMatrix<float, 2, 2>::matrix_t' (aka 'float __attribute__((matrix_type(2, 2)))'))}}
21   // expected-error@-2 {{invalid operands to binary expression ('MyMatrix<unsigned int, 2, 2>::matrix_t' (aka 'unsigned int __attribute__((matrix_type(2, 2)))') and 'MyMatrix<unsigned int, 3, 3>::matrix_t' (aka 'unsigned int __attribute__((matrix_type(3, 3)))'))}}
22 }
23 
test_add_template(unsigned * Ptr1,float * Ptr2)24 void test_add_template(unsigned *Ptr1, float *Ptr2) {
25   MyMatrix<unsigned, 2, 2> Mat1;
26   MyMatrix<unsigned, 3, 3> Mat2;
27   MyMatrix<float, 2, 2> Mat3;
28   Mat1.value = *((decltype(Mat1)::matrix_t *)Ptr1);
29   unsigned v1 = add<unsigned, 2, 2, unsigned, 2, 2, unsigned, 2, 2>(Mat1, Mat1);
30   // expected-error@-1 {{cannot initialize a variable of type 'unsigned int' with an rvalue of type 'typename MyMatrix<unsigned int, 2U, 2U>::matrix_t' (aka 'unsigned int __attribute__((matrix_type(2, 2)))')}}
31   // expected-note@-2 {{in instantiation of function template specialization 'add<unsigned int, 2U, 2U, unsigned int, 2U, 2U, unsigned int, 2U, 2U>' requested here}}
32 
33   Mat1.value = add<unsigned, 2, 2, unsigned, 3, 3, unsigned, 2, 2>(Mat1, Mat2);
34   // expected-note@-1 {{in instantiation of function template specialization 'add<unsigned int, 2U, 2U, unsigned int, 3U, 3U, unsigned int, 2U, 2U>' requested here}}
35 
36   Mat1.value = add<unsigned, 3, 3, float, 2, 2, unsigned, 2, 2>(Mat2, Mat3);
37   // expected-note@-1 {{in instantiation of function template specialization 'add<unsigned int, 3U, 3U, float, 2U, 2U, unsigned int, 2U, 2U>' requested here}}
38 }
39 
40 template <typename EltTy0, unsigned R0, unsigned C0, typename EltTy1, unsigned R1, unsigned C1, typename EltTy2, unsigned R2, unsigned C2>
subtract(MyMatrix<EltTy0,R0,C0> & A,MyMatrix<EltTy1,R1,C1> & B)41 typename MyMatrix<EltTy2, R2, C2>::matrix_t subtract(MyMatrix<EltTy0, R0, C0> &A, MyMatrix<EltTy1, R1, C1> &B) {
42   char *v1 = A.value - B.value;
43   // expected-error@-1 {{cannot initialize a variable of type 'char *' with an rvalue of type 'MyMatrix<unsigned int, 2, 2>::matrix_t' (aka 'unsigned int __attribute__((matrix_type(2, 2)))')}}
44   // expected-error@-2 {{invalid operands to binary expression ('MyMatrix<unsigned int, 3, 3>::matrix_t' (aka 'unsigned int __attribute__((matrix_type(3, 3)))') and 'MyMatrix<float, 2, 2>::matrix_t' (aka 'float __attribute__((matrix_type(2, 2)))')}}
45   // expected-error@-3 {{invalid operands to binary expression ('MyMatrix<unsigned int, 2, 2>::matrix_t' (aka 'unsigned int __attribute__((matrix_type(2, 2)))') and 'MyMatrix<unsigned int, 3, 3>::matrix_t' (aka 'unsigned int __attribute__((matrix_type(3, 3)))')}}
46 
47   return A.value - B.value;
48   // expected-error@-1 {{invalid operands to binary expression ('MyMatrix<unsigned int, 3, 3>::matrix_t' (aka 'unsigned int __attribute__((matrix_type(3, 3)))') and 'MyMatrix<float, 2, 2>::matrix_t' (aka 'float __attribute__((matrix_type(2, 2)))')}}
49   // expected-error@-2 {{invalid operands to binary expression ('MyMatrix<unsigned int, 2, 2>::matrix_t' (aka 'unsigned int __attribute__((matrix_type(2, 2)))') and 'MyMatrix<unsigned int, 3, 3>::matrix_t' (aka 'unsigned int __attribute__((matrix_type(3, 3)))')}}
50 }
51 
test_subtract_template(unsigned * Ptr1,float * Ptr2)52 void test_subtract_template(unsigned *Ptr1, float *Ptr2) {
53   MyMatrix<unsigned, 2, 2> Mat1;
54   MyMatrix<unsigned, 3, 3> Mat2;
55   MyMatrix<float, 2, 2> Mat3;
56   Mat1.value = *((decltype(Mat1)::matrix_t *)Ptr1);
57   unsigned v1 = subtract<unsigned, 2, 2, unsigned, 2, 2, unsigned, 2, 2>(Mat1, Mat1);
58   // expected-error@-1 {{cannot initialize a variable of type 'unsigned int' with an rvalue of type 'typename MyMatrix<unsigned int, 2U, 2U>::matrix_t' (aka 'unsigned int __attribute__((matrix_type(2, 2)))')}}
59   // expected-note@-2 {{in instantiation of function template specialization 'subtract<unsigned int, 2U, 2U, unsigned int, 2U, 2U, unsigned int, 2U, 2U>' requested here}}
60 
61   Mat1.value = subtract<unsigned, 2, 2, unsigned, 3, 3, unsigned, 2, 2>(Mat1, Mat2);
62   // expected-note@-1 {{in instantiation of function template specialization 'subtract<unsigned int, 2U, 2U, unsigned int, 3U, 3U, unsigned int, 2U, 2U>' requested here}}
63 
64   Mat1.value = subtract<unsigned, 3, 3, float, 2, 2, unsigned, 2, 2>(Mat2, Mat3);
65   // expected-note@-1 {{in instantiation of function template specialization 'subtract<unsigned int, 3U, 3U, float, 2U, 2U, unsigned int, 2U, 2U>' requested here}}
66 }
67 
68 template <typename EltTy0, unsigned R0, unsigned C0, typename EltTy1, unsigned R1, unsigned C1, typename EltTy2, unsigned R2, unsigned C2>
multiply(MyMatrix<EltTy0,R0,C0> & A,MyMatrix<EltTy1,R1,C1> & B)69 typename MyMatrix<EltTy2, R2, C2>::matrix_t multiply(MyMatrix<EltTy0, R0, C0> &A, MyMatrix<EltTy1, R1, C1> &B) {
70   char *v1 = A.value * B.value;
71   // expected-error@-1 {{cannot initialize a variable of type 'char *' with an rvalue of type 'unsigned int __attribute__((matrix_type(2, 2)))'}}
72   // expected-error@-2 {{invalid operands to binary expression ('MyMatrix<unsigned int, 3, 2>::matrix_t' (aka 'unsigned int __attribute__((matrix_type(3, 2)))') and 'MyMatrix<unsigned int, 3, 3>::matrix_t' (aka 'unsigned int __attribute__((matrix_type(3, 3)))'))}}
73   // expected-error@-3 {{invalid operands to binary expression ('MyMatrix<float, 2, 2>::matrix_t' (aka 'float __attribute__((matrix_type(2, 2)))') and 'MyMatrix<unsigned int, 2, 2>::matrix_t' (aka 'unsigned int __attribute__((matrix_type(2, 2)))'))}}
74 
75   MyMatrix<int, 5, 6> m;
76   B.value = m.value * A.value;
77   // expected-error@-1 {{invalid operands to binary expression ('MyMatrix<int, 5, 6>::matrix_t' (aka 'int __attribute__((matrix_type(5, 6)))') and 'MyMatrix<unsigned int, 2, 2>::matrix_t' (aka 'unsigned int __attribute__((matrix_type(2, 2)))'))}}
78   // expected-error@-2 {{invalid operands to binary expression ('MyMatrix<int, 5, 6>::matrix_t' (aka 'int __attribute__((matrix_type(5, 6)))') and 'MyMatrix<unsigned int, 3, 2>::matrix_t' (aka 'unsigned int __attribute__((matrix_type(3, 2)))'))}}
79   // expected-error@-3 {{invalid operands to binary expression ('MyMatrix<int, 5, 6>::matrix_t' (aka 'int __attribute__((matrix_type(5, 6)))') and 'MyMatrix<float, 2, 2>::matrix_t' (aka 'float __attribute__((matrix_type(2, 2)))'))}}
80 
81   return A.value * B.value;
82   // expected-error@-1 {{invalid operands to binary expression ('MyMatrix<unsigned int, 3, 2>::matrix_t' (aka 'unsigned int __attribute__((matrix_type(3, 2)))') and 'MyMatrix<unsigned int, 3, 3>::matrix_t' (aka 'unsigned int __attribute__((matrix_type(3, 3)))'))}}
83   // expected-error@-2 {{invalid operands to binary expression ('MyMatrix<float, 2, 2>::matrix_t' (aka 'float __attribute__((matrix_type(2, 2)))') and 'MyMatrix<unsigned int, 2, 2>::matrix_t' (aka 'unsigned int __attribute__((matrix_type(2, 2)))'))}}
84 }
85 
test_multiply_template(unsigned * Ptr1,float * Ptr2)86 void test_multiply_template(unsigned *Ptr1, float *Ptr2) {
87   MyMatrix<unsigned, 2, 2> Mat1;
88   MyMatrix<unsigned, 3, 3> Mat2;
89   MyMatrix<float, 2, 2> Mat3;
90   Mat1.value = *((decltype(Mat1)::matrix_t *)Ptr1);
91   unsigned v1 = multiply<unsigned, 2, 2, unsigned, 2, 2, unsigned, 2, 2>(Mat1, Mat1);
92   // expected-note@-1 {{in instantiation of function template specialization 'multiply<unsigned int, 2U, 2U, unsigned int, 2U, 2U, unsigned int, 2U, 2U>' requested here}}
93   // expected-error@-2 {{cannot initialize a variable of type 'unsigned int' with an rvalue of type 'typename MyMatrix<unsigned int, 2U, 2U>::matrix_t' (aka 'unsigned int __attribute__((matrix_type(2, 2)))')}}
94 
95   MyMatrix<unsigned, 3, 2> Mat4;
96   Mat1.value = multiply<unsigned, 3, 2, unsigned, 3, 3, unsigned, 2, 2>(Mat4, Mat2);
97   // expected-note@-1 {{in instantiation of function template specialization 'multiply<unsigned int, 3U, 2U, unsigned int, 3U, 3U, unsigned int, 2U, 2U>' requested here}}
98 
99   Mat1.value = multiply<float, 2, 2, unsigned, 2, 2, unsigned, 2, 2>(Mat3, Mat1);
100   // expected-note@-1 {{in instantiation of function template specialization 'multiply<float, 2U, 2U, unsigned int, 2U, 2U, unsigned int, 2U, 2U>' requested here}}
101 
102   Mat4.value = Mat4.value * Mat1;
103   // expected-error@-1 {{no viable conversion from 'MyMatrix<unsigned int, 2, 2>' to 'unsigned int'}}
104   // expected-error@-2 {{invalid operands to binary expression ('MyMatrix<unsigned int, 3, 2>::matrix_t' (aka 'unsigned int __attribute__((matrix_type(3, 2)))') and 'MyMatrix<unsigned int, 2, 2>')}}
105 }
106 
107 struct UserT {};
108 
109 struct StructWithC {
operator UserTStructWithC110   operator UserT() {
111     // expected-note@-1 4 {{candidate function}}
112     return {};
113   }
114 };
115 
test_DoubleWrapper(MyMatrix<double,10,9> & m,StructWithC & c)116 void test_DoubleWrapper(MyMatrix<double, 10, 9> &m, StructWithC &c) {
117   m.value = m.value + c;
118   // expected-error@-1 {{no viable conversion from 'StructWithC' to 'double'}}
119   // expected-error@-2 {{invalid operands to binary expression ('MyMatrix<double, 10, 9>::matrix_t' (aka 'double __attribute__((matrix_type(10, 9)))') and 'StructWithC')}}
120 
121   m.value = c + m.value;
122   // expected-error@-1 {{no viable conversion from 'StructWithC' to 'double'}}
123   // expected-error@-2 {{invalid operands to binary expression ('StructWithC' and 'MyMatrix<double, 10, 9>::matrix_t' (aka 'double __attribute__((matrix_type(10, 9)))'))}}
124 
125   m.value = m.value - c;
126   // expected-error@-1 {{no viable conversion from 'StructWithC' to 'double'}}
127   // expected-error@-2 {{invalid operands to binary expression ('MyMatrix<double, 10, 9>::matrix_t' (aka 'double __attribute__((matrix_type(10, 9)))') and 'StructWithC')}}
128 
129   m.value = c - m.value;
130   // expected-error@-1 {{no viable conversion from 'StructWithC' to 'double'}}
131   // expected-error@-2 {{invalid operands to binary expression ('StructWithC' and 'MyMatrix<double, 10, 9>::matrix_t' (aka 'double __attribute__((matrix_type(10, 9)))'))}}
132 }
133 
134 sx5x10_t get_matrix();
135 
insert(sx5x10_t a,float f)136 void insert(sx5x10_t a, float f) {
137   // Non integer indexes.
138   a[3][f] = 0;
139   // expected-error@-1 {{matrix column index is not an integer}}
140   a[f][9] = 0;
141   // expected-error@-1 {{matrix row index is not an integer}}
142   a[f][f] = 0;
143   // expected-error@-1 {{matrix row index is not an integer}}
144   // expected-error@-2 {{matrix column index is not an integer}}
145   a[0][f] = 0;
146   // expected-error@-1 {{matrix column index is not an integer}}
147 
148   // Invalid element type.
149   a[3][4] = &f;
150   // expected-error@-1 {{assigning to 'float' from incompatible type 'float *'; remove &}}
151 
152   // Indexes outside allowed dimensions.
153   a[-1][3] = 10.0;
154   // expected-error@-1 {{matrix row index is outside the allowed range [0, 5)}}
155   a[3][-1] = 10.0;
156   // expected-error@-1 {{matrix column index is outside the allowed range [0, 10)}}
157   a[3][-1u] = 10.0;
158   // expected-error@-1 {{matrix column index is outside the allowed range [0, 10)}}
159   a[-1u][3] = 10.0;
160   // expected-error@-1 {{matrix row index is outside the allowed range [0, 5)}}
161   a[5][2] = 10.0;
162   // expected-error@-1 {{matrix row index is outside the allowed range [0, 5)}}
163   a[4][10] = 10.0;
164   // expected-error@-1 {{matrix column index is outside the allowed range [0, 10)}}
165   a[5][10.0] = f;
166   // expected-error@-1 {{matrix row index is outside the allowed range [0, 5)}}
167   // expected-error@-2 {{matrix column index is not an integer}}
168 
169   get_matrix()[0][0] = f;
170   // expected-error@-1 {{expression is not assignable}}
171   get_matrix()[5][10.0] = f;
172   // expected-error@-1 {{matrix row index is outside the allowed range [0, 5)}}
173   // expected-error@-2 {{matrix column index is not an integer}}
174   get_matrix()[3] = 5.0;
175   // expected-error@-1 {{single subscript expressions are not allowed for matrix values}}
176 
177   float &x = reinterpret_cast<float &>(a[3][3]);
178   // expected-error@-1 {{reinterpret_cast of a matrix element to 'float &' needs its address, which is not allowed}}
179 
180   a[4, 5] = 5.0;
181   // expected-error@-1 {{comma expressions are not allowed as indices in matrix subscript expressions}}
182   // expected-warning@-2 {{left operand of comma operator has no effect}}
183 
184   a[4, 5, 4] = 5.0;
185   // expected-error@-1 {{comma expressions are not allowed as indices in matrix subscript expressions}}
186   // expected-warning@-2 {{left operand of comma operator has no effect}}
187   // expected-warning@-3 {{left operand of comma operator has no effect}}
188 }
189 
extract(sx5x10_t a,float f)190 void extract(sx5x10_t a, float f) {
191   // Non integer indexes.
192   float v1 = a[3][f];
193   // expected-error@-1 {{matrix column index is not an integer}}
194   float v2 = a[f][9];
195   // expected-error@-1 {{matrix row index is not an integer}}
196   float v3 = a[f][f];
197   // expected-error@-1 {{matrix row index is not an integer}}
198   // expected-error@-2 {{matrix column index is not an integer}}
199 
200   // Invalid element type.
201   char *v4 = a[3][4];
202   // expected-error@-1 {{cannot initialize a variable of type 'char *' with an lvalue of type 'float'}}
203 
204   // Indexes outside allowed dimensions.
205   float v5 = a[-1][3];
206   // expected-error@-1 {{matrix row index is outside the allowed range [0, 5)}}
207   float v6 = a[3][-1];
208   // expected-error@-1 {{matrix column index is outside the allowed range [0, 10)}}
209   float v8 = a[-1u][3];
210   // expected-error@-1 {{matrix row index is outside the allowed range [0, 5)}}
211   float v9 = a[5][2];
212   // expected-error@-1 {{matrix row index is outside the allowed range [0, 5)}}
213   float v10 = a[4][10];
214   // expected-error@-1 {{matrix column index is outside the allowed range [0, 10)}}
215   float v11 = a[5][10.0];
216   // expected-error@-1 {{matrix row index is outside the allowed range [0, 5)}}
217   // expected-error@-2 {{matrix column index is not an integer}}
218 
219   float v12 = get_matrix()[0][0];
220   float v13 = get_matrix()[5][10.0];
221   // expected-error@-1 {{matrix row index is outside the allowed range [0, 5)}}
222   // expected-error@-2 {{matrix column index is not an integer}}
223 }
224 
const_subscript_reference(sx5x10_t m)225 const float &const_subscript_reference(sx5x10_t m) {
226   return m[2][2];
227   // expected-warning@-1 {{returning reference to local temporary object}}
228 }
229 
const_subscript_reference(const sx5x10_t & m)230 const float &const_subscript_reference(const sx5x10_t &m) {
231   return m[2][2];
232   // expected-warning@-1 {{returning reference to local temporary object}}
233 }
234 
nonconst_subscript_reference(sx5x10_t m)235 float &nonconst_subscript_reference(sx5x10_t m) {
236   return m[2][2];
237   // expected-error@-1 {{non-const reference cannot bind to matrix element}}
238 }
239 
incomplete_matrix_index_expr(sx5x10_t a,float f)240 void incomplete_matrix_index_expr(sx5x10_t a, float f) {
241   float x = a[3];
242   // expected-error@-1 {{single subscript expressions are not allowed for matrix values}}
243   a[2] = f;
244   // expected-error@-1 {{single subscript expressions are not allowed for matrix values}}
245 }
246