blob: 50ec0d196d37811e9acd37edb8cc639a33115c1e [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#include <map> // for test 50
4#include <string> // for test 58
5
6#define LOCKABLE __attribute__ ((lockable))
7#define SCOPED_LOCKABLE __attribute__ ((scoped_lockable))
8#define GUARDED_BY(x) __attribute__ ((guarded_by(x)))
9#define GUARDED_VAR __attribute__ ((guarded_var))
10#define PT_GUARDED_BY(x) __attribute__ ((pt_guarded_by(x)))
11#define PT_GUARDED_VAR __attribute__ ((pt_guarded_var))
12#define ACQUIRED_AFTER(...) __attribute__ ((acquired_after(__VA_ARGS__)))
13#define ACQUIRED_BEFORE(...) __attribute__ ((acquired_before(__VA_ARGS__)))
14#define EXCLUSIVE_LOCK_FUNCTION(...) __attribute__ ((exclusive_lock_function(__VA_ARGS__)))
15#define SHARED_LOCK_FUNCTION(...) __attribute__ ((shared_lock_function(__VA_ARGS__)))
16#define EXCLUSIVE_TRYLOCK_FUNCTION(...) __attribute__ ((exclusive_trylock_function(__VA_ARGS__)))
17#define SHARED_TRYLOCK_FUNCTION(...) __attribute__ ((shared_trylock_function(__VA_ARGS__)))
18#define UNLOCK_FUNCTION(...) __attribute__ ((unlock_function(__VA_ARGS__)))
19#define LOCK_RETURNED(x) __attribute__ ((lock_returned(x)))
20#define LOCKS_EXCLUDED(...) __attribute__ ((locks_excluded(__VA_ARGS__)))
21#define EXCLUSIVE_LOCKS_REQUIRED(...) \
22 __attribute__ ((exclusive_locks_required(__VA_ARGS__)))
23#define SHARED_LOCKS_REQUIRED(...) \
24 __attribute__ ((shared_locks_required(__VA_ARGS__)))
25#define NO_THREAD_SAFETY_ANALYSIS __attribute__ ((no_thread_safety_analysis))
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +000026
27//-----------------------------------------//
28// Helper fields
29//-----------------------------------------//
30
31
32class __attribute__((lockable)) Mutex {
33 public:
34 void Lock() __attribute__((exclusive_lock_function));
35 void ReaderLock() __attribute__((shared_lock_function));
36 void Unlock() __attribute__((unlock_function));
37 bool TryLock() __attribute__((exclusive_trylock_function(true)));
38 bool ReaderTryLock() __attribute__((shared_trylock_function(true)));
39 void LockWhen(const int &cond) __attribute__((exclusive_lock_function));
40};
41
42
43Mutex sls_mu;
44
45Mutex sls_mu2 __attribute__((acquired_after(sls_mu)));
46int sls_guard_var __attribute__((guarded_var)) = 0;
47int sls_guardby_var __attribute__((guarded_by(sls_mu))) = 0;
48
49bool getBool();
50
51class MutexWrapper {
52public:
53 Mutex mu;
Caitlin Sadowski194418f2011-09-14 20:00:24 +000054 int x __attribute__((guarded_by(mu)));
55 void MyLock() __attribute__((exclusive_lock_function(mu)));
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +000056};
57
58MutexWrapper sls_mw;
59
60void sls_fun_0() {
61 sls_mw.mu.Lock();
Caitlin Sadowski194418f2011-09-14 20:00:24 +000062 sls_mw.x = 5;
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +000063 sls_mw.mu.Unlock();
64}
65
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +000066void sls_fun_2() {
67 sls_mu.Lock();
68 int x = sls_guard_var;
69 sls_mu.Unlock();
70}
71
72void sls_fun_3() {
73 sls_mu.Lock();
74 sls_guard_var = 2;
75 sls_mu.Unlock();
76}
77
78void sls_fun_4() {
79 sls_mu2.Lock();
80 sls_guard_var = 2;
81 sls_mu2.Unlock();
82}
83
84void sls_fun_5() {
85 sls_mu.Lock();
86 int x = sls_guardby_var;
87 sls_mu.Unlock();
88}
89
90void sls_fun_6() {
91 sls_mu.Lock();
92 sls_guardby_var = 2;
93 sls_mu.Unlock();
94}
95
96void sls_fun_7() {
97 sls_mu.Lock();
98 sls_mu2.Lock();
99 sls_mu2.Unlock();
100 sls_mu.Unlock();
101}
102
103void sls_fun_8() {
104 sls_mu.Lock();
105 if (getBool())
106 sls_mu.Unlock();
107 else
108 sls_mu.Unlock();
109}
110
111void sls_fun_9() {
112 if (getBool())
113 sls_mu.Lock();
114 else
115 sls_mu.Lock();
116 sls_mu.Unlock();
117}
118
119void sls_fun_good_6() {
120 if (getBool()) {
121 sls_mu.Lock();
122 } else {
123 if (getBool()) {
124 getBool(); // EMPTY
125 } else {
126 getBool(); // EMPTY
127 }
128 sls_mu.Lock();
129 }
130 sls_mu.Unlock();
131}
132
133void sls_fun_good_7() {
134 sls_mu.Lock();
135 while (getBool()) {
136 sls_mu.Unlock();
137 if (getBool()) {
138 if (getBool()) {
139 sls_mu.Lock();
140 continue;
141 }
142 }
143 sls_mu.Lock();
144 }
145 sls_mu.Unlock();
146}
147
Caitlin Sadowski194418f2011-09-14 20:00:24 +0000148void sls_fun_good_8() {
149 sls_mw.MyLock();
150 sls_mw.mu.Unlock();
151}
152
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000153void sls_fun_bad_1() {
154 sls_mu.Unlock(); // \
Caitlin Sadowski8bccabe2011-09-08 21:52:50 +0000155 // expected-warning{{unlocking 'sls_mu' that was not locked}}
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000156}
157
158void sls_fun_bad_2() {
159 sls_mu.Lock();
160 sls_mu.Lock(); // \
Caitlin Sadowski8bccabe2011-09-08 21:52:50 +0000161 // expected-warning{{locking 'sls_mu' that is already locked}}
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000162 sls_mu.Unlock();
163}
164
165void sls_fun_bad_3() {
166 sls_mu.Lock(); // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000167 // expected-warning{{mutex 'sls_mu' is still locked at the end of function 'sls_fun_bad_3'}}
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000168}
169
170void sls_fun_bad_4() {
171 if (getBool())
172 sls_mu.Lock(); // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000173 // expected-warning{{mutex 'sls_mu' is still locked at the end of its scope}}
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000174 else
175 sls_mu2.Lock(); // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000176 // expected-warning{{mutex 'sls_mu2' is still locked at the end of its scope}}
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000177}
178
179void sls_fun_bad_5() {
180 sls_mu.Lock(); // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000181 // expected-warning{{mutex 'sls_mu' is still locked at the end of its scope}}
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000182 if (getBool())
183 sls_mu.Unlock();
184}
185
186void sls_fun_bad_6() {
187 if (getBool()) {
188 sls_mu.Lock(); // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000189 // expected-warning{{mutex 'sls_mu' is still locked at the end of its scope}}
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000190 } else {
191 if (getBool()) {
192 getBool(); // EMPTY
193 } else {
194 getBool(); // EMPTY
195 }
196 }
197 sls_mu.Unlock(); // \
Caitlin Sadowski8bccabe2011-09-08 21:52:50 +0000198 // expected-warning{{unlocking 'sls_mu' that was not locked}}
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000199}
200
201void sls_fun_bad_7() {
Caitlin Sadowski4e4bc752011-09-15 17:25:19 +0000202 sls_mu.Lock(); // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000203 // expected-warning{{expecting mutex 'sls_mu' to be locked at start of each loop}}
Caitlin Sadowski4e4bc752011-09-15 17:25:19 +0000204 while (getBool()) {
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000205 sls_mu.Unlock();
206 if (getBool()) {
207 if (getBool()) {
208 continue;
209 }
210 }
211 sls_mu.Lock(); // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000212 // expected-warning{{mutex 'sls_mu' is still locked at the end of its scope}}
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000213 }
214 sls_mu.Unlock();
215}
216
217void sls_fun_bad_8() {
Caitlin Sadowski4e4bc752011-09-15 17:25:19 +0000218 sls_mu.Lock(); // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000219 // expected-warning{{expecting mutex 'sls_mu' to be locked at start of each loop}}
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000220 do {
Caitlin Sadowski4e4bc752011-09-15 17:25:19 +0000221 sls_mu.Unlock();
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000222 } while (getBool());
223}
224
225void sls_fun_bad_9() {
226 do {
227 sls_mu.Lock(); // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000228 // expected-warning{{expecting mutex 'sls_mu' to be locked at start of each loop}}
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000229 } while (getBool());
230 sls_mu.Unlock();
231}
232
233void sls_fun_bad_10() {
234 sls_mu.Lock(); // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000235 // expected-warning{{mutex 'sls_mu' is still locked at the end of function 'sls_fun_bad_10'}} \
236 // expected-warning{{expecting mutex 'sls_mu' to be locked at start of each loop}}
Caitlin Sadowski4e4bc752011-09-15 17:25:19 +0000237 while(getBool()) {
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000238 sls_mu.Unlock();
239 }
240}
241
242void sls_fun_bad_11() {
243 while (getBool()) {
244 sls_mu.Lock(); // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000245 // expected-warning{{expecting mutex 'sls_mu' to be locked at start of each loop}}
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000246 }
247 sls_mu.Unlock(); // \
Caitlin Sadowski8bccabe2011-09-08 21:52:50 +0000248 // expected-warning{{unlocking 'sls_mu' that was not locked}}
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000249}
250
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000251//-----------------------------------------//
252// Handling lock expressions in attribute args
253// -------------------------------------------//
254
255Mutex aa_mu;
256
257class GlobalLocker {
258public:
259 void globalLock() __attribute__((exclusive_lock_function(aa_mu)));
260 void globalUnlock() __attribute__((unlock_function(aa_mu)));
261};
262
263GlobalLocker glock;
264
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000265void aa_fun_1() {
266 glock.globalLock();
267 glock.globalUnlock();
268}
269
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000270void aa_fun_bad_1() {
271 glock.globalUnlock(); // \
Caitlin Sadowski8bccabe2011-09-08 21:52:50 +0000272 // expected-warning{{unlocking 'aa_mu' that was not locked}}
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000273}
274
275void aa_fun_bad_2() {
276 glock.globalLock();
277 glock.globalLock(); // \
Caitlin Sadowski8bccabe2011-09-08 21:52:50 +0000278 // expected-warning{{locking 'aa_mu' that is already locked}}
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000279 glock.globalUnlock();
280}
281
282void aa_fun_bad_3() {
283 glock.globalLock(); // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000284 // expected-warning{{mutex 'aa_mu' is still locked at the end of function 'aa_fun_bad_3'}}
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000285}
Caitlin Sadowskib4d0a962011-08-29 17:12:27 +0000286
Caitlin Sadowskib4d0a962011-08-29 17:12:27 +0000287//--------------------------------------------------//
288// Regression tests for unusual method names
289//--------------------------------------------------//
290
291Mutex wmu;
292
293// Test diagnostics for other method names.
294class WeirdMethods {
295 WeirdMethods() {
296 wmu.Lock(); // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000297 // expected-warning {{mutex 'wmu' is still locked at the end of function 'WeirdMethods'}}
Caitlin Sadowskib4d0a962011-08-29 17:12:27 +0000298 }
299 ~WeirdMethods() {
300 wmu.Lock(); // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000301 // expected-warning {{mutex 'wmu' is still locked at the end of function '~WeirdMethods'}}
Caitlin Sadowskib4d0a962011-08-29 17:12:27 +0000302 }
303 void operator++() {
304 wmu.Lock(); // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000305 // expected-warning {{mutex 'wmu' is still locked at the end of function 'operator++'}}
Caitlin Sadowskib4d0a962011-08-29 17:12:27 +0000306 }
307 operator int*() {
308 wmu.Lock(); // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000309 // expected-warning {{mutex 'wmu' is still locked at the end of function 'operator int *'}}
Caitlin Sadowskib4d0a962011-08-29 17:12:27 +0000310 return 0;
311 }
312};
313
Caitlin Sadowski05b436e2011-08-29 22:27:51 +0000314//-----------------------------------------------//
315// Errors for guarded by or guarded var variables
316// ----------------------------------------------//
317
318int *pgb_gvar __attribute__((pt_guarded_var));
319int *pgb_var __attribute__((pt_guarded_by(sls_mu)));
320
321class PGBFoo {
322 public:
323 int x;
324 int *pgb_field __attribute__((guarded_by(sls_mu2)))
325 __attribute__((pt_guarded_by(sls_mu)));
326 void testFoo() {
327 pgb_field = &x; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000328 // expected-warning {{writing variable 'pgb_field' requires locking 'sls_mu2' exclusively}}
329 *pgb_field = x; // expected-warning {{reading variable 'pgb_field' requires locking 'sls_mu2'}} \
330 // expected-warning {{writing the value pointed to by 'pgb_field' requires locking 'sls_mu' exclusively}}
331 x = *pgb_field; // expected-warning {{reading variable 'pgb_field' requires locking 'sls_mu2'}} \
332 // expected-warning {{reading the value pointed to by 'pgb_field' requires locking 'sls_mu'}}
333 (*pgb_field)++; // expected-warning {{reading variable 'pgb_field' requires locking 'sls_mu2'}} \
334 // expected-warning {{writing the value pointed to by 'pgb_field' requires locking 'sls_mu' exclusively}}
Caitlin Sadowski05b436e2011-08-29 22:27:51 +0000335 }
336};
337
338class GBFoo {
339 public:
340 int gb_field __attribute__((guarded_by(sls_mu)));
341
342 void testFoo() {
343 gb_field = 0; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000344 // expected-warning {{writing variable 'gb_field' requires locking 'sls_mu' exclusively}}
Caitlin Sadowski05b436e2011-08-29 22:27:51 +0000345 }
Caitlin Sadowskiaf370612011-09-08 18:35:21 +0000346
347 void testNoAnal() __attribute__((no_thread_safety_analysis)) {
348 gb_field = 0;
349 }
Caitlin Sadowski05b436e2011-08-29 22:27:51 +0000350};
351
352GBFoo GlobalGBFoo __attribute__((guarded_by(sls_mu)));
353
354void gb_fun_0() {
355 sls_mu.Lock();
356 int x = *pgb_var;
357 sls_mu.Unlock();
358}
359
360void gb_fun_1() {
361 sls_mu.Lock();
362 *pgb_var = 2;
363 sls_mu.Unlock();
364}
365
366void gb_fun_2() {
367 int x;
368 pgb_var = &x;
369}
370
371void gb_fun_3() {
372 int *x = pgb_var;
373}
374
375void gb_bad_0() {
376 sls_guard_var = 1; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000377 // expected-warning{{writing variable 'sls_guard_var' requires locking any mutex exclusively}}
Caitlin Sadowski05b436e2011-08-29 22:27:51 +0000378}
379
380void gb_bad_1() {
381 int x = sls_guard_var; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000382 // expected-warning{{reading variable 'sls_guard_var' requires locking any mutex}}
Caitlin Sadowski05b436e2011-08-29 22:27:51 +0000383}
384
385void gb_bad_2() {
386 sls_guardby_var = 1; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000387 // expected-warning {{writing variable 'sls_guardby_var' requires locking 'sls_mu' exclusively}}
Caitlin Sadowski05b436e2011-08-29 22:27:51 +0000388}
389
390void gb_bad_3() {
391 int x = sls_guardby_var; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000392 // expected-warning {{reading variable 'sls_guardby_var' requires locking 'sls_mu'}}
Caitlin Sadowski05b436e2011-08-29 22:27:51 +0000393}
394
395void gb_bad_4() {
396 *pgb_gvar = 1; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000397 // expected-warning {{writing the value pointed to by 'pgb_gvar' requires locking any mutex exclusively}}
Caitlin Sadowski05b436e2011-08-29 22:27:51 +0000398}
399
400void gb_bad_5() {
401 int x = *pgb_gvar; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000402 // expected-warning {{reading the value pointed to by 'pgb_gvar' requires locking any mutex}}
Caitlin Sadowski05b436e2011-08-29 22:27:51 +0000403}
404
405void gb_bad_6() {
406 *pgb_var = 1; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000407 // expected-warning {{writing the value pointed to by 'pgb_var' requires locking 'sls_mu' exclusively}}
Caitlin Sadowski05b436e2011-08-29 22:27:51 +0000408}
409
410void gb_bad_7() {
411 int x = *pgb_var; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000412 // expected-warning {{reading the value pointed to by 'pgb_var' requires locking 'sls_mu'}}
Caitlin Sadowski05b436e2011-08-29 22:27:51 +0000413}
414
415void gb_bad_8() {
416 GBFoo G;
417 G.gb_field = 0; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000418 // expected-warning {{writing variable 'gb_field' requires locking 'sls_mu'}}
Caitlin Sadowski05b436e2011-08-29 22:27:51 +0000419}
420
421void gb_bad_9() {
422 sls_guard_var++; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000423 // expected-warning{{writing variable 'sls_guard_var' requires locking any mutex exclusively}}
Caitlin Sadowski05b436e2011-08-29 22:27:51 +0000424 sls_guard_var--; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000425 // expected-warning{{writing variable 'sls_guard_var' requires locking any mutex exclusively}}
Caitlin Sadowski05b436e2011-08-29 22:27:51 +0000426 ++sls_guard_var; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000427 // expected-warning{{writing variable 'sls_guard_var' requires locking any mutex exclusively}}
Caitlin Sadowskia49d1d82011-09-09 16:07:55 +0000428 --sls_guard_var;// \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000429 // expected-warning{{writing variable 'sls_guard_var' requires locking any mutex exclusively}}
Caitlin Sadowski05b436e2011-08-29 22:27:51 +0000430}
Caitlin Sadowskib4d0a962011-08-29 17:12:27 +0000431
Caitlin Sadowskieff98fc2011-09-08 17:42:22 +0000432//-----------------------------------------------//
433// Warnings on variables with late parsed attributes
434// ----------------------------------------------//
435
436class LateFoo {
437public:
438 int a __attribute__((guarded_by(mu)));
439 int b;
440
441 void foo() __attribute__((exclusive_locks_required(mu))) { }
442
443 void test() {
444 a = 0; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000445 // expected-warning{{writing variable 'a' requires locking 'mu' exclusively}}
Caitlin Sadowskieff98fc2011-09-08 17:42:22 +0000446 b = a; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000447 // expected-warning {{reading variable 'a' requires locking 'mu'}}
Caitlin Sadowskieff98fc2011-09-08 17:42:22 +0000448 c = 0; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000449 // expected-warning {{writing variable 'c' requires locking 'mu' exclusively}}
Caitlin Sadowskieff98fc2011-09-08 17:42:22 +0000450 }
451
452 int c __attribute__((guarded_by(mu)));
453
454 Mutex mu;
455};
456
Caitlin Sadowski99107eb2011-09-09 16:21:55 +0000457class LateBar {
458 public:
459 int a_ __attribute__((guarded_by(mu1_)));
460 int b_;
461 int *q __attribute__((pt_guarded_by(mu)));
462 Mutex mu1_;
463 Mutex mu;
464 LateFoo Foo;
465 LateFoo Foo2;
466 LateFoo *FooPointer;
467};
468
469LateBar b1, *b3;
470
471void late_0() {
472 LateFoo FooA;
473 LateFoo FooB;
474 FooA.mu.Lock();
475 FooA.a = 5;
476 FooA.mu.Unlock();
477}
478
479void late_1() {
480 LateBar BarA;
481 BarA.FooPointer->mu.Lock();
482 BarA.FooPointer->a = 2;
483 BarA.FooPointer->mu.Unlock();
484}
485
486void late_bad_0() {
487 LateFoo fooA;
488 LateFoo fooB;
489 fooA.mu.Lock();
490 fooB.a = 5; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000491 // expected-warning{{writing variable 'a' requires locking 'mu' exclusively}}
Caitlin Sadowski99107eb2011-09-09 16:21:55 +0000492 fooA.mu.Unlock();
493}
494
495void late_bad_1() {
496 Mutex mu;
497 mu.Lock();
498 b1.mu1_.Lock();
499 int res = b1.a_ + b3->b_;
500 b3->b_ = *b1.q; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000501 // expected-warning{{reading the value pointed to by 'q' requires locking 'mu'}}
Caitlin Sadowski99107eb2011-09-09 16:21:55 +0000502 b1.mu1_.Unlock();
503 b1.b_ = res;
504 mu.Unlock();
505}
506
507void late_bad_2() {
508 LateBar BarA;
509 BarA.FooPointer->mu.Lock();
510 BarA.Foo.a = 2; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000511 // expected-warning{{writing variable 'a' requires locking 'mu' exclusively}}
Caitlin Sadowski99107eb2011-09-09 16:21:55 +0000512 BarA.FooPointer->mu.Unlock();
513}
514
515void late_bad_3() {
516 LateBar BarA;
517 BarA.Foo.mu.Lock();
518 BarA.FooPointer->a = 2; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000519 // expected-warning{{writing variable 'a' requires locking 'mu' exclusively}}
Caitlin Sadowski99107eb2011-09-09 16:21:55 +0000520 BarA.Foo.mu.Unlock();
521}
522
523void late_bad_4() {
524 LateBar BarA;
525 BarA.Foo.mu.Lock();
526 BarA.Foo2.a = 2; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000527 // expected-warning{{writing variable 'a' requires locking 'mu' exclusively}}
Caitlin Sadowski99107eb2011-09-09 16:21:55 +0000528 BarA.Foo.mu.Unlock();
529}
530
Caitlin Sadowskia53257c2011-09-08 18:19:38 +0000531//-----------------------------------------------//
532// Extra warnings for shared vs. exclusive locks
533// ----------------------------------------------//
534
535void shared_fun_0() {
536 sls_mu.Lock();
537 do {
538 sls_mu.Unlock();
539 sls_mu.Lock();
540 } while (getBool());
541 sls_mu.Unlock();
542}
543
544void shared_fun_1() {
Caitlin Sadowski4e4bc752011-09-15 17:25:19 +0000545 sls_mu.ReaderLock(); // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000546 // expected-warning {{mutex 'sls_mu' is locked exclusively and shared in the same scope}}
Caitlin Sadowskia53257c2011-09-08 18:19:38 +0000547 do {
548 sls_mu.Unlock();
Caitlin Sadowski4e4bc752011-09-15 17:25:19 +0000549 sls_mu.Lock(); // \
550 // expected-note {{the other lock of mutex 'sls_mu' is here}}
Caitlin Sadowskia53257c2011-09-08 18:19:38 +0000551 } while (getBool());
552 sls_mu.Unlock();
553}
554
555void shared_fun_3() {
556 if (getBool())
557 sls_mu.Lock();
558 else
559 sls_mu.Lock();
560 *pgb_var = 1;
561 sls_mu.Unlock();
562}
563
564void shared_fun_4() {
565 if (getBool())
566 sls_mu.ReaderLock();
567 else
568 sls_mu.ReaderLock();
569 int x = sls_guardby_var;
570 sls_mu.Unlock();
571}
572
573void shared_fun_8() {
574 if (getBool())
575 sls_mu.Lock(); // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000576 // expected-warning {{mutex 'sls_mu' is locked exclusively and shared in the same scope}}
Caitlin Sadowskia53257c2011-09-08 18:19:38 +0000577 else
578 sls_mu.ReaderLock(); // \
Caitlin Sadowski8bccabe2011-09-08 21:52:50 +0000579 // expected-note {{the other lock of mutex 'sls_mu' is here}}
Caitlin Sadowskia53257c2011-09-08 18:19:38 +0000580 sls_mu.Unlock();
581}
582
583void shared_bad_0() {
Caitlin Sadowski4e4bc752011-09-15 17:25:19 +0000584 sls_mu.Lock(); // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000585 // expected-warning {{mutex 'sls_mu' is locked exclusively and shared in the same scope}}
Caitlin Sadowskia53257c2011-09-08 18:19:38 +0000586 do {
587 sls_mu.Unlock();
Caitlin Sadowski4e4bc752011-09-15 17:25:19 +0000588 sls_mu.ReaderLock(); // \
589 // expected-note {{the other lock of mutex 'sls_mu' is here}}
Caitlin Sadowskia53257c2011-09-08 18:19:38 +0000590 } while (getBool());
591 sls_mu.Unlock();
592}
593
594void shared_bad_1() {
595 if (getBool())
596 sls_mu.Lock(); // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000597 // expected-warning {{mutex 'sls_mu' is locked exclusively and shared in the same scope}}
Caitlin Sadowskia53257c2011-09-08 18:19:38 +0000598 else
599 sls_mu.ReaderLock(); // \
Caitlin Sadowski8bccabe2011-09-08 21:52:50 +0000600 // expected-note {{the other lock of mutex 'sls_mu' is here}}
Caitlin Sadowskia53257c2011-09-08 18:19:38 +0000601 *pgb_var = 1;
602 sls_mu.Unlock();
603}
604
605void shared_bad_2() {
606 if (getBool())
607 sls_mu.ReaderLock(); // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000608 // expected-warning {{mutex 'sls_mu' is locked exclusively and shared in the same scope}}
Caitlin Sadowskia53257c2011-09-08 18:19:38 +0000609 else
610 sls_mu.Lock(); // \
Caitlin Sadowski8bccabe2011-09-08 21:52:50 +0000611 // expected-note {{the other lock of mutex 'sls_mu' is here}}
Caitlin Sadowskia53257c2011-09-08 18:19:38 +0000612 *pgb_var = 1;
613 sls_mu.Unlock();
614}
Caitlin Sadowski978191e2011-09-08 18:27:31 +0000615
616// FIXME: Add support for functions (not only methods)
617class LRBar {
618 public:
619 void aa_elr_fun() __attribute__((exclusive_locks_required(aa_mu)));
620 void aa_elr_fun_s() __attribute__((shared_locks_required(aa_mu)));
621 void le_fun() __attribute__((locks_excluded(sls_mu)));
622};
623
624class LRFoo {
625 public:
626 void test() __attribute__((exclusive_locks_required(sls_mu)));
627 void testShared() __attribute__((shared_locks_required(sls_mu2)));
628};
629
630void elr_fun() __attribute__((exclusive_locks_required(sls_mu)));
631void elr_fun() {}
632
633LRFoo MyLRFoo;
634LRBar Bar;
635
636void es_fun_0() {
637 aa_mu.Lock();
638 Bar.aa_elr_fun();
639 aa_mu.Unlock();
640}
641
642void es_fun_1() {
643 aa_mu.Lock();
644 Bar.aa_elr_fun_s();
645 aa_mu.Unlock();
646}
647
648void es_fun_2() {
649 aa_mu.ReaderLock();
650 Bar.aa_elr_fun_s();
651 aa_mu.Unlock();
652}
653
654void es_fun_3() {
655 sls_mu.Lock();
656 MyLRFoo.test();
657 sls_mu.Unlock();
658}
659
660void es_fun_4() {
661 sls_mu2.Lock();
662 MyLRFoo.testShared();
663 sls_mu2.Unlock();
664}
665
666void es_fun_5() {
667 sls_mu2.ReaderLock();
668 MyLRFoo.testShared();
669 sls_mu2.Unlock();
670}
671
672void es_fun_6() {
673 Bar.le_fun();
674}
675
676void es_fun_7() {
677 sls_mu.Lock();
678 elr_fun();
679 sls_mu.Unlock();
680}
681
Caitlin Sadowskiaf370612011-09-08 18:35:21 +0000682void es_fun_8() __attribute__((no_thread_safety_analysis));
683
684void es_fun_8() {
685 Bar.aa_elr_fun_s();
686}
687
Caitlin Sadowskicb967512011-09-15 17:43:08 +0000688void es_fun_9() __attribute__((shared_locks_required(aa_mu)));
689void es_fun_9() {
690 Bar.aa_elr_fun_s();
691}
692
693void es_fun_10() __attribute__((exclusive_locks_required(aa_mu)));
694void es_fun_10() {
695 Bar.aa_elr_fun_s();
696}
697
Caitlin Sadowski978191e2011-09-08 18:27:31 +0000698void es_bad_0() {
699 Bar.aa_elr_fun(); // \
Caitlin Sadowski8bccabe2011-09-08 21:52:50 +0000700 // expected-warning {{calling function 'aa_elr_fun' requires exclusive lock on 'aa_mu'}}
Caitlin Sadowski978191e2011-09-08 18:27:31 +0000701}
702
703void es_bad_1() {
704 aa_mu.ReaderLock();
705 Bar.aa_elr_fun(); // \
Caitlin Sadowski8bccabe2011-09-08 21:52:50 +0000706 // expected-warning {{calling function 'aa_elr_fun' requires exclusive lock on 'aa_mu'}}
Caitlin Sadowski978191e2011-09-08 18:27:31 +0000707 aa_mu.Unlock();
708}
709
710void es_bad_2() {
711 Bar.aa_elr_fun_s(); // \
Caitlin Sadowski8bccabe2011-09-08 21:52:50 +0000712 // expected-warning {{calling function 'aa_elr_fun_s' requires shared lock on 'aa_mu'}}
Caitlin Sadowski978191e2011-09-08 18:27:31 +0000713}
714
715void es_bad_3() {
716 MyLRFoo.test(); // \
Caitlin Sadowski8bccabe2011-09-08 21:52:50 +0000717 // expected-warning {{calling function 'test' requires exclusive lock on 'sls_mu'}}
Caitlin Sadowski978191e2011-09-08 18:27:31 +0000718}
719
720void es_bad_4() {
721 MyLRFoo.testShared(); // \
Caitlin Sadowski8bccabe2011-09-08 21:52:50 +0000722 // expected-warning {{calling function 'testShared' requires shared lock on 'sls_mu2'}}
Caitlin Sadowski978191e2011-09-08 18:27:31 +0000723}
724
725void es_bad_5() {
726 sls_mu.ReaderLock();
727 MyLRFoo.test(); // \
Caitlin Sadowski8bccabe2011-09-08 21:52:50 +0000728 // expected-warning {{calling function 'test' requires exclusive lock on 'sls_mu'}}
Caitlin Sadowski978191e2011-09-08 18:27:31 +0000729 sls_mu.Unlock();
730}
731
732void es_bad_6() {
733 sls_mu.Lock();
734 Bar.le_fun(); // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000735 // expected-warning {{cannot call function 'le_fun' while mutex 'sls_mu' is locked}}
Caitlin Sadowski978191e2011-09-08 18:27:31 +0000736 sls_mu.Unlock();
737}
738
739void es_bad_7() {
740 sls_mu.ReaderLock();
741 Bar.le_fun(); // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000742 // expected-warning {{cannot call function 'le_fun' while mutex 'sls_mu' is locked}}
Caitlin Sadowski978191e2011-09-08 18:27:31 +0000743 sls_mu.Unlock();
744}
Caitlin Sadowski194418f2011-09-14 20:00:24 +0000745
746//-----------------------------------------------//
747// Unparseable lock expressions
748// ----------------------------------------------//
749
750Mutex UPmu;
751// FIXME: add support for lock expressions involving arrays.
752Mutex mua[5];
753
754int x __attribute__((guarded_by(UPmu = sls_mu))); // \
755 // expected-warning{{cannot resolve lock expression to a specific lockable object}}
756int y __attribute__((guarded_by(mua[0]))); // \
757 // expected-warning{{cannot resolve lock expression to a specific lockable object}}
758
759
760void testUnparse() {
761 // no errors, since the lock expressions are not resolved
762 x = 5;
763 y = 5;
764}
765
766void testUnparse2() {
767 mua[0].Lock(); // \
768 // expected-warning{{cannot resolve lock expression to a specific lockable object}}
769 (&(mua[0]) + 4)->Lock(); // \
770 // expected-warning{{cannot resolve lock expression to a specific lockable object}}
771}
772
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +0000773
774//----------------------------------------------------------------------------//
775// The following test cases are ported from the gcc thread safety implementation
776// They are each wrapped inside a namespace with the test number of the gcc test
777//
778// FIXME: add all the gcc tests, once this analysis passes them.
779//----------------------------------------------------------------------------//
780
781//-----------------------------------------//
782// Good testcases (no errors)
783//-----------------------------------------//
784
785namespace thread_annot_lock_20 {
786class Bar {
787 public:
788 static int func1() EXCLUSIVE_LOCKS_REQUIRED(mu1_);
789 static int b_ GUARDED_BY(mu1_);
790 static Mutex mu1_;
791 static int a_ GUARDED_BY(mu1_);
792};
793
794Bar b1;
795
796int Bar::func1()
797{
798 int res = 5;
799
800 if (a_ == 4)
801 res = b_;
802 return res;
803}
804} // end namespace thread_annot_lock_20
805
806namespace thread_annot_lock_22 {
807// Test various usage of GUARDED_BY and PT_GUARDED_BY annotations, especially
808// uses in class definitions.
809Mutex mu;
810
811class Bar {
812 public:
813 int a_ GUARDED_BY(mu1_);
814 int b_;
815 int *q PT_GUARDED_BY(mu);
816 Mutex mu1_ ACQUIRED_AFTER(mu);
817};
818
819Bar b1, *b3;
820int *p GUARDED_BY(mu) PT_GUARDED_BY(mu);
821int res GUARDED_BY(mu) = 5;
822
823int func(int i)
824{
825 int x;
826 mu.Lock();
827 b1.mu1_.Lock();
828 res = b1.a_ + b3->b_;
829 *p = i;
830 b1.a_ = res + b3->b_;
831 b3->b_ = *b1.q;
832 b1.mu1_.Unlock();
833 b1.b_ = res;
834 x = res;
835 mu.Unlock();
836 return x;
837}
838} // end namespace thread_annot_lock_22
839
840namespace thread_annot_lock_27_modified {
841// test lock annotations applied to function definitions
842// Modified: applied annotations only to function declarations
843Mutex mu1;
844Mutex mu2 ACQUIRED_AFTER(mu1);
845
846class Foo {
847 public:
848 int method1(int i) SHARED_LOCKS_REQUIRED(mu2) EXCLUSIVE_LOCKS_REQUIRED(mu1);
849};
850
851int Foo::method1(int i) {
852 return i;
853}
854
855
856int foo(int i) EXCLUSIVE_LOCKS_REQUIRED(mu2) SHARED_LOCKS_REQUIRED(mu1);
857int foo(int i) {
858 return i;
859}
860
861static int bar(int i) EXCLUSIVE_LOCKS_REQUIRED(mu1);
862static int bar(int i) {
863 return i;
864}
865
866void main() {
867 Foo a;
868
869 mu1.Lock();
870 mu2.Lock();
871 a.method1(1);
872 foo(2);
873 mu2.Unlock();
874 bar(3);
875 mu1.Unlock();
876}
877} // end namespace thread_annot_lock_27_modified
878
879
880namespace thread_annot_lock_38 {
881// Test the case where a template member function is annotated with lock
882// attributes in a non-template class.
883class Foo {
884 public:
885 void func1(int y) LOCKS_EXCLUDED(mu_);
886 template <typename T> void func2(T x) LOCKS_EXCLUDED(mu_);
887 private:
888 Mutex mu_;
889};
890
891Foo *foo;
892
893void main()
894{
895 foo->func1(5);
896 foo->func2(5);
897}
898} // end namespace thread_annot_lock_38
899
900namespace thread_annot_lock_43 {
901// Tests lock canonicalization
902class Foo {
903 public:
904 Mutex *mu_;
905};
906
907class FooBar {
908 public:
909 Foo *foo_;
910 int GetA() EXCLUSIVE_LOCKS_REQUIRED(foo_->mu_) { return a_; }
911 int a_ GUARDED_BY(foo_->mu_);
912};
913
914FooBar *fb;
915
916void main()
917{
918 int x;
919 fb->foo_->mu_->Lock();
920 x = fb->GetA();
921 fb->foo_->mu_->Unlock();
922}
923} // end namespace thread_annot_lock_43
924
925namespace thread_annot_lock_49 {
926// Test the support for use of lock expression in the annotations
927class Foo {
928 public:
929 Mutex foo_mu_;
930};
931
932class Bar {
933 private:
934 Foo *foo;
935 Mutex bar_mu_ ACQUIRED_AFTER(foo->foo_mu_);
936
937 public:
938 void Test1() {
939 foo->foo_mu_.Lock();
940 bar_mu_.Lock();
941 bar_mu_.Unlock();
942 foo->foo_mu_.Unlock();
943 }
944};
945
946void main() {
947 Bar bar;
948 bar.Test1();
949}
950} // end namespace thread_annot_lock_49
951
952namespace thread_annot_lock_61_modified {
953 // Modified to fix the compiler errors
954 // Test the fix for a bug introduced by the support of pass-by-reference
955 // paramters.
956 struct Foo { Foo &operator<< (bool) {return *this;} };
957 Foo &getFoo();
958 struct Bar { Foo &func () {return getFoo();} };
959 struct Bas { void operator& (Foo &) {} };
960 void mumble()
961 {
962 Bas() & Bar().func() << "" << "";
963 Bas() & Bar().func() << "";
964 }
965} // end namespace thread_annot_lock_61_modified
966
967
968namespace thread_annot_lock_65 {
969// Test the fix for a bug in the support of allowing reader locks for
970// non-const, non-modifying overload functions. (We didn't handle the builtin
971// properly.)
972enum MyFlags {
973 Zero,
974 One,
975 Two,
976 Three,
977 Four,
978 Five,
979 Six,
980 Seven,
981 Eight,
982 Nine
983};
984
985inline MyFlags
986operator|(MyFlags a, MyFlags b)
987{
988 return MyFlags(static_cast<int>(a) | static_cast<int>(b));
989}
990
991inline MyFlags&
992operator|=(MyFlags& a, MyFlags b)
993{
994 return a = a | b;
995}
996} // end namespace thread_annot_lock_65
997
998namespace thread_annot_lock_66_modified {
999// Modified: Moved annotation to function defn
1000// Test annotations on out-of-line definitions of member functions where the
1001// annotations refer to locks that are also data members in the class.
1002Mutex mu;
1003
1004class Foo {
1005 public:
1006 int method1(int i) SHARED_LOCKS_REQUIRED(mu1, mu, mu2);
1007 int data GUARDED_BY(mu1);
1008 Mutex *mu1;
1009 Mutex *mu2;
1010};
1011
1012int Foo::method1(int i)
1013{
1014 return data + i;
1015}
1016
1017void main()
1018{
1019 Foo a;
1020
1021 a.mu2->Lock();
1022 a.mu1->Lock();
1023 mu.Lock();
1024 a.method1(1);
1025 mu.Unlock();
1026 a.mu1->Unlock();
1027 a.mu2->Unlock();
1028}
1029} // end namespace thread_annot_lock_66_modified
1030
1031namespace thread_annot_lock_68_modified {
1032// Test a fix to a bug in the delayed name binding with nested template
1033// instantiation. We use a stack to make sure a name is not resolved to an
1034// inner context.
1035template <typename T>
1036class Bar {
1037 Mutex mu_;
1038};
1039
1040template <typename T>
1041class Foo {
1042 public:
1043 void func(T x) {
1044 mu_.Lock();
1045 count_ = x;
1046 mu_.Unlock();
1047 }
1048
1049 private:
1050 T count_ GUARDED_BY(mu_);
1051 Bar<T> bar_;
1052 Mutex mu_;
1053};
1054
1055void main()
1056{
1057 Foo<int> *foo;
1058 foo->func(5);
1059}
1060} // end namespace thread_annot_lock_68_modified
1061
1062namespace thread_annot_lock_30_modified {
1063// Test delay parsing of lock attribute arguments with nested classes.
1064// Modified: trylocks replaced with exclusive_lock_fun
1065int a = 0;
1066
1067class Bar {
1068 struct Foo;
1069
1070 public:
1071 void MyLock() EXCLUSIVE_LOCK_FUNCTION(mu);
1072
1073 int func() {
1074 MyLock();
1075// if (foo == 0) {
1076// return 0;
1077// }
1078 a = 5;
1079 mu.Unlock();
1080 return 1;
1081 }
1082
1083 class FooBar {
1084 int x;
1085 int y;
1086 };
1087
1088 private:
1089 Mutex mu;
1090};
1091
1092Bar *bar;
1093
1094void main()
1095{
1096 bar->func();
1097}
1098} // end namespace thread_annot_lock_30_modified
1099
1100namespace thread_annot_lock_47 {
1101// Test the support for annotations on virtual functions.
1102// This is a good test case. (i.e. There should be no warning emitted by the
1103// compiler.)
1104class Base {
1105 public:
1106 virtual void func1() EXCLUSIVE_LOCKS_REQUIRED(mu_);
1107 virtual void func2() LOCKS_EXCLUDED(mu_);
1108 Mutex mu_;
1109};
1110
1111class Child : public Base {
1112 public:
1113 virtual void func1() EXCLUSIVE_LOCKS_REQUIRED(mu_);
1114 virtual void func2() LOCKS_EXCLUDED(mu_);
1115};
1116
1117void main() {
1118 Child *c;
1119 Base *b = c;
1120
1121 b->mu_.Lock();
1122 b->func1();
1123 b->mu_.Unlock();
1124 b->func2();
1125
1126 c->mu_.Lock();
1127 c->func1();
1128 c->mu_.Unlock();
1129 c->func2();
1130}
1131} // end namespace thread_annot_lock_47
1132
1133//-----------------------------------------//
1134// Tests which produce errors
1135//-----------------------------------------//
1136
1137namespace thread_annot_lock_13 {
1138Mutex mu1;
1139Mutex mu2;
1140
1141int g GUARDED_BY(mu1);
1142int w GUARDED_BY(mu2);
1143
1144class Foo {
1145 public:
1146 void bar() LOCKS_EXCLUDED(mu_, mu1);
1147 int foo() SHARED_LOCKS_REQUIRED(mu_) EXCLUSIVE_LOCKS_REQUIRED(mu2);
1148
1149 private:
1150 int a_ GUARDED_BY(mu_);
1151 public:
1152 Mutex mu_ ACQUIRED_AFTER(mu1);
1153};
1154
1155int Foo::foo()
1156{
1157 int res;
1158 w = 5.2;
1159 res = a_ + 5;
1160 return res;
1161}
1162
1163void Foo::bar()
1164{
1165 int x;
1166 mu_.Lock();
1167 x = foo(); // expected-warning {{calling function 'foo' requires exclusive lock on 'mu2'}}
1168 a_ = x + 1;
1169 mu_.Unlock();
1170 if (x > 5) {
1171 mu1.Lock();
1172 g = 2.3;
1173 mu1.Unlock();
1174 }
1175}
1176
1177void main()
1178{
1179 Foo f1, *f2;
1180 f1.mu_.Lock();
Caitlin Sadowski74558b42011-09-15 18:13:32 +00001181 f1.bar(); // expected-warning {{cannot call function 'bar' while mutex 'mu_' is locked}}
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001182 mu2.Lock();
1183 f1.foo();
1184 mu2.Unlock();
1185 f1.mu_.Unlock();
1186 f2->mu_.Lock();
Caitlin Sadowski74558b42011-09-15 18:13:32 +00001187 f2->bar(); // expected-warning {{cannot call function 'bar' while mutex 'mu_' is locked}}
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001188 f2->mu_.Unlock();
1189 mu2.Lock();
1190 w = 2.5;
1191 mu2.Unlock();
1192}
1193} // end namespace thread_annot_lock_13
1194
1195namespace thread_annot_lock_18_modified {
1196// Modified: Trylocks removed
1197// Test the ability to distnguish between the same lock field of
1198// different objects of a class.
1199 class Bar {
1200 public:
1201 bool MyLock() EXCLUSIVE_LOCK_FUNCTION(mu1_);
1202 void MyUnlock() UNLOCK_FUNCTION(mu1_);
1203 int a_ GUARDED_BY(mu1_);
1204
1205 private:
1206 Mutex mu1_;
1207};
1208
1209Bar *b1, *b2;
1210
1211void func()
1212{
1213 b1->MyLock();
1214 b1->a_ = 5;
Caitlin Sadowski74558b42011-09-15 18:13:32 +00001215 b2->a_ = 3; // expected-warning {{writing variable 'a_' requires locking 'mu1_' exclusively}}
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001216 b2->MyLock();
1217 b2->MyUnlock();
1218 b1->MyUnlock();
1219}
1220} // end namespace thread_annot_lock_18_modified
1221
1222namespace thread_annot_lock_21 {
1223// Test various usage of GUARDED_BY and PT_GUARDED_BY annotations, especially
1224// uses in class definitions.
1225Mutex mu;
1226
1227class Bar {
1228 public:
1229 int a_ GUARDED_BY(mu1_);
1230 int b_;
1231 int *q PT_GUARDED_BY(mu);
1232 Mutex mu1_ ACQUIRED_AFTER(mu);
1233};
1234
1235Bar b1, *b3;
1236int *p GUARDED_BY(mu) PT_GUARDED_BY(mu);
1237
1238int res GUARDED_BY(mu) = 5;
1239
1240int func(int i)
1241{
1242 int x;
1243 b3->mu1_.Lock();
Caitlin Sadowski74558b42011-09-15 18:13:32 +00001244 res = b1.a_ + b3->b_; // expected-warning {{reading variable 'a_' requires locking 'mu1_'}} \
1245 // expected-warning {{writing variable 'res' requires locking 'mu' exclusively}}
1246 *p = i; // expected-warning {{reading variable 'p' requires locking 'mu'}} \
1247 // expected-warning {{writing the value pointed to by 'p' requires locking 'mu' exclusively}}
1248 b1.a_ = res + b3->b_; // expected-warning {{reading variable 'res' requires locking 'mu'}} \
1249 // expected-warning {{writing variable 'a_' requires locking 'mu1_' exclusively}}
1250 b3->b_ = *b1.q; // expected-warning {{reading the value pointed to by 'q' requires locking 'mu'}}
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001251 b3->mu1_.Unlock();
Caitlin Sadowski74558b42011-09-15 18:13:32 +00001252 b1.b_ = res; // expected-warning {{reading variable 'res' requires locking 'mu'}}
1253 x = res; // expected-warning {{reading variable 'res' requires locking 'mu'}}
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001254 return x;
1255}
1256} // end namespace thread_annot_lock_21
1257
1258namespace thread_annot_lock_35_modified {
1259// Test the analyzer's ability to distinguish the lock field of different
1260// objects.
1261class Foo {
1262 private:
1263 Mutex lock_;
1264 int a_ GUARDED_BY(lock_);
1265
1266 public:
1267 void Func(Foo* child) LOCKS_EXCLUDED(lock_) {
1268 Foo *new_foo = new Foo;
1269
1270 lock_.Lock();
1271
1272 child->Func(new_foo); // There shouldn't be any warning here as the
1273 // acquired lock is not in child.
1274 child->bar(7); // expected-warning {{calling function 'bar' requires exclusive lock on 'lock_'}}
Caitlin Sadowski74558b42011-09-15 18:13:32 +00001275 child->a_ = 5; // expected-warning {{writing variable 'a_' requires locking 'lock_' exclusively}}
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001276 lock_.Unlock();
1277 }
1278
1279 void bar(int y) EXCLUSIVE_LOCKS_REQUIRED(lock_) {
1280 a_ = y;
1281 }
1282};
1283
1284Foo *x;
1285
1286void main() {
1287 Foo *child = new Foo;
1288 x->Func(child);
1289}
1290} // end namespace thread_annot_lock_35_modified
1291
1292namespace thread_annot_lock_36_modified {
1293// Modified to move the annotations to function defns.
1294// Test the analyzer's ability to distinguish the lock field of different
1295// objects
1296class Foo {
1297 private:
1298 Mutex lock_;
1299 int a_ GUARDED_BY(lock_);
1300
1301 public:
1302 void Func(Foo* child) LOCKS_EXCLUDED(lock_);
1303 void bar(int y) EXCLUSIVE_LOCKS_REQUIRED(lock_);
1304};
1305
1306void Foo::Func(Foo* child) {
1307 Foo *new_foo = new Foo;
1308
1309 lock_.Lock();
1310
1311 child->lock_.Lock();
Caitlin Sadowski74558b42011-09-15 18:13:32 +00001312 child->Func(new_foo); // expected-warning {{cannot call function 'Func' while mutex 'lock_' is locked}}
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001313 child->bar(7);
1314 child->a_ = 5;
1315 child->lock_.Unlock();
1316
1317 lock_.Unlock();
1318}
1319
1320void Foo::bar(int y) {
1321 a_ = y;
1322}
1323
1324
1325Foo *x;
1326
1327void main() {
1328 Foo *child = new Foo;
1329 x->Func(child);
1330}
1331} // end namespace thread_annot_lock_36_modified
1332
1333
1334namespace thread_annot_lock_42 {
1335// Test support of multiple lock attributes of the same kind on a decl.
1336class Foo {
1337 private:
1338 Mutex mu1, mu2, mu3;
1339 int x GUARDED_BY(mu1) GUARDED_BY(mu2);
1340 int y GUARDED_BY(mu2);
1341
1342 void f2() LOCKS_EXCLUDED(mu1) LOCKS_EXCLUDED(mu2) LOCKS_EXCLUDED(mu3) {
1343 mu2.Lock();
1344 y = 2;
1345 mu2.Unlock();
1346 }
1347
1348 public:
1349 void f1() EXCLUSIVE_LOCKS_REQUIRED(mu2) EXCLUSIVE_LOCKS_REQUIRED(mu1) {
1350 x = 5;
Caitlin Sadowski74558b42011-09-15 18:13:32 +00001351 f2(); // expected-warning {{cannot call function 'f2' while mutex 'mu1' is locked}} \
1352 // expected-warning {{cannot call function 'f2' while mutex 'mu2' is locked}}
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001353 }
1354};
1355
1356Foo *foo;
1357
1358void func()
1359{
1360 foo->f1(); // expected-warning {{calling function 'f1' requires exclusive lock on 'mu2'}} \
1361 // expected-warning {{calling function 'f1' requires exclusive lock on 'mu1'}}
1362}
1363} // end namespace thread_annot_lock_42
1364
1365namespace thread_annot_lock_46 {
1366// Test the support for annotations on virtual functions.
1367class Base {
1368 public:
1369 virtual void func1() EXCLUSIVE_LOCKS_REQUIRED(mu_);
1370 virtual void func2() LOCKS_EXCLUDED(mu_);
1371 Mutex mu_;
1372};
1373
1374class Child : public Base {
1375 public:
1376 virtual void func1() EXCLUSIVE_LOCKS_REQUIRED(mu_);
1377 virtual void func2() LOCKS_EXCLUDED(mu_);
1378};
1379
1380void main() {
1381 Child *c;
1382 Base *b = c;
1383
1384 b->func1(); // expected-warning {{calling function 'func1' requires exclusive lock on 'mu_'}}
1385 b->mu_.Lock();
Caitlin Sadowski74558b42011-09-15 18:13:32 +00001386 b->func2(); // expected-warning {{cannot call function 'func2' while mutex 'mu_' is locked}}
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001387 b->mu_.Unlock();
1388
1389 c->func1(); // expected-warning {{calling function 'func1' requires exclusive lock on 'mu_'}}
1390 c->mu_.Lock();
Caitlin Sadowski74558b42011-09-15 18:13:32 +00001391 c->func2(); // expected-warning {{cannot call function 'func2' while mutex 'mu_' is locked}}
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001392 c->mu_.Unlock();
1393}
1394} // end namespace thread_annot_lock_46
1395
1396namespace thread_annot_lock_67_modified {
1397// Modified: attributes on definitions moved to declarations
1398// Test annotations on out-of-line definitions of member functions where the
1399// annotations refer to locks that are also data members in the class.
1400Mutex mu;
1401Mutex mu3;
1402
1403class Foo {
1404 public:
1405 int method1(int i) SHARED_LOCKS_REQUIRED(mu1, mu, mu2, mu3);
1406 int data GUARDED_BY(mu1);
1407 Mutex *mu1;
1408 Mutex *mu2;
1409};
1410
1411int Foo::method1(int i) {
1412 return data + i;
1413}
1414
1415void main()
1416{
1417 Foo a;
1418 a.method1(1); // expected-warning {{calling function 'method1' requires shared lock on 'mu1'}} \
1419 // expected-warning {{calling function 'method1' requires shared lock on 'mu'}} \
1420 // expected-warning {{calling function 'method1' requires shared lock on 'mu2'}} \
1421 // expected-warning {{calling function 'method1' requires shared lock on 'mu3'}}
1422}
1423} // end namespace thread_annot_lock_67_modified
1424
1425