blob: 06c013887aba68c9aaa0762cf00e21c93ece6274 [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
752int x __attribute__((guarded_by(UPmu = sls_mu))); // \
753 // expected-warning{{cannot resolve lock expression to a specific lockable object}}
754int y __attribute__((guarded_by(mua[0]))); // \
755 // expected-warning{{cannot resolve lock expression to a specific lockable object}}
756
757
758void testUnparse() {
759 // no errors, since the lock expressions are not resolved
760 x = 5;
761 y = 5;
762}
763
764void testUnparse2() {
765 mua[0].Lock(); // \
766 // expected-warning{{cannot resolve lock expression to a specific lockable object}}
767 (&(mua[0]) + 4)->Lock(); // \
768 // expected-warning{{cannot resolve lock expression to a specific lockable object}}
769}
770
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +0000771
772//----------------------------------------------------------------------------//
773// The following test cases are ported from the gcc thread safety implementation
774// They are each wrapped inside a namespace with the test number of the gcc test
775//
776// FIXME: add all the gcc tests, once this analysis passes them.
777//----------------------------------------------------------------------------//
778
779//-----------------------------------------//
780// Good testcases (no errors)
781//-----------------------------------------//
782
783namespace thread_annot_lock_20 {
784class Bar {
785 public:
786 static int func1() EXCLUSIVE_LOCKS_REQUIRED(mu1_);
787 static int b_ GUARDED_BY(mu1_);
788 static Mutex mu1_;
789 static int a_ GUARDED_BY(mu1_);
790};
791
792Bar b1;
793
794int Bar::func1()
795{
796 int res = 5;
797
798 if (a_ == 4)
799 res = b_;
800 return res;
801}
802} // end namespace thread_annot_lock_20
803
804namespace thread_annot_lock_22 {
805// Test various usage of GUARDED_BY and PT_GUARDED_BY annotations, especially
806// uses in class definitions.
807Mutex mu;
808
809class Bar {
810 public:
811 int a_ GUARDED_BY(mu1_);
812 int b_;
813 int *q PT_GUARDED_BY(mu);
814 Mutex mu1_ ACQUIRED_AFTER(mu);
815};
816
817Bar b1, *b3;
818int *p GUARDED_BY(mu) PT_GUARDED_BY(mu);
819int res GUARDED_BY(mu) = 5;
820
821int func(int i)
822{
823 int x;
824 mu.Lock();
825 b1.mu1_.Lock();
826 res = b1.a_ + b3->b_;
827 *p = i;
828 b1.a_ = res + b3->b_;
829 b3->b_ = *b1.q;
830 b1.mu1_.Unlock();
831 b1.b_ = res;
832 x = res;
833 mu.Unlock();
834 return x;
835}
836} // end namespace thread_annot_lock_22
837
838namespace thread_annot_lock_27_modified {
839// test lock annotations applied to function definitions
840// Modified: applied annotations only to function declarations
841Mutex mu1;
842Mutex mu2 ACQUIRED_AFTER(mu1);
843
844class Foo {
845 public:
846 int method1(int i) SHARED_LOCKS_REQUIRED(mu2) EXCLUSIVE_LOCKS_REQUIRED(mu1);
847};
848
849int Foo::method1(int i) {
850 return i;
851}
852
853
854int foo(int i) EXCLUSIVE_LOCKS_REQUIRED(mu2) SHARED_LOCKS_REQUIRED(mu1);
855int foo(int i) {
856 return i;
857}
858
859static int bar(int i) EXCLUSIVE_LOCKS_REQUIRED(mu1);
860static int bar(int i) {
861 return i;
862}
863
864void main() {
865 Foo a;
866
867 mu1.Lock();
868 mu2.Lock();
869 a.method1(1);
870 foo(2);
871 mu2.Unlock();
872 bar(3);
873 mu1.Unlock();
874}
875} // end namespace thread_annot_lock_27_modified
876
877
878namespace thread_annot_lock_38 {
879// Test the case where a template member function is annotated with lock
880// attributes in a non-template class.
881class Foo {
882 public:
883 void func1(int y) LOCKS_EXCLUDED(mu_);
884 template <typename T> void func2(T x) LOCKS_EXCLUDED(mu_);
885 private:
886 Mutex mu_;
887};
888
889Foo *foo;
890
891void main()
892{
893 foo->func1(5);
894 foo->func2(5);
895}
896} // end namespace thread_annot_lock_38
897
898namespace thread_annot_lock_43 {
899// Tests lock canonicalization
900class Foo {
901 public:
902 Mutex *mu_;
903};
904
905class FooBar {
906 public:
907 Foo *foo_;
908 int GetA() EXCLUSIVE_LOCKS_REQUIRED(foo_->mu_) { return a_; }
909 int a_ GUARDED_BY(foo_->mu_);
910};
911
912FooBar *fb;
913
914void main()
915{
916 int x;
917 fb->foo_->mu_->Lock();
918 x = fb->GetA();
919 fb->foo_->mu_->Unlock();
920}
921} // end namespace thread_annot_lock_43
922
923namespace thread_annot_lock_49 {
924// Test the support for use of lock expression in the annotations
925class Foo {
926 public:
927 Mutex foo_mu_;
928};
929
930class Bar {
931 private:
932 Foo *foo;
933 Mutex bar_mu_ ACQUIRED_AFTER(foo->foo_mu_);
934
935 public:
936 void Test1() {
937 foo->foo_mu_.Lock();
938 bar_mu_.Lock();
939 bar_mu_.Unlock();
940 foo->foo_mu_.Unlock();
941 }
942};
943
944void main() {
945 Bar bar;
946 bar.Test1();
947}
948} // end namespace thread_annot_lock_49
949
950namespace thread_annot_lock_61_modified {
951 // Modified to fix the compiler errors
952 // Test the fix for a bug introduced by the support of pass-by-reference
953 // paramters.
954 struct Foo { Foo &operator<< (bool) {return *this;} };
955 Foo &getFoo();
956 struct Bar { Foo &func () {return getFoo();} };
957 struct Bas { void operator& (Foo &) {} };
958 void mumble()
959 {
960 Bas() & Bar().func() << "" << "";
961 Bas() & Bar().func() << "";
962 }
963} // end namespace thread_annot_lock_61_modified
964
965
966namespace thread_annot_lock_65 {
967// Test the fix for a bug in the support of allowing reader locks for
968// non-const, non-modifying overload functions. (We didn't handle the builtin
969// properly.)
970enum MyFlags {
971 Zero,
972 One,
973 Two,
974 Three,
975 Four,
976 Five,
977 Six,
978 Seven,
979 Eight,
980 Nine
981};
982
983inline MyFlags
984operator|(MyFlags a, MyFlags b)
985{
986 return MyFlags(static_cast<int>(a) | static_cast<int>(b));
987}
988
989inline MyFlags&
990operator|=(MyFlags& a, MyFlags b)
991{
992 return a = a | b;
993}
994} // end namespace thread_annot_lock_65
995
996namespace thread_annot_lock_66_modified {
997// Modified: Moved annotation to function defn
998// Test annotations on out-of-line definitions of member functions where the
999// annotations refer to locks that are also data members in the class.
1000Mutex mu;
1001
1002class Foo {
1003 public:
1004 int method1(int i) SHARED_LOCKS_REQUIRED(mu1, mu, mu2);
1005 int data GUARDED_BY(mu1);
1006 Mutex *mu1;
1007 Mutex *mu2;
1008};
1009
1010int Foo::method1(int i)
1011{
1012 return data + i;
1013}
1014
1015void main()
1016{
1017 Foo a;
1018
1019 a.mu2->Lock();
1020 a.mu1->Lock();
1021 mu.Lock();
1022 a.method1(1);
1023 mu.Unlock();
1024 a.mu1->Unlock();
1025 a.mu2->Unlock();
1026}
1027} // end namespace thread_annot_lock_66_modified
1028
1029namespace thread_annot_lock_68_modified {
1030// Test a fix to a bug in the delayed name binding with nested template
1031// instantiation. We use a stack to make sure a name is not resolved to an
1032// inner context.
1033template <typename T>
1034class Bar {
1035 Mutex mu_;
1036};
1037
1038template <typename T>
1039class Foo {
1040 public:
1041 void func(T x) {
1042 mu_.Lock();
1043 count_ = x;
1044 mu_.Unlock();
1045 }
1046
1047 private:
1048 T count_ GUARDED_BY(mu_);
1049 Bar<T> bar_;
1050 Mutex mu_;
1051};
1052
1053void main()
1054{
1055 Foo<int> *foo;
1056 foo->func(5);
1057}
1058} // end namespace thread_annot_lock_68_modified
1059
1060namespace thread_annot_lock_30_modified {
1061// Test delay parsing of lock attribute arguments with nested classes.
1062// Modified: trylocks replaced with exclusive_lock_fun
1063int a = 0;
1064
1065class Bar {
1066 struct Foo;
1067
1068 public:
1069 void MyLock() EXCLUSIVE_LOCK_FUNCTION(mu);
1070
1071 int func() {
1072 MyLock();
1073// if (foo == 0) {
1074// return 0;
1075// }
1076 a = 5;
1077 mu.Unlock();
1078 return 1;
1079 }
1080
1081 class FooBar {
1082 int x;
1083 int y;
1084 };
1085
1086 private:
1087 Mutex mu;
1088};
1089
1090Bar *bar;
1091
1092void main()
1093{
1094 bar->func();
1095}
1096} // end namespace thread_annot_lock_30_modified
1097
1098namespace thread_annot_lock_47 {
1099// Test the support for annotations on virtual functions.
1100// This is a good test case. (i.e. There should be no warning emitted by the
1101// compiler.)
1102class Base {
1103 public:
1104 virtual void func1() EXCLUSIVE_LOCKS_REQUIRED(mu_);
1105 virtual void func2() LOCKS_EXCLUDED(mu_);
1106 Mutex mu_;
1107};
1108
1109class Child : public Base {
1110 public:
1111 virtual void func1() EXCLUSIVE_LOCKS_REQUIRED(mu_);
1112 virtual void func2() LOCKS_EXCLUDED(mu_);
1113};
1114
1115void main() {
1116 Child *c;
1117 Base *b = c;
1118
1119 b->mu_.Lock();
1120 b->func1();
1121 b->mu_.Unlock();
1122 b->func2();
1123
1124 c->mu_.Lock();
1125 c->func1();
1126 c->mu_.Unlock();
1127 c->func2();
1128}
1129} // end namespace thread_annot_lock_47
1130
1131//-----------------------------------------//
1132// Tests which produce errors
1133//-----------------------------------------//
1134
1135namespace thread_annot_lock_13 {
1136Mutex mu1;
1137Mutex mu2;
1138
1139int g GUARDED_BY(mu1);
1140int w GUARDED_BY(mu2);
1141
1142class Foo {
1143 public:
1144 void bar() LOCKS_EXCLUDED(mu_, mu1);
1145 int foo() SHARED_LOCKS_REQUIRED(mu_) EXCLUSIVE_LOCKS_REQUIRED(mu2);
1146
1147 private:
1148 int a_ GUARDED_BY(mu_);
1149 public:
1150 Mutex mu_ ACQUIRED_AFTER(mu1);
1151};
1152
1153int Foo::foo()
1154{
1155 int res;
1156 w = 5.2;
1157 res = a_ + 5;
1158 return res;
1159}
1160
1161void Foo::bar()
1162{
1163 int x;
1164 mu_.Lock();
1165 x = foo(); // expected-warning {{calling function 'foo' requires exclusive lock on 'mu2'}}
1166 a_ = x + 1;
1167 mu_.Unlock();
1168 if (x > 5) {
1169 mu1.Lock();
1170 g = 2.3;
1171 mu1.Unlock();
1172 }
1173}
1174
1175void main()
1176{
1177 Foo f1, *f2;
1178 f1.mu_.Lock();
Caitlin Sadowski74558b42011-09-15 18:13:32 +00001179 f1.bar(); // expected-warning {{cannot call function 'bar' while mutex 'mu_' is locked}}
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001180 mu2.Lock();
1181 f1.foo();
1182 mu2.Unlock();
1183 f1.mu_.Unlock();
1184 f2->mu_.Lock();
Caitlin Sadowski74558b42011-09-15 18:13:32 +00001185 f2->bar(); // expected-warning {{cannot call function 'bar' while mutex 'mu_' is locked}}
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001186 f2->mu_.Unlock();
1187 mu2.Lock();
1188 w = 2.5;
1189 mu2.Unlock();
1190}
1191} // end namespace thread_annot_lock_13
1192
1193namespace thread_annot_lock_18_modified {
1194// Modified: Trylocks removed
1195// Test the ability to distnguish between the same lock field of
1196// different objects of a class.
1197 class Bar {
1198 public:
1199 bool MyLock() EXCLUSIVE_LOCK_FUNCTION(mu1_);
1200 void MyUnlock() UNLOCK_FUNCTION(mu1_);
1201 int a_ GUARDED_BY(mu1_);
1202
1203 private:
1204 Mutex mu1_;
1205};
1206
1207Bar *b1, *b2;
1208
1209void func()
1210{
1211 b1->MyLock();
1212 b1->a_ = 5;
Caitlin Sadowski74558b42011-09-15 18:13:32 +00001213 b2->a_ = 3; // expected-warning {{writing variable 'a_' requires locking 'mu1_' exclusively}}
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001214 b2->MyLock();
1215 b2->MyUnlock();
1216 b1->MyUnlock();
1217}
1218} // end namespace thread_annot_lock_18_modified
1219
1220namespace thread_annot_lock_21 {
1221// Test various usage of GUARDED_BY and PT_GUARDED_BY annotations, especially
1222// uses in class definitions.
1223Mutex mu;
1224
1225class Bar {
1226 public:
1227 int a_ GUARDED_BY(mu1_);
1228 int b_;
1229 int *q PT_GUARDED_BY(mu);
1230 Mutex mu1_ ACQUIRED_AFTER(mu);
1231};
1232
1233Bar b1, *b3;
1234int *p GUARDED_BY(mu) PT_GUARDED_BY(mu);
1235
1236int res GUARDED_BY(mu) = 5;
1237
1238int func(int i)
1239{
1240 int x;
1241 b3->mu1_.Lock();
Caitlin Sadowski74558b42011-09-15 18:13:32 +00001242 res = b1.a_ + b3->b_; // expected-warning {{reading variable 'a_' requires locking 'mu1_'}} \
1243 // expected-warning {{writing variable 'res' requires locking 'mu' exclusively}}
1244 *p = i; // expected-warning {{reading variable 'p' requires locking 'mu'}} \
1245 // expected-warning {{writing the value pointed to by 'p' requires locking 'mu' exclusively}}
1246 b1.a_ = res + b3->b_; // expected-warning {{reading variable 'res' requires locking 'mu'}} \
1247 // expected-warning {{writing variable 'a_' requires locking 'mu1_' exclusively}}
1248 b3->b_ = *b1.q; // expected-warning {{reading the value pointed to by 'q' requires locking 'mu'}}
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001249 b3->mu1_.Unlock();
Caitlin Sadowski74558b42011-09-15 18:13:32 +00001250 b1.b_ = res; // expected-warning {{reading variable 'res' requires locking 'mu'}}
1251 x = res; // expected-warning {{reading variable 'res' requires locking 'mu'}}
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001252 return x;
1253}
1254} // end namespace thread_annot_lock_21
1255
1256namespace thread_annot_lock_35_modified {
1257// Test the analyzer's ability to distinguish the lock field of different
1258// objects.
1259class Foo {
1260 private:
1261 Mutex lock_;
1262 int a_ GUARDED_BY(lock_);
1263
1264 public:
1265 void Func(Foo* child) LOCKS_EXCLUDED(lock_) {
1266 Foo *new_foo = new Foo;
1267
1268 lock_.Lock();
1269
1270 child->Func(new_foo); // There shouldn't be any warning here as the
1271 // acquired lock is not in child.
1272 child->bar(7); // expected-warning {{calling function 'bar' requires exclusive lock on 'lock_'}}
Caitlin Sadowski74558b42011-09-15 18:13:32 +00001273 child->a_ = 5; // expected-warning {{writing variable 'a_' requires locking 'lock_' exclusively}}
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001274 lock_.Unlock();
1275 }
1276
1277 void bar(int y) EXCLUSIVE_LOCKS_REQUIRED(lock_) {
1278 a_ = y;
1279 }
1280};
1281
1282Foo *x;
1283
1284void main() {
1285 Foo *child = new Foo;
1286 x->Func(child);
1287}
1288} // end namespace thread_annot_lock_35_modified
1289
1290namespace thread_annot_lock_36_modified {
1291// Modified to move the annotations to function defns.
1292// Test the analyzer's ability to distinguish the lock field of different
1293// objects
1294class Foo {
1295 private:
1296 Mutex lock_;
1297 int a_ GUARDED_BY(lock_);
1298
1299 public:
1300 void Func(Foo* child) LOCKS_EXCLUDED(lock_);
1301 void bar(int y) EXCLUSIVE_LOCKS_REQUIRED(lock_);
1302};
1303
1304void Foo::Func(Foo* child) {
1305 Foo *new_foo = new Foo;
1306
1307 lock_.Lock();
1308
1309 child->lock_.Lock();
Caitlin Sadowski74558b42011-09-15 18:13:32 +00001310 child->Func(new_foo); // expected-warning {{cannot call function 'Func' while mutex 'lock_' is locked}}
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001311 child->bar(7);
1312 child->a_ = 5;
1313 child->lock_.Unlock();
1314
1315 lock_.Unlock();
1316}
1317
1318void Foo::bar(int y) {
1319 a_ = y;
1320}
1321
1322
1323Foo *x;
1324
1325void main() {
1326 Foo *child = new Foo;
1327 x->Func(child);
1328}
1329} // end namespace thread_annot_lock_36_modified
1330
1331
1332namespace thread_annot_lock_42 {
1333// Test support of multiple lock attributes of the same kind on a decl.
1334class Foo {
1335 private:
1336 Mutex mu1, mu2, mu3;
1337 int x GUARDED_BY(mu1) GUARDED_BY(mu2);
1338 int y GUARDED_BY(mu2);
1339
1340 void f2() LOCKS_EXCLUDED(mu1) LOCKS_EXCLUDED(mu2) LOCKS_EXCLUDED(mu3) {
1341 mu2.Lock();
1342 y = 2;
1343 mu2.Unlock();
1344 }
1345
1346 public:
1347 void f1() EXCLUSIVE_LOCKS_REQUIRED(mu2) EXCLUSIVE_LOCKS_REQUIRED(mu1) {
1348 x = 5;
Caitlin Sadowski74558b42011-09-15 18:13:32 +00001349 f2(); // expected-warning {{cannot call function 'f2' while mutex 'mu1' is locked}} \
1350 // expected-warning {{cannot call function 'f2' while mutex 'mu2' is locked}}
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001351 }
1352};
1353
1354Foo *foo;
1355
1356void func()
1357{
1358 foo->f1(); // expected-warning {{calling function 'f1' requires exclusive lock on 'mu2'}} \
1359 // expected-warning {{calling function 'f1' requires exclusive lock on 'mu1'}}
1360}
1361} // end namespace thread_annot_lock_42
1362
1363namespace thread_annot_lock_46 {
1364// Test the support for annotations on virtual functions.
1365class Base {
1366 public:
1367 virtual void func1() EXCLUSIVE_LOCKS_REQUIRED(mu_);
1368 virtual void func2() LOCKS_EXCLUDED(mu_);
1369 Mutex mu_;
1370};
1371
1372class Child : public Base {
1373 public:
1374 virtual void func1() EXCLUSIVE_LOCKS_REQUIRED(mu_);
1375 virtual void func2() LOCKS_EXCLUDED(mu_);
1376};
1377
1378void main() {
1379 Child *c;
1380 Base *b = c;
1381
1382 b->func1(); // expected-warning {{calling function 'func1' requires exclusive lock on 'mu_'}}
1383 b->mu_.Lock();
Caitlin Sadowski74558b42011-09-15 18:13:32 +00001384 b->func2(); // expected-warning {{cannot call function 'func2' while mutex 'mu_' is locked}}
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001385 b->mu_.Unlock();
1386
1387 c->func1(); // expected-warning {{calling function 'func1' requires exclusive lock on 'mu_'}}
1388 c->mu_.Lock();
Caitlin Sadowski74558b42011-09-15 18:13:32 +00001389 c->func2(); // expected-warning {{cannot call function 'func2' while mutex 'mu_' is locked}}
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001390 c->mu_.Unlock();
1391}
1392} // end namespace thread_annot_lock_46
1393
1394namespace thread_annot_lock_67_modified {
1395// Modified: attributes on definitions moved to declarations
1396// Test annotations on out-of-line definitions of member functions where the
1397// annotations refer to locks that are also data members in the class.
1398Mutex mu;
1399Mutex mu3;
1400
1401class Foo {
1402 public:
1403 int method1(int i) SHARED_LOCKS_REQUIRED(mu1, mu, mu2, mu3);
1404 int data GUARDED_BY(mu1);
1405 Mutex *mu1;
1406 Mutex *mu2;
1407};
1408
1409int Foo::method1(int i) {
1410 return data + i;
1411}
1412
1413void main()
1414{
1415 Foo a;
1416 a.method1(1); // expected-warning {{calling function 'method1' requires shared lock on 'mu1'}} \
1417 // expected-warning {{calling function 'method1' requires shared lock on 'mu'}} \
1418 // expected-warning {{calling function 'method1' requires shared lock on 'mu2'}} \
1419 // expected-warning {{calling function 'method1' requires shared lock on 'mu3'}}
1420}
1421} // end namespace thread_annot_lock_67_modified
1422
1423
DeLesley Hutchins81216392011-10-17 21:38:02 +00001424namespace substitution_test {
1425 class MyData {
1426 public:
1427 Mutex mu;
1428
1429 void lockData() __attribute__((exclusive_lock_function(mu))) { }
1430 void unlockData() __attribute__((unlock_function(mu))) { }
1431
1432 void doSomething() __attribute__((exclusive_locks_required(mu))) { }
1433 };
1434
1435
1436 class DataLocker {
1437 public:
1438 void lockData (MyData *d) __attribute__((exclusive_lock_function(d->mu))) { }
1439 void unlockData(MyData *d) __attribute__((unlock_function(d->mu))) { }
1440 };
1441
1442
1443 class Foo {
1444 public:
1445 void foo(MyData* d) __attribute__((exclusive_locks_required(d->mu))) { }
1446
1447 void bar1(MyData* d) {
1448 d->lockData();
1449 foo(d);
1450 d->unlockData();
1451 }
1452
1453 void bar2(MyData* d) {
1454 DataLocker dlr;
1455 dlr.lockData(d);
1456 foo(d);
1457 dlr.unlockData(d);
1458 }
1459
1460 void bar3(MyData* d1, MyData* d2) {
1461 DataLocker dlr;
1462 dlr.lockData(d1); // \
1463 // expected-warning {{mutex 'mu' is still locked at the end of function}}
1464 dlr.unlockData(d2); // \
1465 // expected-warning {{unlocking 'mu' that was not locked}}
1466 }
1467
1468 void bar4(MyData* d1, MyData* d2) {
1469 DataLocker dlr;
1470 dlr.lockData(d1);
1471 foo(d2); // \
1472 // expected-warning {{calling function 'foo' requires exclusive lock on 'mu'}}
1473 dlr.unlockData(d1);
1474 }
1475 };
1476} // end namespace substituation_test
1477
DeLesley Hutchinse0eaa852011-10-21 18:06:53 +00001478
1479namespace 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() {
1490 // destructors not implemented yet...
1491 Foo foo; // \
1492 // expected-warning {{mutex 'fooMu' is still locked at the end of function}}
1493 myVar = 0;
1494 }
1495}
1496