blob: b020e5712a0372b3879de7c55081ea3cd7357d35 [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
39
40Mutex sls_mu;
41
42Mutex sls_mu2 __attribute__((acquired_after(sls_mu)));
43int sls_guard_var __attribute__((guarded_var)) = 0;
44int sls_guardby_var __attribute__((guarded_by(sls_mu))) = 0;
45
46bool getBool();
47
48class MutexWrapper {
49public:
50 Mutex mu;
Caitlin Sadowski194418f2011-09-14 20:00:24 +000051 int x __attribute__((guarded_by(mu)));
52 void MyLock() __attribute__((exclusive_lock_function(mu)));
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +000053};
54
55MutexWrapper sls_mw;
56
57void sls_fun_0() {
58 sls_mw.mu.Lock();
Caitlin Sadowski194418f2011-09-14 20:00:24 +000059 sls_mw.x = 5;
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +000060 sls_mw.mu.Unlock();
61}
62
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +000063void sls_fun_2() {
64 sls_mu.Lock();
65 int x = sls_guard_var;
66 sls_mu.Unlock();
67}
68
69void sls_fun_3() {
70 sls_mu.Lock();
71 sls_guard_var = 2;
72 sls_mu.Unlock();
73}
74
75void sls_fun_4() {
76 sls_mu2.Lock();
77 sls_guard_var = 2;
78 sls_mu2.Unlock();
79}
80
81void sls_fun_5() {
82 sls_mu.Lock();
83 int x = sls_guardby_var;
84 sls_mu.Unlock();
85}
86
87void sls_fun_6() {
88 sls_mu.Lock();
89 sls_guardby_var = 2;
90 sls_mu.Unlock();
91}
92
93void sls_fun_7() {
94 sls_mu.Lock();
95 sls_mu2.Lock();
96 sls_mu2.Unlock();
97 sls_mu.Unlock();
98}
99
100void sls_fun_8() {
101 sls_mu.Lock();
102 if (getBool())
103 sls_mu.Unlock();
104 else
105 sls_mu.Unlock();
106}
107
108void sls_fun_9() {
109 if (getBool())
110 sls_mu.Lock();
111 else
112 sls_mu.Lock();
113 sls_mu.Unlock();
114}
115
116void sls_fun_good_6() {
117 if (getBool()) {
118 sls_mu.Lock();
119 } else {
120 if (getBool()) {
121 getBool(); // EMPTY
122 } else {
123 getBool(); // EMPTY
124 }
125 sls_mu.Lock();
126 }
127 sls_mu.Unlock();
128}
129
130void sls_fun_good_7() {
131 sls_mu.Lock();
132 while (getBool()) {
133 sls_mu.Unlock();
134 if (getBool()) {
135 if (getBool()) {
136 sls_mu.Lock();
137 continue;
138 }
139 }
140 sls_mu.Lock();
141 }
142 sls_mu.Unlock();
143}
144
Caitlin Sadowski194418f2011-09-14 20:00:24 +0000145void sls_fun_good_8() {
146 sls_mw.MyLock();
147 sls_mw.mu.Unlock();
148}
149
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000150void sls_fun_bad_1() {
151 sls_mu.Unlock(); // \
Caitlin Sadowski8bccabe2011-09-08 21:52:50 +0000152 // expected-warning{{unlocking 'sls_mu' that was not locked}}
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000153}
154
155void sls_fun_bad_2() {
156 sls_mu.Lock();
157 sls_mu.Lock(); // \
Caitlin Sadowski8bccabe2011-09-08 21:52:50 +0000158 // expected-warning{{locking 'sls_mu' that is already locked}}
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000159 sls_mu.Unlock();
160}
161
162void sls_fun_bad_3() {
163 sls_mu.Lock(); // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000164 // expected-warning{{mutex 'sls_mu' is still locked at the end of function 'sls_fun_bad_3'}}
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000165}
166
167void sls_fun_bad_4() {
168 if (getBool())
169 sls_mu.Lock(); // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000170 // expected-warning{{mutex 'sls_mu' is still locked at the end of its scope}}
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000171 else
172 sls_mu2.Lock(); // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000173 // expected-warning{{mutex 'sls_mu2' is still locked at the end of its scope}}
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000174}
175
176void sls_fun_bad_5() {
177 sls_mu.Lock(); // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000178 // expected-warning{{mutex 'sls_mu' is still locked at the end of its scope}}
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000179 if (getBool())
180 sls_mu.Unlock();
181}
182
183void sls_fun_bad_6() {
184 if (getBool()) {
185 sls_mu.Lock(); // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000186 // expected-warning{{mutex 'sls_mu' is still locked at the end of its scope}}
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000187 } else {
188 if (getBool()) {
189 getBool(); // EMPTY
190 } else {
191 getBool(); // EMPTY
192 }
193 }
194 sls_mu.Unlock(); // \
Caitlin Sadowski8bccabe2011-09-08 21:52:50 +0000195 // expected-warning{{unlocking 'sls_mu' that was not locked}}
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000196}
197
198void sls_fun_bad_7() {
Caitlin Sadowski4e4bc752011-09-15 17:25:19 +0000199 sls_mu.Lock(); // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000200 // expected-warning{{expecting mutex 'sls_mu' to be locked at start of each loop}}
Caitlin Sadowski4e4bc752011-09-15 17:25:19 +0000201 while (getBool()) {
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000202 sls_mu.Unlock();
203 if (getBool()) {
204 if (getBool()) {
205 continue;
206 }
207 }
208 sls_mu.Lock(); // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000209 // expected-warning{{mutex 'sls_mu' is still locked at the end of its scope}}
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000210 }
211 sls_mu.Unlock();
212}
213
214void sls_fun_bad_8() {
Caitlin Sadowski4e4bc752011-09-15 17:25:19 +0000215 sls_mu.Lock(); // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000216 // expected-warning{{expecting mutex 'sls_mu' to be locked at start of each loop}}
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000217 do {
Caitlin Sadowski4e4bc752011-09-15 17:25:19 +0000218 sls_mu.Unlock();
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000219 } while (getBool());
220}
221
222void sls_fun_bad_9() {
223 do {
224 sls_mu.Lock(); // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000225 // expected-warning{{expecting mutex 'sls_mu' to be locked at start of each loop}}
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000226 } while (getBool());
227 sls_mu.Unlock();
228}
229
230void sls_fun_bad_10() {
231 sls_mu.Lock(); // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000232 // expected-warning{{mutex 'sls_mu' is still locked at the end of function 'sls_fun_bad_10'}} \
233 // expected-warning{{expecting mutex 'sls_mu' to be locked at start of each loop}}
Caitlin Sadowski4e4bc752011-09-15 17:25:19 +0000234 while(getBool()) {
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000235 sls_mu.Unlock();
236 }
237}
238
239void sls_fun_bad_11() {
240 while (getBool()) {
241 sls_mu.Lock(); // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000242 // expected-warning{{expecting mutex 'sls_mu' to be locked at start of each loop}}
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000243 }
244 sls_mu.Unlock(); // \
Caitlin Sadowski8bccabe2011-09-08 21:52:50 +0000245 // expected-warning{{unlocking 'sls_mu' that was not locked}}
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000246}
247
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000248//-----------------------------------------//
249// Handling lock expressions in attribute args
250// -------------------------------------------//
251
252Mutex aa_mu;
253
254class GlobalLocker {
255public:
256 void globalLock() __attribute__((exclusive_lock_function(aa_mu)));
257 void globalUnlock() __attribute__((unlock_function(aa_mu)));
258};
259
260GlobalLocker glock;
261
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000262void aa_fun_1() {
263 glock.globalLock();
264 glock.globalUnlock();
265}
266
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000267void aa_fun_bad_1() {
268 glock.globalUnlock(); // \
Caitlin Sadowski8bccabe2011-09-08 21:52:50 +0000269 // expected-warning{{unlocking 'aa_mu' that was not locked}}
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000270}
271
272void aa_fun_bad_2() {
273 glock.globalLock();
274 glock.globalLock(); // \
Caitlin Sadowski8bccabe2011-09-08 21:52:50 +0000275 // expected-warning{{locking 'aa_mu' that is already locked}}
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000276 glock.globalUnlock();
277}
278
279void aa_fun_bad_3() {
280 glock.globalLock(); // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000281 // expected-warning{{mutex 'aa_mu' is still locked at the end of function 'aa_fun_bad_3'}}
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000282}
Caitlin Sadowskib4d0a962011-08-29 17:12:27 +0000283
Caitlin Sadowskib4d0a962011-08-29 17:12:27 +0000284//--------------------------------------------------//
285// Regression tests for unusual method names
286//--------------------------------------------------//
287
288Mutex wmu;
289
290// Test diagnostics for other method names.
291class WeirdMethods {
292 WeirdMethods() {
293 wmu.Lock(); // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000294 // expected-warning {{mutex 'wmu' is still locked at the end of function 'WeirdMethods'}}
Caitlin Sadowskib4d0a962011-08-29 17:12:27 +0000295 }
296 ~WeirdMethods() {
297 wmu.Lock(); // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000298 // expected-warning {{mutex 'wmu' is still locked at the end of function '~WeirdMethods'}}
Caitlin Sadowskib4d0a962011-08-29 17:12:27 +0000299 }
300 void operator++() {
301 wmu.Lock(); // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000302 // expected-warning {{mutex 'wmu' is still locked at the end of function 'operator++'}}
Caitlin Sadowskib4d0a962011-08-29 17:12:27 +0000303 }
304 operator int*() {
305 wmu.Lock(); // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000306 // expected-warning {{mutex 'wmu' is still locked at the end of function 'operator int *'}}
Caitlin Sadowskib4d0a962011-08-29 17:12:27 +0000307 return 0;
308 }
309};
310
Caitlin Sadowski05b436e2011-08-29 22:27:51 +0000311//-----------------------------------------------//
312// Errors for guarded by or guarded var variables
313// ----------------------------------------------//
314
315int *pgb_gvar __attribute__((pt_guarded_var));
316int *pgb_var __attribute__((pt_guarded_by(sls_mu)));
317
318class PGBFoo {
319 public:
320 int x;
321 int *pgb_field __attribute__((guarded_by(sls_mu2)))
322 __attribute__((pt_guarded_by(sls_mu)));
323 void testFoo() {
324 pgb_field = &x; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000325 // expected-warning {{writing variable 'pgb_field' requires locking 'sls_mu2' exclusively}}
326 *pgb_field = x; // expected-warning {{reading variable 'pgb_field' requires locking 'sls_mu2'}} \
327 // expected-warning {{writing the value pointed to by 'pgb_field' requires locking 'sls_mu' exclusively}}
328 x = *pgb_field; // expected-warning {{reading variable 'pgb_field' requires locking 'sls_mu2'}} \
329 // expected-warning {{reading the value pointed to by 'pgb_field' requires locking 'sls_mu'}}
330 (*pgb_field)++; // expected-warning {{reading variable 'pgb_field' requires locking 'sls_mu2'}} \
331 // expected-warning {{writing the value pointed to by 'pgb_field' requires locking 'sls_mu' exclusively}}
Caitlin Sadowski05b436e2011-08-29 22:27:51 +0000332 }
333};
334
335class GBFoo {
336 public:
337 int gb_field __attribute__((guarded_by(sls_mu)));
338
339 void testFoo() {
340 gb_field = 0; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000341 // expected-warning {{writing variable 'gb_field' requires locking 'sls_mu' exclusively}}
Caitlin Sadowski05b436e2011-08-29 22:27:51 +0000342 }
Caitlin Sadowskiaf370612011-09-08 18:35:21 +0000343
344 void testNoAnal() __attribute__((no_thread_safety_analysis)) {
345 gb_field = 0;
346 }
Caitlin Sadowski05b436e2011-08-29 22:27:51 +0000347};
348
349GBFoo GlobalGBFoo __attribute__((guarded_by(sls_mu)));
350
351void gb_fun_0() {
352 sls_mu.Lock();
353 int x = *pgb_var;
354 sls_mu.Unlock();
355}
356
357void gb_fun_1() {
358 sls_mu.Lock();
359 *pgb_var = 2;
360 sls_mu.Unlock();
361}
362
363void gb_fun_2() {
364 int x;
365 pgb_var = &x;
366}
367
368void gb_fun_3() {
369 int *x = pgb_var;
370}
371
372void gb_bad_0() {
373 sls_guard_var = 1; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000374 // expected-warning{{writing variable 'sls_guard_var' requires locking any mutex exclusively}}
Caitlin Sadowski05b436e2011-08-29 22:27:51 +0000375}
376
377void gb_bad_1() {
378 int x = sls_guard_var; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000379 // expected-warning{{reading variable 'sls_guard_var' requires locking any mutex}}
Caitlin Sadowski05b436e2011-08-29 22:27:51 +0000380}
381
382void gb_bad_2() {
383 sls_guardby_var = 1; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000384 // expected-warning {{writing variable 'sls_guardby_var' requires locking 'sls_mu' exclusively}}
Caitlin Sadowski05b436e2011-08-29 22:27:51 +0000385}
386
387void gb_bad_3() {
388 int x = sls_guardby_var; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000389 // expected-warning {{reading variable 'sls_guardby_var' requires locking 'sls_mu'}}
Caitlin Sadowski05b436e2011-08-29 22:27:51 +0000390}
391
392void gb_bad_4() {
393 *pgb_gvar = 1; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000394 // expected-warning {{writing the value pointed to by 'pgb_gvar' requires locking any mutex exclusively}}
Caitlin Sadowski05b436e2011-08-29 22:27:51 +0000395}
396
397void gb_bad_5() {
398 int x = *pgb_gvar; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000399 // expected-warning {{reading the value pointed to by 'pgb_gvar' requires locking any mutex}}
Caitlin Sadowski05b436e2011-08-29 22:27:51 +0000400}
401
402void gb_bad_6() {
403 *pgb_var = 1; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000404 // expected-warning {{writing the value pointed to by 'pgb_var' requires locking 'sls_mu' exclusively}}
Caitlin Sadowski05b436e2011-08-29 22:27:51 +0000405}
406
407void gb_bad_7() {
408 int x = *pgb_var; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000409 // expected-warning {{reading the value pointed to by 'pgb_var' requires locking 'sls_mu'}}
Caitlin Sadowski05b436e2011-08-29 22:27:51 +0000410}
411
412void gb_bad_8() {
413 GBFoo G;
414 G.gb_field = 0; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000415 // expected-warning {{writing variable 'gb_field' requires locking 'sls_mu'}}
Caitlin Sadowski05b436e2011-08-29 22:27:51 +0000416}
417
418void gb_bad_9() {
419 sls_guard_var++; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000420 // expected-warning{{writing variable 'sls_guard_var' requires locking any mutex exclusively}}
Caitlin Sadowski05b436e2011-08-29 22:27:51 +0000421 sls_guard_var--; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000422 // expected-warning{{writing variable 'sls_guard_var' requires locking any mutex exclusively}}
Caitlin Sadowski05b436e2011-08-29 22:27:51 +0000423 ++sls_guard_var; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000424 // expected-warning{{writing variable 'sls_guard_var' requires locking any mutex exclusively}}
Caitlin Sadowskia49d1d82011-09-09 16:07:55 +0000425 --sls_guard_var;// \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000426 // expected-warning{{writing variable 'sls_guard_var' requires locking any mutex exclusively}}
Caitlin Sadowski05b436e2011-08-29 22:27:51 +0000427}
Caitlin Sadowskib4d0a962011-08-29 17:12:27 +0000428
Caitlin Sadowskieff98fc2011-09-08 17:42:22 +0000429//-----------------------------------------------//
430// Warnings on variables with late parsed attributes
431// ----------------------------------------------//
432
433class LateFoo {
434public:
435 int a __attribute__((guarded_by(mu)));
436 int b;
437
438 void foo() __attribute__((exclusive_locks_required(mu))) { }
439
440 void test() {
441 a = 0; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000442 // expected-warning{{writing variable 'a' requires locking 'mu' exclusively}}
Caitlin Sadowskieff98fc2011-09-08 17:42:22 +0000443 b = a; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000444 // expected-warning {{reading variable 'a' requires locking 'mu'}}
Caitlin Sadowskieff98fc2011-09-08 17:42:22 +0000445 c = 0; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000446 // expected-warning {{writing variable 'c' requires locking 'mu' exclusively}}
Caitlin Sadowskieff98fc2011-09-08 17:42:22 +0000447 }
448
449 int c __attribute__((guarded_by(mu)));
450
451 Mutex mu;
452};
453
Caitlin Sadowski99107eb2011-09-09 16:21:55 +0000454class LateBar {
455 public:
456 int a_ __attribute__((guarded_by(mu1_)));
457 int b_;
458 int *q __attribute__((pt_guarded_by(mu)));
459 Mutex mu1_;
460 Mutex mu;
461 LateFoo Foo;
462 LateFoo Foo2;
463 LateFoo *FooPointer;
464};
465
466LateBar b1, *b3;
467
468void late_0() {
469 LateFoo FooA;
470 LateFoo FooB;
471 FooA.mu.Lock();
472 FooA.a = 5;
473 FooA.mu.Unlock();
474}
475
476void late_1() {
477 LateBar BarA;
478 BarA.FooPointer->mu.Lock();
479 BarA.FooPointer->a = 2;
480 BarA.FooPointer->mu.Unlock();
481}
482
483void late_bad_0() {
484 LateFoo fooA;
485 LateFoo fooB;
486 fooA.mu.Lock();
487 fooB.a = 5; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000488 // expected-warning{{writing variable 'a' requires locking 'mu' exclusively}}
Caitlin Sadowski99107eb2011-09-09 16:21:55 +0000489 fooA.mu.Unlock();
490}
491
492void late_bad_1() {
493 Mutex mu;
494 mu.Lock();
495 b1.mu1_.Lock();
496 int res = b1.a_ + b3->b_;
497 b3->b_ = *b1.q; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000498 // expected-warning{{reading the value pointed to by 'q' requires locking 'mu'}}
Caitlin Sadowski99107eb2011-09-09 16:21:55 +0000499 b1.mu1_.Unlock();
500 b1.b_ = res;
501 mu.Unlock();
502}
503
504void late_bad_2() {
505 LateBar BarA;
506 BarA.FooPointer->mu.Lock();
507 BarA.Foo.a = 2; // \
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 BarA.FooPointer->mu.Unlock();
510}
511
512void late_bad_3() {
513 LateBar BarA;
514 BarA.Foo.mu.Lock();
515 BarA.FooPointer->a = 2; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000516 // expected-warning{{writing variable 'a' requires locking 'mu' exclusively}}
Caitlin Sadowski99107eb2011-09-09 16:21:55 +0000517 BarA.Foo.mu.Unlock();
518}
519
520void late_bad_4() {
521 LateBar BarA;
522 BarA.Foo.mu.Lock();
523 BarA.Foo2.a = 2; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000524 // expected-warning{{writing variable 'a' requires locking 'mu' exclusively}}
Caitlin Sadowski99107eb2011-09-09 16:21:55 +0000525 BarA.Foo.mu.Unlock();
526}
527
Caitlin Sadowskia53257c2011-09-08 18:19:38 +0000528//-----------------------------------------------//
529// Extra warnings for shared vs. exclusive locks
530// ----------------------------------------------//
531
532void shared_fun_0() {
533 sls_mu.Lock();
534 do {
535 sls_mu.Unlock();
536 sls_mu.Lock();
537 } while (getBool());
538 sls_mu.Unlock();
539}
540
541void shared_fun_1() {
Caitlin Sadowski4e4bc752011-09-15 17:25:19 +0000542 sls_mu.ReaderLock(); // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000543 // expected-warning {{mutex 'sls_mu' is locked exclusively and shared in the same scope}}
Caitlin Sadowskia53257c2011-09-08 18:19:38 +0000544 do {
545 sls_mu.Unlock();
Caitlin Sadowski4e4bc752011-09-15 17:25:19 +0000546 sls_mu.Lock(); // \
547 // expected-note {{the other lock of mutex 'sls_mu' is here}}
Caitlin Sadowskia53257c2011-09-08 18:19:38 +0000548 } while (getBool());
549 sls_mu.Unlock();
550}
551
552void shared_fun_3() {
553 if (getBool())
554 sls_mu.Lock();
555 else
556 sls_mu.Lock();
557 *pgb_var = 1;
558 sls_mu.Unlock();
559}
560
561void shared_fun_4() {
562 if (getBool())
563 sls_mu.ReaderLock();
564 else
565 sls_mu.ReaderLock();
566 int x = sls_guardby_var;
567 sls_mu.Unlock();
568}
569
570void shared_fun_8() {
571 if (getBool())
572 sls_mu.Lock(); // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000573 // expected-warning {{mutex 'sls_mu' is locked exclusively and shared in the same scope}}
Caitlin Sadowskia53257c2011-09-08 18:19:38 +0000574 else
575 sls_mu.ReaderLock(); // \
Caitlin Sadowski8bccabe2011-09-08 21:52:50 +0000576 // expected-note {{the other lock of mutex 'sls_mu' is here}}
Caitlin Sadowskia53257c2011-09-08 18:19:38 +0000577 sls_mu.Unlock();
578}
579
580void shared_bad_0() {
Caitlin Sadowski4e4bc752011-09-15 17:25:19 +0000581 sls_mu.Lock(); // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000582 // expected-warning {{mutex 'sls_mu' is locked exclusively and shared in the same scope}}
Caitlin Sadowskia53257c2011-09-08 18:19:38 +0000583 do {
584 sls_mu.Unlock();
Caitlin Sadowski4e4bc752011-09-15 17:25:19 +0000585 sls_mu.ReaderLock(); // \
586 // expected-note {{the other lock of mutex 'sls_mu' is here}}
Caitlin Sadowskia53257c2011-09-08 18:19:38 +0000587 } while (getBool());
588 sls_mu.Unlock();
589}
590
591void shared_bad_1() {
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 *pgb_var = 1;
599 sls_mu.Unlock();
600}
601
602void shared_bad_2() {
603 if (getBool())
604 sls_mu.ReaderLock(); // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000605 // expected-warning {{mutex 'sls_mu' is locked exclusively and shared in the same scope}}
Caitlin Sadowskia53257c2011-09-08 18:19:38 +0000606 else
607 sls_mu.Lock(); // \
Caitlin Sadowski8bccabe2011-09-08 21:52:50 +0000608 // expected-note {{the other lock of mutex 'sls_mu' is here}}
Caitlin Sadowskia53257c2011-09-08 18:19:38 +0000609 *pgb_var = 1;
610 sls_mu.Unlock();
611}
Caitlin Sadowski978191e2011-09-08 18:27:31 +0000612
613// FIXME: Add support for functions (not only methods)
614class LRBar {
615 public:
616 void aa_elr_fun() __attribute__((exclusive_locks_required(aa_mu)));
617 void aa_elr_fun_s() __attribute__((shared_locks_required(aa_mu)));
618 void le_fun() __attribute__((locks_excluded(sls_mu)));
619};
620
621class LRFoo {
622 public:
623 void test() __attribute__((exclusive_locks_required(sls_mu)));
624 void testShared() __attribute__((shared_locks_required(sls_mu2)));
625};
626
627void elr_fun() __attribute__((exclusive_locks_required(sls_mu)));
628void elr_fun() {}
629
630LRFoo MyLRFoo;
631LRBar Bar;
632
633void es_fun_0() {
634 aa_mu.Lock();
635 Bar.aa_elr_fun();
636 aa_mu.Unlock();
637}
638
639void es_fun_1() {
640 aa_mu.Lock();
641 Bar.aa_elr_fun_s();
642 aa_mu.Unlock();
643}
644
645void es_fun_2() {
646 aa_mu.ReaderLock();
647 Bar.aa_elr_fun_s();
648 aa_mu.Unlock();
649}
650
651void es_fun_3() {
652 sls_mu.Lock();
653 MyLRFoo.test();
654 sls_mu.Unlock();
655}
656
657void es_fun_4() {
658 sls_mu2.Lock();
659 MyLRFoo.testShared();
660 sls_mu2.Unlock();
661}
662
663void es_fun_5() {
664 sls_mu2.ReaderLock();
665 MyLRFoo.testShared();
666 sls_mu2.Unlock();
667}
668
669void es_fun_6() {
670 Bar.le_fun();
671}
672
673void es_fun_7() {
674 sls_mu.Lock();
675 elr_fun();
676 sls_mu.Unlock();
677}
678
Caitlin Sadowskiaf370612011-09-08 18:35:21 +0000679void es_fun_8() __attribute__((no_thread_safety_analysis));
680
681void es_fun_8() {
682 Bar.aa_elr_fun_s();
683}
684
Caitlin Sadowskicb967512011-09-15 17:43:08 +0000685void es_fun_9() __attribute__((shared_locks_required(aa_mu)));
686void es_fun_9() {
687 Bar.aa_elr_fun_s();
688}
689
690void es_fun_10() __attribute__((exclusive_locks_required(aa_mu)));
691void es_fun_10() {
692 Bar.aa_elr_fun_s();
693}
694
Caitlin Sadowski978191e2011-09-08 18:27:31 +0000695void es_bad_0() {
696 Bar.aa_elr_fun(); // \
Caitlin Sadowski8bccabe2011-09-08 21:52:50 +0000697 // expected-warning {{calling function 'aa_elr_fun' requires exclusive lock on 'aa_mu'}}
Caitlin Sadowski978191e2011-09-08 18:27:31 +0000698}
699
700void es_bad_1() {
701 aa_mu.ReaderLock();
702 Bar.aa_elr_fun(); // \
Caitlin Sadowski8bccabe2011-09-08 21:52:50 +0000703 // expected-warning {{calling function 'aa_elr_fun' requires exclusive lock on 'aa_mu'}}
Caitlin Sadowski978191e2011-09-08 18:27:31 +0000704 aa_mu.Unlock();
705}
706
707void es_bad_2() {
708 Bar.aa_elr_fun_s(); // \
Caitlin Sadowski8bccabe2011-09-08 21:52:50 +0000709 // expected-warning {{calling function 'aa_elr_fun_s' requires shared lock on 'aa_mu'}}
Caitlin Sadowski978191e2011-09-08 18:27:31 +0000710}
711
712void es_bad_3() {
713 MyLRFoo.test(); // \
Caitlin Sadowski8bccabe2011-09-08 21:52:50 +0000714 // expected-warning {{calling function 'test' requires exclusive lock on 'sls_mu'}}
Caitlin Sadowski978191e2011-09-08 18:27:31 +0000715}
716
717void es_bad_4() {
718 MyLRFoo.testShared(); // \
Caitlin Sadowski8bccabe2011-09-08 21:52:50 +0000719 // expected-warning {{calling function 'testShared' requires shared lock on 'sls_mu2'}}
Caitlin Sadowski978191e2011-09-08 18:27:31 +0000720}
721
722void es_bad_5() {
723 sls_mu.ReaderLock();
724 MyLRFoo.test(); // \
Caitlin Sadowski8bccabe2011-09-08 21:52:50 +0000725 // expected-warning {{calling function 'test' requires exclusive lock on 'sls_mu'}}
Caitlin Sadowski978191e2011-09-08 18:27:31 +0000726 sls_mu.Unlock();
727}
728
729void es_bad_6() {
730 sls_mu.Lock();
731 Bar.le_fun(); // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000732 // expected-warning {{cannot call function 'le_fun' while mutex 'sls_mu' is locked}}
Caitlin Sadowski978191e2011-09-08 18:27:31 +0000733 sls_mu.Unlock();
734}
735
736void es_bad_7() {
737 sls_mu.ReaderLock();
738 Bar.le_fun(); // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000739 // expected-warning {{cannot call function 'le_fun' while mutex 'sls_mu' is locked}}
Caitlin Sadowski978191e2011-09-08 18:27:31 +0000740 sls_mu.Unlock();
741}
Caitlin Sadowski194418f2011-09-14 20:00:24 +0000742
DeLesley Hutchins81216392011-10-17 21:38:02 +0000743
Caitlin Sadowski194418f2011-09-14 20:00:24 +0000744//-----------------------------------------------//
745// Unparseable lock expressions
746// ----------------------------------------------//
747
748Mutex UPmu;
749// FIXME: add support for lock expressions involving arrays.
750Mutex mua[5];
751
DeLesley Hutchinsf1ac6372011-10-21 18:10:14 +0000752int x __attribute__((guarded_by(UPmu = sls_mu)));
753int y __attribute__((guarded_by(mua[0])));
Caitlin Sadowski194418f2011-09-14 20:00:24 +0000754
755
756void testUnparse() {
DeLesley Hutchinsf1ac6372011-10-21 18:10:14 +0000757 x = 5; // \
758 // expected-warning{{cannot resolve lock expression}}
759 y = 5; // \
760 // expected-warning{{cannot resolve lock expression}}
Caitlin Sadowski194418f2011-09-14 20:00:24 +0000761}
762
763void testUnparse2() {
764 mua[0].Lock(); // \
DeLesley Hutchinsf1ac6372011-10-21 18:10:14 +0000765 // expected-warning{{cannot resolve lock expression}}
Caitlin Sadowski194418f2011-09-14 20:00:24 +0000766 (&(mua[0]) + 4)->Lock(); // \
DeLesley Hutchinsf1ac6372011-10-21 18:10:14 +0000767 // expected-warning{{cannot resolve lock expression}}
Caitlin Sadowski194418f2011-09-14 20:00:24 +0000768}
769
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +0000770
771//----------------------------------------------------------------------------//
772// The following test cases are ported from the gcc thread safety implementation
773// They are each wrapped inside a namespace with the test number of the gcc test
774//
775// FIXME: add all the gcc tests, once this analysis passes them.
776//----------------------------------------------------------------------------//
777
778//-----------------------------------------//
779// Good testcases (no errors)
780//-----------------------------------------//
781
782namespace thread_annot_lock_20 {
783class Bar {
784 public:
785 static int func1() EXCLUSIVE_LOCKS_REQUIRED(mu1_);
786 static int b_ GUARDED_BY(mu1_);
787 static Mutex mu1_;
788 static int a_ GUARDED_BY(mu1_);
789};
790
791Bar b1;
792
793int Bar::func1()
794{
795 int res = 5;
796
797 if (a_ == 4)
798 res = b_;
799 return res;
800}
801} // end namespace thread_annot_lock_20
802
803namespace thread_annot_lock_22 {
804// Test various usage of GUARDED_BY and PT_GUARDED_BY annotations, especially
805// uses in class definitions.
806Mutex mu;
807
808class Bar {
809 public:
810 int a_ GUARDED_BY(mu1_);
811 int b_;
812 int *q PT_GUARDED_BY(mu);
813 Mutex mu1_ ACQUIRED_AFTER(mu);
814};
815
816Bar b1, *b3;
817int *p GUARDED_BY(mu) PT_GUARDED_BY(mu);
818int res GUARDED_BY(mu) = 5;
819
820int func(int i)
821{
822 int x;
823 mu.Lock();
824 b1.mu1_.Lock();
825 res = b1.a_ + b3->b_;
826 *p = i;
827 b1.a_ = res + b3->b_;
828 b3->b_ = *b1.q;
829 b1.mu1_.Unlock();
830 b1.b_ = res;
831 x = res;
832 mu.Unlock();
833 return x;
834}
835} // end namespace thread_annot_lock_22
836
837namespace thread_annot_lock_27_modified {
838// test lock annotations applied to function definitions
839// Modified: applied annotations only to function declarations
840Mutex mu1;
841Mutex mu2 ACQUIRED_AFTER(mu1);
842
843class Foo {
844 public:
845 int method1(int i) SHARED_LOCKS_REQUIRED(mu2) EXCLUSIVE_LOCKS_REQUIRED(mu1);
846};
847
848int Foo::method1(int i) {
849 return i;
850}
851
852
853int foo(int i) EXCLUSIVE_LOCKS_REQUIRED(mu2) SHARED_LOCKS_REQUIRED(mu1);
854int foo(int i) {
855 return i;
856}
857
858static int bar(int i) EXCLUSIVE_LOCKS_REQUIRED(mu1);
859static int bar(int i) {
860 return i;
861}
862
863void main() {
864 Foo a;
865
866 mu1.Lock();
867 mu2.Lock();
868 a.method1(1);
869 foo(2);
870 mu2.Unlock();
871 bar(3);
872 mu1.Unlock();
873}
874} // end namespace thread_annot_lock_27_modified
875
876
877namespace thread_annot_lock_38 {
878// Test the case where a template member function is annotated with lock
879// attributes in a non-template class.
880class Foo {
881 public:
882 void func1(int y) LOCKS_EXCLUDED(mu_);
883 template <typename T> void func2(T x) LOCKS_EXCLUDED(mu_);
884 private:
885 Mutex mu_;
886};
887
888Foo *foo;
889
890void main()
891{
892 foo->func1(5);
893 foo->func2(5);
894}
895} // end namespace thread_annot_lock_38
896
897namespace thread_annot_lock_43 {
898// Tests lock canonicalization
899class Foo {
900 public:
901 Mutex *mu_;
902};
903
904class FooBar {
905 public:
906 Foo *foo_;
907 int GetA() EXCLUSIVE_LOCKS_REQUIRED(foo_->mu_) { return a_; }
908 int a_ GUARDED_BY(foo_->mu_);
909};
910
911FooBar *fb;
912
913void main()
914{
915 int x;
916 fb->foo_->mu_->Lock();
917 x = fb->GetA();
918 fb->foo_->mu_->Unlock();
919}
920} // end namespace thread_annot_lock_43
921
922namespace thread_annot_lock_49 {
923// Test the support for use of lock expression in the annotations
924class Foo {
925 public:
926 Mutex foo_mu_;
927};
928
929class Bar {
930 private:
931 Foo *foo;
932 Mutex bar_mu_ ACQUIRED_AFTER(foo->foo_mu_);
933
934 public:
935 void Test1() {
936 foo->foo_mu_.Lock();
937 bar_mu_.Lock();
938 bar_mu_.Unlock();
939 foo->foo_mu_.Unlock();
940 }
941};
942
943void main() {
944 Bar bar;
945 bar.Test1();
946}
947} // end namespace thread_annot_lock_49
948
949namespace thread_annot_lock_61_modified {
950 // Modified to fix the compiler errors
951 // Test the fix for a bug introduced by the support of pass-by-reference
952 // paramters.
953 struct Foo { Foo &operator<< (bool) {return *this;} };
954 Foo &getFoo();
955 struct Bar { Foo &func () {return getFoo();} };
956 struct Bas { void operator& (Foo &) {} };
957 void mumble()
958 {
959 Bas() & Bar().func() << "" << "";
960 Bas() & Bar().func() << "";
961 }
962} // end namespace thread_annot_lock_61_modified
963
964
965namespace thread_annot_lock_65 {
966// Test the fix for a bug in the support of allowing reader locks for
967// non-const, non-modifying overload functions. (We didn't handle the builtin
968// properly.)
969enum MyFlags {
970 Zero,
971 One,
972 Two,
973 Three,
974 Four,
975 Five,
976 Six,
977 Seven,
978 Eight,
979 Nine
980};
981
982inline MyFlags
983operator|(MyFlags a, MyFlags b)
984{
985 return MyFlags(static_cast<int>(a) | static_cast<int>(b));
986}
987
988inline MyFlags&
989operator|=(MyFlags& a, MyFlags b)
990{
991 return a = a | b;
992}
993} // end namespace thread_annot_lock_65
994
995namespace thread_annot_lock_66_modified {
996// Modified: Moved annotation to function defn
997// Test annotations on out-of-line definitions of member functions where the
998// annotations refer to locks that are also data members in the class.
999Mutex mu;
1000
1001class Foo {
1002 public:
1003 int method1(int i) SHARED_LOCKS_REQUIRED(mu1, mu, mu2);
1004 int data GUARDED_BY(mu1);
1005 Mutex *mu1;
1006 Mutex *mu2;
1007};
1008
1009int Foo::method1(int i)
1010{
1011 return data + i;
1012}
1013
1014void main()
1015{
1016 Foo a;
1017
1018 a.mu2->Lock();
1019 a.mu1->Lock();
1020 mu.Lock();
1021 a.method1(1);
1022 mu.Unlock();
1023 a.mu1->Unlock();
1024 a.mu2->Unlock();
1025}
1026} // end namespace thread_annot_lock_66_modified
1027
1028namespace thread_annot_lock_68_modified {
1029// Test a fix to a bug in the delayed name binding with nested template
1030// instantiation. We use a stack to make sure a name is not resolved to an
1031// inner context.
1032template <typename T>
1033class Bar {
1034 Mutex mu_;
1035};
1036
1037template <typename T>
1038class Foo {
1039 public:
1040 void func(T x) {
1041 mu_.Lock();
1042 count_ = x;
1043 mu_.Unlock();
1044 }
1045
1046 private:
1047 T count_ GUARDED_BY(mu_);
1048 Bar<T> bar_;
1049 Mutex mu_;
1050};
1051
1052void main()
1053{
1054 Foo<int> *foo;
1055 foo->func(5);
1056}
1057} // end namespace thread_annot_lock_68_modified
1058
1059namespace thread_annot_lock_30_modified {
1060// Test delay parsing of lock attribute arguments with nested classes.
1061// Modified: trylocks replaced with exclusive_lock_fun
1062int a = 0;
1063
1064class Bar {
1065 struct Foo;
1066
1067 public:
1068 void MyLock() EXCLUSIVE_LOCK_FUNCTION(mu);
1069
1070 int func() {
1071 MyLock();
1072// if (foo == 0) {
1073// return 0;
1074// }
1075 a = 5;
1076 mu.Unlock();
1077 return 1;
1078 }
1079
1080 class FooBar {
1081 int x;
1082 int y;
1083 };
1084
1085 private:
1086 Mutex mu;
1087};
1088
1089Bar *bar;
1090
1091void main()
1092{
1093 bar->func();
1094}
1095} // end namespace thread_annot_lock_30_modified
1096
1097namespace thread_annot_lock_47 {
1098// Test the support for annotations on virtual functions.
1099// This is a good test case. (i.e. There should be no warning emitted by the
1100// compiler.)
1101class Base {
1102 public:
1103 virtual void func1() EXCLUSIVE_LOCKS_REQUIRED(mu_);
1104 virtual void func2() LOCKS_EXCLUDED(mu_);
1105 Mutex mu_;
1106};
1107
1108class Child : public Base {
1109 public:
1110 virtual void func1() EXCLUSIVE_LOCKS_REQUIRED(mu_);
1111 virtual void func2() LOCKS_EXCLUDED(mu_);
1112};
1113
1114void main() {
1115 Child *c;
1116 Base *b = c;
1117
1118 b->mu_.Lock();
1119 b->func1();
1120 b->mu_.Unlock();
1121 b->func2();
1122
1123 c->mu_.Lock();
1124 c->func1();
1125 c->mu_.Unlock();
1126 c->func2();
1127}
1128} // end namespace thread_annot_lock_47
1129
1130//-----------------------------------------//
1131// Tests which produce errors
1132//-----------------------------------------//
1133
1134namespace thread_annot_lock_13 {
1135Mutex mu1;
1136Mutex mu2;
1137
1138int g GUARDED_BY(mu1);
1139int w GUARDED_BY(mu2);
1140
1141class Foo {
1142 public:
1143 void bar() LOCKS_EXCLUDED(mu_, mu1);
1144 int foo() SHARED_LOCKS_REQUIRED(mu_) EXCLUSIVE_LOCKS_REQUIRED(mu2);
1145
1146 private:
1147 int a_ GUARDED_BY(mu_);
1148 public:
1149 Mutex mu_ ACQUIRED_AFTER(mu1);
1150};
1151
1152int Foo::foo()
1153{
1154 int res;
1155 w = 5.2;
1156 res = a_ + 5;
1157 return res;
1158}
1159
1160void Foo::bar()
1161{
1162 int x;
1163 mu_.Lock();
1164 x = foo(); // expected-warning {{calling function 'foo' requires exclusive lock on 'mu2'}}
1165 a_ = x + 1;
1166 mu_.Unlock();
1167 if (x > 5) {
1168 mu1.Lock();
1169 g = 2.3;
1170 mu1.Unlock();
1171 }
1172}
1173
1174void main()
1175{
1176 Foo f1, *f2;
1177 f1.mu_.Lock();
Caitlin Sadowski74558b42011-09-15 18:13:32 +00001178 f1.bar(); // expected-warning {{cannot call function 'bar' while mutex 'mu_' is locked}}
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001179 mu2.Lock();
1180 f1.foo();
1181 mu2.Unlock();
1182 f1.mu_.Unlock();
1183 f2->mu_.Lock();
Caitlin Sadowski74558b42011-09-15 18:13:32 +00001184 f2->bar(); // expected-warning {{cannot call function 'bar' while mutex 'mu_' is locked}}
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001185 f2->mu_.Unlock();
1186 mu2.Lock();
1187 w = 2.5;
1188 mu2.Unlock();
1189}
1190} // end namespace thread_annot_lock_13
1191
1192namespace thread_annot_lock_18_modified {
1193// Modified: Trylocks removed
1194// Test the ability to distnguish between the same lock field of
1195// different objects of a class.
1196 class Bar {
1197 public:
1198 bool MyLock() EXCLUSIVE_LOCK_FUNCTION(mu1_);
1199 void MyUnlock() UNLOCK_FUNCTION(mu1_);
1200 int a_ GUARDED_BY(mu1_);
1201
1202 private:
1203 Mutex mu1_;
1204};
1205
1206Bar *b1, *b2;
1207
1208void func()
1209{
1210 b1->MyLock();
1211 b1->a_ = 5;
Caitlin Sadowski74558b42011-09-15 18:13:32 +00001212 b2->a_ = 3; // expected-warning {{writing variable 'a_' requires locking 'mu1_' exclusively}}
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001213 b2->MyLock();
1214 b2->MyUnlock();
1215 b1->MyUnlock();
1216}
1217} // end namespace thread_annot_lock_18_modified
1218
1219namespace thread_annot_lock_21 {
1220// Test various usage of GUARDED_BY and PT_GUARDED_BY annotations, especially
1221// uses in class definitions.
1222Mutex mu;
1223
1224class Bar {
1225 public:
1226 int a_ GUARDED_BY(mu1_);
1227 int b_;
1228 int *q PT_GUARDED_BY(mu);
1229 Mutex mu1_ ACQUIRED_AFTER(mu);
1230};
1231
1232Bar b1, *b3;
1233int *p GUARDED_BY(mu) PT_GUARDED_BY(mu);
1234
1235int res GUARDED_BY(mu) = 5;
1236
1237int func(int i)
1238{
1239 int x;
1240 b3->mu1_.Lock();
Caitlin Sadowski74558b42011-09-15 18:13:32 +00001241 res = b1.a_ + b3->b_; // expected-warning {{reading variable 'a_' requires locking 'mu1_'}} \
1242 // expected-warning {{writing variable 'res' requires locking 'mu' exclusively}}
1243 *p = i; // expected-warning {{reading variable 'p' requires locking 'mu'}} \
1244 // expected-warning {{writing the value pointed to by 'p' requires locking 'mu' exclusively}}
1245 b1.a_ = res + b3->b_; // expected-warning {{reading variable 'res' requires locking 'mu'}} \
1246 // expected-warning {{writing variable 'a_' requires locking 'mu1_' exclusively}}
1247 b3->b_ = *b1.q; // expected-warning {{reading the value pointed to by 'q' requires locking 'mu'}}
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001248 b3->mu1_.Unlock();
Caitlin Sadowski74558b42011-09-15 18:13:32 +00001249 b1.b_ = res; // expected-warning {{reading variable 'res' requires locking 'mu'}}
1250 x = res; // expected-warning {{reading variable 'res' requires locking 'mu'}}
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001251 return x;
1252}
1253} // end namespace thread_annot_lock_21
1254
1255namespace thread_annot_lock_35_modified {
1256// Test the analyzer's ability to distinguish the lock field of different
1257// objects.
1258class Foo {
1259 private:
1260 Mutex lock_;
1261 int a_ GUARDED_BY(lock_);
1262
1263 public:
1264 void Func(Foo* child) LOCKS_EXCLUDED(lock_) {
1265 Foo *new_foo = new Foo;
1266
1267 lock_.Lock();
1268
1269 child->Func(new_foo); // There shouldn't be any warning here as the
1270 // acquired lock is not in child.
1271 child->bar(7); // expected-warning {{calling function 'bar' requires exclusive lock on 'lock_'}}
Caitlin Sadowski74558b42011-09-15 18:13:32 +00001272 child->a_ = 5; // expected-warning {{writing variable 'a_' requires locking 'lock_' exclusively}}
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001273 lock_.Unlock();
1274 }
1275
1276 void bar(int y) EXCLUSIVE_LOCKS_REQUIRED(lock_) {
1277 a_ = y;
1278 }
1279};
1280
1281Foo *x;
1282
1283void main() {
1284 Foo *child = new Foo;
1285 x->Func(child);
1286}
1287} // end namespace thread_annot_lock_35_modified
1288
1289namespace thread_annot_lock_36_modified {
1290// Modified to move the annotations to function defns.
1291// Test the analyzer's ability to distinguish the lock field of different
1292// objects
1293class Foo {
1294 private:
1295 Mutex lock_;
1296 int a_ GUARDED_BY(lock_);
1297
1298 public:
1299 void Func(Foo* child) LOCKS_EXCLUDED(lock_);
1300 void bar(int y) EXCLUSIVE_LOCKS_REQUIRED(lock_);
1301};
1302
1303void Foo::Func(Foo* child) {
1304 Foo *new_foo = new Foo;
1305
1306 lock_.Lock();
1307
1308 child->lock_.Lock();
Caitlin Sadowski74558b42011-09-15 18:13:32 +00001309 child->Func(new_foo); // expected-warning {{cannot call function 'Func' while mutex 'lock_' is locked}}
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001310 child->bar(7);
1311 child->a_ = 5;
1312 child->lock_.Unlock();
1313
1314 lock_.Unlock();
1315}
1316
1317void Foo::bar(int y) {
1318 a_ = y;
1319}
1320
1321
1322Foo *x;
1323
1324void main() {
1325 Foo *child = new Foo;
1326 x->Func(child);
1327}
1328} // end namespace thread_annot_lock_36_modified
1329
1330
1331namespace thread_annot_lock_42 {
1332// Test support of multiple lock attributes of the same kind on a decl.
1333class Foo {
1334 private:
1335 Mutex mu1, mu2, mu3;
1336 int x GUARDED_BY(mu1) GUARDED_BY(mu2);
1337 int y GUARDED_BY(mu2);
1338
1339 void f2() LOCKS_EXCLUDED(mu1) LOCKS_EXCLUDED(mu2) LOCKS_EXCLUDED(mu3) {
1340 mu2.Lock();
1341 y = 2;
1342 mu2.Unlock();
1343 }
1344
1345 public:
1346 void f1() EXCLUSIVE_LOCKS_REQUIRED(mu2) EXCLUSIVE_LOCKS_REQUIRED(mu1) {
1347 x = 5;
Caitlin Sadowski74558b42011-09-15 18:13:32 +00001348 f2(); // expected-warning {{cannot call function 'f2' while mutex 'mu1' is locked}} \
1349 // expected-warning {{cannot call function 'f2' while mutex 'mu2' is locked}}
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001350 }
1351};
1352
1353Foo *foo;
1354
1355void func()
1356{
1357 foo->f1(); // expected-warning {{calling function 'f1' requires exclusive lock on 'mu2'}} \
1358 // expected-warning {{calling function 'f1' requires exclusive lock on 'mu1'}}
1359}
1360} // end namespace thread_annot_lock_42
1361
1362namespace thread_annot_lock_46 {
1363// Test the support for annotations on virtual functions.
1364class Base {
1365 public:
1366 virtual void func1() EXCLUSIVE_LOCKS_REQUIRED(mu_);
1367 virtual void func2() LOCKS_EXCLUDED(mu_);
1368 Mutex mu_;
1369};
1370
1371class Child : public Base {
1372 public:
1373 virtual void func1() EXCLUSIVE_LOCKS_REQUIRED(mu_);
1374 virtual void func2() LOCKS_EXCLUDED(mu_);
1375};
1376
1377void main() {
1378 Child *c;
1379 Base *b = c;
1380
1381 b->func1(); // expected-warning {{calling function 'func1' requires exclusive lock on 'mu_'}}
1382 b->mu_.Lock();
Caitlin Sadowski74558b42011-09-15 18:13:32 +00001383 b->func2(); // expected-warning {{cannot call function 'func2' while mutex 'mu_' is locked}}
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001384 b->mu_.Unlock();
1385
1386 c->func1(); // expected-warning {{calling function 'func1' requires exclusive lock on 'mu_'}}
1387 c->mu_.Lock();
Caitlin Sadowski74558b42011-09-15 18:13:32 +00001388 c->func2(); // expected-warning {{cannot call function 'func2' while mutex 'mu_' is locked}}
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001389 c->mu_.Unlock();
1390}
1391} // end namespace thread_annot_lock_46
1392
1393namespace thread_annot_lock_67_modified {
1394// Modified: attributes on definitions moved to declarations
1395// Test annotations on out-of-line definitions of member functions where the
1396// annotations refer to locks that are also data members in the class.
1397Mutex mu;
1398Mutex mu3;
1399
1400class Foo {
1401 public:
1402 int method1(int i) SHARED_LOCKS_REQUIRED(mu1, mu, mu2, mu3);
1403 int data GUARDED_BY(mu1);
1404 Mutex *mu1;
1405 Mutex *mu2;
1406};
1407
1408int Foo::method1(int i) {
1409 return data + i;
1410}
1411
1412void main()
1413{
1414 Foo a;
1415 a.method1(1); // expected-warning {{calling function 'method1' requires shared lock on 'mu1'}} \
1416 // expected-warning {{calling function 'method1' requires shared lock on 'mu'}} \
1417 // expected-warning {{calling function 'method1' requires shared lock on 'mu2'}} \
1418 // expected-warning {{calling function 'method1' requires shared lock on 'mu3'}}
1419}
1420} // end namespace thread_annot_lock_67_modified
1421
1422
DeLesley Hutchins81216392011-10-17 21:38:02 +00001423namespace substitution_test {
1424 class MyData {
1425 public:
1426 Mutex mu;
1427
1428 void lockData() __attribute__((exclusive_lock_function(mu))) { }
1429 void unlockData() __attribute__((unlock_function(mu))) { }
1430
1431 void doSomething() __attribute__((exclusive_locks_required(mu))) { }
1432 };
1433
1434
1435 class DataLocker {
1436 public:
1437 void lockData (MyData *d) __attribute__((exclusive_lock_function(d->mu))) { }
1438 void unlockData(MyData *d) __attribute__((unlock_function(d->mu))) { }
1439 };
1440
1441
1442 class Foo {
1443 public:
1444 void foo(MyData* d) __attribute__((exclusive_locks_required(d->mu))) { }
1445
1446 void bar1(MyData* d) {
1447 d->lockData();
1448 foo(d);
1449 d->unlockData();
1450 }
1451
1452 void bar2(MyData* d) {
1453 DataLocker dlr;
1454 dlr.lockData(d);
1455 foo(d);
1456 dlr.unlockData(d);
1457 }
1458
1459 void bar3(MyData* d1, MyData* d2) {
1460 DataLocker dlr;
1461 dlr.lockData(d1); // \
1462 // expected-warning {{mutex 'mu' is still locked at the end of function}}
1463 dlr.unlockData(d2); // \
1464 // expected-warning {{unlocking 'mu' that was not locked}}
1465 }
1466
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 };
1519
1520 template<typename U>
1521 struct IndirectLock {
1522 int DoNaughtyThings(T *t) {
1523 return t->s->n; // expected-warning {{reading variable 's' requires locking 'm'}}
1524 }
1525 };
1526
Richard Smithf11e9232011-10-25 01:05:41 +00001527 template struct IndirectLock<int>; // expected-note {{here}}
Richard Smith97f9fe02011-10-25 00:41:24 +00001528
1529}