Run DCE after a LoopFlatten test to reduce spurious output [nfc]
[llvm-project.git] / clang / test / Sema / aarch64-sme-func-attrs.c
blob73c0934d689e7c93422bff5c5b6781db715b4bfd
1 // RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sme -fsyntax-only -verify %s
2 // RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sme -fsyntax-only -verify=expected-cpp -x c++ %s
4 // Valid attributes
6 void sme_arm_streaming(void) __arm_streaming;
7 void sme_arm_streaming_compatible(void) __arm_streaming_compatible;
9 __arm_new_za void sme_arm_new_za(void) {}
10 void sme_arm_shared_za(void) __arm_shared_za;
11 void sme_arm_preserves_za(void) __arm_preserves_za;
13 __arm_new_za void sme_arm_streaming_new_za(void) __arm_streaming {}
14 void sme_arm_streaming_shared_za(void) __arm_streaming __arm_shared_za;
15 void sme_arm_streaming_preserves_za(void) __arm_streaming __arm_preserves_za;
17 __arm_new_za void sme_arm_sc_new_za(void) __arm_streaming_compatible {}
18 void sme_arm_sc_shared_za(void) __arm_streaming_compatible __arm_shared_za;
19 void sme_arm_sc_preserves_za(void) __arm_streaming_compatible __arm_preserves_za;
21 void sme_arm_shared_preserves_za(void) __arm_shared_za __arm_preserves_za;
23 __arm_locally_streaming void sme_arm_locally_streaming(void) { }
24 __arm_locally_streaming void sme_arm_streaming_and_locally_streaming(void) __arm_streaming { }
25 __arm_locally_streaming void sme_arm_streaming_and_streaming_compatible(void) __arm_streaming_compatible { }
27 __arm_locally_streaming __arm_new_za void sme_arm_ls_new_za(void) { }
28 __arm_locally_streaming void sme_arm_ls_shared_za(void) __arm_shared_za { }
29 __arm_locally_streaming void sme_arm_ls_preserves_za(void) __arm_preserves_za { }
31 // Valid attributes on function pointers
33 void streaming_ptr(void) __arm_streaming;
34 typedef void (*fptrty1) (void) __arm_streaming;
35 fptrty1 call_streaming_func() { return streaming_ptr; }
37 void streaming_compatible_ptr(void) __arm_streaming_compatible;
38 typedef void (*fptrty2) (void) __arm_streaming_compatible;
39 fptrty2 call_sc_func() { return streaming_compatible_ptr; }
41 void shared_za_ptr(void) __arm_shared_za;
42 typedef void (*fptrty3) (void) __arm_shared_za;
43 fptrty3 call_shared_za_func() { return shared_za_ptr; }
45 void preserves_za_ptr(void) __arm_preserves_za;
46 typedef void (*fptrty4) (void) __arm_preserves_za;
47 fptrty4 call_preserve_za_func() { return preserves_za_ptr; }
49 void shared_preserves_za_ptr(void) __arm_shared_za __arm_preserves_za;
50 typedef void (*fptrty5) (void) __arm_shared_za __arm_preserves_za;
51 fptrty5 call_shared_preserve_za_func() { return shared_preserves_za_ptr; }
53 typedef void (*fptrty6) (void);
54 fptrty6 cast_nza_func_to_normal() { return sme_arm_new_za; }
55 fptrty6 cast_ls_func_to_normal() { return sme_arm_locally_streaming; }
57 // Invalid attributes
59 // expected-cpp-error@+4 {{'__arm_streaming_compatible' and '__arm_streaming' are not compatible}}
60 // expected-cpp-note@+3 {{conflicting attribute is here}}
61 // expected-error@+2 {{'__arm_streaming_compatible' and '__arm_streaming' are not compatible}}
62 // expected-note@+1 {{conflicting attribute is here}}
63 void streaming_mode(void) __arm_streaming __arm_streaming_compatible;
65 // expected-cpp-error@+4 {{'__arm_streaming' and '__arm_streaming_compatible' are not compatible}}
66 // expected-cpp-note@+3 {{conflicting attribute is here}}
67 // expected-error@+2 {{'__arm_streaming' and '__arm_streaming_compatible' are not compatible}}
68 // expected-note@+1 {{conflicting attribute is here}}
69 void streaming_compatible(void) __arm_streaming_compatible __arm_streaming;
71 // expected-cpp-error@+2 {{'__arm_new_za' and '__arm_shared_za' are not compatible}}
72 // expected-error@+1 {{'__arm_new_za' and '__arm_shared_za' are not compatible}}
73 __arm_new_za void new_shared_za(void) __arm_shared_za {}
75 // expected-cpp-error@+2 {{'__arm_new_za' and '__arm_preserves_za' are not compatible}}
76 // expected-error@+1 {{'__arm_new_za' and '__arm_preserves_za' are not compatible}}
77 __arm_new_za void new_preserves_za(void) __arm_preserves_za {}
79 // Invalid attributes on function pointers
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 void streaming_ptr_invalid(void) __arm_streaming __arm_streaming_compatible;
86 // expected-cpp-error@+4 {{'__arm_streaming_compatible' and '__arm_streaming' are not compatible}}
87 // expected-cpp-note@+3 {{conflicting attribute is here}}
88 // expected-error@+2 {{'__arm_streaming_compatible' and '__arm_streaming' are not compatible}}
89 // expected-note@+1 {{conflicting attribute is here}}
90 typedef void (*fptrty7) (void) __arm_streaming __arm_streaming_compatible;
91 fptrty7 invalid_streaming_func() { return streaming_ptr_invalid; }
93 // expected-warning@+2 {{'__arm_streaming' only applies to non-K&R-style functions}}
94 // expected-error@+1 {{'__arm_streaming' only applies to function types; type here is 'void ()'}}
95 void function_no_prototype() __arm_streaming;
98 // Check for incorrect conversions of function pointers with the attributes
101 typedef void (*n_ptrty) (void);
102 typedef void (*s_ptrty) (void) __arm_streaming;
103 s_ptrty return_valid_streaming_fptr(s_ptrty f) { return f; }
105 // 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 (*)()')}}
106 // 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')}}
107 s_ptrty return_invalid_fptr_streaming_normal(n_ptrty f) { return f; }
108 // 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')}}
109 // 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)')}}
110 n_ptrty return_invalid_fptr_normal_streaming(s_ptrty f) { return f; }
112 // Test an instance where the result type is not a prototyped function, such that we still get a diagnostic.
113 typedef void (*nonproto_n_ptrty) ();
114 // 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')}}
115 // 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 (*)()')}}
116 nonproto_n_ptrty return_invalid_fptr_streaming_nonprotonormal(s_ptrty f) { return f; }
118 typedef void (*sc_ptrty) (void) __arm_streaming_compatible;
119 sc_ptrty return_valid_streaming_compatible_fptr(sc_ptrty f) { return f; }
121 // 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 (*)()')}}
122 // 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')}}
123 sc_ptrty return_invalid_fptr_streaming_compatible_normal(n_ptrty f) { return f; }
124 // 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')}}
125 // 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)')}}
126 n_ptrty return_invalid_fptr_normal_streaming_compatible(sc_ptrty f) { return f; }
128 typedef void (*sz_ptrty) (void) __arm_shared_za;
129 sz_ptrty return_valid_shared_za_fptr(sz_ptrty f) { return f; }
132 // expected-cpp-error@+2 {{cannot initialize return object of type 'sz_ptrty' (aka 'void (*)() __arm_shared_za') with an lvalue of type 'n_ptrty' (aka 'void (*)()')}}
133 // 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_shared_za')}}
134 sz_ptrty return_invalid_fptr_shared_za_normal(n_ptrty f) { return f; }
135 // expected-cpp-error@+2 {{cannot initialize return object of type 'n_ptrty' (aka 'void (*)()') with an lvalue of type 'sz_ptrty' (aka 'void (*)() __arm_shared_za')}}
136 // expected-error@+1 {{incompatible function pointer types returning 'sz_ptrty' (aka 'void (*)(void) __arm_shared_za') from a function with result type 'n_ptrty' (aka 'void (*)(void)')}}
137 n_ptrty return_invalid_fptr_normal_shared_za(sz_ptrty f) { return f; }
139 typedef void (*pz_ptrty) (void) __arm_preserves_za;
140 pz_ptrty return_valid_preserves_za_fptr(pz_ptrty f) { return f; }
142 // 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 (*)()')}}
143 // 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')}}
144 pz_ptrty return_invalid_fptr_preserves_za_normal(n_ptrty f) { return f; }
145 // No diagnostics, the preserves_za hint should be dropped silently.
146 n_ptrty return_invalid_fptr_normal_preserves_za(pz_ptrty f) { return f; }
148 // Test template instantiations
149 #ifdef __cplusplus
150 template <typename T> T templated(T x) __arm_streaming { return x; }
151 template <> int templated<int>(int x) __arm_streaming { return x + 1; }
152 template <> float templated<float>(float x) __arm_streaming { return x + 2; }
153 // 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}}
154 // expected-cpp-note@-4 {{candidate template ignored: could not match 'short (short) __arm_streaming' against 'short (short)'}}
155 template short templated<short>(short);
156 #endif
158 // Conflicting attributes on redeclarations
160 // expected-error@+5 {{function declared 'void (void) __arm_streaming_compatible' was previously declared 'void (void) __arm_streaming', which has different SME function attributes}}
161 // expected-note@+3 {{previous declaration is here}}
162 // expected-cpp-error@+3 {{function declared 'void () __arm_streaming_compatible' was previously declared 'void () __arm_streaming', which has different SME function attributes}}
163 // expected-cpp-note@+1 {{previous declaration is here}}
164 void redecl(void) __arm_streaming;
165 void redecl(void) __arm_streaming_compatible { }
167 // expected-error@+5 {{function declared 'void (void) __arm_shared_za' was previously declared 'void (void) __arm_shared_za __arm_preserves_za', which has different SME function attributes}}
168 // expected-note@+3 {{previous declaration is here}}
169 // expected-cpp-error@+3 {{function declared 'void () __arm_shared_za' was previously declared 'void () __arm_shared_za __arm_preserves_za', which has different SME function attributes}}
170 // expected-cpp-note@+1 {{previous declaration is here}}
171 void redecl_preserve_za(void) __arm_shared_za __arm_preserves_za;;
172 void redecl_preserve_za(void) __arm_shared_za {}
174 // expected-error@+5 {{function declared 'void (void) __arm_shared_za __arm_preserves_za' was previously declared 'void (void) __arm_shared_za', which has different SME function attributes}}
175 // expected-note@+3 {{previous declaration is here}}
176 // expected-cpp-error@+3 {{function declared 'void () __arm_shared_za __arm_preserves_za' was previously declared 'void () __arm_shared_za', which has different SME function attributes}}
177 // expected-cpp-note@+1 {{previous declaration is here}}
178 void redecl_nopreserve_za(void) __arm_shared_za;
179 void redecl_nopreserve_za(void) __arm_shared_za __arm_preserves_za {}
181 void non_za_definition(void (*shared_za_fn_ptr)(void) __arm_shared_za) {
182 sme_arm_new_za(); // OK
183 // expected-error@+2 {{call to a shared ZA function requires the caller to have ZA state}}
184 // expected-cpp-error@+1 {{call to a shared ZA function requires the caller to have ZA state}}
185 sme_arm_shared_za();
186 // expected-error@+2 {{call to a shared ZA function requires the caller to have ZA state}}
187 // expected-cpp-error@+1 {{call to a shared ZA function requires the caller to have ZA state}}
188 shared_za_fn_ptr();
191 void shared_za_definition(void (*shared_za_fn_ptr)(void) __arm_shared_za) __arm_shared_za {
192 sme_arm_shared_za(); // OK
193 shared_za_fn_ptr(); // OK
196 __arm_new_za void new_za_definition(void (*shared_za_fn_ptr)(void) __arm_shared_za) {
197 sme_arm_shared_za(); // OK
198 shared_za_fn_ptr(); // OK
201 #ifdef __cplusplus
202 int shared_za_initializer(void) __arm_shared_za;
203 // expected-cpp-error@+1 {{call to a shared ZA function requires the caller to have ZA state}}
204 int global = shared_za_initializer();
206 struct S {
207 virtual void shared_za_memberfn(void) __arm_shared_za;
210 struct S2 : public S {
211 // expected-cpp-error@+2 {{virtual function 'shared_za_memberfn' has different attributes ('void ()') than the function it overrides (which has 'void () __arm_shared_za')}}
212 // expected-cpp-note@-5 {{overridden virtual function is here}}
213 __arm_new_za void shared_za_memberfn(void) override {}
216 // The '__arm_preserves_za' property cannot be dropped when overriding a virtual
217 // function. It is however fine for the overriding function to be '__arm_preserves_za'
218 // even though the function that it overrides is not.
220 struct S_PreservesZA {
221 virtual void memberfn(void) __arm_preserves_za;
224 struct S_Drop_PreservesZA : S_PreservesZA {
225 // expected-cpp-error@+2 {{virtual function 'memberfn' has different attributes ('void ()') than the function it overrides (which has 'void () __arm_preserves_za')}}
226 // expected-cpp-note@-5 {{overridden virtual function is here}}
227 void memberfn(void) override {}
230 struct S_NoPreservesZA {
231 virtual void memberfn(void);
233 struct S_AddPreservesZA : S_NoPreservesZA {
234 // This is fine, the overridden function just adds more guarantees.
235 void memberfn(void) __arm_preserves_za override {}
239 // Check that the attribute propagates through template instantiations.
240 template <typename Ty>
241 struct S3 {
242 static constexpr int value = 0;
245 template <>
246 struct S3<void (*)()> {
247 static constexpr int value = 1;
250 template <>
251 struct S3<void (* __arm_streaming)()> {
252 static constexpr int value = 2;
255 template <>
256 struct S3<void (* __arm_streaming_compatible)()> {
257 static constexpr int value = 4;
260 template <>
261 struct S3<void (* __arm_shared_za)()> {
262 static constexpr int value = 8;
265 template <>
266 struct S3<void (* __arm_preserves_za)()> {
267 static constexpr int value = 16;
270 void normal_func(void) {}
271 void streaming_func(void) __arm_streaming {}
272 void streaming_compatible_func(void) __arm_streaming_compatible {}
273 void shared_za_func(void) __arm_shared_za {}
274 void preserves_za_func(void) __arm_preserves_za {}
276 static_assert(S3<decltype(+normal_func)>::value == 1, "why are we picking the wrong specialization?");
277 static_assert(S3<decltype(+streaming_func)>::value == 2, "why are we picking the wrong specialization?");
278 static_assert(S3<decltype(+streaming_compatible_func)>::value == 4, "why are we picking the wrong specialization?");
279 static_assert(S3<decltype(+shared_za_func)>::value == 8, "why are we picking the wrong specialization?");
280 static_assert(S3<decltype(+preserves_za_func)>::value == 16, "why are we picking the wrong specialization?");
282 // Also test the attribute is propagated with variadic templates
283 constexpr int eval_variadic_template() { return 0; }
284 template <typename T, typename... Other>
285 constexpr int eval_variadic_template(T f, Other... other) {
286 return S3<decltype(f)>::value + eval_variadic_template(other...);
288 static_assert(eval_variadic_template(normal_func, streaming_func,
289 streaming_compatible_func,
290 shared_za_func, preserves_za_func) == 31,
291 "attributes not propagated properly in variadic template");
293 // Test that the attribute is propagated with template specialization.
294 template<typename T> int test_templated_f(T);
295 template<> constexpr int test_templated_f<void(*)(void)>(void(*)(void)) { return 1; }
296 template<> constexpr int test_templated_f<void(*)(void)__arm_streaming>(void(*)(void)__arm_streaming) { return 2; }
297 template<> constexpr int test_templated_f<void(*)(void)__arm_streaming_compatible>(void(*)(void)__arm_streaming_compatible) { return 4; }
298 template<> constexpr int test_templated_f<void(*)(void)__arm_shared_za>(void(*)(void)__arm_shared_za) { return 8; }
299 template<> constexpr int test_templated_f<void(*)(void)__arm_preserves_za>(void(*)(void)__arm_preserves_za) { return 16; }
301 static_assert(test_templated_f(&normal_func) == 1, "Instantiated to wrong function");
302 static_assert(test_templated_f(&streaming_func) == 2, "Instantiated to wrong function");
303 static_assert(test_templated_f(&streaming_compatible_func) == 4, "Instantiated to wrong function");
304 static_assert(test_templated_f(&shared_za_func) == 8, "Instantiated to wrong function");
305 static_assert(test_templated_f(&preserves_za_func) == 16, "Instantiated to wrong function");
307 // expected-cpp-error@+2 {{'__arm_streaming' only applies to function types; type here is 'int'}}
308 // expected-error@+1 {{'__arm_streaming' only applies to function types; type here is 'int'}}
309 int invalid_type_for_attribute __arm_streaming;
311 // Test overloads
312 constexpr int overload(void f(void)) { return 1; }
313 constexpr int overload(void f(void) __arm_streaming) { return 2; }
314 constexpr int overload(void f(void) __arm_streaming_compatible) { return 4; }
315 constexpr int overload(void f(void) __arm_shared_za) { return 8; }
316 constexpr int overload(void f(void) __arm_preserves_za) { return 16; }
317 static_assert(overload(&normal_func) == 1, "Overloaded to wrong function");
318 static_assert(overload(&streaming_func) == 2, "Overloaded to wrong function");
319 static_assert(overload(&streaming_compatible_func) == 4, "Overloaded to wrong function");
320 static_assert(overload(&shared_za_func) == 8, "Overloaded to wrong function");
321 static_assert(overload(&preserves_za_func) == 16, "Overloaded to wrong function");
323 // Test implicit instantiation
324 template <typename T> struct X {
325 static void foo(T) __arm_streaming { }
327 constexpr int overload_int(void f(int)) { return 1; }
328 constexpr int overload_int(void f(int) __arm_streaming) { return 2; }
329 constexpr X<int> *ptr = 0;
330 static_assert(overload_int(ptr->foo) == 2, "Overloaded to the wrong function after implicit instantiation");
332 #endif // ifdef __cplusplus