blob: f9923804331e159106a753e67aeec02549e0de19 [file] [log] [blame]
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +00001// RUN: %clang_cc1 -fsyntax-only -verify -Wthread-safety %s
2
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00003#define LOCKABLE __attribute__ ((lockable))
4#define SCOPED_LOCKABLE __attribute__ ((scoped_lockable))
5#define GUARDED_BY(x) __attribute__ ((guarded_by(x)))
6#define GUARDED_VAR __attribute__ ((guarded_var))
7#define PT_GUARDED_BY(x) __attribute__ ((pt_guarded_by(x)))
8#define PT_GUARDED_VAR __attribute__ ((pt_guarded_var))
9#define ACQUIRED_AFTER(...) __attribute__ ((acquired_after(__VA_ARGS__)))
10#define ACQUIRED_BEFORE(...) __attribute__ ((acquired_before(__VA_ARGS__)))
11#define EXCLUSIVE_LOCK_FUNCTION(...) __attribute__ ((exclusive_lock_function(__VA_ARGS__)))
12#define SHARED_LOCK_FUNCTION(...) __attribute__ ((shared_lock_function(__VA_ARGS__)))
13#define EXCLUSIVE_TRYLOCK_FUNCTION(...) __attribute__ ((exclusive_trylock_function(__VA_ARGS__)))
14#define SHARED_TRYLOCK_FUNCTION(...) __attribute__ ((shared_trylock_function(__VA_ARGS__)))
15#define UNLOCK_FUNCTION(...) __attribute__ ((unlock_function(__VA_ARGS__)))
16#define LOCK_RETURNED(x) __attribute__ ((lock_returned(x)))
17#define LOCKS_EXCLUDED(...) __attribute__ ((locks_excluded(__VA_ARGS__)))
18#define EXCLUSIVE_LOCKS_REQUIRED(...) \
19 __attribute__ ((exclusive_locks_required(__VA_ARGS__)))
20#define SHARED_LOCKS_REQUIRED(...) \
21 __attribute__ ((shared_locks_required(__VA_ARGS__)))
22#define NO_THREAD_SAFETY_ANALYSIS __attribute__ ((no_thread_safety_analysis))
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +000023
24//-----------------------------------------//
25// Helper fields
26//-----------------------------------------//
27
28
29class __attribute__((lockable)) Mutex {
30 public:
31 void Lock() __attribute__((exclusive_lock_function));
32 void ReaderLock() __attribute__((shared_lock_function));
33 void Unlock() __attribute__((unlock_function));
34 bool TryLock() __attribute__((exclusive_trylock_function(true)));
35 bool ReaderTryLock() __attribute__((shared_trylock_function(true)));
36 void LockWhen(const int &cond) __attribute__((exclusive_lock_function));
37};
38
DeLesley Hutchins1fa3c062011-12-08 20:23:06 +000039class __attribute__((scoped_lockable)) MutexLock {
40 public:
41 MutexLock(Mutex *mu) __attribute__((exclusive_lock_function(mu)));
42 ~MutexLock() __attribute__((unlock_function));
43};
44
45class __attribute__((scoped_lockable)) ReaderMutexLock {
46 public:
47 ReaderMutexLock(Mutex *mu) __attribute__((exclusive_lock_function(mu)));
48 ~ReaderMutexLock() __attribute__((unlock_function));
49};
50
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +000051
52Mutex sls_mu;
53
54Mutex sls_mu2 __attribute__((acquired_after(sls_mu)));
55int sls_guard_var __attribute__((guarded_var)) = 0;
56int sls_guardby_var __attribute__((guarded_by(sls_mu))) = 0;
57
58bool getBool();
59
60class MutexWrapper {
61public:
62 Mutex mu;
Caitlin Sadowski194418f2011-09-14 20:00:24 +000063 int x __attribute__((guarded_by(mu)));
64 void MyLock() __attribute__((exclusive_lock_function(mu)));
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +000065};
66
67MutexWrapper sls_mw;
68
69void sls_fun_0() {
70 sls_mw.mu.Lock();
Caitlin Sadowski194418f2011-09-14 20:00:24 +000071 sls_mw.x = 5;
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +000072 sls_mw.mu.Unlock();
73}
74
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +000075void sls_fun_2() {
76 sls_mu.Lock();
77 int x = sls_guard_var;
78 sls_mu.Unlock();
79}
80
81void sls_fun_3() {
82 sls_mu.Lock();
83 sls_guard_var = 2;
84 sls_mu.Unlock();
85}
86
87void sls_fun_4() {
88 sls_mu2.Lock();
89 sls_guard_var = 2;
90 sls_mu2.Unlock();
91}
92
93void sls_fun_5() {
94 sls_mu.Lock();
95 int x = sls_guardby_var;
96 sls_mu.Unlock();
97}
98
99void sls_fun_6() {
100 sls_mu.Lock();
101 sls_guardby_var = 2;
102 sls_mu.Unlock();
103}
104
105void sls_fun_7() {
106 sls_mu.Lock();
107 sls_mu2.Lock();
108 sls_mu2.Unlock();
109 sls_mu.Unlock();
110}
111
112void sls_fun_8() {
113 sls_mu.Lock();
114 if (getBool())
115 sls_mu.Unlock();
116 else
117 sls_mu.Unlock();
118}
119
120void sls_fun_9() {
121 if (getBool())
122 sls_mu.Lock();
123 else
124 sls_mu.Lock();
125 sls_mu.Unlock();
126}
127
128void sls_fun_good_6() {
129 if (getBool()) {
130 sls_mu.Lock();
131 } else {
132 if (getBool()) {
133 getBool(); // EMPTY
134 } else {
135 getBool(); // EMPTY
136 }
137 sls_mu.Lock();
138 }
139 sls_mu.Unlock();
140}
141
142void sls_fun_good_7() {
143 sls_mu.Lock();
144 while (getBool()) {
145 sls_mu.Unlock();
146 if (getBool()) {
147 if (getBool()) {
148 sls_mu.Lock();
149 continue;
150 }
151 }
152 sls_mu.Lock();
153 }
154 sls_mu.Unlock();
155}
156
Caitlin Sadowski194418f2011-09-14 20:00:24 +0000157void sls_fun_good_8() {
158 sls_mw.MyLock();
159 sls_mw.mu.Unlock();
160}
161
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000162void sls_fun_bad_1() {
163 sls_mu.Unlock(); // \
Caitlin Sadowski8bccabe2011-09-08 21:52:50 +0000164 // expected-warning{{unlocking 'sls_mu' that was not locked}}
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000165}
166
167void sls_fun_bad_2() {
168 sls_mu.Lock();
169 sls_mu.Lock(); // \
Caitlin Sadowski8bccabe2011-09-08 21:52:50 +0000170 // expected-warning{{locking 'sls_mu' that is already locked}}
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000171 sls_mu.Unlock();
172}
173
174void sls_fun_bad_3() {
175 sls_mu.Lock(); // \
Richard Trieu2fe9b7f2011-12-15 00:38:15 +0000176 // expected-warning{{mutex 'sls_mu' is still locked at the end of function}}
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000177}
178
179void sls_fun_bad_4() {
180 if (getBool())
181 sls_mu.Lock(); // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000182 // expected-warning{{mutex 'sls_mu' is still locked at the end of its scope}}
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000183 else
184 sls_mu2.Lock(); // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000185 // expected-warning{{mutex 'sls_mu2' is still locked at the end of its scope}}
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000186}
187
188void sls_fun_bad_5() {
189 sls_mu.Lock(); // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000190 // expected-warning{{mutex 'sls_mu' is still locked at the end of its scope}}
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000191 if (getBool())
192 sls_mu.Unlock();
193}
194
195void sls_fun_bad_6() {
196 if (getBool()) {
197 sls_mu.Lock(); // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000198 // expected-warning{{mutex 'sls_mu' is still locked at the end of its scope}}
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000199 } else {
200 if (getBool()) {
201 getBool(); // EMPTY
202 } else {
203 getBool(); // EMPTY
204 }
205 }
206 sls_mu.Unlock(); // \
Caitlin Sadowski8bccabe2011-09-08 21:52:50 +0000207 // expected-warning{{unlocking 'sls_mu' that was not locked}}
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000208}
209
210void sls_fun_bad_7() {
Caitlin Sadowski4e4bc752011-09-15 17:25:19 +0000211 sls_mu.Lock(); // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000212 // expected-warning{{expecting mutex 'sls_mu' to be locked at start of each loop}}
Caitlin Sadowski4e4bc752011-09-15 17:25:19 +0000213 while (getBool()) {
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000214 sls_mu.Unlock();
215 if (getBool()) {
216 if (getBool()) {
217 continue;
218 }
219 }
220 sls_mu.Lock(); // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000221 // expected-warning{{mutex 'sls_mu' is still locked at the end of its scope}}
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000222 }
223 sls_mu.Unlock();
224}
225
226void sls_fun_bad_8() {
Caitlin Sadowski4e4bc752011-09-15 17:25:19 +0000227 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 do {
Caitlin Sadowski4e4bc752011-09-15 17:25:19 +0000230 sls_mu.Unlock();
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000231 } while (getBool());
232}
233
234void sls_fun_bad_9() {
235 do {
236 sls_mu.Lock(); // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000237 // expected-warning{{expecting mutex 'sls_mu' to be locked at start of each loop}}
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000238 } while (getBool());
239 sls_mu.Unlock();
240}
241
242void sls_fun_bad_10() {
243 sls_mu.Lock(); // \
Richard Trieu2fe9b7f2011-12-15 00:38:15 +0000244 // expected-warning{{mutex 'sls_mu' is still locked at the end of function}} \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000245 // expected-warning{{expecting mutex 'sls_mu' to be locked at start of each loop}}
Caitlin Sadowski4e4bc752011-09-15 17:25:19 +0000246 while(getBool()) {
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000247 sls_mu.Unlock();
248 }
249}
250
251void sls_fun_bad_11() {
252 while (getBool()) {
253 sls_mu.Lock(); // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000254 // expected-warning{{expecting mutex 'sls_mu' to be locked at start of each loop}}
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000255 }
256 sls_mu.Unlock(); // \
Caitlin Sadowski8bccabe2011-09-08 21:52:50 +0000257 // expected-warning{{unlocking 'sls_mu' that was not locked}}
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000258}
259
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000260//-----------------------------------------//
261// Handling lock expressions in attribute args
262// -------------------------------------------//
263
264Mutex aa_mu;
265
266class GlobalLocker {
267public:
268 void globalLock() __attribute__((exclusive_lock_function(aa_mu)));
269 void globalUnlock() __attribute__((unlock_function(aa_mu)));
270};
271
272GlobalLocker glock;
273
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000274void aa_fun_1() {
275 glock.globalLock();
276 glock.globalUnlock();
277}
278
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000279void aa_fun_bad_1() {
280 glock.globalUnlock(); // \
Caitlin Sadowski8bccabe2011-09-08 21:52:50 +0000281 // expected-warning{{unlocking 'aa_mu' that was not locked}}
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000282}
283
284void aa_fun_bad_2() {
285 glock.globalLock();
286 glock.globalLock(); // \
Caitlin Sadowski8bccabe2011-09-08 21:52:50 +0000287 // expected-warning{{locking 'aa_mu' that is already locked}}
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000288 glock.globalUnlock();
289}
290
291void aa_fun_bad_3() {
292 glock.globalLock(); // \
Richard Trieu2fe9b7f2011-12-15 00:38:15 +0000293 // expected-warning{{mutex 'aa_mu' is still locked at the end of function}}
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000294}
Caitlin Sadowskib4d0a962011-08-29 17:12:27 +0000295
Caitlin Sadowskib4d0a962011-08-29 17:12:27 +0000296//--------------------------------------------------//
297// Regression tests for unusual method names
298//--------------------------------------------------//
299
300Mutex wmu;
301
302// Test diagnostics for other method names.
303class WeirdMethods {
304 WeirdMethods() {
305 wmu.Lock(); // \
Richard Trieu2fe9b7f2011-12-15 00:38:15 +0000306 // expected-warning {{mutex 'wmu' is still locked at the end of function}}
Caitlin Sadowskib4d0a962011-08-29 17:12:27 +0000307 }
308 ~WeirdMethods() {
309 wmu.Lock(); // \
Richard Trieu2fe9b7f2011-12-15 00:38:15 +0000310 // expected-warning {{mutex 'wmu' is still locked at the end of function}}
Caitlin Sadowskib4d0a962011-08-29 17:12:27 +0000311 }
312 void operator++() {
313 wmu.Lock(); // \
Richard Trieu2fe9b7f2011-12-15 00:38:15 +0000314 // expected-warning {{mutex 'wmu' is still locked at the end of function}}
Caitlin Sadowskib4d0a962011-08-29 17:12:27 +0000315 }
316 operator int*() {
317 wmu.Lock(); // \
Richard Trieu2fe9b7f2011-12-15 00:38:15 +0000318 // expected-warning {{mutex 'wmu' is still locked at the end of function}}
Caitlin Sadowskib4d0a962011-08-29 17:12:27 +0000319 return 0;
320 }
321};
322
Caitlin Sadowski05b436e2011-08-29 22:27:51 +0000323//-----------------------------------------------//
324// Errors for guarded by or guarded var variables
325// ----------------------------------------------//
326
327int *pgb_gvar __attribute__((pt_guarded_var));
328int *pgb_var __attribute__((pt_guarded_by(sls_mu)));
329
330class PGBFoo {
331 public:
332 int x;
333 int *pgb_field __attribute__((guarded_by(sls_mu2)))
334 __attribute__((pt_guarded_by(sls_mu)));
335 void testFoo() {
336 pgb_field = &x; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000337 // expected-warning {{writing variable 'pgb_field' requires locking 'sls_mu2' exclusively}}
338 *pgb_field = x; // expected-warning {{reading variable 'pgb_field' requires locking 'sls_mu2'}} \
339 // expected-warning {{writing the value pointed to by 'pgb_field' requires locking 'sls_mu' exclusively}}
340 x = *pgb_field; // expected-warning {{reading variable 'pgb_field' requires locking 'sls_mu2'}} \
341 // expected-warning {{reading the value pointed to by 'pgb_field' requires locking 'sls_mu'}}
342 (*pgb_field)++; // expected-warning {{reading variable 'pgb_field' requires locking 'sls_mu2'}} \
343 // expected-warning {{writing the value pointed to by 'pgb_field' requires locking 'sls_mu' exclusively}}
Caitlin Sadowski05b436e2011-08-29 22:27:51 +0000344 }
345};
346
347class GBFoo {
348 public:
349 int gb_field __attribute__((guarded_by(sls_mu)));
350
351 void testFoo() {
352 gb_field = 0; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000353 // expected-warning {{writing variable 'gb_field' requires locking 'sls_mu' exclusively}}
Caitlin Sadowski05b436e2011-08-29 22:27:51 +0000354 }
Caitlin Sadowskiaf370612011-09-08 18:35:21 +0000355
356 void testNoAnal() __attribute__((no_thread_safety_analysis)) {
357 gb_field = 0;
358 }
Caitlin Sadowski05b436e2011-08-29 22:27:51 +0000359};
360
361GBFoo GlobalGBFoo __attribute__((guarded_by(sls_mu)));
362
363void gb_fun_0() {
364 sls_mu.Lock();
365 int x = *pgb_var;
366 sls_mu.Unlock();
367}
368
369void gb_fun_1() {
370 sls_mu.Lock();
371 *pgb_var = 2;
372 sls_mu.Unlock();
373}
374
375void gb_fun_2() {
376 int x;
377 pgb_var = &x;
378}
379
380void gb_fun_3() {
381 int *x = pgb_var;
382}
383
384void gb_bad_0() {
385 sls_guard_var = 1; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000386 // expected-warning{{writing variable 'sls_guard_var' requires locking any mutex exclusively}}
Caitlin Sadowski05b436e2011-08-29 22:27:51 +0000387}
388
389void gb_bad_1() {
390 int x = sls_guard_var; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000391 // expected-warning{{reading variable 'sls_guard_var' requires locking any mutex}}
Caitlin Sadowski05b436e2011-08-29 22:27:51 +0000392}
393
394void gb_bad_2() {
395 sls_guardby_var = 1; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000396 // expected-warning {{writing variable 'sls_guardby_var' requires locking 'sls_mu' exclusively}}
Caitlin Sadowski05b436e2011-08-29 22:27:51 +0000397}
398
399void gb_bad_3() {
400 int x = sls_guardby_var; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000401 // expected-warning {{reading variable 'sls_guardby_var' requires locking 'sls_mu'}}
Caitlin Sadowski05b436e2011-08-29 22:27:51 +0000402}
403
404void gb_bad_4() {
405 *pgb_gvar = 1; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000406 // expected-warning {{writing the value pointed to by 'pgb_gvar' requires locking any mutex exclusively}}
Caitlin Sadowski05b436e2011-08-29 22:27:51 +0000407}
408
409void gb_bad_5() {
410 int x = *pgb_gvar; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000411 // expected-warning {{reading the value pointed to by 'pgb_gvar' requires locking any mutex}}
Caitlin Sadowski05b436e2011-08-29 22:27:51 +0000412}
413
414void gb_bad_6() {
415 *pgb_var = 1; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000416 // expected-warning {{writing the value pointed to by 'pgb_var' requires locking 'sls_mu' exclusively}}
Caitlin Sadowski05b436e2011-08-29 22:27:51 +0000417}
418
419void gb_bad_7() {
420 int x = *pgb_var; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000421 // expected-warning {{reading the value pointed to by 'pgb_var' requires locking 'sls_mu'}}
Caitlin Sadowski05b436e2011-08-29 22:27:51 +0000422}
423
424void gb_bad_8() {
425 GBFoo G;
426 G.gb_field = 0; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000427 // expected-warning {{writing variable 'gb_field' requires locking 'sls_mu'}}
Caitlin Sadowski05b436e2011-08-29 22:27:51 +0000428}
429
430void gb_bad_9() {
431 sls_guard_var++; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000432 // expected-warning{{writing variable 'sls_guard_var' requires locking any mutex exclusively}}
Caitlin Sadowski05b436e2011-08-29 22:27:51 +0000433 sls_guard_var--; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000434 // expected-warning{{writing variable 'sls_guard_var' requires locking any mutex exclusively}}
Caitlin Sadowski05b436e2011-08-29 22:27:51 +0000435 ++sls_guard_var; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000436 // expected-warning{{writing variable 'sls_guard_var' requires locking any mutex exclusively}}
Caitlin Sadowskia49d1d82011-09-09 16:07:55 +0000437 --sls_guard_var;// \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000438 // expected-warning{{writing variable 'sls_guard_var' requires locking any mutex exclusively}}
Caitlin Sadowski05b436e2011-08-29 22:27:51 +0000439}
Caitlin Sadowskib4d0a962011-08-29 17:12:27 +0000440
Caitlin Sadowskieff98fc2011-09-08 17:42:22 +0000441//-----------------------------------------------//
442// Warnings on variables with late parsed attributes
443// ----------------------------------------------//
444
445class LateFoo {
446public:
447 int a __attribute__((guarded_by(mu)));
448 int b;
449
450 void foo() __attribute__((exclusive_locks_required(mu))) { }
451
452 void test() {
453 a = 0; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000454 // expected-warning{{writing variable 'a' requires locking 'mu' exclusively}}
Caitlin Sadowskieff98fc2011-09-08 17:42:22 +0000455 b = a; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000456 // expected-warning {{reading variable 'a' requires locking 'mu'}}
Caitlin Sadowskieff98fc2011-09-08 17:42:22 +0000457 c = 0; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000458 // expected-warning {{writing variable 'c' requires locking 'mu' exclusively}}
Caitlin Sadowskieff98fc2011-09-08 17:42:22 +0000459 }
460
461 int c __attribute__((guarded_by(mu)));
462
463 Mutex mu;
464};
465
Caitlin Sadowski99107eb2011-09-09 16:21:55 +0000466class LateBar {
467 public:
468 int a_ __attribute__((guarded_by(mu1_)));
469 int b_;
470 int *q __attribute__((pt_guarded_by(mu)));
471 Mutex mu1_;
472 Mutex mu;
473 LateFoo Foo;
474 LateFoo Foo2;
475 LateFoo *FooPointer;
476};
477
478LateBar b1, *b3;
479
480void late_0() {
481 LateFoo FooA;
482 LateFoo FooB;
483 FooA.mu.Lock();
484 FooA.a = 5;
485 FooA.mu.Unlock();
486}
487
488void late_1() {
489 LateBar BarA;
490 BarA.FooPointer->mu.Lock();
491 BarA.FooPointer->a = 2;
492 BarA.FooPointer->mu.Unlock();
493}
494
495void late_bad_0() {
496 LateFoo fooA;
497 LateFoo fooB;
498 fooA.mu.Lock();
499 fooB.a = 5; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000500 // expected-warning{{writing variable 'a' requires locking 'mu' exclusively}}
Caitlin Sadowski99107eb2011-09-09 16:21:55 +0000501 fooA.mu.Unlock();
502}
503
504void late_bad_1() {
505 Mutex mu;
506 mu.Lock();
507 b1.mu1_.Lock();
508 int res = b1.a_ + b3->b_;
509 b3->b_ = *b1.q; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000510 // expected-warning{{reading the value pointed to by 'q' requires locking 'mu'}}
Caitlin Sadowski99107eb2011-09-09 16:21:55 +0000511 b1.mu1_.Unlock();
512 b1.b_ = res;
513 mu.Unlock();
514}
515
516void late_bad_2() {
517 LateBar BarA;
518 BarA.FooPointer->mu.Lock();
519 BarA.Foo.a = 2; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000520 // expected-warning{{writing variable 'a' requires locking 'mu' exclusively}}
Caitlin Sadowski99107eb2011-09-09 16:21:55 +0000521 BarA.FooPointer->mu.Unlock();
522}
523
524void late_bad_3() {
525 LateBar BarA;
526 BarA.Foo.mu.Lock();
527 BarA.FooPointer->a = 2; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000528 // expected-warning{{writing variable 'a' requires locking 'mu' exclusively}}
Caitlin Sadowski99107eb2011-09-09 16:21:55 +0000529 BarA.Foo.mu.Unlock();
530}
531
532void late_bad_4() {
533 LateBar BarA;
534 BarA.Foo.mu.Lock();
535 BarA.Foo2.a = 2; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000536 // expected-warning{{writing variable 'a' requires locking 'mu' exclusively}}
Caitlin Sadowski99107eb2011-09-09 16:21:55 +0000537 BarA.Foo.mu.Unlock();
538}
539
Caitlin Sadowskia53257c2011-09-08 18:19:38 +0000540//-----------------------------------------------//
541// Extra warnings for shared vs. exclusive locks
542// ----------------------------------------------//
543
544void shared_fun_0() {
545 sls_mu.Lock();
546 do {
547 sls_mu.Unlock();
548 sls_mu.Lock();
549 } while (getBool());
550 sls_mu.Unlock();
551}
552
553void shared_fun_1() {
Caitlin Sadowski4e4bc752011-09-15 17:25:19 +0000554 sls_mu.ReaderLock(); // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000555 // expected-warning {{mutex 'sls_mu' is locked exclusively and shared in the same scope}}
Caitlin Sadowskia53257c2011-09-08 18:19:38 +0000556 do {
557 sls_mu.Unlock();
Caitlin Sadowski4e4bc752011-09-15 17:25:19 +0000558 sls_mu.Lock(); // \
559 // expected-note {{the other lock of mutex 'sls_mu' is here}}
Caitlin Sadowskia53257c2011-09-08 18:19:38 +0000560 } while (getBool());
561 sls_mu.Unlock();
562}
563
564void shared_fun_3() {
565 if (getBool())
566 sls_mu.Lock();
567 else
568 sls_mu.Lock();
569 *pgb_var = 1;
570 sls_mu.Unlock();
571}
572
573void shared_fun_4() {
574 if (getBool())
575 sls_mu.ReaderLock();
576 else
577 sls_mu.ReaderLock();
578 int x = sls_guardby_var;
579 sls_mu.Unlock();
580}
581
582void shared_fun_8() {
583 if (getBool())
584 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 else
587 sls_mu.ReaderLock(); // \
Caitlin Sadowski8bccabe2011-09-08 21:52:50 +0000588 // expected-note {{the other lock of mutex 'sls_mu' is here}}
Caitlin Sadowskia53257c2011-09-08 18:19:38 +0000589 sls_mu.Unlock();
590}
591
592void shared_bad_0() {
Caitlin Sadowski4e4bc752011-09-15 17:25:19 +0000593 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 do {
596 sls_mu.Unlock();
Caitlin Sadowski4e4bc752011-09-15 17:25:19 +0000597 sls_mu.ReaderLock(); // \
598 // expected-note {{the other lock of mutex 'sls_mu' is here}}
Caitlin Sadowskia53257c2011-09-08 18:19:38 +0000599 } while (getBool());
600 sls_mu.Unlock();
601}
602
603void shared_bad_1() {
604 if (getBool())
605 sls_mu.Lock(); // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000606 // expected-warning {{mutex 'sls_mu' is locked exclusively and shared in the same scope}}
Caitlin Sadowskia53257c2011-09-08 18:19:38 +0000607 else
608 sls_mu.ReaderLock(); // \
Caitlin Sadowski8bccabe2011-09-08 21:52:50 +0000609 // expected-note {{the other lock of mutex 'sls_mu' is here}}
Caitlin Sadowskia53257c2011-09-08 18:19:38 +0000610 *pgb_var = 1;
611 sls_mu.Unlock();
612}
613
614void shared_bad_2() {
615 if (getBool())
616 sls_mu.ReaderLock(); // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000617 // expected-warning {{mutex 'sls_mu' is locked exclusively and shared in the same scope}}
Caitlin Sadowskia53257c2011-09-08 18:19:38 +0000618 else
619 sls_mu.Lock(); // \
Caitlin Sadowski8bccabe2011-09-08 21:52:50 +0000620 // expected-note {{the other lock of mutex 'sls_mu' is here}}
Caitlin Sadowskia53257c2011-09-08 18:19:38 +0000621 *pgb_var = 1;
622 sls_mu.Unlock();
623}
Caitlin Sadowski978191e2011-09-08 18:27:31 +0000624
625// FIXME: Add support for functions (not only methods)
626class LRBar {
627 public:
628 void aa_elr_fun() __attribute__((exclusive_locks_required(aa_mu)));
629 void aa_elr_fun_s() __attribute__((shared_locks_required(aa_mu)));
630 void le_fun() __attribute__((locks_excluded(sls_mu)));
631};
632
633class LRFoo {
634 public:
635 void test() __attribute__((exclusive_locks_required(sls_mu)));
636 void testShared() __attribute__((shared_locks_required(sls_mu2)));
637};
638
639void elr_fun() __attribute__((exclusive_locks_required(sls_mu)));
640void elr_fun() {}
641
642LRFoo MyLRFoo;
643LRBar Bar;
644
645void es_fun_0() {
646 aa_mu.Lock();
647 Bar.aa_elr_fun();
648 aa_mu.Unlock();
649}
650
651void es_fun_1() {
652 aa_mu.Lock();
653 Bar.aa_elr_fun_s();
654 aa_mu.Unlock();
655}
656
657void es_fun_2() {
658 aa_mu.ReaderLock();
659 Bar.aa_elr_fun_s();
660 aa_mu.Unlock();
661}
662
663void es_fun_3() {
664 sls_mu.Lock();
665 MyLRFoo.test();
666 sls_mu.Unlock();
667}
668
669void es_fun_4() {
670 sls_mu2.Lock();
671 MyLRFoo.testShared();
672 sls_mu2.Unlock();
673}
674
675void es_fun_5() {
676 sls_mu2.ReaderLock();
677 MyLRFoo.testShared();
678 sls_mu2.Unlock();
679}
680
681void es_fun_6() {
682 Bar.le_fun();
683}
684
685void es_fun_7() {
686 sls_mu.Lock();
687 elr_fun();
688 sls_mu.Unlock();
689}
690
Caitlin Sadowskiaf370612011-09-08 18:35:21 +0000691void es_fun_8() __attribute__((no_thread_safety_analysis));
692
693void es_fun_8() {
694 Bar.aa_elr_fun_s();
695}
696
Caitlin Sadowskicb967512011-09-15 17:43:08 +0000697void es_fun_9() __attribute__((shared_locks_required(aa_mu)));
698void es_fun_9() {
699 Bar.aa_elr_fun_s();
700}
701
702void es_fun_10() __attribute__((exclusive_locks_required(aa_mu)));
703void es_fun_10() {
704 Bar.aa_elr_fun_s();
705}
706
Caitlin Sadowski978191e2011-09-08 18:27:31 +0000707void es_bad_0() {
708 Bar.aa_elr_fun(); // \
Caitlin Sadowski8bccabe2011-09-08 21:52:50 +0000709 // expected-warning {{calling function 'aa_elr_fun' requires exclusive lock on 'aa_mu'}}
Caitlin Sadowski978191e2011-09-08 18:27:31 +0000710}
711
712void es_bad_1() {
713 aa_mu.ReaderLock();
714 Bar.aa_elr_fun(); // \
Caitlin Sadowski8bccabe2011-09-08 21:52:50 +0000715 // expected-warning {{calling function 'aa_elr_fun' requires exclusive lock on 'aa_mu'}}
Caitlin Sadowski978191e2011-09-08 18:27:31 +0000716 aa_mu.Unlock();
717}
718
719void es_bad_2() {
720 Bar.aa_elr_fun_s(); // \
Caitlin Sadowski8bccabe2011-09-08 21:52:50 +0000721 // expected-warning {{calling function 'aa_elr_fun_s' requires shared lock on 'aa_mu'}}
Caitlin Sadowski978191e2011-09-08 18:27:31 +0000722}
723
724void es_bad_3() {
725 MyLRFoo.test(); // \
Caitlin Sadowski8bccabe2011-09-08 21:52:50 +0000726 // expected-warning {{calling function 'test' requires exclusive lock on 'sls_mu'}}
Caitlin Sadowski978191e2011-09-08 18:27:31 +0000727}
728
729void es_bad_4() {
730 MyLRFoo.testShared(); // \
Caitlin Sadowski8bccabe2011-09-08 21:52:50 +0000731 // expected-warning {{calling function 'testShared' requires shared lock on 'sls_mu2'}}
Caitlin Sadowski978191e2011-09-08 18:27:31 +0000732}
733
734void es_bad_5() {
735 sls_mu.ReaderLock();
736 MyLRFoo.test(); // \
Caitlin Sadowski8bccabe2011-09-08 21:52:50 +0000737 // expected-warning {{calling function 'test' requires exclusive lock on 'sls_mu'}}
Caitlin Sadowski978191e2011-09-08 18:27:31 +0000738 sls_mu.Unlock();
739}
740
741void es_bad_6() {
742 sls_mu.Lock();
743 Bar.le_fun(); // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000744 // expected-warning {{cannot call function 'le_fun' while mutex 'sls_mu' is locked}}
Caitlin Sadowski978191e2011-09-08 18:27:31 +0000745 sls_mu.Unlock();
746}
747
748void es_bad_7() {
749 sls_mu.ReaderLock();
750 Bar.le_fun(); // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000751 // expected-warning {{cannot call function 'le_fun' while mutex 'sls_mu' is locked}}
Caitlin Sadowski978191e2011-09-08 18:27:31 +0000752 sls_mu.Unlock();
753}
Caitlin Sadowski194418f2011-09-14 20:00:24 +0000754
DeLesley Hutchins81216392011-10-17 21:38:02 +0000755
Caitlin Sadowski194418f2011-09-14 20:00:24 +0000756//-----------------------------------------------//
757// Unparseable lock expressions
758// ----------------------------------------------//
759
760Mutex UPmu;
761// FIXME: add support for lock expressions involving arrays.
762Mutex mua[5];
763
DeLesley Hutchinsf1ac6372011-10-21 18:10:14 +0000764int x __attribute__((guarded_by(UPmu = sls_mu)));
765int y __attribute__((guarded_by(mua[0])));
Caitlin Sadowski194418f2011-09-14 20:00:24 +0000766
767
768void testUnparse() {
DeLesley Hutchinsf1ac6372011-10-21 18:10:14 +0000769 x = 5; // \
770 // expected-warning{{cannot resolve lock expression}}
771 y = 5; // \
772 // expected-warning{{cannot resolve lock expression}}
Caitlin Sadowski194418f2011-09-14 20:00:24 +0000773}
774
775void testUnparse2() {
776 mua[0].Lock(); // \
DeLesley Hutchinsf1ac6372011-10-21 18:10:14 +0000777 // expected-warning{{cannot resolve lock expression}}
Caitlin Sadowski194418f2011-09-14 20:00:24 +0000778 (&(mua[0]) + 4)->Lock(); // \
DeLesley Hutchinsf1ac6372011-10-21 18:10:14 +0000779 // expected-warning{{cannot resolve lock expression}}
Caitlin Sadowski194418f2011-09-14 20:00:24 +0000780}
781
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +0000782
783//----------------------------------------------------------------------------//
784// The following test cases are ported from the gcc thread safety implementation
785// They are each wrapped inside a namespace with the test number of the gcc test
786//
787// FIXME: add all the gcc tests, once this analysis passes them.
788//----------------------------------------------------------------------------//
789
790//-----------------------------------------//
791// Good testcases (no errors)
792//-----------------------------------------//
793
794namespace thread_annot_lock_20 {
795class Bar {
796 public:
797 static int func1() EXCLUSIVE_LOCKS_REQUIRED(mu1_);
798 static int b_ GUARDED_BY(mu1_);
799 static Mutex mu1_;
800 static int a_ GUARDED_BY(mu1_);
801};
802
803Bar b1;
804
805int Bar::func1()
806{
807 int res = 5;
808
809 if (a_ == 4)
810 res = b_;
811 return res;
812}
813} // end namespace thread_annot_lock_20
814
815namespace thread_annot_lock_22 {
816// Test various usage of GUARDED_BY and PT_GUARDED_BY annotations, especially
817// uses in class definitions.
818Mutex mu;
819
820class Bar {
821 public:
822 int a_ GUARDED_BY(mu1_);
823 int b_;
824 int *q PT_GUARDED_BY(mu);
825 Mutex mu1_ ACQUIRED_AFTER(mu);
826};
827
828Bar b1, *b3;
829int *p GUARDED_BY(mu) PT_GUARDED_BY(mu);
830int res GUARDED_BY(mu) = 5;
831
832int func(int i)
833{
834 int x;
835 mu.Lock();
836 b1.mu1_.Lock();
837 res = b1.a_ + b3->b_;
838 *p = i;
839 b1.a_ = res + b3->b_;
840 b3->b_ = *b1.q;
841 b1.mu1_.Unlock();
842 b1.b_ = res;
843 x = res;
844 mu.Unlock();
845 return x;
846}
847} // end namespace thread_annot_lock_22
848
849namespace thread_annot_lock_27_modified {
850// test lock annotations applied to function definitions
851// Modified: applied annotations only to function declarations
852Mutex mu1;
853Mutex mu2 ACQUIRED_AFTER(mu1);
854
855class Foo {
856 public:
857 int method1(int i) SHARED_LOCKS_REQUIRED(mu2) EXCLUSIVE_LOCKS_REQUIRED(mu1);
858};
859
860int Foo::method1(int i) {
861 return i;
862}
863
864
865int foo(int i) EXCLUSIVE_LOCKS_REQUIRED(mu2) SHARED_LOCKS_REQUIRED(mu1);
866int foo(int i) {
867 return i;
868}
869
870static int bar(int i) EXCLUSIVE_LOCKS_REQUIRED(mu1);
871static int bar(int i) {
872 return i;
873}
874
875void main() {
876 Foo a;
877
878 mu1.Lock();
879 mu2.Lock();
880 a.method1(1);
881 foo(2);
882 mu2.Unlock();
883 bar(3);
884 mu1.Unlock();
885}
886} // end namespace thread_annot_lock_27_modified
887
888
889namespace thread_annot_lock_38 {
890// Test the case where a template member function is annotated with lock
891// attributes in a non-template class.
892class Foo {
893 public:
894 void func1(int y) LOCKS_EXCLUDED(mu_);
895 template <typename T> void func2(T x) LOCKS_EXCLUDED(mu_);
896 private:
897 Mutex mu_;
898};
899
900Foo *foo;
901
902void main()
903{
904 foo->func1(5);
905 foo->func2(5);
906}
907} // end namespace thread_annot_lock_38
908
909namespace thread_annot_lock_43 {
910// Tests lock canonicalization
911class Foo {
912 public:
913 Mutex *mu_;
914};
915
916class FooBar {
917 public:
918 Foo *foo_;
919 int GetA() EXCLUSIVE_LOCKS_REQUIRED(foo_->mu_) { return a_; }
920 int a_ GUARDED_BY(foo_->mu_);
921};
922
923FooBar *fb;
924
925void main()
926{
927 int x;
928 fb->foo_->mu_->Lock();
929 x = fb->GetA();
930 fb->foo_->mu_->Unlock();
931}
932} // end namespace thread_annot_lock_43
933
934namespace thread_annot_lock_49 {
935// Test the support for use of lock expression in the annotations
936class Foo {
937 public:
938 Mutex foo_mu_;
939};
940
941class Bar {
942 private:
943 Foo *foo;
944 Mutex bar_mu_ ACQUIRED_AFTER(foo->foo_mu_);
945
946 public:
947 void Test1() {
948 foo->foo_mu_.Lock();
949 bar_mu_.Lock();
950 bar_mu_.Unlock();
951 foo->foo_mu_.Unlock();
952 }
953};
954
955void main() {
956 Bar bar;
957 bar.Test1();
958}
959} // end namespace thread_annot_lock_49
960
961namespace thread_annot_lock_61_modified {
962 // Modified to fix the compiler errors
963 // Test the fix for a bug introduced by the support of pass-by-reference
964 // paramters.
965 struct Foo { Foo &operator<< (bool) {return *this;} };
966 Foo &getFoo();
967 struct Bar { Foo &func () {return getFoo();} };
968 struct Bas { void operator& (Foo &) {} };
969 void mumble()
970 {
971 Bas() & Bar().func() << "" << "";
972 Bas() & Bar().func() << "";
973 }
974} // end namespace thread_annot_lock_61_modified
975
976
977namespace thread_annot_lock_65 {
978// Test the fix for a bug in the support of allowing reader locks for
979// non-const, non-modifying overload functions. (We didn't handle the builtin
980// properly.)
981enum MyFlags {
982 Zero,
983 One,
984 Two,
985 Three,
986 Four,
987 Five,
988 Six,
989 Seven,
990 Eight,
991 Nine
992};
993
994inline MyFlags
995operator|(MyFlags a, MyFlags b)
996{
997 return MyFlags(static_cast<int>(a) | static_cast<int>(b));
998}
999
1000inline MyFlags&
1001operator|=(MyFlags& a, MyFlags b)
1002{
1003 return a = a | b;
1004}
1005} // end namespace thread_annot_lock_65
1006
1007namespace thread_annot_lock_66_modified {
1008// Modified: Moved annotation to function defn
1009// Test annotations on out-of-line definitions of member functions where the
1010// annotations refer to locks that are also data members in the class.
1011Mutex mu;
1012
1013class Foo {
1014 public:
1015 int method1(int i) SHARED_LOCKS_REQUIRED(mu1, mu, mu2);
1016 int data GUARDED_BY(mu1);
1017 Mutex *mu1;
1018 Mutex *mu2;
1019};
1020
1021int Foo::method1(int i)
1022{
1023 return data + i;
1024}
1025
1026void main()
1027{
1028 Foo a;
1029
1030 a.mu2->Lock();
1031 a.mu1->Lock();
1032 mu.Lock();
1033 a.method1(1);
1034 mu.Unlock();
1035 a.mu1->Unlock();
1036 a.mu2->Unlock();
1037}
1038} // end namespace thread_annot_lock_66_modified
1039
1040namespace thread_annot_lock_68_modified {
1041// Test a fix to a bug in the delayed name binding with nested template
1042// instantiation. We use a stack to make sure a name is not resolved to an
1043// inner context.
1044template <typename T>
1045class Bar {
1046 Mutex mu_;
1047};
1048
1049template <typename T>
1050class Foo {
1051 public:
1052 void func(T x) {
1053 mu_.Lock();
DeLesley Hutchins23323e02012-01-20 22:50:54 +00001054 count_ = x;
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001055 mu_.Unlock();
1056 }
1057
1058 private:
DeLesley Hutchins23323e02012-01-20 22:50:54 +00001059 T count_ GUARDED_BY(mu_);
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001060 Bar<T> bar_;
1061 Mutex mu_;
1062};
1063
1064void main()
1065{
1066 Foo<int> *foo;
1067 foo->func(5);
1068}
1069} // end namespace thread_annot_lock_68_modified
1070
1071namespace thread_annot_lock_30_modified {
1072// Test delay parsing of lock attribute arguments with nested classes.
1073// Modified: trylocks replaced with exclusive_lock_fun
1074int a = 0;
1075
1076class Bar {
1077 struct Foo;
1078
1079 public:
1080 void MyLock() EXCLUSIVE_LOCK_FUNCTION(mu);
1081
1082 int func() {
1083 MyLock();
1084// if (foo == 0) {
1085// return 0;
1086// }
1087 a = 5;
1088 mu.Unlock();
1089 return 1;
1090 }
1091
1092 class FooBar {
1093 int x;
1094 int y;
1095 };
1096
1097 private:
1098 Mutex mu;
1099};
1100
1101Bar *bar;
1102
1103void main()
1104{
1105 bar->func();
1106}
1107} // end namespace thread_annot_lock_30_modified
1108
1109namespace thread_annot_lock_47 {
1110// Test the support for annotations on virtual functions.
1111// This is a good test case. (i.e. There should be no warning emitted by the
1112// compiler.)
1113class Base {
1114 public:
1115 virtual void func1() EXCLUSIVE_LOCKS_REQUIRED(mu_);
1116 virtual void func2() LOCKS_EXCLUDED(mu_);
1117 Mutex mu_;
1118};
1119
1120class Child : public Base {
1121 public:
1122 virtual void func1() EXCLUSIVE_LOCKS_REQUIRED(mu_);
1123 virtual void func2() LOCKS_EXCLUDED(mu_);
1124};
1125
1126void main() {
1127 Child *c;
1128 Base *b = c;
1129
1130 b->mu_.Lock();
1131 b->func1();
1132 b->mu_.Unlock();
1133 b->func2();
1134
1135 c->mu_.Lock();
1136 c->func1();
1137 c->mu_.Unlock();
1138 c->func2();
1139}
1140} // end namespace thread_annot_lock_47
1141
1142//-----------------------------------------//
1143// Tests which produce errors
1144//-----------------------------------------//
1145
1146namespace thread_annot_lock_13 {
1147Mutex mu1;
1148Mutex mu2;
1149
1150int g GUARDED_BY(mu1);
1151int w GUARDED_BY(mu2);
1152
1153class Foo {
1154 public:
1155 void bar() LOCKS_EXCLUDED(mu_, mu1);
1156 int foo() SHARED_LOCKS_REQUIRED(mu_) EXCLUSIVE_LOCKS_REQUIRED(mu2);
1157
1158 private:
1159 int a_ GUARDED_BY(mu_);
1160 public:
1161 Mutex mu_ ACQUIRED_AFTER(mu1);
1162};
1163
1164int Foo::foo()
1165{
1166 int res;
1167 w = 5.2;
1168 res = a_ + 5;
1169 return res;
1170}
1171
1172void Foo::bar()
1173{
1174 int x;
1175 mu_.Lock();
1176 x = foo(); // expected-warning {{calling function 'foo' requires exclusive lock on 'mu2'}}
1177 a_ = x + 1;
1178 mu_.Unlock();
1179 if (x > 5) {
1180 mu1.Lock();
1181 g = 2.3;
1182 mu1.Unlock();
1183 }
1184}
1185
1186void main()
1187{
1188 Foo f1, *f2;
1189 f1.mu_.Lock();
Caitlin Sadowski74558b42011-09-15 18:13:32 +00001190 f1.bar(); // expected-warning {{cannot call function 'bar' while mutex 'mu_' is locked}}
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001191 mu2.Lock();
1192 f1.foo();
1193 mu2.Unlock();
1194 f1.mu_.Unlock();
1195 f2->mu_.Lock();
Caitlin Sadowski74558b42011-09-15 18:13:32 +00001196 f2->bar(); // expected-warning {{cannot call function 'bar' while mutex 'mu_' is locked}}
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001197 f2->mu_.Unlock();
1198 mu2.Lock();
1199 w = 2.5;
1200 mu2.Unlock();
1201}
1202} // end namespace thread_annot_lock_13
1203
1204namespace thread_annot_lock_18_modified {
1205// Modified: Trylocks removed
1206// Test the ability to distnguish between the same lock field of
1207// different objects of a class.
1208 class Bar {
1209 public:
1210 bool MyLock() EXCLUSIVE_LOCK_FUNCTION(mu1_);
1211 void MyUnlock() UNLOCK_FUNCTION(mu1_);
1212 int a_ GUARDED_BY(mu1_);
1213
1214 private:
1215 Mutex mu1_;
1216};
1217
1218Bar *b1, *b2;
1219
1220void func()
1221{
1222 b1->MyLock();
1223 b1->a_ = 5;
Caitlin Sadowski74558b42011-09-15 18:13:32 +00001224 b2->a_ = 3; // expected-warning {{writing variable 'a_' requires locking 'mu1_' exclusively}}
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001225 b2->MyLock();
1226 b2->MyUnlock();
1227 b1->MyUnlock();
1228}
1229} // end namespace thread_annot_lock_18_modified
1230
1231namespace thread_annot_lock_21 {
1232// Test various usage of GUARDED_BY and PT_GUARDED_BY annotations, especially
1233// uses in class definitions.
1234Mutex mu;
1235
1236class Bar {
1237 public:
1238 int a_ GUARDED_BY(mu1_);
1239 int b_;
1240 int *q PT_GUARDED_BY(mu);
1241 Mutex mu1_ ACQUIRED_AFTER(mu);
1242};
1243
1244Bar b1, *b3;
1245int *p GUARDED_BY(mu) PT_GUARDED_BY(mu);
1246
1247int res GUARDED_BY(mu) = 5;
1248
1249int func(int i)
1250{
1251 int x;
1252 b3->mu1_.Lock();
Caitlin Sadowski74558b42011-09-15 18:13:32 +00001253 res = b1.a_ + b3->b_; // expected-warning {{reading variable 'a_' requires locking 'mu1_'}} \
1254 // expected-warning {{writing variable 'res' requires locking 'mu' exclusively}}
1255 *p = i; // expected-warning {{reading variable 'p' requires locking 'mu'}} \
1256 // expected-warning {{writing the value pointed to by 'p' requires locking 'mu' exclusively}}
1257 b1.a_ = res + b3->b_; // expected-warning {{reading variable 'res' requires locking 'mu'}} \
1258 // expected-warning {{writing variable 'a_' requires locking 'mu1_' exclusively}}
1259 b3->b_ = *b1.q; // expected-warning {{reading the value pointed to by 'q' requires locking 'mu'}}
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001260 b3->mu1_.Unlock();
Caitlin Sadowski74558b42011-09-15 18:13:32 +00001261 b1.b_ = res; // expected-warning {{reading variable 'res' requires locking 'mu'}}
1262 x = res; // expected-warning {{reading variable 'res' requires locking 'mu'}}
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001263 return x;
1264}
1265} // end namespace thread_annot_lock_21
1266
1267namespace thread_annot_lock_35_modified {
1268// Test the analyzer's ability to distinguish the lock field of different
1269// objects.
1270class Foo {
1271 private:
1272 Mutex lock_;
1273 int a_ GUARDED_BY(lock_);
1274
1275 public:
1276 void Func(Foo* child) LOCKS_EXCLUDED(lock_) {
1277 Foo *new_foo = new Foo;
1278
1279 lock_.Lock();
1280
1281 child->Func(new_foo); // There shouldn't be any warning here as the
1282 // acquired lock is not in child.
1283 child->bar(7); // expected-warning {{calling function 'bar' requires exclusive lock on 'lock_'}}
Caitlin Sadowski74558b42011-09-15 18:13:32 +00001284 child->a_ = 5; // expected-warning {{writing variable 'a_' requires locking 'lock_' exclusively}}
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001285 lock_.Unlock();
1286 }
1287
1288 void bar(int y) EXCLUSIVE_LOCKS_REQUIRED(lock_) {
1289 a_ = y;
1290 }
1291};
1292
1293Foo *x;
1294
1295void main() {
1296 Foo *child = new Foo;
1297 x->Func(child);
1298}
1299} // end namespace thread_annot_lock_35_modified
1300
1301namespace thread_annot_lock_36_modified {
1302// Modified to move the annotations to function defns.
1303// Test the analyzer's ability to distinguish the lock field of different
1304// objects
1305class Foo {
1306 private:
1307 Mutex lock_;
1308 int a_ GUARDED_BY(lock_);
1309
1310 public:
1311 void Func(Foo* child) LOCKS_EXCLUDED(lock_);
1312 void bar(int y) EXCLUSIVE_LOCKS_REQUIRED(lock_);
1313};
1314
1315void Foo::Func(Foo* child) {
1316 Foo *new_foo = new Foo;
1317
1318 lock_.Lock();
1319
1320 child->lock_.Lock();
Caitlin Sadowski74558b42011-09-15 18:13:32 +00001321 child->Func(new_foo); // expected-warning {{cannot call function 'Func' while mutex 'lock_' is locked}}
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001322 child->bar(7);
1323 child->a_ = 5;
1324 child->lock_.Unlock();
1325
1326 lock_.Unlock();
1327}
1328
1329void Foo::bar(int y) {
1330 a_ = y;
1331}
1332
1333
1334Foo *x;
1335
1336void main() {
1337 Foo *child = new Foo;
1338 x->Func(child);
1339}
1340} // end namespace thread_annot_lock_36_modified
1341
1342
1343namespace thread_annot_lock_42 {
1344// Test support of multiple lock attributes of the same kind on a decl.
1345class Foo {
1346 private:
1347 Mutex mu1, mu2, mu3;
1348 int x GUARDED_BY(mu1) GUARDED_BY(mu2);
1349 int y GUARDED_BY(mu2);
1350
1351 void f2() LOCKS_EXCLUDED(mu1) LOCKS_EXCLUDED(mu2) LOCKS_EXCLUDED(mu3) {
1352 mu2.Lock();
1353 y = 2;
1354 mu2.Unlock();
1355 }
1356
1357 public:
1358 void f1() EXCLUSIVE_LOCKS_REQUIRED(mu2) EXCLUSIVE_LOCKS_REQUIRED(mu1) {
1359 x = 5;
Caitlin Sadowski74558b42011-09-15 18:13:32 +00001360 f2(); // expected-warning {{cannot call function 'f2' while mutex 'mu1' is locked}} \
1361 // expected-warning {{cannot call function 'f2' while mutex 'mu2' is locked}}
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001362 }
1363};
1364
1365Foo *foo;
1366
1367void func()
1368{
1369 foo->f1(); // expected-warning {{calling function 'f1' requires exclusive lock on 'mu2'}} \
1370 // expected-warning {{calling function 'f1' requires exclusive lock on 'mu1'}}
1371}
1372} // end namespace thread_annot_lock_42
1373
1374namespace thread_annot_lock_46 {
1375// Test the support for annotations on virtual functions.
1376class Base {
1377 public:
1378 virtual void func1() EXCLUSIVE_LOCKS_REQUIRED(mu_);
1379 virtual void func2() LOCKS_EXCLUDED(mu_);
1380 Mutex mu_;
1381};
1382
1383class Child : public Base {
1384 public:
1385 virtual void func1() EXCLUSIVE_LOCKS_REQUIRED(mu_);
1386 virtual void func2() LOCKS_EXCLUDED(mu_);
1387};
1388
1389void main() {
1390 Child *c;
1391 Base *b = c;
1392
1393 b->func1(); // expected-warning {{calling function 'func1' requires exclusive lock on 'mu_'}}
1394 b->mu_.Lock();
Caitlin Sadowski74558b42011-09-15 18:13:32 +00001395 b->func2(); // expected-warning {{cannot call function 'func2' while mutex 'mu_' is locked}}
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001396 b->mu_.Unlock();
1397
1398 c->func1(); // expected-warning {{calling function 'func1' requires exclusive lock on 'mu_'}}
1399 c->mu_.Lock();
Caitlin Sadowski74558b42011-09-15 18:13:32 +00001400 c->func2(); // expected-warning {{cannot call function 'func2' while mutex 'mu_' is locked}}
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001401 c->mu_.Unlock();
1402}
1403} // end namespace thread_annot_lock_46
1404
1405namespace thread_annot_lock_67_modified {
1406// Modified: attributes on definitions moved to declarations
1407// Test annotations on out-of-line definitions of member functions where the
1408// annotations refer to locks that are also data members in the class.
1409Mutex mu;
1410Mutex mu3;
1411
1412class Foo {
1413 public:
1414 int method1(int i) SHARED_LOCKS_REQUIRED(mu1, mu, mu2, mu3);
1415 int data GUARDED_BY(mu1);
1416 Mutex *mu1;
1417 Mutex *mu2;
1418};
1419
1420int Foo::method1(int i) {
1421 return data + i;
1422}
1423
1424void main()
1425{
1426 Foo a;
1427 a.method1(1); // expected-warning {{calling function 'method1' requires shared lock on 'mu1'}} \
1428 // expected-warning {{calling function 'method1' requires shared lock on 'mu'}} \
1429 // expected-warning {{calling function 'method1' requires shared lock on 'mu2'}} \
1430 // expected-warning {{calling function 'method1' requires shared lock on 'mu3'}}
1431}
1432} // end namespace thread_annot_lock_67_modified
1433
1434
DeLesley Hutchins81216392011-10-17 21:38:02 +00001435namespace substitution_test {
1436 class MyData {
1437 public:
1438 Mutex mu;
1439
1440 void lockData() __attribute__((exclusive_lock_function(mu))) { }
1441 void unlockData() __attribute__((unlock_function(mu))) { }
1442
1443 void doSomething() __attribute__((exclusive_locks_required(mu))) { }
1444 };
1445
1446
1447 class DataLocker {
1448 public:
1449 void lockData (MyData *d) __attribute__((exclusive_lock_function(d->mu))) { }
1450 void unlockData(MyData *d) __attribute__((unlock_function(d->mu))) { }
1451 };
1452
1453
1454 class Foo {
1455 public:
1456 void foo(MyData* d) __attribute__((exclusive_locks_required(d->mu))) { }
1457
1458 void bar1(MyData* d) {
1459 d->lockData();
1460 foo(d);
1461 d->unlockData();
1462 }
1463
1464 void bar2(MyData* d) {
1465 DataLocker dlr;
1466 dlr.lockData(d);
1467 foo(d);
1468 dlr.unlockData(d);
1469 }
1470
1471 void bar3(MyData* d1, MyData* d2) {
1472 DataLocker dlr;
1473 dlr.lockData(d1); // \
1474 // expected-warning {{mutex 'mu' is still locked at the end of function}}
1475 dlr.unlockData(d2); // \
1476 // expected-warning {{unlocking 'mu' that was not locked}}
1477 }
1478
1479 void bar4(MyData* d1, MyData* d2) {
1480 DataLocker dlr;
1481 dlr.lockData(d1);
1482 foo(d2); // \
1483 // expected-warning {{calling function 'foo' requires exclusive lock on 'mu'}}
1484 dlr.unlockData(d1);
1485 }
1486 };
1487} // end namespace substituation_test
1488
DeLesley Hutchinse0eaa852011-10-21 18:06:53 +00001489
DeLesley Hutchinsf1ac6372011-10-21 18:10:14 +00001490
DeLesley Hutchinse0eaa852011-10-21 18:06:53 +00001491namespace constructor_destructor_tests {
1492 Mutex fooMu;
1493 int myVar GUARDED_BY(fooMu);
1494
1495 class Foo {
1496 public:
1497 Foo() __attribute__((exclusive_lock_function(fooMu))) { }
1498 ~Foo() __attribute__((unlock_function(fooMu))) { }
1499 };
1500
1501 void fooTest() {
DeLesley Hutchins6db51f72011-10-21 20:51:27 +00001502 Foo foo;
DeLesley Hutchinse0eaa852011-10-21 18:06:53 +00001503 myVar = 0;
1504 }
1505}
1506
DeLesley Hutchinsf1ac6372011-10-21 18:10:14 +00001507
1508namespace invalid_lock_expression_test {
1509
1510class LOCKABLE MyLockable {
1511public:
1512 MyLockable() __attribute__((exclusive_lock_function)) { }
DeLesley Hutchins6db51f72011-10-21 20:51:27 +00001513 ~MyLockable() { }
DeLesley Hutchinsf1ac6372011-10-21 18:10:14 +00001514};
1515
1516// create an empty lock expression
1517void foo() {
1518 MyLockable lock; // \
1519 // expected-warning {{cannot resolve lock expression}}
1520}
1521
1522} // end namespace invalid_lock_expression_test
1523
Richard Smith97f9fe02011-10-25 00:41:24 +00001524namespace template_member_test {
DeLesley Hutchinsf1ac6372011-10-21 18:10:14 +00001525
Richard Smith97f9fe02011-10-25 00:41:24 +00001526 struct S { int n; };
1527 struct T {
1528 Mutex m;
1529 S *s GUARDED_BY(this->m);
1530 };
Richard Smitha01c7112011-10-25 06:33:21 +00001531 Mutex m;
1532 struct U {
1533 union {
1534 int n;
1535 };
1536 } *u GUARDED_BY(m);
Richard Smith97f9fe02011-10-25 00:41:24 +00001537
1538 template<typename U>
1539 struct IndirectLock {
1540 int DoNaughtyThings(T *t) {
Richard Smitha01c7112011-10-25 06:33:21 +00001541 u->n = 0; // expected-warning {{reading variable 'u' requires locking 'm'}}
Richard Smith97f9fe02011-10-25 00:41:24 +00001542 return t->s->n; // expected-warning {{reading variable 's' requires locking 'm'}}
1543 }
1544 };
1545
Richard Smithf11e9232011-10-25 01:05:41 +00001546 template struct IndirectLock<int>; // expected-note {{here}}
Richard Smith97f9fe02011-10-25 00:41:24 +00001547
Richard Smith601d2ee2011-10-26 06:15:36 +00001548 struct V {
1549 void f(int);
1550 void f(double);
1551
1552 Mutex m;
1553 V *p GUARDED_BY(this->m);
1554 };
1555 template<typename U> struct W {
1556 V v;
1557 void f(U u) {
1558 v.p->f(u); // expected-warning {{reading variable 'p' requires locking 'm'}}
1559 }
1560 };
1561 template struct W<int>; // expected-note {{here}}
1562
Richard Smith97f9fe02011-10-25 00:41:24 +00001563}
DeLesley Hutchins1fa3c062011-12-08 20:23:06 +00001564
1565namespace test_scoped_lockable {
1566
1567struct TestScopedLockable {
1568 Mutex mu1;
1569 Mutex mu2;
1570 int a __attribute__((guarded_by(mu1)));
1571 int b __attribute__((guarded_by(mu2)));
1572
1573 bool getBool();
1574
1575 void foo1() {
1576 MutexLock mulock(&mu1);
1577 a = 5;
1578 }
1579
1580 void foo2() {
1581 ReaderMutexLock mulock1(&mu1);
1582 if (getBool()) {
1583 MutexLock mulock2a(&mu2);
1584 b = a + 1;
1585 }
1586 else {
1587 MutexLock mulock2b(&mu2);
1588 b = a + 2;
1589 }
1590 }
1591
1592 void foo3() {
1593 MutexLock mulock_a(&mu1);
1594 MutexLock mulock_b(&mu1); // \
1595 // expected-warning {{locking 'mu1' that is already locked}}
1596 } // expected-warning {{unlocking 'mu1' that was not locked}}
1597
1598 void foo4() {
1599 MutexLock mulock1(&mu1), mulock2(&mu2);
1600 a = b+1;
1601 b = a+1;
1602 }
1603};
1604
1605} // end namespace test_scoped_lockable
1606
1607
DeLesley Hutchinsdf497822011-12-29 00:56:48 +00001608namespace FunctionAttrTest {
1609
1610class Foo {
1611public:
1612 Mutex mu_;
1613 int a GUARDED_BY(mu_);
1614};
1615
1616Foo fooObj;
1617
1618void foo() EXCLUSIVE_LOCKS_REQUIRED(fooObj.mu_);
1619
1620void bar() {
1621 foo(); // expected-warning {{calling function 'foo' requires exclusive lock on 'mu_'}}
1622 fooObj.mu_.Lock();
1623 foo();
1624 fooObj.mu_.Unlock();
1625}
1626
1627}; // end namespace FunctionAttrTest
1628
1629
DeLesley Hutchinsb4fa4182012-01-06 19:16:50 +00001630struct TestTryLock {
1631 Mutex mu;
1632 int a GUARDED_BY(mu);
1633 bool cond;
1634
1635 void foo1() {
1636 if (mu.TryLock()) {
1637 a = 1;
1638 mu.Unlock();
1639 }
1640 }
1641
1642 void foo2() {
1643 if (!mu.TryLock()) return;
1644 a = 2;
1645 mu.Unlock();
1646 }
1647
1648 void foo3() {
1649 bool b = mu.TryLock();
1650 if (b) {
1651 a = 3;
1652 mu.Unlock();
1653 }
1654 }
1655
1656 void foo4() {
1657 bool b = mu.TryLock();
1658 if (!b) return;
1659 a = 4;
1660 mu.Unlock();
1661 }
1662
1663 void foo5() {
1664 while (mu.TryLock()) {
1665 a = a + 1;
1666 mu.Unlock();
1667 }
1668 }
1669
1670 void foo6() {
1671 bool b = mu.TryLock();
1672 b = !b;
1673 if (b) return;
1674 a = 6;
1675 mu.Unlock();
1676 }
1677
1678 void foo7() {
1679 bool b1 = mu.TryLock();
1680 bool b2 = !b1;
1681 bool b3 = !b2;
1682 if (b3) {
1683 a = 7;
1684 mu.Unlock();
1685 }
1686 }
1687
1688 // Test use-def chains: join points
1689 void foo8() {
1690 bool b = mu.TryLock();
1691 bool b2 = b;
1692 if (cond)
1693 b = true;
1694 if (b) { // b should be unknown at this point, becuase of the join point
1695 a = 8; // expected-warning {{writing variable 'a' requires locking 'mu' exclusively}}
1696 }
1697 if (b2) { // b2 should be known at this point.
1698 a = 8;
1699 mu.Unlock();
1700 }
1701 }
1702
1703 // Test use-def-chains: back edges
1704 void foo9() {
1705 bool b = mu.TryLock();
1706
1707 for (int i = 0; i < 10; ++i);
1708
1709 if (b) { // b is still known, because the loop doesn't alter it
1710 a = 9;
1711 mu.Unlock();
1712 }
1713 }
1714
1715 // Test use-def chains: back edges
1716 void foo10() {
1717 bool b = mu.TryLock();
1718
1719 while (cond) {
1720 if (b) { // b should be uknown at this point b/c of the loop
1721 a = 10; // expected-warning {{writing variable 'a' requires locking 'mu' exclusively}}
1722 }
1723 b = !b;
1724 }
1725 }
1726}; // end TestTrylock
1727
1728
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +00001729namespace TestTemplateAttributeInstantiation {
1730
1731class Foo1 {
1732public:
1733 Mutex mu_;
1734 int a GUARDED_BY(mu_);
1735};
1736
1737class Foo2 {
1738public:
1739 int a GUARDED_BY(mu_);
1740 Mutex mu_;
1741};
1742
1743
1744class Bar {
1745public:
1746 // Test non-dependent expressions in attributes on template functions
1747 template <class T>
1748 void barND(Foo1 *foo, T *fooT) EXCLUSIVE_LOCKS_REQUIRED(foo->mu_) {
1749 foo->a = 0;
1750 }
1751
1752 // Test dependent expressions in attributes on template functions
1753 template <class T>
1754 void barD(Foo1 *foo, T *fooT) EXCLUSIVE_LOCKS_REQUIRED(fooT->mu_) {
1755 fooT->a = 0;
1756 }
1757};
1758
1759
1760template <class T>
1761class BarT {
1762public:
1763 Foo1 fooBase;
1764 T fooBaseT;
1765
1766 // Test non-dependent expression in ordinary method on template class
1767 void barND() EXCLUSIVE_LOCKS_REQUIRED(fooBase.mu_) {
1768 fooBase.a = 0;
1769 }
1770
1771 // Test dependent expressions in ordinary methods on template class
1772 void barD() EXCLUSIVE_LOCKS_REQUIRED(fooBaseT.mu_) {
1773 fooBaseT.a = 0;
1774 }
1775
1776 // Test dependent expressions in template method in template class
1777 template <class T2>
1778 void barTD(T2 *fooT) EXCLUSIVE_LOCKS_REQUIRED(fooBaseT.mu_, fooT->mu_) {
1779 fooBaseT.a = 0;
1780 fooT->a = 0;
1781 }
1782};
1783
1784template <class T>
1785class Cell {
1786public:
1787 Mutex mu_;
1788 // Test dependent guarded_by
1789 T data GUARDED_BY(mu_);
1790
DeLesley Hutchins23323e02012-01-20 22:50:54 +00001791 void fooEx() EXCLUSIVE_LOCKS_REQUIRED(mu_) {
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +00001792 data = 0;
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +00001793 }
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +00001794
1795 void foo() {
1796 mu_.Lock();
1797 data = 0;
1798 mu_.Unlock();
1799 }
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +00001800};
1801
1802void test() {
1803 Bar b;
1804 BarT<Foo2> bt;
1805 Foo1 f1;
1806 Foo2 f2;
1807
1808 f1.mu_.Lock();
1809 f2.mu_.Lock();
1810 bt.fooBase.mu_.Lock();
1811 bt.fooBaseT.mu_.Lock();
1812
1813 b.barND(&f1, &f2);
1814 b.barD(&f1, &f2);
1815 bt.barND();
1816 bt.barD();
1817 bt.barTD(&f2);
1818
1819 f1.mu_.Unlock();
1820 bt.barTD(&f1); // \
1821 // expected-warning {{calling function 'barTD' requires exclusive lock on 'mu_'}}
1822
1823 bt.fooBase.mu_.Unlock();
1824 bt.fooBaseT.mu_.Unlock();
1825 f2.mu_.Unlock();
1826
1827 Cell<int> cell;
1828 cell.data = 0; // \
1829 // expected-warning {{writing variable 'data' requires locking 'mu_' exclusively}}
1830 cell.foo();
DeLesley Hutchins23323e02012-01-20 22:50:54 +00001831 cell.mu_.Lock();
1832 cell.fooEx();
1833 cell.mu_.Unlock();
1834}
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +00001835
DeLesley Hutchins23323e02012-01-20 22:50:54 +00001836
1837template <class T>
1838class CellDelayed {
1839public:
1840 // Test dependent guarded_by
1841 T data GUARDED_BY(mu_);
1842
1843 void fooEx(CellDelayed<T> *other) EXCLUSIVE_LOCKS_REQUIRED(mu_, other->mu_) {
1844 this->data = other->data;
1845 }
1846
1847 template <class T2>
1848 void fooExT(CellDelayed<T2> *otherT) EXCLUSIVE_LOCKS_REQUIRED(mu_, otherT->mu_) {
1849 this->data = otherT->data;
1850 }
1851
1852 void foo() {
1853 mu_.Lock();
1854 data = 0;
1855 mu_.Unlock();
1856 }
1857
1858 Mutex mu_;
1859};
1860
1861void testDelayed() {
1862 CellDelayed<int> celld;
1863 CellDelayed<int> celld2;
1864 celld.foo();
1865 celld.mu_.Lock();
1866 celld2.mu_.Lock();
1867
1868 celld.fooEx(&celld2);
1869 celld.fooExT(&celld2);
1870
1871 celld2.mu_.Unlock();
1872 celld.mu_.Unlock();
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +00001873}
1874
1875}; // end namespace TestTemplateAttributeInstantiation
1876
1877