blob: fa8786a957fb6ff2ff6b0259392eeaedbada743b [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 Hutchins60ff1982012-09-20 23:14:43 +00001658namespace TryLockTest {
1659
DeLesley Hutchinsb4fa4182012-01-06 19:16:50 +00001660struct TestTryLock {
1661 Mutex mu;
1662 int a GUARDED_BY(mu);
1663 bool cond;
1664
1665 void foo1() {
1666 if (mu.TryLock()) {
1667 a = 1;
1668 mu.Unlock();
1669 }
1670 }
1671
1672 void foo2() {
1673 if (!mu.TryLock()) return;
1674 a = 2;
1675 mu.Unlock();
1676 }
1677
1678 void foo3() {
1679 bool b = mu.TryLock();
1680 if (b) {
1681 a = 3;
1682 mu.Unlock();
1683 }
1684 }
1685
1686 void foo4() {
1687 bool b = mu.TryLock();
1688 if (!b) return;
1689 a = 4;
1690 mu.Unlock();
1691 }
1692
1693 void foo5() {
1694 while (mu.TryLock()) {
1695 a = a + 1;
1696 mu.Unlock();
1697 }
1698 }
1699
1700 void foo6() {
1701 bool b = mu.TryLock();
1702 b = !b;
1703 if (b) return;
1704 a = 6;
1705 mu.Unlock();
1706 }
1707
1708 void foo7() {
1709 bool b1 = mu.TryLock();
1710 bool b2 = !b1;
1711 bool b3 = !b2;
1712 if (b3) {
1713 a = 7;
1714 mu.Unlock();
1715 }
1716 }
1717
1718 // Test use-def chains: join points
1719 void foo8() {
1720 bool b = mu.TryLock();
1721 bool b2 = b;
1722 if (cond)
1723 b = true;
Sylvestre Ledru43e3dee2012-07-31 06:56:50 +00001724 if (b) { // b should be unknown at this point, because of the join point
DeLesley Hutchinsb4fa4182012-01-06 19:16:50 +00001725 a = 8; // expected-warning {{writing variable 'a' requires locking 'mu' exclusively}}
1726 }
1727 if (b2) { // b2 should be known at this point.
1728 a = 8;
1729 mu.Unlock();
1730 }
1731 }
1732
1733 // Test use-def-chains: back edges
1734 void foo9() {
1735 bool b = mu.TryLock();
1736
1737 for (int i = 0; i < 10; ++i);
1738
1739 if (b) { // b is still known, because the loop doesn't alter it
1740 a = 9;
1741 mu.Unlock();
1742 }
1743 }
1744
1745 // Test use-def chains: back edges
1746 void foo10() {
1747 bool b = mu.TryLock();
1748
1749 while (cond) {
1750 if (b) { // b should be uknown at this point b/c of the loop
1751 a = 10; // expected-warning {{writing variable 'a' requires locking 'mu' exclusively}}
1752 }
1753 b = !b;
1754 }
1755 }
DeLesley Hutchins60ff1982012-09-20 23:14:43 +00001756
1757 // Test merge of exclusive trylock
1758 void foo11() {
1759 if (cond) {
1760 if (!mu.TryLock())
1761 return;
1762 }
1763 else {
1764 mu.Lock();
1765 }
1766 a = 10;
1767 mu.Unlock();
1768 }
1769
1770 // Test merge of shared trylock
1771 void foo12() {
1772 if (cond) {
1773 if (!mu.ReaderTryLock())
1774 return;
1775 }
1776 else {
1777 mu.ReaderLock();
1778 }
1779 int i = a;
1780 mu.Unlock();
1781 }
DeLesley Hutchinsb4fa4182012-01-06 19:16:50 +00001782}; // end TestTrylock
1783
DeLesley Hutchins60ff1982012-09-20 23:14:43 +00001784} // end namespace TrylockTest
1785
DeLesley Hutchinsb4fa4182012-01-06 19:16:50 +00001786
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +00001787namespace TestTemplateAttributeInstantiation {
1788
1789class Foo1 {
1790public:
1791 Mutex mu_;
1792 int a GUARDED_BY(mu_);
1793};
1794
1795class Foo2 {
1796public:
1797 int a GUARDED_BY(mu_);
1798 Mutex mu_;
1799};
1800
1801
1802class Bar {
1803public:
1804 // Test non-dependent expressions in attributes on template functions
1805 template <class T>
1806 void barND(Foo1 *foo, T *fooT) EXCLUSIVE_LOCKS_REQUIRED(foo->mu_) {
1807 foo->a = 0;
1808 }
1809
1810 // Test dependent expressions in attributes on template functions
1811 template <class T>
1812 void barD(Foo1 *foo, T *fooT) EXCLUSIVE_LOCKS_REQUIRED(fooT->mu_) {
1813 fooT->a = 0;
1814 }
1815};
1816
1817
1818template <class T>
1819class BarT {
1820public:
1821 Foo1 fooBase;
1822 T fooBaseT;
1823
1824 // Test non-dependent expression in ordinary method on template class
1825 void barND() EXCLUSIVE_LOCKS_REQUIRED(fooBase.mu_) {
1826 fooBase.a = 0;
1827 }
1828
1829 // Test dependent expressions in ordinary methods on template class
1830 void barD() EXCLUSIVE_LOCKS_REQUIRED(fooBaseT.mu_) {
1831 fooBaseT.a = 0;
1832 }
1833
1834 // Test dependent expressions in template method in template class
1835 template <class T2>
1836 void barTD(T2 *fooT) EXCLUSIVE_LOCKS_REQUIRED(fooBaseT.mu_, fooT->mu_) {
1837 fooBaseT.a = 0;
1838 fooT->a = 0;
1839 }
1840};
1841
1842template <class T>
1843class Cell {
1844public:
1845 Mutex mu_;
1846 // Test dependent guarded_by
1847 T data GUARDED_BY(mu_);
1848
DeLesley Hutchins23323e02012-01-20 22:50:54 +00001849 void fooEx() EXCLUSIVE_LOCKS_REQUIRED(mu_) {
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +00001850 data = 0;
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +00001851 }
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +00001852
1853 void foo() {
1854 mu_.Lock();
1855 data = 0;
1856 mu_.Unlock();
1857 }
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +00001858};
1859
1860void test() {
1861 Bar b;
1862 BarT<Foo2> bt;
1863 Foo1 f1;
1864 Foo2 f2;
1865
1866 f1.mu_.Lock();
1867 f2.mu_.Lock();
1868 bt.fooBase.mu_.Lock();
1869 bt.fooBaseT.mu_.Lock();
1870
1871 b.barND(&f1, &f2);
1872 b.barD(&f1, &f2);
1873 bt.barND();
1874 bt.barD();
1875 bt.barTD(&f2);
1876
1877 f1.mu_.Unlock();
1878 bt.barTD(&f1); // \
DeLesley Hutchins3f0ec522012-09-10 19:58:23 +00001879 // expected-warning {{calling function 'barTD' requires exclusive lock on 'f1.mu_'}} \
1880 // expected-note {{found near match 'bt.fooBase.mu_'}}
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +00001881
1882 bt.fooBase.mu_.Unlock();
1883 bt.fooBaseT.mu_.Unlock();
1884 f2.mu_.Unlock();
1885
1886 Cell<int> cell;
1887 cell.data = 0; // \
DeLesley Hutchinsa74b7152012-08-10 20:19:55 +00001888 // expected-warning {{writing variable 'data' requires locking 'cell.mu_' exclusively}}
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +00001889 cell.foo();
DeLesley Hutchins23323e02012-01-20 22:50:54 +00001890 cell.mu_.Lock();
1891 cell.fooEx();
1892 cell.mu_.Unlock();
1893}
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +00001894
DeLesley Hutchins23323e02012-01-20 22:50:54 +00001895
1896template <class T>
1897class CellDelayed {
1898public:
1899 // Test dependent guarded_by
1900 T data GUARDED_BY(mu_);
DeLesley Hutchinsdd5756c2012-02-16 17:30:51 +00001901 static T static_data GUARDED_BY(static_mu_);
DeLesley Hutchins23323e02012-01-20 22:50:54 +00001902
1903 void fooEx(CellDelayed<T> *other) EXCLUSIVE_LOCKS_REQUIRED(mu_, other->mu_) {
1904 this->data = other->data;
1905 }
1906
1907 template <class T2>
1908 void fooExT(CellDelayed<T2> *otherT) EXCLUSIVE_LOCKS_REQUIRED(mu_, otherT->mu_) {
1909 this->data = otherT->data;
1910 }
1911
1912 void foo() {
1913 mu_.Lock();
1914 data = 0;
1915 mu_.Unlock();
1916 }
1917
1918 Mutex mu_;
DeLesley Hutchinsdd5756c2012-02-16 17:30:51 +00001919 static Mutex static_mu_;
DeLesley Hutchins23323e02012-01-20 22:50:54 +00001920};
1921
1922void testDelayed() {
1923 CellDelayed<int> celld;
1924 CellDelayed<int> celld2;
1925 celld.foo();
1926 celld.mu_.Lock();
1927 celld2.mu_.Lock();
1928
1929 celld.fooEx(&celld2);
1930 celld.fooExT(&celld2);
1931
1932 celld2.mu_.Unlock();
1933 celld.mu_.Unlock();
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +00001934}
1935
1936}; // end namespace TestTemplateAttributeInstantiation
1937
1938
DeLesley Hutchinse03b2b32012-01-20 23:24:41 +00001939namespace FunctionDeclDefTest {
1940
1941class Foo {
1942public:
1943 Mutex mu_;
1944 int a GUARDED_BY(mu_);
1945
1946 virtual void foo1(Foo *f_declared) EXCLUSIVE_LOCKS_REQUIRED(f_declared->mu_);
1947};
1948
1949// EXCLUSIVE_LOCKS_REQUIRED should be applied, and rewritten to f_defined->mu_
1950void Foo::foo1(Foo *f_defined) {
1951 f_defined->a = 0;
1952};
1953
1954void test() {
1955 Foo myfoo;
1956 myfoo.foo1(&myfoo); // \
DeLesley Hutchinsa74b7152012-08-10 20:19:55 +00001957 // expected-warning {{calling function 'foo1' requires exclusive lock on 'myfoo.mu_'}}
DeLesley Hutchinse03b2b32012-01-20 23:24:41 +00001958 myfoo.mu_.Lock();
1959 myfoo.foo1(&myfoo);
1960 myfoo.mu_.Unlock();
1961}
1962
1963};
Richard Smith2e515622012-02-03 04:45:26 +00001964
1965namespace GoingNative {
1966
1967 struct __attribute__((lockable)) mutex {
1968 void lock() __attribute__((exclusive_lock_function));
1969 void unlock() __attribute__((unlock_function));
1970 // ...
1971 };
1972 bool foo();
1973 bool bar();
1974 mutex m;
1975 void test() {
1976 m.lock();
1977 while (foo()) {
1978 m.unlock();
1979 // ...
1980 if (bar()) {
1981 // ...
1982 if (foo())
1983 continue; // expected-warning {{expecting mutex 'm' to be locked at start of each loop}}
1984 //...
1985 }
1986 // ...
1987 m.lock(); // expected-note {{mutex acquired here}}
1988 }
1989 m.unlock();
1990 }
1991
1992}
DeLesley Hutchinsc24a2332012-02-16 16:50:43 +00001993
1994
1995
1996namespace FunctionDefinitionTest {
1997
1998class Foo {
1999public:
2000 void foo1();
2001 void foo2();
2002 void foo3(Foo *other);
2003
2004 template<class T>
2005 void fooT1(const T& dummy1);
2006
2007 template<class T>
2008 void fooT2(const T& dummy2) EXCLUSIVE_LOCKS_REQUIRED(mu_);
2009
2010 Mutex mu_;
2011 int a GUARDED_BY(mu_);
2012};
2013
2014template<class T>
2015class FooT {
2016public:
2017 void foo();
2018
2019 Mutex mu_;
2020 T a GUARDED_BY(mu_);
2021};
2022
2023
2024void Foo::foo1() NO_THREAD_SAFETY_ANALYSIS {
2025 a = 1;
2026}
2027
2028void Foo::foo2() EXCLUSIVE_LOCKS_REQUIRED(mu_) {
2029 a = 2;
2030}
2031
2032void Foo::foo3(Foo *other) EXCLUSIVE_LOCKS_REQUIRED(other->mu_) {
2033 other->a = 3;
2034}
2035
2036template<class T>
2037void Foo::fooT1(const T& dummy1) EXCLUSIVE_LOCKS_REQUIRED(mu_) {
2038 a = dummy1;
2039}
2040
2041/* TODO -- uncomment with template instantiation of attributes.
2042template<class T>
2043void Foo::fooT2(const T& dummy2) {
2044 a = dummy2;
2045}
2046*/
2047
2048void fooF1(Foo *f) EXCLUSIVE_LOCKS_REQUIRED(f->mu_) {
2049 f->a = 1;
2050}
2051
2052void fooF2(Foo *f);
2053void fooF2(Foo *f) EXCLUSIVE_LOCKS_REQUIRED(f->mu_) {
2054 f->a = 2;
2055}
2056
2057void fooF3(Foo *f) EXCLUSIVE_LOCKS_REQUIRED(f->mu_);
2058void fooF3(Foo *f) {
2059 f->a = 3;
2060}
2061
2062template<class T>
2063void FooT<T>::foo() EXCLUSIVE_LOCKS_REQUIRED(mu_) {
2064 a = 0;
2065}
2066
2067void test() {
2068 int dummy = 0;
2069 Foo myFoo;
2070
2071 myFoo.foo2(); // \
DeLesley Hutchinsa74b7152012-08-10 20:19:55 +00002072 // expected-warning {{calling function 'foo2' requires exclusive lock on 'myFoo.mu_'}}
DeLesley Hutchinsc24a2332012-02-16 16:50:43 +00002073 myFoo.foo3(&myFoo); // \
DeLesley Hutchinsa74b7152012-08-10 20:19:55 +00002074 // expected-warning {{calling function 'foo3' requires exclusive lock on 'myFoo.mu_'}}
DeLesley Hutchinsc24a2332012-02-16 16:50:43 +00002075 myFoo.fooT1(dummy); // \
DeLesley Hutchinsa74b7152012-08-10 20:19:55 +00002076 // expected-warning {{calling function 'fooT1' requires exclusive lock on 'myFoo.mu_'}}
DeLesley Hutchinsc24a2332012-02-16 16:50:43 +00002077
DeLesley Hutchinsa74b7152012-08-10 20:19:55 +00002078 myFoo.fooT2(dummy); // \
2079 // expected-warning {{calling function 'fooT2' requires exclusive lock on 'myFoo.mu_'}}
DeLesley Hutchinsc24a2332012-02-16 16:50:43 +00002080
2081 fooF1(&myFoo); // \
DeLesley Hutchinsa74b7152012-08-10 20:19:55 +00002082 // expected-warning {{calling function 'fooF1' requires exclusive lock on 'myFoo.mu_'}}
DeLesley Hutchinsc24a2332012-02-16 16:50:43 +00002083 fooF2(&myFoo); // \
DeLesley Hutchinsa74b7152012-08-10 20:19:55 +00002084 // expected-warning {{calling function 'fooF2' requires exclusive lock on 'myFoo.mu_'}}
DeLesley Hutchinsc24a2332012-02-16 16:50:43 +00002085 fooF3(&myFoo); // \
DeLesley Hutchinsa74b7152012-08-10 20:19:55 +00002086 // expected-warning {{calling function 'fooF3' requires exclusive lock on 'myFoo.mu_'}}
DeLesley Hutchinsc24a2332012-02-16 16:50:43 +00002087
2088 myFoo.mu_.Lock();
2089 myFoo.foo2();
2090 myFoo.foo3(&myFoo);
2091 myFoo.fooT1(dummy);
2092
DeLesley Hutchinsa74b7152012-08-10 20:19:55 +00002093 myFoo.fooT2(dummy);
DeLesley Hutchinsc24a2332012-02-16 16:50:43 +00002094
2095 fooF1(&myFoo);
2096 fooF2(&myFoo);
2097 fooF3(&myFoo);
2098 myFoo.mu_.Unlock();
2099
2100 FooT<int> myFooT;
2101 myFooT.foo(); // \
DeLesley Hutchinsa74b7152012-08-10 20:19:55 +00002102 // expected-warning {{calling function 'foo' requires exclusive lock on 'myFooT.mu_'}}
DeLesley Hutchinsc24a2332012-02-16 16:50:43 +00002103}
2104
DeLesley Hutchins4bda3ec2012-02-16 17:03:24 +00002105} // end namespace FunctionDefinitionTest
2106
2107
2108namespace SelfLockingTest {
2109
2110class LOCKABLE MyLock {
2111public:
2112 int foo GUARDED_BY(this);
2113
2114 void lock() EXCLUSIVE_LOCK_FUNCTION();
2115 void unlock() UNLOCK_FUNCTION();
2116
2117 void doSomething() {
2118 this->lock(); // allow 'this' as a lock expression
2119 foo = 0;
2120 doSomethingElse();
2121 this->unlock();
2122 }
2123
2124 void doSomethingElse() EXCLUSIVE_LOCKS_REQUIRED(this) {
2125 foo = 1;
2126 };
2127
2128 void test() {
2129 foo = 2; // \
2130 // expected-warning {{writing variable 'foo' requires locking 'this' exclusively}}
2131 }
DeLesley Hutchinsc24a2332012-02-16 16:50:43 +00002132};
2133
DeLesley Hutchins2f13bec2012-02-16 17:13:43 +00002134
2135class LOCKABLE MyLock2 {
2136public:
2137 Mutex mu_;
2138 int foo GUARDED_BY(this);
2139
2140 // don't check inside lock and unlock functions
2141 void lock() EXCLUSIVE_LOCK_FUNCTION() { mu_.Lock(); }
2142 void unlock() UNLOCK_FUNCTION() { mu_.Unlock(); }
2143
2144 // don't check inside constructors and destructors
2145 MyLock2() { foo = 1; }
2146 ~MyLock2() { foo = 0; }
2147};
2148
2149
DeLesley Hutchins4bda3ec2012-02-16 17:03:24 +00002150} // end namespace SelfLockingTest
2151
2152
DeLesley Hutchinsd08d5992012-02-25 00:11:55 +00002153namespace InvalidNonstatic {
2154
2155// Forward decl here causes bogus "invalid use of non-static data member"
2156// on reference to mutex_ in guarded_by attribute.
2157class Foo;
2158
2159class Foo {
2160 Mutex* mutex_;
2161
2162 int foo __attribute__((guarded_by(mutex_)));
2163};
2164
2165} // end namespace InvalidNonStatic
2166
DeLesley Hutchins2a35be82012-03-02 22:02:58 +00002167
2168namespace NoReturnTest {
2169
2170bool condition();
2171void fatal() __attribute__((noreturn));
2172
2173Mutex mu_;
2174
2175void test1() {
2176 MutexLock lock(&mu_);
2177 if (condition()) {
2178 fatal();
2179 return;
2180 }
2181}
2182
DeLesley Hutchins2287c5e2012-03-02 22:12:59 +00002183} // end namespace NoReturnTest
2184
2185
2186namespace TestMultiDecl {
2187
2188class Foo {
2189public:
2190 int GUARDED_BY(mu_) a;
2191 int GUARDED_BY(mu_) b, c;
2192
2193 void foo() {
2194 a = 0; // \
2195 // expected-warning {{writing variable 'a' requires locking 'mu_' exclusively}}
2196 b = 0; // \
2197 // expected-warning {{writing variable 'b' requires locking 'mu_' exclusively}}
2198 c = 0; // \
2199 // expected-warning {{writing variable 'c' requires locking 'mu_' exclusively}}
2200 }
2201
2202private:
2203 Mutex mu_;
DeLesley Hutchins2a35be82012-03-02 22:02:58 +00002204};
DeLesley Hutchins2287c5e2012-03-02 22:12:59 +00002205
2206} // end namespace TestMultiDecl
2207
DeLesley Hutchins7ec419a2012-03-02 22:29:50 +00002208
2209namespace WarnNoDecl {
2210
2211class Foo {
2212 void foo(int a); __attribute__(( // \
2213 // expected-warning {{declaration does not declare anything}}
2214 exclusive_locks_required(a))); // \
2215 // expected-warning {{attribute exclusive_locks_required ignored}}
2216};
2217
2218} // end namespace WarnNoDecl
2219
2220
DeLesley Hutchins0d95dfc2012-03-02 23:36:05 +00002221
2222namespace MoreLockExpressions {
2223
2224class Foo {
2225public:
2226 Mutex mu_;
2227 int a GUARDED_BY(mu_);
2228};
2229
2230class Bar {
2231public:
2232 int b;
2233 Foo* f;
2234
2235 Foo& getFoo() { return *f; }
2236 Foo& getFoo2(int c) { return *f; }
2237 Foo& getFoo3(int c, int d) { return *f; }
2238
2239 Foo& getFooey() { return *f; }
2240};
2241
2242Foo& getBarFoo(Bar &bar, int c) { return bar.getFoo2(c); }
2243
2244void test() {
2245 Foo foo;
2246 Foo *fooArray;
2247 Bar bar;
2248 int a;
2249 int b;
2250 int c;
2251
2252 bar.getFoo().mu_.Lock();
2253 bar.getFoo().a = 0;
2254 bar.getFoo().mu_.Unlock();
2255
2256 (bar.getFoo().mu_).Lock(); // test parenthesis
2257 bar.getFoo().a = 0;
2258 (bar.getFoo().mu_).Unlock();
2259
2260 bar.getFoo2(a).mu_.Lock();
2261 bar.getFoo2(a).a = 0;
2262 bar.getFoo2(a).mu_.Unlock();
2263
2264 bar.getFoo3(a, b).mu_.Lock();
2265 bar.getFoo3(a, b).a = 0;
2266 bar.getFoo3(a, b).mu_.Unlock();
2267
2268 getBarFoo(bar, a).mu_.Lock();
2269 getBarFoo(bar, a).a = 0;
2270 getBarFoo(bar, a).mu_.Unlock();
2271
2272 bar.getFoo2(10).mu_.Lock();
2273 bar.getFoo2(10).a = 0;
2274 bar.getFoo2(10).mu_.Unlock();
2275
2276 bar.getFoo2(a + 1).mu_.Lock();
2277 bar.getFoo2(a + 1).a = 0;
2278 bar.getFoo2(a + 1).mu_.Unlock();
2279
2280 (a > 0 ? fooArray[1] : fooArray[b]).mu_.Lock();
2281 (a > 0 ? fooArray[1] : fooArray[b]).a = 0;
2282 (a > 0 ? fooArray[1] : fooArray[b]).mu_.Unlock();
2283
2284 bar.getFoo().mu_.Lock();
2285 bar.getFooey().a = 0; // \
DeLesley Hutchins3f0ec522012-09-10 19:58:23 +00002286 // expected-warning {{writing variable 'a' requires locking 'bar.getFooey().mu_' exclusively}} \
2287 // expected-note {{found near match 'bar.getFoo().mu_'}}
DeLesley Hutchins0d95dfc2012-03-02 23:36:05 +00002288 bar.getFoo().mu_.Unlock();
2289
2290 bar.getFoo2(a).mu_.Lock();
2291 bar.getFoo2(b).a = 0; // \
DeLesley Hutchins3f0ec522012-09-10 19:58:23 +00002292 // expected-warning {{writing variable 'a' requires locking 'bar.getFoo2(b).mu_' exclusively}} \
2293 // expected-note {{found near match 'bar.getFoo2(a).mu_'}}
DeLesley Hutchins0d95dfc2012-03-02 23:36:05 +00002294 bar.getFoo2(a).mu_.Unlock();
2295
2296 bar.getFoo3(a, b).mu_.Lock();
2297 bar.getFoo3(a, c).a = 0; // \
DeLesley Hutchins3f0ec522012-09-10 19:58:23 +00002298 // expected-warning {{writing variable 'a' requires locking 'bar.getFoo3(a,c).mu_' exclusively}} \
2299 // expected-note {{'bar.getFoo3(a,b).mu_'}}
DeLesley Hutchins0d95dfc2012-03-02 23:36:05 +00002300 bar.getFoo3(a, b).mu_.Unlock();
2301
2302 getBarFoo(bar, a).mu_.Lock();
2303 getBarFoo(bar, b).a = 0; // \
DeLesley Hutchins3f0ec522012-09-10 19:58:23 +00002304 // expected-warning {{writing variable 'a' requires locking 'getBarFoo(bar,b).mu_' exclusively}} \
2305 // expected-note {{'getBarFoo(bar,a).mu_'}}
DeLesley Hutchins0d95dfc2012-03-02 23:36:05 +00002306 getBarFoo(bar, a).mu_.Unlock();
2307
2308 (a > 0 ? fooArray[1] : fooArray[b]).mu_.Lock();
2309 (a > 0 ? fooArray[b] : fooArray[c]).a = 0; // \
DeLesley Hutchins3f0ec522012-09-10 19:58:23 +00002310 // expected-warning {{writing variable 'a' requires locking '((a#_)#_#fooArray[b]).mu_' exclusively}} \
2311 // expected-note {{'((a#_)#_#fooArray[_]).mu_'}}
DeLesley Hutchins0d95dfc2012-03-02 23:36:05 +00002312 (a > 0 ? fooArray[1] : fooArray[b]).mu_.Unlock();
2313}
2314
2315
DeLesley Hutchins0da44142012-06-22 17:07:28 +00002316} // end namespace MoreLockExpressions
2317
2318
2319namespace TrylockJoinPoint {
2320
2321class Foo {
2322 Mutex mu;
2323 bool c;
2324
2325 void foo() {
2326 if (c) {
2327 if (!mu.TryLock())
2328 return;
2329 } else {
2330 mu.Lock();
2331 }
2332 mu.Unlock();
2333 }
2334};
2335
2336} // end namespace TrylockJoinPoint
DeLesley Hutchins0d95dfc2012-03-02 23:36:05 +00002337
2338
DeLesley Hutchinsf63797c2012-06-25 18:33:18 +00002339namespace LockReturned {
2340
2341class Foo {
2342public:
2343 int a GUARDED_BY(mu_);
2344 void foo() EXCLUSIVE_LOCKS_REQUIRED(mu_);
2345 void foo2(Foo* f) EXCLUSIVE_LOCKS_REQUIRED(mu_, f->mu_);
2346
2347 static void sfoo(Foo* f) EXCLUSIVE_LOCKS_REQUIRED(f->mu_);
2348
2349 Mutex* getMu() LOCK_RETURNED(mu_);
2350
2351 Mutex mu_;
2352
2353 static Mutex* getMu(Foo* f) LOCK_RETURNED(f->mu_);
2354};
2355
2356
2357// Calls getMu() directly to lock and unlock
2358void test1(Foo* f1, Foo* f2) {
DeLesley Hutchinsa74b7152012-08-10 20:19:55 +00002359 f1->a = 0; // expected-warning {{writing variable 'a' requires locking 'f1->mu_' exclusively}}
2360 f1->foo(); // expected-warning {{calling function 'foo' requires exclusive lock on 'f1->mu_'}}
DeLesley Hutchinsf63797c2012-06-25 18:33:18 +00002361
DeLesley Hutchinsa74b7152012-08-10 20:19:55 +00002362 f1->foo2(f2); // expected-warning {{calling function 'foo2' requires exclusive lock on 'f1->mu_'}} \
2363 // expected-warning {{calling function 'foo2' requires exclusive lock on 'f2->mu_'}}
2364 Foo::sfoo(f1); // expected-warning {{calling function 'sfoo' requires exclusive lock on 'f1->mu_'}}
DeLesley Hutchinsf63797c2012-06-25 18:33:18 +00002365
2366 f1->getMu()->Lock();
2367
2368 f1->a = 0;
2369 f1->foo();
DeLesley Hutchins3f0ec522012-09-10 19:58:23 +00002370 f1->foo2(f2); // \
2371 // expected-warning {{calling function 'foo2' requires exclusive lock on 'f2->mu_'}} \
2372 // expected-note {{found near match 'f1->mu_'}}
DeLesley Hutchinsf63797c2012-06-25 18:33:18 +00002373
2374 Foo::getMu(f2)->Lock();
2375 f1->foo2(f2);
2376 Foo::getMu(f2)->Unlock();
2377
2378 Foo::sfoo(f1);
2379
2380 f1->getMu()->Unlock();
2381}
2382
2383
2384Mutex* getFooMu(Foo* f) LOCK_RETURNED(Foo::getMu(f));
2385
2386class Bar : public Foo {
2387public:
2388 int b GUARDED_BY(getMu());
2389 void bar() EXCLUSIVE_LOCKS_REQUIRED(getMu());
2390 void bar2(Bar* g) EXCLUSIVE_LOCKS_REQUIRED(getMu(this), g->getMu());
2391
2392 static void sbar(Bar* g) EXCLUSIVE_LOCKS_REQUIRED(g->getMu());
2393 static void sbar2(Bar* g) EXCLUSIVE_LOCKS_REQUIRED(getFooMu(g));
2394};
2395
2396
2397
2398// Use getMu() within other attributes.
2399// This requires at lest levels of substitution, more in the case of
2400void test2(Bar* b1, Bar* b2) {
DeLesley Hutchinsa74b7152012-08-10 20:19:55 +00002401 b1->b = 0; // expected-warning {{writing variable 'b' requires locking 'b1->mu_' exclusively}}
2402 b1->bar(); // expected-warning {{calling function 'bar' requires exclusive lock on 'b1->mu_'}}
2403 b1->bar2(b2); // expected-warning {{calling function 'bar2' requires exclusive lock on 'b1->mu_'}} \
2404 // expected-warning {{calling function 'bar2' requires exclusive lock on 'b2->mu_'}}
2405 Bar::sbar(b1); // expected-warning {{calling function 'sbar' requires exclusive lock on 'b1->mu_'}}
2406 Bar::sbar2(b1); // expected-warning {{calling function 'sbar2' requires exclusive lock on 'b1->mu_'}}
DeLesley Hutchinsf63797c2012-06-25 18:33:18 +00002407
2408 b1->getMu()->Lock();
2409
2410 b1->b = 0;
2411 b1->bar();
DeLesley Hutchins3f0ec522012-09-10 19:58:23 +00002412 b1->bar2(b2); // \
2413 // expected-warning {{calling function 'bar2' requires exclusive lock on 'b2->mu_'}} \
2414 // // expected-note {{found near match 'b1->mu_'}}
DeLesley Hutchinsf63797c2012-06-25 18:33:18 +00002415
2416 b2->getMu()->Lock();
2417 b1->bar2(b2);
2418
2419 b2->getMu()->Unlock();
2420
2421 Bar::sbar(b1);
2422 Bar::sbar2(b1);
2423
2424 b1->getMu()->Unlock();
2425}
2426
2427
2428// Sanity check -- lock the mutex directly, but use attributes that call getMu()
2429// Also lock the mutex using getFooMu, which calls a lock_returned function.
2430void test3(Bar* b1, Bar* b2) {
2431 b1->mu_.Lock();
2432 b1->b = 0;
2433 b1->bar();
2434
2435 getFooMu(b2)->Lock();
2436 b1->bar2(b2);
2437 getFooMu(b2)->Unlock();
2438
2439 Bar::sbar(b1);
2440 Bar::sbar2(b1);
2441
2442 b1->mu_.Unlock();
2443}
2444
2445} // end namespace LockReturned
2446
2447
DeLesley Hutchinsc99a5d82012-06-28 22:42:48 +00002448namespace ReleasableScopedLock {
2449
2450class Foo {
2451 Mutex mu_;
2452 bool c;
2453 int a GUARDED_BY(mu_);
2454
2455 void test1();
2456 void test2();
2457 void test3();
DeLesley Hutchins5381c052012-07-05 21:16:29 +00002458 void test4();
2459 void test5();
DeLesley Hutchinsc99a5d82012-06-28 22:42:48 +00002460};
2461
2462
2463void Foo::test1() {
2464 ReleasableMutexLock rlock(&mu_);
2465 rlock.Release();
2466}
2467
2468void Foo::test2() {
2469 ReleasableMutexLock rlock(&mu_);
2470 if (c) { // test join point -- held/not held during release
2471 rlock.Release();
2472 }
2473}
2474
2475void Foo::test3() {
2476 ReleasableMutexLock rlock(&mu_);
2477 a = 0;
2478 rlock.Release();
2479 a = 1; // expected-warning {{writing variable 'a' requires locking 'mu_' exclusively}}
2480}
2481
DeLesley Hutchins5381c052012-07-05 21:16:29 +00002482void Foo::test4() {
2483 ReleasableMutexLock rlock(&mu_);
2484 rlock.Release();
2485 rlock.Release(); // expected-warning {{unlocking 'mu_' that was not locked}}
2486}
2487
2488void Foo::test5() {
2489 ReleasableMutexLock rlock(&mu_);
2490 if (c) {
2491 rlock.Release();
2492 }
2493 // no warning on join point for managed lock.
2494 rlock.Release(); // expected-warning {{unlocking 'mu_' that was not locked}}
2495}
2496
2497
DeLesley Hutchinsc99a5d82012-06-28 22:42:48 +00002498} // end namespace ReleasableScopedLock
2499
2500
DeLesley Hutchins76f0a6e2012-07-02 21:59:24 +00002501namespace TrylockFunctionTest {
2502
2503class Foo {
2504public:
2505 Mutex mu1_;
2506 Mutex mu2_;
2507 bool c;
2508
2509 bool lockBoth() EXCLUSIVE_TRYLOCK_FUNCTION(true, mu1_, mu2_);
2510};
2511
2512bool Foo::lockBoth() {
2513 if (!mu1_.TryLock())
2514 return false;
2515
2516 mu2_.Lock();
2517 if (!c) {
2518 mu1_.Unlock();
2519 mu2_.Unlock();
2520 return false;
2521 }
2522
2523 return true;
2524}
2525
2526
2527} // end namespace TrylockFunctionTest
DeLesley Hutchinsc99a5d82012-06-28 22:42:48 +00002528
2529
2530
DeLesley Hutchinsc36eda12012-07-02 22:12:12 +00002531namespace DoubleLockBug {
2532
2533class Foo {
2534public:
2535 Mutex mu_;
2536 int a GUARDED_BY(mu_);
2537
DeLesley Hutchins5381c052012-07-05 21:16:29 +00002538 void foo1() EXCLUSIVE_LOCKS_REQUIRED(mu_);
2539 int foo2() SHARED_LOCKS_REQUIRED(mu_);
DeLesley Hutchinsc36eda12012-07-02 22:12:12 +00002540};
2541
2542
DeLesley Hutchins5381c052012-07-05 21:16:29 +00002543void Foo::foo1() EXCLUSIVE_LOCKS_REQUIRED(mu_) {
DeLesley Hutchinsc36eda12012-07-02 22:12:12 +00002544 a = 0;
2545}
2546
DeLesley Hutchins5381c052012-07-05 21:16:29 +00002547int Foo::foo2() SHARED_LOCKS_REQUIRED(mu_) {
2548 return a;
2549}
2550
2551}
2552
DeLesley Hutchinsc36eda12012-07-02 22:12:12 +00002553
2554
DeLesley Hutchins879a4332012-07-02 22:16:54 +00002555namespace UnlockBug {
DeLesley Hutchinsc36eda12012-07-02 22:12:12 +00002556
DeLesley Hutchins879a4332012-07-02 22:16:54 +00002557class Foo {
2558public:
2559 Mutex mutex_;
2560
2561 void foo1() EXCLUSIVE_LOCKS_REQUIRED(mutex_) { // expected-note {{mutex acquired here}}
2562 mutex_.Unlock();
2563 } // expected-warning {{expecting mutex 'mutex_' to be locked at the end of function}}
2564
2565
2566 void foo2() SHARED_LOCKS_REQUIRED(mutex_) { // expected-note {{mutex acquired here}}
2567 mutex_.Unlock();
2568 } // expected-warning {{expecting mutex 'mutex_' to be locked at the end of function}}
2569};
2570
2571} // end namespace UnlockBug
DeLesley Hutchinsc36eda12012-07-02 22:12:12 +00002572
DeLesley Hutchinsc99a5d82012-06-28 22:42:48 +00002573
DeLesley Hutchins5381c052012-07-05 21:16:29 +00002574
DeLesley Hutchinsbbe33412012-07-02 22:26:29 +00002575namespace FoolishScopedLockableBug {
2576
2577class SCOPED_LOCKABLE WTF_ScopedLockable {
2578public:
2579 WTF_ScopedLockable(Mutex* mu) EXCLUSIVE_LOCK_FUNCTION(mu);
2580
2581 // have to call release() manually;
2582 ~WTF_ScopedLockable();
2583
2584 void release() UNLOCK_FUNCTION();
2585};
2586
2587
2588class Foo {
2589 Mutex mu_;
2590 int a GUARDED_BY(mu_);
2591 bool c;
2592
2593 void doSomething();
2594
2595 void test1() {
2596 WTF_ScopedLockable wtf(&mu_);
2597 wtf.release();
2598 }
2599
2600 void test2() {
2601 WTF_ScopedLockable wtf(&mu_); // expected-note {{mutex acquired here}}
2602 } // expected-warning {{mutex 'mu_' is still locked at the end of function}}
2603
2604 void test3() {
2605 if (c) {
2606 WTF_ScopedLockable wtf(&mu_);
2607 wtf.release();
2608 }
2609 }
2610
2611 void test4() {
2612 if (c) {
2613 doSomething();
2614 }
2615 else {
2616 WTF_ScopedLockable wtf(&mu_);
2617 wtf.release();
2618 }
2619 }
2620
2621 void test5() {
2622 if (c) {
2623 WTF_ScopedLockable wtf(&mu_); // expected-note {{mutex acquired here}}
2624 }
2625 } // expected-warning {{mutex 'mu_' is not locked on every path through here}}
2626
2627 void test6() {
2628 if (c) {
2629 doSomething();
2630 }
2631 else {
2632 WTF_ScopedLockable wtf(&mu_); // expected-note {{mutex acquired here}}
2633 }
2634 } // expected-warning {{mutex 'mu_' is not locked on every path through here}}
2635};
2636
2637
2638} // end namespace FoolishScopedLockableBug
2639
DeLesley Hutchins9d6e7f32012-07-03 18:25:56 +00002640
DeLesley Hutchins5381c052012-07-05 21:16:29 +00002641
DeLesley Hutchins9d6e7f32012-07-03 18:25:56 +00002642namespace TemporaryCleanupExpr {
2643
2644class Foo {
2645 int a GUARDED_BY(getMutexPtr().get());
2646
2647 SmartPtr<Mutex> getMutexPtr();
2648
2649 void test();
2650};
2651
2652
2653void Foo::test() {
2654 {
2655 ReaderMutexLock lock(getMutexPtr().get());
2656 int b = a;
DeLesley Hutchins96fac6a2012-07-03 19:47:18 +00002657 }
DeLesley Hutchinsa74b7152012-08-10 20:19:55 +00002658 int b = a; // expected-warning {{reading variable 'a' requires locking 'getMutexPtr()'}}
DeLesley Hutchins9d6e7f32012-07-03 18:25:56 +00002659}
2660
2661} // end namespace TemporaryCleanupExpr
2662
2663
DeLesley Hutchins96fac6a2012-07-03 19:47:18 +00002664
2665namespace SmartPointerTests {
2666
2667class Foo {
2668public:
2669 SmartPtr<Mutex> mu_;
2670 int a GUARDED_BY(mu_);
2671 int b GUARDED_BY(mu_.get());
2672 int c GUARDED_BY(*mu_);
2673
2674 void Lock() EXCLUSIVE_LOCK_FUNCTION(mu_);
2675 void Unlock() UNLOCK_FUNCTION(mu_);
2676
2677 void test0();
2678 void test1();
2679 void test2();
2680 void test3();
2681 void test4();
2682 void test5();
2683 void test6();
2684 void test7();
2685 void test8();
2686};
2687
2688void Foo::test0() {
2689 a = 0; // expected-warning {{writing variable 'a' requires locking 'mu_' exclusively}}
2690 b = 0; // expected-warning {{writing variable 'b' requires locking 'mu_' exclusively}}
2691 c = 0; // expected-warning {{writing variable 'c' requires locking 'mu_' exclusively}}
2692}
2693
2694void Foo::test1() {
2695 mu_->Lock();
2696 a = 0;
2697 b = 0;
2698 c = 0;
2699 mu_->Unlock();
2700}
2701
2702void Foo::test2() {
2703 (*mu_).Lock();
2704 a = 0;
2705 b = 0;
2706 c = 0;
2707 (*mu_).Unlock();
2708}
2709
2710
2711void Foo::test3() {
2712 mu_.get()->Lock();
2713 a = 0;
2714 b = 0;
2715 c = 0;
2716 mu_.get()->Unlock();
2717}
2718
2719
2720void Foo::test4() {
2721 MutexLock lock(mu_.get());
2722 a = 0;
2723 b = 0;
2724 c = 0;
2725}
2726
2727
2728void Foo::test5() {
2729 MutexLock lock(&(*mu_));
2730 a = 0;
2731 b = 0;
2732 c = 0;
2733}
2734
2735
2736void Foo::test6() {
2737 Lock();
2738 a = 0;
2739 b = 0;
2740 c = 0;
2741 Unlock();
2742}
2743
2744
2745void Foo::test7() {
2746 {
2747 Lock();
2748 mu_->Unlock();
2749 }
2750 {
2751 mu_->Lock();
2752 Unlock();
2753 }
2754 {
2755 mu_.get()->Lock();
2756 mu_->Unlock();
2757 }
2758 {
2759 mu_->Lock();
2760 mu_.get()->Unlock();
2761 }
2762 {
2763 mu_.get()->Lock();
2764 (*mu_).Unlock();
2765 }
2766 {
2767 (*mu_).Lock();
2768 mu_->Unlock();
2769 }
2770}
2771
2772
2773void Foo::test8() {
2774 mu_->Lock();
2775 mu_.get()->Lock(); // expected-warning {{locking 'mu_' that is already locked}}
2776 (*mu_).Lock(); // expected-warning {{locking 'mu_' that is already locked}}
2777 mu_.get()->Unlock();
2778 Unlock(); // expected-warning {{unlocking 'mu_' that was not locked}}
2779}
2780
2781
2782class Bar {
2783 SmartPtr<Foo> foo;
2784
2785 void test0();
2786 void test1();
2787 void test2();
2788 void test3();
2789};
2790
2791
2792void Bar::test0() {
DeLesley Hutchinsa74b7152012-08-10 20:19:55 +00002793 foo->a = 0; // expected-warning {{writing variable 'a' requires locking 'foo->mu_' exclusively}}
2794 (*foo).b = 0; // expected-warning {{writing variable 'b' requires locking 'foo->mu_' exclusively}}
2795 foo.get()->c = 0; // expected-warning {{writing variable 'c' requires locking 'foo->mu_' exclusively}}
DeLesley Hutchins96fac6a2012-07-03 19:47:18 +00002796}
2797
2798
2799void Bar::test1() {
2800 foo->mu_->Lock();
2801 foo->a = 0;
2802 (*foo).b = 0;
2803 foo.get()->c = 0;
2804 foo->mu_->Unlock();
2805}
2806
2807
2808void Bar::test2() {
2809 (*foo).mu_->Lock();
2810 foo->a = 0;
2811 (*foo).b = 0;
2812 foo.get()->c = 0;
2813 foo.get()->mu_->Unlock();
2814}
2815
2816
2817void Bar::test3() {
2818 MutexLock lock(foo->mu_.get());
2819 foo->a = 0;
2820 (*foo).b = 0;
2821 foo.get()->c = 0;
2822}
2823
2824} // end namespace SmartPointerTests
2825
2826
2827
DeLesley Hutchins5381c052012-07-05 21:16:29 +00002828namespace DuplicateAttributeTest {
2829
2830class LOCKABLE Foo {
2831public:
2832 Mutex mu1_;
2833 Mutex mu2_;
2834 Mutex mu3_;
2835 int a GUARDED_BY(mu1_);
2836 int b GUARDED_BY(mu2_);
2837 int c GUARDED_BY(mu3_);
2838
2839 void lock() EXCLUSIVE_LOCK_FUNCTION();
2840 void unlock() UNLOCK_FUNCTION();
2841
2842 void lock1() EXCLUSIVE_LOCK_FUNCTION(mu1_);
2843 void slock1() SHARED_LOCK_FUNCTION(mu1_);
2844 void lock3() EXCLUSIVE_LOCK_FUNCTION(mu1_, mu2_, mu3_);
2845 void locklots()
2846 EXCLUSIVE_LOCK_FUNCTION(mu1_)
2847 EXCLUSIVE_LOCK_FUNCTION(mu2_)
2848 EXCLUSIVE_LOCK_FUNCTION(mu1_, mu2_, mu3_);
2849
2850 void unlock1() UNLOCK_FUNCTION(mu1_);
2851 void unlock3() UNLOCK_FUNCTION(mu1_, mu2_, mu3_);
2852 void unlocklots()
2853 UNLOCK_FUNCTION(mu1_)
2854 UNLOCK_FUNCTION(mu2_)
2855 UNLOCK_FUNCTION(mu1_, mu2_, mu3_);
2856};
2857
2858
2859void Foo::lock() EXCLUSIVE_LOCK_FUNCTION() { }
2860void Foo::unlock() UNLOCK_FUNCTION() { }
2861
2862void Foo::lock1() EXCLUSIVE_LOCK_FUNCTION(mu1_) {
2863 mu1_.Lock();
2864}
2865
2866void Foo::slock1() SHARED_LOCK_FUNCTION(mu1_) {
2867 mu1_.Lock();
2868}
2869
2870void Foo::lock3() EXCLUSIVE_LOCK_FUNCTION(mu1_, mu2_, mu3_) {
2871 mu1_.Lock();
2872 mu2_.Lock();
2873 mu3_.Lock();
2874}
2875
2876void Foo::locklots()
2877 EXCLUSIVE_LOCK_FUNCTION(mu1_, mu2_)
2878 EXCLUSIVE_LOCK_FUNCTION(mu2_, mu3_) {
2879 mu1_.Lock();
2880 mu2_.Lock();
2881 mu3_.Lock();
2882}
2883
2884void Foo::unlock1() UNLOCK_FUNCTION(mu1_) {
2885 mu1_.Unlock();
2886}
2887
2888void Foo::unlock3() UNLOCK_FUNCTION(mu1_, mu2_, mu3_) {
2889 mu1_.Unlock();
2890 mu2_.Unlock();
2891 mu3_.Unlock();
2892}
2893
2894void Foo::unlocklots()
2895 UNLOCK_FUNCTION(mu1_, mu2_)
2896 UNLOCK_FUNCTION(mu2_, mu3_) {
2897 mu1_.Unlock();
2898 mu2_.Unlock();
2899 mu3_.Unlock();
2900}
2901
2902
2903void test0() {
2904 Foo foo;
2905 foo.lock();
2906 foo.unlock();
2907
2908 foo.lock();
2909 foo.lock(); // expected-warning {{locking 'foo' that is already locked}}
2910 foo.unlock();
2911 foo.unlock(); // expected-warning {{unlocking 'foo' that was not locked}}
2912}
2913
2914
2915void test1() {
2916 Foo foo;
2917 foo.lock1();
2918 foo.a = 0;
2919 foo.unlock1();
2920
2921 foo.lock1();
DeLesley Hutchinsa74b7152012-08-10 20:19:55 +00002922 foo.lock1(); // expected-warning {{locking 'foo.mu1_' that is already locked}}
DeLesley Hutchins5381c052012-07-05 21:16:29 +00002923 foo.a = 0;
2924 foo.unlock1();
DeLesley Hutchinsa74b7152012-08-10 20:19:55 +00002925 foo.unlock1(); // expected-warning {{unlocking 'foo.mu1_' that was not locked}}
DeLesley Hutchins5381c052012-07-05 21:16:29 +00002926}
2927
2928
2929int test2() {
2930 Foo foo;
2931 foo.slock1();
2932 int d1 = foo.a;
2933 foo.unlock1();
2934
2935 foo.slock1();
DeLesley Hutchinsa74b7152012-08-10 20:19:55 +00002936 foo.slock1(); // expected-warning {{locking 'foo.mu1_' that is already locked}}
DeLesley Hutchins5381c052012-07-05 21:16:29 +00002937 int d2 = foo.a;
2938 foo.unlock1();
DeLesley Hutchinsa74b7152012-08-10 20:19:55 +00002939 foo.unlock1(); // expected-warning {{unlocking 'foo.mu1_' that was not locked}}
DeLesley Hutchins5381c052012-07-05 21:16:29 +00002940 return d1 + d2;
2941}
2942
2943
2944void test3() {
2945 Foo foo;
2946 foo.lock3();
2947 foo.a = 0;
2948 foo.b = 0;
2949 foo.c = 0;
2950 foo.unlock3();
2951
2952 foo.lock3();
2953 foo.lock3(); // \
DeLesley Hutchinsa74b7152012-08-10 20:19:55 +00002954 // expected-warning {{locking 'foo.mu1_' that is already locked}} \
2955 // expected-warning {{locking 'foo.mu2_' that is already locked}} \
2956 // expected-warning {{locking 'foo.mu3_' that is already locked}}
DeLesley Hutchins5381c052012-07-05 21:16:29 +00002957 foo.a = 0;
2958 foo.b = 0;
2959 foo.c = 0;
2960 foo.unlock3();
2961 foo.unlock3(); // \
DeLesley Hutchinsa74b7152012-08-10 20:19:55 +00002962 // expected-warning {{unlocking 'foo.mu1_' that was not locked}} \
2963 // expected-warning {{unlocking 'foo.mu2_' that was not locked}} \
2964 // expected-warning {{unlocking 'foo.mu3_' that was not locked}}
DeLesley Hutchins5381c052012-07-05 21:16:29 +00002965}
2966
2967
2968void testlots() {
2969 Foo foo;
2970 foo.locklots();
2971 foo.a = 0;
2972 foo.b = 0;
2973 foo.c = 0;
2974 foo.unlocklots();
2975
2976 foo.locklots();
2977 foo.locklots(); // \
DeLesley Hutchinsa74b7152012-08-10 20:19:55 +00002978 // expected-warning {{locking 'foo.mu1_' that is already locked}} \
2979 // expected-warning {{locking 'foo.mu2_' that is already locked}} \
2980 // expected-warning {{locking 'foo.mu3_' that is already locked}}
DeLesley Hutchins5381c052012-07-05 21:16:29 +00002981 foo.a = 0;
2982 foo.b = 0;
2983 foo.c = 0;
2984 foo.unlocklots();
2985 foo.unlocklots(); // \
DeLesley Hutchinsa74b7152012-08-10 20:19:55 +00002986 // expected-warning {{unlocking 'foo.mu1_' that was not locked}} \
2987 // expected-warning {{unlocking 'foo.mu2_' that was not locked}} \
2988 // expected-warning {{unlocking 'foo.mu3_' that was not locked}}
DeLesley Hutchins5381c052012-07-05 21:16:29 +00002989}
2990
2991} // end namespace DuplicateAttributeTest
2992
2993
2994
DeLesley Hutchins13106112012-07-10 21:47:55 +00002995namespace TryLockEqTest {
2996
2997class Foo {
2998 Mutex mu_;
2999 int a GUARDED_BY(mu_);
3000 bool c;
3001
3002 int tryLockMutexI() EXCLUSIVE_TRYLOCK_FUNCTION(1, mu_);
3003 Mutex* tryLockMutexP() EXCLUSIVE_TRYLOCK_FUNCTION(1, mu_);
3004 void unlock() UNLOCK_FUNCTION(mu_);
3005
3006 void test1();
3007 void test2();
3008};
3009
3010
3011void Foo::test1() {
3012 if (tryLockMutexP() == 0) {
3013 a = 0; // expected-warning {{writing variable 'a' requires locking 'mu_' exclusively}}
3014 return;
3015 }
3016 a = 0;
3017 unlock();
3018
3019 if (tryLockMutexP() != 0) {
3020 a = 0;
3021 unlock();
3022 }
3023
3024 if (0 != tryLockMutexP()) {
3025 a = 0;
3026 unlock();
3027 }
3028
3029 if (!(tryLockMutexP() == 0)) {
3030 a = 0;
3031 unlock();
3032 }
3033
3034 if (tryLockMutexI() == 0) {
3035 a = 0; // expected-warning {{writing variable 'a' requires locking 'mu_' exclusively}}
3036 return;
3037 }
3038 a = 0;
3039 unlock();
3040
3041 if (0 == tryLockMutexI()) {
3042 a = 0; // expected-warning {{writing variable 'a' requires locking 'mu_' exclusively}}
3043 return;
3044 }
3045 a = 0;
3046 unlock();
3047
3048 if (tryLockMutexI() == 1) {
3049 a = 0;
3050 unlock();
3051 }
3052
3053 if (mu_.TryLock() == false) {
3054 a = 0; // expected-warning {{writing variable 'a' requires locking 'mu_' exclusively}}
3055 return;
3056 }
3057 a = 0;
3058 unlock();
3059
3060 if (mu_.TryLock() == true) {
3061 a = 0;
3062 unlock();
3063 }
3064 else {
3065 a = 0; // expected-warning {{writing variable 'a' requires locking 'mu_' exclusively}}
3066 }
3067
3068#if __has_feature(cxx_nullptr)
3069 if (tryLockMutexP() == nullptr) {
3070 a = 0; // expected-warning {{writing variable 'a' requires locking 'mu_' exclusively}}
3071 return;
3072 }
3073 a = 0;
3074 unlock();
3075#endif
3076}
3077
3078
3079void Foo::test2() {
3080/* FIXME: these tests depend on changes to the CFG.
3081 *
3082 if (mu_.TryLock() && c) {
3083 a = 0;
3084 unlock();
3085 }
3086 else return;
3087
3088 if (c && mu_.TryLock()) {
3089 a = 0;
3090 unlock();
3091 }
3092 else return;
3093
3094 if (!(mu_.TryLock() && c))
3095 return;
3096 a = 0;
3097 unlock();
3098
3099 if (!(c && mu_.TryLock()))
3100 return;
3101 a = 0;
3102 unlock();
3103
3104 if (!(mu_.TryLock() == 0) && c) {
3105 a = 0;
3106 unlock();
3107 }
3108
3109 if (!mu_.TryLock() || c)
3110 return;
3111 a = 0;
3112 unlock();
3113*/
3114}
3115
DeLesley Hutchins13106112012-07-10 21:47:55 +00003116} // end namespace TryLockEqTest
DeLesley Hutchins5381c052012-07-05 21:16:29 +00003117
DeLesley Hutchins96fac6a2012-07-03 19:47:18 +00003118
DeLesley Hutchinsee2f0322012-08-10 20:29:46 +00003119namespace ExistentialPatternMatching {
3120
3121class Graph {
3122public:
3123 Mutex mu_;
3124};
3125
3126void LockAllGraphs() EXCLUSIVE_LOCK_FUNCTION(&Graph::mu_);
3127void UnlockAllGraphs() UNLOCK_FUNCTION(&Graph::mu_);
3128
3129class Node {
3130public:
3131 int a GUARDED_BY(&Graph::mu_);
3132
3133 void foo() EXCLUSIVE_LOCKS_REQUIRED(&Graph::mu_) {
3134 a = 0;
3135 }
3136 void foo2() LOCKS_EXCLUDED(&Graph::mu_);
3137};
3138
3139void test() {
3140 Graph g1;
3141 Graph g2;
3142 Node n1;
3143
3144 n1.a = 0; // expected-warning {{writing variable 'a' requires locking '&ExistentialPatternMatching::Graph::mu_' exclusively}}
3145 n1.foo(); // expected-warning {{calling function 'foo' requires exclusive lock on '&ExistentialPatternMatching::Graph::mu_'}}
3146 n1.foo2();
3147
3148 g1.mu_.Lock();
3149 n1.a = 0;
3150 n1.foo();
3151 n1.foo2(); // expected-warning {{cannot call function 'foo2' while mutex '&ExistentialPatternMatching::Graph::mu_' is locked}}
3152 g1.mu_.Unlock();
3153
3154 g2.mu_.Lock();
3155 n1.a = 0;
3156 n1.foo();
3157 n1.foo2(); // expected-warning {{cannot call function 'foo2' while mutex '&ExistentialPatternMatching::Graph::mu_' is locked}}
3158 g2.mu_.Unlock();
3159
3160 LockAllGraphs();
3161 n1.a = 0;
3162 n1.foo();
3163 n1.foo2(); // expected-warning {{cannot call function 'foo2' while mutex '&ExistentialPatternMatching::Graph::mu_' is locked}}
3164 UnlockAllGraphs();
3165
3166 LockAllGraphs();
3167 g1.mu_.Unlock();
3168
3169 LockAllGraphs();
3170 g2.mu_.Unlock();
3171
3172 LockAllGraphs();
3173 g1.mu_.Lock(); // expected-warning {{locking 'g1.mu_' that is already locked}}
3174 g1.mu_.Unlock();
3175}
3176
3177} // end namespace ExistentialPatternMatching
3178
DeLesley Hutchins4e4c1572012-08-31 21:57:32 +00003179
3180namespace StringIgnoreTest {
3181
3182class Foo {
3183public:
3184 Mutex mu_;
3185 void lock() EXCLUSIVE_LOCK_FUNCTION("");
3186 void unlock() UNLOCK_FUNCTION("");
3187 void goober() EXCLUSIVE_LOCKS_REQUIRED("");
3188 void roober() SHARED_LOCKS_REQUIRED("");
3189};
3190
3191
3192class Bar : public Foo {
3193public:
3194 void bar(Foo* f) {
3195 f->unlock();
3196 f->goober();
3197 f->roober();
3198 f->lock();
3199 };
3200};
3201
3202} // end namespace StringIgnoreTest
3203
3204
DeLesley Hutchins54081532012-08-31 22:09:53 +00003205namespace LockReturnedScopeFix {
3206
3207class Base {
3208protected:
3209 struct Inner;
3210 bool c;
3211
3212 const Mutex& getLock(const Inner* i);
3213
3214 void lockInner (Inner* i) EXCLUSIVE_LOCK_FUNCTION(getLock(i));
3215 void unlockInner(Inner* i) UNLOCK_FUNCTION(getLock(i));
3216 void foo(Inner* i) EXCLUSIVE_LOCKS_REQUIRED(getLock(i));
3217
3218 void bar(Inner* i);
3219};
3220
3221
3222struct Base::Inner {
3223 Mutex lock_;
3224 void doSomething() EXCLUSIVE_LOCKS_REQUIRED(lock_);
3225};
3226
3227
3228const Mutex& Base::getLock(const Inner* i) LOCK_RETURNED(i->lock_) {
3229 return i->lock_;
3230}
3231
3232
3233void Base::foo(Inner* i) {
3234 i->doSomething();
3235}
3236
3237void Base::bar(Inner* i) {
3238 if (c) {
3239 i->lock_.Lock();
3240 unlockInner(i);
3241 }
3242 else {
3243 lockInner(i);
3244 i->lock_.Unlock();
3245 }
3246}
3247
3248} // end namespace LockReturnedScopeFix
3249
DeLesley Hutchinsfd0f11c2012-09-05 20:01:16 +00003250
3251namespace TrylockWithCleanups {
3252
3253class MyString {
3254public:
3255 MyString(const char* s);
3256 ~MyString();
3257};
3258
3259struct Foo {
3260 Mutex mu_;
3261 int a GUARDED_BY(mu_);
3262};
3263
3264Foo* GetAndLockFoo(const MyString& s)
3265 EXCLUSIVE_TRYLOCK_FUNCTION(true, &Foo::mu_);
3266
3267static void test() {
3268 Foo* lt = GetAndLockFoo("foo");
3269 if (!lt) return;
3270 int a = lt->a;
3271 lt->mu_.Unlock();
3272}
3273
DeLesley Hutchins24a6c942012-09-11 18:27:46 +00003274} // end namespace TrylockWithCleanups
DeLesley Hutchinsfd0f11c2012-09-05 20:01:16 +00003275
3276
DeLesley Hutchins0b4db3e2012-09-07 17:34:53 +00003277namespace UniversalLock {
3278
3279class Foo {
3280 Mutex mu_;
3281 bool c;
3282
3283 int a GUARDED_BY(mu_);
3284 void r_foo() SHARED_LOCKS_REQUIRED(mu_);
3285 void w_foo() EXCLUSIVE_LOCKS_REQUIRED(mu_);
3286
3287 void test1() {
3288 int b;
3289
3290 beginNoWarnOnReads();
3291 b = a;
3292 r_foo();
3293 endNoWarnOnReads();
3294
3295 beginNoWarnOnWrites();
3296 a = 0;
3297 w_foo();
3298 endNoWarnOnWrites();
3299 }
3300
3301 // don't warn on joins with universal lock
3302 void test2() {
3303 if (c) {
3304 beginNoWarnOnWrites();
3305 }
3306 a = 0; // \
3307 // expected-warning {{writing variable 'a' requires locking 'mu_' exclusively}}
3308 endNoWarnOnWrites(); // \
3309 // expected-warning {{unlocking '*' that was not locked}}
3310 }
3311
3312
3313 // make sure the universal lock joins properly
3314 void test3() {
3315 if (c) {
3316 mu_.Lock();
3317 beginNoWarnOnWrites();
3318 }
3319 else {
3320 beginNoWarnOnWrites();
3321 mu_.Lock();
3322 }
3323 a = 0;
3324 endNoWarnOnWrites();
3325 mu_.Unlock();
3326 }
3327
3328
3329 // combine universal lock with other locks
3330 void test4() {
3331 beginNoWarnOnWrites();
3332 mu_.Lock();
3333 mu_.Unlock();
3334 endNoWarnOnWrites();
3335
3336 mu_.Lock();
3337 beginNoWarnOnWrites();
3338 endNoWarnOnWrites();
3339 mu_.Unlock();
3340
3341 mu_.Lock();
3342 beginNoWarnOnWrites();
3343 mu_.Unlock();
3344 endNoWarnOnWrites();
3345 }
3346};
3347
DeLesley Hutchins24a6c942012-09-11 18:27:46 +00003348} // end namespace UniversalLock
3349
3350
3351namespace TemplateLockReturned {
3352
3353template<class T>
3354class BaseT {
3355public:
3356 virtual void baseMethod() = 0;
3357 Mutex* get_mutex() LOCK_RETURNED(mutex_) { return &mutex_; }
3358
3359 Mutex mutex_;
3360 int a GUARDED_BY(mutex_);
3361};
3362
3363
3364class Derived : public BaseT<int> {
3365public:
3366 void baseMethod() EXCLUSIVE_LOCKS_REQUIRED(get_mutex()) {
3367 a = 0;
3368 }
3369};
3370
3371} // end namespace TemplateLockReturned
3372
3373
DeLesley Hutchinsf9ee0ba2012-09-11 23:04:49 +00003374namespace ExprMatchingBugFix {
3375
3376class Foo {
3377public:
3378 Mutex mu_;
3379};
3380
3381
3382class Bar {
3383public:
3384 bool c;
3385 Foo* foo;
3386 Bar(Foo* f) : foo(f) { }
3387
3388 struct Nested {
3389 Foo* foo;
3390 Nested(Foo* f) : foo(f) { }
3391
3392 void unlockFoo() UNLOCK_FUNCTION(&Foo::mu_);
3393 };
3394
3395 void test();
3396};
3397
3398
3399void Bar::test() {
3400 foo->mu_.Lock();
3401 if (c) {
3402 Nested *n = new Nested(foo);
3403 n->unlockFoo();
3404 }
3405 else {
3406 foo->mu_.Unlock();
3407 }
3408}
3409
3410}; // end namespace ExprMatchingBugfix
3411
3412
DeLesley Hutchins5b280f22012-09-19 19:18:29 +00003413namespace ComplexNameTest {
DeLesley Hutchinsf9ee0ba2012-09-11 23:04:49 +00003414
DeLesley Hutchins5b280f22012-09-19 19:18:29 +00003415class Foo {
3416public:
3417 static Mutex mu_;
3418
3419 Foo() EXCLUSIVE_LOCKS_REQUIRED(mu_) { }
3420 ~Foo() EXCLUSIVE_LOCKS_REQUIRED(mu_) { }
3421
3422 int operator[](int i) EXCLUSIVE_LOCKS_REQUIRED(mu_) { return 0; }
3423};
3424
3425class Bar {
3426public:
3427 static Mutex mu_;
3428
3429 Bar() LOCKS_EXCLUDED(mu_) { }
3430 ~Bar() LOCKS_EXCLUDED(mu_) { }
3431
3432 int operator[](int i) LOCKS_EXCLUDED(mu_) { return 0; }
3433};
3434
3435
3436void test1() {
3437 Foo f; // expected-warning {{calling function 'Foo' requires exclusive lock on 'mu_'}}
3438 int a = f[0]; // expected-warning {{calling function 'operator[]' requires exclusive lock on 'mu_'}}
3439} // expected-warning {{calling function '~Foo' requires exclusive lock on 'mu_'}}
3440
3441
3442void test2() {
3443 Bar::mu_.Lock();
3444 {
3445 Bar b; // expected-warning {{cannot call function 'Bar' while mutex 'mu_' is locked}}
3446 int a = b[0]; // expected-warning {{cannot call function 'operator[]' while mutex 'mu_' is locked}}
3447 } // expected-warning {{cannot call function '~Bar' while mutex 'mu_' is locked}}
3448 Bar::mu_.Unlock();
3449}
3450
3451}; // end namespace ComplexNameTest
DeLesley Hutchins2a237e02012-09-19 19:49:40 +00003452
3453
3454namespace UnreachableExitTest {
3455
3456class FemmeFatale {
3457public:
3458 FemmeFatale();
3459 ~FemmeFatale() __attribute__((noreturn));
3460};
3461
3462void exitNow() __attribute__((noreturn));
3463
3464Mutex fatalmu_;
3465
3466void test1() EXCLUSIVE_LOCKS_REQUIRED(fatalmu_) {
3467 exitNow();
3468}
3469
3470void test2() EXCLUSIVE_LOCKS_REQUIRED(fatalmu_) {
3471 FemmeFatale femme;
3472}
3473
3474bool c;
3475
3476void test3() EXCLUSIVE_LOCKS_REQUIRED(fatalmu_) {
3477 if (c) {
3478 exitNow();
3479 }
3480 else {
3481 FemmeFatale femme;
3482 }
3483}
3484
3485} // end namespace UnreachableExitTest
DeLesley Hutchins186af2d2012-09-20 22:18:02 +00003486
3487
3488namespace VirtualMethodCanonicalizationTest {
3489
3490class Base {
3491public:
3492 virtual Mutex* getMutex() = 0;
3493};
3494
3495class Base2 : public Base {
3496public:
3497 Mutex* getMutex();
3498};
3499
3500class Base3 : public Base2 {
3501public:
3502 Mutex* getMutex();
3503};
3504
3505class Derived : public Base3 {
3506public:
3507 Mutex* getMutex(); // overrides Base::getMutex()
3508};
3509
3510void baseFun(Base *b) EXCLUSIVE_LOCKS_REQUIRED(b->getMutex()) { }
3511
3512void derivedFun(Derived *d) EXCLUSIVE_LOCKS_REQUIRED(d->getMutex()) {
3513 baseFun(d);
3514}
3515
3516} // end namespace VirtualMethodCanonicalizationTest
3517