blob: 20d816a41d8c85b40539bdd3e355655a0adb9aeb [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 {
316 WeirdMethods() {
Richard Smith2e515622012-02-03 04:45:26 +0000317 wmu.Lock(); // expected-note {{mutex acquired here}}
318 } // expected-warning {{mutex 'wmu' is still locked at the end of function}}
Caitlin Sadowskib4d0a962011-08-29 17:12:27 +0000319 ~WeirdMethods() {
Richard Smith2e515622012-02-03 04:45:26 +0000320 wmu.Lock(); // expected-note {{mutex acquired here}}
321 } // expected-warning {{mutex 'wmu' is still locked at the end of function}}
Caitlin Sadowskib4d0a962011-08-29 17:12:27 +0000322 void operator++() {
Richard Smith2e515622012-02-03 04:45:26 +0000323 wmu.Lock(); // expected-note {{mutex acquired here}}
324 } // expected-warning {{mutex 'wmu' is still locked at the end of function}}
Caitlin Sadowskib4d0a962011-08-29 17:12:27 +0000325 operator int*() {
Richard Smith2e515622012-02-03 04:45:26 +0000326 wmu.Lock(); // expected-note {{mutex acquired here}}
Caitlin Sadowskib4d0a962011-08-29 17:12:27 +0000327 return 0;
Richard Smith2e515622012-02-03 04:45:26 +0000328 } // expected-warning {{mutex 'wmu' is still locked at the end of function}}
Caitlin Sadowskib4d0a962011-08-29 17:12:27 +0000329};
330
Caitlin Sadowski05b436e2011-08-29 22:27:51 +0000331//-----------------------------------------------//
332// Errors for guarded by or guarded var variables
333// ----------------------------------------------//
334
335int *pgb_gvar __attribute__((pt_guarded_var));
336int *pgb_var __attribute__((pt_guarded_by(sls_mu)));
337
338class PGBFoo {
339 public:
340 int x;
341 int *pgb_field __attribute__((guarded_by(sls_mu2)))
342 __attribute__((pt_guarded_by(sls_mu)));
343 void testFoo() {
344 pgb_field = &x; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000345 // expected-warning {{writing variable 'pgb_field' requires locking 'sls_mu2' exclusively}}
346 *pgb_field = x; // expected-warning {{reading variable 'pgb_field' requires locking 'sls_mu2'}} \
347 // expected-warning {{writing the value pointed to by 'pgb_field' requires locking 'sls_mu' exclusively}}
348 x = *pgb_field; // expected-warning {{reading variable 'pgb_field' requires locking 'sls_mu2'}} \
349 // expected-warning {{reading the value pointed to by 'pgb_field' requires locking 'sls_mu'}}
350 (*pgb_field)++; // expected-warning {{reading variable 'pgb_field' requires locking 'sls_mu2'}} \
351 // expected-warning {{writing the value pointed to by 'pgb_field' requires locking 'sls_mu' exclusively}}
Caitlin Sadowski05b436e2011-08-29 22:27:51 +0000352 }
353};
354
355class GBFoo {
356 public:
357 int gb_field __attribute__((guarded_by(sls_mu)));
358
359 void testFoo() {
360 gb_field = 0; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000361 // expected-warning {{writing variable 'gb_field' requires locking 'sls_mu' exclusively}}
Caitlin Sadowski05b436e2011-08-29 22:27:51 +0000362 }
Caitlin Sadowskiaf370612011-09-08 18:35:21 +0000363
364 void testNoAnal() __attribute__((no_thread_safety_analysis)) {
365 gb_field = 0;
366 }
Caitlin Sadowski05b436e2011-08-29 22:27:51 +0000367};
368
369GBFoo GlobalGBFoo __attribute__((guarded_by(sls_mu)));
370
371void gb_fun_0() {
372 sls_mu.Lock();
373 int x = *pgb_var;
374 sls_mu.Unlock();
375}
376
377void gb_fun_1() {
378 sls_mu.Lock();
379 *pgb_var = 2;
380 sls_mu.Unlock();
381}
382
383void gb_fun_2() {
384 int x;
385 pgb_var = &x;
386}
387
388void gb_fun_3() {
389 int *x = pgb_var;
390}
391
392void gb_bad_0() {
393 sls_guard_var = 1; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000394 // expected-warning{{writing variable 'sls_guard_var' requires locking any mutex exclusively}}
Caitlin Sadowski05b436e2011-08-29 22:27:51 +0000395}
396
397void gb_bad_1() {
398 int x = sls_guard_var; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000399 // expected-warning{{reading variable 'sls_guard_var' requires locking any mutex}}
Caitlin Sadowski05b436e2011-08-29 22:27:51 +0000400}
401
402void gb_bad_2() {
403 sls_guardby_var = 1; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000404 // expected-warning {{writing variable 'sls_guardby_var' requires locking 'sls_mu' exclusively}}
Caitlin Sadowski05b436e2011-08-29 22:27:51 +0000405}
406
407void gb_bad_3() {
408 int x = sls_guardby_var; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000409 // expected-warning {{reading variable 'sls_guardby_var' requires locking 'sls_mu'}}
Caitlin Sadowski05b436e2011-08-29 22:27:51 +0000410}
411
412void gb_bad_4() {
413 *pgb_gvar = 1; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000414 // expected-warning {{writing the value pointed to by 'pgb_gvar' requires locking any mutex exclusively}}
Caitlin Sadowski05b436e2011-08-29 22:27:51 +0000415}
416
417void gb_bad_5() {
418 int x = *pgb_gvar; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000419 // expected-warning {{reading the value pointed to by 'pgb_gvar' requires locking any mutex}}
Caitlin Sadowski05b436e2011-08-29 22:27:51 +0000420}
421
422void gb_bad_6() {
423 *pgb_var = 1; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000424 // expected-warning {{writing the value pointed to by 'pgb_var' requires locking 'sls_mu' exclusively}}
Caitlin Sadowski05b436e2011-08-29 22:27:51 +0000425}
426
427void gb_bad_7() {
428 int x = *pgb_var; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000429 // expected-warning {{reading the value pointed to by 'pgb_var' requires locking 'sls_mu'}}
Caitlin Sadowski05b436e2011-08-29 22:27:51 +0000430}
431
432void gb_bad_8() {
433 GBFoo G;
434 G.gb_field = 0; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000435 // expected-warning {{writing variable 'gb_field' requires locking 'sls_mu'}}
Caitlin Sadowski05b436e2011-08-29 22:27:51 +0000436}
437
438void gb_bad_9() {
439 sls_guard_var++; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000440 // expected-warning{{writing variable 'sls_guard_var' requires locking any mutex exclusively}}
Caitlin Sadowski05b436e2011-08-29 22:27:51 +0000441 sls_guard_var--; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000442 // expected-warning{{writing variable 'sls_guard_var' requires locking any mutex exclusively}}
Caitlin Sadowski05b436e2011-08-29 22:27:51 +0000443 ++sls_guard_var; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000444 // expected-warning{{writing variable 'sls_guard_var' requires locking any mutex exclusively}}
Caitlin Sadowskia49d1d82011-09-09 16:07:55 +0000445 --sls_guard_var;// \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000446 // expected-warning{{writing variable 'sls_guard_var' requires locking any mutex exclusively}}
Caitlin Sadowski05b436e2011-08-29 22:27:51 +0000447}
Caitlin Sadowskib4d0a962011-08-29 17:12:27 +0000448
Caitlin Sadowskieff98fc2011-09-08 17:42:22 +0000449//-----------------------------------------------//
450// Warnings on variables with late parsed attributes
451// ----------------------------------------------//
452
453class LateFoo {
454public:
455 int a __attribute__((guarded_by(mu)));
456 int b;
457
458 void foo() __attribute__((exclusive_locks_required(mu))) { }
459
460 void test() {
461 a = 0; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000462 // expected-warning{{writing variable 'a' requires locking 'mu' exclusively}}
Caitlin Sadowskieff98fc2011-09-08 17:42:22 +0000463 b = a; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000464 // expected-warning {{reading variable 'a' requires locking 'mu'}}
Caitlin Sadowskieff98fc2011-09-08 17:42:22 +0000465 c = 0; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000466 // expected-warning {{writing variable 'c' requires locking 'mu' exclusively}}
Caitlin Sadowskieff98fc2011-09-08 17:42:22 +0000467 }
468
469 int c __attribute__((guarded_by(mu)));
470
471 Mutex mu;
472};
473
Caitlin Sadowski99107eb2011-09-09 16:21:55 +0000474class LateBar {
475 public:
476 int a_ __attribute__((guarded_by(mu1_)));
477 int b_;
478 int *q __attribute__((pt_guarded_by(mu)));
479 Mutex mu1_;
480 Mutex mu;
481 LateFoo Foo;
482 LateFoo Foo2;
483 LateFoo *FooPointer;
484};
485
486LateBar b1, *b3;
487
488void late_0() {
489 LateFoo FooA;
490 LateFoo FooB;
491 FooA.mu.Lock();
492 FooA.a = 5;
493 FooA.mu.Unlock();
494}
495
496void late_1() {
497 LateBar BarA;
498 BarA.FooPointer->mu.Lock();
499 BarA.FooPointer->a = 2;
500 BarA.FooPointer->mu.Unlock();
501}
502
503void late_bad_0() {
504 LateFoo fooA;
505 LateFoo fooB;
506 fooA.mu.Lock();
507 fooB.a = 5; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000508 // expected-warning{{writing variable 'a' requires locking 'mu' exclusively}}
Caitlin Sadowski99107eb2011-09-09 16:21:55 +0000509 fooA.mu.Unlock();
510}
511
512void late_bad_1() {
513 Mutex mu;
514 mu.Lock();
515 b1.mu1_.Lock();
516 int res = b1.a_ + b3->b_;
517 b3->b_ = *b1.q; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000518 // expected-warning{{reading the value pointed to by 'q' requires locking 'mu'}}
Caitlin Sadowski99107eb2011-09-09 16:21:55 +0000519 b1.mu1_.Unlock();
520 b1.b_ = res;
521 mu.Unlock();
522}
523
524void late_bad_2() {
525 LateBar BarA;
526 BarA.FooPointer->mu.Lock();
527 BarA.Foo.a = 2; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000528 // expected-warning{{writing variable 'a' requires locking 'mu' exclusively}}
Caitlin Sadowski99107eb2011-09-09 16:21:55 +0000529 BarA.FooPointer->mu.Unlock();
530}
531
532void late_bad_3() {
533 LateBar BarA;
534 BarA.Foo.mu.Lock();
535 BarA.FooPointer->a = 2; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000536 // expected-warning{{writing variable 'a' requires locking 'mu' exclusively}}
Caitlin Sadowski99107eb2011-09-09 16:21:55 +0000537 BarA.Foo.mu.Unlock();
538}
539
540void late_bad_4() {
541 LateBar BarA;
542 BarA.Foo.mu.Lock();
543 BarA.Foo2.a = 2; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000544 // expected-warning{{writing variable 'a' requires locking 'mu' exclusively}}
Caitlin Sadowski99107eb2011-09-09 16:21:55 +0000545 BarA.Foo.mu.Unlock();
546}
547
Caitlin Sadowskia53257c2011-09-08 18:19:38 +0000548//-----------------------------------------------//
549// Extra warnings for shared vs. exclusive locks
550// ----------------------------------------------//
551
552void shared_fun_0() {
553 sls_mu.Lock();
554 do {
555 sls_mu.Unlock();
556 sls_mu.Lock();
557 } while (getBool());
558 sls_mu.Unlock();
559}
560
561void shared_fun_1() {
Caitlin Sadowski4e4bc752011-09-15 17:25:19 +0000562 sls_mu.ReaderLock(); // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000563 // expected-warning {{mutex 'sls_mu' is locked exclusively and shared in the same scope}}
Caitlin Sadowskia53257c2011-09-08 18:19:38 +0000564 do {
565 sls_mu.Unlock();
Caitlin Sadowski4e4bc752011-09-15 17:25:19 +0000566 sls_mu.Lock(); // \
567 // expected-note {{the other lock of mutex 'sls_mu' is here}}
Caitlin Sadowskia53257c2011-09-08 18:19:38 +0000568 } while (getBool());
569 sls_mu.Unlock();
570}
571
572void shared_fun_3() {
573 if (getBool())
574 sls_mu.Lock();
575 else
576 sls_mu.Lock();
577 *pgb_var = 1;
578 sls_mu.Unlock();
579}
580
581void shared_fun_4() {
582 if (getBool())
583 sls_mu.ReaderLock();
584 else
585 sls_mu.ReaderLock();
586 int x = sls_guardby_var;
587 sls_mu.Unlock();
588}
589
590void shared_fun_8() {
591 if (getBool())
592 sls_mu.Lock(); // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000593 // expected-warning {{mutex 'sls_mu' is locked exclusively and shared in the same scope}}
Caitlin Sadowskia53257c2011-09-08 18:19:38 +0000594 else
595 sls_mu.ReaderLock(); // \
Caitlin Sadowski8bccabe2011-09-08 21:52:50 +0000596 // expected-note {{the other lock of mutex 'sls_mu' is here}}
Caitlin Sadowskia53257c2011-09-08 18:19:38 +0000597 sls_mu.Unlock();
598}
599
600void shared_bad_0() {
Caitlin Sadowski4e4bc752011-09-15 17:25:19 +0000601 sls_mu.Lock(); // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000602 // expected-warning {{mutex 'sls_mu' is locked exclusively and shared in the same scope}}
Caitlin Sadowskia53257c2011-09-08 18:19:38 +0000603 do {
604 sls_mu.Unlock();
Caitlin Sadowski4e4bc752011-09-15 17:25:19 +0000605 sls_mu.ReaderLock(); // \
606 // expected-note {{the other lock of mutex 'sls_mu' is here}}
Caitlin Sadowskia53257c2011-09-08 18:19:38 +0000607 } while (getBool());
608 sls_mu.Unlock();
609}
610
611void shared_bad_1() {
612 if (getBool())
613 sls_mu.Lock(); // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000614 // expected-warning {{mutex 'sls_mu' is locked exclusively and shared in the same scope}}
Caitlin Sadowskia53257c2011-09-08 18:19:38 +0000615 else
616 sls_mu.ReaderLock(); // \
Caitlin Sadowski8bccabe2011-09-08 21:52:50 +0000617 // expected-note {{the other lock of mutex 'sls_mu' is here}}
Caitlin Sadowskia53257c2011-09-08 18:19:38 +0000618 *pgb_var = 1;
619 sls_mu.Unlock();
620}
621
622void shared_bad_2() {
623 if (getBool())
624 sls_mu.ReaderLock(); // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000625 // expected-warning {{mutex 'sls_mu' is locked exclusively and shared in the same scope}}
Caitlin Sadowskia53257c2011-09-08 18:19:38 +0000626 else
627 sls_mu.Lock(); // \
Caitlin Sadowski8bccabe2011-09-08 21:52:50 +0000628 // expected-note {{the other lock of mutex 'sls_mu' is here}}
Caitlin Sadowskia53257c2011-09-08 18:19:38 +0000629 *pgb_var = 1;
630 sls_mu.Unlock();
631}
Caitlin Sadowski978191e2011-09-08 18:27:31 +0000632
633// FIXME: Add support for functions (not only methods)
634class LRBar {
635 public:
636 void aa_elr_fun() __attribute__((exclusive_locks_required(aa_mu)));
637 void aa_elr_fun_s() __attribute__((shared_locks_required(aa_mu)));
638 void le_fun() __attribute__((locks_excluded(sls_mu)));
639};
640
641class LRFoo {
642 public:
643 void test() __attribute__((exclusive_locks_required(sls_mu)));
644 void testShared() __attribute__((shared_locks_required(sls_mu2)));
645};
646
647void elr_fun() __attribute__((exclusive_locks_required(sls_mu)));
648void elr_fun() {}
649
650LRFoo MyLRFoo;
651LRBar Bar;
652
653void es_fun_0() {
654 aa_mu.Lock();
655 Bar.aa_elr_fun();
656 aa_mu.Unlock();
657}
658
659void es_fun_1() {
660 aa_mu.Lock();
661 Bar.aa_elr_fun_s();
662 aa_mu.Unlock();
663}
664
665void es_fun_2() {
666 aa_mu.ReaderLock();
667 Bar.aa_elr_fun_s();
668 aa_mu.Unlock();
669}
670
671void es_fun_3() {
672 sls_mu.Lock();
673 MyLRFoo.test();
674 sls_mu.Unlock();
675}
676
677void es_fun_4() {
678 sls_mu2.Lock();
679 MyLRFoo.testShared();
680 sls_mu2.Unlock();
681}
682
683void es_fun_5() {
684 sls_mu2.ReaderLock();
685 MyLRFoo.testShared();
686 sls_mu2.Unlock();
687}
688
689void es_fun_6() {
690 Bar.le_fun();
691}
692
693void es_fun_7() {
694 sls_mu.Lock();
695 elr_fun();
696 sls_mu.Unlock();
697}
698
Caitlin Sadowskiaf370612011-09-08 18:35:21 +0000699void es_fun_8() __attribute__((no_thread_safety_analysis));
700
701void es_fun_8() {
702 Bar.aa_elr_fun_s();
703}
704
Caitlin Sadowskicb967512011-09-15 17:43:08 +0000705void es_fun_9() __attribute__((shared_locks_required(aa_mu)));
706void es_fun_9() {
707 Bar.aa_elr_fun_s();
708}
709
710void es_fun_10() __attribute__((exclusive_locks_required(aa_mu)));
711void es_fun_10() {
712 Bar.aa_elr_fun_s();
713}
714
Caitlin Sadowski978191e2011-09-08 18:27:31 +0000715void es_bad_0() {
716 Bar.aa_elr_fun(); // \
Caitlin Sadowski8bccabe2011-09-08 21:52:50 +0000717 // expected-warning {{calling function 'aa_elr_fun' requires exclusive lock on 'aa_mu'}}
Caitlin Sadowski978191e2011-09-08 18:27:31 +0000718}
719
720void es_bad_1() {
721 aa_mu.ReaderLock();
722 Bar.aa_elr_fun(); // \
Caitlin Sadowski8bccabe2011-09-08 21:52:50 +0000723 // expected-warning {{calling function 'aa_elr_fun' requires exclusive lock on 'aa_mu'}}
Caitlin Sadowski978191e2011-09-08 18:27:31 +0000724 aa_mu.Unlock();
725}
726
727void es_bad_2() {
728 Bar.aa_elr_fun_s(); // \
Caitlin Sadowski8bccabe2011-09-08 21:52:50 +0000729 // expected-warning {{calling function 'aa_elr_fun_s' requires shared lock on 'aa_mu'}}
Caitlin Sadowski978191e2011-09-08 18:27:31 +0000730}
731
732void es_bad_3() {
733 MyLRFoo.test(); // \
Caitlin Sadowski8bccabe2011-09-08 21:52:50 +0000734 // expected-warning {{calling function 'test' requires exclusive lock on 'sls_mu'}}
Caitlin Sadowski978191e2011-09-08 18:27:31 +0000735}
736
737void es_bad_4() {
738 MyLRFoo.testShared(); // \
Caitlin Sadowski8bccabe2011-09-08 21:52:50 +0000739 // expected-warning {{calling function 'testShared' requires shared lock on 'sls_mu2'}}
Caitlin Sadowski978191e2011-09-08 18:27:31 +0000740}
741
742void es_bad_5() {
743 sls_mu.ReaderLock();
744 MyLRFoo.test(); // \
Caitlin Sadowski8bccabe2011-09-08 21:52:50 +0000745 // expected-warning {{calling function 'test' requires exclusive lock on 'sls_mu'}}
Caitlin Sadowski978191e2011-09-08 18:27:31 +0000746 sls_mu.Unlock();
747}
748
749void es_bad_6() {
750 sls_mu.Lock();
751 Bar.le_fun(); // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000752 // expected-warning {{cannot call function 'le_fun' while mutex 'sls_mu' is locked}}
Caitlin Sadowski978191e2011-09-08 18:27:31 +0000753 sls_mu.Unlock();
754}
755
756void es_bad_7() {
757 sls_mu.ReaderLock();
758 Bar.le_fun(); // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000759 // expected-warning {{cannot call function 'le_fun' while mutex 'sls_mu' is locked}}
Caitlin Sadowski978191e2011-09-08 18:27:31 +0000760 sls_mu.Unlock();
761}
Caitlin Sadowski194418f2011-09-14 20:00:24 +0000762
DeLesley Hutchins81216392011-10-17 21:38:02 +0000763
Caitlin Sadowski194418f2011-09-14 20:00:24 +0000764//-----------------------------------------------//
765// Unparseable lock expressions
766// ----------------------------------------------//
767
768Mutex UPmu;
769// FIXME: add support for lock expressions involving arrays.
770Mutex mua[5];
771
DeLesley Hutchinsf1ac6372011-10-21 18:10:14 +0000772int x __attribute__((guarded_by(UPmu = sls_mu)));
773int y __attribute__((guarded_by(mua[0])));
Caitlin Sadowski194418f2011-09-14 20:00:24 +0000774
775
776void testUnparse() {
DeLesley Hutchinsf1ac6372011-10-21 18:10:14 +0000777 x = 5; // \
778 // expected-warning{{cannot resolve lock expression}}
779 y = 5; // \
780 // expected-warning{{cannot resolve lock expression}}
Caitlin Sadowski194418f2011-09-14 20:00:24 +0000781}
782
783void testUnparse2() {
784 mua[0].Lock(); // \
DeLesley Hutchinsf1ac6372011-10-21 18:10:14 +0000785 // expected-warning{{cannot resolve lock expression}}
Caitlin Sadowski194418f2011-09-14 20:00:24 +0000786 (&(mua[0]) + 4)->Lock(); // \
DeLesley Hutchinsf1ac6372011-10-21 18:10:14 +0000787 // expected-warning{{cannot resolve lock expression}}
Caitlin Sadowski194418f2011-09-14 20:00:24 +0000788}
789
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +0000790
791//----------------------------------------------------------------------------//
792// The following test cases are ported from the gcc thread safety implementation
793// They are each wrapped inside a namespace with the test number of the gcc test
794//
795// FIXME: add all the gcc tests, once this analysis passes them.
796//----------------------------------------------------------------------------//
797
798//-----------------------------------------//
799// Good testcases (no errors)
800//-----------------------------------------//
801
802namespace thread_annot_lock_20 {
803class Bar {
804 public:
805 static int func1() EXCLUSIVE_LOCKS_REQUIRED(mu1_);
806 static int b_ GUARDED_BY(mu1_);
807 static Mutex mu1_;
808 static int a_ GUARDED_BY(mu1_);
809};
810
811Bar b1;
812
813int Bar::func1()
814{
815 int res = 5;
816
817 if (a_ == 4)
818 res = b_;
819 return res;
820}
821} // end namespace thread_annot_lock_20
822
823namespace thread_annot_lock_22 {
824// Test various usage of GUARDED_BY and PT_GUARDED_BY annotations, especially
825// uses in class definitions.
826Mutex mu;
827
828class Bar {
829 public:
830 int a_ GUARDED_BY(mu1_);
831 int b_;
832 int *q PT_GUARDED_BY(mu);
833 Mutex mu1_ ACQUIRED_AFTER(mu);
834};
835
836Bar b1, *b3;
837int *p GUARDED_BY(mu) PT_GUARDED_BY(mu);
838int res GUARDED_BY(mu) = 5;
839
840int func(int i)
841{
842 int x;
843 mu.Lock();
844 b1.mu1_.Lock();
845 res = b1.a_ + b3->b_;
846 *p = i;
847 b1.a_ = res + b3->b_;
848 b3->b_ = *b1.q;
849 b1.mu1_.Unlock();
850 b1.b_ = res;
851 x = res;
852 mu.Unlock();
853 return x;
854}
855} // end namespace thread_annot_lock_22
856
857namespace thread_annot_lock_27_modified {
858// test lock annotations applied to function definitions
859// Modified: applied annotations only to function declarations
860Mutex mu1;
861Mutex mu2 ACQUIRED_AFTER(mu1);
862
863class Foo {
864 public:
865 int method1(int i) SHARED_LOCKS_REQUIRED(mu2) EXCLUSIVE_LOCKS_REQUIRED(mu1);
866};
867
868int Foo::method1(int i) {
869 return i;
870}
871
872
873int foo(int i) EXCLUSIVE_LOCKS_REQUIRED(mu2) SHARED_LOCKS_REQUIRED(mu1);
874int foo(int i) {
875 return i;
876}
877
878static int bar(int i) EXCLUSIVE_LOCKS_REQUIRED(mu1);
879static int bar(int i) {
880 return i;
881}
882
883void main() {
884 Foo a;
885
886 mu1.Lock();
887 mu2.Lock();
888 a.method1(1);
889 foo(2);
890 mu2.Unlock();
891 bar(3);
892 mu1.Unlock();
893}
894} // end namespace thread_annot_lock_27_modified
895
896
897namespace thread_annot_lock_38 {
898// Test the case where a template member function is annotated with lock
899// attributes in a non-template class.
900class Foo {
901 public:
902 void func1(int y) LOCKS_EXCLUDED(mu_);
903 template <typename T> void func2(T x) LOCKS_EXCLUDED(mu_);
904 private:
905 Mutex mu_;
906};
907
908Foo *foo;
909
910void main()
911{
912 foo->func1(5);
913 foo->func2(5);
914}
915} // end namespace thread_annot_lock_38
916
917namespace thread_annot_lock_43 {
918// Tests lock canonicalization
919class Foo {
920 public:
921 Mutex *mu_;
922};
923
924class FooBar {
925 public:
926 Foo *foo_;
927 int GetA() EXCLUSIVE_LOCKS_REQUIRED(foo_->mu_) { return a_; }
928 int a_ GUARDED_BY(foo_->mu_);
929};
930
931FooBar *fb;
932
933void main()
934{
935 int x;
936 fb->foo_->mu_->Lock();
937 x = fb->GetA();
938 fb->foo_->mu_->Unlock();
939}
940} // end namespace thread_annot_lock_43
941
942namespace thread_annot_lock_49 {
943// Test the support for use of lock expression in the annotations
944class Foo {
945 public:
946 Mutex foo_mu_;
947};
948
949class Bar {
950 private:
951 Foo *foo;
952 Mutex bar_mu_ ACQUIRED_AFTER(foo->foo_mu_);
953
954 public:
955 void Test1() {
956 foo->foo_mu_.Lock();
957 bar_mu_.Lock();
958 bar_mu_.Unlock();
959 foo->foo_mu_.Unlock();
960 }
961};
962
963void main() {
964 Bar bar;
965 bar.Test1();
966}
967} // end namespace thread_annot_lock_49
968
969namespace thread_annot_lock_61_modified {
970 // Modified to fix the compiler errors
971 // Test the fix for a bug introduced by the support of pass-by-reference
972 // paramters.
973 struct Foo { Foo &operator<< (bool) {return *this;} };
974 Foo &getFoo();
975 struct Bar { Foo &func () {return getFoo();} };
976 struct Bas { void operator& (Foo &) {} };
977 void mumble()
978 {
979 Bas() & Bar().func() << "" << "";
980 Bas() & Bar().func() << "";
981 }
982} // end namespace thread_annot_lock_61_modified
983
984
985namespace thread_annot_lock_65 {
986// Test the fix for a bug in the support of allowing reader locks for
987// non-const, non-modifying overload functions. (We didn't handle the builtin
988// properly.)
989enum MyFlags {
990 Zero,
991 One,
992 Two,
993 Three,
994 Four,
995 Five,
996 Six,
997 Seven,
998 Eight,
999 Nine
1000};
1001
1002inline MyFlags
1003operator|(MyFlags a, MyFlags b)
1004{
1005 return MyFlags(static_cast<int>(a) | static_cast<int>(b));
1006}
1007
1008inline MyFlags&
1009operator|=(MyFlags& a, MyFlags b)
1010{
1011 return a = a | b;
1012}
1013} // end namespace thread_annot_lock_65
1014
1015namespace thread_annot_lock_66_modified {
1016// Modified: Moved annotation to function defn
1017// Test annotations on out-of-line definitions of member functions where the
1018// annotations refer to locks that are also data members in the class.
1019Mutex mu;
1020
1021class Foo {
1022 public:
1023 int method1(int i) SHARED_LOCKS_REQUIRED(mu1, mu, mu2);
1024 int data GUARDED_BY(mu1);
1025 Mutex *mu1;
1026 Mutex *mu2;
1027};
1028
1029int Foo::method1(int i)
1030{
1031 return data + i;
1032}
1033
1034void main()
1035{
1036 Foo a;
1037
1038 a.mu2->Lock();
1039 a.mu1->Lock();
1040 mu.Lock();
1041 a.method1(1);
1042 mu.Unlock();
1043 a.mu1->Unlock();
1044 a.mu2->Unlock();
1045}
1046} // end namespace thread_annot_lock_66_modified
1047
1048namespace thread_annot_lock_68_modified {
1049// Test a fix to a bug in the delayed name binding with nested template
1050// instantiation. We use a stack to make sure a name is not resolved to an
1051// inner context.
1052template <typename T>
1053class Bar {
1054 Mutex mu_;
1055};
1056
1057template <typename T>
1058class Foo {
1059 public:
1060 void func(T x) {
1061 mu_.Lock();
DeLesley Hutchins23323e02012-01-20 22:50:54 +00001062 count_ = x;
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001063 mu_.Unlock();
1064 }
1065
1066 private:
DeLesley Hutchins23323e02012-01-20 22:50:54 +00001067 T count_ GUARDED_BY(mu_);
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001068 Bar<T> bar_;
1069 Mutex mu_;
1070};
1071
1072void main()
1073{
1074 Foo<int> *foo;
1075 foo->func(5);
1076}
1077} // end namespace thread_annot_lock_68_modified
1078
1079namespace thread_annot_lock_30_modified {
1080// Test delay parsing of lock attribute arguments with nested classes.
1081// Modified: trylocks replaced with exclusive_lock_fun
1082int a = 0;
1083
1084class Bar {
1085 struct Foo;
1086
1087 public:
1088 void MyLock() EXCLUSIVE_LOCK_FUNCTION(mu);
1089
1090 int func() {
1091 MyLock();
1092// if (foo == 0) {
1093// return 0;
1094// }
1095 a = 5;
1096 mu.Unlock();
1097 return 1;
1098 }
1099
1100 class FooBar {
1101 int x;
1102 int y;
1103 };
1104
1105 private:
1106 Mutex mu;
1107};
1108
1109Bar *bar;
1110
1111void main()
1112{
1113 bar->func();
1114}
1115} // end namespace thread_annot_lock_30_modified
1116
1117namespace thread_annot_lock_47 {
1118// Test the support for annotations on virtual functions.
1119// This is a good test case. (i.e. There should be no warning emitted by the
1120// compiler.)
1121class Base {
1122 public:
1123 virtual void func1() EXCLUSIVE_LOCKS_REQUIRED(mu_);
1124 virtual void func2() LOCKS_EXCLUDED(mu_);
1125 Mutex mu_;
1126};
1127
1128class Child : public Base {
1129 public:
1130 virtual void func1() EXCLUSIVE_LOCKS_REQUIRED(mu_);
1131 virtual void func2() LOCKS_EXCLUDED(mu_);
1132};
1133
1134void main() {
1135 Child *c;
1136 Base *b = c;
1137
1138 b->mu_.Lock();
1139 b->func1();
1140 b->mu_.Unlock();
1141 b->func2();
1142
1143 c->mu_.Lock();
1144 c->func1();
1145 c->mu_.Unlock();
1146 c->func2();
1147}
1148} // end namespace thread_annot_lock_47
1149
1150//-----------------------------------------//
1151// Tests which produce errors
1152//-----------------------------------------//
1153
1154namespace thread_annot_lock_13 {
1155Mutex mu1;
1156Mutex mu2;
1157
1158int g GUARDED_BY(mu1);
1159int w GUARDED_BY(mu2);
1160
1161class Foo {
1162 public:
1163 void bar() LOCKS_EXCLUDED(mu_, mu1);
1164 int foo() SHARED_LOCKS_REQUIRED(mu_) EXCLUSIVE_LOCKS_REQUIRED(mu2);
1165
1166 private:
1167 int a_ GUARDED_BY(mu_);
1168 public:
1169 Mutex mu_ ACQUIRED_AFTER(mu1);
1170};
1171
1172int Foo::foo()
1173{
1174 int res;
1175 w = 5.2;
1176 res = a_ + 5;
1177 return res;
1178}
1179
1180void Foo::bar()
1181{
1182 int x;
1183 mu_.Lock();
1184 x = foo(); // expected-warning {{calling function 'foo' requires exclusive lock on 'mu2'}}
1185 a_ = x + 1;
1186 mu_.Unlock();
1187 if (x > 5) {
1188 mu1.Lock();
1189 g = 2.3;
1190 mu1.Unlock();
1191 }
1192}
1193
1194void main()
1195{
1196 Foo f1, *f2;
1197 f1.mu_.Lock();
Caitlin Sadowski74558b42011-09-15 18:13:32 +00001198 f1.bar(); // expected-warning {{cannot call function 'bar' while mutex 'mu_' is locked}}
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001199 mu2.Lock();
1200 f1.foo();
1201 mu2.Unlock();
1202 f1.mu_.Unlock();
1203 f2->mu_.Lock();
Caitlin Sadowski74558b42011-09-15 18:13:32 +00001204 f2->bar(); // expected-warning {{cannot call function 'bar' while mutex 'mu_' is locked}}
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001205 f2->mu_.Unlock();
1206 mu2.Lock();
1207 w = 2.5;
1208 mu2.Unlock();
1209}
1210} // end namespace thread_annot_lock_13
1211
1212namespace thread_annot_lock_18_modified {
1213// Modified: Trylocks removed
1214// Test the ability to distnguish between the same lock field of
1215// different objects of a class.
1216 class Bar {
1217 public:
1218 bool MyLock() EXCLUSIVE_LOCK_FUNCTION(mu1_);
1219 void MyUnlock() UNLOCK_FUNCTION(mu1_);
1220 int a_ GUARDED_BY(mu1_);
1221
1222 private:
1223 Mutex mu1_;
1224};
1225
1226Bar *b1, *b2;
1227
1228void func()
1229{
1230 b1->MyLock();
1231 b1->a_ = 5;
Caitlin Sadowski74558b42011-09-15 18:13:32 +00001232 b2->a_ = 3; // expected-warning {{writing variable 'a_' requires locking 'mu1_' exclusively}}
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001233 b2->MyLock();
1234 b2->MyUnlock();
1235 b1->MyUnlock();
1236}
1237} // end namespace thread_annot_lock_18_modified
1238
1239namespace thread_annot_lock_21 {
1240// Test various usage of GUARDED_BY and PT_GUARDED_BY annotations, especially
1241// uses in class definitions.
1242Mutex mu;
1243
1244class Bar {
1245 public:
1246 int a_ GUARDED_BY(mu1_);
1247 int b_;
1248 int *q PT_GUARDED_BY(mu);
1249 Mutex mu1_ ACQUIRED_AFTER(mu);
1250};
1251
1252Bar b1, *b3;
1253int *p GUARDED_BY(mu) PT_GUARDED_BY(mu);
1254
1255int res GUARDED_BY(mu) = 5;
1256
1257int func(int i)
1258{
1259 int x;
1260 b3->mu1_.Lock();
Caitlin Sadowski74558b42011-09-15 18:13:32 +00001261 res = b1.a_ + b3->b_; // expected-warning {{reading variable 'a_' requires locking 'mu1_'}} \
1262 // expected-warning {{writing variable 'res' requires locking 'mu' exclusively}}
1263 *p = i; // expected-warning {{reading variable 'p' requires locking 'mu'}} \
1264 // expected-warning {{writing the value pointed to by 'p' requires locking 'mu' exclusively}}
1265 b1.a_ = res + b3->b_; // expected-warning {{reading variable 'res' requires locking 'mu'}} \
1266 // expected-warning {{writing variable 'a_' requires locking 'mu1_' exclusively}}
1267 b3->b_ = *b1.q; // expected-warning {{reading the value pointed to by 'q' requires locking 'mu'}}
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001268 b3->mu1_.Unlock();
Caitlin Sadowski74558b42011-09-15 18:13:32 +00001269 b1.b_ = res; // expected-warning {{reading variable 'res' requires locking 'mu'}}
1270 x = res; // expected-warning {{reading variable 'res' requires locking 'mu'}}
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001271 return x;
1272}
1273} // end namespace thread_annot_lock_21
1274
1275namespace thread_annot_lock_35_modified {
1276// Test the analyzer's ability to distinguish the lock field of different
1277// objects.
1278class Foo {
1279 private:
1280 Mutex lock_;
1281 int a_ GUARDED_BY(lock_);
1282
1283 public:
1284 void Func(Foo* child) LOCKS_EXCLUDED(lock_) {
1285 Foo *new_foo = new Foo;
1286
1287 lock_.Lock();
1288
1289 child->Func(new_foo); // There shouldn't be any warning here as the
1290 // acquired lock is not in child.
1291 child->bar(7); // expected-warning {{calling function 'bar' requires exclusive lock on 'lock_'}}
Caitlin Sadowski74558b42011-09-15 18:13:32 +00001292 child->a_ = 5; // expected-warning {{writing variable 'a_' requires locking 'lock_' exclusively}}
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001293 lock_.Unlock();
1294 }
1295
1296 void bar(int y) EXCLUSIVE_LOCKS_REQUIRED(lock_) {
1297 a_ = y;
1298 }
1299};
1300
1301Foo *x;
1302
1303void main() {
1304 Foo *child = new Foo;
1305 x->Func(child);
1306}
1307} // end namespace thread_annot_lock_35_modified
1308
1309namespace thread_annot_lock_36_modified {
1310// Modified to move the annotations to function defns.
1311// Test the analyzer's ability to distinguish the lock field of different
1312// objects
1313class Foo {
1314 private:
1315 Mutex lock_;
1316 int a_ GUARDED_BY(lock_);
1317
1318 public:
1319 void Func(Foo* child) LOCKS_EXCLUDED(lock_);
1320 void bar(int y) EXCLUSIVE_LOCKS_REQUIRED(lock_);
1321};
1322
1323void Foo::Func(Foo* child) {
1324 Foo *new_foo = new Foo;
1325
1326 lock_.Lock();
1327
1328 child->lock_.Lock();
Caitlin Sadowski74558b42011-09-15 18:13:32 +00001329 child->Func(new_foo); // expected-warning {{cannot call function 'Func' while mutex 'lock_' is locked}}
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001330 child->bar(7);
1331 child->a_ = 5;
1332 child->lock_.Unlock();
1333
1334 lock_.Unlock();
1335}
1336
1337void Foo::bar(int y) {
1338 a_ = y;
1339}
1340
1341
1342Foo *x;
1343
1344void main() {
1345 Foo *child = new Foo;
1346 x->Func(child);
1347}
1348} // end namespace thread_annot_lock_36_modified
1349
1350
1351namespace thread_annot_lock_42 {
1352// Test support of multiple lock attributes of the same kind on a decl.
1353class Foo {
1354 private:
1355 Mutex mu1, mu2, mu3;
1356 int x GUARDED_BY(mu1) GUARDED_BY(mu2);
1357 int y GUARDED_BY(mu2);
1358
1359 void f2() LOCKS_EXCLUDED(mu1) LOCKS_EXCLUDED(mu2) LOCKS_EXCLUDED(mu3) {
1360 mu2.Lock();
1361 y = 2;
1362 mu2.Unlock();
1363 }
1364
1365 public:
1366 void f1() EXCLUSIVE_LOCKS_REQUIRED(mu2) EXCLUSIVE_LOCKS_REQUIRED(mu1) {
1367 x = 5;
Caitlin Sadowski74558b42011-09-15 18:13:32 +00001368 f2(); // expected-warning {{cannot call function 'f2' while mutex 'mu1' is locked}} \
1369 // expected-warning {{cannot call function 'f2' while mutex 'mu2' is locked}}
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001370 }
1371};
1372
1373Foo *foo;
1374
1375void func()
1376{
1377 foo->f1(); // expected-warning {{calling function 'f1' requires exclusive lock on 'mu2'}} \
1378 // expected-warning {{calling function 'f1' requires exclusive lock on 'mu1'}}
1379}
1380} // end namespace thread_annot_lock_42
1381
1382namespace thread_annot_lock_46 {
1383// Test the support for annotations on virtual functions.
1384class Base {
1385 public:
1386 virtual void func1() EXCLUSIVE_LOCKS_REQUIRED(mu_);
1387 virtual void func2() LOCKS_EXCLUDED(mu_);
1388 Mutex mu_;
1389};
1390
1391class Child : public Base {
1392 public:
1393 virtual void func1() EXCLUSIVE_LOCKS_REQUIRED(mu_);
1394 virtual void func2() LOCKS_EXCLUDED(mu_);
1395};
1396
1397void main() {
1398 Child *c;
1399 Base *b = c;
1400
1401 b->func1(); // expected-warning {{calling function 'func1' requires exclusive lock on 'mu_'}}
1402 b->mu_.Lock();
Caitlin Sadowski74558b42011-09-15 18:13:32 +00001403 b->func2(); // expected-warning {{cannot call function 'func2' while mutex 'mu_' is locked}}
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001404 b->mu_.Unlock();
1405
1406 c->func1(); // expected-warning {{calling function 'func1' requires exclusive lock on 'mu_'}}
1407 c->mu_.Lock();
Caitlin Sadowski74558b42011-09-15 18:13:32 +00001408 c->func2(); // expected-warning {{cannot call function 'func2' while mutex 'mu_' is locked}}
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001409 c->mu_.Unlock();
1410}
1411} // end namespace thread_annot_lock_46
1412
1413namespace thread_annot_lock_67_modified {
1414// Modified: attributes on definitions moved to declarations
1415// Test annotations on out-of-line definitions of member functions where the
1416// annotations refer to locks that are also data members in the class.
1417Mutex mu;
1418Mutex mu3;
1419
1420class Foo {
1421 public:
1422 int method1(int i) SHARED_LOCKS_REQUIRED(mu1, mu, mu2, mu3);
1423 int data GUARDED_BY(mu1);
1424 Mutex *mu1;
1425 Mutex *mu2;
1426};
1427
1428int Foo::method1(int i) {
1429 return data + i;
1430}
1431
1432void main()
1433{
1434 Foo a;
1435 a.method1(1); // expected-warning {{calling function 'method1' requires shared lock on 'mu1'}} \
1436 // expected-warning {{calling function 'method1' requires shared lock on 'mu'}} \
1437 // expected-warning {{calling function 'method1' requires shared lock on 'mu2'}} \
1438 // expected-warning {{calling function 'method1' requires shared lock on 'mu3'}}
1439}
1440} // end namespace thread_annot_lock_67_modified
1441
1442
DeLesley Hutchins81216392011-10-17 21:38:02 +00001443namespace substitution_test {
1444 class MyData {
1445 public:
1446 Mutex mu;
1447
1448 void lockData() __attribute__((exclusive_lock_function(mu))) { }
1449 void unlockData() __attribute__((unlock_function(mu))) { }
1450
1451 void doSomething() __attribute__((exclusive_locks_required(mu))) { }
1452 };
1453
1454
1455 class DataLocker {
1456 public:
1457 void lockData (MyData *d) __attribute__((exclusive_lock_function(d->mu))) { }
1458 void unlockData(MyData *d) __attribute__((unlock_function(d->mu))) { }
1459 };
1460
1461
1462 class Foo {
1463 public:
1464 void foo(MyData* d) __attribute__((exclusive_locks_required(d->mu))) { }
1465
1466 void bar1(MyData* d) {
1467 d->lockData();
1468 foo(d);
1469 d->unlockData();
1470 }
1471
1472 void bar2(MyData* d) {
1473 DataLocker dlr;
1474 dlr.lockData(d);
1475 foo(d);
1476 dlr.unlockData(d);
1477 }
1478
1479 void bar3(MyData* d1, MyData* d2) {
1480 DataLocker dlr;
Richard Smith2e515622012-02-03 04:45:26 +00001481 dlr.lockData(d1); // expected-note {{mutex acquired here}}
DeLesley Hutchins81216392011-10-17 21:38:02 +00001482 dlr.unlockData(d2); // \
1483 // expected-warning {{unlocking 'mu' that was not locked}}
Richard Smith2e515622012-02-03 04:45:26 +00001484 } // expected-warning {{mutex 'mu' is still locked at the end of function}}
DeLesley Hutchins81216392011-10-17 21:38:02 +00001485
1486 void bar4(MyData* d1, MyData* d2) {
1487 DataLocker dlr;
1488 dlr.lockData(d1);
1489 foo(d2); // \
1490 // expected-warning {{calling function 'foo' requires exclusive lock on 'mu'}}
1491 dlr.unlockData(d1);
1492 }
1493 };
1494} // end namespace substituation_test
1495
DeLesley Hutchinse0eaa852011-10-21 18:06:53 +00001496
DeLesley Hutchinsf1ac6372011-10-21 18:10:14 +00001497
DeLesley Hutchinse0eaa852011-10-21 18:06:53 +00001498namespace constructor_destructor_tests {
1499 Mutex fooMu;
1500 int myVar GUARDED_BY(fooMu);
1501
1502 class Foo {
1503 public:
1504 Foo() __attribute__((exclusive_lock_function(fooMu))) { }
1505 ~Foo() __attribute__((unlock_function(fooMu))) { }
1506 };
1507
1508 void fooTest() {
DeLesley Hutchins6db51f72011-10-21 20:51:27 +00001509 Foo foo;
DeLesley Hutchinse0eaa852011-10-21 18:06:53 +00001510 myVar = 0;
1511 }
1512}
1513
DeLesley Hutchinsf1ac6372011-10-21 18:10:14 +00001514
1515namespace invalid_lock_expression_test {
1516
1517class LOCKABLE MyLockable {
1518public:
1519 MyLockable() __attribute__((exclusive_lock_function)) { }
DeLesley Hutchins6db51f72011-10-21 20:51:27 +00001520 ~MyLockable() { }
DeLesley Hutchinsf1ac6372011-10-21 18:10:14 +00001521};
1522
1523// create an empty lock expression
1524void foo() {
1525 MyLockable lock; // \
1526 // expected-warning {{cannot resolve lock expression}}
1527}
1528
1529} // end namespace invalid_lock_expression_test
1530
Richard Smith97f9fe02011-10-25 00:41:24 +00001531namespace template_member_test {
DeLesley Hutchinsf1ac6372011-10-21 18:10:14 +00001532
Richard Smith97f9fe02011-10-25 00:41:24 +00001533 struct S { int n; };
1534 struct T {
1535 Mutex m;
1536 S *s GUARDED_BY(this->m);
1537 };
Richard Smitha01c7112011-10-25 06:33:21 +00001538 Mutex m;
1539 struct U {
1540 union {
1541 int n;
1542 };
1543 } *u GUARDED_BY(m);
Richard Smith97f9fe02011-10-25 00:41:24 +00001544
1545 template<typename U>
1546 struct IndirectLock {
1547 int DoNaughtyThings(T *t) {
Richard Smitha01c7112011-10-25 06:33:21 +00001548 u->n = 0; // expected-warning {{reading variable 'u' requires locking 'm'}}
Richard Smith97f9fe02011-10-25 00:41:24 +00001549 return t->s->n; // expected-warning {{reading variable 's' requires locking 'm'}}
1550 }
1551 };
1552
Richard Smithf11e9232011-10-25 01:05:41 +00001553 template struct IndirectLock<int>; // expected-note {{here}}
Richard Smith97f9fe02011-10-25 00:41:24 +00001554
Richard Smith601d2ee2011-10-26 06:15:36 +00001555 struct V {
1556 void f(int);
1557 void f(double);
1558
1559 Mutex m;
1560 V *p GUARDED_BY(this->m);
1561 };
1562 template<typename U> struct W {
1563 V v;
1564 void f(U u) {
1565 v.p->f(u); // expected-warning {{reading variable 'p' requires locking 'm'}}
1566 }
1567 };
1568 template struct W<int>; // expected-note {{here}}
1569
Richard Smith97f9fe02011-10-25 00:41:24 +00001570}
DeLesley Hutchins1fa3c062011-12-08 20:23:06 +00001571
1572namespace test_scoped_lockable {
1573
1574struct TestScopedLockable {
1575 Mutex mu1;
1576 Mutex mu2;
1577 int a __attribute__((guarded_by(mu1)));
1578 int b __attribute__((guarded_by(mu2)));
1579
1580 bool getBool();
1581
1582 void foo1() {
1583 MutexLock mulock(&mu1);
1584 a = 5;
1585 }
1586
1587 void foo2() {
1588 ReaderMutexLock mulock1(&mu1);
1589 if (getBool()) {
1590 MutexLock mulock2a(&mu2);
1591 b = a + 1;
1592 }
1593 else {
1594 MutexLock mulock2b(&mu2);
1595 b = a + 2;
1596 }
1597 }
1598
1599 void foo3() {
1600 MutexLock mulock_a(&mu1);
1601 MutexLock mulock_b(&mu1); // \
1602 // expected-warning {{locking 'mu1' that is already locked}}
1603 } // expected-warning {{unlocking 'mu1' that was not locked}}
1604
1605 void foo4() {
1606 MutexLock mulock1(&mu1), mulock2(&mu2);
1607 a = b+1;
1608 b = a+1;
1609 }
1610};
1611
1612} // end namespace test_scoped_lockable
1613
1614
DeLesley Hutchinsdf497822011-12-29 00:56:48 +00001615namespace FunctionAttrTest {
1616
1617class Foo {
1618public:
1619 Mutex mu_;
1620 int a GUARDED_BY(mu_);
1621};
1622
1623Foo fooObj;
1624
1625void foo() EXCLUSIVE_LOCKS_REQUIRED(fooObj.mu_);
1626
1627void bar() {
1628 foo(); // expected-warning {{calling function 'foo' requires exclusive lock on 'mu_'}}
1629 fooObj.mu_.Lock();
1630 foo();
1631 fooObj.mu_.Unlock();
1632}
1633
1634}; // end namespace FunctionAttrTest
1635
1636
DeLesley Hutchinsb4fa4182012-01-06 19:16:50 +00001637struct TestTryLock {
1638 Mutex mu;
1639 int a GUARDED_BY(mu);
1640 bool cond;
1641
1642 void foo1() {
1643 if (mu.TryLock()) {
1644 a = 1;
1645 mu.Unlock();
1646 }
1647 }
1648
1649 void foo2() {
1650 if (!mu.TryLock()) return;
1651 a = 2;
1652 mu.Unlock();
1653 }
1654
1655 void foo3() {
1656 bool b = mu.TryLock();
1657 if (b) {
1658 a = 3;
1659 mu.Unlock();
1660 }
1661 }
1662
1663 void foo4() {
1664 bool b = mu.TryLock();
1665 if (!b) return;
1666 a = 4;
1667 mu.Unlock();
1668 }
1669
1670 void foo5() {
1671 while (mu.TryLock()) {
1672 a = a + 1;
1673 mu.Unlock();
1674 }
1675 }
1676
1677 void foo6() {
1678 bool b = mu.TryLock();
1679 b = !b;
1680 if (b) return;
1681 a = 6;
1682 mu.Unlock();
1683 }
1684
1685 void foo7() {
1686 bool b1 = mu.TryLock();
1687 bool b2 = !b1;
1688 bool b3 = !b2;
1689 if (b3) {
1690 a = 7;
1691 mu.Unlock();
1692 }
1693 }
1694
1695 // Test use-def chains: join points
1696 void foo8() {
1697 bool b = mu.TryLock();
1698 bool b2 = b;
1699 if (cond)
1700 b = true;
1701 if (b) { // b should be unknown at this point, becuase of the join point
1702 a = 8; // expected-warning {{writing variable 'a' requires locking 'mu' exclusively}}
1703 }
1704 if (b2) { // b2 should be known at this point.
1705 a = 8;
1706 mu.Unlock();
1707 }
1708 }
1709
1710 // Test use-def-chains: back edges
1711 void foo9() {
1712 bool b = mu.TryLock();
1713
1714 for (int i = 0; i < 10; ++i);
1715
1716 if (b) { // b is still known, because the loop doesn't alter it
1717 a = 9;
1718 mu.Unlock();
1719 }
1720 }
1721
1722 // Test use-def chains: back edges
1723 void foo10() {
1724 bool b = mu.TryLock();
1725
1726 while (cond) {
1727 if (b) { // b should be uknown at this point b/c of the loop
1728 a = 10; // expected-warning {{writing variable 'a' requires locking 'mu' exclusively}}
1729 }
1730 b = !b;
1731 }
1732 }
1733}; // end TestTrylock
1734
1735
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +00001736namespace TestTemplateAttributeInstantiation {
1737
1738class Foo1 {
1739public:
1740 Mutex mu_;
1741 int a GUARDED_BY(mu_);
1742};
1743
1744class Foo2 {
1745public:
1746 int a GUARDED_BY(mu_);
1747 Mutex mu_;
1748};
1749
1750
1751class Bar {
1752public:
1753 // Test non-dependent expressions in attributes on template functions
1754 template <class T>
1755 void barND(Foo1 *foo, T *fooT) EXCLUSIVE_LOCKS_REQUIRED(foo->mu_) {
1756 foo->a = 0;
1757 }
1758
1759 // Test dependent expressions in attributes on template functions
1760 template <class T>
1761 void barD(Foo1 *foo, T *fooT) EXCLUSIVE_LOCKS_REQUIRED(fooT->mu_) {
1762 fooT->a = 0;
1763 }
1764};
1765
1766
1767template <class T>
1768class BarT {
1769public:
1770 Foo1 fooBase;
1771 T fooBaseT;
1772
1773 // Test non-dependent expression in ordinary method on template class
1774 void barND() EXCLUSIVE_LOCKS_REQUIRED(fooBase.mu_) {
1775 fooBase.a = 0;
1776 }
1777
1778 // Test dependent expressions in ordinary methods on template class
1779 void barD() EXCLUSIVE_LOCKS_REQUIRED(fooBaseT.mu_) {
1780 fooBaseT.a = 0;
1781 }
1782
1783 // Test dependent expressions in template method in template class
1784 template <class T2>
1785 void barTD(T2 *fooT) EXCLUSIVE_LOCKS_REQUIRED(fooBaseT.mu_, fooT->mu_) {
1786 fooBaseT.a = 0;
1787 fooT->a = 0;
1788 }
1789};
1790
1791template <class T>
1792class Cell {
1793public:
1794 Mutex mu_;
1795 // Test dependent guarded_by
1796 T data GUARDED_BY(mu_);
1797
DeLesley Hutchins23323e02012-01-20 22:50:54 +00001798 void fooEx() EXCLUSIVE_LOCKS_REQUIRED(mu_) {
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +00001799 data = 0;
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +00001800 }
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +00001801
1802 void foo() {
1803 mu_.Lock();
1804 data = 0;
1805 mu_.Unlock();
1806 }
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +00001807};
1808
1809void test() {
1810 Bar b;
1811 BarT<Foo2> bt;
1812 Foo1 f1;
1813 Foo2 f2;
1814
1815 f1.mu_.Lock();
1816 f2.mu_.Lock();
1817 bt.fooBase.mu_.Lock();
1818 bt.fooBaseT.mu_.Lock();
1819
1820 b.barND(&f1, &f2);
1821 b.barD(&f1, &f2);
1822 bt.barND();
1823 bt.barD();
1824 bt.barTD(&f2);
1825
1826 f1.mu_.Unlock();
1827 bt.barTD(&f1); // \
1828 // expected-warning {{calling function 'barTD' requires exclusive lock on 'mu_'}}
1829
1830 bt.fooBase.mu_.Unlock();
1831 bt.fooBaseT.mu_.Unlock();
1832 f2.mu_.Unlock();
1833
1834 Cell<int> cell;
1835 cell.data = 0; // \
1836 // expected-warning {{writing variable 'data' requires locking 'mu_' exclusively}}
1837 cell.foo();
DeLesley Hutchins23323e02012-01-20 22:50:54 +00001838 cell.mu_.Lock();
1839 cell.fooEx();
1840 cell.mu_.Unlock();
1841}
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +00001842
DeLesley Hutchins23323e02012-01-20 22:50:54 +00001843
1844template <class T>
1845class CellDelayed {
1846public:
1847 // Test dependent guarded_by
1848 T data GUARDED_BY(mu_);
1849
1850 void fooEx(CellDelayed<T> *other) EXCLUSIVE_LOCKS_REQUIRED(mu_, other->mu_) {
1851 this->data = other->data;
1852 }
1853
1854 template <class T2>
1855 void fooExT(CellDelayed<T2> *otherT) EXCLUSIVE_LOCKS_REQUIRED(mu_, otherT->mu_) {
1856 this->data = otherT->data;
1857 }
1858
1859 void foo() {
1860 mu_.Lock();
1861 data = 0;
1862 mu_.Unlock();
1863 }
1864
1865 Mutex mu_;
1866};
1867
1868void testDelayed() {
1869 CellDelayed<int> celld;
1870 CellDelayed<int> celld2;
1871 celld.foo();
1872 celld.mu_.Lock();
1873 celld2.mu_.Lock();
1874
1875 celld.fooEx(&celld2);
1876 celld.fooExT(&celld2);
1877
1878 celld2.mu_.Unlock();
1879 celld.mu_.Unlock();
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +00001880}
1881
1882}; // end namespace TestTemplateAttributeInstantiation
1883
1884
DeLesley Hutchinse03b2b32012-01-20 23:24:41 +00001885namespace FunctionDeclDefTest {
1886
1887class Foo {
1888public:
1889 Mutex mu_;
1890 int a GUARDED_BY(mu_);
1891
1892 virtual void foo1(Foo *f_declared) EXCLUSIVE_LOCKS_REQUIRED(f_declared->mu_);
1893};
1894
1895// EXCLUSIVE_LOCKS_REQUIRED should be applied, and rewritten to f_defined->mu_
1896void Foo::foo1(Foo *f_defined) {
1897 f_defined->a = 0;
1898};
1899
1900void test() {
1901 Foo myfoo;
1902 myfoo.foo1(&myfoo); // \
1903 // expected-warning {{calling function 'foo1' requires exclusive lock on 'mu_'}}
1904 myfoo.mu_.Lock();
1905 myfoo.foo1(&myfoo);
1906 myfoo.mu_.Unlock();
1907}
1908
1909};
Richard Smith2e515622012-02-03 04:45:26 +00001910
1911namespace GoingNative {
1912
1913 struct __attribute__((lockable)) mutex {
1914 void lock() __attribute__((exclusive_lock_function));
1915 void unlock() __attribute__((unlock_function));
1916 // ...
1917 };
1918 bool foo();
1919 bool bar();
1920 mutex m;
1921 void test() {
1922 m.lock();
1923 while (foo()) {
1924 m.unlock();
1925 // ...
1926 if (bar()) {
1927 // ...
1928 if (foo())
1929 continue; // expected-warning {{expecting mutex 'm' to be locked at start of each loop}}
1930 //...
1931 }
1932 // ...
1933 m.lock(); // expected-note {{mutex acquired here}}
1934 }
1935 m.unlock();
1936 }
1937
1938}
DeLesley Hutchinsc24a2332012-02-16 16:50:43 +00001939
1940
1941
1942namespace FunctionDefinitionTest {
1943
1944class Foo {
1945public:
1946 void foo1();
1947 void foo2();
1948 void foo3(Foo *other);
1949
1950 template<class T>
1951 void fooT1(const T& dummy1);
1952
1953 template<class T>
1954 void fooT2(const T& dummy2) EXCLUSIVE_LOCKS_REQUIRED(mu_);
1955
1956 Mutex mu_;
1957 int a GUARDED_BY(mu_);
1958};
1959
1960template<class T>
1961class FooT {
1962public:
1963 void foo();
1964
1965 Mutex mu_;
1966 T a GUARDED_BY(mu_);
1967};
1968
1969
1970void Foo::foo1() NO_THREAD_SAFETY_ANALYSIS {
1971 a = 1;
1972}
1973
1974void Foo::foo2() EXCLUSIVE_LOCKS_REQUIRED(mu_) {
1975 a = 2;
1976}
1977
1978void Foo::foo3(Foo *other) EXCLUSIVE_LOCKS_REQUIRED(other->mu_) {
1979 other->a = 3;
1980}
1981
1982template<class T>
1983void Foo::fooT1(const T& dummy1) EXCLUSIVE_LOCKS_REQUIRED(mu_) {
1984 a = dummy1;
1985}
1986
1987/* TODO -- uncomment with template instantiation of attributes.
1988template<class T>
1989void Foo::fooT2(const T& dummy2) {
1990 a = dummy2;
1991}
1992*/
1993
1994void fooF1(Foo *f) EXCLUSIVE_LOCKS_REQUIRED(f->mu_) {
1995 f->a = 1;
1996}
1997
1998void fooF2(Foo *f);
1999void fooF2(Foo *f) EXCLUSIVE_LOCKS_REQUIRED(f->mu_) {
2000 f->a = 2;
2001}
2002
2003void fooF3(Foo *f) EXCLUSIVE_LOCKS_REQUIRED(f->mu_);
2004void fooF3(Foo *f) {
2005 f->a = 3;
2006}
2007
2008template<class T>
2009void FooT<T>::foo() EXCLUSIVE_LOCKS_REQUIRED(mu_) {
2010 a = 0;
2011}
2012
2013void test() {
2014 int dummy = 0;
2015 Foo myFoo;
2016
2017 myFoo.foo2(); // \
2018 // expected-warning {{calling function 'foo2' requires exclusive lock on 'mu_'}}
2019 myFoo.foo3(&myFoo); // \
2020 // expected-warning {{calling function 'foo3' requires exclusive lock on 'mu_'}}
2021 myFoo.fooT1(dummy); // \
2022 // expected-warning {{calling function 'fooT1' requires exclusive lock on 'mu_'}}
2023
2024 // FIXME: uncomment with template instantiation of attributes patch
2025 // myFoo.fooT2(dummy); // expected warning
2026
2027 fooF1(&myFoo); // \
2028 // expected-warning {{calling function 'fooF1' requires exclusive lock on 'mu_'}}
2029 fooF2(&myFoo); // \
2030 // expected-warning {{calling function 'fooF2' requires exclusive lock on 'mu_'}}
2031 fooF3(&myFoo); // \
2032 // expected-warning {{calling function 'fooF3' requires exclusive lock on 'mu_'}}
2033
2034 myFoo.mu_.Lock();
2035 myFoo.foo2();
2036 myFoo.foo3(&myFoo);
2037 myFoo.fooT1(dummy);
2038
2039 // FIXME: uncomment with template instantiation of attributes patch
2040 // myFoo.fooT2(dummy);
2041
2042 fooF1(&myFoo);
2043 fooF2(&myFoo);
2044 fooF3(&myFoo);
2045 myFoo.mu_.Unlock();
2046
2047 FooT<int> myFooT;
2048 myFooT.foo(); // \
2049 // expected-warning {{calling function 'foo' requires exclusive lock on 'mu_'}}
2050}
2051
DeLesley Hutchins4bda3ec2012-02-16 17:03:24 +00002052} // end namespace FunctionDefinitionTest
2053
2054
2055namespace SelfLockingTest {
2056
2057class LOCKABLE MyLock {
2058public:
2059 int foo GUARDED_BY(this);
2060
2061 void lock() EXCLUSIVE_LOCK_FUNCTION();
2062 void unlock() UNLOCK_FUNCTION();
2063
2064 void doSomething() {
2065 this->lock(); // allow 'this' as a lock expression
2066 foo = 0;
2067 doSomethingElse();
2068 this->unlock();
2069 }
2070
2071 void doSomethingElse() EXCLUSIVE_LOCKS_REQUIRED(this) {
2072 foo = 1;
2073 };
2074
2075 void test() {
2076 foo = 2; // \
2077 // expected-warning {{writing variable 'foo' requires locking 'this' exclusively}}
2078 }
DeLesley Hutchinsc24a2332012-02-16 16:50:43 +00002079};
2080
DeLesley Hutchins4bda3ec2012-02-16 17:03:24 +00002081} // end namespace SelfLockingTest
2082
2083