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
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
; }
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
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);
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}}
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}}
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
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();
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
>
242 static constexpr int value
= 0;
246 struct S3
<void (*)()> {
247 static constexpr int value
= 1;
251 struct S3
<void (* __arm_streaming
)()> {
252 static constexpr int value
= 2;
256 struct S3
<void (* __arm_streaming_compatible
)()> {
257 static constexpr int value
= 4;
261 struct S3
<void (* __arm_shared_za
)()> {
262 static constexpr int value
= 8;
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
;
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