1 | // RUN: %clang_cc1 -fsyntax-only -verify -Wthread-safety %s |
2 | // RUN: %clang_cc1 -fsyntax-only -verify -Wthread-safety -std=c++98 %s |
3 | // RUN: %clang_cc1 -fsyntax-only -verify -Wthread-safety -std=c++11 %s -D CPP11 |
4 | |
5 | #define LOCKABLE __attribute__ ((lockable)) |
6 | #define SCOPED_LOCKABLE __attribute__ ((scoped_lockable)) |
7 | #define GUARDED_BY(x) __attribute__ ((guarded_by(x))) |
8 | #define GUARDED_VAR __attribute__ ((guarded_var)) |
9 | #define PT_GUARDED_BY(x) __attribute__ ((pt_guarded_by(x))) |
10 | #define PT_GUARDED_VAR __attribute__ ((pt_guarded_var)) |
11 | #define ACQUIRED_AFTER(...) __attribute__ ((acquired_after(__VA_ARGS__))) |
12 | #define ACQUIRED_BEFORE(...) __attribute__ ((acquired_before(__VA_ARGS__))) |
13 | #define EXCLUSIVE_LOCK_FUNCTION(...) __attribute__ ((exclusive_lock_function(__VA_ARGS__))) |
14 | #define SHARED_LOCK_FUNCTION(...) __attribute__ ((shared_lock_function(__VA_ARGS__))) |
15 | #define ASSERT_EXCLUSIVE_LOCK(...) __attribute__ ((assert_exclusive_lock(__VA_ARGS__))) |
16 | #define ASSERT_SHARED_LOCK(...) __attribute__ ((assert_shared_lock(__VA_ARGS__))) |
17 | #define EXCLUSIVE_TRYLOCK_FUNCTION(...) __attribute__ ((exclusive_trylock_function(__VA_ARGS__))) |
18 | #define SHARED_TRYLOCK_FUNCTION(...) __attribute__ ((shared_trylock_function(__VA_ARGS__))) |
19 | #define UNLOCK_FUNCTION(...) __attribute__ ((unlock_function(__VA_ARGS__))) |
20 | #define LOCK_RETURNED(x) __attribute__ ((lock_returned(x))) |
21 | #define LOCKS_EXCLUDED(...) __attribute__ ((locks_excluded(__VA_ARGS__))) |
22 | #define EXCLUSIVE_LOCKS_REQUIRED(...) \ |
23 | __attribute__ ((exclusive_locks_required(__VA_ARGS__))) |
24 | #define SHARED_LOCKS_REQUIRED(...) \ |
25 | __attribute__ ((shared_locks_required(__VA_ARGS__))) |
26 | #define NO_THREAD_SAFETY_ANALYSIS __attribute__ ((no_thread_safety_analysis)) |
27 | |
28 | |
29 | class LOCKABLE Mutex { |
30 | public: |
31 | void Lock() EXCLUSIVE_LOCK_FUNCTION(); |
32 | void ReaderLock() SHARED_LOCK_FUNCTION(); |
33 | void Unlock() UNLOCK_FUNCTION(); |
34 | |
35 | bool TryLock() EXCLUSIVE_TRYLOCK_FUNCTION(true); |
36 | bool ReaderTryLock() SHARED_TRYLOCK_FUNCTION(true); |
37 | |
38 | void AssertHeld() ASSERT_EXCLUSIVE_LOCK(); |
39 | void AssertReaderHeld() ASSERT_SHARED_LOCK(); |
40 | }; |
41 | |
42 | class UnlockableMu{ |
43 | }; |
44 | |
45 | class MuWrapper { |
46 | public: |
47 | Mutex mu; |
48 | Mutex getMu() { |
49 | return mu; |
50 | } |
51 | Mutex * getMuPointer() { |
52 | return μ |
53 | } |
54 | }; |
55 | |
56 | |
57 | class MuDoubleWrapper { |
58 | public: |
59 | MuWrapper* muWrapper; |
60 | MuWrapper* getWrapper() { |
61 | return muWrapper; |
62 | } |
63 | }; |
64 | |
65 | Mutex mu1; |
66 | UnlockableMu umu; |
67 | Mutex mu2; |
68 | MuWrapper muWrapper; |
69 | MuDoubleWrapper muDoubleWrapper; |
70 | Mutex* muPointer; |
71 | Mutex** muDoublePointer = & muPointer; |
72 | Mutex& muRef = mu1; |
73 | |
74 | //---------------------------------------// |
75 | // Scoping tests |
76 | //--------------------------------------// |
77 | |
78 | class Foo { |
79 | Mutex foomu; |
80 | void needLock() EXCLUSIVE_LOCK_FUNCTION(foomu); |
81 | }; |
82 | |
83 | class Foo2 { |
84 | void needLock() EXCLUSIVE_LOCK_FUNCTION(foomu); |
85 | Mutex foomu; |
86 | }; |
87 | |
88 | class Bar { |
89 | Mutex barmu; |
90 | Mutex barmu2 ACQUIRED_AFTER(barmu); |
91 | }; |
92 | |
93 | |
94 | //-----------------------------------------// |
95 | // No Thread Safety Analysis (noanal) // |
96 | //-----------------------------------------// |
97 | |
98 | // FIXME: Right now we cannot parse attributes put on function definitions |
99 | // We would like to patch this at some point. |
100 | |
101 | #if !__has_attribute(no_thread_safety_analysis) |
102 | #error "Should support no_thread_safety_analysis attribute" |
103 | #endif |
104 | |
105 | void noanal_fun() NO_THREAD_SAFETY_ANALYSIS; |
106 | |
107 | void noanal_fun_args() __attribute__((no_thread_safety_analysis(1))); // \ |
108 | // expected-error {{'no_thread_safety_analysis' attribute takes no arguments}} |
109 | |
110 | int noanal_testfn(int y) NO_THREAD_SAFETY_ANALYSIS; |
111 | |
112 | int noanal_testfn(int y) { |
113 | int x NO_THREAD_SAFETY_ANALYSIS = y; // \ |
114 | // expected-warning {{'no_thread_safety_analysis' attribute only applies to functions}} |
115 | return x; |
116 | }; |
117 | |
118 | int noanal_test_var NO_THREAD_SAFETY_ANALYSIS; // \ |
119 | // expected-warning {{'no_thread_safety_analysis' attribute only applies to functions}} |
120 | |
121 | class NoanalFoo { |
122 | private: |
123 | int test_field NO_THREAD_SAFETY_ANALYSIS; // \ |
124 | // expected-warning {{'no_thread_safety_analysis' attribute only applies to functions}} |
125 | void test_method() NO_THREAD_SAFETY_ANALYSIS; |
126 | }; |
127 | |
128 | class NO_THREAD_SAFETY_ANALYSIS NoanalTestClass { // \ |
129 | // expected-warning {{'no_thread_safety_analysis' attribute only applies to functions}} |
130 | }; |
131 | |
132 | void noanal_fun_params(int lvar NO_THREAD_SAFETY_ANALYSIS); // \ |
133 | // expected-warning {{'no_thread_safety_analysis' attribute only applies to functions}} |
134 | |
135 | |
136 | //-----------------------------------------// |
137 | // Guarded Var Attribute (gv) |
138 | //-----------------------------------------// |
139 | |
140 | #if !__has_attribute(guarded_var) |
141 | #error "Should support guarded_var attribute" |
142 | #endif |
143 | |
144 | int gv_var_noargs GUARDED_VAR; |
145 | |
146 | int gv_var_args __attribute__((guarded_var(1))); // \ |
147 | // expected-error {{'guarded_var' attribute takes no arguments}} |
148 | |
149 | class GVFoo { |
150 | private: |
151 | int gv_field_noargs GUARDED_VAR; |
152 | int gv_field_args __attribute__((guarded_var(1))); // \ |
153 | // expected-error {{'guarded_var' attribute takes no arguments}} |
154 | }; |
155 | |
156 | class GUARDED_VAR GV { // \ |
157 | // expected-warning {{'guarded_var' attribute only applies to non-static data members and global variables}} |
158 | }; |
159 | |
160 | void gv_function() GUARDED_VAR; // \ |
161 | // expected-warning {{'guarded_var' attribute only applies to}} |
162 | |
163 | void gv_function_params(int gv_lvar GUARDED_VAR); // \ |
164 | // expected-warning {{'guarded_var' attribute only applies to}} |
165 | |
166 | int gv_testfn(int y){ |
167 | int x GUARDED_VAR = y; // \ |
168 | // expected-warning {{'guarded_var' attribute only applies to}} |
169 | return x; |
170 | } |
171 | |
172 | //-----------------------------------------// |
173 | // Pt Guarded Var Attribute (pgv) |
174 | //-----------------------------------------// |
175 | |
176 | //FIXME: add support for boost::scoped_ptr<int> fancyptr and references |
177 | |
178 | #if !__has_attribute(pt_guarded_var) |
179 | #error "Should support pt_guarded_var attribute" |
180 | #endif |
181 | |
182 | int *pgv_pt_var_noargs PT_GUARDED_VAR; |
183 | |
184 | int pgv_var_noargs PT_GUARDED_VAR; // \ |
185 | // expected-warning {{'pt_guarded_var' only applies to pointer types; type here is 'int'}} |
186 | |
187 | class PGVFoo { |
188 | private: |
189 | int *pt_field_noargs PT_GUARDED_VAR; |
190 | int field_noargs PT_GUARDED_VAR; // \ |
191 | // expected-warning {{'pt_guarded_var' only applies to pointer types; type here is 'int'}} |
192 | int *gv_field_args __attribute__((pt_guarded_var(1))); // \ |
193 | // expected-error {{'pt_guarded_var' attribute takes no arguments}} |
194 | }; |
195 | |
196 | class PT_GUARDED_VAR PGV { // \ |
197 | // expected-warning {{'pt_guarded_var' attribute only applies to non-static data members and global variables}} |
198 | }; |
199 | |
200 | int *pgv_var_args __attribute__((pt_guarded_var(1))); // \ |
201 | // expected-error {{'pt_guarded_var' attribute takes no arguments}} |
202 | |
203 | |
204 | void pgv_function() PT_GUARDED_VAR; // \ |
205 | // expected-warning {{'pt_guarded_var' attribute only applies to}} |
206 | |
207 | void pgv_function_params(int *gv_lvar PT_GUARDED_VAR); // \ |
208 | // expected-warning {{'pt_guarded_var' attribute only applies to}} |
209 | |
210 | void pgv_testfn(int y){ |
211 | int *x PT_GUARDED_VAR = new int(0); // \ |
212 | // expected-warning {{'pt_guarded_var' attribute only applies to}} |
213 | delete x; |
214 | } |
215 | |
216 | //-----------------------------------------// |
217 | // Lockable Attribute (l) |
218 | //-----------------------------------------// |
219 | |
220 | //FIXME: In future we may want to add support for structs, ObjC classes, etc. |
221 | |
222 | #if !__has_attribute(lockable) |
223 | #error "Should support lockable attribute" |
224 | #endif |
225 | |
226 | class LOCKABLE LTestClass { |
227 | }; |
228 | |
229 | class __attribute__((lockable (1))) LTestClass_args { // \ |
230 | // expected-error {{'lockable' attribute takes no arguments}} |
231 | }; |
232 | |
233 | void l_test_function() LOCKABLE; // \ |
234 | // expected-warning {{'lockable' attribute only applies to structs, unions, and classes}} |
235 | |
236 | int l_testfn(int y) { |
237 | int x LOCKABLE = y; // \ |
238 | // expected-warning {{'lockable' attribute only applies to}} |
239 | return x; |
240 | } |
241 | |
242 | int l_test_var LOCKABLE; // \ |
243 | // expected-warning {{'lockable' attribute only applies to}} |
244 | |
245 | class LFoo { |
246 | private: |
247 | int test_field LOCKABLE; // \ |
248 | // expected-warning {{'lockable' attribute only applies to}} |
249 | void test_method() LOCKABLE; // \ |
250 | // expected-warning {{'lockable' attribute only applies to}} |
251 | }; |
252 | |
253 | |
254 | void l_function_params(int lvar LOCKABLE); // \ |
255 | // expected-warning {{'lockable' attribute only applies to}} |
256 | |
257 | |
258 | //-----------------------------------------// |
259 | // Scoped Lockable Attribute (sl) |
260 | //-----------------------------------------// |
261 | |
262 | #if !__has_attribute(scoped_lockable) |
263 | #error "Should support scoped_lockable attribute" |
264 | #endif |
265 | |
266 | class SCOPED_LOCKABLE SLTestClass { |
267 | }; |
268 | |
269 | class __attribute__((scoped_lockable (1))) SLTestClass_args { // \ |
270 | // expected-error {{'scoped_lockable' attribute takes no arguments}} |
271 | }; |
272 | |
273 | void sl_test_function() SCOPED_LOCKABLE; // \ |
274 | // expected-warning {{'scoped_lockable' attribute only applies to structs, unions, and classes}} |
275 | |
276 | int sl_testfn(int y) { |
277 | int x SCOPED_LOCKABLE = y; // \ |
278 | // expected-warning {{'scoped_lockable' attribute only applies to}} |
279 | return x; |
280 | } |
281 | |
282 | int sl_test_var SCOPED_LOCKABLE; // \ |
283 | // expected-warning {{'scoped_lockable' attribute only applies to}} |
284 | |
285 | class SLFoo { |
286 | private: |
287 | int test_field SCOPED_LOCKABLE; // \ |
288 | // expected-warning {{'scoped_lockable' attribute only applies to}} |
289 | void test_method() SCOPED_LOCKABLE; // \ |
290 | // expected-warning {{'scoped_lockable' attribute only applies to}} |
291 | }; |
292 | |
293 | |
294 | void sl_function_params(int lvar SCOPED_LOCKABLE); // \ |
295 | // expected-warning {{'scoped_lockable' attribute only applies to}} |
296 | |
297 | |
298 | //-----------------------------------------// |
299 | // Guarded By Attribute (gb) |
300 | //-----------------------------------------// |
301 | |
302 | // FIXME: Eventually, would we like this attribute to take more than 1 arg? |
303 | |
304 | #if !__has_attribute(guarded_by) |
305 | #error "Should support guarded_by attribute" |
306 | #endif |
307 | |
308 | //1. Check applied to the right types & argument number |
309 | |
310 | int gb_var_arg GUARDED_BY(mu1); |
311 | |
312 | int gb_non_ascii GUARDED_BY(L"wide"); // expected-warning {{ignoring 'guarded_by' attribute because its argument is invalid}} |
313 | |
314 | int gb_var_args __attribute__((guarded_by(mu1, mu2))); // \ |
315 | // expected-error {{'guarded_by' attribute takes one argument}} |
316 | |
317 | int gb_var_noargs __attribute__((guarded_by)); // \ |
318 | // expected-error {{'guarded_by' attribute takes one argument}} |
319 | |
320 | class GBFoo { |
321 | private: |
322 | int gb_field_noargs __attribute__((guarded_by)); // \ |
323 | // expected-error {{'guarded_by' attribute takes one argument}} |
324 | int gb_field_args GUARDED_BY(mu1); |
325 | }; |
326 | |
327 | class GUARDED_BY(mu1) GB { // \ |
328 | // expected-warning {{'guarded_by' attribute only applies to non-static data members and global variables}} |
329 | }; |
330 | |
331 | void gb_function() GUARDED_BY(mu1); // \ |
332 | // expected-warning {{'guarded_by' attribute only applies to}} |
333 | |
334 | void gb_function_params(int gv_lvar GUARDED_BY(mu1)); // \ |
335 | // expected-warning {{'guarded_by' attribute only applies to}} |
336 | |
337 | int gb_testfn(int y){ |
338 | int x GUARDED_BY(mu1) = y; // \ |
339 | // expected-warning {{'guarded_by' attribute only applies to}} |
340 | return x; |
341 | } |
342 | |
343 | //2. Check argument parsing. |
344 | |
345 | // legal attribute arguments |
346 | int gb_var_arg_1 GUARDED_BY(muWrapper.mu); |
347 | int gb_var_arg_2 GUARDED_BY(muDoubleWrapper.muWrapper->mu); |
348 | int gb_var_arg_3 GUARDED_BY(muWrapper.getMu()); |
349 | int gb_var_arg_4 GUARDED_BY(*muWrapper.getMuPointer()); |
350 | int gb_var_arg_5 GUARDED_BY(&mu1); |
351 | int gb_var_arg_6 GUARDED_BY(muRef); |
352 | int gb_var_arg_7 GUARDED_BY(muDoubleWrapper.getWrapper()->getMu()); |
353 | int gb_var_arg_8 GUARDED_BY(muPointer); |
354 | int gb_var_arg_9 GUARDED_BY(!&mu1); |
355 | int gb_var_arg_10 GUARDED_BY(!&*&mu1); |
356 | |
357 | // illegal attribute arguments |
358 | int gb_var_arg_bad_1 GUARDED_BY(1); // \ |
359 | // expected-warning {{'guarded_by' attribute requires arguments whose type is annotated with 'capability' attribute; type here is 'int'}} |
360 | int gb_var_arg_bad_2 GUARDED_BY("mu"); // \ |
361 | // expected-warning {{ignoring 'guarded_by' attribute because its argument is invalid}} |
362 | int gb_var_arg_bad_3 GUARDED_BY(muDoublePointer); // \ |
363 | // expected-warning {{'guarded_by' attribute requires arguments whose type is annotated with 'capability' attribute; type here is 'Mutex **'}} |
364 | int gb_var_arg_bad_4 GUARDED_BY(umu); // \ |
365 | // expected-warning {{'guarded_by' attribute requires arguments whose type is annotated with 'capability' attribute; type here is 'UnlockableMu'}} |
366 | |
367 | //3. |
368 | // Thread Safety analysis tests |
369 | |
370 | |
371 | //-----------------------------------------// |
372 | // Pt Guarded By Attribute (pgb) |
373 | //-----------------------------------------// |
374 | |
375 | #if !__has_attribute(pt_guarded_by) |
376 | #error "Should support pt_guarded_by attribute" |
377 | #endif |
378 | |
379 | //1. Check applied to the right types & argument number |
380 | |
381 | int *pgb_var_noargs __attribute__((pt_guarded_by)); // \ |
382 | // expected-error {{'pt_guarded_by' attribute takes one argument}} |
383 | |
384 | int *pgb_ptr_var_arg PT_GUARDED_BY(mu1); |
385 | |
386 | int *pgb_ptr_var_args __attribute__((pt_guarded_by(mu1, mu2))); // \ |
387 | // expected-error {{'pt_guarded_by' attribute takes one argument}} |
388 | |
389 | int pgb_var_args PT_GUARDED_BY(mu1); // \ |
390 | // expected-warning {{'pt_guarded_by' only applies to pointer types; type here is 'int'}} |
391 | |
392 | class PGBFoo { |
393 | private: |
394 | int *pgb_field_noargs __attribute__((pt_guarded_by)); // \ |
395 | // expected-error {{'pt_guarded_by' attribute takes one argument}} |
396 | int *pgb_field_args PT_GUARDED_BY(mu1); |
397 | }; |
398 | |
399 | class PT_GUARDED_BY(mu1) PGB { // \ |
400 | // expected-warning {{'pt_guarded_by' attribute only applies to non-static data members and global variables}} |
401 | }; |
402 | |
403 | void pgb_function() PT_GUARDED_BY(mu1); // \ |
404 | // expected-warning {{'pt_guarded_by' attribute only applies to}} |
405 | |
406 | void pgb_function_params(int gv_lvar PT_GUARDED_BY(mu1)); // \ |
407 | // expected-warning {{'pt_guarded_by' attribute only applies to}} |
408 | |
409 | void pgb_testfn(int y){ |
410 | int *x PT_GUARDED_BY(mu1) = new int(0); // \ |
411 | // expected-warning {{'pt_guarded_by' attribute only applies to}} |
412 | delete x; |
413 | } |
414 | |
415 | //2. Check argument parsing. |
416 | |
417 | // legal attribute arguments |
418 | int * pgb_var_arg_1 PT_GUARDED_BY(muWrapper.mu); |
419 | int * pgb_var_arg_2 PT_GUARDED_BY(muDoubleWrapper.muWrapper->mu); |
420 | int * pgb_var_arg_3 PT_GUARDED_BY(muWrapper.getMu()); |
421 | int * pgb_var_arg_4 PT_GUARDED_BY(*muWrapper.getMuPointer()); |
422 | int * pgb_var_arg_5 PT_GUARDED_BY(&mu1); |
423 | int * pgb_var_arg_6 PT_GUARDED_BY(muRef); |
424 | int * pgb_var_arg_7 PT_GUARDED_BY(muDoubleWrapper.getWrapper()->getMu()); |
425 | int * pgb_var_arg_8 PT_GUARDED_BY(muPointer); |
426 | |
427 | |
428 | // illegal attribute arguments |
429 | int * pgb_var_arg_bad_1 PT_GUARDED_BY(1); // \ |
430 | // expected-warning {{'pt_guarded_by' attribute requires arguments whose type is annotated with 'capability' attribute; type here is 'int'}} |
431 | int * pgb_var_arg_bad_2 PT_GUARDED_BY("mu"); // \ |
432 | // expected-warning {{ignoring 'pt_guarded_by' attribute because its argument is invalid}} |
433 | int * pgb_var_arg_bad_3 PT_GUARDED_BY(muDoublePointer); // \ |
434 | // expected-warning {{'pt_guarded_by' attribute requires arguments whose type is annotated with 'capability' attribute; type here is 'Mutex **'}} |
435 | int * pgb_var_arg_bad_4 PT_GUARDED_BY(umu); // \ |
436 | // expected-warning {{'pt_guarded_by' attribute requires arguments whose type is annotated with 'capability' attribute}} |
437 | |
438 | |
439 | //-----------------------------------------// |
440 | // Acquired After (aa) |
441 | //-----------------------------------------// |
442 | |
443 | // FIXME: Would we like this attribute to take more than 1 arg? |
444 | |
445 | #if !__has_attribute(acquired_after) |
446 | #error "Should support acquired_after attribute" |
447 | #endif |
448 | |
449 | Mutex mu_aa ACQUIRED_AFTER(mu1); |
450 | |
451 | Mutex aa_var_noargs __attribute__((acquired_after)); // \ |
452 | // expected-error {{'acquired_after' attribute takes at least 1 argument}} |
453 | |
454 | class AAFoo { |
455 | private: |
456 | Mutex aa_field_noargs __attribute__((acquired_after)); // \ |
457 | // expected-error {{'acquired_after' attribute takes at least 1 argument}} |
458 | Mutex aa_field_args ACQUIRED_AFTER(mu1); |
459 | }; |
460 | |
461 | class ACQUIRED_AFTER(mu1) AA { // \ |
462 | // expected-warning {{'acquired_after' attribute only applies to non-static data members and global variables}} |
463 | }; |
464 | |
465 | void aa_function() ACQUIRED_AFTER(mu1); // \ |
466 | // expected-warning {{'acquired_after' attribute only applies to}} |
467 | |
468 | void aa_function_params(int gv_lvar ACQUIRED_AFTER(mu1)); // \ |
469 | // expected-warning {{'acquired_after' attribute only applies to}} |
470 | |
471 | void aa_testfn(int y){ |
472 | Mutex x ACQUIRED_AFTER(mu1) = Mutex(); // \ |
473 | // expected-warning {{'acquired_after' attribute only applies to}} |
474 | } |
475 | |
476 | //Check argument parsing. |
477 | |
478 | // legal attribute arguments |
479 | Mutex aa_var_arg_1 ACQUIRED_AFTER(muWrapper.mu); |
480 | Mutex aa_var_arg_2 ACQUIRED_AFTER(muDoubleWrapper.muWrapper->mu); |
481 | Mutex aa_var_arg_3 ACQUIRED_AFTER(muWrapper.getMu()); |
482 | Mutex aa_var_arg_4 ACQUIRED_AFTER(*muWrapper.getMuPointer()); |
483 | Mutex aa_var_arg_5 ACQUIRED_AFTER(&mu1); |
484 | Mutex aa_var_arg_6 ACQUIRED_AFTER(muRef); |
485 | Mutex aa_var_arg_7 ACQUIRED_AFTER(muDoubleWrapper.getWrapper()->getMu()); |
486 | Mutex aa_var_arg_8 ACQUIRED_AFTER(muPointer); |
487 | |
488 | |
489 | // illegal attribute arguments |
490 | Mutex aa_var_arg_bad_1 ACQUIRED_AFTER(1); // \ |
491 | // expected-warning {{'acquired_after' attribute requires arguments whose type is annotated with 'capability' attribute; type here is 'int'}} |
492 | Mutex aa_var_arg_bad_2 ACQUIRED_AFTER("mu"); // \ |
493 | // expected-warning {{ignoring 'acquired_after' attribute because its argument is invalid}} |
494 | Mutex aa_var_arg_bad_3 ACQUIRED_AFTER(muDoublePointer); // \ |
495 | // expected-warning {{'acquired_after' attribute requires arguments whose type is annotated with 'capability' attribute; type here is 'Mutex **'}} |
496 | Mutex aa_var_arg_bad_4 ACQUIRED_AFTER(umu); // \ |
497 | // expected-warning {{'acquired_after' attribute requires arguments whose type is annotated with 'capability' attribute}} |
498 | UnlockableMu aa_var_arg_bad_5 ACQUIRED_AFTER(mu_aa); // \ |
499 | // expected-warning {{'acquired_after' attribute can only be applied in a context annotated with 'capability("mutex")' attribute}} |
500 | |
501 | //-----------------------------------------// |
502 | // Acquired Before (ab) |
503 | //-----------------------------------------// |
504 | |
505 | #if !__has_attribute(acquired_before) |
506 | #error "Should support acquired_before attribute" |
507 | #endif |
508 | |
509 | Mutex mu_ab ACQUIRED_BEFORE(mu1); |
510 | |
511 | Mutex ab_var_noargs __attribute__((acquired_before)); // \ |
512 | // expected-error {{'acquired_before' attribute takes at least 1 argument}} |
513 | |
514 | class ABFoo { |
515 | private: |
516 | Mutex ab_field_noargs __attribute__((acquired_before)); // \ |
517 | // expected-error {{'acquired_before' attribute takes at least 1 argument}} |
518 | Mutex ab_field_args ACQUIRED_BEFORE(mu1); |
519 | }; |
520 | |
521 | class ACQUIRED_BEFORE(mu1) AB { // \ |
522 | // expected-warning {{'acquired_before' attribute only applies to non-static data members and global variables}} |
523 | }; |
524 | |
525 | void ab_function() ACQUIRED_BEFORE(mu1); // \ |
526 | // expected-warning {{'acquired_before' attribute only applies to}} |
527 | |
528 | void ab_function_params(int gv_lvar ACQUIRED_BEFORE(mu1)); // \ |
529 | // expected-warning {{'acquired_before' attribute only applies to}} |
530 | |
531 | void ab_testfn(int y){ |
532 | Mutex x ACQUIRED_BEFORE(mu1) = Mutex(); // \ |
533 | // expected-warning {{'acquired_before' attribute only applies to}} |
534 | } |
535 | |
536 | // Note: illegal int ab_int ACQUIRED_BEFORE(mu1) will |
537 | // be taken care of by warnings that ab__int is not lockable. |
538 | |
539 | //Check argument parsing. |
540 | |
541 | // legal attribute arguments |
542 | Mutex ab_var_arg_1 ACQUIRED_BEFORE(muWrapper.mu); |
543 | Mutex ab_var_arg_2 ACQUIRED_BEFORE(muDoubleWrapper.muWrapper->mu); |
544 | Mutex ab_var_arg_3 ACQUIRED_BEFORE(muWrapper.getMu()); |
545 | Mutex ab_var_arg_4 ACQUIRED_BEFORE(*muWrapper.getMuPointer()); |
546 | Mutex ab_var_arg_5 ACQUIRED_BEFORE(&mu1); |
547 | Mutex ab_var_arg_6 ACQUIRED_BEFORE(muRef); |
548 | Mutex ab_var_arg_7 ACQUIRED_BEFORE(muDoubleWrapper.getWrapper()->getMu()); |
549 | Mutex ab_var_arg_8 ACQUIRED_BEFORE(muPointer); |
550 | |
551 | |
552 | // illegal attribute arguments |
553 | Mutex ab_var_arg_bad_1 ACQUIRED_BEFORE(1); // \ |
554 | // expected-warning {{'acquired_before' attribute requires arguments whose type is annotated with 'capability' attribute; type here is 'int'}} |
555 | Mutex ab_var_arg_bad_2 ACQUIRED_BEFORE("mu"); // \ |
556 | // expected-warning {{ignoring 'acquired_before' attribute because its argument is invalid}} |
557 | Mutex ab_var_arg_bad_3 ACQUIRED_BEFORE(muDoublePointer); // \ |
558 | // expected-warning {{'acquired_before' attribute requires arguments whose type is annotated with 'capability' attribute; type here is 'Mutex **'}} |
559 | Mutex ab_var_arg_bad_4 ACQUIRED_BEFORE(umu); // \ |
560 | // expected-warning {{'acquired_before' attribute requires arguments whose type is annotated with 'capability' attribute}} |
561 | UnlockableMu ab_var_arg_bad_5 ACQUIRED_BEFORE(mu_ab); // \ |
562 | // expected-warning {{'acquired_before' attribute can only be applied in a context annotated with 'capability("mutex")' attribute}} |
563 | |
564 | |
565 | //-----------------------------------------// |
566 | // Exclusive Lock Function (elf) |
567 | //-----------------------------------------// |
568 | |
569 | #if !__has_attribute(exclusive_lock_function) |
570 | #error "Should support exclusive_lock_function attribute" |
571 | #endif |
572 | |
573 | // takes zero or more arguments, all locks (vars/fields) |
574 | |
575 | void elf_function() EXCLUSIVE_LOCK_FUNCTION(); // expected-warning {{'exclusive_lock_function' attribute without capability arguments can only be applied to non-static methods of a class}} |
576 | |
577 | void elf_function_args() EXCLUSIVE_LOCK_FUNCTION(mu1, mu2); |
578 | |
579 | int elf_testfn(int y) EXCLUSIVE_LOCK_FUNCTION(); // expected-warning {{'exclusive_lock_function' attribute without capability arguments can only be applied to non-static methods of a class}} |
580 | |
581 | int elf_testfn(int y) { |
582 | int x EXCLUSIVE_LOCK_FUNCTION() = y; // \ |
583 | // expected-warning {{'exclusive_lock_function' attribute only applies to functions}} |
584 | return x; |
585 | }; |
586 | |
587 | int elf_test_var EXCLUSIVE_LOCK_FUNCTION(); // \ |
588 | // expected-warning {{'exclusive_lock_function' attribute only applies to functions}} |
589 | |
590 | class ElfFoo { |
591 | private: |
592 | int test_field EXCLUSIVE_LOCK_FUNCTION(); // \ |
593 | // expected-warning {{'exclusive_lock_function' attribute only applies to functions}} |
594 | void test_method() EXCLUSIVE_LOCK_FUNCTION(); // \ |
595 | // expected-warning {{'exclusive_lock_function' attribute without capability arguments refers to 'this', but 'ElfFoo' isn't annotated with 'capability' or 'scoped_lockable' attribute}} |
596 | }; |
597 | |
598 | class EXCLUSIVE_LOCK_FUNCTION() ElfTestClass { // \ |
599 | // expected-warning {{'exclusive_lock_function' attribute only applies to functions}} |
600 | }; |
601 | |
602 | void elf_fun_params(int lvar EXCLUSIVE_LOCK_FUNCTION()); // \ |
603 | // expected-warning {{'exclusive_lock_function' attribute only applies to functions}} |
604 | |
605 | // Check argument parsing. |
606 | |
607 | // legal attribute arguments |
608 | int elf_function_1() EXCLUSIVE_LOCK_FUNCTION(muWrapper.mu); |
609 | int elf_function_2() EXCLUSIVE_LOCK_FUNCTION(muDoubleWrapper.muWrapper->mu); |
610 | int elf_function_3() EXCLUSIVE_LOCK_FUNCTION(muWrapper.getMu()); |
611 | int elf_function_4() EXCLUSIVE_LOCK_FUNCTION(*muWrapper.getMuPointer()); |
612 | int elf_function_5() EXCLUSIVE_LOCK_FUNCTION(&mu1); |
613 | int elf_function_6() EXCLUSIVE_LOCK_FUNCTION(muRef); |
614 | int elf_function_7() EXCLUSIVE_LOCK_FUNCTION(muDoubleWrapper.getWrapper()->getMu()); |
615 | int elf_function_8() EXCLUSIVE_LOCK_FUNCTION(muPointer); |
616 | int elf_function_9(Mutex x) EXCLUSIVE_LOCK_FUNCTION(1); |
617 | int elf_function_9(Mutex x, Mutex y) EXCLUSIVE_LOCK_FUNCTION(1,2); |
618 | |
619 | |
620 | // illegal attribute arguments |
621 | int elf_function_bad_2() EXCLUSIVE_LOCK_FUNCTION("mu"); // \ |
622 | // expected-warning {{ignoring 'exclusive_lock_function' attribute because its argument is invalid}} |
623 | int elf_function_bad_3() EXCLUSIVE_LOCK_FUNCTION(muDoublePointer); // \ |
624 | // expected-warning {{'exclusive_lock_function' attribute requires arguments whose type is annotated with 'capability' attribute; type here is 'Mutex **'}} |
625 | int elf_function_bad_4() EXCLUSIVE_LOCK_FUNCTION(umu); // \ |
626 | // expected-warning {{'exclusive_lock_function' attribute requires arguments whose type is annotated with 'capability' attribute}} |
627 | |
628 | int elf_function_bad_1() EXCLUSIVE_LOCK_FUNCTION(1); // \ |
629 | // expected-error {{'exclusive_lock_function' attribute parameter 1 is out of bounds: no parameters to index into}} |
630 | int elf_function_bad_5(Mutex x) EXCLUSIVE_LOCK_FUNCTION(0); // \ |
631 | // expected-error {{'exclusive_lock_function' attribute parameter 1 is out of bounds: can only be 1, since there is one parameter}} |
632 | int elf_function_bad_6(Mutex x, Mutex y) EXCLUSIVE_LOCK_FUNCTION(0); // \ |
633 | // expected-error {{'exclusive_lock_function' attribute parameter 1 is out of bounds: must be between 1 and 2}} |
634 | int elf_function_bad_7() EXCLUSIVE_LOCK_FUNCTION(0); // \ |
635 | // expected-error {{'exclusive_lock_function' attribute parameter 1 is out of bounds: no parameters to index into}} |
636 | |
637 | |
638 | //-----------------------------------------// |
639 | // Shared Lock Function (slf) |
640 | //-----------------------------------------// |
641 | |
642 | #if !__has_attribute(shared_lock_function) |
643 | #error "Should support shared_lock_function attribute" |
644 | #endif |
645 | |
646 | // takes zero or more arguments, all locks (vars/fields) |
647 | |
648 | void slf_function() SHARED_LOCK_FUNCTION(); // expected-warning {{'shared_lock_function' attribute without capability arguments can only be applied to non-static methods of a class}} |
649 | |
650 | void slf_function_args() SHARED_LOCK_FUNCTION(mu1, mu2); |
651 | |
652 | int slf_testfn(int y) SHARED_LOCK_FUNCTION(); // expected-warning {{'shared_lock_function' attribute without capability arguments can only be applied to non-static methods of a class}} |
653 | |
654 | int slf_testfn(int y) { |
655 | int x SHARED_LOCK_FUNCTION() = y; // \ |
656 | // expected-warning {{'shared_lock_function' attribute only applies to functions}} |
657 | return x; |
658 | }; |
659 | |
660 | int slf_test_var SHARED_LOCK_FUNCTION(); // \ |
661 | // expected-warning {{'shared_lock_function' attribute only applies to functions}} |
662 | |
663 | void slf_fun_params(int lvar SHARED_LOCK_FUNCTION()); // \ |
664 | // expected-warning {{'shared_lock_function' attribute only applies to functions}} |
665 | |
666 | class SlfFoo { |
667 | private: |
668 | int test_field SHARED_LOCK_FUNCTION(); // \ |
669 | // expected-warning {{'shared_lock_function' attribute only applies to functions}} |
670 | void test_method() SHARED_LOCK_FUNCTION(); // \ |
671 | // expected-warning {{'shared_lock_function' attribute without capability arguments refers to 'this', but 'SlfFoo' isn't annotated with 'capability' or 'scoped_lockable' attribute}} |
672 | }; |
673 | |
674 | class SHARED_LOCK_FUNCTION() SlfTestClass { // \ |
675 | // expected-warning {{'shared_lock_function' attribute only applies to functions}} |
676 | }; |
677 | |
678 | // Check argument parsing. |
679 | |
680 | // legal attribute arguments |
681 | int slf_function_1() SHARED_LOCK_FUNCTION(muWrapper.mu); |
682 | int slf_function_2() SHARED_LOCK_FUNCTION(muDoubleWrapper.muWrapper->mu); |
683 | int slf_function_3() SHARED_LOCK_FUNCTION(muWrapper.getMu()); |
684 | int slf_function_4() SHARED_LOCK_FUNCTION(*muWrapper.getMuPointer()); |
685 | int slf_function_5() SHARED_LOCK_FUNCTION(&mu1); |
686 | int slf_function_6() SHARED_LOCK_FUNCTION(muRef); |
687 | int slf_function_7() SHARED_LOCK_FUNCTION(muDoubleWrapper.getWrapper()->getMu()); |
688 | int slf_function_8() SHARED_LOCK_FUNCTION(muPointer); |
689 | int slf_function_9(Mutex x) SHARED_LOCK_FUNCTION(1); |
690 | int slf_function_9(Mutex x, Mutex y) SHARED_LOCK_FUNCTION(1,2); |
691 | |
692 | |
693 | // illegal attribute arguments |
694 | int slf_function_bad_2() SHARED_LOCK_FUNCTION("mu"); // \ |
695 | // expected-warning {{ignoring 'shared_lock_function' attribute because its argument is invalid}} |
696 | int slf_function_bad_3() SHARED_LOCK_FUNCTION(muDoublePointer); // \ |
697 | // expected-warning {{'shared_lock_function' attribute requires arguments whose type is annotated with 'capability' attribute; type here is 'Mutex **'}} |
698 | int slf_function_bad_4() SHARED_LOCK_FUNCTION(umu); // \ |
699 | // expected-warning {{'shared_lock_function' attribute requires arguments whose type is annotated with 'capability' attribute}} |
700 | |
701 | int slf_function_bad_1() SHARED_LOCK_FUNCTION(1); // \ |
702 | // expected-error {{'shared_lock_function' attribute parameter 1 is out of bounds: no parameters to index into}} |
703 | int slf_function_bad_5(Mutex x) SHARED_LOCK_FUNCTION(0); // \ |
704 | // expected-error {{'shared_lock_function' attribute parameter 1 is out of bounds: can only be 1, since there is one parameter}} |
705 | int slf_function_bad_6(Mutex x, Mutex y) SHARED_LOCK_FUNCTION(0); // \ |
706 | // expected-error {{'shared_lock_function' attribute parameter 1 is out of bounds: must be between 1 and 2}} |
707 | int slf_function_bad_7() SHARED_LOCK_FUNCTION(0); // \ |
708 | // expected-error {{'shared_lock_function' attribute parameter 1 is out of bounds: no parameters to index into}} |
709 | |
710 | |
711 | //-----------------------------------------// |
712 | // Exclusive TryLock Function (etf) |
713 | //-----------------------------------------// |
714 | |
715 | #if !__has_attribute(exclusive_trylock_function) |
716 | #error "Should support exclusive_trylock_function attribute" |
717 | #endif |
718 | |
719 | // takes a mandatory boolean or integer argument specifying the retval |
720 | // plus an optional list of locks (vars/fields) |
721 | |
722 | void etf_function() __attribute__((exclusive_trylock_function)); // \ |
723 | // expected-error {{'exclusive_trylock_function' attribute takes at least 1 argument}} |
724 | |
725 | void etf_function_args() EXCLUSIVE_TRYLOCK_FUNCTION(1, mu2); |
726 | |
727 | void etf_function_arg() EXCLUSIVE_TRYLOCK_FUNCTION(1); // \ |
728 | // expected-warning {{'exclusive_trylock_function' attribute without capability arguments can only be applied to non-static methods of a class}} |
729 | |
730 | int etf_testfn(int y) EXCLUSIVE_TRYLOCK_FUNCTION(1); // \ |
731 | // expected-warning {{'exclusive_trylock_function' attribute without capability arguments can only be applied to non-static methods of a class}} |
732 | |
733 | int etf_testfn(int y) { |
734 | int x EXCLUSIVE_TRYLOCK_FUNCTION(1) = y; // \ |
735 | // expected-warning {{'exclusive_trylock_function' attribute only applies to functions}} |
736 | return x; |
737 | }; |
738 | |
739 | int etf_test_var EXCLUSIVE_TRYLOCK_FUNCTION(1); // \ |
740 | // expected-warning {{'exclusive_trylock_function' attribute only applies to functions}} |
741 | |
742 | class EtfFoo { |
743 | private: |
744 | int test_field EXCLUSIVE_TRYLOCK_FUNCTION(1); // \ |
745 | // expected-warning {{'exclusive_trylock_function' attribute only applies to functions}} |
746 | void test_method() EXCLUSIVE_TRYLOCK_FUNCTION(1); // \ |
747 | // expected-warning {{'exclusive_trylock_function' attribute without capability arguments refers to 'this', but 'EtfFoo' isn't annotated with 'capability' or 'scoped_lockable' attribute}} |
748 | }; |
749 | |
750 | class EXCLUSIVE_TRYLOCK_FUNCTION(1) EtfTestClass { // \ |
751 | // expected-warning {{'exclusive_trylock_function' attribute only applies to functions}} |
752 | }; |
753 | |
754 | void etf_fun_params(int lvar EXCLUSIVE_TRYLOCK_FUNCTION(1)); // \ |
755 | // expected-warning {{'exclusive_trylock_function' attribute only applies to functions}} |
756 | |
757 | // Check argument parsing. |
758 | |
759 | // legal attribute arguments |
760 | int etf_function_1() EXCLUSIVE_TRYLOCK_FUNCTION(1, muWrapper.mu); |
761 | int etf_function_2() EXCLUSIVE_TRYLOCK_FUNCTION(1, muDoubleWrapper.muWrapper->mu); |
762 | int etf_function_3() EXCLUSIVE_TRYLOCK_FUNCTION(1, muWrapper.getMu()); |
763 | int etf_function_4() EXCLUSIVE_TRYLOCK_FUNCTION(1, *muWrapper.getMuPointer()); |
764 | int etf_function_5() EXCLUSIVE_TRYLOCK_FUNCTION(1, &mu1); |
765 | int etf_function_6() EXCLUSIVE_TRYLOCK_FUNCTION(1, muRef); |
766 | int etf_function_7() EXCLUSIVE_TRYLOCK_FUNCTION(1, muDoubleWrapper.getWrapper()->getMu()); |
767 | int etf_functetfn_8() EXCLUSIVE_TRYLOCK_FUNCTION(1, muPointer); |
768 | int etf_function_9() EXCLUSIVE_TRYLOCK_FUNCTION(true); // \ |
769 | // expected-warning {{'exclusive_trylock_function' attribute without capability arguments can only be applied to non-static methods of a class}} |
770 | |
771 | |
772 | // illegal attribute arguments |
773 | int etf_function_bad_1() EXCLUSIVE_TRYLOCK_FUNCTION(mu1); // \ |
774 | // expected-error {{'exclusive_trylock_function' attribute requires parameter 1 to be int or bool}} |
775 | int etf_function_bad_2() EXCLUSIVE_TRYLOCK_FUNCTION("mu"); // \ |
776 | // expected-error {{'exclusive_trylock_function' attribute requires parameter 1 to be int or bool}} |
777 | int etf_function_bad_3() EXCLUSIVE_TRYLOCK_FUNCTION(muDoublePointer); // \ |
778 | // expected-error {{'exclusive_trylock_function' attribute requires parameter 1 to be int or bool}} |
779 | |
780 | int etf_function_bad_4() EXCLUSIVE_TRYLOCK_FUNCTION(1, "mu"); // \ |
781 | // expected-warning {{ignoring 'exclusive_trylock_function' attribute because its argument is invalid}} |
782 | int etf_function_bad_5() EXCLUSIVE_TRYLOCK_FUNCTION(1, muDoublePointer); // \ |
783 | // expected-warning {{'exclusive_trylock_function' attribute requires arguments whose type is annotated with 'capability' attribute; type here is 'Mutex **'}} |
784 | int etf_function_bad_6() EXCLUSIVE_TRYLOCK_FUNCTION(1, umu); // \ |
785 | // expected-warning {{'exclusive_trylock_function' attribute requires arguments whose type is annotated with 'capability' attribute}} |
786 | |
787 | |
788 | //-----------------------------------------// |
789 | // Shared TryLock Function (stf) |
790 | //-----------------------------------------// |
791 | |
792 | #if !__has_attribute(shared_trylock_function) |
793 | #error "Should support shared_trylock_function attribute" |
794 | #endif |
795 | |
796 | // takes a mandatory boolean or integer argument specifying the retval |
797 | // plus an optional list of locks (vars/fields) |
798 | |
799 | void stf_function() __attribute__((shared_trylock_function)); // \ |
800 | // expected-error {{'shared_trylock_function' attribute takes at least 1 argument}} |
801 | |
802 | void stf_function_args() SHARED_TRYLOCK_FUNCTION(1, mu2); |
803 | |
804 | void stf_function_arg() SHARED_TRYLOCK_FUNCTION(1); // \ |
805 | // expected-warning {{'shared_trylock_function' attribute without capability arguments can only be applied to non-static methods of a class}} |
806 | |
807 | int stf_testfn(int y) SHARED_TRYLOCK_FUNCTION(1); // \ |
808 | // expected-warning {{'shared_trylock_function' attribute without capability arguments can only be applied to non-static methods of a class}} |
809 | |
810 | int stf_testfn(int y) { |
811 | int x SHARED_TRYLOCK_FUNCTION(1) = y; // \ |
812 | // expected-warning {{'shared_trylock_function' attribute only applies to functions}} |
813 | return x; |
814 | }; |
815 | |
816 | int stf_test_var SHARED_TRYLOCK_FUNCTION(1); // \ |
817 | // expected-warning {{'shared_trylock_function' attribute only applies to functions}} |
818 | |
819 | void stf_fun_params(int lvar SHARED_TRYLOCK_FUNCTION(1)); // \ |
820 | // expected-warning {{'shared_trylock_function' attribute only applies to functions}} |
821 | |
822 | |
823 | class StfFoo { |
824 | private: |
825 | int test_field SHARED_TRYLOCK_FUNCTION(1); // \ |
826 | // expected-warning {{'shared_trylock_function' attribute only applies to functions}} |
827 | void test_method() SHARED_TRYLOCK_FUNCTION(1); // \ |
828 | // expected-warning {{'shared_trylock_function' attribute without capability arguments refers to 'this', but 'StfFoo' isn't annotated with 'capability' or 'scoped_lockable' attribute}} |
829 | }; |
830 | |
831 | class SHARED_TRYLOCK_FUNCTION(1) StfTestClass { // \ |
832 | // expected-warning {{'shared_trylock_function' attribute only applies to functions}} |
833 | }; |
834 | |
835 | // Check argument parsing. |
836 | |
837 | // legal attribute arguments |
838 | int stf_function_1() SHARED_TRYLOCK_FUNCTION(1, muWrapper.mu); |
839 | int stf_function_2() SHARED_TRYLOCK_FUNCTION(1, muDoubleWrapper.muWrapper->mu); |
840 | int stf_function_3() SHARED_TRYLOCK_FUNCTION(1, muWrapper.getMu()); |
841 | int stf_function_4() SHARED_TRYLOCK_FUNCTION(1, *muWrapper.getMuPointer()); |
842 | int stf_function_5() SHARED_TRYLOCK_FUNCTION(1, &mu1); |
843 | int stf_function_6() SHARED_TRYLOCK_FUNCTION(1, muRef); |
844 | int stf_function_7() SHARED_TRYLOCK_FUNCTION(1, muDoubleWrapper.getWrapper()->getMu()); |
845 | int stf_function_8() SHARED_TRYLOCK_FUNCTION(1, muPointer); |
846 | int stf_function_9() SHARED_TRYLOCK_FUNCTION(true); // \ |
847 | // expected-warning {{'shared_trylock_function' attribute without capability arguments can only be applied to non-static methods of a class}} |
848 | |
849 | |
850 | // illegal attribute arguments |
851 | int stf_function_bad_1() SHARED_TRYLOCK_FUNCTION(mu1); // \ |
852 | // expected-error {{'shared_trylock_function' attribute requires parameter 1 to be int or bool}} |
853 | int stf_function_bad_2() SHARED_TRYLOCK_FUNCTION("mu"); // \ |
854 | // expected-error {{'shared_trylock_function' attribute requires parameter 1 to be int or bool}} |
855 | int stf_function_bad_3() SHARED_TRYLOCK_FUNCTION(muDoublePointer); // \ |
856 | // expected-error {{'shared_trylock_function' attribute requires parameter 1 to be int or bool}} |
857 | |
858 | int stf_function_bad_4() SHARED_TRYLOCK_FUNCTION(1, "mu"); // \ |
859 | // expected-warning {{ignoring 'shared_trylock_function' attribute because its argument is invalid}} |
860 | int stf_function_bad_5() SHARED_TRYLOCK_FUNCTION(1, muDoublePointer); // \ |
861 | // expected-warning {{'shared_trylock_function' attribute requires arguments whose type is annotated with 'capability' attribute; type here is 'Mutex **'}} |
862 | int stf_function_bad_6() SHARED_TRYLOCK_FUNCTION(1, umu); // \ |
863 | // expected-warning {{'shared_trylock_function' attribute requires arguments whose type is annotated with 'capability' attribute}} |
864 | |
865 | |
866 | //-----------------------------------------// |
867 | // Unlock Function (uf) |
868 | //-----------------------------------------// |
869 | |
870 | #if !__has_attribute(unlock_function) |
871 | #error "Should support unlock_function attribute" |
872 | #endif |
873 | |
874 | // takes zero or more arguments, all locks (vars/fields) |
875 | |
876 | void uf_function() UNLOCK_FUNCTION(); // \ |
877 | // expected-warning {{'unlock_function' attribute without capability arguments can only be applied to non-static methods of a class}} |
878 | |
879 | |
880 | void uf_function_args() UNLOCK_FUNCTION(mu1, mu2); |
881 | |
882 | int uf_testfn(int y) UNLOCK_FUNCTION(); //\ |
883 | // expected-warning {{'unlock_function' attribute without capability arguments can only be applied to non-static methods of a class}} |
884 | |
885 | int uf_testfn(int y) { |
886 | int x UNLOCK_FUNCTION() = y; // \ |
887 | // expected-warning {{'unlock_function' attribute only applies to functions}} |
888 | return x; |
889 | }; |
890 | |
891 | int uf_test_var UNLOCK_FUNCTION(); // \ |
892 | // expected-warning {{'unlock_function' attribute only applies to functions}} |
893 | |
894 | class UfFoo { |
895 | private: |
896 | int test_field UNLOCK_FUNCTION(); // \ |
897 | // expected-warning {{'unlock_function' attribute only applies to functions}} |
898 | void test_method() UNLOCK_FUNCTION(); // \ |
899 | // expected-warning {{'unlock_function' attribute without capability arguments refers to 'this', but 'UfFoo' isn't annotated with 'capability' or 'scoped_lockable' attribute}} |
900 | }; |
901 | |
902 | class NO_THREAD_SAFETY_ANALYSIS UfTestClass { // \ |
903 | // expected-warning {{'no_thread_safety_analysis' attribute only applies to functions}} |
904 | }; |
905 | |
906 | void uf_fun_params(int lvar UNLOCK_FUNCTION()); // \ |
907 | // expected-warning {{'unlock_function' attribute only applies to functions}} |
908 | |
909 | // Check argument parsing. |
910 | |
911 | // legal attribute arguments |
912 | int uf_function_1() UNLOCK_FUNCTION(muWrapper.mu); |
913 | int uf_function_2() UNLOCK_FUNCTION(muDoubleWrapper.muWrapper->mu); |
914 | int uf_function_3() UNLOCK_FUNCTION(muWrapper.getMu()); |
915 | int uf_function_4() UNLOCK_FUNCTION(*muWrapper.getMuPointer()); |
916 | int uf_function_5() UNLOCK_FUNCTION(&mu1); |
917 | int uf_function_6() UNLOCK_FUNCTION(muRef); |
918 | int uf_function_7() UNLOCK_FUNCTION(muDoubleWrapper.getWrapper()->getMu()); |
919 | int uf_function_8() UNLOCK_FUNCTION(muPointer); |
920 | int uf_function_9(Mutex x) UNLOCK_FUNCTION(1); |
921 | int uf_function_9(Mutex x, Mutex y) UNLOCK_FUNCTION(1,2); |
922 | |
923 | |
924 | // illegal attribute arguments |
925 | int uf_function_bad_2() UNLOCK_FUNCTION("mu"); // \ |
926 | // expected-warning {{ignoring 'unlock_function' attribute because its argument is invalid}} |
927 | int uf_function_bad_3() UNLOCK_FUNCTION(muDoublePointer); // \ |
928 | // expected-warning {{'unlock_function' attribute requires arguments whose type is annotated with 'capability' attribute; type here is 'Mutex **'}} |
929 | int uf_function_bad_4() UNLOCK_FUNCTION(umu); // \ |
930 | // expected-warning {{'unlock_function' attribute requires arguments whose type is annotated with 'capability' attribute}} |
931 | |
932 | int uf_function_bad_1() UNLOCK_FUNCTION(1); // \ |
933 | // expected-error {{'unlock_function' attribute parameter 1 is out of bounds: no parameters to index into}} |
934 | int uf_function_bad_5(Mutex x) UNLOCK_FUNCTION(0); // \ |
935 | // expected-error {{'unlock_function' attribute parameter 1 is out of bounds: can only be 1, since there is one parameter}} |
936 | int uf_function_bad_6(Mutex x, Mutex y) UNLOCK_FUNCTION(0); // \ |
937 | // expected-error {{'unlock_function' attribute parameter 1 is out of bounds: must be between 1 and 2}} |
938 | int uf_function_bad_7() UNLOCK_FUNCTION(0); // \ |
939 | // expected-error {{'unlock_function' attribute parameter 1 is out of bounds: no parameters to index into}} |
940 | |
941 | |
942 | //-----------------------------------------// |
943 | // Lock Returned (lr) |
944 | //-----------------------------------------// |
945 | |
946 | #if !__has_attribute(lock_returned) |
947 | #error "Should support lock_returned attribute" |
948 | #endif |
949 | |
950 | // Takes exactly one argument, a var/field |
951 | |
952 | void lr_function() __attribute__((lock_returned)); // \ |
953 | // expected-error {{'lock_returned' attribute takes one argument}} |
954 | |
955 | void lr_function_arg() LOCK_RETURNED(mu1); |
956 | |
957 | void lr_function_args() __attribute__((lock_returned(mu1, mu2))); // \ |
958 | // expected-error {{'lock_returned' attribute takes one argument}} |
959 | |
960 | int lr_testfn(int y) LOCK_RETURNED(mu1); |
961 | |
962 | int lr_testfn(int y) { |
963 | int x LOCK_RETURNED(mu1) = y; // \ |
964 | // expected-warning {{'lock_returned' attribute only applies to functions}} |
965 | return x; |
966 | }; |
967 | |
968 | int lr_test_var LOCK_RETURNED(mu1); // \ |
969 | // expected-warning {{'lock_returned' attribute only applies to functions}} |
970 | |
971 | void lr_fun_params(int lvar LOCK_RETURNED(mu1)); // \ |
972 | // expected-warning {{'lock_returned' attribute only applies to functions}} |
973 | |
974 | class LrFoo { |
975 | private: |
976 | int test_field LOCK_RETURNED(mu1); // \ |
977 | // expected-warning {{'lock_returned' attribute only applies to functions}} |
978 | void test_method() LOCK_RETURNED(mu1); |
979 | }; |
980 | |
981 | class LOCK_RETURNED(mu1) LrTestClass { // \ |
982 | // expected-warning {{'lock_returned' attribute only applies to functions}} |
983 | }; |
984 | |
985 | // Check argument parsing. |
986 | |
987 | // legal attribute arguments |
988 | int lr_function_1() LOCK_RETURNED(muWrapper.mu); |
989 | int lr_function_2() LOCK_RETURNED(muDoubleWrapper.muWrapper->mu); |
990 | int lr_function_3() LOCK_RETURNED(muWrapper.getMu()); |
991 | int lr_function_4() LOCK_RETURNED(*muWrapper.getMuPointer()); |
992 | int lr_function_5() LOCK_RETURNED(&mu1); |
993 | int lr_function_6() LOCK_RETURNED(muRef); |
994 | int lr_function_7() LOCK_RETURNED(muDoubleWrapper.getWrapper()->getMu()); |
995 | int lr_function_8() LOCK_RETURNED(muPointer); |
996 | |
997 | |
998 | // illegal attribute arguments |
999 | int lr_function_bad_1() LOCK_RETURNED(1); // \ |
1000 | // expected-warning {{'lock_returned' attribute requires arguments whose type is annotated with 'capability' attribute; type here is 'int'}} |
1001 | int lr_function_bad_2() LOCK_RETURNED("mu"); // \ |
1002 | // expected-warning {{ignoring 'lock_returned' attribute because its argument is invalid}} |
1003 | int lr_function_bad_3() LOCK_RETURNED(muDoublePointer); // \ |
1004 | // expected-warning {{'lock_returned' attribute requires arguments whose type is annotated with 'capability' attribute; type here is 'Mutex **'}} |
1005 | int lr_function_bad_4() LOCK_RETURNED(umu); // \ |
1006 | // expected-warning {{'lock_returned' attribute requires arguments whose type is annotated with 'capability' attribute}} |
1007 | |
1008 | |
1009 | |
1010 | //-----------------------------------------// |
1011 | // Locks Excluded (le) |
1012 | //-----------------------------------------// |
1013 | |
1014 | #if !__has_attribute(locks_excluded) |
1015 | #error "Should support locks_excluded attribute" |
1016 | #endif |
1017 | |
1018 | // takes one or more arguments, all locks (vars/fields) |
1019 | |
1020 | void le_function() __attribute__((locks_excluded)); // \ |
1021 | // expected-error {{'locks_excluded' attribute takes at least 1 argument}} |
1022 | |
1023 | void le_function_arg() LOCKS_EXCLUDED(mu1); |
1024 | |
1025 | void le_function_args() LOCKS_EXCLUDED(mu1, mu2); |
1026 | |
1027 | int le_testfn(int y) LOCKS_EXCLUDED(mu1); |
1028 | |
1029 | int le_testfn(int y) { |
1030 | int x LOCKS_EXCLUDED(mu1) = y; // \ |
1031 | // expected-warning {{'locks_excluded' attribute only applies to functions}} |
1032 | return x; |
1033 | }; |
1034 | |
1035 | int le_test_var LOCKS_EXCLUDED(mu1); // \ |
1036 | // expected-warning {{'locks_excluded' attribute only applies to functions}} |
1037 | |
1038 | void le_fun_params(int lvar LOCKS_EXCLUDED(mu1)); // \ |
1039 | // expected-warning {{'locks_excluded' attribute only applies to functions}} |
1040 | |
1041 | class LeFoo { |
1042 | private: |
1043 | int test_field LOCKS_EXCLUDED(mu1); // \ |
1044 | // expected-warning {{'locks_excluded' attribute only applies to functions}} |
1045 | void test_method() LOCKS_EXCLUDED(mu1); |
1046 | }; |
1047 | |
1048 | class LOCKS_EXCLUDED(mu1) LeTestClass { // \ |
1049 | // expected-warning {{'locks_excluded' attribute only applies to functions}} |
1050 | }; |
1051 | |
1052 | // Check argument parsing. |
1053 | |
1054 | // legal attribute arguments |
1055 | int le_function_1() LOCKS_EXCLUDED(muWrapper.mu); |
1056 | int le_function_2() LOCKS_EXCLUDED(muDoubleWrapper.muWrapper->mu); |
1057 | int le_function_3() LOCKS_EXCLUDED(muWrapper.getMu()); |
1058 | int le_function_4() LOCKS_EXCLUDED(*muWrapper.getMuPointer()); |
1059 | int le_function_5() LOCKS_EXCLUDED(&mu1); |
1060 | int le_function_6() LOCKS_EXCLUDED(muRef); |
1061 | int le_function_7() LOCKS_EXCLUDED(muDoubleWrapper.getWrapper()->getMu()); |
1062 | int le_function_8() LOCKS_EXCLUDED(muPointer); |
1063 | |
1064 | |
1065 | // illegal attribute arguments |
1066 | int le_function_bad_1() LOCKS_EXCLUDED(1); // \ |
1067 | // expected-warning {{'locks_excluded' attribute requires arguments whose type is annotated with 'capability' attribute; type here is 'int'}} |
1068 | int le_function_bad_2() LOCKS_EXCLUDED("mu"); // \ |
1069 | // expected-warning {{ignoring 'locks_excluded' attribute because its argument is invalid}} |
1070 | int le_function_bad_3() LOCKS_EXCLUDED(muDoublePointer); // \ |
1071 | // expected-warning {{'locks_excluded' attribute requires arguments whose type is annotated with 'capability' attribute; type here is 'Mutex **'}} |
1072 | int le_function_bad_4() LOCKS_EXCLUDED(umu); // \ |
1073 | // expected-warning {{'locks_excluded' attribute requires arguments whose type is annotated with 'capability' attribute}} |
1074 | |
1075 | |
1076 | |
1077 | //-----------------------------------------// |
1078 | // Exclusive Locks Required (elr) |
1079 | //-----------------------------------------// |
1080 | |
1081 | #if !__has_attribute(exclusive_locks_required) |
1082 | #error "Should support exclusive_locks_required attribute" |
1083 | #endif |
1084 | |
1085 | // takes one or more arguments, all locks (vars/fields) |
1086 | |
1087 | void elr_function() __attribute__((exclusive_locks_required)); // \ |
1088 | // expected-error {{'exclusive_locks_required' attribute takes at least 1 argument}} |
1089 | |
1090 | void elr_function_arg() EXCLUSIVE_LOCKS_REQUIRED(mu1); |
1091 | |
1092 | void elr_function_args() EXCLUSIVE_LOCKS_REQUIRED(mu1, mu2); |
1093 | |
1094 | int elr_testfn(int y) EXCLUSIVE_LOCKS_REQUIRED(mu1); |
1095 | |
1096 | int elr_testfn(int y) { |
1097 | int x EXCLUSIVE_LOCKS_REQUIRED(mu1) = y; // \ |
1098 | // expected-warning {{'exclusive_locks_required' attribute only applies to functions}} |
1099 | return x; |
1100 | }; |
1101 | |
1102 | int elr_test_var EXCLUSIVE_LOCKS_REQUIRED(mu1); // \ |
1103 | // expected-warning {{'exclusive_locks_required' attribute only applies to functions}} |
1104 | |
1105 | void elr_fun_params(int lvar EXCLUSIVE_LOCKS_REQUIRED(mu1)); // \ |
1106 | // expected-warning {{'exclusive_locks_required' attribute only applies to functions}} |
1107 | |
1108 | class ElrFoo { |
1109 | private: |
1110 | int test_field EXCLUSIVE_LOCKS_REQUIRED(mu1); // \ |
1111 | // expected-warning {{'exclusive_locks_required' attribute only applies to functions}} |
1112 | void test_method() EXCLUSIVE_LOCKS_REQUIRED(mu1); |
1113 | }; |
1114 | |
1115 | class EXCLUSIVE_LOCKS_REQUIRED(mu1) ElrTestClass { // \ |
1116 | // expected-warning {{'exclusive_locks_required' attribute only applies to functions}} |
1117 | }; |
1118 | |
1119 | // Check argument parsing. |
1120 | |
1121 | // legal attribute arguments |
1122 | int elr_function_1() EXCLUSIVE_LOCKS_REQUIRED(muWrapper.mu); |
1123 | int elr_function_2() EXCLUSIVE_LOCKS_REQUIRED(muDoubleWrapper.muWrapper->mu); |
1124 | int elr_function_3() EXCLUSIVE_LOCKS_REQUIRED(muWrapper.getMu()); |
1125 | int elr_function_4() EXCLUSIVE_LOCKS_REQUIRED(*muWrapper.getMuPointer()); |
1126 | int elr_function_5() EXCLUSIVE_LOCKS_REQUIRED(&mu1); |
1127 | int elr_function_6() EXCLUSIVE_LOCKS_REQUIRED(muRef); |
1128 | int elr_function_7() EXCLUSIVE_LOCKS_REQUIRED(muDoubleWrapper.getWrapper()->getMu()); |
1129 | int elr_function_8() EXCLUSIVE_LOCKS_REQUIRED(muPointer); |
1130 | |
1131 | |
1132 | // illegal attribute arguments |
1133 | int elr_function_bad_1() EXCLUSIVE_LOCKS_REQUIRED(1); // \ |
1134 | // expected-warning {{'exclusive_locks_required' attribute requires arguments whose type is annotated with 'capability' attribute; type here is 'int'}} |
1135 | int elr_function_bad_2() EXCLUSIVE_LOCKS_REQUIRED("mu"); // \ |
1136 | // expected-warning {{ignoring 'exclusive_locks_required' attribute because its argument is invalid}} |
1137 | int elr_function_bad_3() EXCLUSIVE_LOCKS_REQUIRED(muDoublePointer); // \ |
1138 | // expected-warning {{'exclusive_locks_required' attribute requires arguments whose type is annotated with 'capability' attribute; type here is 'Mutex **'}} |
1139 | int elr_function_bad_4() EXCLUSIVE_LOCKS_REQUIRED(umu); // \ |
1140 | // expected-warning {{'exclusive_locks_required' attribute requires arguments whose type is annotated with 'capability' attribute}} |
1141 | |
1142 | |
1143 | |
1144 | |
1145 | //-----------------------------------------// |
1146 | // Shared Locks Required (slr) |
1147 | //-----------------------------------------// |
1148 | |
1149 | #if !__has_attribute(shared_locks_required) |
1150 | #error "Should support shared_locks_required attribute" |
1151 | #endif |
1152 | |
1153 | // takes one or more arguments, all locks (vars/fields) |
1154 | |
1155 | void slr_function() __attribute__((shared_locks_required)); // \ |
1156 | // expected-error {{'shared_locks_required' attribute takes at least 1 argument}} |
1157 | |
1158 | void slr_function_arg() SHARED_LOCKS_REQUIRED(mu1); |
1159 | |
1160 | void slr_function_args() SHARED_LOCKS_REQUIRED(mu1, mu2); |
1161 | |
1162 | int slr_testfn(int y) SHARED_LOCKS_REQUIRED(mu1); |
1163 | |
1164 | int slr_testfn(int y) { |
1165 | int x SHARED_LOCKS_REQUIRED(mu1) = y; // \ |
1166 | // expected-warning {{'shared_locks_required' attribute only applies to functions}} |
1167 | return x; |
1168 | }; |
1169 | |
1170 | int slr_test_var SHARED_LOCKS_REQUIRED(mu1); // \ |
1171 | // expected-warning {{'shared_locks_required' attribute only applies to functions}} |
1172 | |
1173 | void slr_fun_params(int lvar SHARED_LOCKS_REQUIRED(mu1)); // \ |
1174 | // expected-warning {{'shared_locks_required' attribute only applies to functions}} |
1175 | |
1176 | class SlrFoo { |
1177 | private: |
1178 | int test_field SHARED_LOCKS_REQUIRED(mu1); // \ |
1179 | // expected-warning {{'shared_locks_required' attribute only applies to functions}} |
1180 | void test_method() SHARED_LOCKS_REQUIRED(mu1); |
1181 | }; |
1182 | |
1183 | class SHARED_LOCKS_REQUIRED(mu1) SlrTestClass { // \ |
1184 | // expected-warning {{'shared_locks_required' attribute only applies to functions}} |
1185 | }; |
1186 | |
1187 | // Check argument parsing. |
1188 | |
1189 | // legal attribute arguments |
1190 | int slr_function_1() SHARED_LOCKS_REQUIRED(muWrapper.mu); |
1191 | int slr_function_2() SHARED_LOCKS_REQUIRED(muDoubleWrapper.muWrapper->mu); |
1192 | int slr_function_3() SHARED_LOCKS_REQUIRED(muWrapper.getMu()); |
1193 | int slr_function_4() SHARED_LOCKS_REQUIRED(*muWrapper.getMuPointer()); |
1194 | int slr_function_5() SHARED_LOCKS_REQUIRED(&mu1); |
1195 | int slr_function_6() SHARED_LOCKS_REQUIRED(muRef); |
1196 | int slr_function_7() SHARED_LOCKS_REQUIRED(muDoubleWrapper.getWrapper()->getMu()); |
1197 | int slr_function_8() SHARED_LOCKS_REQUIRED(muPointer); |
1198 | |
1199 | |
1200 | // illegal attribute arguments |
1201 | int slr_function_bad_1() SHARED_LOCKS_REQUIRED(1); // \ |
1202 | // expected-warning {{'shared_locks_required' attribute requires arguments whose type is annotated with 'capability' attribute; type here is 'int'}} |
1203 | int slr_function_bad_2() SHARED_LOCKS_REQUIRED("mu"); // \ |
1204 | // expected-warning {{ignoring 'shared_locks_required' attribute because its argument is invalid}} |
1205 | int slr_function_bad_3() SHARED_LOCKS_REQUIRED(muDoublePointer); // \ |
1206 | // expected-warning {{'shared_locks_required' attribute requires arguments whose type is annotated with 'capability' attribute; type here is 'Mutex **'}} |
1207 | int slr_function_bad_4() SHARED_LOCKS_REQUIRED(umu); // \ |
1208 | // expected-warning {{'shared_locks_required' attribute requires arguments whose type is annotated with 'capability' attribute}} |
1209 | |
1210 | |
1211 | //-----------------------------------------// |
1212 | // Regression tests for unusual cases. |
1213 | //-----------------------------------------// |
1214 | |
1215 | int trivially_false_edges(bool b) { |
1216 | // Create NULL (never taken) edges in CFG |
1217 | if (false) return 1; |
1218 | else return 2; |
1219 | } |
1220 | |
1221 | // Possible Clang bug -- method pointer in template parameter |
1222 | class UnFoo { |
1223 | public: |
1224 | void foo(); |
1225 | }; |
1226 | |
1227 | template<void (UnFoo::*methptr)()> |
1228 | class MCaller { |
1229 | public: |
1230 | static void call_method_ptr(UnFoo *f) { |
1231 | // FIXME: Possible Clang bug: |
1232 | // getCalleeDecl() returns NULL in the following case: |
1233 | (f->*methptr)(); |
1234 | } |
1235 | }; |
1236 | |
1237 | void call_method_ptr_inst(UnFoo* f) { |
1238 | MCaller<&UnFoo::foo>::call_method_ptr(f); |
1239 | } |
1240 | |
1241 | int temp; |
1242 | void empty_back_edge() { |
1243 | // Create a back edge to a block with with no statements |
1244 | for (;;) { |
1245 | ++temp; |
1246 | if (temp > 10) break; |
1247 | } |
1248 | } |
1249 | |
1250 | struct Foomger { |
1251 | void operator++(); |
1252 | }; |
1253 | |
1254 | struct Foomgoper { |
1255 | Foomger f; |
1256 | |
1257 | bool done(); |
1258 | void invalid_back_edge() { |
1259 | do { |
1260 | // FIXME: Possible Clang bug: |
1261 | // The first statement in this basic block has no source location |
1262 | ++f; |
1263 | } while (!done()); |
1264 | } |
1265 | }; |
1266 | |
1267 | template <typename Mutex> |
1268 | struct SCOPED_LOCKABLE SLTemplateClass { |
1269 | ~SLTemplateClass() UNLOCK_FUNCTION(); |
1270 | }; |
1271 | |
1272 | template <typename Mutex> |
1273 | struct NonSLTemplateClass { |
1274 | ~NonSLTemplateClass() UNLOCK_FUNCTION(); // \ |
1275 | // expected-warning{{'unlock_function' attribute without capability arguments refers to 'this', but 'NonSLTemplateClass' isn't annotated with 'capability' or 'scoped_lockable' attribute}} |
1276 | }; |
1277 | |
1278 | template <> |
1279 | struct SLTemplateClass<int> {}; |
1280 | |
1281 | template <typename Mutex> |
1282 | struct SLTemplateDerived : public SLTemplateClass<Mutex> { |
1283 | ~SLTemplateDerived() UNLOCK_FUNCTION(); |
1284 | }; |
1285 | |
1286 | // FIXME: warn on template instantiation. |
1287 | template struct SLTemplateDerived<int>; |
1288 | |
1289 | struct SLDerived1 : public SLTemplateClass<double> { |
1290 | ~SLDerived1() UNLOCK_FUNCTION(); |
1291 | }; |
1292 | |
1293 | struct SLDerived2 : public SLTemplateClass<int> { |
1294 | ~SLDerived2() UNLOCK_FUNCTION(); // \ |
1295 | // expected-warning{{'unlock_function' attribute without capability arguments refers to 'this', but 'SLDerived2' isn't annotated with 'capability' or 'scoped_lockable' attribute}} |
1296 | }; |
1297 | |
1298 | //----------------------------------------------------- |
1299 | // Parsing of member variables and function parameters |
1300 | //------------------------------------------------------ |
1301 | |
1302 | Mutex gmu; |
1303 | |
1304 | class StaticMu { |
1305 | static Mutex statmu; |
1306 | }; |
1307 | |
1308 | class FooLate { |
1309 | public: |
1310 | void foo1() EXCLUSIVE_LOCKS_REQUIRED(gmu) { } |
1311 | void foo2() EXCLUSIVE_LOCKS_REQUIRED(mu) { } |
1312 | void foo3(Mutex *m) EXCLUSIVE_LOCKS_REQUIRED(m) { } |
1313 | void foo3(FooLate *f) EXCLUSIVE_LOCKS_REQUIRED(f->mu) { } |
1314 | void foo4(FooLate *f) EXCLUSIVE_LOCKS_REQUIRED(f->mu); |
1315 | |
1316 | static void foo5() EXCLUSIVE_LOCKS_REQUIRED(mu); |
1317 | //FIXME: Bug 32066 - Error should be emitted irrespective of C++ dialect |
1318 | #if __cplusplus <= 199711L |
1319 | // expected-error@-3 {{invalid use of member 'mu' in static member function}} |
1320 | #endif |
1321 | |
1322 | template <class T> |
1323 | void foo6() EXCLUSIVE_LOCKS_REQUIRED(T::statmu) { } |
1324 | |
1325 | template <class T> |
1326 | void foo7(T* f) EXCLUSIVE_LOCKS_REQUIRED(f->mu) { } |
1327 | |
1328 | int a GUARDED_BY(gmu); |
1329 | int b GUARDED_BY(mu); |
1330 | int c GUARDED_BY(this->mu); |
1331 | |
1332 | Mutex mu; |
1333 | }; |
1334 | |
1335 | //------------------------- |
1336 | // Empty argument lists |
1337 | //------------------------- |
1338 | |
1339 | class LOCKABLE EmptyArgListsTest { |
1340 | void lock() EXCLUSIVE_LOCK_FUNCTION() { } |
1341 | void unlock() UNLOCK_FUNCTION() { } |
1342 | }; |
1343 | |
1344 | |
1345 | namespace FunctionDefinitionParseTest { |
1346 | // Test parsing of attributes on function definitions. |
1347 | |
1348 | class Foo { |
1349 | public: |
1350 | Mutex mu_; |
1351 | void foo1(); |
1352 | void foo2(Foo *f); |
1353 | }; |
1354 | |
1355 | template <class T> |
1356 | class Bar { |
1357 | public: |
1358 | Mutex mu_; |
1359 | void bar(); |
1360 | }; |
1361 | |
1362 | void Foo::foo1() EXCLUSIVE_LOCKS_REQUIRED(mu_) { } |
1363 | void Foo::foo2(Foo *f) EXCLUSIVE_LOCKS_REQUIRED(f->mu_) { } |
1364 | |
1365 | template <class T> |
1366 | void Bar<T>::bar() EXCLUSIVE_LOCKS_REQUIRED(mu_) { } |
1367 | |
1368 | void baz(Foo *f) EXCLUSIVE_LOCKS_REQUIRED(f->mu_) { } |
1369 | |
1370 | } // end namespace |
1371 | |
1372 | |
1373 | namespace TestMultiDecl { |
1374 | |
1375 | class Foo { |
1376 | public: |
1377 | int GUARDED_BY(mu_) a; |
1378 | int GUARDED_BY(mu_) b, c; |
1379 | |
1380 | private: |
1381 | Mutex mu_; |
1382 | }; |
1383 | |
1384 | } // end namespace TestMultiDecl |
1385 | |
1386 | |
1387 | namespace NestedClassLateDecl { |
1388 | |
1389 | class Foo { |
1390 | class Bar { |
1391 | int a GUARDED_BY(mu); |
1392 | int b GUARDED_BY(fooMuStatic); |
1393 | |
1394 | void bar() EXCLUSIVE_LOCKS_REQUIRED(mu) { a = 0; } |
1395 | void bar2(Bar* b) EXCLUSIVE_LOCKS_REQUIRED(b->mu) { b->a = 0; } |
1396 | void bar3(Foo* f) EXCLUSIVE_LOCKS_REQUIRED(f->fooMu) { f->a = 0; } |
1397 | |
1398 | Mutex mu; |
1399 | }; |
1400 | |
1401 | int a GUARDED_BY(fooMu); |
1402 | Mutex fooMu; |
1403 | static Mutex fooMuStatic; |
1404 | }; |
1405 | |
1406 | } |
1407 | |
1408 | namespace PointerToMemberTest { |
1409 | |
1410 | // Empty string should be ignored. |
1411 | int testEmptyAttribute GUARDED_BY(""); |
1412 | void testEmptyAttributeFunction() EXCLUSIVE_LOCKS_REQUIRED(""); |
1413 | |
1414 | class Graph { |
1415 | public: |
1416 | Mutex mu_; |
1417 | |
1418 | static Mutex* get_static_mu() LOCK_RETURNED(&Graph::mu_); |
1419 | }; |
1420 | |
1421 | class Node { |
1422 | public: |
1423 | void foo() EXCLUSIVE_LOCKS_REQUIRED(&Graph::mu_); |
1424 | int a GUARDED_BY(&Graph::mu_); |
1425 | }; |
1426 | |
1427 | } |
1428 | |
1429 | |
1430 | namespace SmartPointerTest { |
1431 | |
1432 | template<class T> |
1433 | class smart_ptr { |
1434 | public: |
1435 | T* operator->() { return ptr_; } |
1436 | T& operator*() { return ptr_; } |
1437 | |
1438 | private: |
1439 | T* ptr_; |
1440 | }; |
1441 | |
1442 | |
1443 | Mutex gmu; |
1444 | smart_ptr<int> gdat PT_GUARDED_BY(gmu); |
1445 | |
1446 | |
1447 | class MyClass { |
1448 | public: |
1449 | Mutex mu_; |
1450 | smart_ptr<Mutex> smu_; |
1451 | |
1452 | |
1453 | smart_ptr<int> a PT_GUARDED_BY(mu_); |
1454 | int b GUARDED_BY(smu_); |
1455 | }; |
1456 | |
1457 | } |
1458 | |
1459 | |
1460 | namespace InheritanceTest { |
1461 | |
1462 | class LOCKABLE Base { |
1463 | public: |
1464 | void lock() EXCLUSIVE_LOCK_FUNCTION(); |
1465 | void unlock() UNLOCK_FUNCTION(); |
1466 | }; |
1467 | |
1468 | class Base2 { }; |
1469 | |
1470 | class Derived1 : public Base { }; |
1471 | |
1472 | class Derived2 : public Base2, public Derived1 { }; |
1473 | |
1474 | class Derived3 : public Base2 { }; |
1475 | |
1476 | class Foo { |
1477 | Derived1 mu1_; |
1478 | Derived2 mu2_; |
1479 | Derived3 mu3_; |
1480 | int a GUARDED_BY(mu1_); |
1481 | int b GUARDED_BY(mu2_); |
1482 | int c GUARDED_BY(mu3_); // \ |
1483 | // expected-warning {{'guarded_by' attribute requires arguments whose type is annotated with 'capability' attribute; type here is 'InheritanceTest::Derived3'}} |
1484 | |
1485 | void foo() EXCLUSIVE_LOCKS_REQUIRED(mu1_, mu2_) { |
1486 | a = 0; |
1487 | b = 0; |
1488 | } |
1489 | }; |
1490 | |
1491 | } |
1492 | |
1493 | |
1494 | namespace InvalidDeclTest { |
1495 | |
1496 | class Foo { }; |
1497 | namespace { |
1498 | void Foo::bar(Mutex* mu) LOCKS_EXCLUDED(mu) { } // \ |
1499 | // expected-error {{cannot define or redeclare 'bar' here because namespace '' does not enclose namespace 'Foo'}} \ |
1500 | // expected-warning {{attribute locks_excluded ignored, because it is not attached to a declaration}} |
1501 | } |
1502 | |
1503 | } // end namespace InvalidDeclTest |
1504 | |
1505 | |
1506 | namespace StaticScopeTest { |
1507 | |
1508 | class FooStream; |
1509 | |
1510 | class Foo { |
1511 | mutable Mutex mu; |
1512 | int a GUARDED_BY(mu); |
1513 | |
1514 | static int si GUARDED_BY(mu); |
1515 | //FIXME: Bug 32066 - Error should be emitted irrespective of C++ dialect |
1516 | #if __cplusplus <= 199711L |
1517 | // expected-error@-3 {{invalid use of non-static data member 'mu'}} |
1518 | #endif |
1519 | |
1520 | static void foo() EXCLUSIVE_LOCKS_REQUIRED(mu); |
1521 | //FIXME: Bug 32066 - Error should be emitted irrespective of C++ dialect |
1522 | #if __cplusplus <= 199711L |
1523 | // expected-error@-3 {{invalid use of member 'mu' in static member function}} |
1524 | #endif |
1525 | |
1526 | friend FooStream& operator<<(FooStream& s, const Foo& f) |
1527 | EXCLUSIVE_LOCKS_REQUIRED(mu); |
1528 | //FIXME: Bug 32066 - Error should be emitted irrespective of C++ dialect |
1529 | #if __cplusplus <= 199711L |
1530 | // expected-error@-3 {{invalid use of non-static data member 'mu'}} |
1531 | #endif |
1532 | }; |
1533 | |
1534 | |
1535 | } // end namespace StaticScopeTest |
1536 | |
1537 | |
1538 | namespace FunctionAttributesInsideClass_ICE_Test { |
1539 | |
1540 | class Foo { |
1541 | public: |
1542 | /* Originally found when parsing foo() as an ordinary method after the |
1543 | * the following: |
1544 | |
1545 | template <class T> |
1546 | void syntaxErrorMethod(int i) { |
1547 | if (i) { |
1548 | foo( |
1549 | } |
1550 | } |
1551 | */ |
1552 | |
1553 | void method() { |
1554 | void foo() EXCLUSIVE_LOCKS_REQUIRED(mu); // \ |
1555 | // expected-error {{use of undeclared identifier 'mu'}} |
1556 | } |
1557 | }; |
1558 | |
1559 | } // end namespace FunctionAttributesInsideClass_ICE_Test |
1560 | |
1561 | |
1562 | #ifdef CPP11 |
1563 | namespace CRASH_POST_R301735 { |
1564 | class SomeClass { |
1565 | public: |
1566 | void foo() { |
1567 | auto l = [this] { auto l = [] () EXCLUSIVE_LOCKS_REQUIRED(mu_) {}; }; |
1568 | } |
1569 | Mutex mu_; |
1570 | }; |
1571 | } |
1572 | #endif |
1573 | |