blob: 446c9099f110c9695d4c2894f59c8e59c4e9c37c [file] [log] [blame]
DeLesley Hutchins13106112012-07-10 21:47:55 +00001// RUN: %clang_cc1 -fsyntax-only -verify -Wthread-safety -std=c++11 %s
2
3// FIXME: should also run %clang_cc1 -fsyntax-only -verify -Wthread-safety -std=c++11 -Wc++98-compat %s
4// FIXME: should also run %clang_cc1 -fsyntax-only -verify -Wthread-safety %s
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +00005
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00006#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
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +000027
28class __attribute__((lockable)) Mutex {
29 public:
30 void Lock() __attribute__((exclusive_lock_function));
31 void ReaderLock() __attribute__((shared_lock_function));
32 void Unlock() __attribute__((unlock_function));
33 bool TryLock() __attribute__((exclusive_trylock_function(true)));
34 bool ReaderTryLock() __attribute__((shared_trylock_function(true)));
35 void LockWhen(const int &cond) __attribute__((exclusive_lock_function));
36};
37
DeLesley Hutchins1fa3c062011-12-08 20:23:06 +000038class __attribute__((scoped_lockable)) MutexLock {
39 public:
40 MutexLock(Mutex *mu) __attribute__((exclusive_lock_function(mu)));
41 ~MutexLock() __attribute__((unlock_function));
42};
43
44class __attribute__((scoped_lockable)) ReaderMutexLock {
45 public:
46 ReaderMutexLock(Mutex *mu) __attribute__((exclusive_lock_function(mu)));
47 ~ReaderMutexLock() __attribute__((unlock_function));
48};
49
DeLesley Hutchinsc99a5d82012-06-28 22:42:48 +000050class SCOPED_LOCKABLE ReleasableMutexLock {
51 public:
52 ReleasableMutexLock(Mutex *mu) EXCLUSIVE_LOCK_FUNCTION(mu);
53 ~ReleasableMutexLock() UNLOCK_FUNCTION();
54
55 void Release() UNLOCK_FUNCTION();
56};
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +000057
DeLesley Hutchins9d6e7f32012-07-03 18:25:56 +000058
DeLesley Hutchins0b4db3e2012-09-07 17:34:53 +000059// The universal lock, written "*", allows checking to be selectively turned
60// off for a particular piece of code.
61void beginNoWarnOnReads() SHARED_LOCK_FUNCTION("*");
62void endNoWarnOnReads() UNLOCK_FUNCTION("*");
63void beginNoWarnOnWrites() EXCLUSIVE_LOCK_FUNCTION("*");
64void endNoWarnOnWrites() UNLOCK_FUNCTION("*");
65
66
DeLesley Hutchins9d6e7f32012-07-03 18:25:56 +000067template<class T>
68class SmartPtr {
69public:
70 SmartPtr(T* p) : ptr_(p) { }
71 SmartPtr(const SmartPtr<T>& p) : ptr_(p.ptr_) { }
72 ~SmartPtr();
73
74 T* get() const { return ptr_; }
75 T* operator->() const { return ptr_; }
DeLesley Hutchins96fac6a2012-07-03 19:47:18 +000076 T& operator*() const { return *ptr_; }
DeLesley Hutchins9d6e7f32012-07-03 18:25:56 +000077
78private:
79 T* ptr_;
80};
81
82
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +000083Mutex sls_mu;
84
85Mutex sls_mu2 __attribute__((acquired_after(sls_mu)));
86int sls_guard_var __attribute__((guarded_var)) = 0;
87int sls_guardby_var __attribute__((guarded_by(sls_mu))) = 0;
88
89bool getBool();
90
91class MutexWrapper {
92public:
93 Mutex mu;
Caitlin Sadowski194418f2011-09-14 20:00:24 +000094 int x __attribute__((guarded_by(mu)));
95 void MyLock() __attribute__((exclusive_lock_function(mu)));
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +000096};
97
98MutexWrapper sls_mw;
99
100void sls_fun_0() {
101 sls_mw.mu.Lock();
Caitlin Sadowski194418f2011-09-14 20:00:24 +0000102 sls_mw.x = 5;
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000103 sls_mw.mu.Unlock();
104}
105
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000106void sls_fun_2() {
107 sls_mu.Lock();
108 int x = sls_guard_var;
109 sls_mu.Unlock();
110}
111
112void sls_fun_3() {
113 sls_mu.Lock();
114 sls_guard_var = 2;
115 sls_mu.Unlock();
116}
117
118void sls_fun_4() {
119 sls_mu2.Lock();
120 sls_guard_var = 2;
121 sls_mu2.Unlock();
122}
123
124void sls_fun_5() {
125 sls_mu.Lock();
126 int x = sls_guardby_var;
127 sls_mu.Unlock();
128}
129
130void sls_fun_6() {
131 sls_mu.Lock();
132 sls_guardby_var = 2;
133 sls_mu.Unlock();
134}
135
136void sls_fun_7() {
137 sls_mu.Lock();
138 sls_mu2.Lock();
139 sls_mu2.Unlock();
140 sls_mu.Unlock();
141}
142
143void sls_fun_8() {
144 sls_mu.Lock();
145 if (getBool())
146 sls_mu.Unlock();
147 else
148 sls_mu.Unlock();
149}
150
151void sls_fun_9() {
152 if (getBool())
153 sls_mu.Lock();
154 else
155 sls_mu.Lock();
156 sls_mu.Unlock();
157}
158
159void sls_fun_good_6() {
160 if (getBool()) {
161 sls_mu.Lock();
162 } else {
163 if (getBool()) {
164 getBool(); // EMPTY
165 } else {
166 getBool(); // EMPTY
167 }
168 sls_mu.Lock();
169 }
170 sls_mu.Unlock();
171}
172
173void sls_fun_good_7() {
174 sls_mu.Lock();
175 while (getBool()) {
176 sls_mu.Unlock();
177 if (getBool()) {
178 if (getBool()) {
179 sls_mu.Lock();
180 continue;
181 }
182 }
183 sls_mu.Lock();
184 }
185 sls_mu.Unlock();
186}
187
Caitlin Sadowski194418f2011-09-14 20:00:24 +0000188void sls_fun_good_8() {
189 sls_mw.MyLock();
190 sls_mw.mu.Unlock();
191}
192
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000193void sls_fun_bad_1() {
194 sls_mu.Unlock(); // \
Caitlin Sadowski8bccabe2011-09-08 21:52:50 +0000195 // expected-warning{{unlocking 'sls_mu' that was not locked}}
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000196}
197
198void sls_fun_bad_2() {
199 sls_mu.Lock();
200 sls_mu.Lock(); // \
Caitlin Sadowski8bccabe2011-09-08 21:52:50 +0000201 // expected-warning{{locking 'sls_mu' that is already locked}}
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000202 sls_mu.Unlock();
203}
204
205void sls_fun_bad_3() {
Richard Smith2e515622012-02-03 04:45:26 +0000206 sls_mu.Lock(); // expected-note {{mutex acquired here}}
207} // expected-warning{{mutex 'sls_mu' is still locked at the end of function}}
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000208
209void sls_fun_bad_4() {
210 if (getBool())
DeLesley Hutchins0da44142012-06-22 17:07:28 +0000211 sls_mu.Lock(); // expected-note{{mutex acquired here}}
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000212 else
DeLesley Hutchins0da44142012-06-22 17:07:28 +0000213 sls_mu2.Lock(); // expected-note{{mutex acquired here}}
214} // expected-warning{{mutex 'sls_mu' is not locked on every path through here}} \
215 // expected-warning{{mutex 'sls_mu2' is not locked on every path through here}}
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000216
217void sls_fun_bad_5() {
Richard Smith2e515622012-02-03 04:45:26 +0000218 sls_mu.Lock(); // expected-note {{mutex acquired here}}
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000219 if (getBool())
220 sls_mu.Unlock();
Richard Smith2e515622012-02-03 04:45:26 +0000221} // expected-warning{{mutex 'sls_mu' is not locked on every path through here}}
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000222
223void sls_fun_bad_6() {
224 if (getBool()) {
Richard Smith2e515622012-02-03 04:45:26 +0000225 sls_mu.Lock(); // expected-note {{mutex acquired here}}
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000226 } else {
227 if (getBool()) {
228 getBool(); // EMPTY
229 } else {
230 getBool(); // EMPTY
231 }
232 }
233 sls_mu.Unlock(); // \
Richard Smith2e515622012-02-03 04:45:26 +0000234 expected-warning{{mutex 'sls_mu' is not locked on every path through here}}\
235 expected-warning{{unlocking 'sls_mu' that was not locked}}
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000236}
237
238void sls_fun_bad_7() {
Richard Smithaacde712012-02-03 03:30:07 +0000239 sls_mu.Lock();
Caitlin Sadowski4e4bc752011-09-15 17:25:19 +0000240 while (getBool()) {
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000241 sls_mu.Unlock();
242 if (getBool()) {
243 if (getBool()) {
Richard Smith2e515622012-02-03 04:45:26 +0000244 continue; // \
245 expected-warning{{expecting mutex 'sls_mu' to be locked at start of each loop}}
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000246 }
247 }
Richard Smith2e515622012-02-03 04:45:26 +0000248 sls_mu.Lock(); // expected-note {{mutex acquired here}}
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000249 }
250 sls_mu.Unlock();
251}
252
253void sls_fun_bad_8() {
Richard Smith2e515622012-02-03 04:45:26 +0000254 sls_mu.Lock(); // expected-note{{mutex acquired here}}
255
DeLesley Hutchins0da44142012-06-22 17:07:28 +0000256 do {
257 sls_mu.Unlock(); // expected-warning{{expecting mutex 'sls_mu' to be locked at start of each loop}}
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000258 } while (getBool());
259}
260
261void sls_fun_bad_9() {
262 do {
DeLesley Hutchins0da44142012-06-22 17:07:28 +0000263 sls_mu.Lock(); // \
Richard Smith2e515622012-02-03 04:45:26 +0000264 // expected-warning{{expecting mutex 'sls_mu' to be locked at start of each loop}} \
265 // expected-note{{mutex acquired here}}
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000266 } while (getBool());
267 sls_mu.Unlock();
268}
269
270void sls_fun_bad_10() {
DeLesley Hutchins0da44142012-06-22 17:07:28 +0000271 sls_mu.Lock(); // expected-note 2{{mutex acquired here}}
272 while(getBool()) { // expected-warning{{expecting mutex 'sls_mu' to be locked at start of each loop}}
273 sls_mu.Unlock();
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000274 }
Richard Smith2e515622012-02-03 04:45:26 +0000275} // expected-warning{{mutex 'sls_mu' is still locked at the end of function}}
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000276
277void sls_fun_bad_11() {
Richard Smith2e515622012-02-03 04:45:26 +0000278 while (getBool()) { // \
DeLesley Hutchins0da44142012-06-22 17:07:28 +0000279 expected-warning{{expecting mutex 'sls_mu' to be locked at start of each loop}}
Richard Smith2e515622012-02-03 04:45:26 +0000280 sls_mu.Lock(); // expected-note {{mutex acquired here}}
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000281 }
282 sls_mu.Unlock(); // \
Caitlin Sadowski8bccabe2011-09-08 21:52:50 +0000283 // expected-warning{{unlocking 'sls_mu' that was not locked}}
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000284}
285
Richard Smithaacde712012-02-03 03:30:07 +0000286void sls_fun_bad_12() {
Richard Smith2e515622012-02-03 04:45:26 +0000287 sls_mu.Lock(); // expected-note {{mutex acquired here}}
Richard Smithaacde712012-02-03 03:30:07 +0000288 while (getBool()) {
289 sls_mu.Unlock();
290 if (getBool()) {
291 if (getBool()) {
Richard Smith2e515622012-02-03 04:45:26 +0000292 break; // expected-warning{{mutex 'sls_mu' is not locked on every path through here}}
Richard Smithaacde712012-02-03 03:30:07 +0000293 }
294 }
295 sls_mu.Lock();
296 }
297 sls_mu.Unlock();
298}
299
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000300//-----------------------------------------//
301// Handling lock expressions in attribute args
302// -------------------------------------------//
303
304Mutex aa_mu;
305
306class GlobalLocker {
307public:
308 void globalLock() __attribute__((exclusive_lock_function(aa_mu)));
309 void globalUnlock() __attribute__((unlock_function(aa_mu)));
310};
311
312GlobalLocker glock;
313
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000314void aa_fun_1() {
315 glock.globalLock();
316 glock.globalUnlock();
317}
318
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000319void aa_fun_bad_1() {
320 glock.globalUnlock(); // \
Caitlin Sadowski8bccabe2011-09-08 21:52:50 +0000321 // expected-warning{{unlocking 'aa_mu' that was not locked}}
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000322}
323
324void aa_fun_bad_2() {
325 glock.globalLock();
326 glock.globalLock(); // \
Caitlin Sadowski8bccabe2011-09-08 21:52:50 +0000327 // expected-warning{{locking 'aa_mu' that is already locked}}
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000328 glock.globalUnlock();
329}
330
331void aa_fun_bad_3() {
Richard Smith2e515622012-02-03 04:45:26 +0000332 glock.globalLock(); // expected-note{{mutex acquired here}}
333} // expected-warning{{mutex 'aa_mu' is still locked at the end of function}}
Caitlin Sadowskib4d0a962011-08-29 17:12:27 +0000334
Caitlin Sadowskib4d0a962011-08-29 17:12:27 +0000335//--------------------------------------------------//
336// Regression tests for unusual method names
337//--------------------------------------------------//
338
339Mutex wmu;
340
341// Test diagnostics for other method names.
342class WeirdMethods {
DeLesley Hutchins2f13bec2012-02-16 17:13:43 +0000343 // FIXME: can't currently check inside constructors and destructors.
Caitlin Sadowskib4d0a962011-08-29 17:12:27 +0000344 WeirdMethods() {
DeLesley Hutchins2f13bec2012-02-16 17:13:43 +0000345 wmu.Lock(); // EXPECTED-NOTE {{mutex acquired here}}
346 } // EXPECTED-WARNING {{mutex 'wmu' is still locked at the end of function}}
Caitlin Sadowskib4d0a962011-08-29 17:12:27 +0000347 ~WeirdMethods() {
DeLesley Hutchins2f13bec2012-02-16 17:13:43 +0000348 wmu.Lock(); // EXPECTED-NOTE {{mutex acquired here}}
349 } // EXPECTED-WARNING {{mutex 'wmu' is still locked at the end of function}}
Caitlin Sadowskib4d0a962011-08-29 17:12:27 +0000350 void operator++() {
Richard Smith2e515622012-02-03 04:45:26 +0000351 wmu.Lock(); // expected-note {{mutex acquired here}}
352 } // expected-warning {{mutex 'wmu' is still locked at the end of function}}
Caitlin Sadowskib4d0a962011-08-29 17:12:27 +0000353 operator int*() {
Richard Smith2e515622012-02-03 04:45:26 +0000354 wmu.Lock(); // expected-note {{mutex acquired here}}
Caitlin Sadowskib4d0a962011-08-29 17:12:27 +0000355 return 0;
Richard Smith2e515622012-02-03 04:45:26 +0000356 } // expected-warning {{mutex 'wmu' is still locked at the end of function}}
Caitlin Sadowskib4d0a962011-08-29 17:12:27 +0000357};
358
Caitlin Sadowski05b436e2011-08-29 22:27:51 +0000359//-----------------------------------------------//
360// Errors for guarded by or guarded var variables
361// ----------------------------------------------//
362
363int *pgb_gvar __attribute__((pt_guarded_var));
364int *pgb_var __attribute__((pt_guarded_by(sls_mu)));
365
366class PGBFoo {
367 public:
368 int x;
369 int *pgb_field __attribute__((guarded_by(sls_mu2)))
370 __attribute__((pt_guarded_by(sls_mu)));
371 void testFoo() {
372 pgb_field = &x; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000373 // expected-warning {{writing variable 'pgb_field' requires locking 'sls_mu2' exclusively}}
374 *pgb_field = x; // expected-warning {{reading variable 'pgb_field' requires locking 'sls_mu2'}} \
375 // expected-warning {{writing the value pointed to by 'pgb_field' requires locking 'sls_mu' exclusively}}
376 x = *pgb_field; // expected-warning {{reading variable 'pgb_field' requires locking 'sls_mu2'}} \
377 // expected-warning {{reading the value pointed to by 'pgb_field' requires locking 'sls_mu'}}
378 (*pgb_field)++; // expected-warning {{reading variable 'pgb_field' requires locking 'sls_mu2'}} \
379 // expected-warning {{writing the value pointed to by 'pgb_field' requires locking 'sls_mu' exclusively}}
Caitlin Sadowski05b436e2011-08-29 22:27:51 +0000380 }
381};
382
383class GBFoo {
384 public:
385 int gb_field __attribute__((guarded_by(sls_mu)));
386
387 void testFoo() {
388 gb_field = 0; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000389 // expected-warning {{writing variable 'gb_field' requires locking 'sls_mu' exclusively}}
Caitlin Sadowski05b436e2011-08-29 22:27:51 +0000390 }
Caitlin Sadowskiaf370612011-09-08 18:35:21 +0000391
392 void testNoAnal() __attribute__((no_thread_safety_analysis)) {
393 gb_field = 0;
394 }
Caitlin Sadowski05b436e2011-08-29 22:27:51 +0000395};
396
397GBFoo GlobalGBFoo __attribute__((guarded_by(sls_mu)));
398
399void gb_fun_0() {
400 sls_mu.Lock();
401 int x = *pgb_var;
402 sls_mu.Unlock();
403}
404
405void gb_fun_1() {
406 sls_mu.Lock();
407 *pgb_var = 2;
408 sls_mu.Unlock();
409}
410
411void gb_fun_2() {
412 int x;
413 pgb_var = &x;
414}
415
416void gb_fun_3() {
417 int *x = pgb_var;
418}
419
420void gb_bad_0() {
421 sls_guard_var = 1; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000422 // expected-warning{{writing variable 'sls_guard_var' requires locking any mutex exclusively}}
Caitlin Sadowski05b436e2011-08-29 22:27:51 +0000423}
424
425void gb_bad_1() {
426 int x = sls_guard_var; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000427 // expected-warning{{reading variable 'sls_guard_var' requires locking any mutex}}
Caitlin Sadowski05b436e2011-08-29 22:27:51 +0000428}
429
430void gb_bad_2() {
431 sls_guardby_var = 1; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000432 // expected-warning {{writing variable 'sls_guardby_var' requires locking 'sls_mu' exclusively}}
Caitlin Sadowski05b436e2011-08-29 22:27:51 +0000433}
434
435void gb_bad_3() {
436 int x = sls_guardby_var; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000437 // expected-warning {{reading variable 'sls_guardby_var' requires locking 'sls_mu'}}
Caitlin Sadowski05b436e2011-08-29 22:27:51 +0000438}
439
440void gb_bad_4() {
441 *pgb_gvar = 1; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000442 // expected-warning {{writing the value pointed to by 'pgb_gvar' requires locking any mutex exclusively}}
Caitlin Sadowski05b436e2011-08-29 22:27:51 +0000443}
444
445void gb_bad_5() {
446 int x = *pgb_gvar; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000447 // expected-warning {{reading the value pointed to by 'pgb_gvar' requires locking any mutex}}
Caitlin Sadowski05b436e2011-08-29 22:27:51 +0000448}
449
450void gb_bad_6() {
451 *pgb_var = 1; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000452 // expected-warning {{writing the value pointed to by 'pgb_var' requires locking 'sls_mu' exclusively}}
Caitlin Sadowski05b436e2011-08-29 22:27:51 +0000453}
454
455void gb_bad_7() {
456 int x = *pgb_var; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000457 // expected-warning {{reading the value pointed to by 'pgb_var' requires locking 'sls_mu'}}
Caitlin Sadowski05b436e2011-08-29 22:27:51 +0000458}
459
460void gb_bad_8() {
461 GBFoo G;
462 G.gb_field = 0; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000463 // expected-warning {{writing variable 'gb_field' requires locking 'sls_mu'}}
Caitlin Sadowski05b436e2011-08-29 22:27:51 +0000464}
465
466void gb_bad_9() {
467 sls_guard_var++; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000468 // expected-warning{{writing variable 'sls_guard_var' requires locking any mutex exclusively}}
Caitlin Sadowski05b436e2011-08-29 22:27:51 +0000469 sls_guard_var--; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000470 // expected-warning{{writing variable 'sls_guard_var' requires locking any mutex exclusively}}
Caitlin Sadowski05b436e2011-08-29 22:27:51 +0000471 ++sls_guard_var; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000472 // expected-warning{{writing variable 'sls_guard_var' requires locking any mutex exclusively}}
Caitlin Sadowskia49d1d82011-09-09 16:07:55 +0000473 --sls_guard_var;// \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000474 // expected-warning{{writing variable 'sls_guard_var' requires locking any mutex exclusively}}
Caitlin Sadowski05b436e2011-08-29 22:27:51 +0000475}
Caitlin Sadowskib4d0a962011-08-29 17:12:27 +0000476
Caitlin Sadowskieff98fc2011-09-08 17:42:22 +0000477//-----------------------------------------------//
478// Warnings on variables with late parsed attributes
479// ----------------------------------------------//
480
481class LateFoo {
482public:
483 int a __attribute__((guarded_by(mu)));
484 int b;
485
486 void foo() __attribute__((exclusive_locks_required(mu))) { }
487
488 void test() {
489 a = 0; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000490 // expected-warning{{writing variable 'a' requires locking 'mu' exclusively}}
Caitlin Sadowskieff98fc2011-09-08 17:42:22 +0000491 b = a; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000492 // expected-warning {{reading variable 'a' requires locking 'mu'}}
Caitlin Sadowskieff98fc2011-09-08 17:42:22 +0000493 c = 0; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000494 // expected-warning {{writing variable 'c' requires locking 'mu' exclusively}}
Caitlin Sadowskieff98fc2011-09-08 17:42:22 +0000495 }
496
497 int c __attribute__((guarded_by(mu)));
498
499 Mutex mu;
500};
501
Caitlin Sadowski99107eb2011-09-09 16:21:55 +0000502class LateBar {
503 public:
504 int a_ __attribute__((guarded_by(mu1_)));
505 int b_;
506 int *q __attribute__((pt_guarded_by(mu)));
507 Mutex mu1_;
508 Mutex mu;
509 LateFoo Foo;
510 LateFoo Foo2;
511 LateFoo *FooPointer;
512};
513
514LateBar b1, *b3;
515
516void late_0() {
517 LateFoo FooA;
518 LateFoo FooB;
519 FooA.mu.Lock();
520 FooA.a = 5;
521 FooA.mu.Unlock();
522}
523
524void late_1() {
525 LateBar BarA;
526 BarA.FooPointer->mu.Lock();
527 BarA.FooPointer->a = 2;
528 BarA.FooPointer->mu.Unlock();
529}
530
531void late_bad_0() {
532 LateFoo fooA;
533 LateFoo fooB;
534 fooA.mu.Lock();
535 fooB.a = 5; // \
DeLesley Hutchinsa74b7152012-08-10 20:19:55 +0000536 // expected-warning{{writing variable 'a' requires locking 'fooB.mu' exclusively}}
Caitlin Sadowski99107eb2011-09-09 16:21:55 +0000537 fooA.mu.Unlock();
538}
539
540void late_bad_1() {
541 Mutex mu;
542 mu.Lock();
543 b1.mu1_.Lock();
544 int res = b1.a_ + b3->b_;
545 b3->b_ = *b1.q; // \
DeLesley Hutchinsa74b7152012-08-10 20:19:55 +0000546 // expected-warning{{reading the value pointed to by 'q' requires locking 'b1.mu'}}
Caitlin Sadowski99107eb2011-09-09 16:21:55 +0000547 b1.mu1_.Unlock();
548 b1.b_ = res;
549 mu.Unlock();
550}
551
552void late_bad_2() {
553 LateBar BarA;
554 BarA.FooPointer->mu.Lock();
555 BarA.Foo.a = 2; // \
DeLesley Hutchinsa74b7152012-08-10 20:19:55 +0000556 // expected-warning{{writing variable 'a' requires locking 'BarA.Foo.mu' exclusively}}
Caitlin Sadowski99107eb2011-09-09 16:21:55 +0000557 BarA.FooPointer->mu.Unlock();
558}
559
560void late_bad_3() {
561 LateBar BarA;
562 BarA.Foo.mu.Lock();
563 BarA.FooPointer->a = 2; // \
DeLesley Hutchinsa74b7152012-08-10 20:19:55 +0000564 // expected-warning{{writing variable 'a' requires locking 'BarA.FooPointer->mu' exclusively}}
Caitlin Sadowski99107eb2011-09-09 16:21:55 +0000565 BarA.Foo.mu.Unlock();
566}
567
568void late_bad_4() {
569 LateBar BarA;
570 BarA.Foo.mu.Lock();
571 BarA.Foo2.a = 2; // \
DeLesley Hutchinsa74b7152012-08-10 20:19:55 +0000572 // expected-warning{{writing variable 'a' requires locking 'BarA.Foo2.mu' exclusively}}
Caitlin Sadowski99107eb2011-09-09 16:21:55 +0000573 BarA.Foo.mu.Unlock();
574}
575
Caitlin Sadowskia53257c2011-09-08 18:19:38 +0000576//-----------------------------------------------//
577// Extra warnings for shared vs. exclusive locks
578// ----------------------------------------------//
579
580void shared_fun_0() {
581 sls_mu.Lock();
582 do {
583 sls_mu.Unlock();
584 sls_mu.Lock();
585 } while (getBool());
586 sls_mu.Unlock();
587}
588
589void shared_fun_1() {
Caitlin Sadowski4e4bc752011-09-15 17:25:19 +0000590 sls_mu.ReaderLock(); // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000591 // expected-warning {{mutex 'sls_mu' is locked exclusively and shared in the same scope}}
Caitlin Sadowskia53257c2011-09-08 18:19:38 +0000592 do {
593 sls_mu.Unlock();
Caitlin Sadowski4e4bc752011-09-15 17:25:19 +0000594 sls_mu.Lock(); // \
595 // expected-note {{the other lock of mutex 'sls_mu' is here}}
Caitlin Sadowskia53257c2011-09-08 18:19:38 +0000596 } while (getBool());
597 sls_mu.Unlock();
598}
599
600void shared_fun_3() {
601 if (getBool())
602 sls_mu.Lock();
603 else
604 sls_mu.Lock();
605 *pgb_var = 1;
606 sls_mu.Unlock();
607}
608
609void shared_fun_4() {
610 if (getBool())
611 sls_mu.ReaderLock();
612 else
613 sls_mu.ReaderLock();
614 int x = sls_guardby_var;
615 sls_mu.Unlock();
616}
617
618void shared_fun_8() {
619 if (getBool())
620 sls_mu.Lock(); // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000621 // expected-warning {{mutex 'sls_mu' is locked exclusively and shared in the same scope}}
Caitlin Sadowskia53257c2011-09-08 18:19:38 +0000622 else
623 sls_mu.ReaderLock(); // \
Caitlin Sadowski8bccabe2011-09-08 21:52:50 +0000624 // expected-note {{the other lock of mutex 'sls_mu' is here}}
Caitlin Sadowskia53257c2011-09-08 18:19:38 +0000625 sls_mu.Unlock();
626}
627
628void shared_bad_0() {
Caitlin Sadowski4e4bc752011-09-15 17:25:19 +0000629 sls_mu.Lock(); // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000630 // expected-warning {{mutex 'sls_mu' is locked exclusively and shared in the same scope}}
Caitlin Sadowskia53257c2011-09-08 18:19:38 +0000631 do {
632 sls_mu.Unlock();
Caitlin Sadowski4e4bc752011-09-15 17:25:19 +0000633 sls_mu.ReaderLock(); // \
634 // expected-note {{the other lock of mutex 'sls_mu' is here}}
Caitlin Sadowskia53257c2011-09-08 18:19:38 +0000635 } while (getBool());
636 sls_mu.Unlock();
637}
638
639void shared_bad_1() {
640 if (getBool())
641 sls_mu.Lock(); // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000642 // expected-warning {{mutex 'sls_mu' is locked exclusively and shared in the same scope}}
Caitlin Sadowskia53257c2011-09-08 18:19:38 +0000643 else
644 sls_mu.ReaderLock(); // \
Caitlin Sadowski8bccabe2011-09-08 21:52:50 +0000645 // expected-note {{the other lock of mutex 'sls_mu' is here}}
Caitlin Sadowskia53257c2011-09-08 18:19:38 +0000646 *pgb_var = 1;
647 sls_mu.Unlock();
648}
649
650void shared_bad_2() {
651 if (getBool())
652 sls_mu.ReaderLock(); // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000653 // expected-warning {{mutex 'sls_mu' is locked exclusively and shared in the same scope}}
Caitlin Sadowskia53257c2011-09-08 18:19:38 +0000654 else
655 sls_mu.Lock(); // \
Caitlin Sadowski8bccabe2011-09-08 21:52:50 +0000656 // expected-note {{the other lock of mutex 'sls_mu' is here}}
Caitlin Sadowskia53257c2011-09-08 18:19:38 +0000657 *pgb_var = 1;
658 sls_mu.Unlock();
659}
Caitlin Sadowski978191e2011-09-08 18:27:31 +0000660
661// FIXME: Add support for functions (not only methods)
662class LRBar {
663 public:
664 void aa_elr_fun() __attribute__((exclusive_locks_required(aa_mu)));
665 void aa_elr_fun_s() __attribute__((shared_locks_required(aa_mu)));
666 void le_fun() __attribute__((locks_excluded(sls_mu)));
667};
668
669class LRFoo {
670 public:
671 void test() __attribute__((exclusive_locks_required(sls_mu)));
672 void testShared() __attribute__((shared_locks_required(sls_mu2)));
673};
674
675void elr_fun() __attribute__((exclusive_locks_required(sls_mu)));
676void elr_fun() {}
677
678LRFoo MyLRFoo;
679LRBar Bar;
680
681void es_fun_0() {
682 aa_mu.Lock();
683 Bar.aa_elr_fun();
684 aa_mu.Unlock();
685}
686
687void es_fun_1() {
688 aa_mu.Lock();
689 Bar.aa_elr_fun_s();
690 aa_mu.Unlock();
691}
692
693void es_fun_2() {
694 aa_mu.ReaderLock();
695 Bar.aa_elr_fun_s();
696 aa_mu.Unlock();
697}
698
699void es_fun_3() {
700 sls_mu.Lock();
701 MyLRFoo.test();
702 sls_mu.Unlock();
703}
704
705void es_fun_4() {
706 sls_mu2.Lock();
707 MyLRFoo.testShared();
708 sls_mu2.Unlock();
709}
710
711void es_fun_5() {
712 sls_mu2.ReaderLock();
713 MyLRFoo.testShared();
714 sls_mu2.Unlock();
715}
716
717void es_fun_6() {
718 Bar.le_fun();
719}
720
721void es_fun_7() {
722 sls_mu.Lock();
723 elr_fun();
724 sls_mu.Unlock();
725}
726
Caitlin Sadowskiaf370612011-09-08 18:35:21 +0000727void es_fun_8() __attribute__((no_thread_safety_analysis));
728
729void es_fun_8() {
730 Bar.aa_elr_fun_s();
731}
732
Caitlin Sadowskicb967512011-09-15 17:43:08 +0000733void es_fun_9() __attribute__((shared_locks_required(aa_mu)));
734void es_fun_9() {
735 Bar.aa_elr_fun_s();
736}
737
738void es_fun_10() __attribute__((exclusive_locks_required(aa_mu)));
739void es_fun_10() {
740 Bar.aa_elr_fun_s();
741}
742
Caitlin Sadowski978191e2011-09-08 18:27:31 +0000743void es_bad_0() {
744 Bar.aa_elr_fun(); // \
Caitlin Sadowski8bccabe2011-09-08 21:52:50 +0000745 // expected-warning {{calling function 'aa_elr_fun' requires exclusive lock on 'aa_mu'}}
Caitlin Sadowski978191e2011-09-08 18:27:31 +0000746}
747
748void es_bad_1() {
749 aa_mu.ReaderLock();
750 Bar.aa_elr_fun(); // \
Caitlin Sadowski8bccabe2011-09-08 21:52:50 +0000751 // expected-warning {{calling function 'aa_elr_fun' requires exclusive lock on 'aa_mu'}}
Caitlin Sadowski978191e2011-09-08 18:27:31 +0000752 aa_mu.Unlock();
753}
754
755void es_bad_2() {
756 Bar.aa_elr_fun_s(); // \
Caitlin Sadowski8bccabe2011-09-08 21:52:50 +0000757 // expected-warning {{calling function 'aa_elr_fun_s' requires shared lock on 'aa_mu'}}
Caitlin Sadowski978191e2011-09-08 18:27:31 +0000758}
759
760void es_bad_3() {
761 MyLRFoo.test(); // \
Caitlin Sadowski8bccabe2011-09-08 21:52:50 +0000762 // expected-warning {{calling function 'test' requires exclusive lock on 'sls_mu'}}
Caitlin Sadowski978191e2011-09-08 18:27:31 +0000763}
764
765void es_bad_4() {
766 MyLRFoo.testShared(); // \
Caitlin Sadowski8bccabe2011-09-08 21:52:50 +0000767 // expected-warning {{calling function 'testShared' requires shared lock on 'sls_mu2'}}
Caitlin Sadowski978191e2011-09-08 18:27:31 +0000768}
769
770void es_bad_5() {
771 sls_mu.ReaderLock();
772 MyLRFoo.test(); // \
Caitlin Sadowski8bccabe2011-09-08 21:52:50 +0000773 // expected-warning {{calling function 'test' requires exclusive lock on 'sls_mu'}}
Caitlin Sadowski978191e2011-09-08 18:27:31 +0000774 sls_mu.Unlock();
775}
776
777void es_bad_6() {
778 sls_mu.Lock();
779 Bar.le_fun(); // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000780 // expected-warning {{cannot call function 'le_fun' while mutex 'sls_mu' is locked}}
Caitlin Sadowski978191e2011-09-08 18:27:31 +0000781 sls_mu.Unlock();
782}
783
784void es_bad_7() {
785 sls_mu.ReaderLock();
786 Bar.le_fun(); // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000787 // expected-warning {{cannot call function 'le_fun' while mutex 'sls_mu' is locked}}
Caitlin Sadowski978191e2011-09-08 18:27:31 +0000788 sls_mu.Unlock();
789}
Caitlin Sadowski194418f2011-09-14 20:00:24 +0000790
DeLesley Hutchins81216392011-10-17 21:38:02 +0000791
Caitlin Sadowski194418f2011-09-14 20:00:24 +0000792//-----------------------------------------------//
793// Unparseable lock expressions
794// ----------------------------------------------//
795
DeLesley Hutchins0d95dfc2012-03-02 23:36:05 +0000796// FIXME -- derive new tests for unhandled expressions
Caitlin Sadowski194418f2011-09-14 20:00:24 +0000797
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +0000798
799//----------------------------------------------------------------------------//
800// The following test cases are ported from the gcc thread safety implementation
801// They are each wrapped inside a namespace with the test number of the gcc test
802//
803// FIXME: add all the gcc tests, once this analysis passes them.
804//----------------------------------------------------------------------------//
805
806//-----------------------------------------//
807// Good testcases (no errors)
808//-----------------------------------------//
809
810namespace thread_annot_lock_20 {
811class Bar {
812 public:
813 static int func1() EXCLUSIVE_LOCKS_REQUIRED(mu1_);
814 static int b_ GUARDED_BY(mu1_);
815 static Mutex mu1_;
816 static int a_ GUARDED_BY(mu1_);
817};
818
819Bar b1;
820
821int Bar::func1()
822{
823 int res = 5;
824
825 if (a_ == 4)
826 res = b_;
827 return res;
828}
829} // end namespace thread_annot_lock_20
830
831namespace thread_annot_lock_22 {
832// Test various usage of GUARDED_BY and PT_GUARDED_BY annotations, especially
833// uses in class definitions.
834Mutex mu;
835
836class Bar {
837 public:
838 int a_ GUARDED_BY(mu1_);
839 int b_;
840 int *q PT_GUARDED_BY(mu);
841 Mutex mu1_ ACQUIRED_AFTER(mu);
842};
843
844Bar b1, *b3;
845int *p GUARDED_BY(mu) PT_GUARDED_BY(mu);
846int res GUARDED_BY(mu) = 5;
847
848int func(int i)
849{
850 int x;
851 mu.Lock();
852 b1.mu1_.Lock();
853 res = b1.a_ + b3->b_;
854 *p = i;
855 b1.a_ = res + b3->b_;
856 b3->b_ = *b1.q;
857 b1.mu1_.Unlock();
858 b1.b_ = res;
859 x = res;
860 mu.Unlock();
861 return x;
862}
863} // end namespace thread_annot_lock_22
864
865namespace thread_annot_lock_27_modified {
866// test lock annotations applied to function definitions
867// Modified: applied annotations only to function declarations
868Mutex mu1;
869Mutex mu2 ACQUIRED_AFTER(mu1);
870
871class Foo {
872 public:
873 int method1(int i) SHARED_LOCKS_REQUIRED(mu2) EXCLUSIVE_LOCKS_REQUIRED(mu1);
874};
875
876int Foo::method1(int i) {
877 return i;
878}
879
880
881int foo(int i) EXCLUSIVE_LOCKS_REQUIRED(mu2) SHARED_LOCKS_REQUIRED(mu1);
882int foo(int i) {
883 return i;
884}
885
886static int bar(int i) EXCLUSIVE_LOCKS_REQUIRED(mu1);
887static int bar(int i) {
888 return i;
889}
890
891void main() {
892 Foo a;
893
894 mu1.Lock();
895 mu2.Lock();
896 a.method1(1);
897 foo(2);
898 mu2.Unlock();
899 bar(3);
900 mu1.Unlock();
901}
902} // end namespace thread_annot_lock_27_modified
903
904
905namespace thread_annot_lock_38 {
906// Test the case where a template member function is annotated with lock
907// attributes in a non-template class.
908class Foo {
909 public:
910 void func1(int y) LOCKS_EXCLUDED(mu_);
911 template <typename T> void func2(T x) LOCKS_EXCLUDED(mu_);
912 private:
913 Mutex mu_;
914};
915
916Foo *foo;
917
918void main()
919{
920 foo->func1(5);
921 foo->func2(5);
922}
923} // end namespace thread_annot_lock_38
924
925namespace thread_annot_lock_43 {
926// Tests lock canonicalization
927class Foo {
928 public:
929 Mutex *mu_;
930};
931
932class FooBar {
933 public:
934 Foo *foo_;
935 int GetA() EXCLUSIVE_LOCKS_REQUIRED(foo_->mu_) { return a_; }
936 int a_ GUARDED_BY(foo_->mu_);
937};
938
939FooBar *fb;
940
941void main()
942{
943 int x;
944 fb->foo_->mu_->Lock();
945 x = fb->GetA();
946 fb->foo_->mu_->Unlock();
947}
948} // end namespace thread_annot_lock_43
949
950namespace thread_annot_lock_49 {
951// Test the support for use of lock expression in the annotations
952class Foo {
953 public:
954 Mutex foo_mu_;
955};
956
957class Bar {
958 private:
959 Foo *foo;
960 Mutex bar_mu_ ACQUIRED_AFTER(foo->foo_mu_);
961
962 public:
963 void Test1() {
964 foo->foo_mu_.Lock();
965 bar_mu_.Lock();
966 bar_mu_.Unlock();
967 foo->foo_mu_.Unlock();
968 }
969};
970
971void main() {
972 Bar bar;
973 bar.Test1();
974}
975} // end namespace thread_annot_lock_49
976
977namespace thread_annot_lock_61_modified {
978 // Modified to fix the compiler errors
979 // Test the fix for a bug introduced by the support of pass-by-reference
980 // paramters.
981 struct Foo { Foo &operator<< (bool) {return *this;} };
982 Foo &getFoo();
983 struct Bar { Foo &func () {return getFoo();} };
984 struct Bas { void operator& (Foo &) {} };
985 void mumble()
986 {
987 Bas() & Bar().func() << "" << "";
988 Bas() & Bar().func() << "";
989 }
990} // end namespace thread_annot_lock_61_modified
991
992
993namespace thread_annot_lock_65 {
994// Test the fix for a bug in the support of allowing reader locks for
995// non-const, non-modifying overload functions. (We didn't handle the builtin
996// properly.)
997enum MyFlags {
998 Zero,
999 One,
1000 Two,
1001 Three,
1002 Four,
1003 Five,
1004 Six,
1005 Seven,
1006 Eight,
1007 Nine
1008};
1009
1010inline MyFlags
1011operator|(MyFlags a, MyFlags b)
1012{
1013 return MyFlags(static_cast<int>(a) | static_cast<int>(b));
1014}
1015
1016inline MyFlags&
1017operator|=(MyFlags& a, MyFlags b)
1018{
1019 return a = a | b;
1020}
1021} // end namespace thread_annot_lock_65
1022
1023namespace thread_annot_lock_66_modified {
1024// Modified: Moved annotation to function defn
1025// Test annotations on out-of-line definitions of member functions where the
1026// annotations refer to locks that are also data members in the class.
1027Mutex mu;
1028
1029class Foo {
1030 public:
1031 int method1(int i) SHARED_LOCKS_REQUIRED(mu1, mu, mu2);
1032 int data GUARDED_BY(mu1);
1033 Mutex *mu1;
1034 Mutex *mu2;
1035};
1036
1037int Foo::method1(int i)
1038{
1039 return data + i;
1040}
1041
1042void main()
1043{
1044 Foo a;
1045
1046 a.mu2->Lock();
1047 a.mu1->Lock();
1048 mu.Lock();
1049 a.method1(1);
1050 mu.Unlock();
1051 a.mu1->Unlock();
1052 a.mu2->Unlock();
1053}
1054} // end namespace thread_annot_lock_66_modified
1055
1056namespace thread_annot_lock_68_modified {
1057// Test a fix to a bug in the delayed name binding with nested template
1058// instantiation. We use a stack to make sure a name is not resolved to an
1059// inner context.
1060template <typename T>
1061class Bar {
1062 Mutex mu_;
1063};
1064
1065template <typename T>
1066class Foo {
1067 public:
1068 void func(T x) {
1069 mu_.Lock();
DeLesley Hutchins23323e02012-01-20 22:50:54 +00001070 count_ = x;
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001071 mu_.Unlock();
1072 }
1073
1074 private:
DeLesley Hutchins23323e02012-01-20 22:50:54 +00001075 T count_ GUARDED_BY(mu_);
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001076 Bar<T> bar_;
1077 Mutex mu_;
1078};
1079
1080void main()
1081{
1082 Foo<int> *foo;
1083 foo->func(5);
1084}
1085} // end namespace thread_annot_lock_68_modified
1086
1087namespace thread_annot_lock_30_modified {
1088// Test delay parsing of lock attribute arguments with nested classes.
1089// Modified: trylocks replaced with exclusive_lock_fun
1090int a = 0;
1091
1092class Bar {
1093 struct Foo;
1094
1095 public:
1096 void MyLock() EXCLUSIVE_LOCK_FUNCTION(mu);
1097
1098 int func() {
1099 MyLock();
1100// if (foo == 0) {
1101// return 0;
1102// }
1103 a = 5;
1104 mu.Unlock();
1105 return 1;
1106 }
1107
1108 class FooBar {
1109 int x;
1110 int y;
1111 };
1112
1113 private:
1114 Mutex mu;
1115};
1116
1117Bar *bar;
1118
1119void main()
1120{
1121 bar->func();
1122}
1123} // end namespace thread_annot_lock_30_modified
1124
1125namespace thread_annot_lock_47 {
1126// Test the support for annotations on virtual functions.
1127// This is a good test case. (i.e. There should be no warning emitted by the
1128// compiler.)
1129class Base {
1130 public:
1131 virtual void func1() EXCLUSIVE_LOCKS_REQUIRED(mu_);
1132 virtual void func2() LOCKS_EXCLUDED(mu_);
1133 Mutex mu_;
1134};
1135
1136class Child : public Base {
1137 public:
1138 virtual void func1() EXCLUSIVE_LOCKS_REQUIRED(mu_);
1139 virtual void func2() LOCKS_EXCLUDED(mu_);
1140};
1141
1142void main() {
1143 Child *c;
1144 Base *b = c;
1145
1146 b->mu_.Lock();
1147 b->func1();
1148 b->mu_.Unlock();
1149 b->func2();
1150
1151 c->mu_.Lock();
1152 c->func1();
1153 c->mu_.Unlock();
1154 c->func2();
1155}
1156} // end namespace thread_annot_lock_47
1157
1158//-----------------------------------------//
1159// Tests which produce errors
1160//-----------------------------------------//
1161
1162namespace thread_annot_lock_13 {
1163Mutex mu1;
1164Mutex mu2;
1165
1166int g GUARDED_BY(mu1);
1167int w GUARDED_BY(mu2);
1168
1169class Foo {
1170 public:
1171 void bar() LOCKS_EXCLUDED(mu_, mu1);
1172 int foo() SHARED_LOCKS_REQUIRED(mu_) EXCLUSIVE_LOCKS_REQUIRED(mu2);
1173
1174 private:
1175 int a_ GUARDED_BY(mu_);
1176 public:
1177 Mutex mu_ ACQUIRED_AFTER(mu1);
1178};
1179
1180int Foo::foo()
1181{
1182 int res;
David Blaikiee31b8fb2012-04-05 00:16:44 +00001183 w = 5;
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001184 res = a_ + 5;
1185 return res;
1186}
1187
1188void Foo::bar()
1189{
1190 int x;
1191 mu_.Lock();
1192 x = foo(); // expected-warning {{calling function 'foo' requires exclusive lock on 'mu2'}}
1193 a_ = x + 1;
1194 mu_.Unlock();
1195 if (x > 5) {
1196 mu1.Lock();
David Blaikiee31b8fb2012-04-05 00:16:44 +00001197 g = 2;
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001198 mu1.Unlock();
1199 }
1200}
1201
1202void main()
1203{
1204 Foo f1, *f2;
1205 f1.mu_.Lock();
DeLesley Hutchinsa74b7152012-08-10 20:19:55 +00001206 f1.bar(); // expected-warning {{cannot call function 'bar' while mutex 'f1.mu_' is locked}}
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001207 mu2.Lock();
1208 f1.foo();
1209 mu2.Unlock();
1210 f1.mu_.Unlock();
1211 f2->mu_.Lock();
DeLesley Hutchinsa74b7152012-08-10 20:19:55 +00001212 f2->bar(); // expected-warning {{cannot call function 'bar' while mutex 'f2->mu_' is locked}}
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001213 f2->mu_.Unlock();
1214 mu2.Lock();
David Blaikiee31b8fb2012-04-05 00:16:44 +00001215 w = 2;
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001216 mu2.Unlock();
1217}
1218} // end namespace thread_annot_lock_13
1219
1220namespace thread_annot_lock_18_modified {
1221// Modified: Trylocks removed
1222// Test the ability to distnguish between the same lock field of
1223// different objects of a class.
1224 class Bar {
1225 public:
1226 bool MyLock() EXCLUSIVE_LOCK_FUNCTION(mu1_);
1227 void MyUnlock() UNLOCK_FUNCTION(mu1_);
1228 int a_ GUARDED_BY(mu1_);
1229
1230 private:
1231 Mutex mu1_;
1232};
1233
1234Bar *b1, *b2;
1235
1236void func()
1237{
1238 b1->MyLock();
1239 b1->a_ = 5;
DeLesley Hutchinsa74b7152012-08-10 20:19:55 +00001240 b2->a_ = 3; // expected-warning {{writing variable 'a_' requires locking 'b2->mu1_' exclusively}}
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001241 b2->MyLock();
1242 b2->MyUnlock();
1243 b1->MyUnlock();
1244}
1245} // end namespace thread_annot_lock_18_modified
1246
1247namespace thread_annot_lock_21 {
1248// Test various usage of GUARDED_BY and PT_GUARDED_BY annotations, especially
1249// uses in class definitions.
1250Mutex mu;
1251
1252class Bar {
1253 public:
1254 int a_ GUARDED_BY(mu1_);
1255 int b_;
1256 int *q PT_GUARDED_BY(mu);
1257 Mutex mu1_ ACQUIRED_AFTER(mu);
1258};
1259
1260Bar b1, *b3;
1261int *p GUARDED_BY(mu) PT_GUARDED_BY(mu);
1262
1263int res GUARDED_BY(mu) = 5;
1264
1265int func(int i)
1266{
1267 int x;
1268 b3->mu1_.Lock();
DeLesley Hutchinsa74b7152012-08-10 20:19:55 +00001269 res = b1.a_ + b3->b_; // expected-warning {{reading variable 'a_' requires locking 'b1.mu1_'}} \
Caitlin Sadowski74558b42011-09-15 18:13:32 +00001270 // expected-warning {{writing variable 'res' requires locking 'mu' exclusively}}
1271 *p = i; // expected-warning {{reading variable 'p' requires locking 'mu'}} \
1272 // expected-warning {{writing the value pointed to by 'p' requires locking 'mu' exclusively}}
1273 b1.a_ = res + b3->b_; // expected-warning {{reading variable 'res' requires locking 'mu'}} \
DeLesley Hutchinsa74b7152012-08-10 20:19:55 +00001274 // expected-warning {{writing variable 'a_' requires locking 'b1.mu1_' exclusively}}
Caitlin Sadowski74558b42011-09-15 18:13:32 +00001275 b3->b_ = *b1.q; // expected-warning {{reading the value pointed to by 'q' requires locking 'mu'}}
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001276 b3->mu1_.Unlock();
Caitlin Sadowski74558b42011-09-15 18:13:32 +00001277 b1.b_ = res; // expected-warning {{reading variable 'res' requires locking 'mu'}}
1278 x = res; // expected-warning {{reading variable 'res' requires locking 'mu'}}
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001279 return x;
1280}
1281} // end namespace thread_annot_lock_21
1282
1283namespace thread_annot_lock_35_modified {
1284// Test the analyzer's ability to distinguish the lock field of different
1285// objects.
1286class Foo {
1287 private:
1288 Mutex lock_;
1289 int a_ GUARDED_BY(lock_);
1290
1291 public:
1292 void Func(Foo* child) LOCKS_EXCLUDED(lock_) {
1293 Foo *new_foo = new Foo;
1294
1295 lock_.Lock();
1296
1297 child->Func(new_foo); // There shouldn't be any warning here as the
1298 // acquired lock is not in child.
DeLesley Hutchinsa74b7152012-08-10 20:19:55 +00001299 child->bar(7); // expected-warning {{calling function 'bar' requires exclusive lock on 'child->lock_'}}
1300 child->a_ = 5; // expected-warning {{writing variable 'a_' requires locking 'child->lock_' exclusively}}
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001301 lock_.Unlock();
1302 }
1303
1304 void bar(int y) EXCLUSIVE_LOCKS_REQUIRED(lock_) {
1305 a_ = y;
1306 }
1307};
1308
1309Foo *x;
1310
1311void main() {
1312 Foo *child = new Foo;
1313 x->Func(child);
1314}
1315} // end namespace thread_annot_lock_35_modified
1316
1317namespace thread_annot_lock_36_modified {
1318// Modified to move the annotations to function defns.
1319// Test the analyzer's ability to distinguish the lock field of different
1320// objects
1321class Foo {
1322 private:
1323 Mutex lock_;
1324 int a_ GUARDED_BY(lock_);
1325
1326 public:
1327 void Func(Foo* child) LOCKS_EXCLUDED(lock_);
1328 void bar(int y) EXCLUSIVE_LOCKS_REQUIRED(lock_);
1329};
1330
1331void Foo::Func(Foo* child) {
1332 Foo *new_foo = new Foo;
1333
1334 lock_.Lock();
1335
1336 child->lock_.Lock();
DeLesley Hutchinsa74b7152012-08-10 20:19:55 +00001337 child->Func(new_foo); // expected-warning {{cannot call function 'Func' while mutex 'child->lock_' is locked}}
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001338 child->bar(7);
1339 child->a_ = 5;
1340 child->lock_.Unlock();
1341
1342 lock_.Unlock();
1343}
1344
1345void Foo::bar(int y) {
1346 a_ = y;
1347}
1348
1349
1350Foo *x;
1351
1352void main() {
1353 Foo *child = new Foo;
1354 x->Func(child);
1355}
1356} // end namespace thread_annot_lock_36_modified
1357
1358
1359namespace thread_annot_lock_42 {
1360// Test support of multiple lock attributes of the same kind on a decl.
1361class Foo {
1362 private:
1363 Mutex mu1, mu2, mu3;
1364 int x GUARDED_BY(mu1) GUARDED_BY(mu2);
1365 int y GUARDED_BY(mu2);
1366
1367 void f2() LOCKS_EXCLUDED(mu1) LOCKS_EXCLUDED(mu2) LOCKS_EXCLUDED(mu3) {
1368 mu2.Lock();
1369 y = 2;
1370 mu2.Unlock();
1371 }
1372
1373 public:
1374 void f1() EXCLUSIVE_LOCKS_REQUIRED(mu2) EXCLUSIVE_LOCKS_REQUIRED(mu1) {
1375 x = 5;
Caitlin Sadowski74558b42011-09-15 18:13:32 +00001376 f2(); // expected-warning {{cannot call function 'f2' while mutex 'mu1' is locked}} \
1377 // expected-warning {{cannot call function 'f2' while mutex 'mu2' is locked}}
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001378 }
1379};
1380
1381Foo *foo;
1382
1383void func()
1384{
DeLesley Hutchinsa74b7152012-08-10 20:19:55 +00001385 foo->f1(); // expected-warning {{calling function 'f1' requires exclusive lock on 'foo->mu2'}} \
1386 // expected-warning {{calling function 'f1' requires exclusive lock on 'foo->mu1'}}
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001387}
1388} // end namespace thread_annot_lock_42
1389
1390namespace thread_annot_lock_46 {
1391// Test the support for annotations on virtual functions.
1392class Base {
1393 public:
1394 virtual void func1() EXCLUSIVE_LOCKS_REQUIRED(mu_);
1395 virtual void func2() LOCKS_EXCLUDED(mu_);
1396 Mutex mu_;
1397};
1398
1399class Child : public Base {
1400 public:
1401 virtual void func1() EXCLUSIVE_LOCKS_REQUIRED(mu_);
1402 virtual void func2() LOCKS_EXCLUDED(mu_);
1403};
1404
1405void main() {
1406 Child *c;
1407 Base *b = c;
1408
DeLesley Hutchinsa74b7152012-08-10 20:19:55 +00001409 b->func1(); // expected-warning {{calling function 'func1' requires exclusive lock on 'b->mu_'}}
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001410 b->mu_.Lock();
DeLesley Hutchinsa74b7152012-08-10 20:19:55 +00001411 b->func2(); // expected-warning {{cannot call function 'func2' while mutex 'b->mu_' is locked}}
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001412 b->mu_.Unlock();
1413
DeLesley Hutchinsa74b7152012-08-10 20:19:55 +00001414 c->func1(); // expected-warning {{calling function 'func1' requires exclusive lock on 'c->mu_'}}
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001415 c->mu_.Lock();
DeLesley Hutchinsa74b7152012-08-10 20:19:55 +00001416 c->func2(); // expected-warning {{cannot call function 'func2' while mutex 'c->mu_' is locked}}
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001417 c->mu_.Unlock();
1418}
1419} // end namespace thread_annot_lock_46
1420
1421namespace thread_annot_lock_67_modified {
1422// Modified: attributes on definitions moved to declarations
1423// Test annotations on out-of-line definitions of member functions where the
1424// annotations refer to locks that are also data members in the class.
1425Mutex mu;
1426Mutex mu3;
1427
1428class Foo {
1429 public:
1430 int method1(int i) SHARED_LOCKS_REQUIRED(mu1, mu, mu2, mu3);
1431 int data GUARDED_BY(mu1);
1432 Mutex *mu1;
1433 Mutex *mu2;
1434};
1435
1436int Foo::method1(int i) {
1437 return data + i;
1438}
1439
1440void main()
1441{
1442 Foo a;
DeLesley Hutchinsa74b7152012-08-10 20:19:55 +00001443 a.method1(1); // expected-warning {{calling function 'method1' requires shared lock on 'a.mu1'}} \
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001444 // expected-warning {{calling function 'method1' requires shared lock on 'mu'}} \
DeLesley Hutchinsa74b7152012-08-10 20:19:55 +00001445 // expected-warning {{calling function 'method1' requires shared lock on 'a.mu2'}} \
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001446 // expected-warning {{calling function 'method1' requires shared lock on 'mu3'}}
1447}
1448} // end namespace thread_annot_lock_67_modified
1449
1450
DeLesley Hutchins81216392011-10-17 21:38:02 +00001451namespace substitution_test {
1452 class MyData {
1453 public:
1454 Mutex mu;
1455
1456 void lockData() __attribute__((exclusive_lock_function(mu))) { }
1457 void unlockData() __attribute__((unlock_function(mu))) { }
1458
1459 void doSomething() __attribute__((exclusive_locks_required(mu))) { }
1460 };
1461
1462
1463 class DataLocker {
1464 public:
1465 void lockData (MyData *d) __attribute__((exclusive_lock_function(d->mu))) { }
1466 void unlockData(MyData *d) __attribute__((unlock_function(d->mu))) { }
1467 };
1468
1469
1470 class Foo {
1471 public:
1472 void foo(MyData* d) __attribute__((exclusive_locks_required(d->mu))) { }
1473
1474 void bar1(MyData* d) {
1475 d->lockData();
1476 foo(d);
1477 d->unlockData();
1478 }
1479
1480 void bar2(MyData* d) {
1481 DataLocker dlr;
1482 dlr.lockData(d);
1483 foo(d);
1484 dlr.unlockData(d);
1485 }
1486
1487 void bar3(MyData* d1, MyData* d2) {
1488 DataLocker dlr;
Richard Smith2e515622012-02-03 04:45:26 +00001489 dlr.lockData(d1); // expected-note {{mutex acquired here}}
DeLesley Hutchins81216392011-10-17 21:38:02 +00001490 dlr.unlockData(d2); // \
DeLesley Hutchinsa74b7152012-08-10 20:19:55 +00001491 // expected-warning {{unlocking 'd2->mu' that was not locked}}
1492 } // expected-warning {{mutex 'd1->mu' is still locked at the end of function}}
DeLesley Hutchins81216392011-10-17 21:38:02 +00001493
1494 void bar4(MyData* d1, MyData* d2) {
1495 DataLocker dlr;
1496 dlr.lockData(d1);
1497 foo(d2); // \
DeLesley Hutchinsa74b7152012-08-10 20:19:55 +00001498 // expected-warning {{calling function 'foo' requires exclusive lock on 'd2->mu'}}
DeLesley Hutchins81216392011-10-17 21:38:02 +00001499 dlr.unlockData(d1);
1500 }
1501 };
1502} // end namespace substituation_test
1503
DeLesley Hutchinse0eaa852011-10-21 18:06:53 +00001504
DeLesley Hutchinsf1ac6372011-10-21 18:10:14 +00001505
DeLesley Hutchinse0eaa852011-10-21 18:06:53 +00001506namespace constructor_destructor_tests {
1507 Mutex fooMu;
1508 int myVar GUARDED_BY(fooMu);
1509
1510 class Foo {
1511 public:
1512 Foo() __attribute__((exclusive_lock_function(fooMu))) { }
1513 ~Foo() __attribute__((unlock_function(fooMu))) { }
1514 };
1515
1516 void fooTest() {
DeLesley Hutchins6db51f72011-10-21 20:51:27 +00001517 Foo foo;
DeLesley Hutchinse0eaa852011-10-21 18:06:53 +00001518 myVar = 0;
1519 }
1520}
1521
DeLesley Hutchinsf1ac6372011-10-21 18:10:14 +00001522
1523namespace invalid_lock_expression_test {
1524
1525class LOCKABLE MyLockable {
1526public:
1527 MyLockable() __attribute__((exclusive_lock_function)) { }
DeLesley Hutchins6db51f72011-10-21 20:51:27 +00001528 ~MyLockable() { }
DeLesley Hutchinsf1ac6372011-10-21 18:10:14 +00001529};
1530
1531// create an empty lock expression
1532void foo() {
1533 MyLockable lock; // \
1534 // expected-warning {{cannot resolve lock expression}}
1535}
1536
1537} // end namespace invalid_lock_expression_test
1538
Richard Smith97f9fe02011-10-25 00:41:24 +00001539namespace template_member_test {
DeLesley Hutchinsf1ac6372011-10-21 18:10:14 +00001540
Richard Smith97f9fe02011-10-25 00:41:24 +00001541 struct S { int n; };
1542 struct T {
1543 Mutex m;
1544 S *s GUARDED_BY(this->m);
1545 };
Richard Smitha01c7112011-10-25 06:33:21 +00001546 Mutex m;
1547 struct U {
1548 union {
1549 int n;
1550 };
1551 } *u GUARDED_BY(m);
Richard Smith97f9fe02011-10-25 00:41:24 +00001552
1553 template<typename U>
1554 struct IndirectLock {
1555 int DoNaughtyThings(T *t) {
Richard Smitha01c7112011-10-25 06:33:21 +00001556 u->n = 0; // expected-warning {{reading variable 'u' requires locking 'm'}}
DeLesley Hutchinsa74b7152012-08-10 20:19:55 +00001557 return t->s->n; // expected-warning {{reading variable 's' requires locking 't->m'}}
Richard Smith97f9fe02011-10-25 00:41:24 +00001558 }
1559 };
1560
Richard Smithf11e9232011-10-25 01:05:41 +00001561 template struct IndirectLock<int>; // expected-note {{here}}
Richard Smith97f9fe02011-10-25 00:41:24 +00001562
Richard Smith601d2ee2011-10-26 06:15:36 +00001563 struct V {
1564 void f(int);
1565 void f(double);
1566
1567 Mutex m;
1568 V *p GUARDED_BY(this->m);
1569 };
1570 template<typename U> struct W {
1571 V v;
1572 void f(U u) {
DeLesley Hutchinsa74b7152012-08-10 20:19:55 +00001573 v.p->f(u); // expected-warning {{reading variable 'p' requires locking 'v.m'}}
Richard Smith601d2ee2011-10-26 06:15:36 +00001574 }
1575 };
1576 template struct W<int>; // expected-note {{here}}
1577
Richard Smith97f9fe02011-10-25 00:41:24 +00001578}
DeLesley Hutchins1fa3c062011-12-08 20:23:06 +00001579
1580namespace test_scoped_lockable {
1581
1582struct TestScopedLockable {
1583 Mutex mu1;
1584 Mutex mu2;
1585 int a __attribute__((guarded_by(mu1)));
1586 int b __attribute__((guarded_by(mu2)));
1587
1588 bool getBool();
1589
1590 void foo1() {
1591 MutexLock mulock(&mu1);
1592 a = 5;
1593 }
1594
1595 void foo2() {
1596 ReaderMutexLock mulock1(&mu1);
1597 if (getBool()) {
1598 MutexLock mulock2a(&mu2);
1599 b = a + 1;
1600 }
1601 else {
1602 MutexLock mulock2b(&mu2);
1603 b = a + 2;
1604 }
1605 }
1606
1607 void foo3() {
1608 MutexLock mulock_a(&mu1);
1609 MutexLock mulock_b(&mu1); // \
1610 // expected-warning {{locking 'mu1' that is already locked}}
DeLesley Hutchinsc99a5d82012-06-28 22:42:48 +00001611 }
DeLesley Hutchins1fa3c062011-12-08 20:23:06 +00001612
1613 void foo4() {
1614 MutexLock mulock1(&mu1), mulock2(&mu2);
1615 a = b+1;
1616 b = a+1;
1617 }
1618};
1619
1620} // end namespace test_scoped_lockable
1621
1622
DeLesley Hutchinsdf497822011-12-29 00:56:48 +00001623namespace FunctionAttrTest {
1624
1625class Foo {
1626public:
1627 Mutex mu_;
1628 int a GUARDED_BY(mu_);
1629};
1630
1631Foo fooObj;
1632
1633void foo() EXCLUSIVE_LOCKS_REQUIRED(fooObj.mu_);
1634
1635void bar() {
DeLesley Hutchinsa74b7152012-08-10 20:19:55 +00001636 foo(); // expected-warning {{calling function 'foo' requires exclusive lock on 'fooObj.mu_'}}
DeLesley Hutchinsdf497822011-12-29 00:56:48 +00001637 fooObj.mu_.Lock();
1638 foo();
1639 fooObj.mu_.Unlock();
1640}
1641
1642}; // end namespace FunctionAttrTest
1643
1644
DeLesley Hutchinsb4fa4182012-01-06 19:16:50 +00001645struct TestTryLock {
1646 Mutex mu;
1647 int a GUARDED_BY(mu);
1648 bool cond;
1649
1650 void foo1() {
1651 if (mu.TryLock()) {
1652 a = 1;
1653 mu.Unlock();
1654 }
1655 }
1656
1657 void foo2() {
1658 if (!mu.TryLock()) return;
1659 a = 2;
1660 mu.Unlock();
1661 }
1662
1663 void foo3() {
1664 bool b = mu.TryLock();
1665 if (b) {
1666 a = 3;
1667 mu.Unlock();
1668 }
1669 }
1670
1671 void foo4() {
1672 bool b = mu.TryLock();
1673 if (!b) return;
1674 a = 4;
1675 mu.Unlock();
1676 }
1677
1678 void foo5() {
1679 while (mu.TryLock()) {
1680 a = a + 1;
1681 mu.Unlock();
1682 }
1683 }
1684
1685 void foo6() {
1686 bool b = mu.TryLock();
1687 b = !b;
1688 if (b) return;
1689 a = 6;
1690 mu.Unlock();
1691 }
1692
1693 void foo7() {
1694 bool b1 = mu.TryLock();
1695 bool b2 = !b1;
1696 bool b3 = !b2;
1697 if (b3) {
1698 a = 7;
1699 mu.Unlock();
1700 }
1701 }
1702
1703 // Test use-def chains: join points
1704 void foo8() {
1705 bool b = mu.TryLock();
1706 bool b2 = b;
1707 if (cond)
1708 b = true;
Sylvestre Ledru43e3dee2012-07-31 06:56:50 +00001709 if (b) { // b should be unknown at this point, because of the join point
DeLesley Hutchinsb4fa4182012-01-06 19:16:50 +00001710 a = 8; // expected-warning {{writing variable 'a' requires locking 'mu' exclusively}}
1711 }
1712 if (b2) { // b2 should be known at this point.
1713 a = 8;
1714 mu.Unlock();
1715 }
1716 }
1717
1718 // Test use-def-chains: back edges
1719 void foo9() {
1720 bool b = mu.TryLock();
1721
1722 for (int i = 0; i < 10; ++i);
1723
1724 if (b) { // b is still known, because the loop doesn't alter it
1725 a = 9;
1726 mu.Unlock();
1727 }
1728 }
1729
1730 // Test use-def chains: back edges
1731 void foo10() {
1732 bool b = mu.TryLock();
1733
1734 while (cond) {
1735 if (b) { // b should be uknown at this point b/c of the loop
1736 a = 10; // expected-warning {{writing variable 'a' requires locking 'mu' exclusively}}
1737 }
1738 b = !b;
1739 }
1740 }
1741}; // end TestTrylock
1742
1743
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +00001744namespace TestTemplateAttributeInstantiation {
1745
1746class Foo1 {
1747public:
1748 Mutex mu_;
1749 int a GUARDED_BY(mu_);
1750};
1751
1752class Foo2 {
1753public:
1754 int a GUARDED_BY(mu_);
1755 Mutex mu_;
1756};
1757
1758
1759class Bar {
1760public:
1761 // Test non-dependent expressions in attributes on template functions
1762 template <class T>
1763 void barND(Foo1 *foo, T *fooT) EXCLUSIVE_LOCKS_REQUIRED(foo->mu_) {
1764 foo->a = 0;
1765 }
1766
1767 // Test dependent expressions in attributes on template functions
1768 template <class T>
1769 void barD(Foo1 *foo, T *fooT) EXCLUSIVE_LOCKS_REQUIRED(fooT->mu_) {
1770 fooT->a = 0;
1771 }
1772};
1773
1774
1775template <class T>
1776class BarT {
1777public:
1778 Foo1 fooBase;
1779 T fooBaseT;
1780
1781 // Test non-dependent expression in ordinary method on template class
1782 void barND() EXCLUSIVE_LOCKS_REQUIRED(fooBase.mu_) {
1783 fooBase.a = 0;
1784 }
1785
1786 // Test dependent expressions in ordinary methods on template class
1787 void barD() EXCLUSIVE_LOCKS_REQUIRED(fooBaseT.mu_) {
1788 fooBaseT.a = 0;
1789 }
1790
1791 // Test dependent expressions in template method in template class
1792 template <class T2>
1793 void barTD(T2 *fooT) EXCLUSIVE_LOCKS_REQUIRED(fooBaseT.mu_, fooT->mu_) {
1794 fooBaseT.a = 0;
1795 fooT->a = 0;
1796 }
1797};
1798
1799template <class T>
1800class Cell {
1801public:
1802 Mutex mu_;
1803 // Test dependent guarded_by
1804 T data GUARDED_BY(mu_);
1805
DeLesley Hutchins23323e02012-01-20 22:50:54 +00001806 void fooEx() EXCLUSIVE_LOCKS_REQUIRED(mu_) {
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +00001807 data = 0;
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +00001808 }
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +00001809
1810 void foo() {
1811 mu_.Lock();
1812 data = 0;
1813 mu_.Unlock();
1814 }
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +00001815};
1816
1817void test() {
1818 Bar b;
1819 BarT<Foo2> bt;
1820 Foo1 f1;
1821 Foo2 f2;
1822
1823 f1.mu_.Lock();
1824 f2.mu_.Lock();
1825 bt.fooBase.mu_.Lock();
1826 bt.fooBaseT.mu_.Lock();
1827
1828 b.barND(&f1, &f2);
1829 b.barD(&f1, &f2);
1830 bt.barND();
1831 bt.barD();
1832 bt.barTD(&f2);
1833
1834 f1.mu_.Unlock();
1835 bt.barTD(&f1); // \
DeLesley Hutchinsa74b7152012-08-10 20:19:55 +00001836 // expected-warning {{calling function 'barTD' requires exclusive lock on 'f1.mu_'}}
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +00001837
1838 bt.fooBase.mu_.Unlock();
1839 bt.fooBaseT.mu_.Unlock();
1840 f2.mu_.Unlock();
1841
1842 Cell<int> cell;
1843 cell.data = 0; // \
DeLesley Hutchinsa74b7152012-08-10 20:19:55 +00001844 // expected-warning {{writing variable 'data' requires locking 'cell.mu_' exclusively}}
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +00001845 cell.foo();
DeLesley Hutchins23323e02012-01-20 22:50:54 +00001846 cell.mu_.Lock();
1847 cell.fooEx();
1848 cell.mu_.Unlock();
1849}
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +00001850
DeLesley Hutchins23323e02012-01-20 22:50:54 +00001851
1852template <class T>
1853class CellDelayed {
1854public:
1855 // Test dependent guarded_by
1856 T data GUARDED_BY(mu_);
DeLesley Hutchinsdd5756c2012-02-16 17:30:51 +00001857 static T static_data GUARDED_BY(static_mu_);
DeLesley Hutchins23323e02012-01-20 22:50:54 +00001858
1859 void fooEx(CellDelayed<T> *other) EXCLUSIVE_LOCKS_REQUIRED(mu_, other->mu_) {
1860 this->data = other->data;
1861 }
1862
1863 template <class T2>
1864 void fooExT(CellDelayed<T2> *otherT) EXCLUSIVE_LOCKS_REQUIRED(mu_, otherT->mu_) {
1865 this->data = otherT->data;
1866 }
1867
1868 void foo() {
1869 mu_.Lock();
1870 data = 0;
1871 mu_.Unlock();
1872 }
1873
1874 Mutex mu_;
DeLesley Hutchinsdd5756c2012-02-16 17:30:51 +00001875 static Mutex static_mu_;
DeLesley Hutchins23323e02012-01-20 22:50:54 +00001876};
1877
1878void testDelayed() {
1879 CellDelayed<int> celld;
1880 CellDelayed<int> celld2;
1881 celld.foo();
1882 celld.mu_.Lock();
1883 celld2.mu_.Lock();
1884
1885 celld.fooEx(&celld2);
1886 celld.fooExT(&celld2);
1887
1888 celld2.mu_.Unlock();
1889 celld.mu_.Unlock();
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +00001890}
1891
1892}; // end namespace TestTemplateAttributeInstantiation
1893
1894
DeLesley Hutchinse03b2b32012-01-20 23:24:41 +00001895namespace FunctionDeclDefTest {
1896
1897class Foo {
1898public:
1899 Mutex mu_;
1900 int a GUARDED_BY(mu_);
1901
1902 virtual void foo1(Foo *f_declared) EXCLUSIVE_LOCKS_REQUIRED(f_declared->mu_);
1903};
1904
1905// EXCLUSIVE_LOCKS_REQUIRED should be applied, and rewritten to f_defined->mu_
1906void Foo::foo1(Foo *f_defined) {
1907 f_defined->a = 0;
1908};
1909
1910void test() {
1911 Foo myfoo;
1912 myfoo.foo1(&myfoo); // \
DeLesley Hutchinsa74b7152012-08-10 20:19:55 +00001913 // expected-warning {{calling function 'foo1' requires exclusive lock on 'myfoo.mu_'}}
DeLesley Hutchinse03b2b32012-01-20 23:24:41 +00001914 myfoo.mu_.Lock();
1915 myfoo.foo1(&myfoo);
1916 myfoo.mu_.Unlock();
1917}
1918
1919};
Richard Smith2e515622012-02-03 04:45:26 +00001920
1921namespace GoingNative {
1922
1923 struct __attribute__((lockable)) mutex {
1924 void lock() __attribute__((exclusive_lock_function));
1925 void unlock() __attribute__((unlock_function));
1926 // ...
1927 };
1928 bool foo();
1929 bool bar();
1930 mutex m;
1931 void test() {
1932 m.lock();
1933 while (foo()) {
1934 m.unlock();
1935 // ...
1936 if (bar()) {
1937 // ...
1938 if (foo())
1939 continue; // expected-warning {{expecting mutex 'm' to be locked at start of each loop}}
1940 //...
1941 }
1942 // ...
1943 m.lock(); // expected-note {{mutex acquired here}}
1944 }
1945 m.unlock();
1946 }
1947
1948}
DeLesley Hutchinsc24a2332012-02-16 16:50:43 +00001949
1950
1951
1952namespace FunctionDefinitionTest {
1953
1954class Foo {
1955public:
1956 void foo1();
1957 void foo2();
1958 void foo3(Foo *other);
1959
1960 template<class T>
1961 void fooT1(const T& dummy1);
1962
1963 template<class T>
1964 void fooT2(const T& dummy2) EXCLUSIVE_LOCKS_REQUIRED(mu_);
1965
1966 Mutex mu_;
1967 int a GUARDED_BY(mu_);
1968};
1969
1970template<class T>
1971class FooT {
1972public:
1973 void foo();
1974
1975 Mutex mu_;
1976 T a GUARDED_BY(mu_);
1977};
1978
1979
1980void Foo::foo1() NO_THREAD_SAFETY_ANALYSIS {
1981 a = 1;
1982}
1983
1984void Foo::foo2() EXCLUSIVE_LOCKS_REQUIRED(mu_) {
1985 a = 2;
1986}
1987
1988void Foo::foo3(Foo *other) EXCLUSIVE_LOCKS_REQUIRED(other->mu_) {
1989 other->a = 3;
1990}
1991
1992template<class T>
1993void Foo::fooT1(const T& dummy1) EXCLUSIVE_LOCKS_REQUIRED(mu_) {
1994 a = dummy1;
1995}
1996
1997/* TODO -- uncomment with template instantiation of attributes.
1998template<class T>
1999void Foo::fooT2(const T& dummy2) {
2000 a = dummy2;
2001}
2002*/
2003
2004void fooF1(Foo *f) EXCLUSIVE_LOCKS_REQUIRED(f->mu_) {
2005 f->a = 1;
2006}
2007
2008void fooF2(Foo *f);
2009void fooF2(Foo *f) EXCLUSIVE_LOCKS_REQUIRED(f->mu_) {
2010 f->a = 2;
2011}
2012
2013void fooF3(Foo *f) EXCLUSIVE_LOCKS_REQUIRED(f->mu_);
2014void fooF3(Foo *f) {
2015 f->a = 3;
2016}
2017
2018template<class T>
2019void FooT<T>::foo() EXCLUSIVE_LOCKS_REQUIRED(mu_) {
2020 a = 0;
2021}
2022
2023void test() {
2024 int dummy = 0;
2025 Foo myFoo;
2026
2027 myFoo.foo2(); // \
DeLesley Hutchinsa74b7152012-08-10 20:19:55 +00002028 // expected-warning {{calling function 'foo2' requires exclusive lock on 'myFoo.mu_'}}
DeLesley Hutchinsc24a2332012-02-16 16:50:43 +00002029 myFoo.foo3(&myFoo); // \
DeLesley Hutchinsa74b7152012-08-10 20:19:55 +00002030 // expected-warning {{calling function 'foo3' requires exclusive lock on 'myFoo.mu_'}}
DeLesley Hutchinsc24a2332012-02-16 16:50:43 +00002031 myFoo.fooT1(dummy); // \
DeLesley Hutchinsa74b7152012-08-10 20:19:55 +00002032 // expected-warning {{calling function 'fooT1' requires exclusive lock on 'myFoo.mu_'}}
DeLesley Hutchinsc24a2332012-02-16 16:50:43 +00002033
DeLesley Hutchinsa74b7152012-08-10 20:19:55 +00002034 myFoo.fooT2(dummy); // \
2035 // expected-warning {{calling function 'fooT2' requires exclusive lock on 'myFoo.mu_'}}
DeLesley Hutchinsc24a2332012-02-16 16:50:43 +00002036
2037 fooF1(&myFoo); // \
DeLesley Hutchinsa74b7152012-08-10 20:19:55 +00002038 // expected-warning {{calling function 'fooF1' requires exclusive lock on 'myFoo.mu_'}}
DeLesley Hutchinsc24a2332012-02-16 16:50:43 +00002039 fooF2(&myFoo); // \
DeLesley Hutchinsa74b7152012-08-10 20:19:55 +00002040 // expected-warning {{calling function 'fooF2' requires exclusive lock on 'myFoo.mu_'}}
DeLesley Hutchinsc24a2332012-02-16 16:50:43 +00002041 fooF3(&myFoo); // \
DeLesley Hutchinsa74b7152012-08-10 20:19:55 +00002042 // expected-warning {{calling function 'fooF3' requires exclusive lock on 'myFoo.mu_'}}
DeLesley Hutchinsc24a2332012-02-16 16:50:43 +00002043
2044 myFoo.mu_.Lock();
2045 myFoo.foo2();
2046 myFoo.foo3(&myFoo);
2047 myFoo.fooT1(dummy);
2048
DeLesley Hutchinsa74b7152012-08-10 20:19:55 +00002049 myFoo.fooT2(dummy);
DeLesley Hutchinsc24a2332012-02-16 16:50:43 +00002050
2051 fooF1(&myFoo);
2052 fooF2(&myFoo);
2053 fooF3(&myFoo);
2054 myFoo.mu_.Unlock();
2055
2056 FooT<int> myFooT;
2057 myFooT.foo(); // \
DeLesley Hutchinsa74b7152012-08-10 20:19:55 +00002058 // expected-warning {{calling function 'foo' requires exclusive lock on 'myFooT.mu_'}}
DeLesley Hutchinsc24a2332012-02-16 16:50:43 +00002059}
2060
DeLesley Hutchins4bda3ec2012-02-16 17:03:24 +00002061} // end namespace FunctionDefinitionTest
2062
2063
2064namespace SelfLockingTest {
2065
2066class LOCKABLE MyLock {
2067public:
2068 int foo GUARDED_BY(this);
2069
2070 void lock() EXCLUSIVE_LOCK_FUNCTION();
2071 void unlock() UNLOCK_FUNCTION();
2072
2073 void doSomething() {
2074 this->lock(); // allow 'this' as a lock expression
2075 foo = 0;
2076 doSomethingElse();
2077 this->unlock();
2078 }
2079
2080 void doSomethingElse() EXCLUSIVE_LOCKS_REQUIRED(this) {
2081 foo = 1;
2082 };
2083
2084 void test() {
2085 foo = 2; // \
2086 // expected-warning {{writing variable 'foo' requires locking 'this' exclusively}}
2087 }
DeLesley Hutchinsc24a2332012-02-16 16:50:43 +00002088};
2089
DeLesley Hutchins2f13bec2012-02-16 17:13:43 +00002090
2091class LOCKABLE MyLock2 {
2092public:
2093 Mutex mu_;
2094 int foo GUARDED_BY(this);
2095
2096 // don't check inside lock and unlock functions
2097 void lock() EXCLUSIVE_LOCK_FUNCTION() { mu_.Lock(); }
2098 void unlock() UNLOCK_FUNCTION() { mu_.Unlock(); }
2099
2100 // don't check inside constructors and destructors
2101 MyLock2() { foo = 1; }
2102 ~MyLock2() { foo = 0; }
2103};
2104
2105
DeLesley Hutchins4bda3ec2012-02-16 17:03:24 +00002106} // end namespace SelfLockingTest
2107
2108
DeLesley Hutchinsd08d5992012-02-25 00:11:55 +00002109namespace InvalidNonstatic {
2110
2111// Forward decl here causes bogus "invalid use of non-static data member"
2112// on reference to mutex_ in guarded_by attribute.
2113class Foo;
2114
2115class Foo {
2116 Mutex* mutex_;
2117
2118 int foo __attribute__((guarded_by(mutex_)));
2119};
2120
2121} // end namespace InvalidNonStatic
2122
DeLesley Hutchins2a35be82012-03-02 22:02:58 +00002123
2124namespace NoReturnTest {
2125
2126bool condition();
2127void fatal() __attribute__((noreturn));
2128
2129Mutex mu_;
2130
2131void test1() {
2132 MutexLock lock(&mu_);
2133 if (condition()) {
2134 fatal();
2135 return;
2136 }
2137}
2138
DeLesley Hutchins2287c5e2012-03-02 22:12:59 +00002139} // end namespace NoReturnTest
2140
2141
2142namespace TestMultiDecl {
2143
2144class Foo {
2145public:
2146 int GUARDED_BY(mu_) a;
2147 int GUARDED_BY(mu_) b, c;
2148
2149 void foo() {
2150 a = 0; // \
2151 // expected-warning {{writing variable 'a' requires locking 'mu_' exclusively}}
2152 b = 0; // \
2153 // expected-warning {{writing variable 'b' requires locking 'mu_' exclusively}}
2154 c = 0; // \
2155 // expected-warning {{writing variable 'c' requires locking 'mu_' exclusively}}
2156 }
2157
2158private:
2159 Mutex mu_;
DeLesley Hutchins2a35be82012-03-02 22:02:58 +00002160};
DeLesley Hutchins2287c5e2012-03-02 22:12:59 +00002161
2162} // end namespace TestMultiDecl
2163
DeLesley Hutchins7ec419a2012-03-02 22:29:50 +00002164
2165namespace WarnNoDecl {
2166
2167class Foo {
2168 void foo(int a); __attribute__(( // \
2169 // expected-warning {{declaration does not declare anything}}
2170 exclusive_locks_required(a))); // \
2171 // expected-warning {{attribute exclusive_locks_required ignored}}
2172};
2173
2174} // end namespace WarnNoDecl
2175
2176
DeLesley Hutchins0d95dfc2012-03-02 23:36:05 +00002177
2178namespace MoreLockExpressions {
2179
2180class Foo {
2181public:
2182 Mutex mu_;
2183 int a GUARDED_BY(mu_);
2184};
2185
2186class Bar {
2187public:
2188 int b;
2189 Foo* f;
2190
2191 Foo& getFoo() { return *f; }
2192 Foo& getFoo2(int c) { return *f; }
2193 Foo& getFoo3(int c, int d) { return *f; }
2194
2195 Foo& getFooey() { return *f; }
2196};
2197
2198Foo& getBarFoo(Bar &bar, int c) { return bar.getFoo2(c); }
2199
2200void test() {
2201 Foo foo;
2202 Foo *fooArray;
2203 Bar bar;
2204 int a;
2205 int b;
2206 int c;
2207
2208 bar.getFoo().mu_.Lock();
2209 bar.getFoo().a = 0;
2210 bar.getFoo().mu_.Unlock();
2211
2212 (bar.getFoo().mu_).Lock(); // test parenthesis
2213 bar.getFoo().a = 0;
2214 (bar.getFoo().mu_).Unlock();
2215
2216 bar.getFoo2(a).mu_.Lock();
2217 bar.getFoo2(a).a = 0;
2218 bar.getFoo2(a).mu_.Unlock();
2219
2220 bar.getFoo3(a, b).mu_.Lock();
2221 bar.getFoo3(a, b).a = 0;
2222 bar.getFoo3(a, b).mu_.Unlock();
2223
2224 getBarFoo(bar, a).mu_.Lock();
2225 getBarFoo(bar, a).a = 0;
2226 getBarFoo(bar, a).mu_.Unlock();
2227
2228 bar.getFoo2(10).mu_.Lock();
2229 bar.getFoo2(10).a = 0;
2230 bar.getFoo2(10).mu_.Unlock();
2231
2232 bar.getFoo2(a + 1).mu_.Lock();
2233 bar.getFoo2(a + 1).a = 0;
2234 bar.getFoo2(a + 1).mu_.Unlock();
2235
2236 (a > 0 ? fooArray[1] : fooArray[b]).mu_.Lock();
2237 (a > 0 ? fooArray[1] : fooArray[b]).a = 0;
2238 (a > 0 ? fooArray[1] : fooArray[b]).mu_.Unlock();
2239
2240 bar.getFoo().mu_.Lock();
2241 bar.getFooey().a = 0; // \
DeLesley Hutchinsa74b7152012-08-10 20:19:55 +00002242 // expected-warning {{writing variable 'a' requires locking 'bar.getFooey().mu_' exclusively}}
DeLesley Hutchins0d95dfc2012-03-02 23:36:05 +00002243 bar.getFoo().mu_.Unlock();
2244
2245 bar.getFoo2(a).mu_.Lock();
2246 bar.getFoo2(b).a = 0; // \
DeLesley Hutchinsa74b7152012-08-10 20:19:55 +00002247 // expected-warning {{writing variable 'a' requires locking 'bar.getFoo2(b).mu_' exclusively}}
DeLesley Hutchins0d95dfc2012-03-02 23:36:05 +00002248 bar.getFoo2(a).mu_.Unlock();
2249
2250 bar.getFoo3(a, b).mu_.Lock();
2251 bar.getFoo3(a, c).a = 0; // \
DeLesley Hutchinsa74b7152012-08-10 20:19:55 +00002252 // expected-warning {{writing variable 'a' requires locking 'bar.getFoo3(a,c).mu_' exclusively}}
DeLesley Hutchins0d95dfc2012-03-02 23:36:05 +00002253 bar.getFoo3(a, b).mu_.Unlock();
2254
2255 getBarFoo(bar, a).mu_.Lock();
2256 getBarFoo(bar, b).a = 0; // \
DeLesley Hutchinsa74b7152012-08-10 20:19:55 +00002257 // expected-warning {{writing variable 'a' requires locking 'getBarFoo(bar,b).mu_' exclusively}}
DeLesley Hutchins0d95dfc2012-03-02 23:36:05 +00002258 getBarFoo(bar, a).mu_.Unlock();
2259
2260 (a > 0 ? fooArray[1] : fooArray[b]).mu_.Lock();
2261 (a > 0 ? fooArray[b] : fooArray[c]).a = 0; // \
DeLesley Hutchinsa74b7152012-08-10 20:19:55 +00002262 // expected-warning {{writing variable 'a' requires locking '((a#_)#_#fooArray[b]).mu_' exclusively}}
DeLesley Hutchins0d95dfc2012-03-02 23:36:05 +00002263 (a > 0 ? fooArray[1] : fooArray[b]).mu_.Unlock();
2264}
2265
2266
DeLesley Hutchins0da44142012-06-22 17:07:28 +00002267} // end namespace MoreLockExpressions
2268
2269
2270namespace TrylockJoinPoint {
2271
2272class Foo {
2273 Mutex mu;
2274 bool c;
2275
2276 void foo() {
2277 if (c) {
2278 if (!mu.TryLock())
2279 return;
2280 } else {
2281 mu.Lock();
2282 }
2283 mu.Unlock();
2284 }
2285};
2286
2287} // end namespace TrylockJoinPoint
DeLesley Hutchins0d95dfc2012-03-02 23:36:05 +00002288
2289
DeLesley Hutchinsf63797c2012-06-25 18:33:18 +00002290namespace LockReturned {
2291
2292class Foo {
2293public:
2294 int a GUARDED_BY(mu_);
2295 void foo() EXCLUSIVE_LOCKS_REQUIRED(mu_);
2296 void foo2(Foo* f) EXCLUSIVE_LOCKS_REQUIRED(mu_, f->mu_);
2297
2298 static void sfoo(Foo* f) EXCLUSIVE_LOCKS_REQUIRED(f->mu_);
2299
2300 Mutex* getMu() LOCK_RETURNED(mu_);
2301
2302 Mutex mu_;
2303
2304 static Mutex* getMu(Foo* f) LOCK_RETURNED(f->mu_);
2305};
2306
2307
2308// Calls getMu() directly to lock and unlock
2309void test1(Foo* f1, Foo* f2) {
DeLesley Hutchinsa74b7152012-08-10 20:19:55 +00002310 f1->a = 0; // expected-warning {{writing variable 'a' requires locking 'f1->mu_' exclusively}}
2311 f1->foo(); // expected-warning {{calling function 'foo' requires exclusive lock on 'f1->mu_'}}
DeLesley Hutchinsf63797c2012-06-25 18:33:18 +00002312
DeLesley Hutchinsa74b7152012-08-10 20:19:55 +00002313 f1->foo2(f2); // expected-warning {{calling function 'foo2' requires exclusive lock on 'f1->mu_'}} \
2314 // expected-warning {{calling function 'foo2' requires exclusive lock on 'f2->mu_'}}
2315 Foo::sfoo(f1); // expected-warning {{calling function 'sfoo' requires exclusive lock on 'f1->mu_'}}
DeLesley Hutchinsf63797c2012-06-25 18:33:18 +00002316
2317 f1->getMu()->Lock();
2318
2319 f1->a = 0;
2320 f1->foo();
DeLesley Hutchinsa74b7152012-08-10 20:19:55 +00002321 f1->foo2(f2); // expected-warning {{calling function 'foo2' requires exclusive lock on 'f2->mu_'}}
DeLesley Hutchinsf63797c2012-06-25 18:33:18 +00002322
2323 Foo::getMu(f2)->Lock();
2324 f1->foo2(f2);
2325 Foo::getMu(f2)->Unlock();
2326
2327 Foo::sfoo(f1);
2328
2329 f1->getMu()->Unlock();
2330}
2331
2332
2333Mutex* getFooMu(Foo* f) LOCK_RETURNED(Foo::getMu(f));
2334
2335class Bar : public Foo {
2336public:
2337 int b GUARDED_BY(getMu());
2338 void bar() EXCLUSIVE_LOCKS_REQUIRED(getMu());
2339 void bar2(Bar* g) EXCLUSIVE_LOCKS_REQUIRED(getMu(this), g->getMu());
2340
2341 static void sbar(Bar* g) EXCLUSIVE_LOCKS_REQUIRED(g->getMu());
2342 static void sbar2(Bar* g) EXCLUSIVE_LOCKS_REQUIRED(getFooMu(g));
2343};
2344
2345
2346
2347// Use getMu() within other attributes.
2348// This requires at lest levels of substitution, more in the case of
2349void test2(Bar* b1, Bar* b2) {
DeLesley Hutchinsa74b7152012-08-10 20:19:55 +00002350 b1->b = 0; // expected-warning {{writing variable 'b' requires locking 'b1->mu_' exclusively}}
2351 b1->bar(); // expected-warning {{calling function 'bar' requires exclusive lock on 'b1->mu_'}}
2352 b1->bar2(b2); // expected-warning {{calling function 'bar2' requires exclusive lock on 'b1->mu_'}} \
2353 // expected-warning {{calling function 'bar2' requires exclusive lock on 'b2->mu_'}}
2354 Bar::sbar(b1); // expected-warning {{calling function 'sbar' requires exclusive lock on 'b1->mu_'}}
2355 Bar::sbar2(b1); // expected-warning {{calling function 'sbar2' requires exclusive lock on 'b1->mu_'}}
DeLesley Hutchinsf63797c2012-06-25 18:33:18 +00002356
2357 b1->getMu()->Lock();
2358
2359 b1->b = 0;
2360 b1->bar();
DeLesley Hutchinsa74b7152012-08-10 20:19:55 +00002361 b1->bar2(b2); // expected-warning {{calling function 'bar2' requires exclusive lock on 'b2->mu_'}}
DeLesley Hutchinsf63797c2012-06-25 18:33:18 +00002362
2363 b2->getMu()->Lock();
2364 b1->bar2(b2);
2365
2366 b2->getMu()->Unlock();
2367
2368 Bar::sbar(b1);
2369 Bar::sbar2(b1);
2370
2371 b1->getMu()->Unlock();
2372}
2373
2374
2375// Sanity check -- lock the mutex directly, but use attributes that call getMu()
2376// Also lock the mutex using getFooMu, which calls a lock_returned function.
2377void test3(Bar* b1, Bar* b2) {
2378 b1->mu_.Lock();
2379 b1->b = 0;
2380 b1->bar();
2381
2382 getFooMu(b2)->Lock();
2383 b1->bar2(b2);
2384 getFooMu(b2)->Unlock();
2385
2386 Bar::sbar(b1);
2387 Bar::sbar2(b1);
2388
2389 b1->mu_.Unlock();
2390}
2391
2392} // end namespace LockReturned
2393
2394
DeLesley Hutchinsc99a5d82012-06-28 22:42:48 +00002395namespace ReleasableScopedLock {
2396
2397class Foo {
2398 Mutex mu_;
2399 bool c;
2400 int a GUARDED_BY(mu_);
2401
2402 void test1();
2403 void test2();
2404 void test3();
DeLesley Hutchins5381c052012-07-05 21:16:29 +00002405 void test4();
2406 void test5();
DeLesley Hutchinsc99a5d82012-06-28 22:42:48 +00002407};
2408
2409
2410void Foo::test1() {
2411 ReleasableMutexLock rlock(&mu_);
2412 rlock.Release();
2413}
2414
2415void Foo::test2() {
2416 ReleasableMutexLock rlock(&mu_);
2417 if (c) { // test join point -- held/not held during release
2418 rlock.Release();
2419 }
2420}
2421
2422void Foo::test3() {
2423 ReleasableMutexLock rlock(&mu_);
2424 a = 0;
2425 rlock.Release();
2426 a = 1; // expected-warning {{writing variable 'a' requires locking 'mu_' exclusively}}
2427}
2428
DeLesley Hutchins5381c052012-07-05 21:16:29 +00002429void Foo::test4() {
2430 ReleasableMutexLock rlock(&mu_);
2431 rlock.Release();
2432 rlock.Release(); // expected-warning {{unlocking 'mu_' that was not locked}}
2433}
2434
2435void Foo::test5() {
2436 ReleasableMutexLock rlock(&mu_);
2437 if (c) {
2438 rlock.Release();
2439 }
2440 // no warning on join point for managed lock.
2441 rlock.Release(); // expected-warning {{unlocking 'mu_' that was not locked}}
2442}
2443
2444
DeLesley Hutchinsc99a5d82012-06-28 22:42:48 +00002445} // end namespace ReleasableScopedLock
2446
2447
DeLesley Hutchins76f0a6e2012-07-02 21:59:24 +00002448namespace TrylockFunctionTest {
2449
2450class Foo {
2451public:
2452 Mutex mu1_;
2453 Mutex mu2_;
2454 bool c;
2455
2456 bool lockBoth() EXCLUSIVE_TRYLOCK_FUNCTION(true, mu1_, mu2_);
2457};
2458
2459bool Foo::lockBoth() {
2460 if (!mu1_.TryLock())
2461 return false;
2462
2463 mu2_.Lock();
2464 if (!c) {
2465 mu1_.Unlock();
2466 mu2_.Unlock();
2467 return false;
2468 }
2469
2470 return true;
2471}
2472
2473
2474} // end namespace TrylockFunctionTest
DeLesley Hutchinsc99a5d82012-06-28 22:42:48 +00002475
2476
2477
DeLesley Hutchinsc36eda12012-07-02 22:12:12 +00002478namespace DoubleLockBug {
2479
2480class Foo {
2481public:
2482 Mutex mu_;
2483 int a GUARDED_BY(mu_);
2484
DeLesley Hutchins5381c052012-07-05 21:16:29 +00002485 void foo1() EXCLUSIVE_LOCKS_REQUIRED(mu_);
2486 int foo2() SHARED_LOCKS_REQUIRED(mu_);
DeLesley Hutchinsc36eda12012-07-02 22:12:12 +00002487};
2488
2489
DeLesley Hutchins5381c052012-07-05 21:16:29 +00002490void Foo::foo1() EXCLUSIVE_LOCKS_REQUIRED(mu_) {
DeLesley Hutchinsc36eda12012-07-02 22:12:12 +00002491 a = 0;
2492}
2493
DeLesley Hutchins5381c052012-07-05 21:16:29 +00002494int Foo::foo2() SHARED_LOCKS_REQUIRED(mu_) {
2495 return a;
2496}
2497
2498}
2499
DeLesley Hutchinsc36eda12012-07-02 22:12:12 +00002500
2501
DeLesley Hutchins879a4332012-07-02 22:16:54 +00002502namespace UnlockBug {
DeLesley Hutchinsc36eda12012-07-02 22:12:12 +00002503
DeLesley Hutchins879a4332012-07-02 22:16:54 +00002504class Foo {
2505public:
2506 Mutex mutex_;
2507
2508 void foo1() EXCLUSIVE_LOCKS_REQUIRED(mutex_) { // expected-note {{mutex acquired here}}
2509 mutex_.Unlock();
2510 } // expected-warning {{expecting mutex 'mutex_' to be locked at the end of function}}
2511
2512
2513 void foo2() SHARED_LOCKS_REQUIRED(mutex_) { // expected-note {{mutex acquired here}}
2514 mutex_.Unlock();
2515 } // expected-warning {{expecting mutex 'mutex_' to be locked at the end of function}}
2516};
2517
2518} // end namespace UnlockBug
DeLesley Hutchinsc36eda12012-07-02 22:12:12 +00002519
DeLesley Hutchinsc99a5d82012-06-28 22:42:48 +00002520
DeLesley Hutchins5381c052012-07-05 21:16:29 +00002521
DeLesley Hutchinsbbe33412012-07-02 22:26:29 +00002522namespace FoolishScopedLockableBug {
2523
2524class SCOPED_LOCKABLE WTF_ScopedLockable {
2525public:
2526 WTF_ScopedLockable(Mutex* mu) EXCLUSIVE_LOCK_FUNCTION(mu);
2527
2528 // have to call release() manually;
2529 ~WTF_ScopedLockable();
2530
2531 void release() UNLOCK_FUNCTION();
2532};
2533
2534
2535class Foo {
2536 Mutex mu_;
2537 int a GUARDED_BY(mu_);
2538 bool c;
2539
2540 void doSomething();
2541
2542 void test1() {
2543 WTF_ScopedLockable wtf(&mu_);
2544 wtf.release();
2545 }
2546
2547 void test2() {
2548 WTF_ScopedLockable wtf(&mu_); // expected-note {{mutex acquired here}}
2549 } // expected-warning {{mutex 'mu_' is still locked at the end of function}}
2550
2551 void test3() {
2552 if (c) {
2553 WTF_ScopedLockable wtf(&mu_);
2554 wtf.release();
2555 }
2556 }
2557
2558 void test4() {
2559 if (c) {
2560 doSomething();
2561 }
2562 else {
2563 WTF_ScopedLockable wtf(&mu_);
2564 wtf.release();
2565 }
2566 }
2567
2568 void test5() {
2569 if (c) {
2570 WTF_ScopedLockable wtf(&mu_); // expected-note {{mutex acquired here}}
2571 }
2572 } // expected-warning {{mutex 'mu_' is not locked on every path through here}}
2573
2574 void test6() {
2575 if (c) {
2576 doSomething();
2577 }
2578 else {
2579 WTF_ScopedLockable wtf(&mu_); // expected-note {{mutex acquired here}}
2580 }
2581 } // expected-warning {{mutex 'mu_' is not locked on every path through here}}
2582};
2583
2584
2585} // end namespace FoolishScopedLockableBug
2586
DeLesley Hutchins9d6e7f32012-07-03 18:25:56 +00002587
DeLesley Hutchins5381c052012-07-05 21:16:29 +00002588
DeLesley Hutchins9d6e7f32012-07-03 18:25:56 +00002589namespace TemporaryCleanupExpr {
2590
2591class Foo {
2592 int a GUARDED_BY(getMutexPtr().get());
2593
2594 SmartPtr<Mutex> getMutexPtr();
2595
2596 void test();
2597};
2598
2599
2600void Foo::test() {
2601 {
2602 ReaderMutexLock lock(getMutexPtr().get());
2603 int b = a;
DeLesley Hutchins96fac6a2012-07-03 19:47:18 +00002604 }
DeLesley Hutchinsa74b7152012-08-10 20:19:55 +00002605 int b = a; // expected-warning {{reading variable 'a' requires locking 'getMutexPtr()'}}
DeLesley Hutchins9d6e7f32012-07-03 18:25:56 +00002606}
2607
2608} // end namespace TemporaryCleanupExpr
2609
2610
DeLesley Hutchins96fac6a2012-07-03 19:47:18 +00002611
2612namespace SmartPointerTests {
2613
2614class Foo {
2615public:
2616 SmartPtr<Mutex> mu_;
2617 int a GUARDED_BY(mu_);
2618 int b GUARDED_BY(mu_.get());
2619 int c GUARDED_BY(*mu_);
2620
2621 void Lock() EXCLUSIVE_LOCK_FUNCTION(mu_);
2622 void Unlock() UNLOCK_FUNCTION(mu_);
2623
2624 void test0();
2625 void test1();
2626 void test2();
2627 void test3();
2628 void test4();
2629 void test5();
2630 void test6();
2631 void test7();
2632 void test8();
2633};
2634
2635void Foo::test0() {
2636 a = 0; // expected-warning {{writing variable 'a' requires locking 'mu_' exclusively}}
2637 b = 0; // expected-warning {{writing variable 'b' requires locking 'mu_' exclusively}}
2638 c = 0; // expected-warning {{writing variable 'c' requires locking 'mu_' exclusively}}
2639}
2640
2641void Foo::test1() {
2642 mu_->Lock();
2643 a = 0;
2644 b = 0;
2645 c = 0;
2646 mu_->Unlock();
2647}
2648
2649void Foo::test2() {
2650 (*mu_).Lock();
2651 a = 0;
2652 b = 0;
2653 c = 0;
2654 (*mu_).Unlock();
2655}
2656
2657
2658void Foo::test3() {
2659 mu_.get()->Lock();
2660 a = 0;
2661 b = 0;
2662 c = 0;
2663 mu_.get()->Unlock();
2664}
2665
2666
2667void Foo::test4() {
2668 MutexLock lock(mu_.get());
2669 a = 0;
2670 b = 0;
2671 c = 0;
2672}
2673
2674
2675void Foo::test5() {
2676 MutexLock lock(&(*mu_));
2677 a = 0;
2678 b = 0;
2679 c = 0;
2680}
2681
2682
2683void Foo::test6() {
2684 Lock();
2685 a = 0;
2686 b = 0;
2687 c = 0;
2688 Unlock();
2689}
2690
2691
2692void Foo::test7() {
2693 {
2694 Lock();
2695 mu_->Unlock();
2696 }
2697 {
2698 mu_->Lock();
2699 Unlock();
2700 }
2701 {
2702 mu_.get()->Lock();
2703 mu_->Unlock();
2704 }
2705 {
2706 mu_->Lock();
2707 mu_.get()->Unlock();
2708 }
2709 {
2710 mu_.get()->Lock();
2711 (*mu_).Unlock();
2712 }
2713 {
2714 (*mu_).Lock();
2715 mu_->Unlock();
2716 }
2717}
2718
2719
2720void Foo::test8() {
2721 mu_->Lock();
2722 mu_.get()->Lock(); // expected-warning {{locking 'mu_' that is already locked}}
2723 (*mu_).Lock(); // expected-warning {{locking 'mu_' that is already locked}}
2724 mu_.get()->Unlock();
2725 Unlock(); // expected-warning {{unlocking 'mu_' that was not locked}}
2726}
2727
2728
2729class Bar {
2730 SmartPtr<Foo> foo;
2731
2732 void test0();
2733 void test1();
2734 void test2();
2735 void test3();
2736};
2737
2738
2739void Bar::test0() {
DeLesley Hutchinsa74b7152012-08-10 20:19:55 +00002740 foo->a = 0; // expected-warning {{writing variable 'a' requires locking 'foo->mu_' exclusively}}
2741 (*foo).b = 0; // expected-warning {{writing variable 'b' requires locking 'foo->mu_' exclusively}}
2742 foo.get()->c = 0; // expected-warning {{writing variable 'c' requires locking 'foo->mu_' exclusively}}
DeLesley Hutchins96fac6a2012-07-03 19:47:18 +00002743}
2744
2745
2746void Bar::test1() {
2747 foo->mu_->Lock();
2748 foo->a = 0;
2749 (*foo).b = 0;
2750 foo.get()->c = 0;
2751 foo->mu_->Unlock();
2752}
2753
2754
2755void Bar::test2() {
2756 (*foo).mu_->Lock();
2757 foo->a = 0;
2758 (*foo).b = 0;
2759 foo.get()->c = 0;
2760 foo.get()->mu_->Unlock();
2761}
2762
2763
2764void Bar::test3() {
2765 MutexLock lock(foo->mu_.get());
2766 foo->a = 0;
2767 (*foo).b = 0;
2768 foo.get()->c = 0;
2769}
2770
2771} // end namespace SmartPointerTests
2772
2773
2774
DeLesley Hutchins5381c052012-07-05 21:16:29 +00002775namespace DuplicateAttributeTest {
2776
2777class LOCKABLE Foo {
2778public:
2779 Mutex mu1_;
2780 Mutex mu2_;
2781 Mutex mu3_;
2782 int a GUARDED_BY(mu1_);
2783 int b GUARDED_BY(mu2_);
2784 int c GUARDED_BY(mu3_);
2785
2786 void lock() EXCLUSIVE_LOCK_FUNCTION();
2787 void unlock() UNLOCK_FUNCTION();
2788
2789 void lock1() EXCLUSIVE_LOCK_FUNCTION(mu1_);
2790 void slock1() SHARED_LOCK_FUNCTION(mu1_);
2791 void lock3() EXCLUSIVE_LOCK_FUNCTION(mu1_, mu2_, mu3_);
2792 void locklots()
2793 EXCLUSIVE_LOCK_FUNCTION(mu1_)
2794 EXCLUSIVE_LOCK_FUNCTION(mu2_)
2795 EXCLUSIVE_LOCK_FUNCTION(mu1_, mu2_, mu3_);
2796
2797 void unlock1() UNLOCK_FUNCTION(mu1_);
2798 void unlock3() UNLOCK_FUNCTION(mu1_, mu2_, mu3_);
2799 void unlocklots()
2800 UNLOCK_FUNCTION(mu1_)
2801 UNLOCK_FUNCTION(mu2_)
2802 UNLOCK_FUNCTION(mu1_, mu2_, mu3_);
2803};
2804
2805
2806void Foo::lock() EXCLUSIVE_LOCK_FUNCTION() { }
2807void Foo::unlock() UNLOCK_FUNCTION() { }
2808
2809void Foo::lock1() EXCLUSIVE_LOCK_FUNCTION(mu1_) {
2810 mu1_.Lock();
2811}
2812
2813void Foo::slock1() SHARED_LOCK_FUNCTION(mu1_) {
2814 mu1_.Lock();
2815}
2816
2817void Foo::lock3() EXCLUSIVE_LOCK_FUNCTION(mu1_, mu2_, mu3_) {
2818 mu1_.Lock();
2819 mu2_.Lock();
2820 mu3_.Lock();
2821}
2822
2823void Foo::locklots()
2824 EXCLUSIVE_LOCK_FUNCTION(mu1_, mu2_)
2825 EXCLUSIVE_LOCK_FUNCTION(mu2_, mu3_) {
2826 mu1_.Lock();
2827 mu2_.Lock();
2828 mu3_.Lock();
2829}
2830
2831void Foo::unlock1() UNLOCK_FUNCTION(mu1_) {
2832 mu1_.Unlock();
2833}
2834
2835void Foo::unlock3() UNLOCK_FUNCTION(mu1_, mu2_, mu3_) {
2836 mu1_.Unlock();
2837 mu2_.Unlock();
2838 mu3_.Unlock();
2839}
2840
2841void Foo::unlocklots()
2842 UNLOCK_FUNCTION(mu1_, mu2_)
2843 UNLOCK_FUNCTION(mu2_, mu3_) {
2844 mu1_.Unlock();
2845 mu2_.Unlock();
2846 mu3_.Unlock();
2847}
2848
2849
2850void test0() {
2851 Foo foo;
2852 foo.lock();
2853 foo.unlock();
2854
2855 foo.lock();
2856 foo.lock(); // expected-warning {{locking 'foo' that is already locked}}
2857 foo.unlock();
2858 foo.unlock(); // expected-warning {{unlocking 'foo' that was not locked}}
2859}
2860
2861
2862void test1() {
2863 Foo foo;
2864 foo.lock1();
2865 foo.a = 0;
2866 foo.unlock1();
2867
2868 foo.lock1();
DeLesley Hutchinsa74b7152012-08-10 20:19:55 +00002869 foo.lock1(); // expected-warning {{locking 'foo.mu1_' that is already locked}}
DeLesley Hutchins5381c052012-07-05 21:16:29 +00002870 foo.a = 0;
2871 foo.unlock1();
DeLesley Hutchinsa74b7152012-08-10 20:19:55 +00002872 foo.unlock1(); // expected-warning {{unlocking 'foo.mu1_' that was not locked}}
DeLesley Hutchins5381c052012-07-05 21:16:29 +00002873}
2874
2875
2876int test2() {
2877 Foo foo;
2878 foo.slock1();
2879 int d1 = foo.a;
2880 foo.unlock1();
2881
2882 foo.slock1();
DeLesley Hutchinsa74b7152012-08-10 20:19:55 +00002883 foo.slock1(); // expected-warning {{locking 'foo.mu1_' that is already locked}}
DeLesley Hutchins5381c052012-07-05 21:16:29 +00002884 int d2 = foo.a;
2885 foo.unlock1();
DeLesley Hutchinsa74b7152012-08-10 20:19:55 +00002886 foo.unlock1(); // expected-warning {{unlocking 'foo.mu1_' that was not locked}}
DeLesley Hutchins5381c052012-07-05 21:16:29 +00002887 return d1 + d2;
2888}
2889
2890
2891void test3() {
2892 Foo foo;
2893 foo.lock3();
2894 foo.a = 0;
2895 foo.b = 0;
2896 foo.c = 0;
2897 foo.unlock3();
2898
2899 foo.lock3();
2900 foo.lock3(); // \
DeLesley Hutchinsa74b7152012-08-10 20:19:55 +00002901 // expected-warning {{locking 'foo.mu1_' that is already locked}} \
2902 // expected-warning {{locking 'foo.mu2_' that is already locked}} \
2903 // expected-warning {{locking 'foo.mu3_' that is already locked}}
DeLesley Hutchins5381c052012-07-05 21:16:29 +00002904 foo.a = 0;
2905 foo.b = 0;
2906 foo.c = 0;
2907 foo.unlock3();
2908 foo.unlock3(); // \
DeLesley Hutchinsa74b7152012-08-10 20:19:55 +00002909 // expected-warning {{unlocking 'foo.mu1_' that was not locked}} \
2910 // expected-warning {{unlocking 'foo.mu2_' that was not locked}} \
2911 // expected-warning {{unlocking 'foo.mu3_' that was not locked}}
DeLesley Hutchins5381c052012-07-05 21:16:29 +00002912}
2913
2914
2915void testlots() {
2916 Foo foo;
2917 foo.locklots();
2918 foo.a = 0;
2919 foo.b = 0;
2920 foo.c = 0;
2921 foo.unlocklots();
2922
2923 foo.locklots();
2924 foo.locklots(); // \
DeLesley Hutchinsa74b7152012-08-10 20:19:55 +00002925 // expected-warning {{locking 'foo.mu1_' that is already locked}} \
2926 // expected-warning {{locking 'foo.mu2_' that is already locked}} \
2927 // expected-warning {{locking 'foo.mu3_' that is already locked}}
DeLesley Hutchins5381c052012-07-05 21:16:29 +00002928 foo.a = 0;
2929 foo.b = 0;
2930 foo.c = 0;
2931 foo.unlocklots();
2932 foo.unlocklots(); // \
DeLesley Hutchinsa74b7152012-08-10 20:19:55 +00002933 // expected-warning {{unlocking 'foo.mu1_' that was not locked}} \
2934 // expected-warning {{unlocking 'foo.mu2_' that was not locked}} \
2935 // expected-warning {{unlocking 'foo.mu3_' that was not locked}}
DeLesley Hutchins5381c052012-07-05 21:16:29 +00002936}
2937
2938} // end namespace DuplicateAttributeTest
2939
2940
2941
DeLesley Hutchins13106112012-07-10 21:47:55 +00002942namespace TryLockEqTest {
2943
2944class Foo {
2945 Mutex mu_;
2946 int a GUARDED_BY(mu_);
2947 bool c;
2948
2949 int tryLockMutexI() EXCLUSIVE_TRYLOCK_FUNCTION(1, mu_);
2950 Mutex* tryLockMutexP() EXCLUSIVE_TRYLOCK_FUNCTION(1, mu_);
2951 void unlock() UNLOCK_FUNCTION(mu_);
2952
2953 void test1();
2954 void test2();
2955};
2956
2957
2958void Foo::test1() {
2959 if (tryLockMutexP() == 0) {
2960 a = 0; // expected-warning {{writing variable 'a' requires locking 'mu_' exclusively}}
2961 return;
2962 }
2963 a = 0;
2964 unlock();
2965
2966 if (tryLockMutexP() != 0) {
2967 a = 0;
2968 unlock();
2969 }
2970
2971 if (0 != tryLockMutexP()) {
2972 a = 0;
2973 unlock();
2974 }
2975
2976 if (!(tryLockMutexP() == 0)) {
2977 a = 0;
2978 unlock();
2979 }
2980
2981 if (tryLockMutexI() == 0) {
2982 a = 0; // expected-warning {{writing variable 'a' requires locking 'mu_' exclusively}}
2983 return;
2984 }
2985 a = 0;
2986 unlock();
2987
2988 if (0 == tryLockMutexI()) {
2989 a = 0; // expected-warning {{writing variable 'a' requires locking 'mu_' exclusively}}
2990 return;
2991 }
2992 a = 0;
2993 unlock();
2994
2995 if (tryLockMutexI() == 1) {
2996 a = 0;
2997 unlock();
2998 }
2999
3000 if (mu_.TryLock() == false) {
3001 a = 0; // expected-warning {{writing variable 'a' requires locking 'mu_' exclusively}}
3002 return;
3003 }
3004 a = 0;
3005 unlock();
3006
3007 if (mu_.TryLock() == true) {
3008 a = 0;
3009 unlock();
3010 }
3011 else {
3012 a = 0; // expected-warning {{writing variable 'a' requires locking 'mu_' exclusively}}
3013 }
3014
3015#if __has_feature(cxx_nullptr)
3016 if (tryLockMutexP() == nullptr) {
3017 a = 0; // expected-warning {{writing variable 'a' requires locking 'mu_' exclusively}}
3018 return;
3019 }
3020 a = 0;
3021 unlock();
3022#endif
3023}
3024
3025
3026void Foo::test2() {
3027/* FIXME: these tests depend on changes to the CFG.
3028 *
3029 if (mu_.TryLock() && c) {
3030 a = 0;
3031 unlock();
3032 }
3033 else return;
3034
3035 if (c && mu_.TryLock()) {
3036 a = 0;
3037 unlock();
3038 }
3039 else return;
3040
3041 if (!(mu_.TryLock() && c))
3042 return;
3043 a = 0;
3044 unlock();
3045
3046 if (!(c && mu_.TryLock()))
3047 return;
3048 a = 0;
3049 unlock();
3050
3051 if (!(mu_.TryLock() == 0) && c) {
3052 a = 0;
3053 unlock();
3054 }
3055
3056 if (!mu_.TryLock() || c)
3057 return;
3058 a = 0;
3059 unlock();
3060*/
3061}
3062
DeLesley Hutchins13106112012-07-10 21:47:55 +00003063} // end namespace TryLockEqTest
DeLesley Hutchins5381c052012-07-05 21:16:29 +00003064
DeLesley Hutchins96fac6a2012-07-03 19:47:18 +00003065
DeLesley Hutchinsee2f0322012-08-10 20:29:46 +00003066namespace ExistentialPatternMatching {
3067
3068class Graph {
3069public:
3070 Mutex mu_;
3071};
3072
3073void LockAllGraphs() EXCLUSIVE_LOCK_FUNCTION(&Graph::mu_);
3074void UnlockAllGraphs() UNLOCK_FUNCTION(&Graph::mu_);
3075
3076class Node {
3077public:
3078 int a GUARDED_BY(&Graph::mu_);
3079
3080 void foo() EXCLUSIVE_LOCKS_REQUIRED(&Graph::mu_) {
3081 a = 0;
3082 }
3083 void foo2() LOCKS_EXCLUDED(&Graph::mu_);
3084};
3085
3086void test() {
3087 Graph g1;
3088 Graph g2;
3089 Node n1;
3090
3091 n1.a = 0; // expected-warning {{writing variable 'a' requires locking '&ExistentialPatternMatching::Graph::mu_' exclusively}}
3092 n1.foo(); // expected-warning {{calling function 'foo' requires exclusive lock on '&ExistentialPatternMatching::Graph::mu_'}}
3093 n1.foo2();
3094
3095 g1.mu_.Lock();
3096 n1.a = 0;
3097 n1.foo();
3098 n1.foo2(); // expected-warning {{cannot call function 'foo2' while mutex '&ExistentialPatternMatching::Graph::mu_' is locked}}
3099 g1.mu_.Unlock();
3100
3101 g2.mu_.Lock();
3102 n1.a = 0;
3103 n1.foo();
3104 n1.foo2(); // expected-warning {{cannot call function 'foo2' while mutex '&ExistentialPatternMatching::Graph::mu_' is locked}}
3105 g2.mu_.Unlock();
3106
3107 LockAllGraphs();
3108 n1.a = 0;
3109 n1.foo();
3110 n1.foo2(); // expected-warning {{cannot call function 'foo2' while mutex '&ExistentialPatternMatching::Graph::mu_' is locked}}
3111 UnlockAllGraphs();
3112
3113 LockAllGraphs();
3114 g1.mu_.Unlock();
3115
3116 LockAllGraphs();
3117 g2.mu_.Unlock();
3118
3119 LockAllGraphs();
3120 g1.mu_.Lock(); // expected-warning {{locking 'g1.mu_' that is already locked}}
3121 g1.mu_.Unlock();
3122}
3123
3124} // end namespace ExistentialPatternMatching
3125
DeLesley Hutchins4e4c1572012-08-31 21:57:32 +00003126
3127namespace StringIgnoreTest {
3128
3129class Foo {
3130public:
3131 Mutex mu_;
3132 void lock() EXCLUSIVE_LOCK_FUNCTION("");
3133 void unlock() UNLOCK_FUNCTION("");
3134 void goober() EXCLUSIVE_LOCKS_REQUIRED("");
3135 void roober() SHARED_LOCKS_REQUIRED("");
3136};
3137
3138
3139class Bar : public Foo {
3140public:
3141 void bar(Foo* f) {
3142 f->unlock();
3143 f->goober();
3144 f->roober();
3145 f->lock();
3146 };
3147};
3148
3149} // end namespace StringIgnoreTest
3150
3151
DeLesley Hutchins54081532012-08-31 22:09:53 +00003152namespace LockReturnedScopeFix {
3153
3154class Base {
3155protected:
3156 struct Inner;
3157 bool c;
3158
3159 const Mutex& getLock(const Inner* i);
3160
3161 void lockInner (Inner* i) EXCLUSIVE_LOCK_FUNCTION(getLock(i));
3162 void unlockInner(Inner* i) UNLOCK_FUNCTION(getLock(i));
3163 void foo(Inner* i) EXCLUSIVE_LOCKS_REQUIRED(getLock(i));
3164
3165 void bar(Inner* i);
3166};
3167
3168
3169struct Base::Inner {
3170 Mutex lock_;
3171 void doSomething() EXCLUSIVE_LOCKS_REQUIRED(lock_);
3172};
3173
3174
3175const Mutex& Base::getLock(const Inner* i) LOCK_RETURNED(i->lock_) {
3176 return i->lock_;
3177}
3178
3179
3180void Base::foo(Inner* i) {
3181 i->doSomething();
3182}
3183
3184void Base::bar(Inner* i) {
3185 if (c) {
3186 i->lock_.Lock();
3187 unlockInner(i);
3188 }
3189 else {
3190 lockInner(i);
3191 i->lock_.Unlock();
3192 }
3193}
3194
3195} // end namespace LockReturnedScopeFix
3196
DeLesley Hutchinsfd0f11c2012-09-05 20:01:16 +00003197
3198namespace TrylockWithCleanups {
3199
3200class MyString {
3201public:
3202 MyString(const char* s);
3203 ~MyString();
3204};
3205
3206struct Foo {
3207 Mutex mu_;
3208 int a GUARDED_BY(mu_);
3209};
3210
3211Foo* GetAndLockFoo(const MyString& s)
3212 EXCLUSIVE_TRYLOCK_FUNCTION(true, &Foo::mu_);
3213
3214static void test() {
3215 Foo* lt = GetAndLockFoo("foo");
3216 if (!lt) return;
3217 int a = lt->a;
3218 lt->mu_.Unlock();
3219}
3220
3221}
3222
3223
DeLesley Hutchins0b4db3e2012-09-07 17:34:53 +00003224namespace UniversalLock {
3225
3226class Foo {
3227 Mutex mu_;
3228 bool c;
3229
3230 int a GUARDED_BY(mu_);
3231 void r_foo() SHARED_LOCKS_REQUIRED(mu_);
3232 void w_foo() EXCLUSIVE_LOCKS_REQUIRED(mu_);
3233
3234 void test1() {
3235 int b;
3236
3237 beginNoWarnOnReads();
3238 b = a;
3239 r_foo();
3240 endNoWarnOnReads();
3241
3242 beginNoWarnOnWrites();
3243 a = 0;
3244 w_foo();
3245 endNoWarnOnWrites();
3246 }
3247
3248 // don't warn on joins with universal lock
3249 void test2() {
3250 if (c) {
3251 beginNoWarnOnWrites();
3252 }
3253 a = 0; // \
3254 // expected-warning {{writing variable 'a' requires locking 'mu_' exclusively}}
3255 endNoWarnOnWrites(); // \
3256 // expected-warning {{unlocking '*' that was not locked}}
3257 }
3258
3259
3260 // make sure the universal lock joins properly
3261 void test3() {
3262 if (c) {
3263 mu_.Lock();
3264 beginNoWarnOnWrites();
3265 }
3266 else {
3267 beginNoWarnOnWrites();
3268 mu_.Lock();
3269 }
3270 a = 0;
3271 endNoWarnOnWrites();
3272 mu_.Unlock();
3273 }
3274
3275
3276 // combine universal lock with other locks
3277 void test4() {
3278 beginNoWarnOnWrites();
3279 mu_.Lock();
3280 mu_.Unlock();
3281 endNoWarnOnWrites();
3282
3283 mu_.Lock();
3284 beginNoWarnOnWrites();
3285 endNoWarnOnWrites();
3286 mu_.Unlock();
3287
3288 mu_.Lock();
3289 beginNoWarnOnWrites();
3290 mu_.Unlock();
3291 endNoWarnOnWrites();
3292 }
3293};
3294
3295}