blob: 8bbaf0398fae3b9e041681d8e167ad2087ddc8c1 [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() {
Richard Smith2e515622012-02-03 04:45:26 +0000175 sls_mu.Lock(); // expected-note {{mutex acquired here}}
176} // expected-warning{{mutex 'sls_mu' is still locked at the end of function}}
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000177
178void sls_fun_bad_4() {
179 if (getBool())
180 sls_mu.Lock(); // \
Richard Smith2e515622012-02-03 04:45:26 +0000181 expected-warning{{mutex 'sls_mu2' is not locked on every path through here}} \
182 expected-note{{mutex acquired here}}
183
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000184 else
185 sls_mu2.Lock(); // \
Richard Smith2e515622012-02-03 04:45:26 +0000186 expected-note{{mutex acquired here}}
187} // expected-warning{{mutex 'sls_mu' is not locked on every path through here}}
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000188
189void sls_fun_bad_5() {
Richard Smith2e515622012-02-03 04:45:26 +0000190 sls_mu.Lock(); // expected-note {{mutex acquired here}}
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000191 if (getBool())
192 sls_mu.Unlock();
Richard Smith2e515622012-02-03 04:45:26 +0000193} // expected-warning{{mutex 'sls_mu' is not locked on every path through here}}
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000194
195void sls_fun_bad_6() {
196 if (getBool()) {
Richard Smith2e515622012-02-03 04:45:26 +0000197 sls_mu.Lock(); // expected-note {{mutex acquired here}}
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000198 } else {
199 if (getBool()) {
200 getBool(); // EMPTY
201 } else {
202 getBool(); // EMPTY
203 }
204 }
205 sls_mu.Unlock(); // \
Richard Smith2e515622012-02-03 04:45:26 +0000206 expected-warning{{mutex 'sls_mu' is not locked on every path through here}}\
207 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()) {
Richard Smith2e515622012-02-03 04:45:26 +0000216 continue; // \
217 expected-warning{{expecting mutex 'sls_mu' to be locked at start of each loop}}
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000218 }
219 }
Richard Smith2e515622012-02-03 04:45:26 +0000220 sls_mu.Lock(); // expected-note {{mutex acquired here}}
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000221 }
222 sls_mu.Unlock();
223}
224
225void sls_fun_bad_8() {
Richard Smith2e515622012-02-03 04:45:26 +0000226 sls_mu.Lock(); // expected-note{{mutex acquired here}}
227
228 // FIXME: TERRIBLE SOURCE LOCATION!
229 do { // expected-warning{{expecting mutex 'sls_mu' to be locked at start of each loop}}
Caitlin Sadowski4e4bc752011-09-15 17:25:19 +0000230 sls_mu.Unlock();
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000231 } while (getBool());
232}
233
234void sls_fun_bad_9() {
235 do {
236 sls_mu.Lock(); // \
Richard Smith2e515622012-02-03 04:45:26 +0000237 // expected-warning{{expecting mutex 'sls_mu' to be locked at start of each loop}} \
238 // expected-note{{mutex acquired here}}
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000239 } while (getBool());
240 sls_mu.Unlock();
241}
242
243void sls_fun_bad_10() {
Richard Smith2e515622012-02-03 04:45:26 +0000244 sls_mu.Lock(); // expected-note 2{{mutex acquired here}}
Caitlin Sadowski4e4bc752011-09-15 17:25:19 +0000245 while(getBool()) {
Richard Smith2e515622012-02-03 04:45:26 +0000246 sls_mu.Unlock(); // expected-warning{{expecting mutex 'sls_mu' to be locked at start of each loop}}
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000247 }
Richard Smith2e515622012-02-03 04:45:26 +0000248} // expected-warning{{mutex 'sls_mu' is still locked at the end of function}}
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000249
250void sls_fun_bad_11() {
Richard Smith2e515622012-02-03 04:45:26 +0000251 while (getBool()) { // \
252 expected-warning{{expecting mutex 'sls_mu' to be locked at start of each loop}}
253 sls_mu.Lock(); // expected-note {{mutex acquired here}}
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() {
Richard Smith2e515622012-02-03 04:45:26 +0000260 sls_mu.Lock(); // expected-note {{mutex acquired here}}
Richard Smithaacde712012-02-03 03:30:07 +0000261 while (getBool()) {
262 sls_mu.Unlock();
263 if (getBool()) {
264 if (getBool()) {
Richard Smith2e515622012-02-03 04:45:26 +0000265 break; // expected-warning{{mutex 'sls_mu' is not locked on every path through here}}
Richard Smithaacde712012-02-03 03:30:07 +0000266 }
267 }
268 sls_mu.Lock();
269 }
270 sls_mu.Unlock();
271}
272
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000273//-----------------------------------------//
274// Handling lock expressions in attribute args
275// -------------------------------------------//
276
277Mutex aa_mu;
278
279class GlobalLocker {
280public:
281 void globalLock() __attribute__((exclusive_lock_function(aa_mu)));
282 void globalUnlock() __attribute__((unlock_function(aa_mu)));
283};
284
285GlobalLocker glock;
286
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000287void aa_fun_1() {
288 glock.globalLock();
289 glock.globalUnlock();
290}
291
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000292void aa_fun_bad_1() {
293 glock.globalUnlock(); // \
Caitlin Sadowski8bccabe2011-09-08 21:52:50 +0000294 // expected-warning{{unlocking 'aa_mu' that was not locked}}
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000295}
296
297void aa_fun_bad_2() {
298 glock.globalLock();
299 glock.globalLock(); // \
Caitlin Sadowski8bccabe2011-09-08 21:52:50 +0000300 // expected-warning{{locking 'aa_mu' that is already locked}}
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000301 glock.globalUnlock();
302}
303
304void aa_fun_bad_3() {
Richard Smith2e515622012-02-03 04:45:26 +0000305 glock.globalLock(); // expected-note{{mutex acquired here}}
306} // expected-warning{{mutex 'aa_mu' is still locked at the end of function}}
Caitlin Sadowskib4d0a962011-08-29 17:12:27 +0000307
Caitlin Sadowskib4d0a962011-08-29 17:12:27 +0000308//--------------------------------------------------//
309// Regression tests for unusual method names
310//--------------------------------------------------//
311
312Mutex wmu;
313
314// Test diagnostics for other method names.
315class WeirdMethods {
DeLesley Hutchins2f13bec2012-02-16 17:13:43 +0000316 // FIXME: can't currently check inside constructors and destructors.
Caitlin Sadowskib4d0a962011-08-29 17:12:27 +0000317 WeirdMethods() {
DeLesley Hutchins2f13bec2012-02-16 17:13:43 +0000318 wmu.Lock(); // EXPECTED-NOTE {{mutex acquired here}}
319 } // EXPECTED-WARNING {{mutex 'wmu' is still locked at the end of function}}
Caitlin Sadowskib4d0a962011-08-29 17:12:27 +0000320 ~WeirdMethods() {
DeLesley Hutchins2f13bec2012-02-16 17:13:43 +0000321 wmu.Lock(); // EXPECTED-NOTE {{mutex acquired here}}
322 } // EXPECTED-WARNING {{mutex 'wmu' is still locked at the end of function}}
Caitlin Sadowskib4d0a962011-08-29 17:12:27 +0000323 void operator++() {
Richard Smith2e515622012-02-03 04:45:26 +0000324 wmu.Lock(); // expected-note {{mutex acquired here}}
325 } // expected-warning {{mutex 'wmu' is still locked at the end of function}}
Caitlin Sadowskib4d0a962011-08-29 17:12:27 +0000326 operator int*() {
Richard Smith2e515622012-02-03 04:45:26 +0000327 wmu.Lock(); // expected-note {{mutex acquired here}}
Caitlin Sadowskib4d0a962011-08-29 17:12:27 +0000328 return 0;
Richard Smith2e515622012-02-03 04:45:26 +0000329 } // expected-warning {{mutex 'wmu' is still locked at the end of function}}
Caitlin Sadowskib4d0a962011-08-29 17:12:27 +0000330};
331
Caitlin Sadowski05b436e2011-08-29 22:27:51 +0000332//-----------------------------------------------//
333// Errors for guarded by or guarded var variables
334// ----------------------------------------------//
335
336int *pgb_gvar __attribute__((pt_guarded_var));
337int *pgb_var __attribute__((pt_guarded_by(sls_mu)));
338
339class PGBFoo {
340 public:
341 int x;
342 int *pgb_field __attribute__((guarded_by(sls_mu2)))
343 __attribute__((pt_guarded_by(sls_mu)));
344 void testFoo() {
345 pgb_field = &x; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000346 // expected-warning {{writing variable 'pgb_field' requires locking 'sls_mu2' exclusively}}
347 *pgb_field = x; // expected-warning {{reading variable 'pgb_field' requires locking 'sls_mu2'}} \
348 // expected-warning {{writing the value pointed to by 'pgb_field' requires locking 'sls_mu' exclusively}}
349 x = *pgb_field; // expected-warning {{reading variable 'pgb_field' requires locking 'sls_mu2'}} \
350 // expected-warning {{reading the value pointed to by 'pgb_field' requires locking 'sls_mu'}}
351 (*pgb_field)++; // expected-warning {{reading variable 'pgb_field' requires locking 'sls_mu2'}} \
352 // expected-warning {{writing the value pointed to by 'pgb_field' requires locking 'sls_mu' exclusively}}
Caitlin Sadowski05b436e2011-08-29 22:27:51 +0000353 }
354};
355
356class GBFoo {
357 public:
358 int gb_field __attribute__((guarded_by(sls_mu)));
359
360 void testFoo() {
361 gb_field = 0; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000362 // expected-warning {{writing variable 'gb_field' requires locking 'sls_mu' exclusively}}
Caitlin Sadowski05b436e2011-08-29 22:27:51 +0000363 }
Caitlin Sadowskiaf370612011-09-08 18:35:21 +0000364
365 void testNoAnal() __attribute__((no_thread_safety_analysis)) {
366 gb_field = 0;
367 }
Caitlin Sadowski05b436e2011-08-29 22:27:51 +0000368};
369
370GBFoo GlobalGBFoo __attribute__((guarded_by(sls_mu)));
371
372void gb_fun_0() {
373 sls_mu.Lock();
374 int x = *pgb_var;
375 sls_mu.Unlock();
376}
377
378void gb_fun_1() {
379 sls_mu.Lock();
380 *pgb_var = 2;
381 sls_mu.Unlock();
382}
383
384void gb_fun_2() {
385 int x;
386 pgb_var = &x;
387}
388
389void gb_fun_3() {
390 int *x = pgb_var;
391}
392
393void gb_bad_0() {
394 sls_guard_var = 1; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000395 // expected-warning{{writing variable 'sls_guard_var' requires locking any mutex exclusively}}
Caitlin Sadowski05b436e2011-08-29 22:27:51 +0000396}
397
398void gb_bad_1() {
399 int x = sls_guard_var; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000400 // expected-warning{{reading variable 'sls_guard_var' requires locking any mutex}}
Caitlin Sadowski05b436e2011-08-29 22:27:51 +0000401}
402
403void gb_bad_2() {
404 sls_guardby_var = 1; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000405 // expected-warning {{writing variable 'sls_guardby_var' requires locking 'sls_mu' exclusively}}
Caitlin Sadowski05b436e2011-08-29 22:27:51 +0000406}
407
408void gb_bad_3() {
409 int x = sls_guardby_var; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000410 // expected-warning {{reading variable 'sls_guardby_var' requires locking 'sls_mu'}}
Caitlin Sadowski05b436e2011-08-29 22:27:51 +0000411}
412
413void gb_bad_4() {
414 *pgb_gvar = 1; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000415 // expected-warning {{writing the value pointed to by 'pgb_gvar' requires locking any mutex exclusively}}
Caitlin Sadowski05b436e2011-08-29 22:27:51 +0000416}
417
418void gb_bad_5() {
419 int x = *pgb_gvar; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000420 // expected-warning {{reading the value pointed to by 'pgb_gvar' requires locking any mutex}}
Caitlin Sadowski05b436e2011-08-29 22:27:51 +0000421}
422
423void gb_bad_6() {
424 *pgb_var = 1; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000425 // expected-warning {{writing the value pointed to by 'pgb_var' requires locking 'sls_mu' exclusively}}
Caitlin Sadowski05b436e2011-08-29 22:27:51 +0000426}
427
428void gb_bad_7() {
429 int x = *pgb_var; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000430 // expected-warning {{reading the value pointed to by 'pgb_var' requires locking 'sls_mu'}}
Caitlin Sadowski05b436e2011-08-29 22:27:51 +0000431}
432
433void gb_bad_8() {
434 GBFoo G;
435 G.gb_field = 0; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000436 // expected-warning {{writing variable 'gb_field' requires locking 'sls_mu'}}
Caitlin Sadowski05b436e2011-08-29 22:27:51 +0000437}
438
439void gb_bad_9() {
440 sls_guard_var++; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000441 // expected-warning{{writing variable 'sls_guard_var' requires locking any mutex exclusively}}
Caitlin Sadowski05b436e2011-08-29 22:27:51 +0000442 sls_guard_var--; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000443 // expected-warning{{writing variable 'sls_guard_var' requires locking any mutex exclusively}}
Caitlin Sadowski05b436e2011-08-29 22:27:51 +0000444 ++sls_guard_var; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000445 // expected-warning{{writing variable 'sls_guard_var' requires locking any mutex exclusively}}
Caitlin Sadowskia49d1d82011-09-09 16:07:55 +0000446 --sls_guard_var;// \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000447 // expected-warning{{writing variable 'sls_guard_var' requires locking any mutex exclusively}}
Caitlin Sadowski05b436e2011-08-29 22:27:51 +0000448}
Caitlin Sadowskib4d0a962011-08-29 17:12:27 +0000449
Caitlin Sadowskieff98fc2011-09-08 17:42:22 +0000450//-----------------------------------------------//
451// Warnings on variables with late parsed attributes
452// ----------------------------------------------//
453
454class LateFoo {
455public:
456 int a __attribute__((guarded_by(mu)));
457 int b;
458
459 void foo() __attribute__((exclusive_locks_required(mu))) { }
460
461 void test() {
462 a = 0; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000463 // expected-warning{{writing variable 'a' requires locking 'mu' exclusively}}
Caitlin Sadowskieff98fc2011-09-08 17:42:22 +0000464 b = a; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000465 // expected-warning {{reading variable 'a' requires locking 'mu'}}
Caitlin Sadowskieff98fc2011-09-08 17:42:22 +0000466 c = 0; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000467 // expected-warning {{writing variable 'c' requires locking 'mu' exclusively}}
Caitlin Sadowskieff98fc2011-09-08 17:42:22 +0000468 }
469
470 int c __attribute__((guarded_by(mu)));
471
472 Mutex mu;
473};
474
Caitlin Sadowski99107eb2011-09-09 16:21:55 +0000475class LateBar {
476 public:
477 int a_ __attribute__((guarded_by(mu1_)));
478 int b_;
479 int *q __attribute__((pt_guarded_by(mu)));
480 Mutex mu1_;
481 Mutex mu;
482 LateFoo Foo;
483 LateFoo Foo2;
484 LateFoo *FooPointer;
485};
486
487LateBar b1, *b3;
488
489void late_0() {
490 LateFoo FooA;
491 LateFoo FooB;
492 FooA.mu.Lock();
493 FooA.a = 5;
494 FooA.mu.Unlock();
495}
496
497void late_1() {
498 LateBar BarA;
499 BarA.FooPointer->mu.Lock();
500 BarA.FooPointer->a = 2;
501 BarA.FooPointer->mu.Unlock();
502}
503
504void late_bad_0() {
505 LateFoo fooA;
506 LateFoo fooB;
507 fooA.mu.Lock();
508 fooB.a = 5; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000509 // expected-warning{{writing variable 'a' requires locking 'mu' exclusively}}
Caitlin Sadowski99107eb2011-09-09 16:21:55 +0000510 fooA.mu.Unlock();
511}
512
513void late_bad_1() {
514 Mutex mu;
515 mu.Lock();
516 b1.mu1_.Lock();
517 int res = b1.a_ + b3->b_;
518 b3->b_ = *b1.q; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000519 // expected-warning{{reading the value pointed to by 'q' requires locking 'mu'}}
Caitlin Sadowski99107eb2011-09-09 16:21:55 +0000520 b1.mu1_.Unlock();
521 b1.b_ = res;
522 mu.Unlock();
523}
524
525void late_bad_2() {
526 LateBar BarA;
527 BarA.FooPointer->mu.Lock();
528 BarA.Foo.a = 2; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000529 // expected-warning{{writing variable 'a' requires locking 'mu' exclusively}}
Caitlin Sadowski99107eb2011-09-09 16:21:55 +0000530 BarA.FooPointer->mu.Unlock();
531}
532
533void late_bad_3() {
534 LateBar BarA;
535 BarA.Foo.mu.Lock();
536 BarA.FooPointer->a = 2; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000537 // expected-warning{{writing variable 'a' requires locking 'mu' exclusively}}
Caitlin Sadowski99107eb2011-09-09 16:21:55 +0000538 BarA.Foo.mu.Unlock();
539}
540
541void late_bad_4() {
542 LateBar BarA;
543 BarA.Foo.mu.Lock();
544 BarA.Foo2.a = 2; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000545 // expected-warning{{writing variable 'a' requires locking 'mu' exclusively}}
Caitlin Sadowski99107eb2011-09-09 16:21:55 +0000546 BarA.Foo.mu.Unlock();
547}
548
Caitlin Sadowskia53257c2011-09-08 18:19:38 +0000549//-----------------------------------------------//
550// Extra warnings for shared vs. exclusive locks
551// ----------------------------------------------//
552
553void shared_fun_0() {
554 sls_mu.Lock();
555 do {
556 sls_mu.Unlock();
557 sls_mu.Lock();
558 } while (getBool());
559 sls_mu.Unlock();
560}
561
562void shared_fun_1() {
Caitlin Sadowski4e4bc752011-09-15 17:25:19 +0000563 sls_mu.ReaderLock(); // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000564 // expected-warning {{mutex 'sls_mu' is locked exclusively and shared in the same scope}}
Caitlin Sadowskia53257c2011-09-08 18:19:38 +0000565 do {
566 sls_mu.Unlock();
Caitlin Sadowski4e4bc752011-09-15 17:25:19 +0000567 sls_mu.Lock(); // \
568 // expected-note {{the other lock of mutex 'sls_mu' is here}}
Caitlin Sadowskia53257c2011-09-08 18:19:38 +0000569 } while (getBool());
570 sls_mu.Unlock();
571}
572
573void shared_fun_3() {
574 if (getBool())
575 sls_mu.Lock();
576 else
577 sls_mu.Lock();
578 *pgb_var = 1;
579 sls_mu.Unlock();
580}
581
582void shared_fun_4() {
583 if (getBool())
584 sls_mu.ReaderLock();
585 else
586 sls_mu.ReaderLock();
587 int x = sls_guardby_var;
588 sls_mu.Unlock();
589}
590
591void shared_fun_8() {
592 if (getBool())
593 sls_mu.Lock(); // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000594 // expected-warning {{mutex 'sls_mu' is locked exclusively and shared in the same scope}}
Caitlin Sadowskia53257c2011-09-08 18:19:38 +0000595 else
596 sls_mu.ReaderLock(); // \
Caitlin Sadowski8bccabe2011-09-08 21:52:50 +0000597 // expected-note {{the other lock of mutex 'sls_mu' is here}}
Caitlin Sadowskia53257c2011-09-08 18:19:38 +0000598 sls_mu.Unlock();
599}
600
601void shared_bad_0() {
Caitlin Sadowski4e4bc752011-09-15 17:25:19 +0000602 sls_mu.Lock(); // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000603 // expected-warning {{mutex 'sls_mu' is locked exclusively and shared in the same scope}}
Caitlin Sadowskia53257c2011-09-08 18:19:38 +0000604 do {
605 sls_mu.Unlock();
Caitlin Sadowski4e4bc752011-09-15 17:25:19 +0000606 sls_mu.ReaderLock(); // \
607 // expected-note {{the other lock of mutex 'sls_mu' is here}}
Caitlin Sadowskia53257c2011-09-08 18:19:38 +0000608 } while (getBool());
609 sls_mu.Unlock();
610}
611
612void shared_bad_1() {
613 if (getBool())
614 sls_mu.Lock(); // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000615 // expected-warning {{mutex 'sls_mu' is locked exclusively and shared in the same scope}}
Caitlin Sadowskia53257c2011-09-08 18:19:38 +0000616 else
617 sls_mu.ReaderLock(); // \
Caitlin Sadowski8bccabe2011-09-08 21:52:50 +0000618 // expected-note {{the other lock of mutex 'sls_mu' is here}}
Caitlin Sadowskia53257c2011-09-08 18:19:38 +0000619 *pgb_var = 1;
620 sls_mu.Unlock();
621}
622
623void shared_bad_2() {
624 if (getBool())
625 sls_mu.ReaderLock(); // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000626 // expected-warning {{mutex 'sls_mu' is locked exclusively and shared in the same scope}}
Caitlin Sadowskia53257c2011-09-08 18:19:38 +0000627 else
628 sls_mu.Lock(); // \
Caitlin Sadowski8bccabe2011-09-08 21:52:50 +0000629 // expected-note {{the other lock of mutex 'sls_mu' is here}}
Caitlin Sadowskia53257c2011-09-08 18:19:38 +0000630 *pgb_var = 1;
631 sls_mu.Unlock();
632}
Caitlin Sadowski978191e2011-09-08 18:27:31 +0000633
634// FIXME: Add support for functions (not only methods)
635class LRBar {
636 public:
637 void aa_elr_fun() __attribute__((exclusive_locks_required(aa_mu)));
638 void aa_elr_fun_s() __attribute__((shared_locks_required(aa_mu)));
639 void le_fun() __attribute__((locks_excluded(sls_mu)));
640};
641
642class LRFoo {
643 public:
644 void test() __attribute__((exclusive_locks_required(sls_mu)));
645 void testShared() __attribute__((shared_locks_required(sls_mu2)));
646};
647
648void elr_fun() __attribute__((exclusive_locks_required(sls_mu)));
649void elr_fun() {}
650
651LRFoo MyLRFoo;
652LRBar Bar;
653
654void es_fun_0() {
655 aa_mu.Lock();
656 Bar.aa_elr_fun();
657 aa_mu.Unlock();
658}
659
660void es_fun_1() {
661 aa_mu.Lock();
662 Bar.aa_elr_fun_s();
663 aa_mu.Unlock();
664}
665
666void es_fun_2() {
667 aa_mu.ReaderLock();
668 Bar.aa_elr_fun_s();
669 aa_mu.Unlock();
670}
671
672void es_fun_3() {
673 sls_mu.Lock();
674 MyLRFoo.test();
675 sls_mu.Unlock();
676}
677
678void es_fun_4() {
679 sls_mu2.Lock();
680 MyLRFoo.testShared();
681 sls_mu2.Unlock();
682}
683
684void es_fun_5() {
685 sls_mu2.ReaderLock();
686 MyLRFoo.testShared();
687 sls_mu2.Unlock();
688}
689
690void es_fun_6() {
691 Bar.le_fun();
692}
693
694void es_fun_7() {
695 sls_mu.Lock();
696 elr_fun();
697 sls_mu.Unlock();
698}
699
Caitlin Sadowskiaf370612011-09-08 18:35:21 +0000700void es_fun_8() __attribute__((no_thread_safety_analysis));
701
702void es_fun_8() {
703 Bar.aa_elr_fun_s();
704}
705
Caitlin Sadowskicb967512011-09-15 17:43:08 +0000706void es_fun_9() __attribute__((shared_locks_required(aa_mu)));
707void es_fun_9() {
708 Bar.aa_elr_fun_s();
709}
710
711void es_fun_10() __attribute__((exclusive_locks_required(aa_mu)));
712void es_fun_10() {
713 Bar.aa_elr_fun_s();
714}
715
Caitlin Sadowski978191e2011-09-08 18:27:31 +0000716void es_bad_0() {
717 Bar.aa_elr_fun(); // \
Caitlin Sadowski8bccabe2011-09-08 21:52:50 +0000718 // expected-warning {{calling function 'aa_elr_fun' requires exclusive lock on 'aa_mu'}}
Caitlin Sadowski978191e2011-09-08 18:27:31 +0000719}
720
721void es_bad_1() {
722 aa_mu.ReaderLock();
723 Bar.aa_elr_fun(); // \
Caitlin Sadowski8bccabe2011-09-08 21:52:50 +0000724 // expected-warning {{calling function 'aa_elr_fun' requires exclusive lock on 'aa_mu'}}
Caitlin Sadowski978191e2011-09-08 18:27:31 +0000725 aa_mu.Unlock();
726}
727
728void es_bad_2() {
729 Bar.aa_elr_fun_s(); // \
Caitlin Sadowski8bccabe2011-09-08 21:52:50 +0000730 // expected-warning {{calling function 'aa_elr_fun_s' requires shared lock on 'aa_mu'}}
Caitlin Sadowski978191e2011-09-08 18:27:31 +0000731}
732
733void es_bad_3() {
734 MyLRFoo.test(); // \
Caitlin Sadowski8bccabe2011-09-08 21:52:50 +0000735 // expected-warning {{calling function 'test' requires exclusive lock on 'sls_mu'}}
Caitlin Sadowski978191e2011-09-08 18:27:31 +0000736}
737
738void es_bad_4() {
739 MyLRFoo.testShared(); // \
Caitlin Sadowski8bccabe2011-09-08 21:52:50 +0000740 // expected-warning {{calling function 'testShared' requires shared lock on 'sls_mu2'}}
Caitlin Sadowski978191e2011-09-08 18:27:31 +0000741}
742
743void es_bad_5() {
744 sls_mu.ReaderLock();
745 MyLRFoo.test(); // \
Caitlin Sadowski8bccabe2011-09-08 21:52:50 +0000746 // expected-warning {{calling function 'test' requires exclusive lock on 'sls_mu'}}
Caitlin Sadowski978191e2011-09-08 18:27:31 +0000747 sls_mu.Unlock();
748}
749
750void es_bad_6() {
751 sls_mu.Lock();
752 Bar.le_fun(); // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000753 // expected-warning {{cannot call function 'le_fun' while mutex 'sls_mu' is locked}}
Caitlin Sadowski978191e2011-09-08 18:27:31 +0000754 sls_mu.Unlock();
755}
756
757void es_bad_7() {
758 sls_mu.ReaderLock();
759 Bar.le_fun(); // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000760 // expected-warning {{cannot call function 'le_fun' while mutex 'sls_mu' is locked}}
Caitlin Sadowski978191e2011-09-08 18:27:31 +0000761 sls_mu.Unlock();
762}
Caitlin Sadowski194418f2011-09-14 20:00:24 +0000763
DeLesley Hutchins81216392011-10-17 21:38:02 +0000764
Caitlin Sadowski194418f2011-09-14 20:00:24 +0000765//-----------------------------------------------//
766// Unparseable lock expressions
767// ----------------------------------------------//
768
769Mutex UPmu;
770// FIXME: add support for lock expressions involving arrays.
771Mutex mua[5];
772
DeLesley Hutchinsf1ac6372011-10-21 18:10:14 +0000773int x __attribute__((guarded_by(UPmu = sls_mu)));
774int y __attribute__((guarded_by(mua[0])));
Caitlin Sadowski194418f2011-09-14 20:00:24 +0000775
776
777void testUnparse() {
DeLesley Hutchinsf1ac6372011-10-21 18:10:14 +0000778 x = 5; // \
779 // expected-warning{{cannot resolve lock expression}}
780 y = 5; // \
781 // expected-warning{{cannot resolve lock expression}}
Caitlin Sadowski194418f2011-09-14 20:00:24 +0000782}
783
784void testUnparse2() {
785 mua[0].Lock(); // \
DeLesley Hutchinsf1ac6372011-10-21 18:10:14 +0000786 // expected-warning{{cannot resolve lock expression}}
Caitlin Sadowski194418f2011-09-14 20:00:24 +0000787 (&(mua[0]) + 4)->Lock(); // \
DeLesley Hutchinsf1ac6372011-10-21 18:10:14 +0000788 // expected-warning{{cannot resolve lock expression}}
Caitlin Sadowski194418f2011-09-14 20:00:24 +0000789}
790
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +0000791
792//----------------------------------------------------------------------------//
793// The following test cases are ported from the gcc thread safety implementation
794// They are each wrapped inside a namespace with the test number of the gcc test
795//
796// FIXME: add all the gcc tests, once this analysis passes them.
797//----------------------------------------------------------------------------//
798
799//-----------------------------------------//
800// Good testcases (no errors)
801//-----------------------------------------//
802
803namespace thread_annot_lock_20 {
804class Bar {
805 public:
806 static int func1() EXCLUSIVE_LOCKS_REQUIRED(mu1_);
807 static int b_ GUARDED_BY(mu1_);
808 static Mutex mu1_;
809 static int a_ GUARDED_BY(mu1_);
810};
811
812Bar b1;
813
814int Bar::func1()
815{
816 int res = 5;
817
818 if (a_ == 4)
819 res = b_;
820 return res;
821}
822} // end namespace thread_annot_lock_20
823
824namespace thread_annot_lock_22 {
825// Test various usage of GUARDED_BY and PT_GUARDED_BY annotations, especially
826// uses in class definitions.
827Mutex mu;
828
829class Bar {
830 public:
831 int a_ GUARDED_BY(mu1_);
832 int b_;
833 int *q PT_GUARDED_BY(mu);
834 Mutex mu1_ ACQUIRED_AFTER(mu);
835};
836
837Bar b1, *b3;
838int *p GUARDED_BY(mu) PT_GUARDED_BY(mu);
839int res GUARDED_BY(mu) = 5;
840
841int func(int i)
842{
843 int x;
844 mu.Lock();
845 b1.mu1_.Lock();
846 res = b1.a_ + b3->b_;
847 *p = i;
848 b1.a_ = res + b3->b_;
849 b3->b_ = *b1.q;
850 b1.mu1_.Unlock();
851 b1.b_ = res;
852 x = res;
853 mu.Unlock();
854 return x;
855}
856} // end namespace thread_annot_lock_22
857
858namespace thread_annot_lock_27_modified {
859// test lock annotations applied to function definitions
860// Modified: applied annotations only to function declarations
861Mutex mu1;
862Mutex mu2 ACQUIRED_AFTER(mu1);
863
864class Foo {
865 public:
866 int method1(int i) SHARED_LOCKS_REQUIRED(mu2) EXCLUSIVE_LOCKS_REQUIRED(mu1);
867};
868
869int Foo::method1(int i) {
870 return i;
871}
872
873
874int foo(int i) EXCLUSIVE_LOCKS_REQUIRED(mu2) SHARED_LOCKS_REQUIRED(mu1);
875int foo(int i) {
876 return i;
877}
878
879static int bar(int i) EXCLUSIVE_LOCKS_REQUIRED(mu1);
880static int bar(int i) {
881 return i;
882}
883
884void main() {
885 Foo a;
886
887 mu1.Lock();
888 mu2.Lock();
889 a.method1(1);
890 foo(2);
891 mu2.Unlock();
892 bar(3);
893 mu1.Unlock();
894}
895} // end namespace thread_annot_lock_27_modified
896
897
898namespace thread_annot_lock_38 {
899// Test the case where a template member function is annotated with lock
900// attributes in a non-template class.
901class Foo {
902 public:
903 void func1(int y) LOCKS_EXCLUDED(mu_);
904 template <typename T> void func2(T x) LOCKS_EXCLUDED(mu_);
905 private:
906 Mutex mu_;
907};
908
909Foo *foo;
910
911void main()
912{
913 foo->func1(5);
914 foo->func2(5);
915}
916} // end namespace thread_annot_lock_38
917
918namespace thread_annot_lock_43 {
919// Tests lock canonicalization
920class Foo {
921 public:
922 Mutex *mu_;
923};
924
925class FooBar {
926 public:
927 Foo *foo_;
928 int GetA() EXCLUSIVE_LOCKS_REQUIRED(foo_->mu_) { return a_; }
929 int a_ GUARDED_BY(foo_->mu_);
930};
931
932FooBar *fb;
933
934void main()
935{
936 int x;
937 fb->foo_->mu_->Lock();
938 x = fb->GetA();
939 fb->foo_->mu_->Unlock();
940}
941} // end namespace thread_annot_lock_43
942
943namespace thread_annot_lock_49 {
944// Test the support for use of lock expression in the annotations
945class Foo {
946 public:
947 Mutex foo_mu_;
948};
949
950class Bar {
951 private:
952 Foo *foo;
953 Mutex bar_mu_ ACQUIRED_AFTER(foo->foo_mu_);
954
955 public:
956 void Test1() {
957 foo->foo_mu_.Lock();
958 bar_mu_.Lock();
959 bar_mu_.Unlock();
960 foo->foo_mu_.Unlock();
961 }
962};
963
964void main() {
965 Bar bar;
966 bar.Test1();
967}
968} // end namespace thread_annot_lock_49
969
970namespace thread_annot_lock_61_modified {
971 // Modified to fix the compiler errors
972 // Test the fix for a bug introduced by the support of pass-by-reference
973 // paramters.
974 struct Foo { Foo &operator<< (bool) {return *this;} };
975 Foo &getFoo();
976 struct Bar { Foo &func () {return getFoo();} };
977 struct Bas { void operator& (Foo &) {} };
978 void mumble()
979 {
980 Bas() & Bar().func() << "" << "";
981 Bas() & Bar().func() << "";
982 }
983} // end namespace thread_annot_lock_61_modified
984
985
986namespace thread_annot_lock_65 {
987// Test the fix for a bug in the support of allowing reader locks for
988// non-const, non-modifying overload functions. (We didn't handle the builtin
989// properly.)
990enum MyFlags {
991 Zero,
992 One,
993 Two,
994 Three,
995 Four,
996 Five,
997 Six,
998 Seven,
999 Eight,
1000 Nine
1001};
1002
1003inline MyFlags
1004operator|(MyFlags a, MyFlags b)
1005{
1006 return MyFlags(static_cast<int>(a) | static_cast<int>(b));
1007}
1008
1009inline MyFlags&
1010operator|=(MyFlags& a, MyFlags b)
1011{
1012 return a = a | b;
1013}
1014} // end namespace thread_annot_lock_65
1015
1016namespace thread_annot_lock_66_modified {
1017// Modified: Moved annotation to function defn
1018// Test annotations on out-of-line definitions of member functions where the
1019// annotations refer to locks that are also data members in the class.
1020Mutex mu;
1021
1022class Foo {
1023 public:
1024 int method1(int i) SHARED_LOCKS_REQUIRED(mu1, mu, mu2);
1025 int data GUARDED_BY(mu1);
1026 Mutex *mu1;
1027 Mutex *mu2;
1028};
1029
1030int Foo::method1(int i)
1031{
1032 return data + i;
1033}
1034
1035void main()
1036{
1037 Foo a;
1038
1039 a.mu2->Lock();
1040 a.mu1->Lock();
1041 mu.Lock();
1042 a.method1(1);
1043 mu.Unlock();
1044 a.mu1->Unlock();
1045 a.mu2->Unlock();
1046}
1047} // end namespace thread_annot_lock_66_modified
1048
1049namespace thread_annot_lock_68_modified {
1050// Test a fix to a bug in the delayed name binding with nested template
1051// instantiation. We use a stack to make sure a name is not resolved to an
1052// inner context.
1053template <typename T>
1054class Bar {
1055 Mutex mu_;
1056};
1057
1058template <typename T>
1059class Foo {
1060 public:
1061 void func(T x) {
1062 mu_.Lock();
DeLesley Hutchins23323e02012-01-20 22:50:54 +00001063 count_ = x;
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001064 mu_.Unlock();
1065 }
1066
1067 private:
DeLesley Hutchins23323e02012-01-20 22:50:54 +00001068 T count_ GUARDED_BY(mu_);
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001069 Bar<T> bar_;
1070 Mutex mu_;
1071};
1072
1073void main()
1074{
1075 Foo<int> *foo;
1076 foo->func(5);
1077}
1078} // end namespace thread_annot_lock_68_modified
1079
1080namespace thread_annot_lock_30_modified {
1081// Test delay parsing of lock attribute arguments with nested classes.
1082// Modified: trylocks replaced with exclusive_lock_fun
1083int a = 0;
1084
1085class Bar {
1086 struct Foo;
1087
1088 public:
1089 void MyLock() EXCLUSIVE_LOCK_FUNCTION(mu);
1090
1091 int func() {
1092 MyLock();
1093// if (foo == 0) {
1094// return 0;
1095// }
1096 a = 5;
1097 mu.Unlock();
1098 return 1;
1099 }
1100
1101 class FooBar {
1102 int x;
1103 int y;
1104 };
1105
1106 private:
1107 Mutex mu;
1108};
1109
1110Bar *bar;
1111
1112void main()
1113{
1114 bar->func();
1115}
1116} // end namespace thread_annot_lock_30_modified
1117
1118namespace thread_annot_lock_47 {
1119// Test the support for annotations on virtual functions.
1120// This is a good test case. (i.e. There should be no warning emitted by the
1121// compiler.)
1122class Base {
1123 public:
1124 virtual void func1() EXCLUSIVE_LOCKS_REQUIRED(mu_);
1125 virtual void func2() LOCKS_EXCLUDED(mu_);
1126 Mutex mu_;
1127};
1128
1129class Child : public Base {
1130 public:
1131 virtual void func1() EXCLUSIVE_LOCKS_REQUIRED(mu_);
1132 virtual void func2() LOCKS_EXCLUDED(mu_);
1133};
1134
1135void main() {
1136 Child *c;
1137 Base *b = c;
1138
1139 b->mu_.Lock();
1140 b->func1();
1141 b->mu_.Unlock();
1142 b->func2();
1143
1144 c->mu_.Lock();
1145 c->func1();
1146 c->mu_.Unlock();
1147 c->func2();
1148}
1149} // end namespace thread_annot_lock_47
1150
1151//-----------------------------------------//
1152// Tests which produce errors
1153//-----------------------------------------//
1154
1155namespace thread_annot_lock_13 {
1156Mutex mu1;
1157Mutex mu2;
1158
1159int g GUARDED_BY(mu1);
1160int w GUARDED_BY(mu2);
1161
1162class Foo {
1163 public:
1164 void bar() LOCKS_EXCLUDED(mu_, mu1);
1165 int foo() SHARED_LOCKS_REQUIRED(mu_) EXCLUSIVE_LOCKS_REQUIRED(mu2);
1166
1167 private:
1168 int a_ GUARDED_BY(mu_);
1169 public:
1170 Mutex mu_ ACQUIRED_AFTER(mu1);
1171};
1172
1173int Foo::foo()
1174{
1175 int res;
1176 w = 5.2;
1177 res = a_ + 5;
1178 return res;
1179}
1180
1181void Foo::bar()
1182{
1183 int x;
1184 mu_.Lock();
1185 x = foo(); // expected-warning {{calling function 'foo' requires exclusive lock on 'mu2'}}
1186 a_ = x + 1;
1187 mu_.Unlock();
1188 if (x > 5) {
1189 mu1.Lock();
1190 g = 2.3;
1191 mu1.Unlock();
1192 }
1193}
1194
1195void main()
1196{
1197 Foo f1, *f2;
1198 f1.mu_.Lock();
Caitlin Sadowski74558b42011-09-15 18:13:32 +00001199 f1.bar(); // expected-warning {{cannot call function 'bar' while mutex 'mu_' is locked}}
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001200 mu2.Lock();
1201 f1.foo();
1202 mu2.Unlock();
1203 f1.mu_.Unlock();
1204 f2->mu_.Lock();
Caitlin Sadowski74558b42011-09-15 18:13:32 +00001205 f2->bar(); // expected-warning {{cannot call function 'bar' while mutex 'mu_' is locked}}
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001206 f2->mu_.Unlock();
1207 mu2.Lock();
1208 w = 2.5;
1209 mu2.Unlock();
1210}
1211} // end namespace thread_annot_lock_13
1212
1213namespace thread_annot_lock_18_modified {
1214// Modified: Trylocks removed
1215// Test the ability to distnguish between the same lock field of
1216// different objects of a class.
1217 class Bar {
1218 public:
1219 bool MyLock() EXCLUSIVE_LOCK_FUNCTION(mu1_);
1220 void MyUnlock() UNLOCK_FUNCTION(mu1_);
1221 int a_ GUARDED_BY(mu1_);
1222
1223 private:
1224 Mutex mu1_;
1225};
1226
1227Bar *b1, *b2;
1228
1229void func()
1230{
1231 b1->MyLock();
1232 b1->a_ = 5;
Caitlin Sadowski74558b42011-09-15 18:13:32 +00001233 b2->a_ = 3; // expected-warning {{writing variable 'a_' requires locking 'mu1_' exclusively}}
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001234 b2->MyLock();
1235 b2->MyUnlock();
1236 b1->MyUnlock();
1237}
1238} // end namespace thread_annot_lock_18_modified
1239
1240namespace thread_annot_lock_21 {
1241// Test various usage of GUARDED_BY and PT_GUARDED_BY annotations, especially
1242// uses in class definitions.
1243Mutex mu;
1244
1245class Bar {
1246 public:
1247 int a_ GUARDED_BY(mu1_);
1248 int b_;
1249 int *q PT_GUARDED_BY(mu);
1250 Mutex mu1_ ACQUIRED_AFTER(mu);
1251};
1252
1253Bar b1, *b3;
1254int *p GUARDED_BY(mu) PT_GUARDED_BY(mu);
1255
1256int res GUARDED_BY(mu) = 5;
1257
1258int func(int i)
1259{
1260 int x;
1261 b3->mu1_.Lock();
Caitlin Sadowski74558b42011-09-15 18:13:32 +00001262 res = b1.a_ + b3->b_; // expected-warning {{reading variable 'a_' requires locking 'mu1_'}} \
1263 // expected-warning {{writing variable 'res' requires locking 'mu' exclusively}}
1264 *p = i; // expected-warning {{reading variable 'p' requires locking 'mu'}} \
1265 // expected-warning {{writing the value pointed to by 'p' requires locking 'mu' exclusively}}
1266 b1.a_ = res + b3->b_; // expected-warning {{reading variable 'res' requires locking 'mu'}} \
1267 // expected-warning {{writing variable 'a_' requires locking 'mu1_' exclusively}}
1268 b3->b_ = *b1.q; // expected-warning {{reading the value pointed to by 'q' requires locking 'mu'}}
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001269 b3->mu1_.Unlock();
Caitlin Sadowski74558b42011-09-15 18:13:32 +00001270 b1.b_ = res; // expected-warning {{reading variable 'res' requires locking 'mu'}}
1271 x = res; // expected-warning {{reading variable 'res' requires locking 'mu'}}
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001272 return x;
1273}
1274} // end namespace thread_annot_lock_21
1275
1276namespace thread_annot_lock_35_modified {
1277// Test the analyzer's ability to distinguish the lock field of different
1278// objects.
1279class Foo {
1280 private:
1281 Mutex lock_;
1282 int a_ GUARDED_BY(lock_);
1283
1284 public:
1285 void Func(Foo* child) LOCKS_EXCLUDED(lock_) {
1286 Foo *new_foo = new Foo;
1287
1288 lock_.Lock();
1289
1290 child->Func(new_foo); // There shouldn't be any warning here as the
1291 // acquired lock is not in child.
1292 child->bar(7); // expected-warning {{calling function 'bar' requires exclusive lock on 'lock_'}}
Caitlin Sadowski74558b42011-09-15 18:13:32 +00001293 child->a_ = 5; // expected-warning {{writing variable 'a_' requires locking 'lock_' exclusively}}
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001294 lock_.Unlock();
1295 }
1296
1297 void bar(int y) EXCLUSIVE_LOCKS_REQUIRED(lock_) {
1298 a_ = y;
1299 }
1300};
1301
1302Foo *x;
1303
1304void main() {
1305 Foo *child = new Foo;
1306 x->Func(child);
1307}
1308} // end namespace thread_annot_lock_35_modified
1309
1310namespace thread_annot_lock_36_modified {
1311// Modified to move the annotations to function defns.
1312// Test the analyzer's ability to distinguish the lock field of different
1313// objects
1314class Foo {
1315 private:
1316 Mutex lock_;
1317 int a_ GUARDED_BY(lock_);
1318
1319 public:
1320 void Func(Foo* child) LOCKS_EXCLUDED(lock_);
1321 void bar(int y) EXCLUSIVE_LOCKS_REQUIRED(lock_);
1322};
1323
1324void Foo::Func(Foo* child) {
1325 Foo *new_foo = new Foo;
1326
1327 lock_.Lock();
1328
1329 child->lock_.Lock();
Caitlin Sadowski74558b42011-09-15 18:13:32 +00001330 child->Func(new_foo); // expected-warning {{cannot call function 'Func' while mutex 'lock_' is locked}}
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001331 child->bar(7);
1332 child->a_ = 5;
1333 child->lock_.Unlock();
1334
1335 lock_.Unlock();
1336}
1337
1338void Foo::bar(int y) {
1339 a_ = y;
1340}
1341
1342
1343Foo *x;
1344
1345void main() {
1346 Foo *child = new Foo;
1347 x->Func(child);
1348}
1349} // end namespace thread_annot_lock_36_modified
1350
1351
1352namespace thread_annot_lock_42 {
1353// Test support of multiple lock attributes of the same kind on a decl.
1354class Foo {
1355 private:
1356 Mutex mu1, mu2, mu3;
1357 int x GUARDED_BY(mu1) GUARDED_BY(mu2);
1358 int y GUARDED_BY(mu2);
1359
1360 void f2() LOCKS_EXCLUDED(mu1) LOCKS_EXCLUDED(mu2) LOCKS_EXCLUDED(mu3) {
1361 mu2.Lock();
1362 y = 2;
1363 mu2.Unlock();
1364 }
1365
1366 public:
1367 void f1() EXCLUSIVE_LOCKS_REQUIRED(mu2) EXCLUSIVE_LOCKS_REQUIRED(mu1) {
1368 x = 5;
Caitlin Sadowski74558b42011-09-15 18:13:32 +00001369 f2(); // expected-warning {{cannot call function 'f2' while mutex 'mu1' is locked}} \
1370 // expected-warning {{cannot call function 'f2' while mutex 'mu2' is locked}}
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001371 }
1372};
1373
1374Foo *foo;
1375
1376void func()
1377{
1378 foo->f1(); // expected-warning {{calling function 'f1' requires exclusive lock on 'mu2'}} \
1379 // expected-warning {{calling function 'f1' requires exclusive lock on 'mu1'}}
1380}
1381} // end namespace thread_annot_lock_42
1382
1383namespace thread_annot_lock_46 {
1384// Test the support for annotations on virtual functions.
1385class Base {
1386 public:
1387 virtual void func1() EXCLUSIVE_LOCKS_REQUIRED(mu_);
1388 virtual void func2() LOCKS_EXCLUDED(mu_);
1389 Mutex mu_;
1390};
1391
1392class Child : public Base {
1393 public:
1394 virtual void func1() EXCLUSIVE_LOCKS_REQUIRED(mu_);
1395 virtual void func2() LOCKS_EXCLUDED(mu_);
1396};
1397
1398void main() {
1399 Child *c;
1400 Base *b = c;
1401
1402 b->func1(); // expected-warning {{calling function 'func1' requires exclusive lock on 'mu_'}}
1403 b->mu_.Lock();
Caitlin Sadowski74558b42011-09-15 18:13:32 +00001404 b->func2(); // expected-warning {{cannot call function 'func2' while mutex 'mu_' is locked}}
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001405 b->mu_.Unlock();
1406
1407 c->func1(); // expected-warning {{calling function 'func1' requires exclusive lock on 'mu_'}}
1408 c->mu_.Lock();
Caitlin Sadowski74558b42011-09-15 18:13:32 +00001409 c->func2(); // expected-warning {{cannot call function 'func2' while mutex 'mu_' is locked}}
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001410 c->mu_.Unlock();
1411}
1412} // end namespace thread_annot_lock_46
1413
1414namespace thread_annot_lock_67_modified {
1415// Modified: attributes on definitions moved to declarations
1416// Test annotations on out-of-line definitions of member functions where the
1417// annotations refer to locks that are also data members in the class.
1418Mutex mu;
1419Mutex mu3;
1420
1421class Foo {
1422 public:
1423 int method1(int i) SHARED_LOCKS_REQUIRED(mu1, mu, mu2, mu3);
1424 int data GUARDED_BY(mu1);
1425 Mutex *mu1;
1426 Mutex *mu2;
1427};
1428
1429int Foo::method1(int i) {
1430 return data + i;
1431}
1432
1433void main()
1434{
1435 Foo a;
1436 a.method1(1); // expected-warning {{calling function 'method1' requires shared lock on 'mu1'}} \
1437 // expected-warning {{calling function 'method1' requires shared lock on 'mu'}} \
1438 // expected-warning {{calling function 'method1' requires shared lock on 'mu2'}} \
1439 // expected-warning {{calling function 'method1' requires shared lock on 'mu3'}}
1440}
1441} // end namespace thread_annot_lock_67_modified
1442
1443
DeLesley Hutchins81216392011-10-17 21:38:02 +00001444namespace substitution_test {
1445 class MyData {
1446 public:
1447 Mutex mu;
1448
1449 void lockData() __attribute__((exclusive_lock_function(mu))) { }
1450 void unlockData() __attribute__((unlock_function(mu))) { }
1451
1452 void doSomething() __attribute__((exclusive_locks_required(mu))) { }
1453 };
1454
1455
1456 class DataLocker {
1457 public:
1458 void lockData (MyData *d) __attribute__((exclusive_lock_function(d->mu))) { }
1459 void unlockData(MyData *d) __attribute__((unlock_function(d->mu))) { }
1460 };
1461
1462
1463 class Foo {
1464 public:
1465 void foo(MyData* d) __attribute__((exclusive_locks_required(d->mu))) { }
1466
1467 void bar1(MyData* d) {
1468 d->lockData();
1469 foo(d);
1470 d->unlockData();
1471 }
1472
1473 void bar2(MyData* d) {
1474 DataLocker dlr;
1475 dlr.lockData(d);
1476 foo(d);
1477 dlr.unlockData(d);
1478 }
1479
1480 void bar3(MyData* d1, MyData* d2) {
1481 DataLocker dlr;
Richard Smith2e515622012-02-03 04:45:26 +00001482 dlr.lockData(d1); // expected-note {{mutex acquired here}}
DeLesley Hutchins81216392011-10-17 21:38:02 +00001483 dlr.unlockData(d2); // \
1484 // expected-warning {{unlocking 'mu' that was not locked}}
Richard Smith2e515622012-02-03 04:45:26 +00001485 } // expected-warning {{mutex 'mu' is still locked at the end of function}}
DeLesley Hutchins81216392011-10-17 21:38:02 +00001486
1487 void bar4(MyData* d1, MyData* d2) {
1488 DataLocker dlr;
1489 dlr.lockData(d1);
1490 foo(d2); // \
1491 // expected-warning {{calling function 'foo' requires exclusive lock on 'mu'}}
1492 dlr.unlockData(d1);
1493 }
1494 };
1495} // end namespace substituation_test
1496
DeLesley Hutchinse0eaa852011-10-21 18:06:53 +00001497
DeLesley Hutchinsf1ac6372011-10-21 18:10:14 +00001498
DeLesley Hutchinse0eaa852011-10-21 18:06:53 +00001499namespace constructor_destructor_tests {
1500 Mutex fooMu;
1501 int myVar GUARDED_BY(fooMu);
1502
1503 class Foo {
1504 public:
1505 Foo() __attribute__((exclusive_lock_function(fooMu))) { }
1506 ~Foo() __attribute__((unlock_function(fooMu))) { }
1507 };
1508
1509 void fooTest() {
DeLesley Hutchins6db51f72011-10-21 20:51:27 +00001510 Foo foo;
DeLesley Hutchinse0eaa852011-10-21 18:06:53 +00001511 myVar = 0;
1512 }
1513}
1514
DeLesley Hutchinsf1ac6372011-10-21 18:10:14 +00001515
1516namespace invalid_lock_expression_test {
1517
1518class LOCKABLE MyLockable {
1519public:
1520 MyLockable() __attribute__((exclusive_lock_function)) { }
DeLesley Hutchins6db51f72011-10-21 20:51:27 +00001521 ~MyLockable() { }
DeLesley Hutchinsf1ac6372011-10-21 18:10:14 +00001522};
1523
1524// create an empty lock expression
1525void foo() {
1526 MyLockable lock; // \
1527 // expected-warning {{cannot resolve lock expression}}
1528}
1529
1530} // end namespace invalid_lock_expression_test
1531
Richard Smith97f9fe02011-10-25 00:41:24 +00001532namespace template_member_test {
DeLesley Hutchinsf1ac6372011-10-21 18:10:14 +00001533
Richard Smith97f9fe02011-10-25 00:41:24 +00001534 struct S { int n; };
1535 struct T {
1536 Mutex m;
1537 S *s GUARDED_BY(this->m);
1538 };
Richard Smitha01c7112011-10-25 06:33:21 +00001539 Mutex m;
1540 struct U {
1541 union {
1542 int n;
1543 };
1544 } *u GUARDED_BY(m);
Richard Smith97f9fe02011-10-25 00:41:24 +00001545
1546 template<typename U>
1547 struct IndirectLock {
1548 int DoNaughtyThings(T *t) {
Richard Smitha01c7112011-10-25 06:33:21 +00001549 u->n = 0; // expected-warning {{reading variable 'u' requires locking 'm'}}
Richard Smith97f9fe02011-10-25 00:41:24 +00001550 return t->s->n; // expected-warning {{reading variable 's' requires locking 'm'}}
1551 }
1552 };
1553
Richard Smithf11e9232011-10-25 01:05:41 +00001554 template struct IndirectLock<int>; // expected-note {{here}}
Richard Smith97f9fe02011-10-25 00:41:24 +00001555
Richard Smith601d2ee2011-10-26 06:15:36 +00001556 struct V {
1557 void f(int);
1558 void f(double);
1559
1560 Mutex m;
1561 V *p GUARDED_BY(this->m);
1562 };
1563 template<typename U> struct W {
1564 V v;
1565 void f(U u) {
1566 v.p->f(u); // expected-warning {{reading variable 'p' requires locking 'm'}}
1567 }
1568 };
1569 template struct W<int>; // expected-note {{here}}
1570
Richard Smith97f9fe02011-10-25 00:41:24 +00001571}
DeLesley Hutchins1fa3c062011-12-08 20:23:06 +00001572
1573namespace test_scoped_lockable {
1574
1575struct TestScopedLockable {
1576 Mutex mu1;
1577 Mutex mu2;
1578 int a __attribute__((guarded_by(mu1)));
1579 int b __attribute__((guarded_by(mu2)));
1580
1581 bool getBool();
1582
1583 void foo1() {
1584 MutexLock mulock(&mu1);
1585 a = 5;
1586 }
1587
1588 void foo2() {
1589 ReaderMutexLock mulock1(&mu1);
1590 if (getBool()) {
1591 MutexLock mulock2a(&mu2);
1592 b = a + 1;
1593 }
1594 else {
1595 MutexLock mulock2b(&mu2);
1596 b = a + 2;
1597 }
1598 }
1599
1600 void foo3() {
1601 MutexLock mulock_a(&mu1);
1602 MutexLock mulock_b(&mu1); // \
1603 // expected-warning {{locking 'mu1' that is already locked}}
1604 } // expected-warning {{unlocking 'mu1' that was not locked}}
1605
1606 void foo4() {
1607 MutexLock mulock1(&mu1), mulock2(&mu2);
1608 a = b+1;
1609 b = a+1;
1610 }
1611};
1612
1613} // end namespace test_scoped_lockable
1614
1615
DeLesley Hutchinsdf497822011-12-29 00:56:48 +00001616namespace FunctionAttrTest {
1617
1618class Foo {
1619public:
1620 Mutex mu_;
1621 int a GUARDED_BY(mu_);
1622};
1623
1624Foo fooObj;
1625
1626void foo() EXCLUSIVE_LOCKS_REQUIRED(fooObj.mu_);
1627
1628void bar() {
1629 foo(); // expected-warning {{calling function 'foo' requires exclusive lock on 'mu_'}}
1630 fooObj.mu_.Lock();
1631 foo();
1632 fooObj.mu_.Unlock();
1633}
1634
1635}; // end namespace FunctionAttrTest
1636
1637
DeLesley Hutchinsb4fa4182012-01-06 19:16:50 +00001638struct TestTryLock {
1639 Mutex mu;
1640 int a GUARDED_BY(mu);
1641 bool cond;
1642
1643 void foo1() {
1644 if (mu.TryLock()) {
1645 a = 1;
1646 mu.Unlock();
1647 }
1648 }
1649
1650 void foo2() {
1651 if (!mu.TryLock()) return;
1652 a = 2;
1653 mu.Unlock();
1654 }
1655
1656 void foo3() {
1657 bool b = mu.TryLock();
1658 if (b) {
1659 a = 3;
1660 mu.Unlock();
1661 }
1662 }
1663
1664 void foo4() {
1665 bool b = mu.TryLock();
1666 if (!b) return;
1667 a = 4;
1668 mu.Unlock();
1669 }
1670
1671 void foo5() {
1672 while (mu.TryLock()) {
1673 a = a + 1;
1674 mu.Unlock();
1675 }
1676 }
1677
1678 void foo6() {
1679 bool b = mu.TryLock();
1680 b = !b;
1681 if (b) return;
1682 a = 6;
1683 mu.Unlock();
1684 }
1685
1686 void foo7() {
1687 bool b1 = mu.TryLock();
1688 bool b2 = !b1;
1689 bool b3 = !b2;
1690 if (b3) {
1691 a = 7;
1692 mu.Unlock();
1693 }
1694 }
1695
1696 // Test use-def chains: join points
1697 void foo8() {
1698 bool b = mu.TryLock();
1699 bool b2 = b;
1700 if (cond)
1701 b = true;
1702 if (b) { // b should be unknown at this point, becuase of the join point
1703 a = 8; // expected-warning {{writing variable 'a' requires locking 'mu' exclusively}}
1704 }
1705 if (b2) { // b2 should be known at this point.
1706 a = 8;
1707 mu.Unlock();
1708 }
1709 }
1710
1711 // Test use-def-chains: back edges
1712 void foo9() {
1713 bool b = mu.TryLock();
1714
1715 for (int i = 0; i < 10; ++i);
1716
1717 if (b) { // b is still known, because the loop doesn't alter it
1718 a = 9;
1719 mu.Unlock();
1720 }
1721 }
1722
1723 // Test use-def chains: back edges
1724 void foo10() {
1725 bool b = mu.TryLock();
1726
1727 while (cond) {
1728 if (b) { // b should be uknown at this point b/c of the loop
1729 a = 10; // expected-warning {{writing variable 'a' requires locking 'mu' exclusively}}
1730 }
1731 b = !b;
1732 }
1733 }
1734}; // end TestTrylock
1735
1736
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +00001737namespace TestTemplateAttributeInstantiation {
1738
1739class Foo1 {
1740public:
1741 Mutex mu_;
1742 int a GUARDED_BY(mu_);
1743};
1744
1745class Foo2 {
1746public:
1747 int a GUARDED_BY(mu_);
1748 Mutex mu_;
1749};
1750
1751
1752class Bar {
1753public:
1754 // Test non-dependent expressions in attributes on template functions
1755 template <class T>
1756 void barND(Foo1 *foo, T *fooT) EXCLUSIVE_LOCKS_REQUIRED(foo->mu_) {
1757 foo->a = 0;
1758 }
1759
1760 // Test dependent expressions in attributes on template functions
1761 template <class T>
1762 void barD(Foo1 *foo, T *fooT) EXCLUSIVE_LOCKS_REQUIRED(fooT->mu_) {
1763 fooT->a = 0;
1764 }
1765};
1766
1767
1768template <class T>
1769class BarT {
1770public:
1771 Foo1 fooBase;
1772 T fooBaseT;
1773
1774 // Test non-dependent expression in ordinary method on template class
1775 void barND() EXCLUSIVE_LOCKS_REQUIRED(fooBase.mu_) {
1776 fooBase.a = 0;
1777 }
1778
1779 // Test dependent expressions in ordinary methods on template class
1780 void barD() EXCLUSIVE_LOCKS_REQUIRED(fooBaseT.mu_) {
1781 fooBaseT.a = 0;
1782 }
1783
1784 // Test dependent expressions in template method in template class
1785 template <class T2>
1786 void barTD(T2 *fooT) EXCLUSIVE_LOCKS_REQUIRED(fooBaseT.mu_, fooT->mu_) {
1787 fooBaseT.a = 0;
1788 fooT->a = 0;
1789 }
1790};
1791
1792template <class T>
1793class Cell {
1794public:
1795 Mutex mu_;
1796 // Test dependent guarded_by
1797 T data GUARDED_BY(mu_);
1798
DeLesley Hutchins23323e02012-01-20 22:50:54 +00001799 void fooEx() EXCLUSIVE_LOCKS_REQUIRED(mu_) {
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +00001800 data = 0;
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +00001801 }
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +00001802
1803 void foo() {
1804 mu_.Lock();
1805 data = 0;
1806 mu_.Unlock();
1807 }
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +00001808};
1809
1810void test() {
1811 Bar b;
1812 BarT<Foo2> bt;
1813 Foo1 f1;
1814 Foo2 f2;
1815
1816 f1.mu_.Lock();
1817 f2.mu_.Lock();
1818 bt.fooBase.mu_.Lock();
1819 bt.fooBaseT.mu_.Lock();
1820
1821 b.barND(&f1, &f2);
1822 b.barD(&f1, &f2);
1823 bt.barND();
1824 bt.barD();
1825 bt.barTD(&f2);
1826
1827 f1.mu_.Unlock();
1828 bt.barTD(&f1); // \
1829 // expected-warning {{calling function 'barTD' requires exclusive lock on 'mu_'}}
1830
1831 bt.fooBase.mu_.Unlock();
1832 bt.fooBaseT.mu_.Unlock();
1833 f2.mu_.Unlock();
1834
1835 Cell<int> cell;
1836 cell.data = 0; // \
1837 // expected-warning {{writing variable 'data' requires locking 'mu_' exclusively}}
1838 cell.foo();
DeLesley Hutchins23323e02012-01-20 22:50:54 +00001839 cell.mu_.Lock();
1840 cell.fooEx();
1841 cell.mu_.Unlock();
1842}
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +00001843
DeLesley Hutchins23323e02012-01-20 22:50:54 +00001844
1845template <class T>
1846class CellDelayed {
1847public:
1848 // Test dependent guarded_by
1849 T data GUARDED_BY(mu_);
DeLesley Hutchinsdd5756c2012-02-16 17:30:51 +00001850 static T static_data GUARDED_BY(static_mu_);
DeLesley Hutchins23323e02012-01-20 22:50:54 +00001851
1852 void fooEx(CellDelayed<T> *other) EXCLUSIVE_LOCKS_REQUIRED(mu_, other->mu_) {
1853 this->data = other->data;
1854 }
1855
1856 template <class T2>
1857 void fooExT(CellDelayed<T2> *otherT) EXCLUSIVE_LOCKS_REQUIRED(mu_, otherT->mu_) {
1858 this->data = otherT->data;
1859 }
1860
1861 void foo() {
1862 mu_.Lock();
1863 data = 0;
1864 mu_.Unlock();
1865 }
1866
1867 Mutex mu_;
DeLesley Hutchinsdd5756c2012-02-16 17:30:51 +00001868 static Mutex static_mu_;
DeLesley Hutchins23323e02012-01-20 22:50:54 +00001869};
1870
1871void testDelayed() {
1872 CellDelayed<int> celld;
1873 CellDelayed<int> celld2;
1874 celld.foo();
1875 celld.mu_.Lock();
1876 celld2.mu_.Lock();
1877
1878 celld.fooEx(&celld2);
1879 celld.fooExT(&celld2);
1880
1881 celld2.mu_.Unlock();
1882 celld.mu_.Unlock();
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +00001883}
1884
1885}; // end namespace TestTemplateAttributeInstantiation
1886
1887
DeLesley Hutchinse03b2b32012-01-20 23:24:41 +00001888namespace FunctionDeclDefTest {
1889
1890class Foo {
1891public:
1892 Mutex mu_;
1893 int a GUARDED_BY(mu_);
1894
1895 virtual void foo1(Foo *f_declared) EXCLUSIVE_LOCKS_REQUIRED(f_declared->mu_);
1896};
1897
1898// EXCLUSIVE_LOCKS_REQUIRED should be applied, and rewritten to f_defined->mu_
1899void Foo::foo1(Foo *f_defined) {
1900 f_defined->a = 0;
1901};
1902
1903void test() {
1904 Foo myfoo;
1905 myfoo.foo1(&myfoo); // \
1906 // expected-warning {{calling function 'foo1' requires exclusive lock on 'mu_'}}
1907 myfoo.mu_.Lock();
1908 myfoo.foo1(&myfoo);
1909 myfoo.mu_.Unlock();
1910}
1911
1912};
Richard Smith2e515622012-02-03 04:45:26 +00001913
1914namespace GoingNative {
1915
1916 struct __attribute__((lockable)) mutex {
1917 void lock() __attribute__((exclusive_lock_function));
1918 void unlock() __attribute__((unlock_function));
1919 // ...
1920 };
1921 bool foo();
1922 bool bar();
1923 mutex m;
1924 void test() {
1925 m.lock();
1926 while (foo()) {
1927 m.unlock();
1928 // ...
1929 if (bar()) {
1930 // ...
1931 if (foo())
1932 continue; // expected-warning {{expecting mutex 'm' to be locked at start of each loop}}
1933 //...
1934 }
1935 // ...
1936 m.lock(); // expected-note {{mutex acquired here}}
1937 }
1938 m.unlock();
1939 }
1940
1941}
DeLesley Hutchinsc24a2332012-02-16 16:50:43 +00001942
1943
1944
1945namespace FunctionDefinitionTest {
1946
1947class Foo {
1948public:
1949 void foo1();
1950 void foo2();
1951 void foo3(Foo *other);
1952
1953 template<class T>
1954 void fooT1(const T& dummy1);
1955
1956 template<class T>
1957 void fooT2(const T& dummy2) EXCLUSIVE_LOCKS_REQUIRED(mu_);
1958
1959 Mutex mu_;
1960 int a GUARDED_BY(mu_);
1961};
1962
1963template<class T>
1964class FooT {
1965public:
1966 void foo();
1967
1968 Mutex mu_;
1969 T a GUARDED_BY(mu_);
1970};
1971
1972
1973void Foo::foo1() NO_THREAD_SAFETY_ANALYSIS {
1974 a = 1;
1975}
1976
1977void Foo::foo2() EXCLUSIVE_LOCKS_REQUIRED(mu_) {
1978 a = 2;
1979}
1980
1981void Foo::foo3(Foo *other) EXCLUSIVE_LOCKS_REQUIRED(other->mu_) {
1982 other->a = 3;
1983}
1984
1985template<class T>
1986void Foo::fooT1(const T& dummy1) EXCLUSIVE_LOCKS_REQUIRED(mu_) {
1987 a = dummy1;
1988}
1989
1990/* TODO -- uncomment with template instantiation of attributes.
1991template<class T>
1992void Foo::fooT2(const T& dummy2) {
1993 a = dummy2;
1994}
1995*/
1996
1997void fooF1(Foo *f) EXCLUSIVE_LOCKS_REQUIRED(f->mu_) {
1998 f->a = 1;
1999}
2000
2001void fooF2(Foo *f);
2002void fooF2(Foo *f) EXCLUSIVE_LOCKS_REQUIRED(f->mu_) {
2003 f->a = 2;
2004}
2005
2006void fooF3(Foo *f) EXCLUSIVE_LOCKS_REQUIRED(f->mu_);
2007void fooF3(Foo *f) {
2008 f->a = 3;
2009}
2010
2011template<class T>
2012void FooT<T>::foo() EXCLUSIVE_LOCKS_REQUIRED(mu_) {
2013 a = 0;
2014}
2015
2016void test() {
2017 int dummy = 0;
2018 Foo myFoo;
2019
2020 myFoo.foo2(); // \
2021 // expected-warning {{calling function 'foo2' requires exclusive lock on 'mu_'}}
2022 myFoo.foo3(&myFoo); // \
2023 // expected-warning {{calling function 'foo3' requires exclusive lock on 'mu_'}}
2024 myFoo.fooT1(dummy); // \
2025 // expected-warning {{calling function 'fooT1' requires exclusive lock on 'mu_'}}
2026
2027 // FIXME: uncomment with template instantiation of attributes patch
2028 // myFoo.fooT2(dummy); // expected warning
2029
2030 fooF1(&myFoo); // \
2031 // expected-warning {{calling function 'fooF1' requires exclusive lock on 'mu_'}}
2032 fooF2(&myFoo); // \
2033 // expected-warning {{calling function 'fooF2' requires exclusive lock on 'mu_'}}
2034 fooF3(&myFoo); // \
2035 // expected-warning {{calling function 'fooF3' requires exclusive lock on 'mu_'}}
2036
2037 myFoo.mu_.Lock();
2038 myFoo.foo2();
2039 myFoo.foo3(&myFoo);
2040 myFoo.fooT1(dummy);
2041
2042 // FIXME: uncomment with template instantiation of attributes patch
2043 // myFoo.fooT2(dummy);
2044
2045 fooF1(&myFoo);
2046 fooF2(&myFoo);
2047 fooF3(&myFoo);
2048 myFoo.mu_.Unlock();
2049
2050 FooT<int> myFooT;
2051 myFooT.foo(); // \
2052 // expected-warning {{calling function 'foo' requires exclusive lock on 'mu_'}}
2053}
2054
DeLesley Hutchins4bda3ec2012-02-16 17:03:24 +00002055} // end namespace FunctionDefinitionTest
2056
2057
2058namespace SelfLockingTest {
2059
2060class LOCKABLE MyLock {
2061public:
2062 int foo GUARDED_BY(this);
2063
2064 void lock() EXCLUSIVE_LOCK_FUNCTION();
2065 void unlock() UNLOCK_FUNCTION();
2066
2067 void doSomething() {
2068 this->lock(); // allow 'this' as a lock expression
2069 foo = 0;
2070 doSomethingElse();
2071 this->unlock();
2072 }
2073
2074 void doSomethingElse() EXCLUSIVE_LOCKS_REQUIRED(this) {
2075 foo = 1;
2076 };
2077
2078 void test() {
2079 foo = 2; // \
2080 // expected-warning {{writing variable 'foo' requires locking 'this' exclusively}}
2081 }
DeLesley Hutchinsc24a2332012-02-16 16:50:43 +00002082};
2083
DeLesley Hutchins2f13bec2012-02-16 17:13:43 +00002084
2085class LOCKABLE MyLock2 {
2086public:
2087 Mutex mu_;
2088 int foo GUARDED_BY(this);
2089
2090 // don't check inside lock and unlock functions
2091 void lock() EXCLUSIVE_LOCK_FUNCTION() { mu_.Lock(); }
2092 void unlock() UNLOCK_FUNCTION() { mu_.Unlock(); }
2093
2094 // don't check inside constructors and destructors
2095 MyLock2() { foo = 1; }
2096 ~MyLock2() { foo = 0; }
2097};
2098
2099
DeLesley Hutchins4bda3ec2012-02-16 17:03:24 +00002100} // end namespace SelfLockingTest
2101
2102