blob: 566e5c1b843bb6af9b516c4fd54a31659e2148f6 [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
DeLesley Hutchins0d95dfc2012-03-02 23:36:05 +0000769// FIXME -- derive new tests for unhandled expressions
Caitlin Sadowski194418f2011-09-14 20:00:24 +0000770
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +0000771
772//----------------------------------------------------------------------------//
773// The following test cases are ported from the gcc thread safety implementation
774// They are each wrapped inside a namespace with the test number of the gcc test
775//
776// FIXME: add all the gcc tests, once this analysis passes them.
777//----------------------------------------------------------------------------//
778
779//-----------------------------------------//
780// Good testcases (no errors)
781//-----------------------------------------//
782
783namespace thread_annot_lock_20 {
784class Bar {
785 public:
786 static int func1() EXCLUSIVE_LOCKS_REQUIRED(mu1_);
787 static int b_ GUARDED_BY(mu1_);
788 static Mutex mu1_;
789 static int a_ GUARDED_BY(mu1_);
790};
791
792Bar b1;
793
794int Bar::func1()
795{
796 int res = 5;
797
798 if (a_ == 4)
799 res = b_;
800 return res;
801}
802} // end namespace thread_annot_lock_20
803
804namespace thread_annot_lock_22 {
805// Test various usage of GUARDED_BY and PT_GUARDED_BY annotations, especially
806// uses in class definitions.
807Mutex mu;
808
809class Bar {
810 public:
811 int a_ GUARDED_BY(mu1_);
812 int b_;
813 int *q PT_GUARDED_BY(mu);
814 Mutex mu1_ ACQUIRED_AFTER(mu);
815};
816
817Bar b1, *b3;
818int *p GUARDED_BY(mu) PT_GUARDED_BY(mu);
819int res GUARDED_BY(mu) = 5;
820
821int func(int i)
822{
823 int x;
824 mu.Lock();
825 b1.mu1_.Lock();
826 res = b1.a_ + b3->b_;
827 *p = i;
828 b1.a_ = res + b3->b_;
829 b3->b_ = *b1.q;
830 b1.mu1_.Unlock();
831 b1.b_ = res;
832 x = res;
833 mu.Unlock();
834 return x;
835}
836} // end namespace thread_annot_lock_22
837
838namespace thread_annot_lock_27_modified {
839// test lock annotations applied to function definitions
840// Modified: applied annotations only to function declarations
841Mutex mu1;
842Mutex mu2 ACQUIRED_AFTER(mu1);
843
844class Foo {
845 public:
846 int method1(int i) SHARED_LOCKS_REQUIRED(mu2) EXCLUSIVE_LOCKS_REQUIRED(mu1);
847};
848
849int Foo::method1(int i) {
850 return i;
851}
852
853
854int foo(int i) EXCLUSIVE_LOCKS_REQUIRED(mu2) SHARED_LOCKS_REQUIRED(mu1);
855int foo(int i) {
856 return i;
857}
858
859static int bar(int i) EXCLUSIVE_LOCKS_REQUIRED(mu1);
860static int bar(int i) {
861 return i;
862}
863
864void main() {
865 Foo a;
866
867 mu1.Lock();
868 mu2.Lock();
869 a.method1(1);
870 foo(2);
871 mu2.Unlock();
872 bar(3);
873 mu1.Unlock();
874}
875} // end namespace thread_annot_lock_27_modified
876
877
878namespace thread_annot_lock_38 {
879// Test the case where a template member function is annotated with lock
880// attributes in a non-template class.
881class Foo {
882 public:
883 void func1(int y) LOCKS_EXCLUDED(mu_);
884 template <typename T> void func2(T x) LOCKS_EXCLUDED(mu_);
885 private:
886 Mutex mu_;
887};
888
889Foo *foo;
890
891void main()
892{
893 foo->func1(5);
894 foo->func2(5);
895}
896} // end namespace thread_annot_lock_38
897
898namespace thread_annot_lock_43 {
899// Tests lock canonicalization
900class Foo {
901 public:
902 Mutex *mu_;
903};
904
905class FooBar {
906 public:
907 Foo *foo_;
908 int GetA() EXCLUSIVE_LOCKS_REQUIRED(foo_->mu_) { return a_; }
909 int a_ GUARDED_BY(foo_->mu_);
910};
911
912FooBar *fb;
913
914void main()
915{
916 int x;
917 fb->foo_->mu_->Lock();
918 x = fb->GetA();
919 fb->foo_->mu_->Unlock();
920}
921} // end namespace thread_annot_lock_43
922
923namespace thread_annot_lock_49 {
924// Test the support for use of lock expression in the annotations
925class Foo {
926 public:
927 Mutex foo_mu_;
928};
929
930class Bar {
931 private:
932 Foo *foo;
933 Mutex bar_mu_ ACQUIRED_AFTER(foo->foo_mu_);
934
935 public:
936 void Test1() {
937 foo->foo_mu_.Lock();
938 bar_mu_.Lock();
939 bar_mu_.Unlock();
940 foo->foo_mu_.Unlock();
941 }
942};
943
944void main() {
945 Bar bar;
946 bar.Test1();
947}
948} // end namespace thread_annot_lock_49
949
950namespace thread_annot_lock_61_modified {
951 // Modified to fix the compiler errors
952 // Test the fix for a bug introduced by the support of pass-by-reference
953 // paramters.
954 struct Foo { Foo &operator<< (bool) {return *this;} };
955 Foo &getFoo();
956 struct Bar { Foo &func () {return getFoo();} };
957 struct Bas { void operator& (Foo &) {} };
958 void mumble()
959 {
960 Bas() & Bar().func() << "" << "";
961 Bas() & Bar().func() << "";
962 }
963} // end namespace thread_annot_lock_61_modified
964
965
966namespace thread_annot_lock_65 {
967// Test the fix for a bug in the support of allowing reader locks for
968// non-const, non-modifying overload functions. (We didn't handle the builtin
969// properly.)
970enum MyFlags {
971 Zero,
972 One,
973 Two,
974 Three,
975 Four,
976 Five,
977 Six,
978 Seven,
979 Eight,
980 Nine
981};
982
983inline MyFlags
984operator|(MyFlags a, MyFlags b)
985{
986 return MyFlags(static_cast<int>(a) | static_cast<int>(b));
987}
988
989inline MyFlags&
990operator|=(MyFlags& a, MyFlags b)
991{
992 return a = a | b;
993}
994} // end namespace thread_annot_lock_65
995
996namespace thread_annot_lock_66_modified {
997// Modified: Moved annotation to function defn
998// Test annotations on out-of-line definitions of member functions where the
999// annotations refer to locks that are also data members in the class.
1000Mutex mu;
1001
1002class Foo {
1003 public:
1004 int method1(int i) SHARED_LOCKS_REQUIRED(mu1, mu, mu2);
1005 int data GUARDED_BY(mu1);
1006 Mutex *mu1;
1007 Mutex *mu2;
1008};
1009
1010int Foo::method1(int i)
1011{
1012 return data + i;
1013}
1014
1015void main()
1016{
1017 Foo a;
1018
1019 a.mu2->Lock();
1020 a.mu1->Lock();
1021 mu.Lock();
1022 a.method1(1);
1023 mu.Unlock();
1024 a.mu1->Unlock();
1025 a.mu2->Unlock();
1026}
1027} // end namespace thread_annot_lock_66_modified
1028
1029namespace thread_annot_lock_68_modified {
1030// Test a fix to a bug in the delayed name binding with nested template
1031// instantiation. We use a stack to make sure a name is not resolved to an
1032// inner context.
1033template <typename T>
1034class Bar {
1035 Mutex mu_;
1036};
1037
1038template <typename T>
1039class Foo {
1040 public:
1041 void func(T x) {
1042 mu_.Lock();
DeLesley Hutchins23323e02012-01-20 22:50:54 +00001043 count_ = x;
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001044 mu_.Unlock();
1045 }
1046
1047 private:
DeLesley Hutchins23323e02012-01-20 22:50:54 +00001048 T count_ GUARDED_BY(mu_);
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001049 Bar<T> bar_;
1050 Mutex mu_;
1051};
1052
1053void main()
1054{
1055 Foo<int> *foo;
1056 foo->func(5);
1057}
1058} // end namespace thread_annot_lock_68_modified
1059
1060namespace thread_annot_lock_30_modified {
1061// Test delay parsing of lock attribute arguments with nested classes.
1062// Modified: trylocks replaced with exclusive_lock_fun
1063int a = 0;
1064
1065class Bar {
1066 struct Foo;
1067
1068 public:
1069 void MyLock() EXCLUSIVE_LOCK_FUNCTION(mu);
1070
1071 int func() {
1072 MyLock();
1073// if (foo == 0) {
1074// return 0;
1075// }
1076 a = 5;
1077 mu.Unlock();
1078 return 1;
1079 }
1080
1081 class FooBar {
1082 int x;
1083 int y;
1084 };
1085
1086 private:
1087 Mutex mu;
1088};
1089
1090Bar *bar;
1091
1092void main()
1093{
1094 bar->func();
1095}
1096} // end namespace thread_annot_lock_30_modified
1097
1098namespace thread_annot_lock_47 {
1099// Test the support for annotations on virtual functions.
1100// This is a good test case. (i.e. There should be no warning emitted by the
1101// compiler.)
1102class Base {
1103 public:
1104 virtual void func1() EXCLUSIVE_LOCKS_REQUIRED(mu_);
1105 virtual void func2() LOCKS_EXCLUDED(mu_);
1106 Mutex mu_;
1107};
1108
1109class Child : public Base {
1110 public:
1111 virtual void func1() EXCLUSIVE_LOCKS_REQUIRED(mu_);
1112 virtual void func2() LOCKS_EXCLUDED(mu_);
1113};
1114
1115void main() {
1116 Child *c;
1117 Base *b = c;
1118
1119 b->mu_.Lock();
1120 b->func1();
1121 b->mu_.Unlock();
1122 b->func2();
1123
1124 c->mu_.Lock();
1125 c->func1();
1126 c->mu_.Unlock();
1127 c->func2();
1128}
1129} // end namespace thread_annot_lock_47
1130
1131//-----------------------------------------//
1132// Tests which produce errors
1133//-----------------------------------------//
1134
1135namespace thread_annot_lock_13 {
1136Mutex mu1;
1137Mutex mu2;
1138
1139int g GUARDED_BY(mu1);
1140int w GUARDED_BY(mu2);
1141
1142class Foo {
1143 public:
1144 void bar() LOCKS_EXCLUDED(mu_, mu1);
1145 int foo() SHARED_LOCKS_REQUIRED(mu_) EXCLUSIVE_LOCKS_REQUIRED(mu2);
1146
1147 private:
1148 int a_ GUARDED_BY(mu_);
1149 public:
1150 Mutex mu_ ACQUIRED_AFTER(mu1);
1151};
1152
1153int Foo::foo()
1154{
1155 int res;
David Blaikiee31b8fb2012-04-05 00:16:44 +00001156 w = 5;
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001157 res = a_ + 5;
1158 return res;
1159}
1160
1161void Foo::bar()
1162{
1163 int x;
1164 mu_.Lock();
1165 x = foo(); // expected-warning {{calling function 'foo' requires exclusive lock on 'mu2'}}
1166 a_ = x + 1;
1167 mu_.Unlock();
1168 if (x > 5) {
1169 mu1.Lock();
David Blaikiee31b8fb2012-04-05 00:16:44 +00001170 g = 2;
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001171 mu1.Unlock();
1172 }
1173}
1174
1175void main()
1176{
1177 Foo f1, *f2;
1178 f1.mu_.Lock();
Caitlin Sadowski74558b42011-09-15 18:13:32 +00001179 f1.bar(); // expected-warning {{cannot call function 'bar' while mutex 'mu_' is locked}}
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001180 mu2.Lock();
1181 f1.foo();
1182 mu2.Unlock();
1183 f1.mu_.Unlock();
1184 f2->mu_.Lock();
Caitlin Sadowski74558b42011-09-15 18:13:32 +00001185 f2->bar(); // expected-warning {{cannot call function 'bar' while mutex 'mu_' is locked}}
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001186 f2->mu_.Unlock();
1187 mu2.Lock();
David Blaikiee31b8fb2012-04-05 00:16:44 +00001188 w = 2;
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001189 mu2.Unlock();
1190}
1191} // end namespace thread_annot_lock_13
1192
1193namespace thread_annot_lock_18_modified {
1194// Modified: Trylocks removed
1195// Test the ability to distnguish between the same lock field of
1196// different objects of a class.
1197 class Bar {
1198 public:
1199 bool MyLock() EXCLUSIVE_LOCK_FUNCTION(mu1_);
1200 void MyUnlock() UNLOCK_FUNCTION(mu1_);
1201 int a_ GUARDED_BY(mu1_);
1202
1203 private:
1204 Mutex mu1_;
1205};
1206
1207Bar *b1, *b2;
1208
1209void func()
1210{
1211 b1->MyLock();
1212 b1->a_ = 5;
Caitlin Sadowski74558b42011-09-15 18:13:32 +00001213 b2->a_ = 3; // expected-warning {{writing variable 'a_' requires locking 'mu1_' exclusively}}
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001214 b2->MyLock();
1215 b2->MyUnlock();
1216 b1->MyUnlock();
1217}
1218} // end namespace thread_annot_lock_18_modified
1219
1220namespace thread_annot_lock_21 {
1221// Test various usage of GUARDED_BY and PT_GUARDED_BY annotations, especially
1222// uses in class definitions.
1223Mutex mu;
1224
1225class Bar {
1226 public:
1227 int a_ GUARDED_BY(mu1_);
1228 int b_;
1229 int *q PT_GUARDED_BY(mu);
1230 Mutex mu1_ ACQUIRED_AFTER(mu);
1231};
1232
1233Bar b1, *b3;
1234int *p GUARDED_BY(mu) PT_GUARDED_BY(mu);
1235
1236int res GUARDED_BY(mu) = 5;
1237
1238int func(int i)
1239{
1240 int x;
1241 b3->mu1_.Lock();
Caitlin Sadowski74558b42011-09-15 18:13:32 +00001242 res = b1.a_ + b3->b_; // expected-warning {{reading variable 'a_' requires locking 'mu1_'}} \
1243 // expected-warning {{writing variable 'res' requires locking 'mu' exclusively}}
1244 *p = i; // expected-warning {{reading variable 'p' requires locking 'mu'}} \
1245 // expected-warning {{writing the value pointed to by 'p' requires locking 'mu' exclusively}}
1246 b1.a_ = res + b3->b_; // expected-warning {{reading variable 'res' requires locking 'mu'}} \
1247 // expected-warning {{writing variable 'a_' requires locking 'mu1_' exclusively}}
1248 b3->b_ = *b1.q; // expected-warning {{reading the value pointed to by 'q' requires locking 'mu'}}
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001249 b3->mu1_.Unlock();
Caitlin Sadowski74558b42011-09-15 18:13:32 +00001250 b1.b_ = res; // expected-warning {{reading variable 'res' requires locking 'mu'}}
1251 x = res; // expected-warning {{reading variable 'res' requires locking 'mu'}}
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001252 return x;
1253}
1254} // end namespace thread_annot_lock_21
1255
1256namespace thread_annot_lock_35_modified {
1257// Test the analyzer's ability to distinguish the lock field of different
1258// objects.
1259class Foo {
1260 private:
1261 Mutex lock_;
1262 int a_ GUARDED_BY(lock_);
1263
1264 public:
1265 void Func(Foo* child) LOCKS_EXCLUDED(lock_) {
1266 Foo *new_foo = new Foo;
1267
1268 lock_.Lock();
1269
1270 child->Func(new_foo); // There shouldn't be any warning here as the
1271 // acquired lock is not in child.
1272 child->bar(7); // expected-warning {{calling function 'bar' requires exclusive lock on 'lock_'}}
Caitlin Sadowski74558b42011-09-15 18:13:32 +00001273 child->a_ = 5; // expected-warning {{writing variable 'a_' requires locking 'lock_' exclusively}}
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001274 lock_.Unlock();
1275 }
1276
1277 void bar(int y) EXCLUSIVE_LOCKS_REQUIRED(lock_) {
1278 a_ = y;
1279 }
1280};
1281
1282Foo *x;
1283
1284void main() {
1285 Foo *child = new Foo;
1286 x->Func(child);
1287}
1288} // end namespace thread_annot_lock_35_modified
1289
1290namespace thread_annot_lock_36_modified {
1291// Modified to move the annotations to function defns.
1292// Test the analyzer's ability to distinguish the lock field of different
1293// objects
1294class Foo {
1295 private:
1296 Mutex lock_;
1297 int a_ GUARDED_BY(lock_);
1298
1299 public:
1300 void Func(Foo* child) LOCKS_EXCLUDED(lock_);
1301 void bar(int y) EXCLUSIVE_LOCKS_REQUIRED(lock_);
1302};
1303
1304void Foo::Func(Foo* child) {
1305 Foo *new_foo = new Foo;
1306
1307 lock_.Lock();
1308
1309 child->lock_.Lock();
Caitlin Sadowski74558b42011-09-15 18:13:32 +00001310 child->Func(new_foo); // expected-warning {{cannot call function 'Func' while mutex 'lock_' is locked}}
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001311 child->bar(7);
1312 child->a_ = 5;
1313 child->lock_.Unlock();
1314
1315 lock_.Unlock();
1316}
1317
1318void Foo::bar(int y) {
1319 a_ = y;
1320}
1321
1322
1323Foo *x;
1324
1325void main() {
1326 Foo *child = new Foo;
1327 x->Func(child);
1328}
1329} // end namespace thread_annot_lock_36_modified
1330
1331
1332namespace thread_annot_lock_42 {
1333// Test support of multiple lock attributes of the same kind on a decl.
1334class Foo {
1335 private:
1336 Mutex mu1, mu2, mu3;
1337 int x GUARDED_BY(mu1) GUARDED_BY(mu2);
1338 int y GUARDED_BY(mu2);
1339
1340 void f2() LOCKS_EXCLUDED(mu1) LOCKS_EXCLUDED(mu2) LOCKS_EXCLUDED(mu3) {
1341 mu2.Lock();
1342 y = 2;
1343 mu2.Unlock();
1344 }
1345
1346 public:
1347 void f1() EXCLUSIVE_LOCKS_REQUIRED(mu2) EXCLUSIVE_LOCKS_REQUIRED(mu1) {
1348 x = 5;
Caitlin Sadowski74558b42011-09-15 18:13:32 +00001349 f2(); // expected-warning {{cannot call function 'f2' while mutex 'mu1' is locked}} \
1350 // expected-warning {{cannot call function 'f2' while mutex 'mu2' is locked}}
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001351 }
1352};
1353
1354Foo *foo;
1355
1356void func()
1357{
1358 foo->f1(); // expected-warning {{calling function 'f1' requires exclusive lock on 'mu2'}} \
1359 // expected-warning {{calling function 'f1' requires exclusive lock on 'mu1'}}
1360}
1361} // end namespace thread_annot_lock_42
1362
1363namespace thread_annot_lock_46 {
1364// Test the support for annotations on virtual functions.
1365class Base {
1366 public:
1367 virtual void func1() EXCLUSIVE_LOCKS_REQUIRED(mu_);
1368 virtual void func2() LOCKS_EXCLUDED(mu_);
1369 Mutex mu_;
1370};
1371
1372class Child : public Base {
1373 public:
1374 virtual void func1() EXCLUSIVE_LOCKS_REQUIRED(mu_);
1375 virtual void func2() LOCKS_EXCLUDED(mu_);
1376};
1377
1378void main() {
1379 Child *c;
1380 Base *b = c;
1381
1382 b->func1(); // expected-warning {{calling function 'func1' requires exclusive lock on 'mu_'}}
1383 b->mu_.Lock();
Caitlin Sadowski74558b42011-09-15 18:13:32 +00001384 b->func2(); // expected-warning {{cannot call function 'func2' while mutex 'mu_' is locked}}
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001385 b->mu_.Unlock();
1386
1387 c->func1(); // expected-warning {{calling function 'func1' requires exclusive lock on 'mu_'}}
1388 c->mu_.Lock();
Caitlin Sadowski74558b42011-09-15 18:13:32 +00001389 c->func2(); // expected-warning {{cannot call function 'func2' while mutex 'mu_' is locked}}
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001390 c->mu_.Unlock();
1391}
1392} // end namespace thread_annot_lock_46
1393
1394namespace thread_annot_lock_67_modified {
1395// Modified: attributes on definitions moved to declarations
1396// Test annotations on out-of-line definitions of member functions where the
1397// annotations refer to locks that are also data members in the class.
1398Mutex mu;
1399Mutex mu3;
1400
1401class Foo {
1402 public:
1403 int method1(int i) SHARED_LOCKS_REQUIRED(mu1, mu, mu2, mu3);
1404 int data GUARDED_BY(mu1);
1405 Mutex *mu1;
1406 Mutex *mu2;
1407};
1408
1409int Foo::method1(int i) {
1410 return data + i;
1411}
1412
1413void main()
1414{
1415 Foo a;
1416 a.method1(1); // expected-warning {{calling function 'method1' requires shared lock on 'mu1'}} \
1417 // expected-warning {{calling function 'method1' requires shared lock on 'mu'}} \
1418 // expected-warning {{calling function 'method1' requires shared lock on 'mu2'}} \
1419 // expected-warning {{calling function 'method1' requires shared lock on 'mu3'}}
1420}
1421} // end namespace thread_annot_lock_67_modified
1422
1423
DeLesley Hutchins81216392011-10-17 21:38:02 +00001424namespace substitution_test {
1425 class MyData {
1426 public:
1427 Mutex mu;
1428
1429 void lockData() __attribute__((exclusive_lock_function(mu))) { }
1430 void unlockData() __attribute__((unlock_function(mu))) { }
1431
1432 void doSomething() __attribute__((exclusive_locks_required(mu))) { }
1433 };
1434
1435
1436 class DataLocker {
1437 public:
1438 void lockData (MyData *d) __attribute__((exclusive_lock_function(d->mu))) { }
1439 void unlockData(MyData *d) __attribute__((unlock_function(d->mu))) { }
1440 };
1441
1442
1443 class Foo {
1444 public:
1445 void foo(MyData* d) __attribute__((exclusive_locks_required(d->mu))) { }
1446
1447 void bar1(MyData* d) {
1448 d->lockData();
1449 foo(d);
1450 d->unlockData();
1451 }
1452
1453 void bar2(MyData* d) {
1454 DataLocker dlr;
1455 dlr.lockData(d);
1456 foo(d);
1457 dlr.unlockData(d);
1458 }
1459
1460 void bar3(MyData* d1, MyData* d2) {
1461 DataLocker dlr;
Richard Smith2e515622012-02-03 04:45:26 +00001462 dlr.lockData(d1); // expected-note {{mutex acquired here}}
DeLesley Hutchins81216392011-10-17 21:38:02 +00001463 dlr.unlockData(d2); // \
1464 // expected-warning {{unlocking 'mu' that was not locked}}
Richard Smith2e515622012-02-03 04:45:26 +00001465 } // expected-warning {{mutex 'mu' is still locked at the end of function}}
DeLesley Hutchins81216392011-10-17 21:38:02 +00001466
1467 void bar4(MyData* d1, MyData* d2) {
1468 DataLocker dlr;
1469 dlr.lockData(d1);
1470 foo(d2); // \
1471 // expected-warning {{calling function 'foo' requires exclusive lock on 'mu'}}
1472 dlr.unlockData(d1);
1473 }
1474 };
1475} // end namespace substituation_test
1476
DeLesley Hutchinse0eaa852011-10-21 18:06:53 +00001477
DeLesley Hutchinsf1ac6372011-10-21 18:10:14 +00001478
DeLesley Hutchinse0eaa852011-10-21 18:06:53 +00001479namespace constructor_destructor_tests {
1480 Mutex fooMu;
1481 int myVar GUARDED_BY(fooMu);
1482
1483 class Foo {
1484 public:
1485 Foo() __attribute__((exclusive_lock_function(fooMu))) { }
1486 ~Foo() __attribute__((unlock_function(fooMu))) { }
1487 };
1488
1489 void fooTest() {
DeLesley Hutchins6db51f72011-10-21 20:51:27 +00001490 Foo foo;
DeLesley Hutchinse0eaa852011-10-21 18:06:53 +00001491 myVar = 0;
1492 }
1493}
1494
DeLesley Hutchinsf1ac6372011-10-21 18:10:14 +00001495
1496namespace invalid_lock_expression_test {
1497
1498class LOCKABLE MyLockable {
1499public:
1500 MyLockable() __attribute__((exclusive_lock_function)) { }
DeLesley Hutchins6db51f72011-10-21 20:51:27 +00001501 ~MyLockable() { }
DeLesley Hutchinsf1ac6372011-10-21 18:10:14 +00001502};
1503
1504// create an empty lock expression
1505void foo() {
1506 MyLockable lock; // \
1507 // expected-warning {{cannot resolve lock expression}}
1508}
1509
1510} // end namespace invalid_lock_expression_test
1511
Richard Smith97f9fe02011-10-25 00:41:24 +00001512namespace template_member_test {
DeLesley Hutchinsf1ac6372011-10-21 18:10:14 +00001513
Richard Smith97f9fe02011-10-25 00:41:24 +00001514 struct S { int n; };
1515 struct T {
1516 Mutex m;
1517 S *s GUARDED_BY(this->m);
1518 };
Richard Smitha01c7112011-10-25 06:33:21 +00001519 Mutex m;
1520 struct U {
1521 union {
1522 int n;
1523 };
1524 } *u GUARDED_BY(m);
Richard Smith97f9fe02011-10-25 00:41:24 +00001525
1526 template<typename U>
1527 struct IndirectLock {
1528 int DoNaughtyThings(T *t) {
Richard Smitha01c7112011-10-25 06:33:21 +00001529 u->n = 0; // expected-warning {{reading variable 'u' requires locking 'm'}}
Richard Smith97f9fe02011-10-25 00:41:24 +00001530 return t->s->n; // expected-warning {{reading variable 's' requires locking 'm'}}
1531 }
1532 };
1533
Richard Smithf11e9232011-10-25 01:05:41 +00001534 template struct IndirectLock<int>; // expected-note {{here}}
Richard Smith97f9fe02011-10-25 00:41:24 +00001535
Richard Smith601d2ee2011-10-26 06:15:36 +00001536 struct V {
1537 void f(int);
1538 void f(double);
1539
1540 Mutex m;
1541 V *p GUARDED_BY(this->m);
1542 };
1543 template<typename U> struct W {
1544 V v;
1545 void f(U u) {
1546 v.p->f(u); // expected-warning {{reading variable 'p' requires locking 'm'}}
1547 }
1548 };
1549 template struct W<int>; // expected-note {{here}}
1550
Richard Smith97f9fe02011-10-25 00:41:24 +00001551}
DeLesley Hutchins1fa3c062011-12-08 20:23:06 +00001552
1553namespace test_scoped_lockable {
1554
1555struct TestScopedLockable {
1556 Mutex mu1;
1557 Mutex mu2;
1558 int a __attribute__((guarded_by(mu1)));
1559 int b __attribute__((guarded_by(mu2)));
1560
1561 bool getBool();
1562
1563 void foo1() {
1564 MutexLock mulock(&mu1);
1565 a = 5;
1566 }
1567
1568 void foo2() {
1569 ReaderMutexLock mulock1(&mu1);
1570 if (getBool()) {
1571 MutexLock mulock2a(&mu2);
1572 b = a + 1;
1573 }
1574 else {
1575 MutexLock mulock2b(&mu2);
1576 b = a + 2;
1577 }
1578 }
1579
1580 void foo3() {
1581 MutexLock mulock_a(&mu1);
1582 MutexLock mulock_b(&mu1); // \
1583 // expected-warning {{locking 'mu1' that is already locked}}
1584 } // expected-warning {{unlocking 'mu1' that was not locked}}
1585
1586 void foo4() {
1587 MutexLock mulock1(&mu1), mulock2(&mu2);
1588 a = b+1;
1589 b = a+1;
1590 }
1591};
1592
1593} // end namespace test_scoped_lockable
1594
1595
DeLesley Hutchinsdf497822011-12-29 00:56:48 +00001596namespace FunctionAttrTest {
1597
1598class Foo {
1599public:
1600 Mutex mu_;
1601 int a GUARDED_BY(mu_);
1602};
1603
1604Foo fooObj;
1605
1606void foo() EXCLUSIVE_LOCKS_REQUIRED(fooObj.mu_);
1607
1608void bar() {
1609 foo(); // expected-warning {{calling function 'foo' requires exclusive lock on 'mu_'}}
1610 fooObj.mu_.Lock();
1611 foo();
1612 fooObj.mu_.Unlock();
1613}
1614
1615}; // end namespace FunctionAttrTest
1616
1617
DeLesley Hutchinsb4fa4182012-01-06 19:16:50 +00001618struct TestTryLock {
1619 Mutex mu;
1620 int a GUARDED_BY(mu);
1621 bool cond;
1622
1623 void foo1() {
1624 if (mu.TryLock()) {
1625 a = 1;
1626 mu.Unlock();
1627 }
1628 }
1629
1630 void foo2() {
1631 if (!mu.TryLock()) return;
1632 a = 2;
1633 mu.Unlock();
1634 }
1635
1636 void foo3() {
1637 bool b = mu.TryLock();
1638 if (b) {
1639 a = 3;
1640 mu.Unlock();
1641 }
1642 }
1643
1644 void foo4() {
1645 bool b = mu.TryLock();
1646 if (!b) return;
1647 a = 4;
1648 mu.Unlock();
1649 }
1650
1651 void foo5() {
1652 while (mu.TryLock()) {
1653 a = a + 1;
1654 mu.Unlock();
1655 }
1656 }
1657
1658 void foo6() {
1659 bool b = mu.TryLock();
1660 b = !b;
1661 if (b) return;
1662 a = 6;
1663 mu.Unlock();
1664 }
1665
1666 void foo7() {
1667 bool b1 = mu.TryLock();
1668 bool b2 = !b1;
1669 bool b3 = !b2;
1670 if (b3) {
1671 a = 7;
1672 mu.Unlock();
1673 }
1674 }
1675
1676 // Test use-def chains: join points
1677 void foo8() {
1678 bool b = mu.TryLock();
1679 bool b2 = b;
1680 if (cond)
1681 b = true;
1682 if (b) { // b should be unknown at this point, becuase of the join point
1683 a = 8; // expected-warning {{writing variable 'a' requires locking 'mu' exclusively}}
1684 }
1685 if (b2) { // b2 should be known at this point.
1686 a = 8;
1687 mu.Unlock();
1688 }
1689 }
1690
1691 // Test use-def-chains: back edges
1692 void foo9() {
1693 bool b = mu.TryLock();
1694
1695 for (int i = 0; i < 10; ++i);
1696
1697 if (b) { // b is still known, because the loop doesn't alter it
1698 a = 9;
1699 mu.Unlock();
1700 }
1701 }
1702
1703 // Test use-def chains: back edges
1704 void foo10() {
1705 bool b = mu.TryLock();
1706
1707 while (cond) {
1708 if (b) { // b should be uknown at this point b/c of the loop
1709 a = 10; // expected-warning {{writing variable 'a' requires locking 'mu' exclusively}}
1710 }
1711 b = !b;
1712 }
1713 }
1714}; // end TestTrylock
1715
1716
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +00001717namespace TestTemplateAttributeInstantiation {
1718
1719class Foo1 {
1720public:
1721 Mutex mu_;
1722 int a GUARDED_BY(mu_);
1723};
1724
1725class Foo2 {
1726public:
1727 int a GUARDED_BY(mu_);
1728 Mutex mu_;
1729};
1730
1731
1732class Bar {
1733public:
1734 // Test non-dependent expressions in attributes on template functions
1735 template <class T>
1736 void barND(Foo1 *foo, T *fooT) EXCLUSIVE_LOCKS_REQUIRED(foo->mu_) {
1737 foo->a = 0;
1738 }
1739
1740 // Test dependent expressions in attributes on template functions
1741 template <class T>
1742 void barD(Foo1 *foo, T *fooT) EXCLUSIVE_LOCKS_REQUIRED(fooT->mu_) {
1743 fooT->a = 0;
1744 }
1745};
1746
1747
1748template <class T>
1749class BarT {
1750public:
1751 Foo1 fooBase;
1752 T fooBaseT;
1753
1754 // Test non-dependent expression in ordinary method on template class
1755 void barND() EXCLUSIVE_LOCKS_REQUIRED(fooBase.mu_) {
1756 fooBase.a = 0;
1757 }
1758
1759 // Test dependent expressions in ordinary methods on template class
1760 void barD() EXCLUSIVE_LOCKS_REQUIRED(fooBaseT.mu_) {
1761 fooBaseT.a = 0;
1762 }
1763
1764 // Test dependent expressions in template method in template class
1765 template <class T2>
1766 void barTD(T2 *fooT) EXCLUSIVE_LOCKS_REQUIRED(fooBaseT.mu_, fooT->mu_) {
1767 fooBaseT.a = 0;
1768 fooT->a = 0;
1769 }
1770};
1771
1772template <class T>
1773class Cell {
1774public:
1775 Mutex mu_;
1776 // Test dependent guarded_by
1777 T data GUARDED_BY(mu_);
1778
DeLesley Hutchins23323e02012-01-20 22:50:54 +00001779 void fooEx() EXCLUSIVE_LOCKS_REQUIRED(mu_) {
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +00001780 data = 0;
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +00001781 }
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +00001782
1783 void foo() {
1784 mu_.Lock();
1785 data = 0;
1786 mu_.Unlock();
1787 }
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +00001788};
1789
1790void test() {
1791 Bar b;
1792 BarT<Foo2> bt;
1793 Foo1 f1;
1794 Foo2 f2;
1795
1796 f1.mu_.Lock();
1797 f2.mu_.Lock();
1798 bt.fooBase.mu_.Lock();
1799 bt.fooBaseT.mu_.Lock();
1800
1801 b.barND(&f1, &f2);
1802 b.barD(&f1, &f2);
1803 bt.barND();
1804 bt.barD();
1805 bt.barTD(&f2);
1806
1807 f1.mu_.Unlock();
1808 bt.barTD(&f1); // \
1809 // expected-warning {{calling function 'barTD' requires exclusive lock on 'mu_'}}
1810
1811 bt.fooBase.mu_.Unlock();
1812 bt.fooBaseT.mu_.Unlock();
1813 f2.mu_.Unlock();
1814
1815 Cell<int> cell;
1816 cell.data = 0; // \
1817 // expected-warning {{writing variable 'data' requires locking 'mu_' exclusively}}
1818 cell.foo();
DeLesley Hutchins23323e02012-01-20 22:50:54 +00001819 cell.mu_.Lock();
1820 cell.fooEx();
1821 cell.mu_.Unlock();
1822}
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +00001823
DeLesley Hutchins23323e02012-01-20 22:50:54 +00001824
1825template <class T>
1826class CellDelayed {
1827public:
1828 // Test dependent guarded_by
1829 T data GUARDED_BY(mu_);
DeLesley Hutchinsdd5756c2012-02-16 17:30:51 +00001830 static T static_data GUARDED_BY(static_mu_);
DeLesley Hutchins23323e02012-01-20 22:50:54 +00001831
1832 void fooEx(CellDelayed<T> *other) EXCLUSIVE_LOCKS_REQUIRED(mu_, other->mu_) {
1833 this->data = other->data;
1834 }
1835
1836 template <class T2>
1837 void fooExT(CellDelayed<T2> *otherT) EXCLUSIVE_LOCKS_REQUIRED(mu_, otherT->mu_) {
1838 this->data = otherT->data;
1839 }
1840
1841 void foo() {
1842 mu_.Lock();
1843 data = 0;
1844 mu_.Unlock();
1845 }
1846
1847 Mutex mu_;
DeLesley Hutchinsdd5756c2012-02-16 17:30:51 +00001848 static Mutex static_mu_;
DeLesley Hutchins23323e02012-01-20 22:50:54 +00001849};
1850
1851void testDelayed() {
1852 CellDelayed<int> celld;
1853 CellDelayed<int> celld2;
1854 celld.foo();
1855 celld.mu_.Lock();
1856 celld2.mu_.Lock();
1857
1858 celld.fooEx(&celld2);
1859 celld.fooExT(&celld2);
1860
1861 celld2.mu_.Unlock();
1862 celld.mu_.Unlock();
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +00001863}
1864
1865}; // end namespace TestTemplateAttributeInstantiation
1866
1867
DeLesley Hutchinse03b2b32012-01-20 23:24:41 +00001868namespace FunctionDeclDefTest {
1869
1870class Foo {
1871public:
1872 Mutex mu_;
1873 int a GUARDED_BY(mu_);
1874
1875 virtual void foo1(Foo *f_declared) EXCLUSIVE_LOCKS_REQUIRED(f_declared->mu_);
1876};
1877
1878// EXCLUSIVE_LOCKS_REQUIRED should be applied, and rewritten to f_defined->mu_
1879void Foo::foo1(Foo *f_defined) {
1880 f_defined->a = 0;
1881};
1882
1883void test() {
1884 Foo myfoo;
1885 myfoo.foo1(&myfoo); // \
1886 // expected-warning {{calling function 'foo1' requires exclusive lock on 'mu_'}}
1887 myfoo.mu_.Lock();
1888 myfoo.foo1(&myfoo);
1889 myfoo.mu_.Unlock();
1890}
1891
1892};
Richard Smith2e515622012-02-03 04:45:26 +00001893
1894namespace GoingNative {
1895
1896 struct __attribute__((lockable)) mutex {
1897 void lock() __attribute__((exclusive_lock_function));
1898 void unlock() __attribute__((unlock_function));
1899 // ...
1900 };
1901 bool foo();
1902 bool bar();
1903 mutex m;
1904 void test() {
1905 m.lock();
1906 while (foo()) {
1907 m.unlock();
1908 // ...
1909 if (bar()) {
1910 // ...
1911 if (foo())
1912 continue; // expected-warning {{expecting mutex 'm' to be locked at start of each loop}}
1913 //...
1914 }
1915 // ...
1916 m.lock(); // expected-note {{mutex acquired here}}
1917 }
1918 m.unlock();
1919 }
1920
1921}
DeLesley Hutchinsc24a2332012-02-16 16:50:43 +00001922
1923
1924
1925namespace FunctionDefinitionTest {
1926
1927class Foo {
1928public:
1929 void foo1();
1930 void foo2();
1931 void foo3(Foo *other);
1932
1933 template<class T>
1934 void fooT1(const T& dummy1);
1935
1936 template<class T>
1937 void fooT2(const T& dummy2) EXCLUSIVE_LOCKS_REQUIRED(mu_);
1938
1939 Mutex mu_;
1940 int a GUARDED_BY(mu_);
1941};
1942
1943template<class T>
1944class FooT {
1945public:
1946 void foo();
1947
1948 Mutex mu_;
1949 T a GUARDED_BY(mu_);
1950};
1951
1952
1953void Foo::foo1() NO_THREAD_SAFETY_ANALYSIS {
1954 a = 1;
1955}
1956
1957void Foo::foo2() EXCLUSIVE_LOCKS_REQUIRED(mu_) {
1958 a = 2;
1959}
1960
1961void Foo::foo3(Foo *other) EXCLUSIVE_LOCKS_REQUIRED(other->mu_) {
1962 other->a = 3;
1963}
1964
1965template<class T>
1966void Foo::fooT1(const T& dummy1) EXCLUSIVE_LOCKS_REQUIRED(mu_) {
1967 a = dummy1;
1968}
1969
1970/* TODO -- uncomment with template instantiation of attributes.
1971template<class T>
1972void Foo::fooT2(const T& dummy2) {
1973 a = dummy2;
1974}
1975*/
1976
1977void fooF1(Foo *f) EXCLUSIVE_LOCKS_REQUIRED(f->mu_) {
1978 f->a = 1;
1979}
1980
1981void fooF2(Foo *f);
1982void fooF2(Foo *f) EXCLUSIVE_LOCKS_REQUIRED(f->mu_) {
1983 f->a = 2;
1984}
1985
1986void fooF3(Foo *f) EXCLUSIVE_LOCKS_REQUIRED(f->mu_);
1987void fooF3(Foo *f) {
1988 f->a = 3;
1989}
1990
1991template<class T>
1992void FooT<T>::foo() EXCLUSIVE_LOCKS_REQUIRED(mu_) {
1993 a = 0;
1994}
1995
1996void test() {
1997 int dummy = 0;
1998 Foo myFoo;
1999
2000 myFoo.foo2(); // \
2001 // expected-warning {{calling function 'foo2' requires exclusive lock on 'mu_'}}
2002 myFoo.foo3(&myFoo); // \
2003 // expected-warning {{calling function 'foo3' requires exclusive lock on 'mu_'}}
2004 myFoo.fooT1(dummy); // \
2005 // expected-warning {{calling function 'fooT1' requires exclusive lock on 'mu_'}}
2006
2007 // FIXME: uncomment with template instantiation of attributes patch
2008 // myFoo.fooT2(dummy); // expected warning
2009
2010 fooF1(&myFoo); // \
2011 // expected-warning {{calling function 'fooF1' requires exclusive lock on 'mu_'}}
2012 fooF2(&myFoo); // \
2013 // expected-warning {{calling function 'fooF2' requires exclusive lock on 'mu_'}}
2014 fooF3(&myFoo); // \
2015 // expected-warning {{calling function 'fooF3' requires exclusive lock on 'mu_'}}
2016
2017 myFoo.mu_.Lock();
2018 myFoo.foo2();
2019 myFoo.foo3(&myFoo);
2020 myFoo.fooT1(dummy);
2021
2022 // FIXME: uncomment with template instantiation of attributes patch
2023 // myFoo.fooT2(dummy);
2024
2025 fooF1(&myFoo);
2026 fooF2(&myFoo);
2027 fooF3(&myFoo);
2028 myFoo.mu_.Unlock();
2029
2030 FooT<int> myFooT;
2031 myFooT.foo(); // \
2032 // expected-warning {{calling function 'foo' requires exclusive lock on 'mu_'}}
2033}
2034
DeLesley Hutchins4bda3ec2012-02-16 17:03:24 +00002035} // end namespace FunctionDefinitionTest
2036
2037
2038namespace SelfLockingTest {
2039
2040class LOCKABLE MyLock {
2041public:
2042 int foo GUARDED_BY(this);
2043
2044 void lock() EXCLUSIVE_LOCK_FUNCTION();
2045 void unlock() UNLOCK_FUNCTION();
2046
2047 void doSomething() {
2048 this->lock(); // allow 'this' as a lock expression
2049 foo = 0;
2050 doSomethingElse();
2051 this->unlock();
2052 }
2053
2054 void doSomethingElse() EXCLUSIVE_LOCKS_REQUIRED(this) {
2055 foo = 1;
2056 };
2057
2058 void test() {
2059 foo = 2; // \
2060 // expected-warning {{writing variable 'foo' requires locking 'this' exclusively}}
2061 }
DeLesley Hutchinsc24a2332012-02-16 16:50:43 +00002062};
2063
DeLesley Hutchins2f13bec2012-02-16 17:13:43 +00002064
2065class LOCKABLE MyLock2 {
2066public:
2067 Mutex mu_;
2068 int foo GUARDED_BY(this);
2069
2070 // don't check inside lock and unlock functions
2071 void lock() EXCLUSIVE_LOCK_FUNCTION() { mu_.Lock(); }
2072 void unlock() UNLOCK_FUNCTION() { mu_.Unlock(); }
2073
2074 // don't check inside constructors and destructors
2075 MyLock2() { foo = 1; }
2076 ~MyLock2() { foo = 0; }
2077};
2078
2079
DeLesley Hutchins4bda3ec2012-02-16 17:03:24 +00002080} // end namespace SelfLockingTest
2081
2082
DeLesley Hutchinsd08d5992012-02-25 00:11:55 +00002083namespace InvalidNonstatic {
2084
2085// Forward decl here causes bogus "invalid use of non-static data member"
2086// on reference to mutex_ in guarded_by attribute.
2087class Foo;
2088
2089class Foo {
2090 Mutex* mutex_;
2091
2092 int foo __attribute__((guarded_by(mutex_)));
2093};
2094
2095} // end namespace InvalidNonStatic
2096
DeLesley Hutchins2a35be82012-03-02 22:02:58 +00002097
2098namespace NoReturnTest {
2099
2100bool condition();
2101void fatal() __attribute__((noreturn));
2102
2103Mutex mu_;
2104
2105void test1() {
2106 MutexLock lock(&mu_);
2107 if (condition()) {
2108 fatal();
2109 return;
2110 }
2111}
2112
DeLesley Hutchins2287c5e2012-03-02 22:12:59 +00002113} // end namespace NoReturnTest
2114
2115
2116namespace TestMultiDecl {
2117
2118class Foo {
2119public:
2120 int GUARDED_BY(mu_) a;
2121 int GUARDED_BY(mu_) b, c;
2122
2123 void foo() {
2124 a = 0; // \
2125 // expected-warning {{writing variable 'a' requires locking 'mu_' exclusively}}
2126 b = 0; // \
2127 // expected-warning {{writing variable 'b' requires locking 'mu_' exclusively}}
2128 c = 0; // \
2129 // expected-warning {{writing variable 'c' requires locking 'mu_' exclusively}}
2130 }
2131
2132private:
2133 Mutex mu_;
DeLesley Hutchins2a35be82012-03-02 22:02:58 +00002134};
DeLesley Hutchins2287c5e2012-03-02 22:12:59 +00002135
2136} // end namespace TestMultiDecl
2137
DeLesley Hutchins7ec419a2012-03-02 22:29:50 +00002138
2139namespace WarnNoDecl {
2140
2141class Foo {
2142 void foo(int a); __attribute__(( // \
2143 // expected-warning {{declaration does not declare anything}}
2144 exclusive_locks_required(a))); // \
2145 // expected-warning {{attribute exclusive_locks_required ignored}}
2146};
2147
2148} // end namespace WarnNoDecl
2149
2150
DeLesley Hutchins0d95dfc2012-03-02 23:36:05 +00002151
2152namespace MoreLockExpressions {
2153
2154class Foo {
2155public:
2156 Mutex mu_;
2157 int a GUARDED_BY(mu_);
2158};
2159
2160class Bar {
2161public:
2162 int b;
2163 Foo* f;
2164
2165 Foo& getFoo() { return *f; }
2166 Foo& getFoo2(int c) { return *f; }
2167 Foo& getFoo3(int c, int d) { return *f; }
2168
2169 Foo& getFooey() { return *f; }
2170};
2171
2172Foo& getBarFoo(Bar &bar, int c) { return bar.getFoo2(c); }
2173
2174void test() {
2175 Foo foo;
2176 Foo *fooArray;
2177 Bar bar;
2178 int a;
2179 int b;
2180 int c;
2181
2182 bar.getFoo().mu_.Lock();
2183 bar.getFoo().a = 0;
2184 bar.getFoo().mu_.Unlock();
2185
2186 (bar.getFoo().mu_).Lock(); // test parenthesis
2187 bar.getFoo().a = 0;
2188 (bar.getFoo().mu_).Unlock();
2189
2190 bar.getFoo2(a).mu_.Lock();
2191 bar.getFoo2(a).a = 0;
2192 bar.getFoo2(a).mu_.Unlock();
2193
2194 bar.getFoo3(a, b).mu_.Lock();
2195 bar.getFoo3(a, b).a = 0;
2196 bar.getFoo3(a, b).mu_.Unlock();
2197
2198 getBarFoo(bar, a).mu_.Lock();
2199 getBarFoo(bar, a).a = 0;
2200 getBarFoo(bar, a).mu_.Unlock();
2201
2202 bar.getFoo2(10).mu_.Lock();
2203 bar.getFoo2(10).a = 0;
2204 bar.getFoo2(10).mu_.Unlock();
2205
2206 bar.getFoo2(a + 1).mu_.Lock();
2207 bar.getFoo2(a + 1).a = 0;
2208 bar.getFoo2(a + 1).mu_.Unlock();
2209
2210 (a > 0 ? fooArray[1] : fooArray[b]).mu_.Lock();
2211 (a > 0 ? fooArray[1] : fooArray[b]).a = 0;
2212 (a > 0 ? fooArray[1] : fooArray[b]).mu_.Unlock();
2213
2214 bar.getFoo().mu_.Lock();
2215 bar.getFooey().a = 0; // \
2216 // expected-warning {{writing variable 'a' requires locking 'mu_' exclusively}}
2217 bar.getFoo().mu_.Unlock();
2218
2219 bar.getFoo2(a).mu_.Lock();
2220 bar.getFoo2(b).a = 0; // \
2221 // expected-warning {{writing variable 'a' requires locking 'mu_' exclusively}}
2222 bar.getFoo2(a).mu_.Unlock();
2223
2224 bar.getFoo3(a, b).mu_.Lock();
2225 bar.getFoo3(a, c).a = 0; // \
2226 // expected-warning {{writing variable 'a' requires locking 'mu_' exclusively}}
2227 bar.getFoo3(a, b).mu_.Unlock();
2228
2229 getBarFoo(bar, a).mu_.Lock();
2230 getBarFoo(bar, b).a = 0; // \
2231 // expected-warning {{writing variable 'a' requires locking 'mu_' exclusively}}
2232 getBarFoo(bar, a).mu_.Unlock();
2233
2234 (a > 0 ? fooArray[1] : fooArray[b]).mu_.Lock();
2235 (a > 0 ? fooArray[b] : fooArray[c]).a = 0; // \
2236 // expected-warning {{writing variable 'a' requires locking 'mu_' exclusively}}
2237 (a > 0 ? fooArray[1] : fooArray[b]).mu_.Unlock();
2238}
2239
2240
2241} // end namespace
2242
2243