blob: 634a23343077e8a391266f6fe709f7494a834f7c [file] [log] [blame]
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +00001// RUN: %clang_cc1 -fsyntax-only -verify -Wthread-safety %s
2
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00003#define LOCKABLE __attribute__ ((lockable))
4#define SCOPED_LOCKABLE __attribute__ ((scoped_lockable))
5#define GUARDED_BY(x) __attribute__ ((guarded_by(x)))
6#define GUARDED_VAR __attribute__ ((guarded_var))
7#define PT_GUARDED_BY(x) __attribute__ ((pt_guarded_by(x)))
8#define PT_GUARDED_VAR __attribute__ ((pt_guarded_var))
9#define ACQUIRED_AFTER(...) __attribute__ ((acquired_after(__VA_ARGS__)))
10#define ACQUIRED_BEFORE(...) __attribute__ ((acquired_before(__VA_ARGS__)))
11#define EXCLUSIVE_LOCK_FUNCTION(...) __attribute__ ((exclusive_lock_function(__VA_ARGS__)))
12#define SHARED_LOCK_FUNCTION(...) __attribute__ ((shared_lock_function(__VA_ARGS__)))
13#define EXCLUSIVE_TRYLOCK_FUNCTION(...) __attribute__ ((exclusive_trylock_function(__VA_ARGS__)))
14#define SHARED_TRYLOCK_FUNCTION(...) __attribute__ ((shared_trylock_function(__VA_ARGS__)))
15#define UNLOCK_FUNCTION(...) __attribute__ ((unlock_function(__VA_ARGS__)))
16#define LOCK_RETURNED(x) __attribute__ ((lock_returned(x)))
17#define LOCKS_EXCLUDED(...) __attribute__ ((locks_excluded(__VA_ARGS__)))
18#define EXCLUSIVE_LOCKS_REQUIRED(...) \
19 __attribute__ ((exclusive_locks_required(__VA_ARGS__)))
20#define SHARED_LOCKS_REQUIRED(...) \
21 __attribute__ ((shared_locks_required(__VA_ARGS__)))
22#define NO_THREAD_SAFETY_ANALYSIS __attribute__ ((no_thread_safety_analysis))
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +000023
24//-----------------------------------------//
25// Helper fields
26//-----------------------------------------//
27
28
29class __attribute__((lockable)) Mutex {
30 public:
31 void Lock() __attribute__((exclusive_lock_function));
32 void ReaderLock() __attribute__((shared_lock_function));
33 void Unlock() __attribute__((unlock_function));
34 bool TryLock() __attribute__((exclusive_trylock_function(true)));
35 bool ReaderTryLock() __attribute__((shared_trylock_function(true)));
36 void LockWhen(const int &cond) __attribute__((exclusive_lock_function));
37};
38
DeLesley Hutchins1fa3c062011-12-08 20:23:06 +000039class __attribute__((scoped_lockable)) MutexLock {
40 public:
41 MutexLock(Mutex *mu) __attribute__((exclusive_lock_function(mu)));
42 ~MutexLock() __attribute__((unlock_function));
43};
44
45class __attribute__((scoped_lockable)) ReaderMutexLock {
46 public:
47 ReaderMutexLock(Mutex *mu) __attribute__((exclusive_lock_function(mu)));
48 ~ReaderMutexLock() __attribute__((unlock_function));
49};
50
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +000051
52Mutex sls_mu;
53
54Mutex sls_mu2 __attribute__((acquired_after(sls_mu)));
55int sls_guard_var __attribute__((guarded_var)) = 0;
56int sls_guardby_var __attribute__((guarded_by(sls_mu))) = 0;
57
58bool getBool();
59
60class MutexWrapper {
61public:
62 Mutex mu;
Caitlin Sadowski194418f2011-09-14 20:00:24 +000063 int x __attribute__((guarded_by(mu)));
64 void MyLock() __attribute__((exclusive_lock_function(mu)));
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +000065};
66
67MutexWrapper sls_mw;
68
69void sls_fun_0() {
70 sls_mw.mu.Lock();
Caitlin Sadowski194418f2011-09-14 20:00:24 +000071 sls_mw.x = 5;
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +000072 sls_mw.mu.Unlock();
73}
74
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +000075void sls_fun_2() {
76 sls_mu.Lock();
77 int x = sls_guard_var;
78 sls_mu.Unlock();
79}
80
81void sls_fun_3() {
82 sls_mu.Lock();
83 sls_guard_var = 2;
84 sls_mu.Unlock();
85}
86
87void sls_fun_4() {
88 sls_mu2.Lock();
89 sls_guard_var = 2;
90 sls_mu2.Unlock();
91}
92
93void sls_fun_5() {
94 sls_mu.Lock();
95 int x = sls_guardby_var;
96 sls_mu.Unlock();
97}
98
99void sls_fun_6() {
100 sls_mu.Lock();
101 sls_guardby_var = 2;
102 sls_mu.Unlock();
103}
104
105void sls_fun_7() {
106 sls_mu.Lock();
107 sls_mu2.Lock();
108 sls_mu2.Unlock();
109 sls_mu.Unlock();
110}
111
112void sls_fun_8() {
113 sls_mu.Lock();
114 if (getBool())
115 sls_mu.Unlock();
116 else
117 sls_mu.Unlock();
118}
119
120void sls_fun_9() {
121 if (getBool())
122 sls_mu.Lock();
123 else
124 sls_mu.Lock();
125 sls_mu.Unlock();
126}
127
128void sls_fun_good_6() {
129 if (getBool()) {
130 sls_mu.Lock();
131 } else {
132 if (getBool()) {
133 getBool(); // EMPTY
134 } else {
135 getBool(); // EMPTY
136 }
137 sls_mu.Lock();
138 }
139 sls_mu.Unlock();
140}
141
142void sls_fun_good_7() {
143 sls_mu.Lock();
144 while (getBool()) {
145 sls_mu.Unlock();
146 if (getBool()) {
147 if (getBool()) {
148 sls_mu.Lock();
149 continue;
150 }
151 }
152 sls_mu.Lock();
153 }
154 sls_mu.Unlock();
155}
156
Caitlin Sadowski194418f2011-09-14 20:00:24 +0000157void sls_fun_good_8() {
158 sls_mw.MyLock();
159 sls_mw.mu.Unlock();
160}
161
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000162void sls_fun_bad_1() {
163 sls_mu.Unlock(); // \
Caitlin Sadowski8bccabe2011-09-08 21:52:50 +0000164 // expected-warning{{unlocking 'sls_mu' that was not locked}}
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000165}
166
167void sls_fun_bad_2() {
168 sls_mu.Lock();
169 sls_mu.Lock(); // \
Caitlin Sadowski8bccabe2011-09-08 21:52:50 +0000170 // expected-warning{{locking 'sls_mu' that is already locked}}
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000171 sls_mu.Unlock();
172}
173
174void sls_fun_bad_3() {
175 sls_mu.Lock(); // \
Richard Trieu2fe9b7f2011-12-15 00:38:15 +0000176 // expected-warning{{mutex 'sls_mu' is still locked at the end of function}}
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000177}
178
179void sls_fun_bad_4() {
180 if (getBool())
181 sls_mu.Lock(); // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000182 // expected-warning{{mutex 'sls_mu' is still locked at the end of its scope}}
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000183 else
184 sls_mu2.Lock(); // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000185 // expected-warning{{mutex 'sls_mu2' is still locked at the end of its scope}}
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000186}
187
188void sls_fun_bad_5() {
189 sls_mu.Lock(); // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000190 // expected-warning{{mutex 'sls_mu' is still locked at the end of its scope}}
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000191 if (getBool())
192 sls_mu.Unlock();
193}
194
195void sls_fun_bad_6() {
196 if (getBool()) {
197 sls_mu.Lock(); // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000198 // expected-warning{{mutex 'sls_mu' is still locked at the end of its scope}}
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000199 } else {
200 if (getBool()) {
201 getBool(); // EMPTY
202 } else {
203 getBool(); // EMPTY
204 }
205 }
206 sls_mu.Unlock(); // \
Caitlin Sadowski8bccabe2011-09-08 21:52:50 +0000207 // expected-warning{{unlocking 'sls_mu' that was not locked}}
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000208}
209
210void sls_fun_bad_7() {
Richard Smithaacde712012-02-03 03:30:07 +0000211 sls_mu.Lock();
Caitlin Sadowski4e4bc752011-09-15 17:25:19 +0000212 while (getBool()) {
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000213 sls_mu.Unlock();
214 if (getBool()) {
215 if (getBool()) {
216 continue;
217 }
218 }
219 sls_mu.Lock(); // \
Richard Smithaacde712012-02-03 03:30:07 +0000220 // expected-warning{{expecting mutex 'sls_mu' to be locked at start of each loop}}
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000221 }
222 sls_mu.Unlock();
223}
224
225void sls_fun_bad_8() {
Caitlin Sadowski4e4bc752011-09-15 17:25:19 +0000226 sls_mu.Lock(); // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000227 // expected-warning{{expecting mutex 'sls_mu' to be locked at start of each loop}}
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000228 do {
Caitlin Sadowski4e4bc752011-09-15 17:25:19 +0000229 sls_mu.Unlock();
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000230 } while (getBool());
231}
232
233void sls_fun_bad_9() {
234 do {
235 sls_mu.Lock(); // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000236 // expected-warning{{expecting mutex 'sls_mu' to be locked at start of each loop}}
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000237 } while (getBool());
238 sls_mu.Unlock();
239}
240
241void sls_fun_bad_10() {
242 sls_mu.Lock(); // \
Richard Trieu2fe9b7f2011-12-15 00:38:15 +0000243 // expected-warning{{mutex 'sls_mu' is still locked at the end of function}} \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000244 // expected-warning{{expecting mutex 'sls_mu' to be locked at start of each loop}}
Caitlin Sadowski4e4bc752011-09-15 17:25:19 +0000245 while(getBool()) {
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000246 sls_mu.Unlock();
247 }
248}
249
250void sls_fun_bad_11() {
251 while (getBool()) {
252 sls_mu.Lock(); // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000253 // expected-warning{{expecting mutex 'sls_mu' to be locked at start of each loop}}
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000254 }
255 sls_mu.Unlock(); // \
Caitlin Sadowski8bccabe2011-09-08 21:52:50 +0000256 // expected-warning{{unlocking 'sls_mu' that was not locked}}
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000257}
258
Richard Smithaacde712012-02-03 03:30:07 +0000259void sls_fun_bad_12() {
260 sls_mu.Lock(); // \
261 // expected-warning{{mutex 'sls_mu' is still locked at the end of its scope}}
262 while (getBool()) {
263 sls_mu.Unlock();
264 if (getBool()) {
265 if (getBool()) {
266 break;
267 }
268 }
269 sls_mu.Lock();
270 }
271 sls_mu.Unlock();
272}
273
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000274//-----------------------------------------//
275// Handling lock expressions in attribute args
276// -------------------------------------------//
277
278Mutex aa_mu;
279
280class GlobalLocker {
281public:
282 void globalLock() __attribute__((exclusive_lock_function(aa_mu)));
283 void globalUnlock() __attribute__((unlock_function(aa_mu)));
284};
285
286GlobalLocker glock;
287
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000288void aa_fun_1() {
289 glock.globalLock();
290 glock.globalUnlock();
291}
292
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000293void aa_fun_bad_1() {
294 glock.globalUnlock(); // \
Caitlin Sadowski8bccabe2011-09-08 21:52:50 +0000295 // expected-warning{{unlocking 'aa_mu' that was not locked}}
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000296}
297
298void aa_fun_bad_2() {
299 glock.globalLock();
300 glock.globalLock(); // \
Caitlin Sadowski8bccabe2011-09-08 21:52:50 +0000301 // expected-warning{{locking 'aa_mu' that is already locked}}
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000302 glock.globalUnlock();
303}
304
305void aa_fun_bad_3() {
306 glock.globalLock(); // \
Richard Trieu2fe9b7f2011-12-15 00:38:15 +0000307 // expected-warning{{mutex 'aa_mu' is still locked at the end of function}}
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000308}
Caitlin Sadowskib4d0a962011-08-29 17:12:27 +0000309
Caitlin Sadowskib4d0a962011-08-29 17:12:27 +0000310//--------------------------------------------------//
311// Regression tests for unusual method names
312//--------------------------------------------------//
313
314Mutex wmu;
315
316// Test diagnostics for other method names.
317class WeirdMethods {
318 WeirdMethods() {
319 wmu.Lock(); // \
Richard Trieu2fe9b7f2011-12-15 00:38:15 +0000320 // expected-warning {{mutex 'wmu' is still locked at the end of function}}
Caitlin Sadowskib4d0a962011-08-29 17:12:27 +0000321 }
322 ~WeirdMethods() {
323 wmu.Lock(); // \
Richard Trieu2fe9b7f2011-12-15 00:38:15 +0000324 // expected-warning {{mutex 'wmu' is still locked at the end of function}}
Caitlin Sadowskib4d0a962011-08-29 17:12:27 +0000325 }
326 void operator++() {
327 wmu.Lock(); // \
Richard Trieu2fe9b7f2011-12-15 00:38:15 +0000328 // expected-warning {{mutex 'wmu' is still locked at the end of function}}
Caitlin Sadowskib4d0a962011-08-29 17:12:27 +0000329 }
330 operator int*() {
331 wmu.Lock(); // \
Richard Trieu2fe9b7f2011-12-15 00:38:15 +0000332 // expected-warning {{mutex 'wmu' is still locked at the end of function}}
Caitlin Sadowskib4d0a962011-08-29 17:12:27 +0000333 return 0;
334 }
335};
336
Caitlin Sadowski05b436e2011-08-29 22:27:51 +0000337//-----------------------------------------------//
338// Errors for guarded by or guarded var variables
339// ----------------------------------------------//
340
341int *pgb_gvar __attribute__((pt_guarded_var));
342int *pgb_var __attribute__((pt_guarded_by(sls_mu)));
343
344class PGBFoo {
345 public:
346 int x;
347 int *pgb_field __attribute__((guarded_by(sls_mu2)))
348 __attribute__((pt_guarded_by(sls_mu)));
349 void testFoo() {
350 pgb_field = &x; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000351 // expected-warning {{writing variable 'pgb_field' requires locking 'sls_mu2' exclusively}}
352 *pgb_field = x; // expected-warning {{reading variable 'pgb_field' requires locking 'sls_mu2'}} \
353 // expected-warning {{writing the value pointed to by 'pgb_field' requires locking 'sls_mu' exclusively}}
354 x = *pgb_field; // expected-warning {{reading variable 'pgb_field' requires locking 'sls_mu2'}} \
355 // expected-warning {{reading the value pointed to by 'pgb_field' requires locking 'sls_mu'}}
356 (*pgb_field)++; // expected-warning {{reading variable 'pgb_field' requires locking 'sls_mu2'}} \
357 // expected-warning {{writing the value pointed to by 'pgb_field' requires locking 'sls_mu' exclusively}}
Caitlin Sadowski05b436e2011-08-29 22:27:51 +0000358 }
359};
360
361class GBFoo {
362 public:
363 int gb_field __attribute__((guarded_by(sls_mu)));
364
365 void testFoo() {
366 gb_field = 0; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000367 // expected-warning {{writing variable 'gb_field' requires locking 'sls_mu' exclusively}}
Caitlin Sadowski05b436e2011-08-29 22:27:51 +0000368 }
Caitlin Sadowskiaf370612011-09-08 18:35:21 +0000369
370 void testNoAnal() __attribute__((no_thread_safety_analysis)) {
371 gb_field = 0;
372 }
Caitlin Sadowski05b436e2011-08-29 22:27:51 +0000373};
374
375GBFoo GlobalGBFoo __attribute__((guarded_by(sls_mu)));
376
377void gb_fun_0() {
378 sls_mu.Lock();
379 int x = *pgb_var;
380 sls_mu.Unlock();
381}
382
383void gb_fun_1() {
384 sls_mu.Lock();
385 *pgb_var = 2;
386 sls_mu.Unlock();
387}
388
389void gb_fun_2() {
390 int x;
391 pgb_var = &x;
392}
393
394void gb_fun_3() {
395 int *x = pgb_var;
396}
397
398void gb_bad_0() {
399 sls_guard_var = 1; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000400 // expected-warning{{writing variable 'sls_guard_var' requires locking any mutex exclusively}}
Caitlin Sadowski05b436e2011-08-29 22:27:51 +0000401}
402
403void gb_bad_1() {
404 int x = sls_guard_var; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000405 // expected-warning{{reading variable 'sls_guard_var' requires locking any mutex}}
Caitlin Sadowski05b436e2011-08-29 22:27:51 +0000406}
407
408void gb_bad_2() {
409 sls_guardby_var = 1; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000410 // expected-warning {{writing variable 'sls_guardby_var' requires locking 'sls_mu' exclusively}}
Caitlin Sadowski05b436e2011-08-29 22:27:51 +0000411}
412
413void gb_bad_3() {
414 int x = sls_guardby_var; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000415 // expected-warning {{reading variable 'sls_guardby_var' requires locking 'sls_mu'}}
Caitlin Sadowski05b436e2011-08-29 22:27:51 +0000416}
417
418void gb_bad_4() {
419 *pgb_gvar = 1; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000420 // expected-warning {{writing the value pointed to by 'pgb_gvar' requires locking any mutex exclusively}}
Caitlin Sadowski05b436e2011-08-29 22:27:51 +0000421}
422
423void gb_bad_5() {
424 int x = *pgb_gvar; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000425 // expected-warning {{reading the value pointed to by 'pgb_gvar' requires locking any mutex}}
Caitlin Sadowski05b436e2011-08-29 22:27:51 +0000426}
427
428void gb_bad_6() {
429 *pgb_var = 1; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000430 // expected-warning {{writing the value pointed to by 'pgb_var' requires locking 'sls_mu' exclusively}}
Caitlin Sadowski05b436e2011-08-29 22:27:51 +0000431}
432
433void gb_bad_7() {
434 int x = *pgb_var; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000435 // expected-warning {{reading the value pointed to by 'pgb_var' requires locking 'sls_mu'}}
Caitlin Sadowski05b436e2011-08-29 22:27:51 +0000436}
437
438void gb_bad_8() {
439 GBFoo G;
440 G.gb_field = 0; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000441 // expected-warning {{writing variable 'gb_field' requires locking 'sls_mu'}}
Caitlin Sadowski05b436e2011-08-29 22:27:51 +0000442}
443
444void gb_bad_9() {
445 sls_guard_var++; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000446 // expected-warning{{writing variable 'sls_guard_var' requires locking any mutex exclusively}}
Caitlin Sadowski05b436e2011-08-29 22:27:51 +0000447 sls_guard_var--; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000448 // expected-warning{{writing variable 'sls_guard_var' requires locking any mutex exclusively}}
Caitlin Sadowski05b436e2011-08-29 22:27:51 +0000449 ++sls_guard_var; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000450 // expected-warning{{writing variable 'sls_guard_var' requires locking any mutex exclusively}}
Caitlin Sadowskia49d1d82011-09-09 16:07:55 +0000451 --sls_guard_var;// \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000452 // expected-warning{{writing variable 'sls_guard_var' requires locking any mutex exclusively}}
Caitlin Sadowski05b436e2011-08-29 22:27:51 +0000453}
Caitlin Sadowskib4d0a962011-08-29 17:12:27 +0000454
Caitlin Sadowskieff98fc2011-09-08 17:42:22 +0000455//-----------------------------------------------//
456// Warnings on variables with late parsed attributes
457// ----------------------------------------------//
458
459class LateFoo {
460public:
461 int a __attribute__((guarded_by(mu)));
462 int b;
463
464 void foo() __attribute__((exclusive_locks_required(mu))) { }
465
466 void test() {
467 a = 0; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000468 // expected-warning{{writing variable 'a' requires locking 'mu' exclusively}}
Caitlin Sadowskieff98fc2011-09-08 17:42:22 +0000469 b = a; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000470 // expected-warning {{reading variable 'a' requires locking 'mu'}}
Caitlin Sadowskieff98fc2011-09-08 17:42:22 +0000471 c = 0; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000472 // expected-warning {{writing variable 'c' requires locking 'mu' exclusively}}
Caitlin Sadowskieff98fc2011-09-08 17:42:22 +0000473 }
474
475 int c __attribute__((guarded_by(mu)));
476
477 Mutex mu;
478};
479
Caitlin Sadowski99107eb2011-09-09 16:21:55 +0000480class LateBar {
481 public:
482 int a_ __attribute__((guarded_by(mu1_)));
483 int b_;
484 int *q __attribute__((pt_guarded_by(mu)));
485 Mutex mu1_;
486 Mutex mu;
487 LateFoo Foo;
488 LateFoo Foo2;
489 LateFoo *FooPointer;
490};
491
492LateBar b1, *b3;
493
494void late_0() {
495 LateFoo FooA;
496 LateFoo FooB;
497 FooA.mu.Lock();
498 FooA.a = 5;
499 FooA.mu.Unlock();
500}
501
502void late_1() {
503 LateBar BarA;
504 BarA.FooPointer->mu.Lock();
505 BarA.FooPointer->a = 2;
506 BarA.FooPointer->mu.Unlock();
507}
508
509void late_bad_0() {
510 LateFoo fooA;
511 LateFoo fooB;
512 fooA.mu.Lock();
513 fooB.a = 5; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000514 // expected-warning{{writing variable 'a' requires locking 'mu' exclusively}}
Caitlin Sadowski99107eb2011-09-09 16:21:55 +0000515 fooA.mu.Unlock();
516}
517
518void late_bad_1() {
519 Mutex mu;
520 mu.Lock();
521 b1.mu1_.Lock();
522 int res = b1.a_ + b3->b_;
523 b3->b_ = *b1.q; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000524 // expected-warning{{reading the value pointed to by 'q' requires locking 'mu'}}
Caitlin Sadowski99107eb2011-09-09 16:21:55 +0000525 b1.mu1_.Unlock();
526 b1.b_ = res;
527 mu.Unlock();
528}
529
530void late_bad_2() {
531 LateBar BarA;
532 BarA.FooPointer->mu.Lock();
533 BarA.Foo.a = 2; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000534 // expected-warning{{writing variable 'a' requires locking 'mu' exclusively}}
Caitlin Sadowski99107eb2011-09-09 16:21:55 +0000535 BarA.FooPointer->mu.Unlock();
536}
537
538void late_bad_3() {
539 LateBar BarA;
540 BarA.Foo.mu.Lock();
541 BarA.FooPointer->a = 2; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000542 // expected-warning{{writing variable 'a' requires locking 'mu' exclusively}}
Caitlin Sadowski99107eb2011-09-09 16:21:55 +0000543 BarA.Foo.mu.Unlock();
544}
545
546void late_bad_4() {
547 LateBar BarA;
548 BarA.Foo.mu.Lock();
549 BarA.Foo2.a = 2; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000550 // expected-warning{{writing variable 'a' requires locking 'mu' exclusively}}
Caitlin Sadowski99107eb2011-09-09 16:21:55 +0000551 BarA.Foo.mu.Unlock();
552}
553
Caitlin Sadowskia53257c2011-09-08 18:19:38 +0000554//-----------------------------------------------//
555// Extra warnings for shared vs. exclusive locks
556// ----------------------------------------------//
557
558void shared_fun_0() {
559 sls_mu.Lock();
560 do {
561 sls_mu.Unlock();
562 sls_mu.Lock();
563 } while (getBool());
564 sls_mu.Unlock();
565}
566
567void shared_fun_1() {
Caitlin Sadowski4e4bc752011-09-15 17:25:19 +0000568 sls_mu.ReaderLock(); // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000569 // expected-warning {{mutex 'sls_mu' is locked exclusively and shared in the same scope}}
Caitlin Sadowskia53257c2011-09-08 18:19:38 +0000570 do {
571 sls_mu.Unlock();
Caitlin Sadowski4e4bc752011-09-15 17:25:19 +0000572 sls_mu.Lock(); // \
573 // expected-note {{the other lock of mutex 'sls_mu' is here}}
Caitlin Sadowskia53257c2011-09-08 18:19:38 +0000574 } while (getBool());
575 sls_mu.Unlock();
576}
577
578void shared_fun_3() {
579 if (getBool())
580 sls_mu.Lock();
581 else
582 sls_mu.Lock();
583 *pgb_var = 1;
584 sls_mu.Unlock();
585}
586
587void shared_fun_4() {
588 if (getBool())
589 sls_mu.ReaderLock();
590 else
591 sls_mu.ReaderLock();
592 int x = sls_guardby_var;
593 sls_mu.Unlock();
594}
595
596void shared_fun_8() {
597 if (getBool())
598 sls_mu.Lock(); // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000599 // expected-warning {{mutex 'sls_mu' is locked exclusively and shared in the same scope}}
Caitlin Sadowskia53257c2011-09-08 18:19:38 +0000600 else
601 sls_mu.ReaderLock(); // \
Caitlin Sadowski8bccabe2011-09-08 21:52:50 +0000602 // expected-note {{the other lock of mutex 'sls_mu' is here}}
Caitlin Sadowskia53257c2011-09-08 18:19:38 +0000603 sls_mu.Unlock();
604}
605
606void shared_bad_0() {
Caitlin Sadowski4e4bc752011-09-15 17:25:19 +0000607 sls_mu.Lock(); // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000608 // expected-warning {{mutex 'sls_mu' is locked exclusively and shared in the same scope}}
Caitlin Sadowskia53257c2011-09-08 18:19:38 +0000609 do {
610 sls_mu.Unlock();
Caitlin Sadowski4e4bc752011-09-15 17:25:19 +0000611 sls_mu.ReaderLock(); // \
612 // expected-note {{the other lock of mutex 'sls_mu' is here}}
Caitlin Sadowskia53257c2011-09-08 18:19:38 +0000613 } while (getBool());
614 sls_mu.Unlock();
615}
616
617void shared_bad_1() {
618 if (getBool())
619 sls_mu.Lock(); // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000620 // expected-warning {{mutex 'sls_mu' is locked exclusively and shared in the same scope}}
Caitlin Sadowskia53257c2011-09-08 18:19:38 +0000621 else
622 sls_mu.ReaderLock(); // \
Caitlin Sadowski8bccabe2011-09-08 21:52:50 +0000623 // expected-note {{the other lock of mutex 'sls_mu' is here}}
Caitlin Sadowskia53257c2011-09-08 18:19:38 +0000624 *pgb_var = 1;
625 sls_mu.Unlock();
626}
627
628void shared_bad_2() {
629 if (getBool())
630 sls_mu.ReaderLock(); // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000631 // expected-warning {{mutex 'sls_mu' is locked exclusively and shared in the same scope}}
Caitlin Sadowskia53257c2011-09-08 18:19:38 +0000632 else
633 sls_mu.Lock(); // \
Caitlin Sadowski8bccabe2011-09-08 21:52:50 +0000634 // expected-note {{the other lock of mutex 'sls_mu' is here}}
Caitlin Sadowskia53257c2011-09-08 18:19:38 +0000635 *pgb_var = 1;
636 sls_mu.Unlock();
637}
Caitlin Sadowski978191e2011-09-08 18:27:31 +0000638
639// FIXME: Add support for functions (not only methods)
640class LRBar {
641 public:
642 void aa_elr_fun() __attribute__((exclusive_locks_required(aa_mu)));
643 void aa_elr_fun_s() __attribute__((shared_locks_required(aa_mu)));
644 void le_fun() __attribute__((locks_excluded(sls_mu)));
645};
646
647class LRFoo {
648 public:
649 void test() __attribute__((exclusive_locks_required(sls_mu)));
650 void testShared() __attribute__((shared_locks_required(sls_mu2)));
651};
652
653void elr_fun() __attribute__((exclusive_locks_required(sls_mu)));
654void elr_fun() {}
655
656LRFoo MyLRFoo;
657LRBar Bar;
658
659void es_fun_0() {
660 aa_mu.Lock();
661 Bar.aa_elr_fun();
662 aa_mu.Unlock();
663}
664
665void es_fun_1() {
666 aa_mu.Lock();
667 Bar.aa_elr_fun_s();
668 aa_mu.Unlock();
669}
670
671void es_fun_2() {
672 aa_mu.ReaderLock();
673 Bar.aa_elr_fun_s();
674 aa_mu.Unlock();
675}
676
677void es_fun_3() {
678 sls_mu.Lock();
679 MyLRFoo.test();
680 sls_mu.Unlock();
681}
682
683void es_fun_4() {
684 sls_mu2.Lock();
685 MyLRFoo.testShared();
686 sls_mu2.Unlock();
687}
688
689void es_fun_5() {
690 sls_mu2.ReaderLock();
691 MyLRFoo.testShared();
692 sls_mu2.Unlock();
693}
694
695void es_fun_6() {
696 Bar.le_fun();
697}
698
699void es_fun_7() {
700 sls_mu.Lock();
701 elr_fun();
702 sls_mu.Unlock();
703}
704
Caitlin Sadowskiaf370612011-09-08 18:35:21 +0000705void es_fun_8() __attribute__((no_thread_safety_analysis));
706
707void es_fun_8() {
708 Bar.aa_elr_fun_s();
709}
710
Caitlin Sadowskicb967512011-09-15 17:43:08 +0000711void es_fun_9() __attribute__((shared_locks_required(aa_mu)));
712void es_fun_9() {
713 Bar.aa_elr_fun_s();
714}
715
716void es_fun_10() __attribute__((exclusive_locks_required(aa_mu)));
717void es_fun_10() {
718 Bar.aa_elr_fun_s();
719}
720
Caitlin Sadowski978191e2011-09-08 18:27:31 +0000721void es_bad_0() {
722 Bar.aa_elr_fun(); // \
Caitlin Sadowski8bccabe2011-09-08 21:52:50 +0000723 // expected-warning {{calling function 'aa_elr_fun' requires exclusive lock on 'aa_mu'}}
Caitlin Sadowski978191e2011-09-08 18:27:31 +0000724}
725
726void es_bad_1() {
727 aa_mu.ReaderLock();
728 Bar.aa_elr_fun(); // \
Caitlin Sadowski8bccabe2011-09-08 21:52:50 +0000729 // expected-warning {{calling function 'aa_elr_fun' requires exclusive lock on 'aa_mu'}}
Caitlin Sadowski978191e2011-09-08 18:27:31 +0000730 aa_mu.Unlock();
731}
732
733void es_bad_2() {
734 Bar.aa_elr_fun_s(); // \
Caitlin Sadowski8bccabe2011-09-08 21:52:50 +0000735 // expected-warning {{calling function 'aa_elr_fun_s' requires shared lock on 'aa_mu'}}
Caitlin Sadowski978191e2011-09-08 18:27:31 +0000736}
737
738void es_bad_3() {
739 MyLRFoo.test(); // \
Caitlin Sadowski8bccabe2011-09-08 21:52:50 +0000740 // expected-warning {{calling function 'test' requires exclusive lock on 'sls_mu'}}
Caitlin Sadowski978191e2011-09-08 18:27:31 +0000741}
742
743void es_bad_4() {
744 MyLRFoo.testShared(); // \
Caitlin Sadowski8bccabe2011-09-08 21:52:50 +0000745 // expected-warning {{calling function 'testShared' requires shared lock on 'sls_mu2'}}
Caitlin Sadowski978191e2011-09-08 18:27:31 +0000746}
747
748void es_bad_5() {
749 sls_mu.ReaderLock();
750 MyLRFoo.test(); // \
Caitlin Sadowski8bccabe2011-09-08 21:52:50 +0000751 // expected-warning {{calling function 'test' requires exclusive lock on 'sls_mu'}}
Caitlin Sadowski978191e2011-09-08 18:27:31 +0000752 sls_mu.Unlock();
753}
754
755void es_bad_6() {
756 sls_mu.Lock();
757 Bar.le_fun(); // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000758 // expected-warning {{cannot call function 'le_fun' while mutex 'sls_mu' is locked}}
Caitlin Sadowski978191e2011-09-08 18:27:31 +0000759 sls_mu.Unlock();
760}
761
762void es_bad_7() {
763 sls_mu.ReaderLock();
764 Bar.le_fun(); // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000765 // expected-warning {{cannot call function 'le_fun' while mutex 'sls_mu' is locked}}
Caitlin Sadowski978191e2011-09-08 18:27:31 +0000766 sls_mu.Unlock();
767}
Caitlin Sadowski194418f2011-09-14 20:00:24 +0000768
DeLesley Hutchins81216392011-10-17 21:38:02 +0000769
Caitlin Sadowski194418f2011-09-14 20:00:24 +0000770//-----------------------------------------------//
771// Unparseable lock expressions
772// ----------------------------------------------//
773
774Mutex UPmu;
775// FIXME: add support for lock expressions involving arrays.
776Mutex mua[5];
777
DeLesley Hutchinsf1ac6372011-10-21 18:10:14 +0000778int x __attribute__((guarded_by(UPmu = sls_mu)));
779int y __attribute__((guarded_by(mua[0])));
Caitlin Sadowski194418f2011-09-14 20:00:24 +0000780
781
782void testUnparse() {
DeLesley Hutchinsf1ac6372011-10-21 18:10:14 +0000783 x = 5; // \
784 // expected-warning{{cannot resolve lock expression}}
785 y = 5; // \
786 // expected-warning{{cannot resolve lock expression}}
Caitlin Sadowski194418f2011-09-14 20:00:24 +0000787}
788
789void testUnparse2() {
790 mua[0].Lock(); // \
DeLesley Hutchinsf1ac6372011-10-21 18:10:14 +0000791 // expected-warning{{cannot resolve lock expression}}
Caitlin Sadowski194418f2011-09-14 20:00:24 +0000792 (&(mua[0]) + 4)->Lock(); // \
DeLesley Hutchinsf1ac6372011-10-21 18:10:14 +0000793 // expected-warning{{cannot resolve lock expression}}
Caitlin Sadowski194418f2011-09-14 20:00:24 +0000794}
795
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +0000796
797//----------------------------------------------------------------------------//
798// The following test cases are ported from the gcc thread safety implementation
799// They are each wrapped inside a namespace with the test number of the gcc test
800//
801// FIXME: add all the gcc tests, once this analysis passes them.
802//----------------------------------------------------------------------------//
803
804//-----------------------------------------//
805// Good testcases (no errors)
806//-----------------------------------------//
807
808namespace thread_annot_lock_20 {
809class Bar {
810 public:
811 static int func1() EXCLUSIVE_LOCKS_REQUIRED(mu1_);
812 static int b_ GUARDED_BY(mu1_);
813 static Mutex mu1_;
814 static int a_ GUARDED_BY(mu1_);
815};
816
817Bar b1;
818
819int Bar::func1()
820{
821 int res = 5;
822
823 if (a_ == 4)
824 res = b_;
825 return res;
826}
827} // end namespace thread_annot_lock_20
828
829namespace thread_annot_lock_22 {
830// Test various usage of GUARDED_BY and PT_GUARDED_BY annotations, especially
831// uses in class definitions.
832Mutex mu;
833
834class Bar {
835 public:
836 int a_ GUARDED_BY(mu1_);
837 int b_;
838 int *q PT_GUARDED_BY(mu);
839 Mutex mu1_ ACQUIRED_AFTER(mu);
840};
841
842Bar b1, *b3;
843int *p GUARDED_BY(mu) PT_GUARDED_BY(mu);
844int res GUARDED_BY(mu) = 5;
845
846int func(int i)
847{
848 int x;
849 mu.Lock();
850 b1.mu1_.Lock();
851 res = b1.a_ + b3->b_;
852 *p = i;
853 b1.a_ = res + b3->b_;
854 b3->b_ = *b1.q;
855 b1.mu1_.Unlock();
856 b1.b_ = res;
857 x = res;
858 mu.Unlock();
859 return x;
860}
861} // end namespace thread_annot_lock_22
862
863namespace thread_annot_lock_27_modified {
864// test lock annotations applied to function definitions
865// Modified: applied annotations only to function declarations
866Mutex mu1;
867Mutex mu2 ACQUIRED_AFTER(mu1);
868
869class Foo {
870 public:
871 int method1(int i) SHARED_LOCKS_REQUIRED(mu2) EXCLUSIVE_LOCKS_REQUIRED(mu1);
872};
873
874int Foo::method1(int i) {
875 return i;
876}
877
878
879int foo(int i) EXCLUSIVE_LOCKS_REQUIRED(mu2) SHARED_LOCKS_REQUIRED(mu1);
880int foo(int i) {
881 return i;
882}
883
884static int bar(int i) EXCLUSIVE_LOCKS_REQUIRED(mu1);
885static int bar(int i) {
886 return i;
887}
888
889void main() {
890 Foo a;
891
892 mu1.Lock();
893 mu2.Lock();
894 a.method1(1);
895 foo(2);
896 mu2.Unlock();
897 bar(3);
898 mu1.Unlock();
899}
900} // end namespace thread_annot_lock_27_modified
901
902
903namespace thread_annot_lock_38 {
904// Test the case where a template member function is annotated with lock
905// attributes in a non-template class.
906class Foo {
907 public:
908 void func1(int y) LOCKS_EXCLUDED(mu_);
909 template <typename T> void func2(T x) LOCKS_EXCLUDED(mu_);
910 private:
911 Mutex mu_;
912};
913
914Foo *foo;
915
916void main()
917{
918 foo->func1(5);
919 foo->func2(5);
920}
921} // end namespace thread_annot_lock_38
922
923namespace thread_annot_lock_43 {
924// Tests lock canonicalization
925class Foo {
926 public:
927 Mutex *mu_;
928};
929
930class FooBar {
931 public:
932 Foo *foo_;
933 int GetA() EXCLUSIVE_LOCKS_REQUIRED(foo_->mu_) { return a_; }
934 int a_ GUARDED_BY(foo_->mu_);
935};
936
937FooBar *fb;
938
939void main()
940{
941 int x;
942 fb->foo_->mu_->Lock();
943 x = fb->GetA();
944 fb->foo_->mu_->Unlock();
945}
946} // end namespace thread_annot_lock_43
947
948namespace thread_annot_lock_49 {
949// Test the support for use of lock expression in the annotations
950class Foo {
951 public:
952 Mutex foo_mu_;
953};
954
955class Bar {
956 private:
957 Foo *foo;
958 Mutex bar_mu_ ACQUIRED_AFTER(foo->foo_mu_);
959
960 public:
961 void Test1() {
962 foo->foo_mu_.Lock();
963 bar_mu_.Lock();
964 bar_mu_.Unlock();
965 foo->foo_mu_.Unlock();
966 }
967};
968
969void main() {
970 Bar bar;
971 bar.Test1();
972}
973} // end namespace thread_annot_lock_49
974
975namespace thread_annot_lock_61_modified {
976 // Modified to fix the compiler errors
977 // Test the fix for a bug introduced by the support of pass-by-reference
978 // paramters.
979 struct Foo { Foo &operator<< (bool) {return *this;} };
980 Foo &getFoo();
981 struct Bar { Foo &func () {return getFoo();} };
982 struct Bas { void operator& (Foo &) {} };
983 void mumble()
984 {
985 Bas() & Bar().func() << "" << "";
986 Bas() & Bar().func() << "";
987 }
988} // end namespace thread_annot_lock_61_modified
989
990
991namespace thread_annot_lock_65 {
992// Test the fix for a bug in the support of allowing reader locks for
993// non-const, non-modifying overload functions. (We didn't handle the builtin
994// properly.)
995enum MyFlags {
996 Zero,
997 One,
998 Two,
999 Three,
1000 Four,
1001 Five,
1002 Six,
1003 Seven,
1004 Eight,
1005 Nine
1006};
1007
1008inline MyFlags
1009operator|(MyFlags a, MyFlags b)
1010{
1011 return MyFlags(static_cast<int>(a) | static_cast<int>(b));
1012}
1013
1014inline MyFlags&
1015operator|=(MyFlags& a, MyFlags b)
1016{
1017 return a = a | b;
1018}
1019} // end namespace thread_annot_lock_65
1020
1021namespace thread_annot_lock_66_modified {
1022// Modified: Moved annotation to function defn
1023// Test annotations on out-of-line definitions of member functions where the
1024// annotations refer to locks that are also data members in the class.
1025Mutex mu;
1026
1027class Foo {
1028 public:
1029 int method1(int i) SHARED_LOCKS_REQUIRED(mu1, mu, mu2);
1030 int data GUARDED_BY(mu1);
1031 Mutex *mu1;
1032 Mutex *mu2;
1033};
1034
1035int Foo::method1(int i)
1036{
1037 return data + i;
1038}
1039
1040void main()
1041{
1042 Foo a;
1043
1044 a.mu2->Lock();
1045 a.mu1->Lock();
1046 mu.Lock();
1047 a.method1(1);
1048 mu.Unlock();
1049 a.mu1->Unlock();
1050 a.mu2->Unlock();
1051}
1052} // end namespace thread_annot_lock_66_modified
1053
1054namespace thread_annot_lock_68_modified {
1055// Test a fix to a bug in the delayed name binding with nested template
1056// instantiation. We use a stack to make sure a name is not resolved to an
1057// inner context.
1058template <typename T>
1059class Bar {
1060 Mutex mu_;
1061};
1062
1063template <typename T>
1064class Foo {
1065 public:
1066 void func(T x) {
1067 mu_.Lock();
DeLesley Hutchins23323e02012-01-20 22:50:54 +00001068 count_ = x;
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001069 mu_.Unlock();
1070 }
1071
1072 private:
DeLesley Hutchins23323e02012-01-20 22:50:54 +00001073 T count_ GUARDED_BY(mu_);
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001074 Bar<T> bar_;
1075 Mutex mu_;
1076};
1077
1078void main()
1079{
1080 Foo<int> *foo;
1081 foo->func(5);
1082}
1083} // end namespace thread_annot_lock_68_modified
1084
1085namespace thread_annot_lock_30_modified {
1086// Test delay parsing of lock attribute arguments with nested classes.
1087// Modified: trylocks replaced with exclusive_lock_fun
1088int a = 0;
1089
1090class Bar {
1091 struct Foo;
1092
1093 public:
1094 void MyLock() EXCLUSIVE_LOCK_FUNCTION(mu);
1095
1096 int func() {
1097 MyLock();
1098// if (foo == 0) {
1099// return 0;
1100// }
1101 a = 5;
1102 mu.Unlock();
1103 return 1;
1104 }
1105
1106 class FooBar {
1107 int x;
1108 int y;
1109 };
1110
1111 private:
1112 Mutex mu;
1113};
1114
1115Bar *bar;
1116
1117void main()
1118{
1119 bar->func();
1120}
1121} // end namespace thread_annot_lock_30_modified
1122
1123namespace thread_annot_lock_47 {
1124// Test the support for annotations on virtual functions.
1125// This is a good test case. (i.e. There should be no warning emitted by the
1126// compiler.)
1127class Base {
1128 public:
1129 virtual void func1() EXCLUSIVE_LOCKS_REQUIRED(mu_);
1130 virtual void func2() LOCKS_EXCLUDED(mu_);
1131 Mutex mu_;
1132};
1133
1134class Child : public Base {
1135 public:
1136 virtual void func1() EXCLUSIVE_LOCKS_REQUIRED(mu_);
1137 virtual void func2() LOCKS_EXCLUDED(mu_);
1138};
1139
1140void main() {
1141 Child *c;
1142 Base *b = c;
1143
1144 b->mu_.Lock();
1145 b->func1();
1146 b->mu_.Unlock();
1147 b->func2();
1148
1149 c->mu_.Lock();
1150 c->func1();
1151 c->mu_.Unlock();
1152 c->func2();
1153}
1154} // end namespace thread_annot_lock_47
1155
1156//-----------------------------------------//
1157// Tests which produce errors
1158//-----------------------------------------//
1159
1160namespace thread_annot_lock_13 {
1161Mutex mu1;
1162Mutex mu2;
1163
1164int g GUARDED_BY(mu1);
1165int w GUARDED_BY(mu2);
1166
1167class Foo {
1168 public:
1169 void bar() LOCKS_EXCLUDED(mu_, mu1);
1170 int foo() SHARED_LOCKS_REQUIRED(mu_) EXCLUSIVE_LOCKS_REQUIRED(mu2);
1171
1172 private:
1173 int a_ GUARDED_BY(mu_);
1174 public:
1175 Mutex mu_ ACQUIRED_AFTER(mu1);
1176};
1177
1178int Foo::foo()
1179{
1180 int res;
1181 w = 5.2;
1182 res = a_ + 5;
1183 return res;
1184}
1185
1186void Foo::bar()
1187{
1188 int x;
1189 mu_.Lock();
1190 x = foo(); // expected-warning {{calling function 'foo' requires exclusive lock on 'mu2'}}
1191 a_ = x + 1;
1192 mu_.Unlock();
1193 if (x > 5) {
1194 mu1.Lock();
1195 g = 2.3;
1196 mu1.Unlock();
1197 }
1198}
1199
1200void main()
1201{
1202 Foo f1, *f2;
1203 f1.mu_.Lock();
Caitlin Sadowski74558b42011-09-15 18:13:32 +00001204 f1.bar(); // expected-warning {{cannot call function 'bar' while mutex 'mu_' is locked}}
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001205 mu2.Lock();
1206 f1.foo();
1207 mu2.Unlock();
1208 f1.mu_.Unlock();
1209 f2->mu_.Lock();
Caitlin Sadowski74558b42011-09-15 18:13:32 +00001210 f2->bar(); // expected-warning {{cannot call function 'bar' while mutex 'mu_' is locked}}
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001211 f2->mu_.Unlock();
1212 mu2.Lock();
1213 w = 2.5;
1214 mu2.Unlock();
1215}
1216} // end namespace thread_annot_lock_13
1217
1218namespace thread_annot_lock_18_modified {
1219// Modified: Trylocks removed
1220// Test the ability to distnguish between the same lock field of
1221// different objects of a class.
1222 class Bar {
1223 public:
1224 bool MyLock() EXCLUSIVE_LOCK_FUNCTION(mu1_);
1225 void MyUnlock() UNLOCK_FUNCTION(mu1_);
1226 int a_ GUARDED_BY(mu1_);
1227
1228 private:
1229 Mutex mu1_;
1230};
1231
1232Bar *b1, *b2;
1233
1234void func()
1235{
1236 b1->MyLock();
1237 b1->a_ = 5;
Caitlin Sadowski74558b42011-09-15 18:13:32 +00001238 b2->a_ = 3; // expected-warning {{writing variable 'a_' requires locking 'mu1_' exclusively}}
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001239 b2->MyLock();
1240 b2->MyUnlock();
1241 b1->MyUnlock();
1242}
1243} // end namespace thread_annot_lock_18_modified
1244
1245namespace thread_annot_lock_21 {
1246// Test various usage of GUARDED_BY and PT_GUARDED_BY annotations, especially
1247// uses in class definitions.
1248Mutex mu;
1249
1250class Bar {
1251 public:
1252 int a_ GUARDED_BY(mu1_);
1253 int b_;
1254 int *q PT_GUARDED_BY(mu);
1255 Mutex mu1_ ACQUIRED_AFTER(mu);
1256};
1257
1258Bar b1, *b3;
1259int *p GUARDED_BY(mu) PT_GUARDED_BY(mu);
1260
1261int res GUARDED_BY(mu) = 5;
1262
1263int func(int i)
1264{
1265 int x;
1266 b3->mu1_.Lock();
Caitlin Sadowski74558b42011-09-15 18:13:32 +00001267 res = b1.a_ + b3->b_; // expected-warning {{reading variable 'a_' requires locking 'mu1_'}} \
1268 // expected-warning {{writing variable 'res' requires locking 'mu' exclusively}}
1269 *p = i; // expected-warning {{reading variable 'p' requires locking 'mu'}} \
1270 // expected-warning {{writing the value pointed to by 'p' requires locking 'mu' exclusively}}
1271 b1.a_ = res + b3->b_; // expected-warning {{reading variable 'res' requires locking 'mu'}} \
1272 // expected-warning {{writing variable 'a_' requires locking 'mu1_' exclusively}}
1273 b3->b_ = *b1.q; // expected-warning {{reading the value pointed to by 'q' requires locking 'mu'}}
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001274 b3->mu1_.Unlock();
Caitlin Sadowski74558b42011-09-15 18:13:32 +00001275 b1.b_ = res; // expected-warning {{reading variable 'res' requires locking 'mu'}}
1276 x = res; // expected-warning {{reading variable 'res' requires locking 'mu'}}
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001277 return x;
1278}
1279} // end namespace thread_annot_lock_21
1280
1281namespace thread_annot_lock_35_modified {
1282// Test the analyzer's ability to distinguish the lock field of different
1283// objects.
1284class Foo {
1285 private:
1286 Mutex lock_;
1287 int a_ GUARDED_BY(lock_);
1288
1289 public:
1290 void Func(Foo* child) LOCKS_EXCLUDED(lock_) {
1291 Foo *new_foo = new Foo;
1292
1293 lock_.Lock();
1294
1295 child->Func(new_foo); // There shouldn't be any warning here as the
1296 // acquired lock is not in child.
1297 child->bar(7); // expected-warning {{calling function 'bar' requires exclusive lock on 'lock_'}}
Caitlin Sadowski74558b42011-09-15 18:13:32 +00001298 child->a_ = 5; // expected-warning {{writing variable 'a_' requires locking 'lock_' exclusively}}
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001299 lock_.Unlock();
1300 }
1301
1302 void bar(int y) EXCLUSIVE_LOCKS_REQUIRED(lock_) {
1303 a_ = y;
1304 }
1305};
1306
1307Foo *x;
1308
1309void main() {
1310 Foo *child = new Foo;
1311 x->Func(child);
1312}
1313} // end namespace thread_annot_lock_35_modified
1314
1315namespace thread_annot_lock_36_modified {
1316// Modified to move the annotations to function defns.
1317// Test the analyzer's ability to distinguish the lock field of different
1318// objects
1319class Foo {
1320 private:
1321 Mutex lock_;
1322 int a_ GUARDED_BY(lock_);
1323
1324 public:
1325 void Func(Foo* child) LOCKS_EXCLUDED(lock_);
1326 void bar(int y) EXCLUSIVE_LOCKS_REQUIRED(lock_);
1327};
1328
1329void Foo::Func(Foo* child) {
1330 Foo *new_foo = new Foo;
1331
1332 lock_.Lock();
1333
1334 child->lock_.Lock();
Caitlin Sadowski74558b42011-09-15 18:13:32 +00001335 child->Func(new_foo); // expected-warning {{cannot call function 'Func' while mutex 'lock_' is locked}}
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001336 child->bar(7);
1337 child->a_ = 5;
1338 child->lock_.Unlock();
1339
1340 lock_.Unlock();
1341}
1342
1343void Foo::bar(int y) {
1344 a_ = y;
1345}
1346
1347
1348Foo *x;
1349
1350void main() {
1351 Foo *child = new Foo;
1352 x->Func(child);
1353}
1354} // end namespace thread_annot_lock_36_modified
1355
1356
1357namespace thread_annot_lock_42 {
1358// Test support of multiple lock attributes of the same kind on a decl.
1359class Foo {
1360 private:
1361 Mutex mu1, mu2, mu3;
1362 int x GUARDED_BY(mu1) GUARDED_BY(mu2);
1363 int y GUARDED_BY(mu2);
1364
1365 void f2() LOCKS_EXCLUDED(mu1) LOCKS_EXCLUDED(mu2) LOCKS_EXCLUDED(mu3) {
1366 mu2.Lock();
1367 y = 2;
1368 mu2.Unlock();
1369 }
1370
1371 public:
1372 void f1() EXCLUSIVE_LOCKS_REQUIRED(mu2) EXCLUSIVE_LOCKS_REQUIRED(mu1) {
1373 x = 5;
Caitlin Sadowski74558b42011-09-15 18:13:32 +00001374 f2(); // expected-warning {{cannot call function 'f2' while mutex 'mu1' is locked}} \
1375 // expected-warning {{cannot call function 'f2' while mutex 'mu2' is locked}}
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001376 }
1377};
1378
1379Foo *foo;
1380
1381void func()
1382{
1383 foo->f1(); // expected-warning {{calling function 'f1' requires exclusive lock on 'mu2'}} \
1384 // expected-warning {{calling function 'f1' requires exclusive lock on 'mu1'}}
1385}
1386} // end namespace thread_annot_lock_42
1387
1388namespace thread_annot_lock_46 {
1389// Test the support for annotations on virtual functions.
1390class Base {
1391 public:
1392 virtual void func1() EXCLUSIVE_LOCKS_REQUIRED(mu_);
1393 virtual void func2() LOCKS_EXCLUDED(mu_);
1394 Mutex mu_;
1395};
1396
1397class Child : public Base {
1398 public:
1399 virtual void func1() EXCLUSIVE_LOCKS_REQUIRED(mu_);
1400 virtual void func2() LOCKS_EXCLUDED(mu_);
1401};
1402
1403void main() {
1404 Child *c;
1405 Base *b = c;
1406
1407 b->func1(); // expected-warning {{calling function 'func1' requires exclusive lock on 'mu_'}}
1408 b->mu_.Lock();
Caitlin Sadowski74558b42011-09-15 18:13:32 +00001409 b->func2(); // expected-warning {{cannot call function 'func2' while mutex 'mu_' is locked}}
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001410 b->mu_.Unlock();
1411
1412 c->func1(); // expected-warning {{calling function 'func1' requires exclusive lock on 'mu_'}}
1413 c->mu_.Lock();
Caitlin Sadowski74558b42011-09-15 18:13:32 +00001414 c->func2(); // expected-warning {{cannot call function 'func2' while mutex 'mu_' is locked}}
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001415 c->mu_.Unlock();
1416}
1417} // end namespace thread_annot_lock_46
1418
1419namespace thread_annot_lock_67_modified {
1420// Modified: attributes on definitions moved to declarations
1421// Test annotations on out-of-line definitions of member functions where the
1422// annotations refer to locks that are also data members in the class.
1423Mutex mu;
1424Mutex mu3;
1425
1426class Foo {
1427 public:
1428 int method1(int i) SHARED_LOCKS_REQUIRED(mu1, mu, mu2, mu3);
1429 int data GUARDED_BY(mu1);
1430 Mutex *mu1;
1431 Mutex *mu2;
1432};
1433
1434int Foo::method1(int i) {
1435 return data + i;
1436}
1437
1438void main()
1439{
1440 Foo a;
1441 a.method1(1); // expected-warning {{calling function 'method1' requires shared lock on 'mu1'}} \
1442 // expected-warning {{calling function 'method1' requires shared lock on 'mu'}} \
1443 // expected-warning {{calling function 'method1' requires shared lock on 'mu2'}} \
1444 // expected-warning {{calling function 'method1' requires shared lock on 'mu3'}}
1445}
1446} // end namespace thread_annot_lock_67_modified
1447
1448
DeLesley Hutchins81216392011-10-17 21:38:02 +00001449namespace substitution_test {
1450 class MyData {
1451 public:
1452 Mutex mu;
1453
1454 void lockData() __attribute__((exclusive_lock_function(mu))) { }
1455 void unlockData() __attribute__((unlock_function(mu))) { }
1456
1457 void doSomething() __attribute__((exclusive_locks_required(mu))) { }
1458 };
1459
1460
1461 class DataLocker {
1462 public:
1463 void lockData (MyData *d) __attribute__((exclusive_lock_function(d->mu))) { }
1464 void unlockData(MyData *d) __attribute__((unlock_function(d->mu))) { }
1465 };
1466
1467
1468 class Foo {
1469 public:
1470 void foo(MyData* d) __attribute__((exclusive_locks_required(d->mu))) { }
1471
1472 void bar1(MyData* d) {
1473 d->lockData();
1474 foo(d);
1475 d->unlockData();
1476 }
1477
1478 void bar2(MyData* d) {
1479 DataLocker dlr;
1480 dlr.lockData(d);
1481 foo(d);
1482 dlr.unlockData(d);
1483 }
1484
1485 void bar3(MyData* d1, MyData* d2) {
1486 DataLocker dlr;
1487 dlr.lockData(d1); // \
1488 // expected-warning {{mutex 'mu' is still locked at the end of function}}
1489 dlr.unlockData(d2); // \
1490 // expected-warning {{unlocking 'mu' that was not locked}}
1491 }
1492
1493 void bar4(MyData* d1, MyData* d2) {
1494 DataLocker dlr;
1495 dlr.lockData(d1);
1496 foo(d2); // \
1497 // expected-warning {{calling function 'foo' requires exclusive lock on 'mu'}}
1498 dlr.unlockData(d1);
1499 }
1500 };
1501} // end namespace substituation_test
1502
DeLesley Hutchinse0eaa852011-10-21 18:06:53 +00001503
DeLesley Hutchinsf1ac6372011-10-21 18:10:14 +00001504
DeLesley Hutchinse0eaa852011-10-21 18:06:53 +00001505namespace constructor_destructor_tests {
1506 Mutex fooMu;
1507 int myVar GUARDED_BY(fooMu);
1508
1509 class Foo {
1510 public:
1511 Foo() __attribute__((exclusive_lock_function(fooMu))) { }
1512 ~Foo() __attribute__((unlock_function(fooMu))) { }
1513 };
1514
1515 void fooTest() {
DeLesley Hutchins6db51f72011-10-21 20:51:27 +00001516 Foo foo;
DeLesley Hutchinse0eaa852011-10-21 18:06:53 +00001517 myVar = 0;
1518 }
1519}
1520
DeLesley Hutchinsf1ac6372011-10-21 18:10:14 +00001521
1522namespace invalid_lock_expression_test {
1523
1524class LOCKABLE MyLockable {
1525public:
1526 MyLockable() __attribute__((exclusive_lock_function)) { }
DeLesley Hutchins6db51f72011-10-21 20:51:27 +00001527 ~MyLockable() { }
DeLesley Hutchinsf1ac6372011-10-21 18:10:14 +00001528};
1529
1530// create an empty lock expression
1531void foo() {
1532 MyLockable lock; // \
1533 // expected-warning {{cannot resolve lock expression}}
1534}
1535
1536} // end namespace invalid_lock_expression_test
1537
Richard Smith97f9fe02011-10-25 00:41:24 +00001538namespace template_member_test {
DeLesley Hutchinsf1ac6372011-10-21 18:10:14 +00001539
Richard Smith97f9fe02011-10-25 00:41:24 +00001540 struct S { int n; };
1541 struct T {
1542 Mutex m;
1543 S *s GUARDED_BY(this->m);
1544 };
Richard Smitha01c7112011-10-25 06:33:21 +00001545 Mutex m;
1546 struct U {
1547 union {
1548 int n;
1549 };
1550 } *u GUARDED_BY(m);
Richard Smith97f9fe02011-10-25 00:41:24 +00001551
1552 template<typename U>
1553 struct IndirectLock {
1554 int DoNaughtyThings(T *t) {
Richard Smitha01c7112011-10-25 06:33:21 +00001555 u->n = 0; // expected-warning {{reading variable 'u' requires locking 'm'}}
Richard Smith97f9fe02011-10-25 00:41:24 +00001556 return t->s->n; // expected-warning {{reading variable 's' requires locking 'm'}}
1557 }
1558 };
1559
Richard Smithf11e9232011-10-25 01:05:41 +00001560 template struct IndirectLock<int>; // expected-note {{here}}
Richard Smith97f9fe02011-10-25 00:41:24 +00001561
Richard Smith601d2ee2011-10-26 06:15:36 +00001562 struct V {
1563 void f(int);
1564 void f(double);
1565
1566 Mutex m;
1567 V *p GUARDED_BY(this->m);
1568 };
1569 template<typename U> struct W {
1570 V v;
1571 void f(U u) {
1572 v.p->f(u); // expected-warning {{reading variable 'p' requires locking 'm'}}
1573 }
1574 };
1575 template struct W<int>; // expected-note {{here}}
1576
Richard Smith97f9fe02011-10-25 00:41:24 +00001577}
DeLesley Hutchins1fa3c062011-12-08 20:23:06 +00001578
1579namespace test_scoped_lockable {
1580
1581struct TestScopedLockable {
1582 Mutex mu1;
1583 Mutex mu2;
1584 int a __attribute__((guarded_by(mu1)));
1585 int b __attribute__((guarded_by(mu2)));
1586
1587 bool getBool();
1588
1589 void foo1() {
1590 MutexLock mulock(&mu1);
1591 a = 5;
1592 }
1593
1594 void foo2() {
1595 ReaderMutexLock mulock1(&mu1);
1596 if (getBool()) {
1597 MutexLock mulock2a(&mu2);
1598 b = a + 1;
1599 }
1600 else {
1601 MutexLock mulock2b(&mu2);
1602 b = a + 2;
1603 }
1604 }
1605
1606 void foo3() {
1607 MutexLock mulock_a(&mu1);
1608 MutexLock mulock_b(&mu1); // \
1609 // expected-warning {{locking 'mu1' that is already locked}}
1610 } // expected-warning {{unlocking 'mu1' that was not locked}}
1611
1612 void foo4() {
1613 MutexLock mulock1(&mu1), mulock2(&mu2);
1614 a = b+1;
1615 b = a+1;
1616 }
1617};
1618
1619} // end namespace test_scoped_lockable
1620
1621
DeLesley Hutchinsdf497822011-12-29 00:56:48 +00001622namespace FunctionAttrTest {
1623
1624class Foo {
1625public:
1626 Mutex mu_;
1627 int a GUARDED_BY(mu_);
1628};
1629
1630Foo fooObj;
1631
1632void foo() EXCLUSIVE_LOCKS_REQUIRED(fooObj.mu_);
1633
1634void bar() {
1635 foo(); // expected-warning {{calling function 'foo' requires exclusive lock on 'mu_'}}
1636 fooObj.mu_.Lock();
1637 foo();
1638 fooObj.mu_.Unlock();
1639}
1640
1641}; // end namespace FunctionAttrTest
1642
1643
DeLesley Hutchinsb4fa4182012-01-06 19:16:50 +00001644struct TestTryLock {
1645 Mutex mu;
1646 int a GUARDED_BY(mu);
1647 bool cond;
1648
1649 void foo1() {
1650 if (mu.TryLock()) {
1651 a = 1;
1652 mu.Unlock();
1653 }
1654 }
1655
1656 void foo2() {
1657 if (!mu.TryLock()) return;
1658 a = 2;
1659 mu.Unlock();
1660 }
1661
1662 void foo3() {
1663 bool b = mu.TryLock();
1664 if (b) {
1665 a = 3;
1666 mu.Unlock();
1667 }
1668 }
1669
1670 void foo4() {
1671 bool b = mu.TryLock();
1672 if (!b) return;
1673 a = 4;
1674 mu.Unlock();
1675 }
1676
1677 void foo5() {
1678 while (mu.TryLock()) {
1679 a = a + 1;
1680 mu.Unlock();
1681 }
1682 }
1683
1684 void foo6() {
1685 bool b = mu.TryLock();
1686 b = !b;
1687 if (b) return;
1688 a = 6;
1689 mu.Unlock();
1690 }
1691
1692 void foo7() {
1693 bool b1 = mu.TryLock();
1694 bool b2 = !b1;
1695 bool b3 = !b2;
1696 if (b3) {
1697 a = 7;
1698 mu.Unlock();
1699 }
1700 }
1701
1702 // Test use-def chains: join points
1703 void foo8() {
1704 bool b = mu.TryLock();
1705 bool b2 = b;
1706 if (cond)
1707 b = true;
1708 if (b) { // b should be unknown at this point, becuase of the join point
1709 a = 8; // expected-warning {{writing variable 'a' requires locking 'mu' exclusively}}
1710 }
1711 if (b2) { // b2 should be known at this point.
1712 a = 8;
1713 mu.Unlock();
1714 }
1715 }
1716
1717 // Test use-def-chains: back edges
1718 void foo9() {
1719 bool b = mu.TryLock();
1720
1721 for (int i = 0; i < 10; ++i);
1722
1723 if (b) { // b is still known, because the loop doesn't alter it
1724 a = 9;
1725 mu.Unlock();
1726 }
1727 }
1728
1729 // Test use-def chains: back edges
1730 void foo10() {
1731 bool b = mu.TryLock();
1732
1733 while (cond) {
1734 if (b) { // b should be uknown at this point b/c of the loop
1735 a = 10; // expected-warning {{writing variable 'a' requires locking 'mu' exclusively}}
1736 }
1737 b = !b;
1738 }
1739 }
1740}; // end TestTrylock
1741
1742
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +00001743namespace TestTemplateAttributeInstantiation {
1744
1745class Foo1 {
1746public:
1747 Mutex mu_;
1748 int a GUARDED_BY(mu_);
1749};
1750
1751class Foo2 {
1752public:
1753 int a GUARDED_BY(mu_);
1754 Mutex mu_;
1755};
1756
1757
1758class Bar {
1759public:
1760 // Test non-dependent expressions in attributes on template functions
1761 template <class T>
1762 void barND(Foo1 *foo, T *fooT) EXCLUSIVE_LOCKS_REQUIRED(foo->mu_) {
1763 foo->a = 0;
1764 }
1765
1766 // Test dependent expressions in attributes on template functions
1767 template <class T>
1768 void barD(Foo1 *foo, T *fooT) EXCLUSIVE_LOCKS_REQUIRED(fooT->mu_) {
1769 fooT->a = 0;
1770 }
1771};
1772
1773
1774template <class T>
1775class BarT {
1776public:
1777 Foo1 fooBase;
1778 T fooBaseT;
1779
1780 // Test non-dependent expression in ordinary method on template class
1781 void barND() EXCLUSIVE_LOCKS_REQUIRED(fooBase.mu_) {
1782 fooBase.a = 0;
1783 }
1784
1785 // Test dependent expressions in ordinary methods on template class
1786 void barD() EXCLUSIVE_LOCKS_REQUIRED(fooBaseT.mu_) {
1787 fooBaseT.a = 0;
1788 }
1789
1790 // Test dependent expressions in template method in template class
1791 template <class T2>
1792 void barTD(T2 *fooT) EXCLUSIVE_LOCKS_REQUIRED(fooBaseT.mu_, fooT->mu_) {
1793 fooBaseT.a = 0;
1794 fooT->a = 0;
1795 }
1796};
1797
1798template <class T>
1799class Cell {
1800public:
1801 Mutex mu_;
1802 // Test dependent guarded_by
1803 T data GUARDED_BY(mu_);
1804
DeLesley Hutchins23323e02012-01-20 22:50:54 +00001805 void fooEx() EXCLUSIVE_LOCKS_REQUIRED(mu_) {
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +00001806 data = 0;
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +00001807 }
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +00001808
1809 void foo() {
1810 mu_.Lock();
1811 data = 0;
1812 mu_.Unlock();
1813 }
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +00001814};
1815
1816void test() {
1817 Bar b;
1818 BarT<Foo2> bt;
1819 Foo1 f1;
1820 Foo2 f2;
1821
1822 f1.mu_.Lock();
1823 f2.mu_.Lock();
1824 bt.fooBase.mu_.Lock();
1825 bt.fooBaseT.mu_.Lock();
1826
1827 b.barND(&f1, &f2);
1828 b.barD(&f1, &f2);
1829 bt.barND();
1830 bt.barD();
1831 bt.barTD(&f2);
1832
1833 f1.mu_.Unlock();
1834 bt.barTD(&f1); // \
1835 // expected-warning {{calling function 'barTD' requires exclusive lock on 'mu_'}}
1836
1837 bt.fooBase.mu_.Unlock();
1838 bt.fooBaseT.mu_.Unlock();
1839 f2.mu_.Unlock();
1840
1841 Cell<int> cell;
1842 cell.data = 0; // \
1843 // expected-warning {{writing variable 'data' requires locking 'mu_' exclusively}}
1844 cell.foo();
DeLesley Hutchins23323e02012-01-20 22:50:54 +00001845 cell.mu_.Lock();
1846 cell.fooEx();
1847 cell.mu_.Unlock();
1848}
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +00001849
DeLesley Hutchins23323e02012-01-20 22:50:54 +00001850
1851template <class T>
1852class CellDelayed {
1853public:
1854 // Test dependent guarded_by
1855 T data GUARDED_BY(mu_);
1856
1857 void fooEx(CellDelayed<T> *other) EXCLUSIVE_LOCKS_REQUIRED(mu_, other->mu_) {
1858 this->data = other->data;
1859 }
1860
1861 template <class T2>
1862 void fooExT(CellDelayed<T2> *otherT) EXCLUSIVE_LOCKS_REQUIRED(mu_, otherT->mu_) {
1863 this->data = otherT->data;
1864 }
1865
1866 void foo() {
1867 mu_.Lock();
1868 data = 0;
1869 mu_.Unlock();
1870 }
1871
1872 Mutex mu_;
1873};
1874
1875void testDelayed() {
1876 CellDelayed<int> celld;
1877 CellDelayed<int> celld2;
1878 celld.foo();
1879 celld.mu_.Lock();
1880 celld2.mu_.Lock();
1881
1882 celld.fooEx(&celld2);
1883 celld.fooExT(&celld2);
1884
1885 celld2.mu_.Unlock();
1886 celld.mu_.Unlock();
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +00001887}
1888
1889}; // end namespace TestTemplateAttributeInstantiation
1890
1891
DeLesley Hutchinse03b2b32012-01-20 23:24:41 +00001892namespace FunctionDeclDefTest {
1893
1894class Foo {
1895public:
1896 Mutex mu_;
1897 int a GUARDED_BY(mu_);
1898
1899 virtual void foo1(Foo *f_declared) EXCLUSIVE_LOCKS_REQUIRED(f_declared->mu_);
1900};
1901
1902// EXCLUSIVE_LOCKS_REQUIRED should be applied, and rewritten to f_defined->mu_
1903void Foo::foo1(Foo *f_defined) {
1904 f_defined->a = 0;
1905};
1906
1907void test() {
1908 Foo myfoo;
1909 myfoo.foo1(&myfoo); // \
1910 // expected-warning {{calling function 'foo1' requires exclusive lock on 'mu_'}}
1911 myfoo.mu_.Lock();
1912 myfoo.foo1(&myfoo);
1913 myfoo.mu_.Unlock();
1914}
1915
1916};