blob: 4e8893d3ca64de75d767cf1d41753cbb791c9ca3 [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 Hutchins3f0ec522012-09-10 19:58:23 +0000536 // expected-warning{{writing variable 'a' requires locking 'fooB.mu' exclusively}} \
537 // expected-note{{found near match 'fooA.mu'}}
Caitlin Sadowski99107eb2011-09-09 16:21:55 +0000538 fooA.mu.Unlock();
539}
540
541void late_bad_1() {
542 Mutex mu;
543 mu.Lock();
544 b1.mu1_.Lock();
545 int res = b1.a_ + b3->b_;
546 b3->b_ = *b1.q; // \
DeLesley Hutchinsa74b7152012-08-10 20:19:55 +0000547 // expected-warning{{reading the value pointed to by 'q' requires locking 'b1.mu'}}
Caitlin Sadowski99107eb2011-09-09 16:21:55 +0000548 b1.mu1_.Unlock();
549 b1.b_ = res;
550 mu.Unlock();
551}
552
553void late_bad_2() {
554 LateBar BarA;
555 BarA.FooPointer->mu.Lock();
556 BarA.Foo.a = 2; // \
DeLesley Hutchins3f0ec522012-09-10 19:58:23 +0000557 // expected-warning{{writing variable 'a' requires locking 'BarA.Foo.mu' exclusively}} \
558 // expected-note{{found near match 'BarA.FooPointer->mu'}}
Caitlin Sadowski99107eb2011-09-09 16:21:55 +0000559 BarA.FooPointer->mu.Unlock();
560}
561
562void late_bad_3() {
563 LateBar BarA;
564 BarA.Foo.mu.Lock();
565 BarA.FooPointer->a = 2; // \
DeLesley Hutchins3f0ec522012-09-10 19:58:23 +0000566 // expected-warning{{writing variable 'a' requires locking 'BarA.FooPointer->mu' exclusively}} \
567 // expected-note{{found near match 'BarA.Foo.mu'}}
Caitlin Sadowski99107eb2011-09-09 16:21:55 +0000568 BarA.Foo.mu.Unlock();
569}
570
571void late_bad_4() {
572 LateBar BarA;
573 BarA.Foo.mu.Lock();
574 BarA.Foo2.a = 2; // \
DeLesley Hutchins3f0ec522012-09-10 19:58:23 +0000575 // expected-warning{{writing variable 'a' requires locking 'BarA.Foo2.mu' exclusively}} \
576 // expected-note{{found near match 'BarA.Foo.mu'}}
Caitlin Sadowski99107eb2011-09-09 16:21:55 +0000577 BarA.Foo.mu.Unlock();
578}
579
Caitlin Sadowskia53257c2011-09-08 18:19:38 +0000580//-----------------------------------------------//
581// Extra warnings for shared vs. exclusive locks
582// ----------------------------------------------//
583
584void shared_fun_0() {
585 sls_mu.Lock();
586 do {
587 sls_mu.Unlock();
588 sls_mu.Lock();
589 } while (getBool());
590 sls_mu.Unlock();
591}
592
593void shared_fun_1() {
Caitlin Sadowski4e4bc752011-09-15 17:25:19 +0000594 sls_mu.ReaderLock(); // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000595 // expected-warning {{mutex 'sls_mu' is locked exclusively and shared in the same scope}}
Caitlin Sadowskia53257c2011-09-08 18:19:38 +0000596 do {
597 sls_mu.Unlock();
Caitlin Sadowski4e4bc752011-09-15 17:25:19 +0000598 sls_mu.Lock(); // \
599 // expected-note {{the other lock of mutex 'sls_mu' is here}}
Caitlin Sadowskia53257c2011-09-08 18:19:38 +0000600 } while (getBool());
601 sls_mu.Unlock();
602}
603
604void shared_fun_3() {
605 if (getBool())
606 sls_mu.Lock();
607 else
608 sls_mu.Lock();
609 *pgb_var = 1;
610 sls_mu.Unlock();
611}
612
613void shared_fun_4() {
614 if (getBool())
615 sls_mu.ReaderLock();
616 else
617 sls_mu.ReaderLock();
618 int x = sls_guardby_var;
619 sls_mu.Unlock();
620}
621
622void shared_fun_8() {
623 if (getBool())
624 sls_mu.Lock(); // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000625 // expected-warning {{mutex 'sls_mu' is locked exclusively and shared in the same scope}}
Caitlin Sadowskia53257c2011-09-08 18:19:38 +0000626 else
627 sls_mu.ReaderLock(); // \
Caitlin Sadowski8bccabe2011-09-08 21:52:50 +0000628 // expected-note {{the other lock of mutex 'sls_mu' is here}}
Caitlin Sadowskia53257c2011-09-08 18:19:38 +0000629 sls_mu.Unlock();
630}
631
632void shared_bad_0() {
Caitlin Sadowski4e4bc752011-09-15 17:25:19 +0000633 sls_mu.Lock(); // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000634 // expected-warning {{mutex 'sls_mu' is locked exclusively and shared in the same scope}}
Caitlin Sadowskia53257c2011-09-08 18:19:38 +0000635 do {
636 sls_mu.Unlock();
Caitlin Sadowski4e4bc752011-09-15 17:25:19 +0000637 sls_mu.ReaderLock(); // \
638 // expected-note {{the other lock of mutex 'sls_mu' is here}}
Caitlin Sadowskia53257c2011-09-08 18:19:38 +0000639 } while (getBool());
640 sls_mu.Unlock();
641}
642
643void shared_bad_1() {
644 if (getBool())
645 sls_mu.Lock(); // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000646 // expected-warning {{mutex 'sls_mu' is locked exclusively and shared in the same scope}}
Caitlin Sadowskia53257c2011-09-08 18:19:38 +0000647 else
648 sls_mu.ReaderLock(); // \
Caitlin Sadowski8bccabe2011-09-08 21:52:50 +0000649 // expected-note {{the other lock of mutex 'sls_mu' is here}}
Caitlin Sadowskia53257c2011-09-08 18:19:38 +0000650 *pgb_var = 1;
651 sls_mu.Unlock();
652}
653
654void shared_bad_2() {
655 if (getBool())
656 sls_mu.ReaderLock(); // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000657 // expected-warning {{mutex 'sls_mu' is locked exclusively and shared in the same scope}}
Caitlin Sadowskia53257c2011-09-08 18:19:38 +0000658 else
659 sls_mu.Lock(); // \
Caitlin Sadowski8bccabe2011-09-08 21:52:50 +0000660 // expected-note {{the other lock of mutex 'sls_mu' is here}}
Caitlin Sadowskia53257c2011-09-08 18:19:38 +0000661 *pgb_var = 1;
662 sls_mu.Unlock();
663}
Caitlin Sadowski978191e2011-09-08 18:27:31 +0000664
665// FIXME: Add support for functions (not only methods)
666class LRBar {
667 public:
668 void aa_elr_fun() __attribute__((exclusive_locks_required(aa_mu)));
669 void aa_elr_fun_s() __attribute__((shared_locks_required(aa_mu)));
670 void le_fun() __attribute__((locks_excluded(sls_mu)));
671};
672
673class LRFoo {
674 public:
675 void test() __attribute__((exclusive_locks_required(sls_mu)));
676 void testShared() __attribute__((shared_locks_required(sls_mu2)));
677};
678
679void elr_fun() __attribute__((exclusive_locks_required(sls_mu)));
680void elr_fun() {}
681
682LRFoo MyLRFoo;
683LRBar Bar;
684
685void es_fun_0() {
686 aa_mu.Lock();
687 Bar.aa_elr_fun();
688 aa_mu.Unlock();
689}
690
691void es_fun_1() {
692 aa_mu.Lock();
693 Bar.aa_elr_fun_s();
694 aa_mu.Unlock();
695}
696
697void es_fun_2() {
698 aa_mu.ReaderLock();
699 Bar.aa_elr_fun_s();
700 aa_mu.Unlock();
701}
702
703void es_fun_3() {
704 sls_mu.Lock();
705 MyLRFoo.test();
706 sls_mu.Unlock();
707}
708
709void es_fun_4() {
710 sls_mu2.Lock();
711 MyLRFoo.testShared();
712 sls_mu2.Unlock();
713}
714
715void es_fun_5() {
716 sls_mu2.ReaderLock();
717 MyLRFoo.testShared();
718 sls_mu2.Unlock();
719}
720
721void es_fun_6() {
722 Bar.le_fun();
723}
724
725void es_fun_7() {
726 sls_mu.Lock();
727 elr_fun();
728 sls_mu.Unlock();
729}
730
Caitlin Sadowskiaf370612011-09-08 18:35:21 +0000731void es_fun_8() __attribute__((no_thread_safety_analysis));
732
733void es_fun_8() {
734 Bar.aa_elr_fun_s();
735}
736
Caitlin Sadowskicb967512011-09-15 17:43:08 +0000737void es_fun_9() __attribute__((shared_locks_required(aa_mu)));
738void es_fun_9() {
739 Bar.aa_elr_fun_s();
740}
741
742void es_fun_10() __attribute__((exclusive_locks_required(aa_mu)));
743void es_fun_10() {
744 Bar.aa_elr_fun_s();
745}
746
Caitlin Sadowski978191e2011-09-08 18:27:31 +0000747void es_bad_0() {
748 Bar.aa_elr_fun(); // \
Caitlin Sadowski8bccabe2011-09-08 21:52:50 +0000749 // expected-warning {{calling function 'aa_elr_fun' requires exclusive lock on 'aa_mu'}}
Caitlin Sadowski978191e2011-09-08 18:27:31 +0000750}
751
752void es_bad_1() {
753 aa_mu.ReaderLock();
754 Bar.aa_elr_fun(); // \
Caitlin Sadowski8bccabe2011-09-08 21:52:50 +0000755 // expected-warning {{calling function 'aa_elr_fun' requires exclusive lock on 'aa_mu'}}
Caitlin Sadowski978191e2011-09-08 18:27:31 +0000756 aa_mu.Unlock();
757}
758
759void es_bad_2() {
760 Bar.aa_elr_fun_s(); // \
Caitlin Sadowski8bccabe2011-09-08 21:52:50 +0000761 // expected-warning {{calling function 'aa_elr_fun_s' requires shared lock on 'aa_mu'}}
Caitlin Sadowski978191e2011-09-08 18:27:31 +0000762}
763
764void es_bad_3() {
765 MyLRFoo.test(); // \
Caitlin Sadowski8bccabe2011-09-08 21:52:50 +0000766 // expected-warning {{calling function 'test' requires exclusive lock on 'sls_mu'}}
Caitlin Sadowski978191e2011-09-08 18:27:31 +0000767}
768
769void es_bad_4() {
770 MyLRFoo.testShared(); // \
Caitlin Sadowski8bccabe2011-09-08 21:52:50 +0000771 // expected-warning {{calling function 'testShared' requires shared lock on 'sls_mu2'}}
Caitlin Sadowski978191e2011-09-08 18:27:31 +0000772}
773
774void es_bad_5() {
775 sls_mu.ReaderLock();
776 MyLRFoo.test(); // \
Caitlin Sadowski8bccabe2011-09-08 21:52:50 +0000777 // expected-warning {{calling function 'test' requires exclusive lock on 'sls_mu'}}
Caitlin Sadowski978191e2011-09-08 18:27:31 +0000778 sls_mu.Unlock();
779}
780
781void es_bad_6() {
782 sls_mu.Lock();
783 Bar.le_fun(); // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000784 // expected-warning {{cannot call function 'le_fun' while mutex 'sls_mu' is locked}}
Caitlin Sadowski978191e2011-09-08 18:27:31 +0000785 sls_mu.Unlock();
786}
787
788void es_bad_7() {
789 sls_mu.ReaderLock();
790 Bar.le_fun(); // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000791 // expected-warning {{cannot call function 'le_fun' while mutex 'sls_mu' is locked}}
Caitlin Sadowski978191e2011-09-08 18:27:31 +0000792 sls_mu.Unlock();
793}
Caitlin Sadowski194418f2011-09-14 20:00:24 +0000794
DeLesley Hutchins81216392011-10-17 21:38:02 +0000795
Caitlin Sadowski194418f2011-09-14 20:00:24 +0000796//-----------------------------------------------//
797// Unparseable lock expressions
798// ----------------------------------------------//
799
DeLesley Hutchins0d95dfc2012-03-02 23:36:05 +0000800// FIXME -- derive new tests for unhandled expressions
Caitlin Sadowski194418f2011-09-14 20:00:24 +0000801
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +0000802
803//----------------------------------------------------------------------------//
804// The following test cases are ported from the gcc thread safety implementation
805// They are each wrapped inside a namespace with the test number of the gcc test
806//
807// FIXME: add all the gcc tests, once this analysis passes them.
808//----------------------------------------------------------------------------//
809
810//-----------------------------------------//
811// Good testcases (no errors)
812//-----------------------------------------//
813
814namespace thread_annot_lock_20 {
815class Bar {
816 public:
817 static int func1() EXCLUSIVE_LOCKS_REQUIRED(mu1_);
818 static int b_ GUARDED_BY(mu1_);
819 static Mutex mu1_;
820 static int a_ GUARDED_BY(mu1_);
821};
822
823Bar b1;
824
825int Bar::func1()
826{
827 int res = 5;
828
829 if (a_ == 4)
830 res = b_;
831 return res;
832}
833} // end namespace thread_annot_lock_20
834
835namespace thread_annot_lock_22 {
836// Test various usage of GUARDED_BY and PT_GUARDED_BY annotations, especially
837// uses in class definitions.
838Mutex mu;
839
840class Bar {
841 public:
842 int a_ GUARDED_BY(mu1_);
843 int b_;
844 int *q PT_GUARDED_BY(mu);
845 Mutex mu1_ ACQUIRED_AFTER(mu);
846};
847
848Bar b1, *b3;
849int *p GUARDED_BY(mu) PT_GUARDED_BY(mu);
850int res GUARDED_BY(mu) = 5;
851
852int func(int i)
853{
854 int x;
855 mu.Lock();
856 b1.mu1_.Lock();
857 res = b1.a_ + b3->b_;
858 *p = i;
859 b1.a_ = res + b3->b_;
860 b3->b_ = *b1.q;
861 b1.mu1_.Unlock();
862 b1.b_ = res;
863 x = res;
864 mu.Unlock();
865 return x;
866}
867} // end namespace thread_annot_lock_22
868
869namespace thread_annot_lock_27_modified {
870// test lock annotations applied to function definitions
871// Modified: applied annotations only to function declarations
872Mutex mu1;
873Mutex mu2 ACQUIRED_AFTER(mu1);
874
875class Foo {
876 public:
877 int method1(int i) SHARED_LOCKS_REQUIRED(mu2) EXCLUSIVE_LOCKS_REQUIRED(mu1);
878};
879
880int Foo::method1(int i) {
881 return i;
882}
883
884
885int foo(int i) EXCLUSIVE_LOCKS_REQUIRED(mu2) SHARED_LOCKS_REQUIRED(mu1);
886int foo(int i) {
887 return i;
888}
889
890static int bar(int i) EXCLUSIVE_LOCKS_REQUIRED(mu1);
891static int bar(int i) {
892 return i;
893}
894
895void main() {
896 Foo a;
897
898 mu1.Lock();
899 mu2.Lock();
900 a.method1(1);
901 foo(2);
902 mu2.Unlock();
903 bar(3);
904 mu1.Unlock();
905}
906} // end namespace thread_annot_lock_27_modified
907
908
909namespace thread_annot_lock_38 {
910// Test the case where a template member function is annotated with lock
911// attributes in a non-template class.
912class Foo {
913 public:
914 void func1(int y) LOCKS_EXCLUDED(mu_);
915 template <typename T> void func2(T x) LOCKS_EXCLUDED(mu_);
916 private:
917 Mutex mu_;
918};
919
920Foo *foo;
921
922void main()
923{
924 foo->func1(5);
925 foo->func2(5);
926}
927} // end namespace thread_annot_lock_38
928
929namespace thread_annot_lock_43 {
930// Tests lock canonicalization
931class Foo {
932 public:
933 Mutex *mu_;
934};
935
936class FooBar {
937 public:
938 Foo *foo_;
939 int GetA() EXCLUSIVE_LOCKS_REQUIRED(foo_->mu_) { return a_; }
940 int a_ GUARDED_BY(foo_->mu_);
941};
942
943FooBar *fb;
944
945void main()
946{
947 int x;
948 fb->foo_->mu_->Lock();
949 x = fb->GetA();
950 fb->foo_->mu_->Unlock();
951}
952} // end namespace thread_annot_lock_43
953
954namespace thread_annot_lock_49 {
955// Test the support for use of lock expression in the annotations
956class Foo {
957 public:
958 Mutex foo_mu_;
959};
960
961class Bar {
962 private:
963 Foo *foo;
964 Mutex bar_mu_ ACQUIRED_AFTER(foo->foo_mu_);
965
966 public:
967 void Test1() {
968 foo->foo_mu_.Lock();
969 bar_mu_.Lock();
970 bar_mu_.Unlock();
971 foo->foo_mu_.Unlock();
972 }
973};
974
975void main() {
976 Bar bar;
977 bar.Test1();
978}
979} // end namespace thread_annot_lock_49
980
981namespace thread_annot_lock_61_modified {
982 // Modified to fix the compiler errors
983 // Test the fix for a bug introduced by the support of pass-by-reference
984 // paramters.
985 struct Foo { Foo &operator<< (bool) {return *this;} };
986 Foo &getFoo();
987 struct Bar { Foo &func () {return getFoo();} };
988 struct Bas { void operator& (Foo &) {} };
989 void mumble()
990 {
991 Bas() & Bar().func() << "" << "";
992 Bas() & Bar().func() << "";
993 }
994} // end namespace thread_annot_lock_61_modified
995
996
997namespace thread_annot_lock_65 {
998// Test the fix for a bug in the support of allowing reader locks for
999// non-const, non-modifying overload functions. (We didn't handle the builtin
1000// properly.)
1001enum MyFlags {
1002 Zero,
1003 One,
1004 Two,
1005 Three,
1006 Four,
1007 Five,
1008 Six,
1009 Seven,
1010 Eight,
1011 Nine
1012};
1013
1014inline MyFlags
1015operator|(MyFlags a, MyFlags b)
1016{
1017 return MyFlags(static_cast<int>(a) | static_cast<int>(b));
1018}
1019
1020inline MyFlags&
1021operator|=(MyFlags& a, MyFlags b)
1022{
1023 return a = a | b;
1024}
1025} // end namespace thread_annot_lock_65
1026
1027namespace thread_annot_lock_66_modified {
1028// Modified: Moved annotation to function defn
1029// Test annotations on out-of-line definitions of member functions where the
1030// annotations refer to locks that are also data members in the class.
1031Mutex mu;
1032
1033class Foo {
1034 public:
1035 int method1(int i) SHARED_LOCKS_REQUIRED(mu1, mu, mu2);
1036 int data GUARDED_BY(mu1);
1037 Mutex *mu1;
1038 Mutex *mu2;
1039};
1040
1041int Foo::method1(int i)
1042{
1043 return data + i;
1044}
1045
1046void main()
1047{
1048 Foo a;
1049
1050 a.mu2->Lock();
1051 a.mu1->Lock();
1052 mu.Lock();
1053 a.method1(1);
1054 mu.Unlock();
1055 a.mu1->Unlock();
1056 a.mu2->Unlock();
1057}
1058} // end namespace thread_annot_lock_66_modified
1059
1060namespace thread_annot_lock_68_modified {
1061// Test a fix to a bug in the delayed name binding with nested template
1062// instantiation. We use a stack to make sure a name is not resolved to an
1063// inner context.
1064template <typename T>
1065class Bar {
1066 Mutex mu_;
1067};
1068
1069template <typename T>
1070class Foo {
1071 public:
1072 void func(T x) {
1073 mu_.Lock();
DeLesley Hutchins23323e02012-01-20 22:50:54 +00001074 count_ = x;
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001075 mu_.Unlock();
1076 }
1077
1078 private:
DeLesley Hutchins23323e02012-01-20 22:50:54 +00001079 T count_ GUARDED_BY(mu_);
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001080 Bar<T> bar_;
1081 Mutex mu_;
1082};
1083
1084void main()
1085{
1086 Foo<int> *foo;
1087 foo->func(5);
1088}
1089} // end namespace thread_annot_lock_68_modified
1090
1091namespace thread_annot_lock_30_modified {
1092// Test delay parsing of lock attribute arguments with nested classes.
1093// Modified: trylocks replaced with exclusive_lock_fun
1094int a = 0;
1095
1096class Bar {
1097 struct Foo;
1098
1099 public:
1100 void MyLock() EXCLUSIVE_LOCK_FUNCTION(mu);
1101
1102 int func() {
1103 MyLock();
1104// if (foo == 0) {
1105// return 0;
1106// }
1107 a = 5;
1108 mu.Unlock();
1109 return 1;
1110 }
1111
1112 class FooBar {
1113 int x;
1114 int y;
1115 };
1116
1117 private:
1118 Mutex mu;
1119};
1120
1121Bar *bar;
1122
1123void main()
1124{
1125 bar->func();
1126}
1127} // end namespace thread_annot_lock_30_modified
1128
1129namespace thread_annot_lock_47 {
1130// Test the support for annotations on virtual functions.
1131// This is a good test case. (i.e. There should be no warning emitted by the
1132// compiler.)
1133class Base {
1134 public:
1135 virtual void func1() EXCLUSIVE_LOCKS_REQUIRED(mu_);
1136 virtual void func2() LOCKS_EXCLUDED(mu_);
1137 Mutex mu_;
1138};
1139
1140class Child : public Base {
1141 public:
1142 virtual void func1() EXCLUSIVE_LOCKS_REQUIRED(mu_);
1143 virtual void func2() LOCKS_EXCLUDED(mu_);
1144};
1145
1146void main() {
1147 Child *c;
1148 Base *b = c;
1149
1150 b->mu_.Lock();
1151 b->func1();
1152 b->mu_.Unlock();
1153 b->func2();
1154
1155 c->mu_.Lock();
1156 c->func1();
1157 c->mu_.Unlock();
1158 c->func2();
1159}
1160} // end namespace thread_annot_lock_47
1161
1162//-----------------------------------------//
1163// Tests which produce errors
1164//-----------------------------------------//
1165
1166namespace thread_annot_lock_13 {
1167Mutex mu1;
1168Mutex mu2;
1169
1170int g GUARDED_BY(mu1);
1171int w GUARDED_BY(mu2);
1172
1173class Foo {
1174 public:
1175 void bar() LOCKS_EXCLUDED(mu_, mu1);
1176 int foo() SHARED_LOCKS_REQUIRED(mu_) EXCLUSIVE_LOCKS_REQUIRED(mu2);
1177
1178 private:
1179 int a_ GUARDED_BY(mu_);
1180 public:
1181 Mutex mu_ ACQUIRED_AFTER(mu1);
1182};
1183
1184int Foo::foo()
1185{
1186 int res;
David Blaikiee31b8fb2012-04-05 00:16:44 +00001187 w = 5;
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001188 res = a_ + 5;
1189 return res;
1190}
1191
1192void Foo::bar()
1193{
1194 int x;
1195 mu_.Lock();
1196 x = foo(); // expected-warning {{calling function 'foo' requires exclusive lock on 'mu2'}}
1197 a_ = x + 1;
1198 mu_.Unlock();
1199 if (x > 5) {
1200 mu1.Lock();
David Blaikiee31b8fb2012-04-05 00:16:44 +00001201 g = 2;
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001202 mu1.Unlock();
1203 }
1204}
1205
1206void main()
1207{
1208 Foo f1, *f2;
1209 f1.mu_.Lock();
DeLesley Hutchinsa74b7152012-08-10 20:19:55 +00001210 f1.bar(); // expected-warning {{cannot call function 'bar' while mutex 'f1.mu_' is locked}}
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001211 mu2.Lock();
1212 f1.foo();
1213 mu2.Unlock();
1214 f1.mu_.Unlock();
1215 f2->mu_.Lock();
DeLesley Hutchinsa74b7152012-08-10 20:19:55 +00001216 f2->bar(); // expected-warning {{cannot call function 'bar' while mutex 'f2->mu_' is locked}}
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001217 f2->mu_.Unlock();
1218 mu2.Lock();
David Blaikiee31b8fb2012-04-05 00:16:44 +00001219 w = 2;
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001220 mu2.Unlock();
1221}
1222} // end namespace thread_annot_lock_13
1223
1224namespace thread_annot_lock_18_modified {
1225// Modified: Trylocks removed
1226// Test the ability to distnguish between the same lock field of
1227// different objects of a class.
1228 class Bar {
1229 public:
1230 bool MyLock() EXCLUSIVE_LOCK_FUNCTION(mu1_);
1231 void MyUnlock() UNLOCK_FUNCTION(mu1_);
1232 int a_ GUARDED_BY(mu1_);
1233
1234 private:
1235 Mutex mu1_;
1236};
1237
1238Bar *b1, *b2;
1239
1240void func()
1241{
1242 b1->MyLock();
1243 b1->a_ = 5;
DeLesley Hutchins3f0ec522012-09-10 19:58:23 +00001244 b2->a_ = 3; // \
1245 // expected-warning {{writing variable 'a_' requires locking 'b2->mu1_' exclusively}} \
1246 // expected-note {{found near match 'b1->mu1_'}}
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001247 b2->MyLock();
1248 b2->MyUnlock();
1249 b1->MyUnlock();
1250}
1251} // end namespace thread_annot_lock_18_modified
1252
1253namespace thread_annot_lock_21 {
1254// Test various usage of GUARDED_BY and PT_GUARDED_BY annotations, especially
1255// uses in class definitions.
1256Mutex mu;
1257
1258class Bar {
1259 public:
1260 int a_ GUARDED_BY(mu1_);
1261 int b_;
1262 int *q PT_GUARDED_BY(mu);
1263 Mutex mu1_ ACQUIRED_AFTER(mu);
1264};
1265
1266Bar b1, *b3;
1267int *p GUARDED_BY(mu) PT_GUARDED_BY(mu);
1268
1269int res GUARDED_BY(mu) = 5;
1270
1271int func(int i)
1272{
1273 int x;
1274 b3->mu1_.Lock();
DeLesley Hutchinsa74b7152012-08-10 20:19:55 +00001275 res = b1.a_ + b3->b_; // expected-warning {{reading variable 'a_' requires locking 'b1.mu1_'}} \
DeLesley Hutchins3f0ec522012-09-10 19:58:23 +00001276 // expected-warning {{writing variable 'res' requires locking 'mu' exclusively}} \
1277 // expected-note {{found near match 'b3->mu1_'}}
Caitlin Sadowski74558b42011-09-15 18:13:32 +00001278 *p = i; // expected-warning {{reading variable 'p' requires locking 'mu'}} \
1279 // expected-warning {{writing the value pointed to by 'p' requires locking 'mu' exclusively}}
1280 b1.a_ = res + b3->b_; // expected-warning {{reading variable 'res' requires locking 'mu'}} \
DeLesley Hutchins3f0ec522012-09-10 19:58:23 +00001281 // expected-warning {{writing variable 'a_' requires locking 'b1.mu1_' exclusively}} \
1282 // expected-note {{found near match 'b3->mu1_'}}
Caitlin Sadowski74558b42011-09-15 18:13:32 +00001283 b3->b_ = *b1.q; // expected-warning {{reading the value pointed to by 'q' requires locking 'mu'}}
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001284 b3->mu1_.Unlock();
Caitlin Sadowski74558b42011-09-15 18:13:32 +00001285 b1.b_ = res; // expected-warning {{reading variable 'res' requires locking 'mu'}}
1286 x = res; // expected-warning {{reading variable 'res' requires locking 'mu'}}
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001287 return x;
1288}
1289} // end namespace thread_annot_lock_21
1290
1291namespace thread_annot_lock_35_modified {
1292// Test the analyzer's ability to distinguish the lock field of different
1293// objects.
1294class Foo {
1295 private:
1296 Mutex lock_;
1297 int a_ GUARDED_BY(lock_);
1298
1299 public:
1300 void Func(Foo* child) LOCKS_EXCLUDED(lock_) {
1301 Foo *new_foo = new Foo;
1302
1303 lock_.Lock();
1304
1305 child->Func(new_foo); // There shouldn't be any warning here as the
1306 // acquired lock is not in child.
DeLesley Hutchins3f0ec522012-09-10 19:58:23 +00001307 child->bar(7); // \
1308 // expected-warning {{calling function 'bar' requires exclusive lock on 'child->lock_'}} \
1309 // expected-note {{found near match 'lock_'}}
1310 child->a_ = 5; // \
1311 // expected-warning {{writing variable 'a_' requires locking 'child->lock_' exclusively}} \
1312 // expected-note {{found near match 'lock_'}}
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001313 lock_.Unlock();
1314 }
1315
1316 void bar(int y) EXCLUSIVE_LOCKS_REQUIRED(lock_) {
1317 a_ = y;
1318 }
1319};
1320
1321Foo *x;
1322
1323void main() {
1324 Foo *child = new Foo;
1325 x->Func(child);
1326}
1327} // end namespace thread_annot_lock_35_modified
1328
1329namespace thread_annot_lock_36_modified {
1330// Modified to move the annotations to function defns.
1331// Test the analyzer's ability to distinguish the lock field of different
1332// objects
1333class Foo {
1334 private:
1335 Mutex lock_;
1336 int a_ GUARDED_BY(lock_);
1337
1338 public:
1339 void Func(Foo* child) LOCKS_EXCLUDED(lock_);
1340 void bar(int y) EXCLUSIVE_LOCKS_REQUIRED(lock_);
1341};
1342
1343void Foo::Func(Foo* child) {
1344 Foo *new_foo = new Foo;
1345
1346 lock_.Lock();
1347
1348 child->lock_.Lock();
DeLesley Hutchinsa74b7152012-08-10 20:19:55 +00001349 child->Func(new_foo); // expected-warning {{cannot call function 'Func' while mutex 'child->lock_' is locked}}
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001350 child->bar(7);
1351 child->a_ = 5;
1352 child->lock_.Unlock();
1353
1354 lock_.Unlock();
1355}
1356
1357void Foo::bar(int y) {
1358 a_ = y;
1359}
1360
1361
1362Foo *x;
1363
1364void main() {
1365 Foo *child = new Foo;
1366 x->Func(child);
1367}
1368} // end namespace thread_annot_lock_36_modified
1369
1370
1371namespace thread_annot_lock_42 {
1372// Test support of multiple lock attributes of the same kind on a decl.
1373class Foo {
1374 private:
1375 Mutex mu1, mu2, mu3;
1376 int x GUARDED_BY(mu1) GUARDED_BY(mu2);
1377 int y GUARDED_BY(mu2);
1378
1379 void f2() LOCKS_EXCLUDED(mu1) LOCKS_EXCLUDED(mu2) LOCKS_EXCLUDED(mu3) {
1380 mu2.Lock();
1381 y = 2;
1382 mu2.Unlock();
1383 }
1384
1385 public:
1386 void f1() EXCLUSIVE_LOCKS_REQUIRED(mu2) EXCLUSIVE_LOCKS_REQUIRED(mu1) {
1387 x = 5;
Caitlin Sadowski74558b42011-09-15 18:13:32 +00001388 f2(); // expected-warning {{cannot call function 'f2' while mutex 'mu1' is locked}} \
1389 // expected-warning {{cannot call function 'f2' while mutex 'mu2' is locked}}
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001390 }
1391};
1392
1393Foo *foo;
1394
1395void func()
1396{
DeLesley Hutchinsa74b7152012-08-10 20:19:55 +00001397 foo->f1(); // expected-warning {{calling function 'f1' requires exclusive lock on 'foo->mu2'}} \
1398 // expected-warning {{calling function 'f1' requires exclusive lock on 'foo->mu1'}}
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001399}
1400} // end namespace thread_annot_lock_42
1401
1402namespace thread_annot_lock_46 {
1403// Test the support for annotations on virtual functions.
1404class Base {
1405 public:
1406 virtual void func1() EXCLUSIVE_LOCKS_REQUIRED(mu_);
1407 virtual void func2() LOCKS_EXCLUDED(mu_);
1408 Mutex mu_;
1409};
1410
1411class Child : public Base {
1412 public:
1413 virtual void func1() EXCLUSIVE_LOCKS_REQUIRED(mu_);
1414 virtual void func2() LOCKS_EXCLUDED(mu_);
1415};
1416
1417void main() {
1418 Child *c;
1419 Base *b = c;
1420
DeLesley Hutchinsa74b7152012-08-10 20:19:55 +00001421 b->func1(); // expected-warning {{calling function 'func1' requires exclusive lock on 'b->mu_'}}
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001422 b->mu_.Lock();
DeLesley Hutchinsa74b7152012-08-10 20:19:55 +00001423 b->func2(); // expected-warning {{cannot call function 'func2' while mutex 'b->mu_' is locked}}
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001424 b->mu_.Unlock();
1425
DeLesley Hutchinsa74b7152012-08-10 20:19:55 +00001426 c->func1(); // expected-warning {{calling function 'func1' requires exclusive lock on 'c->mu_'}}
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001427 c->mu_.Lock();
DeLesley Hutchinsa74b7152012-08-10 20:19:55 +00001428 c->func2(); // expected-warning {{cannot call function 'func2' while mutex 'c->mu_' is locked}}
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001429 c->mu_.Unlock();
1430}
1431} // end namespace thread_annot_lock_46
1432
1433namespace thread_annot_lock_67_modified {
1434// Modified: attributes on definitions moved to declarations
1435// Test annotations on out-of-line definitions of member functions where the
1436// annotations refer to locks that are also data members in the class.
1437Mutex mu;
1438Mutex mu3;
1439
1440class Foo {
1441 public:
1442 int method1(int i) SHARED_LOCKS_REQUIRED(mu1, mu, mu2, mu3);
1443 int data GUARDED_BY(mu1);
1444 Mutex *mu1;
1445 Mutex *mu2;
1446};
1447
1448int Foo::method1(int i) {
1449 return data + i;
1450}
1451
1452void main()
1453{
1454 Foo a;
DeLesley Hutchinsa74b7152012-08-10 20:19:55 +00001455 a.method1(1); // expected-warning {{calling function 'method1' requires shared lock on 'a.mu1'}} \
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001456 // expected-warning {{calling function 'method1' requires shared lock on 'mu'}} \
DeLesley Hutchinsa74b7152012-08-10 20:19:55 +00001457 // expected-warning {{calling function 'method1' requires shared lock on 'a.mu2'}} \
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001458 // expected-warning {{calling function 'method1' requires shared lock on 'mu3'}}
1459}
1460} // end namespace thread_annot_lock_67_modified
1461
1462
DeLesley Hutchins81216392011-10-17 21:38:02 +00001463namespace substitution_test {
1464 class MyData {
1465 public:
1466 Mutex mu;
1467
1468 void lockData() __attribute__((exclusive_lock_function(mu))) { }
1469 void unlockData() __attribute__((unlock_function(mu))) { }
1470
1471 void doSomething() __attribute__((exclusive_locks_required(mu))) { }
1472 };
1473
1474
1475 class DataLocker {
1476 public:
1477 void lockData (MyData *d) __attribute__((exclusive_lock_function(d->mu))) { }
1478 void unlockData(MyData *d) __attribute__((unlock_function(d->mu))) { }
1479 };
1480
1481
1482 class Foo {
1483 public:
1484 void foo(MyData* d) __attribute__((exclusive_locks_required(d->mu))) { }
1485
1486 void bar1(MyData* d) {
1487 d->lockData();
1488 foo(d);
1489 d->unlockData();
1490 }
1491
1492 void bar2(MyData* d) {
1493 DataLocker dlr;
1494 dlr.lockData(d);
1495 foo(d);
1496 dlr.unlockData(d);
1497 }
1498
1499 void bar3(MyData* d1, MyData* d2) {
1500 DataLocker dlr;
Richard Smith2e515622012-02-03 04:45:26 +00001501 dlr.lockData(d1); // expected-note {{mutex acquired here}}
DeLesley Hutchins81216392011-10-17 21:38:02 +00001502 dlr.unlockData(d2); // \
DeLesley Hutchinsa74b7152012-08-10 20:19:55 +00001503 // expected-warning {{unlocking 'd2->mu' that was not locked}}
1504 } // expected-warning {{mutex 'd1->mu' is still locked at the end of function}}
DeLesley Hutchins81216392011-10-17 21:38:02 +00001505
1506 void bar4(MyData* d1, MyData* d2) {
1507 DataLocker dlr;
1508 dlr.lockData(d1);
1509 foo(d2); // \
DeLesley Hutchins3f0ec522012-09-10 19:58:23 +00001510 // expected-warning {{calling function 'foo' requires exclusive lock on 'd2->mu'}} \
1511 // expected-note {{found near match 'd1->mu'}}
DeLesley Hutchins81216392011-10-17 21:38:02 +00001512 dlr.unlockData(d1);
1513 }
1514 };
1515} // end namespace substituation_test
1516
DeLesley Hutchinse0eaa852011-10-21 18:06:53 +00001517
DeLesley Hutchinsf1ac6372011-10-21 18:10:14 +00001518
DeLesley Hutchinse0eaa852011-10-21 18:06:53 +00001519namespace constructor_destructor_tests {
1520 Mutex fooMu;
1521 int myVar GUARDED_BY(fooMu);
1522
1523 class Foo {
1524 public:
1525 Foo() __attribute__((exclusive_lock_function(fooMu))) { }
1526 ~Foo() __attribute__((unlock_function(fooMu))) { }
1527 };
1528
1529 void fooTest() {
DeLesley Hutchins6db51f72011-10-21 20:51:27 +00001530 Foo foo;
DeLesley Hutchinse0eaa852011-10-21 18:06:53 +00001531 myVar = 0;
1532 }
1533}
1534
DeLesley Hutchinsf1ac6372011-10-21 18:10:14 +00001535
1536namespace invalid_lock_expression_test {
1537
1538class LOCKABLE MyLockable {
1539public:
1540 MyLockable() __attribute__((exclusive_lock_function)) { }
DeLesley Hutchins6db51f72011-10-21 20:51:27 +00001541 ~MyLockable() { }
DeLesley Hutchinsf1ac6372011-10-21 18:10:14 +00001542};
1543
1544// create an empty lock expression
1545void foo() {
1546 MyLockable lock; // \
1547 // expected-warning {{cannot resolve lock expression}}
1548}
1549
1550} // end namespace invalid_lock_expression_test
1551
Richard Smith97f9fe02011-10-25 00:41:24 +00001552namespace template_member_test {
DeLesley Hutchinsf1ac6372011-10-21 18:10:14 +00001553
Richard Smith97f9fe02011-10-25 00:41:24 +00001554 struct S { int n; };
1555 struct T {
1556 Mutex m;
1557 S *s GUARDED_BY(this->m);
1558 };
Richard Smitha01c7112011-10-25 06:33:21 +00001559 Mutex m;
1560 struct U {
1561 union {
1562 int n;
1563 };
1564 } *u GUARDED_BY(m);
Richard Smith97f9fe02011-10-25 00:41:24 +00001565
1566 template<typename U>
1567 struct IndirectLock {
1568 int DoNaughtyThings(T *t) {
Richard Smitha01c7112011-10-25 06:33:21 +00001569 u->n = 0; // expected-warning {{reading variable 'u' requires locking 'm'}}
DeLesley Hutchinsa74b7152012-08-10 20:19:55 +00001570 return t->s->n; // expected-warning {{reading variable 's' requires locking 't->m'}}
Richard Smith97f9fe02011-10-25 00:41:24 +00001571 }
1572 };
1573
Richard Smithf11e9232011-10-25 01:05:41 +00001574 template struct IndirectLock<int>; // expected-note {{here}}
Richard Smith97f9fe02011-10-25 00:41:24 +00001575
Richard Smith601d2ee2011-10-26 06:15:36 +00001576 struct V {
1577 void f(int);
1578 void f(double);
1579
1580 Mutex m;
1581 V *p GUARDED_BY(this->m);
1582 };
1583 template<typename U> struct W {
1584 V v;
1585 void f(U u) {
DeLesley Hutchinsa74b7152012-08-10 20:19:55 +00001586 v.p->f(u); // expected-warning {{reading variable 'p' requires locking 'v.m'}}
Richard Smith601d2ee2011-10-26 06:15:36 +00001587 }
1588 };
1589 template struct W<int>; // expected-note {{here}}
1590
Richard Smith97f9fe02011-10-25 00:41:24 +00001591}
DeLesley Hutchins1fa3c062011-12-08 20:23:06 +00001592
1593namespace test_scoped_lockable {
1594
1595struct TestScopedLockable {
1596 Mutex mu1;
1597 Mutex mu2;
1598 int a __attribute__((guarded_by(mu1)));
1599 int b __attribute__((guarded_by(mu2)));
1600
1601 bool getBool();
1602
1603 void foo1() {
1604 MutexLock mulock(&mu1);
1605 a = 5;
1606 }
1607
1608 void foo2() {
1609 ReaderMutexLock mulock1(&mu1);
1610 if (getBool()) {
1611 MutexLock mulock2a(&mu2);
1612 b = a + 1;
1613 }
1614 else {
1615 MutexLock mulock2b(&mu2);
1616 b = a + 2;
1617 }
1618 }
1619
1620 void foo3() {
1621 MutexLock mulock_a(&mu1);
1622 MutexLock mulock_b(&mu1); // \
1623 // expected-warning {{locking 'mu1' that is already locked}}
DeLesley Hutchinsc99a5d82012-06-28 22:42:48 +00001624 }
DeLesley Hutchins1fa3c062011-12-08 20:23:06 +00001625
1626 void foo4() {
1627 MutexLock mulock1(&mu1), mulock2(&mu2);
1628 a = b+1;
1629 b = a+1;
1630 }
1631};
1632
1633} // end namespace test_scoped_lockable
1634
1635
DeLesley Hutchinsdf497822011-12-29 00:56:48 +00001636namespace FunctionAttrTest {
1637
1638class Foo {
1639public:
1640 Mutex mu_;
1641 int a GUARDED_BY(mu_);
1642};
1643
1644Foo fooObj;
1645
1646void foo() EXCLUSIVE_LOCKS_REQUIRED(fooObj.mu_);
1647
1648void bar() {
DeLesley Hutchinsa74b7152012-08-10 20:19:55 +00001649 foo(); // expected-warning {{calling function 'foo' requires exclusive lock on 'fooObj.mu_'}}
DeLesley Hutchinsdf497822011-12-29 00:56:48 +00001650 fooObj.mu_.Lock();
1651 foo();
1652 fooObj.mu_.Unlock();
1653}
1654
1655}; // end namespace FunctionAttrTest
1656
1657
DeLesley Hutchinsb4fa4182012-01-06 19:16:50 +00001658struct TestTryLock {
1659 Mutex mu;
1660 int a GUARDED_BY(mu);
1661 bool cond;
1662
1663 void foo1() {
1664 if (mu.TryLock()) {
1665 a = 1;
1666 mu.Unlock();
1667 }
1668 }
1669
1670 void foo2() {
1671 if (!mu.TryLock()) return;
1672 a = 2;
1673 mu.Unlock();
1674 }
1675
1676 void foo3() {
1677 bool b = mu.TryLock();
1678 if (b) {
1679 a = 3;
1680 mu.Unlock();
1681 }
1682 }
1683
1684 void foo4() {
1685 bool b = mu.TryLock();
1686 if (!b) return;
1687 a = 4;
1688 mu.Unlock();
1689 }
1690
1691 void foo5() {
1692 while (mu.TryLock()) {
1693 a = a + 1;
1694 mu.Unlock();
1695 }
1696 }
1697
1698 void foo6() {
1699 bool b = mu.TryLock();
1700 b = !b;
1701 if (b) return;
1702 a = 6;
1703 mu.Unlock();
1704 }
1705
1706 void foo7() {
1707 bool b1 = mu.TryLock();
1708 bool b2 = !b1;
1709 bool b3 = !b2;
1710 if (b3) {
1711 a = 7;
1712 mu.Unlock();
1713 }
1714 }
1715
1716 // Test use-def chains: join points
1717 void foo8() {
1718 bool b = mu.TryLock();
1719 bool b2 = b;
1720 if (cond)
1721 b = true;
Sylvestre Ledru43e3dee2012-07-31 06:56:50 +00001722 if (b) { // b should be unknown at this point, because of the join point
DeLesley Hutchinsb4fa4182012-01-06 19:16:50 +00001723 a = 8; // expected-warning {{writing variable 'a' requires locking 'mu' exclusively}}
1724 }
1725 if (b2) { // b2 should be known at this point.
1726 a = 8;
1727 mu.Unlock();
1728 }
1729 }
1730
1731 // Test use-def-chains: back edges
1732 void foo9() {
1733 bool b = mu.TryLock();
1734
1735 for (int i = 0; i < 10; ++i);
1736
1737 if (b) { // b is still known, because the loop doesn't alter it
1738 a = 9;
1739 mu.Unlock();
1740 }
1741 }
1742
1743 // Test use-def chains: back edges
1744 void foo10() {
1745 bool b = mu.TryLock();
1746
1747 while (cond) {
1748 if (b) { // b should be uknown at this point b/c of the loop
1749 a = 10; // expected-warning {{writing variable 'a' requires locking 'mu' exclusively}}
1750 }
1751 b = !b;
1752 }
1753 }
1754}; // end TestTrylock
1755
1756
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +00001757namespace TestTemplateAttributeInstantiation {
1758
1759class Foo1 {
1760public:
1761 Mutex mu_;
1762 int a GUARDED_BY(mu_);
1763};
1764
1765class Foo2 {
1766public:
1767 int a GUARDED_BY(mu_);
1768 Mutex mu_;
1769};
1770
1771
1772class Bar {
1773public:
1774 // Test non-dependent expressions in attributes on template functions
1775 template <class T>
1776 void barND(Foo1 *foo, T *fooT) EXCLUSIVE_LOCKS_REQUIRED(foo->mu_) {
1777 foo->a = 0;
1778 }
1779
1780 // Test dependent expressions in attributes on template functions
1781 template <class T>
1782 void barD(Foo1 *foo, T *fooT) EXCLUSIVE_LOCKS_REQUIRED(fooT->mu_) {
1783 fooT->a = 0;
1784 }
1785};
1786
1787
1788template <class T>
1789class BarT {
1790public:
1791 Foo1 fooBase;
1792 T fooBaseT;
1793
1794 // Test non-dependent expression in ordinary method on template class
1795 void barND() EXCLUSIVE_LOCKS_REQUIRED(fooBase.mu_) {
1796 fooBase.a = 0;
1797 }
1798
1799 // Test dependent expressions in ordinary methods on template class
1800 void barD() EXCLUSIVE_LOCKS_REQUIRED(fooBaseT.mu_) {
1801 fooBaseT.a = 0;
1802 }
1803
1804 // Test dependent expressions in template method in template class
1805 template <class T2>
1806 void barTD(T2 *fooT) EXCLUSIVE_LOCKS_REQUIRED(fooBaseT.mu_, fooT->mu_) {
1807 fooBaseT.a = 0;
1808 fooT->a = 0;
1809 }
1810};
1811
1812template <class T>
1813class Cell {
1814public:
1815 Mutex mu_;
1816 // Test dependent guarded_by
1817 T data GUARDED_BY(mu_);
1818
DeLesley Hutchins23323e02012-01-20 22:50:54 +00001819 void fooEx() EXCLUSIVE_LOCKS_REQUIRED(mu_) {
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +00001820 data = 0;
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +00001821 }
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +00001822
1823 void foo() {
1824 mu_.Lock();
1825 data = 0;
1826 mu_.Unlock();
1827 }
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +00001828};
1829
1830void test() {
1831 Bar b;
1832 BarT<Foo2> bt;
1833 Foo1 f1;
1834 Foo2 f2;
1835
1836 f1.mu_.Lock();
1837 f2.mu_.Lock();
1838 bt.fooBase.mu_.Lock();
1839 bt.fooBaseT.mu_.Lock();
1840
1841 b.barND(&f1, &f2);
1842 b.barD(&f1, &f2);
1843 bt.barND();
1844 bt.barD();
1845 bt.barTD(&f2);
1846
1847 f1.mu_.Unlock();
1848 bt.barTD(&f1); // \
DeLesley Hutchins3f0ec522012-09-10 19:58:23 +00001849 // expected-warning {{calling function 'barTD' requires exclusive lock on 'f1.mu_'}} \
1850 // expected-note {{found near match 'bt.fooBase.mu_'}}
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +00001851
1852 bt.fooBase.mu_.Unlock();
1853 bt.fooBaseT.mu_.Unlock();
1854 f2.mu_.Unlock();
1855
1856 Cell<int> cell;
1857 cell.data = 0; // \
DeLesley Hutchinsa74b7152012-08-10 20:19:55 +00001858 // expected-warning {{writing variable 'data' requires locking 'cell.mu_' exclusively}}
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +00001859 cell.foo();
DeLesley Hutchins23323e02012-01-20 22:50:54 +00001860 cell.mu_.Lock();
1861 cell.fooEx();
1862 cell.mu_.Unlock();
1863}
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +00001864
DeLesley Hutchins23323e02012-01-20 22:50:54 +00001865
1866template <class T>
1867class CellDelayed {
1868public:
1869 // Test dependent guarded_by
1870 T data GUARDED_BY(mu_);
DeLesley Hutchinsdd5756c2012-02-16 17:30:51 +00001871 static T static_data GUARDED_BY(static_mu_);
DeLesley Hutchins23323e02012-01-20 22:50:54 +00001872
1873 void fooEx(CellDelayed<T> *other) EXCLUSIVE_LOCKS_REQUIRED(mu_, other->mu_) {
1874 this->data = other->data;
1875 }
1876
1877 template <class T2>
1878 void fooExT(CellDelayed<T2> *otherT) EXCLUSIVE_LOCKS_REQUIRED(mu_, otherT->mu_) {
1879 this->data = otherT->data;
1880 }
1881
1882 void foo() {
1883 mu_.Lock();
1884 data = 0;
1885 mu_.Unlock();
1886 }
1887
1888 Mutex mu_;
DeLesley Hutchinsdd5756c2012-02-16 17:30:51 +00001889 static Mutex static_mu_;
DeLesley Hutchins23323e02012-01-20 22:50:54 +00001890};
1891
1892void testDelayed() {
1893 CellDelayed<int> celld;
1894 CellDelayed<int> celld2;
1895 celld.foo();
1896 celld.mu_.Lock();
1897 celld2.mu_.Lock();
1898
1899 celld.fooEx(&celld2);
1900 celld.fooExT(&celld2);
1901
1902 celld2.mu_.Unlock();
1903 celld.mu_.Unlock();
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +00001904}
1905
1906}; // end namespace TestTemplateAttributeInstantiation
1907
1908
DeLesley Hutchinse03b2b32012-01-20 23:24:41 +00001909namespace FunctionDeclDefTest {
1910
1911class Foo {
1912public:
1913 Mutex mu_;
1914 int a GUARDED_BY(mu_);
1915
1916 virtual void foo1(Foo *f_declared) EXCLUSIVE_LOCKS_REQUIRED(f_declared->mu_);
1917};
1918
1919// EXCLUSIVE_LOCKS_REQUIRED should be applied, and rewritten to f_defined->mu_
1920void Foo::foo1(Foo *f_defined) {
1921 f_defined->a = 0;
1922};
1923
1924void test() {
1925 Foo myfoo;
1926 myfoo.foo1(&myfoo); // \
DeLesley Hutchinsa74b7152012-08-10 20:19:55 +00001927 // expected-warning {{calling function 'foo1' requires exclusive lock on 'myfoo.mu_'}}
DeLesley Hutchinse03b2b32012-01-20 23:24:41 +00001928 myfoo.mu_.Lock();
1929 myfoo.foo1(&myfoo);
1930 myfoo.mu_.Unlock();
1931}
1932
1933};
Richard Smith2e515622012-02-03 04:45:26 +00001934
1935namespace GoingNative {
1936
1937 struct __attribute__((lockable)) mutex {
1938 void lock() __attribute__((exclusive_lock_function));
1939 void unlock() __attribute__((unlock_function));
1940 // ...
1941 };
1942 bool foo();
1943 bool bar();
1944 mutex m;
1945 void test() {
1946 m.lock();
1947 while (foo()) {
1948 m.unlock();
1949 // ...
1950 if (bar()) {
1951 // ...
1952 if (foo())
1953 continue; // expected-warning {{expecting mutex 'm' to be locked at start of each loop}}
1954 //...
1955 }
1956 // ...
1957 m.lock(); // expected-note {{mutex acquired here}}
1958 }
1959 m.unlock();
1960 }
1961
1962}
DeLesley Hutchinsc24a2332012-02-16 16:50:43 +00001963
1964
1965
1966namespace FunctionDefinitionTest {
1967
1968class Foo {
1969public:
1970 void foo1();
1971 void foo2();
1972 void foo3(Foo *other);
1973
1974 template<class T>
1975 void fooT1(const T& dummy1);
1976
1977 template<class T>
1978 void fooT2(const T& dummy2) EXCLUSIVE_LOCKS_REQUIRED(mu_);
1979
1980 Mutex mu_;
1981 int a GUARDED_BY(mu_);
1982};
1983
1984template<class T>
1985class FooT {
1986public:
1987 void foo();
1988
1989 Mutex mu_;
1990 T a GUARDED_BY(mu_);
1991};
1992
1993
1994void Foo::foo1() NO_THREAD_SAFETY_ANALYSIS {
1995 a = 1;
1996}
1997
1998void Foo::foo2() EXCLUSIVE_LOCKS_REQUIRED(mu_) {
1999 a = 2;
2000}
2001
2002void Foo::foo3(Foo *other) EXCLUSIVE_LOCKS_REQUIRED(other->mu_) {
2003 other->a = 3;
2004}
2005
2006template<class T>
2007void Foo::fooT1(const T& dummy1) EXCLUSIVE_LOCKS_REQUIRED(mu_) {
2008 a = dummy1;
2009}
2010
2011/* TODO -- uncomment with template instantiation of attributes.
2012template<class T>
2013void Foo::fooT2(const T& dummy2) {
2014 a = dummy2;
2015}
2016*/
2017
2018void fooF1(Foo *f) EXCLUSIVE_LOCKS_REQUIRED(f->mu_) {
2019 f->a = 1;
2020}
2021
2022void fooF2(Foo *f);
2023void fooF2(Foo *f) EXCLUSIVE_LOCKS_REQUIRED(f->mu_) {
2024 f->a = 2;
2025}
2026
2027void fooF3(Foo *f) EXCLUSIVE_LOCKS_REQUIRED(f->mu_);
2028void fooF3(Foo *f) {
2029 f->a = 3;
2030}
2031
2032template<class T>
2033void FooT<T>::foo() EXCLUSIVE_LOCKS_REQUIRED(mu_) {
2034 a = 0;
2035}
2036
2037void test() {
2038 int dummy = 0;
2039 Foo myFoo;
2040
2041 myFoo.foo2(); // \
DeLesley Hutchinsa74b7152012-08-10 20:19:55 +00002042 // expected-warning {{calling function 'foo2' requires exclusive lock on 'myFoo.mu_'}}
DeLesley Hutchinsc24a2332012-02-16 16:50:43 +00002043 myFoo.foo3(&myFoo); // \
DeLesley Hutchinsa74b7152012-08-10 20:19:55 +00002044 // expected-warning {{calling function 'foo3' requires exclusive lock on 'myFoo.mu_'}}
DeLesley Hutchinsc24a2332012-02-16 16:50:43 +00002045 myFoo.fooT1(dummy); // \
DeLesley Hutchinsa74b7152012-08-10 20:19:55 +00002046 // expected-warning {{calling function 'fooT1' requires exclusive lock on 'myFoo.mu_'}}
DeLesley Hutchinsc24a2332012-02-16 16:50:43 +00002047
DeLesley Hutchinsa74b7152012-08-10 20:19:55 +00002048 myFoo.fooT2(dummy); // \
2049 // expected-warning {{calling function 'fooT2' requires exclusive lock on 'myFoo.mu_'}}
DeLesley Hutchinsc24a2332012-02-16 16:50:43 +00002050
2051 fooF1(&myFoo); // \
DeLesley Hutchinsa74b7152012-08-10 20:19:55 +00002052 // expected-warning {{calling function 'fooF1' requires exclusive lock on 'myFoo.mu_'}}
DeLesley Hutchinsc24a2332012-02-16 16:50:43 +00002053 fooF2(&myFoo); // \
DeLesley Hutchinsa74b7152012-08-10 20:19:55 +00002054 // expected-warning {{calling function 'fooF2' requires exclusive lock on 'myFoo.mu_'}}
DeLesley Hutchinsc24a2332012-02-16 16:50:43 +00002055 fooF3(&myFoo); // \
DeLesley Hutchinsa74b7152012-08-10 20:19:55 +00002056 // expected-warning {{calling function 'fooF3' requires exclusive lock on 'myFoo.mu_'}}
DeLesley Hutchinsc24a2332012-02-16 16:50:43 +00002057
2058 myFoo.mu_.Lock();
2059 myFoo.foo2();
2060 myFoo.foo3(&myFoo);
2061 myFoo.fooT1(dummy);
2062
DeLesley Hutchinsa74b7152012-08-10 20:19:55 +00002063 myFoo.fooT2(dummy);
DeLesley Hutchinsc24a2332012-02-16 16:50:43 +00002064
2065 fooF1(&myFoo);
2066 fooF2(&myFoo);
2067 fooF3(&myFoo);
2068 myFoo.mu_.Unlock();
2069
2070 FooT<int> myFooT;
2071 myFooT.foo(); // \
DeLesley Hutchinsa74b7152012-08-10 20:19:55 +00002072 // expected-warning {{calling function 'foo' requires exclusive lock on 'myFooT.mu_'}}
DeLesley Hutchinsc24a2332012-02-16 16:50:43 +00002073}
2074
DeLesley Hutchins4bda3ec2012-02-16 17:03:24 +00002075} // end namespace FunctionDefinitionTest
2076
2077
2078namespace SelfLockingTest {
2079
2080class LOCKABLE MyLock {
2081public:
2082 int foo GUARDED_BY(this);
2083
2084 void lock() EXCLUSIVE_LOCK_FUNCTION();
2085 void unlock() UNLOCK_FUNCTION();
2086
2087 void doSomething() {
2088 this->lock(); // allow 'this' as a lock expression
2089 foo = 0;
2090 doSomethingElse();
2091 this->unlock();
2092 }
2093
2094 void doSomethingElse() EXCLUSIVE_LOCKS_REQUIRED(this) {
2095 foo = 1;
2096 };
2097
2098 void test() {
2099 foo = 2; // \
2100 // expected-warning {{writing variable 'foo' requires locking 'this' exclusively}}
2101 }
DeLesley Hutchinsc24a2332012-02-16 16:50:43 +00002102};
2103
DeLesley Hutchins2f13bec2012-02-16 17:13:43 +00002104
2105class LOCKABLE MyLock2 {
2106public:
2107 Mutex mu_;
2108 int foo GUARDED_BY(this);
2109
2110 // don't check inside lock and unlock functions
2111 void lock() EXCLUSIVE_LOCK_FUNCTION() { mu_.Lock(); }
2112 void unlock() UNLOCK_FUNCTION() { mu_.Unlock(); }
2113
2114 // don't check inside constructors and destructors
2115 MyLock2() { foo = 1; }
2116 ~MyLock2() { foo = 0; }
2117};
2118
2119
DeLesley Hutchins4bda3ec2012-02-16 17:03:24 +00002120} // end namespace SelfLockingTest
2121
2122
DeLesley Hutchinsd08d5992012-02-25 00:11:55 +00002123namespace InvalidNonstatic {
2124
2125// Forward decl here causes bogus "invalid use of non-static data member"
2126// on reference to mutex_ in guarded_by attribute.
2127class Foo;
2128
2129class Foo {
2130 Mutex* mutex_;
2131
2132 int foo __attribute__((guarded_by(mutex_)));
2133};
2134
2135} // end namespace InvalidNonStatic
2136
DeLesley Hutchins2a35be82012-03-02 22:02:58 +00002137
2138namespace NoReturnTest {
2139
2140bool condition();
2141void fatal() __attribute__((noreturn));
2142
2143Mutex mu_;
2144
2145void test1() {
2146 MutexLock lock(&mu_);
2147 if (condition()) {
2148 fatal();
2149 return;
2150 }
2151}
2152
DeLesley Hutchins2287c5e2012-03-02 22:12:59 +00002153} // end namespace NoReturnTest
2154
2155
2156namespace TestMultiDecl {
2157
2158class Foo {
2159public:
2160 int GUARDED_BY(mu_) a;
2161 int GUARDED_BY(mu_) b, c;
2162
2163 void foo() {
2164 a = 0; // \
2165 // expected-warning {{writing variable 'a' requires locking 'mu_' exclusively}}
2166 b = 0; // \
2167 // expected-warning {{writing variable 'b' requires locking 'mu_' exclusively}}
2168 c = 0; // \
2169 // expected-warning {{writing variable 'c' requires locking 'mu_' exclusively}}
2170 }
2171
2172private:
2173 Mutex mu_;
DeLesley Hutchins2a35be82012-03-02 22:02:58 +00002174};
DeLesley Hutchins2287c5e2012-03-02 22:12:59 +00002175
2176} // end namespace TestMultiDecl
2177
DeLesley Hutchins7ec419a2012-03-02 22:29:50 +00002178
2179namespace WarnNoDecl {
2180
2181class Foo {
2182 void foo(int a); __attribute__(( // \
2183 // expected-warning {{declaration does not declare anything}}
2184 exclusive_locks_required(a))); // \
2185 // expected-warning {{attribute exclusive_locks_required ignored}}
2186};
2187
2188} // end namespace WarnNoDecl
2189
2190
DeLesley Hutchins0d95dfc2012-03-02 23:36:05 +00002191
2192namespace MoreLockExpressions {
2193
2194class Foo {
2195public:
2196 Mutex mu_;
2197 int a GUARDED_BY(mu_);
2198};
2199
2200class Bar {
2201public:
2202 int b;
2203 Foo* f;
2204
2205 Foo& getFoo() { return *f; }
2206 Foo& getFoo2(int c) { return *f; }
2207 Foo& getFoo3(int c, int d) { return *f; }
2208
2209 Foo& getFooey() { return *f; }
2210};
2211
2212Foo& getBarFoo(Bar &bar, int c) { return bar.getFoo2(c); }
2213
2214void test() {
2215 Foo foo;
2216 Foo *fooArray;
2217 Bar bar;
2218 int a;
2219 int b;
2220 int c;
2221
2222 bar.getFoo().mu_.Lock();
2223 bar.getFoo().a = 0;
2224 bar.getFoo().mu_.Unlock();
2225
2226 (bar.getFoo().mu_).Lock(); // test parenthesis
2227 bar.getFoo().a = 0;
2228 (bar.getFoo().mu_).Unlock();
2229
2230 bar.getFoo2(a).mu_.Lock();
2231 bar.getFoo2(a).a = 0;
2232 bar.getFoo2(a).mu_.Unlock();
2233
2234 bar.getFoo3(a, b).mu_.Lock();
2235 bar.getFoo3(a, b).a = 0;
2236 bar.getFoo3(a, b).mu_.Unlock();
2237
2238 getBarFoo(bar, a).mu_.Lock();
2239 getBarFoo(bar, a).a = 0;
2240 getBarFoo(bar, a).mu_.Unlock();
2241
2242 bar.getFoo2(10).mu_.Lock();
2243 bar.getFoo2(10).a = 0;
2244 bar.getFoo2(10).mu_.Unlock();
2245
2246 bar.getFoo2(a + 1).mu_.Lock();
2247 bar.getFoo2(a + 1).a = 0;
2248 bar.getFoo2(a + 1).mu_.Unlock();
2249
2250 (a > 0 ? fooArray[1] : fooArray[b]).mu_.Lock();
2251 (a > 0 ? fooArray[1] : fooArray[b]).a = 0;
2252 (a > 0 ? fooArray[1] : fooArray[b]).mu_.Unlock();
2253
2254 bar.getFoo().mu_.Lock();
2255 bar.getFooey().a = 0; // \
DeLesley Hutchins3f0ec522012-09-10 19:58:23 +00002256 // expected-warning {{writing variable 'a' requires locking 'bar.getFooey().mu_' exclusively}} \
2257 // expected-note {{found near match 'bar.getFoo().mu_'}}
DeLesley Hutchins0d95dfc2012-03-02 23:36:05 +00002258 bar.getFoo().mu_.Unlock();
2259
2260 bar.getFoo2(a).mu_.Lock();
2261 bar.getFoo2(b).a = 0; // \
DeLesley Hutchins3f0ec522012-09-10 19:58:23 +00002262 // expected-warning {{writing variable 'a' requires locking 'bar.getFoo2(b).mu_' exclusively}} \
2263 // expected-note {{found near match 'bar.getFoo2(a).mu_'}}
DeLesley Hutchins0d95dfc2012-03-02 23:36:05 +00002264 bar.getFoo2(a).mu_.Unlock();
2265
2266 bar.getFoo3(a, b).mu_.Lock();
2267 bar.getFoo3(a, c).a = 0; // \
DeLesley Hutchins3f0ec522012-09-10 19:58:23 +00002268 // expected-warning {{writing variable 'a' requires locking 'bar.getFoo3(a,c).mu_' exclusively}} \
2269 // expected-note {{'bar.getFoo3(a,b).mu_'}}
DeLesley Hutchins0d95dfc2012-03-02 23:36:05 +00002270 bar.getFoo3(a, b).mu_.Unlock();
2271
2272 getBarFoo(bar, a).mu_.Lock();
2273 getBarFoo(bar, b).a = 0; // \
DeLesley Hutchins3f0ec522012-09-10 19:58:23 +00002274 // expected-warning {{writing variable 'a' requires locking 'getBarFoo(bar,b).mu_' exclusively}} \
2275 // expected-note {{'getBarFoo(bar,a).mu_'}}
DeLesley Hutchins0d95dfc2012-03-02 23:36:05 +00002276 getBarFoo(bar, a).mu_.Unlock();
2277
2278 (a > 0 ? fooArray[1] : fooArray[b]).mu_.Lock();
2279 (a > 0 ? fooArray[b] : fooArray[c]).a = 0; // \
DeLesley Hutchins3f0ec522012-09-10 19:58:23 +00002280 // expected-warning {{writing variable 'a' requires locking '((a#_)#_#fooArray[b]).mu_' exclusively}} \
2281 // expected-note {{'((a#_)#_#fooArray[_]).mu_'}}
DeLesley Hutchins0d95dfc2012-03-02 23:36:05 +00002282 (a > 0 ? fooArray[1] : fooArray[b]).mu_.Unlock();
2283}
2284
2285
DeLesley Hutchins0da44142012-06-22 17:07:28 +00002286} // end namespace MoreLockExpressions
2287
2288
2289namespace TrylockJoinPoint {
2290
2291class Foo {
2292 Mutex mu;
2293 bool c;
2294
2295 void foo() {
2296 if (c) {
2297 if (!mu.TryLock())
2298 return;
2299 } else {
2300 mu.Lock();
2301 }
2302 mu.Unlock();
2303 }
2304};
2305
2306} // end namespace TrylockJoinPoint
DeLesley Hutchins0d95dfc2012-03-02 23:36:05 +00002307
2308
DeLesley Hutchinsf63797c2012-06-25 18:33:18 +00002309namespace LockReturned {
2310
2311class Foo {
2312public:
2313 int a GUARDED_BY(mu_);
2314 void foo() EXCLUSIVE_LOCKS_REQUIRED(mu_);
2315 void foo2(Foo* f) EXCLUSIVE_LOCKS_REQUIRED(mu_, f->mu_);
2316
2317 static void sfoo(Foo* f) EXCLUSIVE_LOCKS_REQUIRED(f->mu_);
2318
2319 Mutex* getMu() LOCK_RETURNED(mu_);
2320
2321 Mutex mu_;
2322
2323 static Mutex* getMu(Foo* f) LOCK_RETURNED(f->mu_);
2324};
2325
2326
2327// Calls getMu() directly to lock and unlock
2328void test1(Foo* f1, Foo* f2) {
DeLesley Hutchinsa74b7152012-08-10 20:19:55 +00002329 f1->a = 0; // expected-warning {{writing variable 'a' requires locking 'f1->mu_' exclusively}}
2330 f1->foo(); // expected-warning {{calling function 'foo' requires exclusive lock on 'f1->mu_'}}
DeLesley Hutchinsf63797c2012-06-25 18:33:18 +00002331
DeLesley Hutchinsa74b7152012-08-10 20:19:55 +00002332 f1->foo2(f2); // expected-warning {{calling function 'foo2' requires exclusive lock on 'f1->mu_'}} \
2333 // expected-warning {{calling function 'foo2' requires exclusive lock on 'f2->mu_'}}
2334 Foo::sfoo(f1); // expected-warning {{calling function 'sfoo' requires exclusive lock on 'f1->mu_'}}
DeLesley Hutchinsf63797c2012-06-25 18:33:18 +00002335
2336 f1->getMu()->Lock();
2337
2338 f1->a = 0;
2339 f1->foo();
DeLesley Hutchins3f0ec522012-09-10 19:58:23 +00002340 f1->foo2(f2); // \
2341 // expected-warning {{calling function 'foo2' requires exclusive lock on 'f2->mu_'}} \
2342 // expected-note {{found near match 'f1->mu_'}}
DeLesley Hutchinsf63797c2012-06-25 18:33:18 +00002343
2344 Foo::getMu(f2)->Lock();
2345 f1->foo2(f2);
2346 Foo::getMu(f2)->Unlock();
2347
2348 Foo::sfoo(f1);
2349
2350 f1->getMu()->Unlock();
2351}
2352
2353
2354Mutex* getFooMu(Foo* f) LOCK_RETURNED(Foo::getMu(f));
2355
2356class Bar : public Foo {
2357public:
2358 int b GUARDED_BY(getMu());
2359 void bar() EXCLUSIVE_LOCKS_REQUIRED(getMu());
2360 void bar2(Bar* g) EXCLUSIVE_LOCKS_REQUIRED(getMu(this), g->getMu());
2361
2362 static void sbar(Bar* g) EXCLUSIVE_LOCKS_REQUIRED(g->getMu());
2363 static void sbar2(Bar* g) EXCLUSIVE_LOCKS_REQUIRED(getFooMu(g));
2364};
2365
2366
2367
2368// Use getMu() within other attributes.
2369// This requires at lest levels of substitution, more in the case of
2370void test2(Bar* b1, Bar* b2) {
DeLesley Hutchinsa74b7152012-08-10 20:19:55 +00002371 b1->b = 0; // expected-warning {{writing variable 'b' requires locking 'b1->mu_' exclusively}}
2372 b1->bar(); // expected-warning {{calling function 'bar' requires exclusive lock on 'b1->mu_'}}
2373 b1->bar2(b2); // expected-warning {{calling function 'bar2' requires exclusive lock on 'b1->mu_'}} \
2374 // expected-warning {{calling function 'bar2' requires exclusive lock on 'b2->mu_'}}
2375 Bar::sbar(b1); // expected-warning {{calling function 'sbar' requires exclusive lock on 'b1->mu_'}}
2376 Bar::sbar2(b1); // expected-warning {{calling function 'sbar2' requires exclusive lock on 'b1->mu_'}}
DeLesley Hutchinsf63797c2012-06-25 18:33:18 +00002377
2378 b1->getMu()->Lock();
2379
2380 b1->b = 0;
2381 b1->bar();
DeLesley Hutchins3f0ec522012-09-10 19:58:23 +00002382 b1->bar2(b2); // \
2383 // expected-warning {{calling function 'bar2' requires exclusive lock on 'b2->mu_'}} \
2384 // // expected-note {{found near match 'b1->mu_'}}
DeLesley Hutchinsf63797c2012-06-25 18:33:18 +00002385
2386 b2->getMu()->Lock();
2387 b1->bar2(b2);
2388
2389 b2->getMu()->Unlock();
2390
2391 Bar::sbar(b1);
2392 Bar::sbar2(b1);
2393
2394 b1->getMu()->Unlock();
2395}
2396
2397
2398// Sanity check -- lock the mutex directly, but use attributes that call getMu()
2399// Also lock the mutex using getFooMu, which calls a lock_returned function.
2400void test3(Bar* b1, Bar* b2) {
2401 b1->mu_.Lock();
2402 b1->b = 0;
2403 b1->bar();
2404
2405 getFooMu(b2)->Lock();
2406 b1->bar2(b2);
2407 getFooMu(b2)->Unlock();
2408
2409 Bar::sbar(b1);
2410 Bar::sbar2(b1);
2411
2412 b1->mu_.Unlock();
2413}
2414
2415} // end namespace LockReturned
2416
2417
DeLesley Hutchinsc99a5d82012-06-28 22:42:48 +00002418namespace ReleasableScopedLock {
2419
2420class Foo {
2421 Mutex mu_;
2422 bool c;
2423 int a GUARDED_BY(mu_);
2424
2425 void test1();
2426 void test2();
2427 void test3();
DeLesley Hutchins5381c052012-07-05 21:16:29 +00002428 void test4();
2429 void test5();
DeLesley Hutchinsc99a5d82012-06-28 22:42:48 +00002430};
2431
2432
2433void Foo::test1() {
2434 ReleasableMutexLock rlock(&mu_);
2435 rlock.Release();
2436}
2437
2438void Foo::test2() {
2439 ReleasableMutexLock rlock(&mu_);
2440 if (c) { // test join point -- held/not held during release
2441 rlock.Release();
2442 }
2443}
2444
2445void Foo::test3() {
2446 ReleasableMutexLock rlock(&mu_);
2447 a = 0;
2448 rlock.Release();
2449 a = 1; // expected-warning {{writing variable 'a' requires locking 'mu_' exclusively}}
2450}
2451
DeLesley Hutchins5381c052012-07-05 21:16:29 +00002452void Foo::test4() {
2453 ReleasableMutexLock rlock(&mu_);
2454 rlock.Release();
2455 rlock.Release(); // expected-warning {{unlocking 'mu_' that was not locked}}
2456}
2457
2458void Foo::test5() {
2459 ReleasableMutexLock rlock(&mu_);
2460 if (c) {
2461 rlock.Release();
2462 }
2463 // no warning on join point for managed lock.
2464 rlock.Release(); // expected-warning {{unlocking 'mu_' that was not locked}}
2465}
2466
2467
DeLesley Hutchinsc99a5d82012-06-28 22:42:48 +00002468} // end namespace ReleasableScopedLock
2469
2470
DeLesley Hutchins76f0a6e2012-07-02 21:59:24 +00002471namespace TrylockFunctionTest {
2472
2473class Foo {
2474public:
2475 Mutex mu1_;
2476 Mutex mu2_;
2477 bool c;
2478
2479 bool lockBoth() EXCLUSIVE_TRYLOCK_FUNCTION(true, mu1_, mu2_);
2480};
2481
2482bool Foo::lockBoth() {
2483 if (!mu1_.TryLock())
2484 return false;
2485
2486 mu2_.Lock();
2487 if (!c) {
2488 mu1_.Unlock();
2489 mu2_.Unlock();
2490 return false;
2491 }
2492
2493 return true;
2494}
2495
2496
2497} // end namespace TrylockFunctionTest
DeLesley Hutchinsc99a5d82012-06-28 22:42:48 +00002498
2499
2500
DeLesley Hutchinsc36eda12012-07-02 22:12:12 +00002501namespace DoubleLockBug {
2502
2503class Foo {
2504public:
2505 Mutex mu_;
2506 int a GUARDED_BY(mu_);
2507
DeLesley Hutchins5381c052012-07-05 21:16:29 +00002508 void foo1() EXCLUSIVE_LOCKS_REQUIRED(mu_);
2509 int foo2() SHARED_LOCKS_REQUIRED(mu_);
DeLesley Hutchinsc36eda12012-07-02 22:12:12 +00002510};
2511
2512
DeLesley Hutchins5381c052012-07-05 21:16:29 +00002513void Foo::foo1() EXCLUSIVE_LOCKS_REQUIRED(mu_) {
DeLesley Hutchinsc36eda12012-07-02 22:12:12 +00002514 a = 0;
2515}
2516
DeLesley Hutchins5381c052012-07-05 21:16:29 +00002517int Foo::foo2() SHARED_LOCKS_REQUIRED(mu_) {
2518 return a;
2519}
2520
2521}
2522
DeLesley Hutchinsc36eda12012-07-02 22:12:12 +00002523
2524
DeLesley Hutchins879a4332012-07-02 22:16:54 +00002525namespace UnlockBug {
DeLesley Hutchinsc36eda12012-07-02 22:12:12 +00002526
DeLesley Hutchins879a4332012-07-02 22:16:54 +00002527class Foo {
2528public:
2529 Mutex mutex_;
2530
2531 void foo1() EXCLUSIVE_LOCKS_REQUIRED(mutex_) { // expected-note {{mutex acquired here}}
2532 mutex_.Unlock();
2533 } // expected-warning {{expecting mutex 'mutex_' to be locked at the end of function}}
2534
2535
2536 void foo2() SHARED_LOCKS_REQUIRED(mutex_) { // expected-note {{mutex acquired here}}
2537 mutex_.Unlock();
2538 } // expected-warning {{expecting mutex 'mutex_' to be locked at the end of function}}
2539};
2540
2541} // end namespace UnlockBug
DeLesley Hutchinsc36eda12012-07-02 22:12:12 +00002542
DeLesley Hutchinsc99a5d82012-06-28 22:42:48 +00002543
DeLesley Hutchins5381c052012-07-05 21:16:29 +00002544
DeLesley Hutchinsbbe33412012-07-02 22:26:29 +00002545namespace FoolishScopedLockableBug {
2546
2547class SCOPED_LOCKABLE WTF_ScopedLockable {
2548public:
2549 WTF_ScopedLockable(Mutex* mu) EXCLUSIVE_LOCK_FUNCTION(mu);
2550
2551 // have to call release() manually;
2552 ~WTF_ScopedLockable();
2553
2554 void release() UNLOCK_FUNCTION();
2555};
2556
2557
2558class Foo {
2559 Mutex mu_;
2560 int a GUARDED_BY(mu_);
2561 bool c;
2562
2563 void doSomething();
2564
2565 void test1() {
2566 WTF_ScopedLockable wtf(&mu_);
2567 wtf.release();
2568 }
2569
2570 void test2() {
2571 WTF_ScopedLockable wtf(&mu_); // expected-note {{mutex acquired here}}
2572 } // expected-warning {{mutex 'mu_' is still locked at the end of function}}
2573
2574 void test3() {
2575 if (c) {
2576 WTF_ScopedLockable wtf(&mu_);
2577 wtf.release();
2578 }
2579 }
2580
2581 void test4() {
2582 if (c) {
2583 doSomething();
2584 }
2585 else {
2586 WTF_ScopedLockable wtf(&mu_);
2587 wtf.release();
2588 }
2589 }
2590
2591 void test5() {
2592 if (c) {
2593 WTF_ScopedLockable wtf(&mu_); // expected-note {{mutex acquired here}}
2594 }
2595 } // expected-warning {{mutex 'mu_' is not locked on every path through here}}
2596
2597 void test6() {
2598 if (c) {
2599 doSomething();
2600 }
2601 else {
2602 WTF_ScopedLockable wtf(&mu_); // expected-note {{mutex acquired here}}
2603 }
2604 } // expected-warning {{mutex 'mu_' is not locked on every path through here}}
2605};
2606
2607
2608} // end namespace FoolishScopedLockableBug
2609
DeLesley Hutchins9d6e7f32012-07-03 18:25:56 +00002610
DeLesley Hutchins5381c052012-07-05 21:16:29 +00002611
DeLesley Hutchins9d6e7f32012-07-03 18:25:56 +00002612namespace TemporaryCleanupExpr {
2613
2614class Foo {
2615 int a GUARDED_BY(getMutexPtr().get());
2616
2617 SmartPtr<Mutex> getMutexPtr();
2618
2619 void test();
2620};
2621
2622
2623void Foo::test() {
2624 {
2625 ReaderMutexLock lock(getMutexPtr().get());
2626 int b = a;
DeLesley Hutchins96fac6a2012-07-03 19:47:18 +00002627 }
DeLesley Hutchinsa74b7152012-08-10 20:19:55 +00002628 int b = a; // expected-warning {{reading variable 'a' requires locking 'getMutexPtr()'}}
DeLesley Hutchins9d6e7f32012-07-03 18:25:56 +00002629}
2630
2631} // end namespace TemporaryCleanupExpr
2632
2633
DeLesley Hutchins96fac6a2012-07-03 19:47:18 +00002634
2635namespace SmartPointerTests {
2636
2637class Foo {
2638public:
2639 SmartPtr<Mutex> mu_;
2640 int a GUARDED_BY(mu_);
2641 int b GUARDED_BY(mu_.get());
2642 int c GUARDED_BY(*mu_);
2643
2644 void Lock() EXCLUSIVE_LOCK_FUNCTION(mu_);
2645 void Unlock() UNLOCK_FUNCTION(mu_);
2646
2647 void test0();
2648 void test1();
2649 void test2();
2650 void test3();
2651 void test4();
2652 void test5();
2653 void test6();
2654 void test7();
2655 void test8();
2656};
2657
2658void Foo::test0() {
2659 a = 0; // expected-warning {{writing variable 'a' requires locking 'mu_' exclusively}}
2660 b = 0; // expected-warning {{writing variable 'b' requires locking 'mu_' exclusively}}
2661 c = 0; // expected-warning {{writing variable 'c' requires locking 'mu_' exclusively}}
2662}
2663
2664void Foo::test1() {
2665 mu_->Lock();
2666 a = 0;
2667 b = 0;
2668 c = 0;
2669 mu_->Unlock();
2670}
2671
2672void Foo::test2() {
2673 (*mu_).Lock();
2674 a = 0;
2675 b = 0;
2676 c = 0;
2677 (*mu_).Unlock();
2678}
2679
2680
2681void Foo::test3() {
2682 mu_.get()->Lock();
2683 a = 0;
2684 b = 0;
2685 c = 0;
2686 mu_.get()->Unlock();
2687}
2688
2689
2690void Foo::test4() {
2691 MutexLock lock(mu_.get());
2692 a = 0;
2693 b = 0;
2694 c = 0;
2695}
2696
2697
2698void Foo::test5() {
2699 MutexLock lock(&(*mu_));
2700 a = 0;
2701 b = 0;
2702 c = 0;
2703}
2704
2705
2706void Foo::test6() {
2707 Lock();
2708 a = 0;
2709 b = 0;
2710 c = 0;
2711 Unlock();
2712}
2713
2714
2715void Foo::test7() {
2716 {
2717 Lock();
2718 mu_->Unlock();
2719 }
2720 {
2721 mu_->Lock();
2722 Unlock();
2723 }
2724 {
2725 mu_.get()->Lock();
2726 mu_->Unlock();
2727 }
2728 {
2729 mu_->Lock();
2730 mu_.get()->Unlock();
2731 }
2732 {
2733 mu_.get()->Lock();
2734 (*mu_).Unlock();
2735 }
2736 {
2737 (*mu_).Lock();
2738 mu_->Unlock();
2739 }
2740}
2741
2742
2743void Foo::test8() {
2744 mu_->Lock();
2745 mu_.get()->Lock(); // expected-warning {{locking 'mu_' that is already locked}}
2746 (*mu_).Lock(); // expected-warning {{locking 'mu_' that is already locked}}
2747 mu_.get()->Unlock();
2748 Unlock(); // expected-warning {{unlocking 'mu_' that was not locked}}
2749}
2750
2751
2752class Bar {
2753 SmartPtr<Foo> foo;
2754
2755 void test0();
2756 void test1();
2757 void test2();
2758 void test3();
2759};
2760
2761
2762void Bar::test0() {
DeLesley Hutchinsa74b7152012-08-10 20:19:55 +00002763 foo->a = 0; // expected-warning {{writing variable 'a' requires locking 'foo->mu_' exclusively}}
2764 (*foo).b = 0; // expected-warning {{writing variable 'b' requires locking 'foo->mu_' exclusively}}
2765 foo.get()->c = 0; // expected-warning {{writing variable 'c' requires locking 'foo->mu_' exclusively}}
DeLesley Hutchins96fac6a2012-07-03 19:47:18 +00002766}
2767
2768
2769void Bar::test1() {
2770 foo->mu_->Lock();
2771 foo->a = 0;
2772 (*foo).b = 0;
2773 foo.get()->c = 0;
2774 foo->mu_->Unlock();
2775}
2776
2777
2778void Bar::test2() {
2779 (*foo).mu_->Lock();
2780 foo->a = 0;
2781 (*foo).b = 0;
2782 foo.get()->c = 0;
2783 foo.get()->mu_->Unlock();
2784}
2785
2786
2787void Bar::test3() {
2788 MutexLock lock(foo->mu_.get());
2789 foo->a = 0;
2790 (*foo).b = 0;
2791 foo.get()->c = 0;
2792}
2793
2794} // end namespace SmartPointerTests
2795
2796
2797
DeLesley Hutchins5381c052012-07-05 21:16:29 +00002798namespace DuplicateAttributeTest {
2799
2800class LOCKABLE Foo {
2801public:
2802 Mutex mu1_;
2803 Mutex mu2_;
2804 Mutex mu3_;
2805 int a GUARDED_BY(mu1_);
2806 int b GUARDED_BY(mu2_);
2807 int c GUARDED_BY(mu3_);
2808
2809 void lock() EXCLUSIVE_LOCK_FUNCTION();
2810 void unlock() UNLOCK_FUNCTION();
2811
2812 void lock1() EXCLUSIVE_LOCK_FUNCTION(mu1_);
2813 void slock1() SHARED_LOCK_FUNCTION(mu1_);
2814 void lock3() EXCLUSIVE_LOCK_FUNCTION(mu1_, mu2_, mu3_);
2815 void locklots()
2816 EXCLUSIVE_LOCK_FUNCTION(mu1_)
2817 EXCLUSIVE_LOCK_FUNCTION(mu2_)
2818 EXCLUSIVE_LOCK_FUNCTION(mu1_, mu2_, mu3_);
2819
2820 void unlock1() UNLOCK_FUNCTION(mu1_);
2821 void unlock3() UNLOCK_FUNCTION(mu1_, mu2_, mu3_);
2822 void unlocklots()
2823 UNLOCK_FUNCTION(mu1_)
2824 UNLOCK_FUNCTION(mu2_)
2825 UNLOCK_FUNCTION(mu1_, mu2_, mu3_);
2826};
2827
2828
2829void Foo::lock() EXCLUSIVE_LOCK_FUNCTION() { }
2830void Foo::unlock() UNLOCK_FUNCTION() { }
2831
2832void Foo::lock1() EXCLUSIVE_LOCK_FUNCTION(mu1_) {
2833 mu1_.Lock();
2834}
2835
2836void Foo::slock1() SHARED_LOCK_FUNCTION(mu1_) {
2837 mu1_.Lock();
2838}
2839
2840void Foo::lock3() EXCLUSIVE_LOCK_FUNCTION(mu1_, mu2_, mu3_) {
2841 mu1_.Lock();
2842 mu2_.Lock();
2843 mu3_.Lock();
2844}
2845
2846void Foo::locklots()
2847 EXCLUSIVE_LOCK_FUNCTION(mu1_, mu2_)
2848 EXCLUSIVE_LOCK_FUNCTION(mu2_, mu3_) {
2849 mu1_.Lock();
2850 mu2_.Lock();
2851 mu3_.Lock();
2852}
2853
2854void Foo::unlock1() UNLOCK_FUNCTION(mu1_) {
2855 mu1_.Unlock();
2856}
2857
2858void Foo::unlock3() UNLOCK_FUNCTION(mu1_, mu2_, mu3_) {
2859 mu1_.Unlock();
2860 mu2_.Unlock();
2861 mu3_.Unlock();
2862}
2863
2864void Foo::unlocklots()
2865 UNLOCK_FUNCTION(mu1_, mu2_)
2866 UNLOCK_FUNCTION(mu2_, mu3_) {
2867 mu1_.Unlock();
2868 mu2_.Unlock();
2869 mu3_.Unlock();
2870}
2871
2872
2873void test0() {
2874 Foo foo;
2875 foo.lock();
2876 foo.unlock();
2877
2878 foo.lock();
2879 foo.lock(); // expected-warning {{locking 'foo' that is already locked}}
2880 foo.unlock();
2881 foo.unlock(); // expected-warning {{unlocking 'foo' that was not locked}}
2882}
2883
2884
2885void test1() {
2886 Foo foo;
2887 foo.lock1();
2888 foo.a = 0;
2889 foo.unlock1();
2890
2891 foo.lock1();
DeLesley Hutchinsa74b7152012-08-10 20:19:55 +00002892 foo.lock1(); // expected-warning {{locking 'foo.mu1_' that is already locked}}
DeLesley Hutchins5381c052012-07-05 21:16:29 +00002893 foo.a = 0;
2894 foo.unlock1();
DeLesley Hutchinsa74b7152012-08-10 20:19:55 +00002895 foo.unlock1(); // expected-warning {{unlocking 'foo.mu1_' that was not locked}}
DeLesley Hutchins5381c052012-07-05 21:16:29 +00002896}
2897
2898
2899int test2() {
2900 Foo foo;
2901 foo.slock1();
2902 int d1 = foo.a;
2903 foo.unlock1();
2904
2905 foo.slock1();
DeLesley Hutchinsa74b7152012-08-10 20:19:55 +00002906 foo.slock1(); // expected-warning {{locking 'foo.mu1_' that is already locked}}
DeLesley Hutchins5381c052012-07-05 21:16:29 +00002907 int d2 = foo.a;
2908 foo.unlock1();
DeLesley Hutchinsa74b7152012-08-10 20:19:55 +00002909 foo.unlock1(); // expected-warning {{unlocking 'foo.mu1_' that was not locked}}
DeLesley Hutchins5381c052012-07-05 21:16:29 +00002910 return d1 + d2;
2911}
2912
2913
2914void test3() {
2915 Foo foo;
2916 foo.lock3();
2917 foo.a = 0;
2918 foo.b = 0;
2919 foo.c = 0;
2920 foo.unlock3();
2921
2922 foo.lock3();
2923 foo.lock3(); // \
DeLesley Hutchinsa74b7152012-08-10 20:19:55 +00002924 // expected-warning {{locking 'foo.mu1_' that is already locked}} \
2925 // expected-warning {{locking 'foo.mu2_' that is already locked}} \
2926 // expected-warning {{locking 'foo.mu3_' that is already locked}}
DeLesley Hutchins5381c052012-07-05 21:16:29 +00002927 foo.a = 0;
2928 foo.b = 0;
2929 foo.c = 0;
2930 foo.unlock3();
2931 foo.unlock3(); // \
DeLesley Hutchinsa74b7152012-08-10 20:19:55 +00002932 // expected-warning {{unlocking 'foo.mu1_' that was not locked}} \
2933 // expected-warning {{unlocking 'foo.mu2_' that was not locked}} \
2934 // expected-warning {{unlocking 'foo.mu3_' that was not locked}}
DeLesley Hutchins5381c052012-07-05 21:16:29 +00002935}
2936
2937
2938void testlots() {
2939 Foo foo;
2940 foo.locklots();
2941 foo.a = 0;
2942 foo.b = 0;
2943 foo.c = 0;
2944 foo.unlocklots();
2945
2946 foo.locklots();
2947 foo.locklots(); // \
DeLesley Hutchinsa74b7152012-08-10 20:19:55 +00002948 // expected-warning {{locking 'foo.mu1_' that is already locked}} \
2949 // expected-warning {{locking 'foo.mu2_' that is already locked}} \
2950 // expected-warning {{locking 'foo.mu3_' that is already locked}}
DeLesley Hutchins5381c052012-07-05 21:16:29 +00002951 foo.a = 0;
2952 foo.b = 0;
2953 foo.c = 0;
2954 foo.unlocklots();
2955 foo.unlocklots(); // \
DeLesley Hutchinsa74b7152012-08-10 20:19:55 +00002956 // expected-warning {{unlocking 'foo.mu1_' that was not locked}} \
2957 // expected-warning {{unlocking 'foo.mu2_' that was not locked}} \
2958 // expected-warning {{unlocking 'foo.mu3_' that was not locked}}
DeLesley Hutchins5381c052012-07-05 21:16:29 +00002959}
2960
2961} // end namespace DuplicateAttributeTest
2962
2963
2964
DeLesley Hutchins13106112012-07-10 21:47:55 +00002965namespace TryLockEqTest {
2966
2967class Foo {
2968 Mutex mu_;
2969 int a GUARDED_BY(mu_);
2970 bool c;
2971
2972 int tryLockMutexI() EXCLUSIVE_TRYLOCK_FUNCTION(1, mu_);
2973 Mutex* tryLockMutexP() EXCLUSIVE_TRYLOCK_FUNCTION(1, mu_);
2974 void unlock() UNLOCK_FUNCTION(mu_);
2975
2976 void test1();
2977 void test2();
2978};
2979
2980
2981void Foo::test1() {
2982 if (tryLockMutexP() == 0) {
2983 a = 0; // expected-warning {{writing variable 'a' requires locking 'mu_' exclusively}}
2984 return;
2985 }
2986 a = 0;
2987 unlock();
2988
2989 if (tryLockMutexP() != 0) {
2990 a = 0;
2991 unlock();
2992 }
2993
2994 if (0 != tryLockMutexP()) {
2995 a = 0;
2996 unlock();
2997 }
2998
2999 if (!(tryLockMutexP() == 0)) {
3000 a = 0;
3001 unlock();
3002 }
3003
3004 if (tryLockMutexI() == 0) {
3005 a = 0; // expected-warning {{writing variable 'a' requires locking 'mu_' exclusively}}
3006 return;
3007 }
3008 a = 0;
3009 unlock();
3010
3011 if (0 == tryLockMutexI()) {
3012 a = 0; // expected-warning {{writing variable 'a' requires locking 'mu_' exclusively}}
3013 return;
3014 }
3015 a = 0;
3016 unlock();
3017
3018 if (tryLockMutexI() == 1) {
3019 a = 0;
3020 unlock();
3021 }
3022
3023 if (mu_.TryLock() == false) {
3024 a = 0; // expected-warning {{writing variable 'a' requires locking 'mu_' exclusively}}
3025 return;
3026 }
3027 a = 0;
3028 unlock();
3029
3030 if (mu_.TryLock() == true) {
3031 a = 0;
3032 unlock();
3033 }
3034 else {
3035 a = 0; // expected-warning {{writing variable 'a' requires locking 'mu_' exclusively}}
3036 }
3037
3038#if __has_feature(cxx_nullptr)
3039 if (tryLockMutexP() == nullptr) {
3040 a = 0; // expected-warning {{writing variable 'a' requires locking 'mu_' exclusively}}
3041 return;
3042 }
3043 a = 0;
3044 unlock();
3045#endif
3046}
3047
3048
3049void Foo::test2() {
3050/* FIXME: these tests depend on changes to the CFG.
3051 *
3052 if (mu_.TryLock() && c) {
3053 a = 0;
3054 unlock();
3055 }
3056 else return;
3057
3058 if (c && mu_.TryLock()) {
3059 a = 0;
3060 unlock();
3061 }
3062 else return;
3063
3064 if (!(mu_.TryLock() && c))
3065 return;
3066 a = 0;
3067 unlock();
3068
3069 if (!(c && mu_.TryLock()))
3070 return;
3071 a = 0;
3072 unlock();
3073
3074 if (!(mu_.TryLock() == 0) && c) {
3075 a = 0;
3076 unlock();
3077 }
3078
3079 if (!mu_.TryLock() || c)
3080 return;
3081 a = 0;
3082 unlock();
3083*/
3084}
3085
DeLesley Hutchins13106112012-07-10 21:47:55 +00003086} // end namespace TryLockEqTest
DeLesley Hutchins5381c052012-07-05 21:16:29 +00003087
DeLesley Hutchins96fac6a2012-07-03 19:47:18 +00003088
DeLesley Hutchinsee2f0322012-08-10 20:29:46 +00003089namespace ExistentialPatternMatching {
3090
3091class Graph {
3092public:
3093 Mutex mu_;
3094};
3095
3096void LockAllGraphs() EXCLUSIVE_LOCK_FUNCTION(&Graph::mu_);
3097void UnlockAllGraphs() UNLOCK_FUNCTION(&Graph::mu_);
3098
3099class Node {
3100public:
3101 int a GUARDED_BY(&Graph::mu_);
3102
3103 void foo() EXCLUSIVE_LOCKS_REQUIRED(&Graph::mu_) {
3104 a = 0;
3105 }
3106 void foo2() LOCKS_EXCLUDED(&Graph::mu_);
3107};
3108
3109void test() {
3110 Graph g1;
3111 Graph g2;
3112 Node n1;
3113
3114 n1.a = 0; // expected-warning {{writing variable 'a' requires locking '&ExistentialPatternMatching::Graph::mu_' exclusively}}
3115 n1.foo(); // expected-warning {{calling function 'foo' requires exclusive lock on '&ExistentialPatternMatching::Graph::mu_'}}
3116 n1.foo2();
3117
3118 g1.mu_.Lock();
3119 n1.a = 0;
3120 n1.foo();
3121 n1.foo2(); // expected-warning {{cannot call function 'foo2' while mutex '&ExistentialPatternMatching::Graph::mu_' is locked}}
3122 g1.mu_.Unlock();
3123
3124 g2.mu_.Lock();
3125 n1.a = 0;
3126 n1.foo();
3127 n1.foo2(); // expected-warning {{cannot call function 'foo2' while mutex '&ExistentialPatternMatching::Graph::mu_' is locked}}
3128 g2.mu_.Unlock();
3129
3130 LockAllGraphs();
3131 n1.a = 0;
3132 n1.foo();
3133 n1.foo2(); // expected-warning {{cannot call function 'foo2' while mutex '&ExistentialPatternMatching::Graph::mu_' is locked}}
3134 UnlockAllGraphs();
3135
3136 LockAllGraphs();
3137 g1.mu_.Unlock();
3138
3139 LockAllGraphs();
3140 g2.mu_.Unlock();
3141
3142 LockAllGraphs();
3143 g1.mu_.Lock(); // expected-warning {{locking 'g1.mu_' that is already locked}}
3144 g1.mu_.Unlock();
3145}
3146
3147} // end namespace ExistentialPatternMatching
3148
DeLesley Hutchins4e4c1572012-08-31 21:57:32 +00003149
3150namespace StringIgnoreTest {
3151
3152class Foo {
3153public:
3154 Mutex mu_;
3155 void lock() EXCLUSIVE_LOCK_FUNCTION("");
3156 void unlock() UNLOCK_FUNCTION("");
3157 void goober() EXCLUSIVE_LOCKS_REQUIRED("");
3158 void roober() SHARED_LOCKS_REQUIRED("");
3159};
3160
3161
3162class Bar : public Foo {
3163public:
3164 void bar(Foo* f) {
3165 f->unlock();
3166 f->goober();
3167 f->roober();
3168 f->lock();
3169 };
3170};
3171
3172} // end namespace StringIgnoreTest
3173
3174
DeLesley Hutchins54081532012-08-31 22:09:53 +00003175namespace LockReturnedScopeFix {
3176
3177class Base {
3178protected:
3179 struct Inner;
3180 bool c;
3181
3182 const Mutex& getLock(const Inner* i);
3183
3184 void lockInner (Inner* i) EXCLUSIVE_LOCK_FUNCTION(getLock(i));
3185 void unlockInner(Inner* i) UNLOCK_FUNCTION(getLock(i));
3186 void foo(Inner* i) EXCLUSIVE_LOCKS_REQUIRED(getLock(i));
3187
3188 void bar(Inner* i);
3189};
3190
3191
3192struct Base::Inner {
3193 Mutex lock_;
3194 void doSomething() EXCLUSIVE_LOCKS_REQUIRED(lock_);
3195};
3196
3197
3198const Mutex& Base::getLock(const Inner* i) LOCK_RETURNED(i->lock_) {
3199 return i->lock_;
3200}
3201
3202
3203void Base::foo(Inner* i) {
3204 i->doSomething();
3205}
3206
3207void Base::bar(Inner* i) {
3208 if (c) {
3209 i->lock_.Lock();
3210 unlockInner(i);
3211 }
3212 else {
3213 lockInner(i);
3214 i->lock_.Unlock();
3215 }
3216}
3217
3218} // end namespace LockReturnedScopeFix
3219
DeLesley Hutchinsfd0f11c2012-09-05 20:01:16 +00003220
3221namespace TrylockWithCleanups {
3222
3223class MyString {
3224public:
3225 MyString(const char* s);
3226 ~MyString();
3227};
3228
3229struct Foo {
3230 Mutex mu_;
3231 int a GUARDED_BY(mu_);
3232};
3233
3234Foo* GetAndLockFoo(const MyString& s)
3235 EXCLUSIVE_TRYLOCK_FUNCTION(true, &Foo::mu_);
3236
3237static void test() {
3238 Foo* lt = GetAndLockFoo("foo");
3239 if (!lt) return;
3240 int a = lt->a;
3241 lt->mu_.Unlock();
3242}
3243
DeLesley Hutchins24a6c942012-09-11 18:27:46 +00003244} // end namespace TrylockWithCleanups
DeLesley Hutchinsfd0f11c2012-09-05 20:01:16 +00003245
3246
DeLesley Hutchins0b4db3e2012-09-07 17:34:53 +00003247namespace UniversalLock {
3248
3249class Foo {
3250 Mutex mu_;
3251 bool c;
3252
3253 int a GUARDED_BY(mu_);
3254 void r_foo() SHARED_LOCKS_REQUIRED(mu_);
3255 void w_foo() EXCLUSIVE_LOCKS_REQUIRED(mu_);
3256
3257 void test1() {
3258 int b;
3259
3260 beginNoWarnOnReads();
3261 b = a;
3262 r_foo();
3263 endNoWarnOnReads();
3264
3265 beginNoWarnOnWrites();
3266 a = 0;
3267 w_foo();
3268 endNoWarnOnWrites();
3269 }
3270
3271 // don't warn on joins with universal lock
3272 void test2() {
3273 if (c) {
3274 beginNoWarnOnWrites();
3275 }
3276 a = 0; // \
3277 // expected-warning {{writing variable 'a' requires locking 'mu_' exclusively}}
3278 endNoWarnOnWrites(); // \
3279 // expected-warning {{unlocking '*' that was not locked}}
3280 }
3281
3282
3283 // make sure the universal lock joins properly
3284 void test3() {
3285 if (c) {
3286 mu_.Lock();
3287 beginNoWarnOnWrites();
3288 }
3289 else {
3290 beginNoWarnOnWrites();
3291 mu_.Lock();
3292 }
3293 a = 0;
3294 endNoWarnOnWrites();
3295 mu_.Unlock();
3296 }
3297
3298
3299 // combine universal lock with other locks
3300 void test4() {
3301 beginNoWarnOnWrites();
3302 mu_.Lock();
3303 mu_.Unlock();
3304 endNoWarnOnWrites();
3305
3306 mu_.Lock();
3307 beginNoWarnOnWrites();
3308 endNoWarnOnWrites();
3309 mu_.Unlock();
3310
3311 mu_.Lock();
3312 beginNoWarnOnWrites();
3313 mu_.Unlock();
3314 endNoWarnOnWrites();
3315 }
3316};
3317
DeLesley Hutchins24a6c942012-09-11 18:27:46 +00003318} // end namespace UniversalLock
3319
3320
3321namespace TemplateLockReturned {
3322
3323template<class T>
3324class BaseT {
3325public:
3326 virtual void baseMethod() = 0;
3327 Mutex* get_mutex() LOCK_RETURNED(mutex_) { return &mutex_; }
3328
3329 Mutex mutex_;
3330 int a GUARDED_BY(mutex_);
3331};
3332
3333
3334class Derived : public BaseT<int> {
3335public:
3336 void baseMethod() EXCLUSIVE_LOCKS_REQUIRED(get_mutex()) {
3337 a = 0;
3338 }
3339};
3340
3341} // end namespace TemplateLockReturned
3342
3343
DeLesley Hutchinsf9ee0ba2012-09-11 23:04:49 +00003344namespace ExprMatchingBugFix {
3345
3346class Foo {
3347public:
3348 Mutex mu_;
3349};
3350
3351
3352class Bar {
3353public:
3354 bool c;
3355 Foo* foo;
3356 Bar(Foo* f) : foo(f) { }
3357
3358 struct Nested {
3359 Foo* foo;
3360 Nested(Foo* f) : foo(f) { }
3361
3362 void unlockFoo() UNLOCK_FUNCTION(&Foo::mu_);
3363 };
3364
3365 void test();
3366};
3367
3368
3369void Bar::test() {
3370 foo->mu_.Lock();
3371 if (c) {
3372 Nested *n = new Nested(foo);
3373 n->unlockFoo();
3374 }
3375 else {
3376 foo->mu_.Unlock();
3377 }
3378}
3379
3380}; // end namespace ExprMatchingBugfix
3381
3382
DeLesley Hutchins5b280f22012-09-19 19:18:29 +00003383namespace ComplexNameTest {
DeLesley Hutchinsf9ee0ba2012-09-11 23:04:49 +00003384
DeLesley Hutchins5b280f22012-09-19 19:18:29 +00003385class Foo {
3386public:
3387 static Mutex mu_;
3388
3389 Foo() EXCLUSIVE_LOCKS_REQUIRED(mu_) { }
3390 ~Foo() EXCLUSIVE_LOCKS_REQUIRED(mu_) { }
3391
3392 int operator[](int i) EXCLUSIVE_LOCKS_REQUIRED(mu_) { return 0; }
3393};
3394
3395class Bar {
3396public:
3397 static Mutex mu_;
3398
3399 Bar() LOCKS_EXCLUDED(mu_) { }
3400 ~Bar() LOCKS_EXCLUDED(mu_) { }
3401
3402 int operator[](int i) LOCKS_EXCLUDED(mu_) { return 0; }
3403};
3404
3405
3406void test1() {
3407 Foo f; // expected-warning {{calling function 'Foo' requires exclusive lock on 'mu_'}}
3408 int a = f[0]; // expected-warning {{calling function 'operator[]' requires exclusive lock on 'mu_'}}
3409} // expected-warning {{calling function '~Foo' requires exclusive lock on 'mu_'}}
3410
3411
3412void test2() {
3413 Bar::mu_.Lock();
3414 {
3415 Bar b; // expected-warning {{cannot call function 'Bar' while mutex 'mu_' is locked}}
3416 int a = b[0]; // expected-warning {{cannot call function 'operator[]' while mutex 'mu_' is locked}}
3417 } // expected-warning {{cannot call function '~Bar' while mutex 'mu_' is locked}}
3418 Bar::mu_.Unlock();
3419}
3420
3421}; // end namespace ComplexNameTest