xref: /llvm-project/clang/test/Sema/aarch64-sme-func-attrs.c (revision b4ce29ab31b29ca926704c160e3909298ddf2b2b)
1 // RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +bf16 -target-feature +sme -target-feature +sme2 -target-feature +sve -Waarch64-sme-attributes -fsyntax-only -verify %s
2 // RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +bf16 -target-feature +sme -target-feature +sme2 -target-feature +sve -Waarch64-sme-attributes -fsyntax-only -verify=expected-cpp -x c++ %s
3 
4 // Valid attributes
5 
6 void sme_arm_streaming(void) __arm_streaming;
7 void sme_arm_streaming_compatible(void) __arm_streaming_compatible;
8 
9 __arm_new("za") void sme_arm_new_za(void) {}
10 void sme_arm_shared_za(void) __arm_inout("za");
11 void sme_arm_preserves_za(void) __arm_preserves("za");
12 void sme_arm_agnostic(void) __arm_agnostic("sme_za_state");
13 
14 __arm_new("za") void sme_arm_streaming_new_za(void) __arm_streaming {}
15 void sme_arm_streaming_shared_za(void) __arm_streaming __arm_inout("za");
16 void sme_arm_streaming_preserves_za(void) __arm_streaming __arm_preserves("za");
17 
18 __arm_new("za") void sme_arm_sc_new_za(void) __arm_streaming_compatible {}
19 void sme_arm_sc_shared_za(void) __arm_streaming_compatible __arm_inout("za");
20 void sme_arm_sc_preserves_za(void) __arm_streaming_compatible __arm_preserves("za");
21 
22 __arm_locally_streaming void sme_arm_locally_streaming(void) { }
23 __arm_locally_streaming void sme_arm_streaming_and_locally_streaming(void) __arm_streaming { }
24 __arm_locally_streaming void sme_arm_streaming_and_streaming_compatible(void) __arm_streaming_compatible { }
25 
26 __arm_locally_streaming __arm_new("za") void sme_arm_ls_new_za(void) { }
27 __arm_locally_streaming void sme_arm_ls_shared_za(void) __arm_inout("za") { }
28 __arm_locally_streaming void sme_arm_ls_preserves_za(void) __arm_preserves("za") { }
29 
30 // Valid attributes on function pointers
31 
32 void streaming_ptr(void) __arm_streaming;
33 typedef  void (*fptrty1) (void) __arm_streaming;
34 fptrty1 call_streaming_func() { return streaming_ptr; }
35 
36 void streaming_compatible_ptr(void) __arm_streaming_compatible;
37 typedef void (*fptrty2) (void) __arm_streaming_compatible;
38 fptrty2 call_sc_func() { return streaming_compatible_ptr; }
39 
40 void shared_za_ptr(void) __arm_inout("za");
41 typedef void (*fptrty3) (void) __arm_inout("za");
42 fptrty3 call_shared_za_func() { return shared_za_ptr; }
43 
44 void preserves_za_ptr(void) __arm_preserves("za");
45 typedef void (*fptrty4) (void) __arm_preserves("za");
46 fptrty4 call_preserve_za_func() { return preserves_za_ptr; }
47 
48 typedef void (*fptrty6) (void);
49 fptrty6 cast_nza_func_to_normal() { return sme_arm_new_za; }
50 fptrty6 cast_ls_func_to_normal() { return sme_arm_locally_streaming; }
51 
52 // Invalid attributes
53 
54 // expected-cpp-error@+4 {{'__arm_streaming_compatible' and '__arm_streaming' are not compatible}}
55 // expected-cpp-note@+3 {{conflicting attribute is here}}
56 // expected-error@+2 {{'__arm_streaming_compatible' and '__arm_streaming' are not compatible}}
57 // expected-note@+1 {{conflicting attribute is here}}
58 void streaming_mode(void) __arm_streaming __arm_streaming_compatible;
59 
60 // expected-cpp-error@+4 {{'__arm_streaming' and '__arm_streaming_compatible' are not compatible}}
61 // expected-cpp-note@+3 {{conflicting attribute is here}}
62 // expected-error@+2 {{'__arm_streaming' and '__arm_streaming_compatible' are not compatible}}
63 // expected-note@+1 {{conflicting attribute is here}}
64 void streaming_compatible(void) __arm_streaming_compatible __arm_streaming;
65 
66 // expected-cpp-error@+2 {{'__arm_new("za")' and '__arm_inout("za")' are not compatible}}
67 // expected-error@+1 {{'__arm_new("za")' and '__arm_inout("za")' are not compatible}}
68 __arm_new("za") void new_shared_za(void) __arm_inout("za") {}
69 
70 // expected-cpp-error@+2 {{'__arm_new("za")' and '__arm_preserves("za")' are not compatible}}
71 // expected-error@+1 {{'__arm_new("za")' and '__arm_preserves("za")' are not compatible}}
72 __arm_new("za") void new_preserves_za(void) __arm_preserves("za") {}
73 
74 // Invalid attributes on function pointers
75 
76 // expected-cpp-error@+4 {{'__arm_streaming_compatible' and '__arm_streaming' are not compatible}}
77 // expected-cpp-note@+3 {{conflicting attribute is here}}
78 // expected-error@+2 {{'__arm_streaming_compatible' and '__arm_streaming' are not compatible}}
79 // expected-note@+1 {{conflicting attribute is here}}
80 void streaming_ptr_invalid(void) __arm_streaming __arm_streaming_compatible;
81 // expected-cpp-error@+4 {{'__arm_streaming_compatible' and '__arm_streaming' are not compatible}}
82 // expected-cpp-note@+3 {{conflicting attribute is here}}
83 // expected-error@+2 {{'__arm_streaming_compatible' and '__arm_streaming' are not compatible}}
84 // expected-note@+1 {{conflicting attribute is here}}
85 typedef void (*fptrty7) (void) __arm_streaming __arm_streaming_compatible;
86 fptrty7 invalid_streaming_func() { return streaming_ptr_invalid; }
87 
88 // expected-warning@+2 {{'__arm_streaming' only applies to non-K&R-style functions}}
89 // expected-error@+1 {{'__arm_streaming' only applies to function types; type here is 'void ()'}}
90 void function_no_prototype() __arm_streaming;
91 
92 // expected-cpp-error@+2 {{__arm_agnostic("sme_za_state") cannot share ZA state with its caller}}
93 // expected-error@+1 {{__arm_agnostic("sme_za_state") cannot share ZA state with its caller}}
94 void sme_arm_agnostic_shared_za_zt0(void) __arm_agnostic("sme_za_state") __arm_inout("zt0") {}
95 
96 // expected-cpp-error@+2 {{__arm_agnostic("sme_za_state") cannot share ZA state with its caller}}
97 // expected-error@+1 {{__arm_agnostic("sme_za_state") cannot share ZA state with its caller}}
98 void sme_arm_agnostic_shared_za_za(void) __arm_agnostic("sme_za_state") __arm_inout("za") {}
99 
100 // expected-cpp-error@+2 {{__arm_agnostic("sme_za_state") cannot share ZA state with its caller}}
101 // expected-error@+1 {{__arm_agnostic("sme_za_state") cannot share ZA state with its caller}}
102 void sme_arm_agnostic_shared_za_za_rev(void) __arm_inout("za") __arm_agnostic("sme_za_state") {}
103 
104 // expected-cpp-error@+2 {{__arm_agnostic("sme_za_state") is not supported together with __arm_new("za") or __arm_new("zt0")}}
105 // expected-error@+1 {{__arm_agnostic("sme_za_state") is not supported together with __arm_new("za") or __arm_new("zt0")}}
106 __arm_new("zt0") void sme_arm_agnostic_arm_new_zt0(void) __arm_agnostic("sme_za_state") {}
107 
108 // expected-cpp-error@+2 {{__arm_agnostic("sme_za_state") is not supported together with __arm_new("za") or __arm_new("zt0")}}
109 // expected-error@+1 {{__arm_agnostic("sme_za_state") is not supported together with __arm_new("za") or __arm_new("zt0")}}
110 __arm_new("za") void sme_arm_agnostic_arm_new_za(void) __arm_agnostic("sme_za_state") {}
111 
112 //
113 // Check for incorrect conversions of function pointers with the attributes
114 //
115 
116 typedef void (*n_ptrty) (void);
117 typedef void (*s_ptrty) (void) __arm_streaming;
118 s_ptrty return_valid_streaming_fptr(s_ptrty f) { return f; }
119 
120 // expected-cpp-error@+2 {{cannot initialize return object of type 's_ptrty' (aka 'void (*)() __arm_streaming') with an lvalue of type 'n_ptrty' (aka 'void (*)()')}}
121 // expected-error@+1 {{incompatible function pointer types returning 'n_ptrty' (aka 'void (*)(void)') from a function with result type 's_ptrty' (aka 'void (*)(void) __arm_streaming')}}
122 s_ptrty return_invalid_fptr_streaming_normal(n_ptrty f) { return f; }
123 // expected-cpp-error@+2 {{cannot initialize return object of type 'n_ptrty' (aka 'void (*)()') with an lvalue of type 's_ptrty' (aka 'void (*)() __arm_streaming')}}
124 // expected-error@+1 {{incompatible function pointer types returning 's_ptrty' (aka 'void (*)(void) __arm_streaming') from a function with result type 'n_ptrty' (aka 'void (*)(void)')}}
125 n_ptrty return_invalid_fptr_normal_streaming(s_ptrty f) { return f; }
126 
127 // Test an instance where the result type is not a prototyped function, such that we still get a diagnostic.
128 typedef void (*nonproto_n_ptrty) ();
129 // expected-cpp-error@+2 {{cannot initialize return object of type 'nonproto_n_ptrty' (aka 'void (*)()') with an lvalue of type 's_ptrty' (aka 'void (*)() __arm_streaming')}}
130 // expected-error@+1 {{incompatible function pointer types returning 's_ptrty' (aka 'void (*)(void) __arm_streaming') from a function with result type 'nonproto_n_ptrty' (aka 'void (*)()')}}
131 nonproto_n_ptrty return_invalid_fptr_streaming_nonprotonormal(s_ptrty f) { return f; }
132 
133 typedef void (*sc_ptrty) (void) __arm_streaming_compatible;
134 sc_ptrty return_valid_streaming_compatible_fptr(sc_ptrty f) { return f; }
135 
136 // expected-cpp-error@+2 {{cannot initialize return object of type 'sc_ptrty' (aka 'void (*)() __arm_streaming_compatible') with an lvalue of type 'n_ptrty' (aka 'void (*)()')}}
137 // expected-error@+1 {{incompatible function pointer types returning 'n_ptrty' (aka 'void (*)(void)') from a function with result type 'sc_ptrty' (aka 'void (*)(void) __arm_streaming_compatible')}}
138 sc_ptrty return_invalid_fptr_streaming_compatible_normal(n_ptrty f) { return f; }
139 // expected-cpp-error@+2 {{cannot initialize return object of type 'n_ptrty' (aka 'void (*)()') with an lvalue of type 'sc_ptrty' (aka 'void (*)() __arm_streaming_compatible')}}
140 // expected-error@+1 {{incompatible function pointer types returning 'sc_ptrty' (aka 'void (*)(void) __arm_streaming_compatible') from a function with result type 'n_ptrty' (aka 'void (*)(void)')}}
141 n_ptrty return_invalid_fptr_normal_streaming_compatible(sc_ptrty f) { return f; }
142 
143 typedef void (*sz_ptrty) (void) __arm_inout("za");
144 sz_ptrty return_valid_shared_za_fptr(sz_ptrty f) { return f; }
145 
146 
147 // expected-cpp-error@+2 {{cannot initialize return object of type 'sz_ptrty' (aka 'void (*)() __arm_inout("za")') with an lvalue of type 'n_ptrty' (aka 'void (*)()')}}
148 // expected-error@+1 {{incompatible function pointer types returning 'n_ptrty' (aka 'void (*)(void)') from a function with result type 'sz_ptrty' (aka 'void (*)(void) __arm_inout("za")')}}
149 sz_ptrty return_invalid_fptr_shared_za_normal(n_ptrty f) { return f; }
150 // expected-cpp-error@+2 {{cannot initialize return object of type 'n_ptrty' (aka 'void (*)()') with an lvalue of type 'sz_ptrty' (aka 'void (*)() __arm_inout("za")')}}
151 // expected-error@+1 {{incompatible function pointer types returning 'sz_ptrty' (aka 'void (*)(void) __arm_inout("za")') from a function with result type 'n_ptrty' (aka 'void (*)(void)')}}
152 n_ptrty return_invalid_fptr_normal_shared_za(sz_ptrty f) { return f; }
153 
154 typedef void (*pz_ptrty) (void) __arm_preserves("za");
155 pz_ptrty return_valid_preserves_za_fptr(pz_ptrty f) { return f; }
156 
157 // expected-cpp-error@+2 {{cannot initialize return object of type 'pz_ptrty' (aka 'void (*)() __arm_preserves("za")') with an lvalue of type 'n_ptrty' (aka 'void (*)()')}}
158 // expected-error@+1 {{incompatible function pointer types returning 'n_ptrty' (aka 'void (*)(void)') from a function with result type 'pz_ptrty' (aka 'void (*)(void) __arm_preserves("za")')}}
159 pz_ptrty return_invalid_fptr_preserves_za_normal(n_ptrty f) { return f; }
160 // expected-cpp-error@+2 {{cannot initialize return object of type 'n_ptrty' (aka 'void (*)()') with an lvalue of type 'pz_ptrty' (aka 'void (*)() __arm_preserves("za")')}}
161 // expected-error@+1 {{incompatible function pointer types returning 'pz_ptrty' (aka 'void (*)(void) __arm_preserves("za")') from a function with result type 'n_ptrty' (aka 'void (*)(void)')}}
162 n_ptrty return_invalid_fptr_normal_preserves_za(pz_ptrty f) { return f; }
163 
164 // Test template instantiations
165 #ifdef __cplusplus
166 template <typename T> T templated(T x) __arm_streaming { return x; }
167 template <> int templated<int>(int x) __arm_streaming { return x + 1; }
168 template <> float templated<float>(float x) __arm_streaming { return x + 2; }
169 // expected-cpp-error@+2 {{explicit instantiation of 'templated' does not refer to a function template, variable template, member function, member class, or static data member}}
170 // expected-cpp-note@-4 {{candidate template ignored: could not match 'short (short) __arm_streaming' against 'short (short)'}}
171 template short templated<short>(short);
172 #endif
173 
174 // Conflicting attributes on redeclarations
175 
176 // expected-error@+5 {{function declared 'void (void) __arm_streaming_compatible' was previously declared 'void (void) __arm_streaming', which has different SME function attributes}}
177 // expected-note@+3 {{previous declaration is here}}
178 // expected-cpp-error@+3 {{function declared 'void () __arm_streaming_compatible' was previously declared 'void () __arm_streaming', which has different SME function attributes}}
179 // expected-cpp-note@+1 {{previous declaration is here}}
180 void redecl(void) __arm_streaming;
181 void redecl(void) __arm_streaming_compatible { }
182 
183 // expected-error@+5 {{function declared 'void (void)' was previously declared 'void (void) __arm_preserves("za")', which has different SME function attributes}}
184 // expected-note@+3 {{previous declaration is here}}
185 // expected-cpp-error@+3 {{function declared 'void ()' was previously declared 'void () __arm_preserves("za")', which has different SME function attributes}}
186 // expected-cpp-note@+1 {{previous declaration is here}}
187 void redecl_preserve_za(void) __arm_preserves("za");;
188 void redecl_preserve_za(void) {}
189 
190 // expected-error@+5 {{function declared 'void (void) __arm_preserves("za")' was previously declared 'void (void)', which has different SME function attributes}}
191 // expected-note@+3 {{previous declaration is here}}
192 // expected-cpp-error@+3 {{function declared 'void () __arm_preserves("za")' was previously declared 'void ()', which has different SME function attributes}}
193 // expected-cpp-note@+1 {{previous declaration is here}}
194 void redecl_nopreserve_za(void);
195 void redecl_nopreserve_za(void) __arm_preserves("za") {}
196 
197 void non_za_definition(void (*shared_za_fn_ptr)(void) __arm_inout("za"), void (*preserves_za_fn_ptr)(void) __arm_preserves("za")) {
198   sme_arm_new_za(); // OK
199   // expected-error@+2 {{call to a shared ZA function requires the caller to have ZA state}}
200   // expected-cpp-error@+1 {{call to a shared ZA function requires the caller to have ZA state}}
201   sme_arm_shared_za();
202   // expected-error@+2 {{call to a shared ZA function requires the caller to have ZA state}}
203   // expected-cpp-error@+1 {{call to a shared ZA function requires the caller to have ZA state}}
204   shared_za_fn_ptr();
205   // expected-error@+2 {{call to a shared ZA function requires the caller to have ZA state}}
206   // expected-cpp-error@+1 {{call to a shared ZA function requires the caller to have ZA state}}
207   preserves_za_fn_ptr();
208 }
209 
210 void shared_za_definition(void (*shared_za_fn_ptr)(void) __arm_inout("za")) __arm_inout("za") {
211   sme_arm_shared_za(); // OK
212   shared_za_fn_ptr(); // OK
213 }
214 
215 __arm_new("za") void new_za_definition(void (*shared_za_fn_ptr)(void) __arm_inout("za")) {
216   sme_arm_shared_za(); // OK
217   shared_za_fn_ptr(); // OK
218 }
219 
220 #ifdef __cplusplus
221 int shared_za_initializer(void) __arm_inout("za");
222 // expected-cpp-error@+1 {{call to a shared ZA function requires the caller to have ZA state}}
223 int global = shared_za_initializer();
224 
225 struct S {
226   virtual void shared_za_memberfn(void) __arm_inout("za");
227 };
228 
229 struct S2 : public S {
230 // expected-cpp-error@+2 {{virtual function 'shared_za_memberfn' has different attributes ('void ()') than the function it overrides (which has 'void () __arm_inout("za")')}}
231 // expected-cpp-note@-5 {{overridden virtual function is here}}
232   __arm_new("za") void shared_za_memberfn(void) override {}
233 };
234 
235 // The '__arm_preserves("za")' property cannot be dropped when overriding a virtual
236 // function. It is however fine for the overriding function to be '__arm_preserves("za")'
237 // even though the function that it overrides is not.
238 
239 struct S_PreservesZA {
240   virtual void memberfn(void) __arm_preserves("za");
241 };
242 
243 struct S_Drop_PreservesZA : S_PreservesZA {
244 // expected-cpp-error@+2 {{virtual function 'memberfn' has different attributes ('void ()') than the function it overrides (which has 'void () __arm_preserves("za")')}}
245 // expected-cpp-note@-5 {{overridden virtual function is here}}
246   void memberfn(void) override {}
247 };
248 
249 struct S_NoPreservesZA {
250   virtual void memberfn(void);
251 };
252 
253 struct S_AddPreservesZA : S_NoPreservesZA {
254 // expected-cpp-error@+2 {{virtual function 'memberfn' has different attributes ('void () __arm_preserves("za")') than the function it overrides (which has 'void ()')}}
255 // expected-cpp-note@-5 {{overridden virtual function is here}}
256   void memberfn(void) __arm_preserves("za") override {}
257 };
258 
259 
260 // Check that the attribute propagates through template instantiations.
261 template <typename Ty>
262 struct S3 {
263   static constexpr int value = 0;
264 };
265 
266 template <>
267 struct S3<void (*)()> {
268   static constexpr int value = 1;
269 };
270 
271 template <>
272 struct S3<void (* __arm_streaming)()> {
273   static constexpr int value = 2;
274 };
275 
276 template <>
277 struct S3<void (* __arm_streaming_compatible)()> {
278   static constexpr int value = 4;
279 };
280 
281 template <>
282 struct S3<void (* __arm_inout("za"))()> {
283   static constexpr int value = 8;
284 };
285 
286 template <>
287 struct S3<void (* __arm_preserves("za"))()> {
288   static constexpr int value = 16;
289 };
290 
291 void normal_func(void) {}
292 void streaming_func(void) __arm_streaming {}
293 void streaming_compatible_func(void) __arm_streaming_compatible {}
294 void shared_za_func(void) __arm_inout("za") {}
295 void preserves_za_func(void) __arm_preserves("za") {}
296 
297 static_assert(S3<decltype(+normal_func)>::value == 1, "why are we picking the wrong specialization?");
298 static_assert(S3<decltype(+streaming_func)>::value == 2, "why are we picking the wrong specialization?");
299 static_assert(S3<decltype(+streaming_compatible_func)>::value == 4, "why are we picking the wrong specialization?");
300 static_assert(S3<decltype(+shared_za_func)>::value == 8, "why are we picking the wrong specialization?");
301 static_assert(S3<decltype(+preserves_za_func)>::value == 16, "why are we picking the wrong specialization?");
302 
303 // Also test the attribute is propagated with variadic templates
304 constexpr int eval_variadic_template() { return 0; }
305 template <typename T, typename... Other>
306 constexpr int eval_variadic_template(T f, Other... other) {
307     return S3<decltype(f)>::value + eval_variadic_template(other...);
308 }
309 static_assert(eval_variadic_template(normal_func, streaming_func,
310                                      streaming_compatible_func,
311                                      shared_za_func, preserves_za_func) == 31,
312               "attributes  not propagated properly in variadic template");
313 
314 // Test that the attribute is propagated with template specialization.
315 template<typename T> int test_templated_f(T);
316 template<> constexpr int test_templated_f<void(*)(void)>(void(*)(void)) { return 1; }
317 template<> constexpr int test_templated_f<void(*)(void)__arm_streaming>(void(*)(void)__arm_streaming) { return 2; }
318 template<> constexpr int test_templated_f<void(*)(void)__arm_streaming_compatible>(void(*)(void)__arm_streaming_compatible) { return 4; }
319 template<> constexpr int test_templated_f<void(*)(void)__arm_inout("za")>(void(*)(void)__arm_inout("za")) { return 8; }
320 template<> constexpr int test_templated_f<void(*)(void)__arm_preserves("za")>(void(*)(void)__arm_preserves("za")) { return 16; }
321 
322 static_assert(test_templated_f(&normal_func) == 1, "Instantiated to wrong function");
323 static_assert(test_templated_f(&streaming_func) == 2, "Instantiated to wrong function");
324 static_assert(test_templated_f(&streaming_compatible_func) == 4, "Instantiated to wrong function");
325 static_assert(test_templated_f(&shared_za_func) == 8, "Instantiated to wrong function");
326 static_assert(test_templated_f(&preserves_za_func) == 16, "Instantiated to wrong function");
327 
328 // expected-cpp-error@+2 {{'__arm_streaming' only applies to function types; type here is 'int'}}
329 // expected-error@+1 {{'__arm_streaming' only applies to function types; type here is 'int'}}
330 int invalid_type_for_attribute __arm_streaming;
331 
332 // Test overloads
333 constexpr int overload(void f(void)) { return 1; }
334 constexpr int overload(void f(void) __arm_streaming) { return 2; }
335 constexpr int overload(void f(void) __arm_streaming_compatible) { return 4; }
336 constexpr int overload(void f(void) __arm_inout("za")) { return 8; }
337 constexpr int overload(void f(void) __arm_preserves("za")) { return 16; }
338 static_assert(overload(&normal_func) == 1, "Overloaded to wrong function");
339 static_assert(overload(&streaming_func) == 2, "Overloaded to wrong function");
340 static_assert(overload(&streaming_compatible_func) == 4, "Overloaded to wrong function");
341 static_assert(overload(&shared_za_func) == 8, "Overloaded to wrong function");
342 static_assert(overload(&preserves_za_func) == 16, "Overloaded to wrong function");
343 
344 // Test implicit instantiation
345 template <typename T> struct X {
346   static void foo(T) __arm_streaming { }
347 };
348 constexpr int overload_int(void f(int)) { return 1; }
349 constexpr int overload_int(void f(int) __arm_streaming) { return 2; }
350 constexpr X<int> *ptr = 0;
351 static_assert(overload_int(ptr->foo) == 2, "Overloaded to the wrong function after implicit instantiation");
352 
353 #endif // ifdef __cplusplus
354 
355 // expected-cpp-error@+2 {{unknown state ''}}
356 // expected-error@+1 {{unknown state ''}}
357 __arm_new("") void invalid_arm_new_empty_string(void);
358 // expected-cpp-error@+2 {{expected string literal as argument of '__arm_new' attribute}}
359 // expected-error@+1 {{expected string literal as argument of '__arm_new' attribute}}
360 __arm_new(0) void invalid_arm_new_non_literal_string(void);
361 // expected-cpp-error@+2 {{unknown state 'unknownstate'}}
362 // expected-error@+1 {{unknown state 'unknownstate'}}
363 __arm_new("unknownstate") void invalid_arm_new_unknown_state(void);
364 
365 // expected-cpp-error@+2 {{unknown state ''}}
366 // expected-error@+1 {{unknown state ''}}
367 void invalid_arm_in_empty_string(void) __arm_in("");
368 // expected-cpp-error@+2 {{expected string literal as argument of '__arm_in' attribute}}
369 // expected-error@+1 {{expected string literal as argument of '__arm_in' attribute}}
370 void invalid_arm_in_non_literal_string(void) __arm_in(0);
371 // expected-cpp-error@+2 {{unknown state 'unknownstate'}}
372 // expected-error@+1 {{unknown state 'unknownstate'}}
373 void invalid_arm_in_unknown_state(void) __arm_in("unknownstate");
374 
375 void valid_state_attrs_in_in1(void) __arm_in("za");
376 void valid_state_attrs_in_in2(void) __arm_in("za", "za");
377 void valid_state_attrs_in_in3(void) __arm_in("zt0");
378 void valid_state_attrs_in_in4(void) __arm_in("zt0", "zt0");
379 void valid_state_attrs_in_in5(void) __arm_in("za", "zt0");
380 __arm_new("za") void valid_state_attrs_in_in6(void) __arm_in("zt0");
381 __arm_new("zt0") void valid_state_attrs_in_in7(void) __arm_in("za");
382 
383 // expected-cpp-error@+2 {{missing state for '__arm_in'}}
384 // expected-error@+1 {{missing state for '__arm_in'}}
385 void invalid_state_attrs_no_arg1(void) __arm_in();
386 // expected-cpp-error@+2 {{missing state for '__arm_new'}}
387 // expected-error@+1 {{missing state for '__arm_new'}}
388 __arm_new() void invalid_state_attrs_no_arg2(void);
389 
390 // expected-cpp-error@+2 {{conflicting attributes for state 'za'}}
391 // expected-error@+1 {{conflicting attributes for state 'za'}}
392 void conflicting_state_attrs_in_out(void) __arm_in("za") __arm_out("za");
393 // expected-cpp-error@+2 {{conflicting attributes for state 'za'}}
394 // expected-error@+1 {{conflicting attributes for state 'za'}}
395 void conflicting_state_attrs_in_inout(void) __arm_in("za") __arm_inout("za");
396 // expected-cpp-error@+2 {{conflicting attributes for state 'za'}}
397 // expected-error@+1 {{conflicting attributes for state 'za'}}
398 void conflicting_state_attrs_in_preserves(void) __arm_in("za") __arm_preserves("za");
399 
400 // expected-cpp-error@+2 {{conflicting attributes for state 'za'}}
401 // expected-error@+1 {{conflicting attributes for state 'za'}}
402 void conflicting_state_attrs_out_in(void) __arm_out("za") __arm_in("za");
403 // expected-cpp-error@+2 {{conflicting attributes for state 'za'}}
404 // expected-error@+1 {{conflicting attributes for state 'za'}}
405 void conflicting_state_attrs_out_inout(void) __arm_out("za") __arm_inout("za");
406 // expected-cpp-error@+2 {{conflicting attributes for state 'za'}}
407 // expected-error@+1 {{conflicting attributes for state 'za'}}
408 void conflicting_state_attrs_out_preserves(void) __arm_out("za") __arm_preserves("za");
409 
410 // expected-cpp-error@+2 {{conflicting attributes for state 'za'}}
411 // expected-error@+1 {{conflicting attributes for state 'za'}}
412 void conflicting_state_attrs_inout_in(void) __arm_inout("za") __arm_in("za");
413 // expected-cpp-error@+2 {{conflicting attributes for state 'za'}}
414 // expected-error@+1 {{conflicting attributes for state 'za'}}
415 void conflicting_state_attrs_inout_out(void) __arm_inout("za") __arm_out("za");
416 // expected-cpp-error@+2 {{conflicting attributes for state 'za'}}
417 // expected-error@+1 {{conflicting attributes for state 'za'}}
418 void conflicting_state_attrs_inout_preserves(void) __arm_inout("za") __arm_preserves("za");
419 
420 // expected-cpp-error@+2 {{conflicting attributes for state 'za'}}
421 // expected-error@+1 {{conflicting attributes for state 'za'}}
422 void conflicting_state_attrs_preserves_in(void) __arm_preserves("za") __arm_in("za");
423 // expected-cpp-error@+2 {{conflicting attributes for state 'za'}}
424 // expected-error@+1 {{conflicting attributes for state 'za'}}
425 void conflicting_state_attrs_preserves_out(void) __arm_preserves("za") __arm_out("za");
426 // expected-cpp-error@+2 {{conflicting attributes for state 'za'}}
427 // expected-error@+1 {{conflicting attributes for state 'za'}}
428 void conflicting_state_attrs_preserves_inout(void) __arm_preserves("za") __arm_inout("za");
429 
430 // expected-cpp-error@+2 {{conflicting attributes for state 'zt0'}}
431 // expected-error@+1 {{conflicting attributes for state 'zt0'}}
432 void conflicting_state_attrs_in_out_zt0(void) __arm_in("zt0") __arm_out("zt0");
433 // expected-cpp-error@+2 {{conflicting attributes for state 'zt0'}}
434 // expected-error@+1 {{conflicting attributes for state 'zt0'}}
435 void conflicting_state_attrs_in_inout_zt0(void) __arm_in("zt0") __arm_inout("zt0");
436 // expected-cpp-error@+2 {{conflicting attributes for state 'zt0'}}
437 // expected-error@+1 {{conflicting attributes for state 'zt0'}}
438 void conflicting_state_attrs_in_preserves_zt0(void) __arm_in("zt0") __arm_preserves("zt0");
439 
440 // expected-cpp-error@+2 {{conflicting attributes for state 'zt0'}}
441 // expected-error@+1 {{conflicting attributes for state 'zt0'}}
442 void conflicting_state_attrs_out_in_zt0(void) __arm_out("zt0") __arm_in("zt0");
443 // expected-cpp-error@+2 {{conflicting attributes for state 'zt0'}}
444 // expected-error@+1 {{conflicting attributes for state 'zt0'}}
445 void conflicting_state_attrs_out_inout_zt0(void) __arm_out("zt0") __arm_inout("zt0");
446 // expected-cpp-error@+2 {{conflicting attributes for state 'zt0'}}
447 // expected-error@+1 {{conflicting attributes for state 'zt0'}}
448 void conflicting_state_attrs_out_preserves_zt0(void) __arm_out("zt0") __arm_preserves("zt0");
449 
450 // expected-cpp-error@+2 {{conflicting attributes for state 'zt0'}}
451 // expected-error@+1 {{conflicting attributes for state 'zt0'}}
452 void conflicting_state_attrs_inout_in_zt0(void) __arm_inout("zt0") __arm_in("zt0");
453 // expected-cpp-error@+2 {{conflicting attributes for state 'zt0'}}
454 // expected-error@+1 {{conflicting attributes for state 'zt0'}}
455 void conflicting_state_attrs_inout_out_zt0(void) __arm_inout("zt0") __arm_out("zt0");
456 // expected-cpp-error@+2 {{conflicting attributes for state 'zt0'}}
457 // expected-error@+1 {{conflicting attributes for state 'zt0'}}
458 void conflicting_state_attrs_inout_preserves_zt0(void) __arm_inout("zt0") __arm_preserves("zt0");
459 
460 // expected-cpp-error@+2 {{conflicting attributes for state 'zt0'}}
461 // expected-error@+1 {{conflicting attributes for state 'zt0'}}
462 void conflicting_state_attrs_preserves_in_zt0(void) __arm_preserves("zt0") __arm_in("zt0");
463 // expected-cpp-error@+2 {{conflicting attributes for state 'zt0'}}
464 // expected-error@+1 {{conflicting attributes for state 'zt0'}}
465 void conflicting_state_attrs_preserves_out_zt0(void) __arm_preserves("zt0") __arm_out("zt0");
466 // expected-cpp-error@+2 {{conflicting attributes for state 'zt0'}}
467 // expected-error@+1 {{conflicting attributes for state 'zt0'}}
468 void conflicting_state_attrs_preserves_inout_zt0(void) __arm_preserves("zt0") __arm_inout("zt0");
469 
470 // Test that we get a diagnostic for unimplemented case.
471 void unimplemented_spill_fill_za(void (*share_zt0_only)(void) __arm_inout("zt0")) __arm_inout("za", "zt0") {
472   // expected-cpp-error@+4 {{call to a function that shares state other than 'za' from a function that has live 'za' state requires a spill/fill of ZA, which is not yet implemented}}
473   // expected-cpp-note@+3 {{add '__arm_preserves("za")' to the callee if it preserves ZA}}
474   // expected-error@+2 {{call to a function that shares state other than 'za' from a function that has live 'za' state requires a spill/fill of ZA, which is not yet implemented}}
475   // expected-note@+1 {{add '__arm_preserves("za")' to the callee if it preserves ZA}}
476   share_zt0_only();
477 }
478 
479 void sme_streaming_with_vl_arg(__SVInt8_t a) __arm_streaming { }
480 
481 __SVInt8_t sme_streaming_returns_vl(void) __arm_streaming { __SVInt8_t r; return r; }
482 
483 void sme_streaming_compatible_with_vl_arg(__SVInt8_t a) __arm_streaming_compatible { }
484 
485 __SVInt8_t sme_streaming_compatible_returns_vl(void) __arm_streaming_compatible { __SVInt8_t r; return r; }
486 
487 void sme_no_streaming_with_vl_arg(__SVInt8_t a) { }
488 
489 __SVInt8_t sme_no_streaming_returns_vl(void) { __SVInt8_t r; return r; }
490 
491 // expected-warning@+2 {{passing a VL-dependent argument to a locally streaming function is undefined behaviour when the streaming and non-streaming vector lengths are different at runtime}}
492 // expected-cpp-warning@+1 {{passing a VL-dependent argument to a locally streaming function is undefined behaviour when the streaming and non-streaming vector lengths are different at runtime}}
493 __arm_locally_streaming void sme_locally_streaming_with_vl_arg(__SVInt8_t a) { }
494 
495 // expected-warning@+2 {{returning a VL-dependent argument from a locally streaming function is undefined behaviour when the streaming and non-streaming vector lengths are different at runtime}}
496 // expected-cpp-warning@+1 {{returning a VL-dependent argument from a locally streaming function is undefined behaviour when the streaming and non-streaming vector lengths are different at runtime}}
497 __arm_locally_streaming __SVInt8_t sme_locally_streaming_returns_vl(void) { __SVInt8_t r; return r; }
498 
499 void sme_no_streaming_calling_streaming_with_vl_args() {
500   __SVInt8_t a;
501   // expected-warning@+2 {{passing a VL-dependent argument to a function with a different streaming-mode is undefined behaviour when the streaming and non-streaming vector lengths are different at runtime}}
502   // expected-cpp-warning@+1 {{passing a VL-dependent argument to a function with a different streaming-mode is undefined behaviour when the streaming and non-streaming vector lengths are different at runtime}}
503   sme_streaming_with_vl_arg(a);
504 }
505 
506 void sme_no_streaming_calling_streaming_with_return_vl() {
507   // expected-warning@+2 {{returning a VL-dependent argument from a function with a different streaming-mode is undefined behaviour when the streaming and non-streaming vector lengths are different at runtime}}
508   // expected-cpp-warning@+1 {{returning a VL-dependent argument from a function with a different streaming-mode is undefined behaviour when the streaming and non-streaming vector lengths are different at runtime}}
509   __SVInt8_t r = sme_streaming_returns_vl();
510 }
511 
512 void sme_streaming_calling_non_streaming_with_vl_args(void) __arm_streaming {
513   __SVInt8_t a;
514   // expected-warning@+2 {{passing a VL-dependent argument to a function with a different streaming-mode is undefined behaviour when the streaming and non-streaming vector lengths are different at runtime}}
515   // expected-cpp-warning@+1 {{passing a VL-dependent argument to a function with a different streaming-mode is undefined behaviour when the streaming and non-streaming vector lengths are different at runtime}}
516   sme_no_streaming_with_vl_arg(a);
517 }
518 
519 void sme_streaming_calling_non_streaming_with_return_vl(void) __arm_streaming {
520   // expected-warning@+2 {{returning a VL-dependent argument from a function with a different streaming-mode is undefined behaviour when the streaming and non-streaming vector lengths are different at runtime}}
521   // expected-cpp-warning@+1 {{returning a VL-dependent argument from a function with a different streaming-mode is undefined behaviour when the streaming and non-streaming vector lengths are different at runtime}}
522   __SVInt8_t r = sme_no_streaming_returns_vl();
523 }
524 
525 void sme_no_streaming_calling_streaming_with_vl_args_param(__SVInt8_t arg, void (*sc)( __SVInt8_t arg) __arm_streaming) {
526   // expected-warning@+2 {{passing a VL-dependent argument to a function with a different streaming-mode is undefined behaviour when the streaming and non-streaming vector lengths are different at runtime}}
527   // expected-cpp-warning@+1 {{passing a VL-dependent argument to a function with a different streaming-mode is undefined behaviour when the streaming and non-streaming vector lengths are different at runtime}}
528   sc(arg);
529 }
530 
531 __SVInt8_t sme_no_streaming_calling_streaming_return_vl_param(__SVInt8_t (*s)(void) __arm_streaming) {
532   // expected-warning@+2 {{returning a VL-dependent argument from a function with a different streaming-mode is undefined behaviour when the streaming and non-streaming vector lengths are different at runtime}}
533   // expected-cpp-warning@+1 {{returning a VL-dependent argument from a function with a different streaming-mode is undefined behaviour when the streaming and non-streaming vector lengths are different at runtime}}
534   return s();
535 }
536 
537 void sme_streaming_compatible_calling_streaming_with_vl_args(__SVInt8_t arg) __arm_streaming_compatible {
538   // expected-warning@+2 {{passing a VL-dependent argument to a function with a different streaming-mode is undefined behaviour when the streaming and non-streaming vector lengths are different at runtime}}
539   // expected-cpp-warning@+1 {{passing a VL-dependent argument to a function with a different streaming-mode is undefined behaviour when the streaming and non-streaming vector lengths are different at runtime}}
540   sme_streaming_with_vl_arg(arg);
541 }
542 
543 void sme_streaming_compatible_calling_sme_streaming_return_vl(void) __arm_streaming_compatible {
544   // expected-warning@+2 {{returning a VL-dependent argument from a function with a different streaming-mode is undefined behaviour when the streaming and non-streaming vector lengths are different at runtime}}
545   // expected-cpp-warning@+1 {{returning a VL-dependent argument from a function with a different streaming-mode is undefined behaviour when the streaming and non-streaming vector lengths are different at runtime}}
546   __SVInt8_t r = sme_streaming_returns_vl();
547 }
548 
549 void sme_streaming_compatible_calling_no_streaming_with_vl_args(__SVInt8_t arg) __arm_streaming_compatible {
550   // expected-warning@+2 {{passing a VL-dependent argument to a function with a different streaming-mode is undefined behaviour when the streaming and non-streaming vector lengths are different at runtime}}
551   // expected-cpp-warning@+1 {{passing a VL-dependent argument to a function with a different streaming-mode is undefined behaviour when the streaming and non-streaming vector lengths are different at runtime}}
552   sme_no_streaming_with_vl_arg(arg);
553 }
554 
555 void sme_streaming_compatible_calling_no_sme_streaming_return_vl(void) __arm_streaming_compatible {
556   // expected-warning@+2 {{returning a VL-dependent argument from a function with a different streaming-mode is undefined behaviour when the streaming and non-streaming vector lengths are different at runtime}}
557   // expected-cpp-warning@+1 {{returning a VL-dependent argument from a function with a different streaming-mode is undefined behaviour when the streaming and non-streaming vector lengths are different at runtime}}
558   __SVInt8_t r = sme_no_streaming_returns_vl();
559 }
560 
561 void sme_streaming_calling_streaming(__SVInt8_t arg, void (*s)( __SVInt8_t arg) __arm_streaming) __arm_streaming {
562   s(arg);
563 }
564 
565 __SVInt8_t sme_streaming_calling_streaming_return_vl(__SVInt8_t (*s)(void) __arm_streaming) __arm_streaming {
566   return s();
567 }
568 
569 void sme_streaming_calling_streaming_with_vl_args(__SVInt8_t a) __arm_streaming {
570   sme_streaming_with_vl_arg(a);
571 }
572 
573 void sme_streaming_calling_streaming_with_return_vl(void) __arm_streaming {
574   __SVInt8_t r = sme_streaming_returns_vl();
575 }
576 
577 void sme_streaming_calling_streaming_compatible_with_vl_args(__SVInt8_t a) __arm_streaming {
578   sme_streaming_compatible_with_vl_arg(a);
579 }
580 
581 void sme_streaming_calling_streaming_compatible_with_return_vl(void) __arm_streaming {
582   __SVInt8_t r = sme_streaming_compatible_returns_vl();
583 }
584 
585 void sme_no_streaming_calling_streaming_compatible_with_vl_args() {
586   __SVInt8_t a;
587   sme_streaming_compatible_with_vl_arg(a);
588 }
589 
590 void sme_no_streaming_calling_streaming_compatible_with_return_vl() {
591   __SVInt8_t r = sme_streaming_compatible_returns_vl();
592 }
593 
594 void sme_no_streaming_calling_non_streaming_compatible_with_vl_args() {
595   __SVInt8_t a;
596   sme_no_streaming_with_vl_arg(a);
597 }
598 
599 void sme_no_streaming_calling_non_streaming_compatible_with_return_vl() {
600   __SVInt8_t r = sme_no_streaming_returns_vl();
601 }
602 
603 void sme_streaming_compatible_calling_streaming_compatible_with_vl_args(__SVInt8_t arg) __arm_streaming_compatible {
604   sme_streaming_compatible_with_vl_arg(arg);
605 }
606 
607 void sme_streaming_compatible_calling_streaming_compatible_with_return_vl(void) __arm_streaming_compatible {
608   __SVInt8_t r = sme_streaming_compatible_returns_vl();
609 }
610