blob: a8b533875d3aad4656e80c8ab6018de1c82a32ad [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
27//-----------------------------------------//
28// Helper fields
29//-----------------------------------------//
30
31
32class __attribute__((lockable)) Mutex {
33 public:
34 void Lock() __attribute__((exclusive_lock_function));
35 void ReaderLock() __attribute__((shared_lock_function));
36 void Unlock() __attribute__((unlock_function));
37 bool TryLock() __attribute__((exclusive_trylock_function(true)));
38 bool ReaderTryLock() __attribute__((shared_trylock_function(true)));
39 void LockWhen(const int &cond) __attribute__((exclusive_lock_function));
40};
41
DeLesley Hutchins1fa3c062011-12-08 20:23:06 +000042class __attribute__((scoped_lockable)) MutexLock {
43 public:
44 MutexLock(Mutex *mu) __attribute__((exclusive_lock_function(mu)));
45 ~MutexLock() __attribute__((unlock_function));
46};
47
48class __attribute__((scoped_lockable)) ReaderMutexLock {
49 public:
50 ReaderMutexLock(Mutex *mu) __attribute__((exclusive_lock_function(mu)));
51 ~ReaderMutexLock() __attribute__((unlock_function));
52};
53
DeLesley Hutchinsc99a5d82012-06-28 22:42:48 +000054class SCOPED_LOCKABLE ReleasableMutexLock {
55 public:
56 ReleasableMutexLock(Mutex *mu) EXCLUSIVE_LOCK_FUNCTION(mu);
57 ~ReleasableMutexLock() UNLOCK_FUNCTION();
58
59 void Release() UNLOCK_FUNCTION();
60};
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +000061
DeLesley Hutchins9d6e7f32012-07-03 18:25:56 +000062
63template<class T>
64class SmartPtr {
65public:
66 SmartPtr(T* p) : ptr_(p) { }
67 SmartPtr(const SmartPtr<T>& p) : ptr_(p.ptr_) { }
68 ~SmartPtr();
69
70 T* get() const { return ptr_; }
71 T* operator->() const { return ptr_; }
DeLesley Hutchins96fac6a2012-07-03 19:47:18 +000072 T& operator*() const { return *ptr_; }
DeLesley Hutchins9d6e7f32012-07-03 18:25:56 +000073
74private:
75 T* ptr_;
76};
77
78
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +000079Mutex sls_mu;
80
81Mutex sls_mu2 __attribute__((acquired_after(sls_mu)));
82int sls_guard_var __attribute__((guarded_var)) = 0;
83int sls_guardby_var __attribute__((guarded_by(sls_mu))) = 0;
84
85bool getBool();
86
87class MutexWrapper {
88public:
89 Mutex mu;
Caitlin Sadowski194418f2011-09-14 20:00:24 +000090 int x __attribute__((guarded_by(mu)));
91 void MyLock() __attribute__((exclusive_lock_function(mu)));
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +000092};
93
94MutexWrapper sls_mw;
95
96void sls_fun_0() {
97 sls_mw.mu.Lock();
Caitlin Sadowski194418f2011-09-14 20:00:24 +000098 sls_mw.x = 5;
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +000099 sls_mw.mu.Unlock();
100}
101
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000102void sls_fun_2() {
103 sls_mu.Lock();
104 int x = sls_guard_var;
105 sls_mu.Unlock();
106}
107
108void sls_fun_3() {
109 sls_mu.Lock();
110 sls_guard_var = 2;
111 sls_mu.Unlock();
112}
113
114void sls_fun_4() {
115 sls_mu2.Lock();
116 sls_guard_var = 2;
117 sls_mu2.Unlock();
118}
119
120void sls_fun_5() {
121 sls_mu.Lock();
122 int x = sls_guardby_var;
123 sls_mu.Unlock();
124}
125
126void sls_fun_6() {
127 sls_mu.Lock();
128 sls_guardby_var = 2;
129 sls_mu.Unlock();
130}
131
132void sls_fun_7() {
133 sls_mu.Lock();
134 sls_mu2.Lock();
135 sls_mu2.Unlock();
136 sls_mu.Unlock();
137}
138
139void sls_fun_8() {
140 sls_mu.Lock();
141 if (getBool())
142 sls_mu.Unlock();
143 else
144 sls_mu.Unlock();
145}
146
147void sls_fun_9() {
148 if (getBool())
149 sls_mu.Lock();
150 else
151 sls_mu.Lock();
152 sls_mu.Unlock();
153}
154
155void sls_fun_good_6() {
156 if (getBool()) {
157 sls_mu.Lock();
158 } else {
159 if (getBool()) {
160 getBool(); // EMPTY
161 } else {
162 getBool(); // EMPTY
163 }
164 sls_mu.Lock();
165 }
166 sls_mu.Unlock();
167}
168
169void sls_fun_good_7() {
170 sls_mu.Lock();
171 while (getBool()) {
172 sls_mu.Unlock();
173 if (getBool()) {
174 if (getBool()) {
175 sls_mu.Lock();
176 continue;
177 }
178 }
179 sls_mu.Lock();
180 }
181 sls_mu.Unlock();
182}
183
Caitlin Sadowski194418f2011-09-14 20:00:24 +0000184void sls_fun_good_8() {
185 sls_mw.MyLock();
186 sls_mw.mu.Unlock();
187}
188
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000189void sls_fun_bad_1() {
190 sls_mu.Unlock(); // \
Caitlin Sadowski8bccabe2011-09-08 21:52:50 +0000191 // expected-warning{{unlocking 'sls_mu' that was not locked}}
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000192}
193
194void sls_fun_bad_2() {
195 sls_mu.Lock();
196 sls_mu.Lock(); // \
Caitlin Sadowski8bccabe2011-09-08 21:52:50 +0000197 // expected-warning{{locking 'sls_mu' that is already locked}}
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000198 sls_mu.Unlock();
199}
200
201void sls_fun_bad_3() {
Richard Smith2e515622012-02-03 04:45:26 +0000202 sls_mu.Lock(); // expected-note {{mutex acquired here}}
203} // expected-warning{{mutex 'sls_mu' is still locked at the end of function}}
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000204
205void sls_fun_bad_4() {
206 if (getBool())
DeLesley Hutchins0da44142012-06-22 17:07:28 +0000207 sls_mu.Lock(); // expected-note{{mutex acquired here}}
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000208 else
DeLesley Hutchins0da44142012-06-22 17:07:28 +0000209 sls_mu2.Lock(); // expected-note{{mutex acquired here}}
210} // expected-warning{{mutex 'sls_mu' is not locked on every path through here}} \
211 // expected-warning{{mutex 'sls_mu2' is not locked on every path through here}}
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000212
213void sls_fun_bad_5() {
Richard Smith2e515622012-02-03 04:45:26 +0000214 sls_mu.Lock(); // expected-note {{mutex acquired here}}
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000215 if (getBool())
216 sls_mu.Unlock();
Richard Smith2e515622012-02-03 04:45:26 +0000217} // expected-warning{{mutex 'sls_mu' is not locked on every path through here}}
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000218
219void sls_fun_bad_6() {
220 if (getBool()) {
Richard Smith2e515622012-02-03 04:45:26 +0000221 sls_mu.Lock(); // expected-note {{mutex acquired here}}
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000222 } else {
223 if (getBool()) {
224 getBool(); // EMPTY
225 } else {
226 getBool(); // EMPTY
227 }
228 }
229 sls_mu.Unlock(); // \
Richard Smith2e515622012-02-03 04:45:26 +0000230 expected-warning{{mutex 'sls_mu' is not locked on every path through here}}\
231 expected-warning{{unlocking 'sls_mu' that was not locked}}
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000232}
233
234void sls_fun_bad_7() {
Richard Smithaacde712012-02-03 03:30:07 +0000235 sls_mu.Lock();
Caitlin Sadowski4e4bc752011-09-15 17:25:19 +0000236 while (getBool()) {
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000237 sls_mu.Unlock();
238 if (getBool()) {
239 if (getBool()) {
Richard Smith2e515622012-02-03 04:45:26 +0000240 continue; // \
241 expected-warning{{expecting mutex 'sls_mu' to be locked at start of each loop}}
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000242 }
243 }
Richard Smith2e515622012-02-03 04:45:26 +0000244 sls_mu.Lock(); // expected-note {{mutex acquired here}}
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000245 }
246 sls_mu.Unlock();
247}
248
249void sls_fun_bad_8() {
Richard Smith2e515622012-02-03 04:45:26 +0000250 sls_mu.Lock(); // expected-note{{mutex acquired here}}
251
DeLesley Hutchins0da44142012-06-22 17:07:28 +0000252 do {
253 sls_mu.Unlock(); // expected-warning{{expecting mutex 'sls_mu' to be locked at start of each loop}}
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000254 } while (getBool());
255}
256
257void sls_fun_bad_9() {
258 do {
DeLesley Hutchins0da44142012-06-22 17:07:28 +0000259 sls_mu.Lock(); // \
Richard Smith2e515622012-02-03 04:45:26 +0000260 // expected-warning{{expecting mutex 'sls_mu' to be locked at start of each loop}} \
261 // expected-note{{mutex acquired here}}
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000262 } while (getBool());
263 sls_mu.Unlock();
264}
265
266void sls_fun_bad_10() {
DeLesley Hutchins0da44142012-06-22 17:07:28 +0000267 sls_mu.Lock(); // expected-note 2{{mutex acquired here}}
268 while(getBool()) { // expected-warning{{expecting mutex 'sls_mu' to be locked at start of each loop}}
269 sls_mu.Unlock();
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000270 }
Richard Smith2e515622012-02-03 04:45:26 +0000271} // expected-warning{{mutex 'sls_mu' is still locked at the end of function}}
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000272
273void sls_fun_bad_11() {
Richard Smith2e515622012-02-03 04:45:26 +0000274 while (getBool()) { // \
DeLesley Hutchins0da44142012-06-22 17:07:28 +0000275 expected-warning{{expecting mutex 'sls_mu' to be locked at start of each loop}}
Richard Smith2e515622012-02-03 04:45:26 +0000276 sls_mu.Lock(); // expected-note {{mutex acquired here}}
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000277 }
278 sls_mu.Unlock(); // \
Caitlin Sadowski8bccabe2011-09-08 21:52:50 +0000279 // expected-warning{{unlocking 'sls_mu' that was not locked}}
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000280}
281
Richard Smithaacde712012-02-03 03:30:07 +0000282void sls_fun_bad_12() {
Richard Smith2e515622012-02-03 04:45:26 +0000283 sls_mu.Lock(); // expected-note {{mutex acquired here}}
Richard Smithaacde712012-02-03 03:30:07 +0000284 while (getBool()) {
285 sls_mu.Unlock();
286 if (getBool()) {
287 if (getBool()) {
Richard Smith2e515622012-02-03 04:45:26 +0000288 break; // expected-warning{{mutex 'sls_mu' is not locked on every path through here}}
Richard Smithaacde712012-02-03 03:30:07 +0000289 }
290 }
291 sls_mu.Lock();
292 }
293 sls_mu.Unlock();
294}
295
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000296//-----------------------------------------//
297// Handling lock expressions in attribute args
298// -------------------------------------------//
299
300Mutex aa_mu;
301
302class GlobalLocker {
303public:
304 void globalLock() __attribute__((exclusive_lock_function(aa_mu)));
305 void globalUnlock() __attribute__((unlock_function(aa_mu)));
306};
307
308GlobalLocker glock;
309
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000310void aa_fun_1() {
311 glock.globalLock();
312 glock.globalUnlock();
313}
314
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000315void aa_fun_bad_1() {
316 glock.globalUnlock(); // \
Caitlin Sadowski8bccabe2011-09-08 21:52:50 +0000317 // expected-warning{{unlocking 'aa_mu' that was not locked}}
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000318}
319
320void aa_fun_bad_2() {
321 glock.globalLock();
322 glock.globalLock(); // \
Caitlin Sadowski8bccabe2011-09-08 21:52:50 +0000323 // expected-warning{{locking 'aa_mu' that is already locked}}
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000324 glock.globalUnlock();
325}
326
327void aa_fun_bad_3() {
Richard Smith2e515622012-02-03 04:45:26 +0000328 glock.globalLock(); // expected-note{{mutex acquired here}}
329} // expected-warning{{mutex 'aa_mu' is still locked at the end of function}}
Caitlin Sadowskib4d0a962011-08-29 17:12:27 +0000330
Caitlin Sadowskib4d0a962011-08-29 17:12:27 +0000331//--------------------------------------------------//
332// Regression tests for unusual method names
333//--------------------------------------------------//
334
335Mutex wmu;
336
337// Test diagnostics for other method names.
338class WeirdMethods {
DeLesley Hutchins2f13bec2012-02-16 17:13:43 +0000339 // FIXME: can't currently check inside constructors and destructors.
Caitlin Sadowskib4d0a962011-08-29 17:12:27 +0000340 WeirdMethods() {
DeLesley Hutchins2f13bec2012-02-16 17:13:43 +0000341 wmu.Lock(); // EXPECTED-NOTE {{mutex acquired here}}
342 } // EXPECTED-WARNING {{mutex 'wmu' is still locked at the end of function}}
Caitlin Sadowskib4d0a962011-08-29 17:12:27 +0000343 ~WeirdMethods() {
DeLesley Hutchins2f13bec2012-02-16 17:13:43 +0000344 wmu.Lock(); // EXPECTED-NOTE {{mutex acquired here}}
345 } // EXPECTED-WARNING {{mutex 'wmu' is still locked at the end of function}}
Caitlin Sadowskib4d0a962011-08-29 17:12:27 +0000346 void operator++() {
Richard Smith2e515622012-02-03 04:45:26 +0000347 wmu.Lock(); // expected-note {{mutex acquired here}}
348 } // expected-warning {{mutex 'wmu' is still locked at the end of function}}
Caitlin Sadowskib4d0a962011-08-29 17:12:27 +0000349 operator int*() {
Richard Smith2e515622012-02-03 04:45:26 +0000350 wmu.Lock(); // expected-note {{mutex acquired here}}
Caitlin Sadowskib4d0a962011-08-29 17:12:27 +0000351 return 0;
Richard Smith2e515622012-02-03 04:45:26 +0000352 } // expected-warning {{mutex 'wmu' is still locked at the end of function}}
Caitlin Sadowskib4d0a962011-08-29 17:12:27 +0000353};
354
Caitlin Sadowski05b436e2011-08-29 22:27:51 +0000355//-----------------------------------------------//
356// Errors for guarded by or guarded var variables
357// ----------------------------------------------//
358
359int *pgb_gvar __attribute__((pt_guarded_var));
360int *pgb_var __attribute__((pt_guarded_by(sls_mu)));
361
362class PGBFoo {
363 public:
364 int x;
365 int *pgb_field __attribute__((guarded_by(sls_mu2)))
366 __attribute__((pt_guarded_by(sls_mu)));
367 void testFoo() {
368 pgb_field = &x; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000369 // expected-warning {{writing variable 'pgb_field' requires locking 'sls_mu2' exclusively}}
370 *pgb_field = x; // expected-warning {{reading variable 'pgb_field' requires locking 'sls_mu2'}} \
371 // expected-warning {{writing the value pointed to by 'pgb_field' requires locking 'sls_mu' exclusively}}
372 x = *pgb_field; // expected-warning {{reading variable 'pgb_field' requires locking 'sls_mu2'}} \
373 // expected-warning {{reading the value pointed to by 'pgb_field' requires locking 'sls_mu'}}
374 (*pgb_field)++; // 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}}
Caitlin Sadowski05b436e2011-08-29 22:27:51 +0000376 }
377};
378
379class GBFoo {
380 public:
381 int gb_field __attribute__((guarded_by(sls_mu)));
382
383 void testFoo() {
384 gb_field = 0; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000385 // expected-warning {{writing variable 'gb_field' requires locking 'sls_mu' exclusively}}
Caitlin Sadowski05b436e2011-08-29 22:27:51 +0000386 }
Caitlin Sadowskiaf370612011-09-08 18:35:21 +0000387
388 void testNoAnal() __attribute__((no_thread_safety_analysis)) {
389 gb_field = 0;
390 }
Caitlin Sadowski05b436e2011-08-29 22:27:51 +0000391};
392
393GBFoo GlobalGBFoo __attribute__((guarded_by(sls_mu)));
394
395void gb_fun_0() {
396 sls_mu.Lock();
397 int x = *pgb_var;
398 sls_mu.Unlock();
399}
400
401void gb_fun_1() {
402 sls_mu.Lock();
403 *pgb_var = 2;
404 sls_mu.Unlock();
405}
406
407void gb_fun_2() {
408 int x;
409 pgb_var = &x;
410}
411
412void gb_fun_3() {
413 int *x = pgb_var;
414}
415
416void gb_bad_0() {
417 sls_guard_var = 1; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000418 // expected-warning{{writing variable 'sls_guard_var' requires locking any mutex exclusively}}
Caitlin Sadowski05b436e2011-08-29 22:27:51 +0000419}
420
421void gb_bad_1() {
422 int x = sls_guard_var; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000423 // expected-warning{{reading variable 'sls_guard_var' requires locking any mutex}}
Caitlin Sadowski05b436e2011-08-29 22:27:51 +0000424}
425
426void gb_bad_2() {
427 sls_guardby_var = 1; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000428 // expected-warning {{writing variable 'sls_guardby_var' requires locking 'sls_mu' exclusively}}
Caitlin Sadowski05b436e2011-08-29 22:27:51 +0000429}
430
431void gb_bad_3() {
432 int x = sls_guardby_var; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000433 // expected-warning {{reading variable 'sls_guardby_var' requires locking 'sls_mu'}}
Caitlin Sadowski05b436e2011-08-29 22:27:51 +0000434}
435
436void gb_bad_4() {
437 *pgb_gvar = 1; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000438 // expected-warning {{writing the value pointed to by 'pgb_gvar' requires locking any mutex exclusively}}
Caitlin Sadowski05b436e2011-08-29 22:27:51 +0000439}
440
441void gb_bad_5() {
442 int x = *pgb_gvar; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000443 // expected-warning {{reading the value pointed to by 'pgb_gvar' requires locking any mutex}}
Caitlin Sadowski05b436e2011-08-29 22:27:51 +0000444}
445
446void gb_bad_6() {
447 *pgb_var = 1; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000448 // expected-warning {{writing the value pointed to by 'pgb_var' requires locking 'sls_mu' exclusively}}
Caitlin Sadowski05b436e2011-08-29 22:27:51 +0000449}
450
451void gb_bad_7() {
452 int x = *pgb_var; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000453 // expected-warning {{reading the value pointed to by 'pgb_var' requires locking 'sls_mu'}}
Caitlin Sadowski05b436e2011-08-29 22:27:51 +0000454}
455
456void gb_bad_8() {
457 GBFoo G;
458 G.gb_field = 0; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000459 // expected-warning {{writing variable 'gb_field' requires locking 'sls_mu'}}
Caitlin Sadowski05b436e2011-08-29 22:27:51 +0000460}
461
462void gb_bad_9() {
463 sls_guard_var++; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000464 // expected-warning{{writing variable 'sls_guard_var' requires locking any mutex exclusively}}
Caitlin Sadowski05b436e2011-08-29 22:27:51 +0000465 sls_guard_var--; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000466 // expected-warning{{writing variable 'sls_guard_var' requires locking any mutex exclusively}}
Caitlin Sadowski05b436e2011-08-29 22:27:51 +0000467 ++sls_guard_var; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000468 // expected-warning{{writing variable 'sls_guard_var' requires locking any mutex exclusively}}
Caitlin Sadowskia49d1d82011-09-09 16:07:55 +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}
Caitlin Sadowskib4d0a962011-08-29 17:12:27 +0000472
Caitlin Sadowskieff98fc2011-09-08 17:42:22 +0000473//-----------------------------------------------//
474// Warnings on variables with late parsed attributes
475// ----------------------------------------------//
476
477class LateFoo {
478public:
479 int a __attribute__((guarded_by(mu)));
480 int b;
481
482 void foo() __attribute__((exclusive_locks_required(mu))) { }
483
484 void test() {
485 a = 0; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000486 // expected-warning{{writing variable 'a' requires locking 'mu' exclusively}}
Caitlin Sadowskieff98fc2011-09-08 17:42:22 +0000487 b = a; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000488 // expected-warning {{reading variable 'a' requires locking 'mu'}}
Caitlin Sadowskieff98fc2011-09-08 17:42:22 +0000489 c = 0; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000490 // expected-warning {{writing variable 'c' requires locking 'mu' exclusively}}
Caitlin Sadowskieff98fc2011-09-08 17:42:22 +0000491 }
492
493 int c __attribute__((guarded_by(mu)));
494
495 Mutex mu;
496};
497
Caitlin Sadowski99107eb2011-09-09 16:21:55 +0000498class LateBar {
499 public:
500 int a_ __attribute__((guarded_by(mu1_)));
501 int b_;
502 int *q __attribute__((pt_guarded_by(mu)));
503 Mutex mu1_;
504 Mutex mu;
505 LateFoo Foo;
506 LateFoo Foo2;
507 LateFoo *FooPointer;
508};
509
510LateBar b1, *b3;
511
512void late_0() {
513 LateFoo FooA;
514 LateFoo FooB;
515 FooA.mu.Lock();
516 FooA.a = 5;
517 FooA.mu.Unlock();
518}
519
520void late_1() {
521 LateBar BarA;
522 BarA.FooPointer->mu.Lock();
523 BarA.FooPointer->a = 2;
524 BarA.FooPointer->mu.Unlock();
525}
526
527void late_bad_0() {
528 LateFoo fooA;
529 LateFoo fooB;
530 fooA.mu.Lock();
531 fooB.a = 5; // \
DeLesley Hutchinsa74b7152012-08-10 20:19:55 +0000532 // expected-warning{{writing variable 'a' requires locking 'fooB.mu' exclusively}}
Caitlin Sadowski99107eb2011-09-09 16:21:55 +0000533 fooA.mu.Unlock();
534}
535
536void late_bad_1() {
537 Mutex mu;
538 mu.Lock();
539 b1.mu1_.Lock();
540 int res = b1.a_ + b3->b_;
541 b3->b_ = *b1.q; // \
DeLesley Hutchinsa74b7152012-08-10 20:19:55 +0000542 // expected-warning{{reading the value pointed to by 'q' requires locking 'b1.mu'}}
Caitlin Sadowski99107eb2011-09-09 16:21:55 +0000543 b1.mu1_.Unlock();
544 b1.b_ = res;
545 mu.Unlock();
546}
547
548void late_bad_2() {
549 LateBar BarA;
550 BarA.FooPointer->mu.Lock();
551 BarA.Foo.a = 2; // \
DeLesley Hutchinsa74b7152012-08-10 20:19:55 +0000552 // expected-warning{{writing variable 'a' requires locking 'BarA.Foo.mu' exclusively}}
Caitlin Sadowski99107eb2011-09-09 16:21:55 +0000553 BarA.FooPointer->mu.Unlock();
554}
555
556void late_bad_3() {
557 LateBar BarA;
558 BarA.Foo.mu.Lock();
559 BarA.FooPointer->a = 2; // \
DeLesley Hutchinsa74b7152012-08-10 20:19:55 +0000560 // expected-warning{{writing variable 'a' requires locking 'BarA.FooPointer->mu' exclusively}}
Caitlin Sadowski99107eb2011-09-09 16:21:55 +0000561 BarA.Foo.mu.Unlock();
562}
563
564void late_bad_4() {
565 LateBar BarA;
566 BarA.Foo.mu.Lock();
567 BarA.Foo2.a = 2; // \
DeLesley Hutchinsa74b7152012-08-10 20:19:55 +0000568 // expected-warning{{writing variable 'a' requires locking 'BarA.Foo2.mu' exclusively}}
Caitlin Sadowski99107eb2011-09-09 16:21:55 +0000569 BarA.Foo.mu.Unlock();
570}
571
Caitlin Sadowskia53257c2011-09-08 18:19:38 +0000572//-----------------------------------------------//
573// Extra warnings for shared vs. exclusive locks
574// ----------------------------------------------//
575
576void shared_fun_0() {
577 sls_mu.Lock();
578 do {
579 sls_mu.Unlock();
580 sls_mu.Lock();
581 } while (getBool());
582 sls_mu.Unlock();
583}
584
585void shared_fun_1() {
Caitlin Sadowski4e4bc752011-09-15 17:25:19 +0000586 sls_mu.ReaderLock(); // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000587 // expected-warning {{mutex 'sls_mu' is locked exclusively and shared in the same scope}}
Caitlin Sadowskia53257c2011-09-08 18:19:38 +0000588 do {
589 sls_mu.Unlock();
Caitlin Sadowski4e4bc752011-09-15 17:25:19 +0000590 sls_mu.Lock(); // \
591 // expected-note {{the other lock of mutex 'sls_mu' is here}}
Caitlin Sadowskia53257c2011-09-08 18:19:38 +0000592 } while (getBool());
593 sls_mu.Unlock();
594}
595
596void shared_fun_3() {
597 if (getBool())
598 sls_mu.Lock();
599 else
600 sls_mu.Lock();
601 *pgb_var = 1;
602 sls_mu.Unlock();
603}
604
605void shared_fun_4() {
606 if (getBool())
607 sls_mu.ReaderLock();
608 else
609 sls_mu.ReaderLock();
610 int x = sls_guardby_var;
611 sls_mu.Unlock();
612}
613
614void shared_fun_8() {
615 if (getBool())
616 sls_mu.Lock(); // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000617 // expected-warning {{mutex 'sls_mu' is locked exclusively and shared in the same scope}}
Caitlin Sadowskia53257c2011-09-08 18:19:38 +0000618 else
619 sls_mu.ReaderLock(); // \
Caitlin Sadowski8bccabe2011-09-08 21:52:50 +0000620 // expected-note {{the other lock of mutex 'sls_mu' is here}}
Caitlin Sadowskia53257c2011-09-08 18:19:38 +0000621 sls_mu.Unlock();
622}
623
624void shared_bad_0() {
Caitlin Sadowski4e4bc752011-09-15 17:25:19 +0000625 sls_mu.Lock(); // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000626 // expected-warning {{mutex 'sls_mu' is locked exclusively and shared in the same scope}}
Caitlin Sadowskia53257c2011-09-08 18:19:38 +0000627 do {
628 sls_mu.Unlock();
Caitlin Sadowski4e4bc752011-09-15 17:25:19 +0000629 sls_mu.ReaderLock(); // \
630 // expected-note {{the other lock of mutex 'sls_mu' is here}}
Caitlin Sadowskia53257c2011-09-08 18:19:38 +0000631 } while (getBool());
632 sls_mu.Unlock();
633}
634
635void shared_bad_1() {
636 if (getBool())
637 sls_mu.Lock(); // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000638 // expected-warning {{mutex 'sls_mu' is locked exclusively and shared in the same scope}}
Caitlin Sadowskia53257c2011-09-08 18:19:38 +0000639 else
640 sls_mu.ReaderLock(); // \
Caitlin Sadowski8bccabe2011-09-08 21:52:50 +0000641 // expected-note {{the other lock of mutex 'sls_mu' is here}}
Caitlin Sadowskia53257c2011-09-08 18:19:38 +0000642 *pgb_var = 1;
643 sls_mu.Unlock();
644}
645
646void shared_bad_2() {
647 if (getBool())
648 sls_mu.ReaderLock(); // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000649 // expected-warning {{mutex 'sls_mu' is locked exclusively and shared in the same scope}}
Caitlin Sadowskia53257c2011-09-08 18:19:38 +0000650 else
651 sls_mu.Lock(); // \
Caitlin Sadowski8bccabe2011-09-08 21:52:50 +0000652 // expected-note {{the other lock of mutex 'sls_mu' is here}}
Caitlin Sadowskia53257c2011-09-08 18:19:38 +0000653 *pgb_var = 1;
654 sls_mu.Unlock();
655}
Caitlin Sadowski978191e2011-09-08 18:27:31 +0000656
657// FIXME: Add support for functions (not only methods)
658class LRBar {
659 public:
660 void aa_elr_fun() __attribute__((exclusive_locks_required(aa_mu)));
661 void aa_elr_fun_s() __attribute__((shared_locks_required(aa_mu)));
662 void le_fun() __attribute__((locks_excluded(sls_mu)));
663};
664
665class LRFoo {
666 public:
667 void test() __attribute__((exclusive_locks_required(sls_mu)));
668 void testShared() __attribute__((shared_locks_required(sls_mu2)));
669};
670
671void elr_fun() __attribute__((exclusive_locks_required(sls_mu)));
672void elr_fun() {}
673
674LRFoo MyLRFoo;
675LRBar Bar;
676
677void es_fun_0() {
678 aa_mu.Lock();
679 Bar.aa_elr_fun();
680 aa_mu.Unlock();
681}
682
683void es_fun_1() {
684 aa_mu.Lock();
685 Bar.aa_elr_fun_s();
686 aa_mu.Unlock();
687}
688
689void es_fun_2() {
690 aa_mu.ReaderLock();
691 Bar.aa_elr_fun_s();
692 aa_mu.Unlock();
693}
694
695void es_fun_3() {
696 sls_mu.Lock();
697 MyLRFoo.test();
698 sls_mu.Unlock();
699}
700
701void es_fun_4() {
702 sls_mu2.Lock();
703 MyLRFoo.testShared();
704 sls_mu2.Unlock();
705}
706
707void es_fun_5() {
708 sls_mu2.ReaderLock();
709 MyLRFoo.testShared();
710 sls_mu2.Unlock();
711}
712
713void es_fun_6() {
714 Bar.le_fun();
715}
716
717void es_fun_7() {
718 sls_mu.Lock();
719 elr_fun();
720 sls_mu.Unlock();
721}
722
Caitlin Sadowskiaf370612011-09-08 18:35:21 +0000723void es_fun_8() __attribute__((no_thread_safety_analysis));
724
725void es_fun_8() {
726 Bar.aa_elr_fun_s();
727}
728
Caitlin Sadowskicb967512011-09-15 17:43:08 +0000729void es_fun_9() __attribute__((shared_locks_required(aa_mu)));
730void es_fun_9() {
731 Bar.aa_elr_fun_s();
732}
733
734void es_fun_10() __attribute__((exclusive_locks_required(aa_mu)));
735void es_fun_10() {
736 Bar.aa_elr_fun_s();
737}
738
Caitlin Sadowski978191e2011-09-08 18:27:31 +0000739void es_bad_0() {
740 Bar.aa_elr_fun(); // \
Caitlin Sadowski8bccabe2011-09-08 21:52:50 +0000741 // expected-warning {{calling function 'aa_elr_fun' requires exclusive lock on 'aa_mu'}}
Caitlin Sadowski978191e2011-09-08 18:27:31 +0000742}
743
744void es_bad_1() {
745 aa_mu.ReaderLock();
746 Bar.aa_elr_fun(); // \
Caitlin Sadowski8bccabe2011-09-08 21:52:50 +0000747 // expected-warning {{calling function 'aa_elr_fun' requires exclusive lock on 'aa_mu'}}
Caitlin Sadowski978191e2011-09-08 18:27:31 +0000748 aa_mu.Unlock();
749}
750
751void es_bad_2() {
752 Bar.aa_elr_fun_s(); // \
Caitlin Sadowski8bccabe2011-09-08 21:52:50 +0000753 // expected-warning {{calling function 'aa_elr_fun_s' requires shared lock on 'aa_mu'}}
Caitlin Sadowski978191e2011-09-08 18:27:31 +0000754}
755
756void es_bad_3() {
757 MyLRFoo.test(); // \
Caitlin Sadowski8bccabe2011-09-08 21:52:50 +0000758 // expected-warning {{calling function 'test' requires exclusive lock on 'sls_mu'}}
Caitlin Sadowski978191e2011-09-08 18:27:31 +0000759}
760
761void es_bad_4() {
762 MyLRFoo.testShared(); // \
Caitlin Sadowski8bccabe2011-09-08 21:52:50 +0000763 // expected-warning {{calling function 'testShared' requires shared lock on 'sls_mu2'}}
Caitlin Sadowski978191e2011-09-08 18:27:31 +0000764}
765
766void es_bad_5() {
767 sls_mu.ReaderLock();
768 MyLRFoo.test(); // \
Caitlin Sadowski8bccabe2011-09-08 21:52:50 +0000769 // expected-warning {{calling function 'test' requires exclusive lock on 'sls_mu'}}
Caitlin Sadowski978191e2011-09-08 18:27:31 +0000770 sls_mu.Unlock();
771}
772
773void es_bad_6() {
774 sls_mu.Lock();
775 Bar.le_fun(); // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000776 // expected-warning {{cannot call function 'le_fun' while mutex 'sls_mu' is locked}}
Caitlin Sadowski978191e2011-09-08 18:27:31 +0000777 sls_mu.Unlock();
778}
779
780void es_bad_7() {
781 sls_mu.ReaderLock();
782 Bar.le_fun(); // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000783 // expected-warning {{cannot call function 'le_fun' while mutex 'sls_mu' is locked}}
Caitlin Sadowski978191e2011-09-08 18:27:31 +0000784 sls_mu.Unlock();
785}
Caitlin Sadowski194418f2011-09-14 20:00:24 +0000786
DeLesley Hutchins81216392011-10-17 21:38:02 +0000787
Caitlin Sadowski194418f2011-09-14 20:00:24 +0000788//-----------------------------------------------//
789// Unparseable lock expressions
790// ----------------------------------------------//
791
DeLesley Hutchins0d95dfc2012-03-02 23:36:05 +0000792// FIXME -- derive new tests for unhandled expressions
Caitlin Sadowski194418f2011-09-14 20:00:24 +0000793
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +0000794
795//----------------------------------------------------------------------------//
796// The following test cases are ported from the gcc thread safety implementation
797// They are each wrapped inside a namespace with the test number of the gcc test
798//
799// FIXME: add all the gcc tests, once this analysis passes them.
800//----------------------------------------------------------------------------//
801
802//-----------------------------------------//
803// Good testcases (no errors)
804//-----------------------------------------//
805
806namespace thread_annot_lock_20 {
807class Bar {
808 public:
809 static int func1() EXCLUSIVE_LOCKS_REQUIRED(mu1_);
810 static int b_ GUARDED_BY(mu1_);
811 static Mutex mu1_;
812 static int a_ GUARDED_BY(mu1_);
813};
814
815Bar b1;
816
817int Bar::func1()
818{
819 int res = 5;
820
821 if (a_ == 4)
822 res = b_;
823 return res;
824}
825} // end namespace thread_annot_lock_20
826
827namespace thread_annot_lock_22 {
828// Test various usage of GUARDED_BY and PT_GUARDED_BY annotations, especially
829// uses in class definitions.
830Mutex mu;
831
832class Bar {
833 public:
834 int a_ GUARDED_BY(mu1_);
835 int b_;
836 int *q PT_GUARDED_BY(mu);
837 Mutex mu1_ ACQUIRED_AFTER(mu);
838};
839
840Bar b1, *b3;
841int *p GUARDED_BY(mu) PT_GUARDED_BY(mu);
842int res GUARDED_BY(mu) = 5;
843
844int func(int i)
845{
846 int x;
847 mu.Lock();
848 b1.mu1_.Lock();
849 res = b1.a_ + b3->b_;
850 *p = i;
851 b1.a_ = res + b3->b_;
852 b3->b_ = *b1.q;
853 b1.mu1_.Unlock();
854 b1.b_ = res;
855 x = res;
856 mu.Unlock();
857 return x;
858}
859} // end namespace thread_annot_lock_22
860
861namespace thread_annot_lock_27_modified {
862// test lock annotations applied to function definitions
863// Modified: applied annotations only to function declarations
864Mutex mu1;
865Mutex mu2 ACQUIRED_AFTER(mu1);
866
867class Foo {
868 public:
869 int method1(int i) SHARED_LOCKS_REQUIRED(mu2) EXCLUSIVE_LOCKS_REQUIRED(mu1);
870};
871
872int Foo::method1(int i) {
873 return i;
874}
875
876
877int foo(int i) EXCLUSIVE_LOCKS_REQUIRED(mu2) SHARED_LOCKS_REQUIRED(mu1);
878int foo(int i) {
879 return i;
880}
881
882static int bar(int i) EXCLUSIVE_LOCKS_REQUIRED(mu1);
883static int bar(int i) {
884 return i;
885}
886
887void main() {
888 Foo a;
889
890 mu1.Lock();
891 mu2.Lock();
892 a.method1(1);
893 foo(2);
894 mu2.Unlock();
895 bar(3);
896 mu1.Unlock();
897}
898} // end namespace thread_annot_lock_27_modified
899
900
901namespace thread_annot_lock_38 {
902// Test the case where a template member function is annotated with lock
903// attributes in a non-template class.
904class Foo {
905 public:
906 void func1(int y) LOCKS_EXCLUDED(mu_);
907 template <typename T> void func2(T x) LOCKS_EXCLUDED(mu_);
908 private:
909 Mutex mu_;
910};
911
912Foo *foo;
913
914void main()
915{
916 foo->func1(5);
917 foo->func2(5);
918}
919} // end namespace thread_annot_lock_38
920
921namespace thread_annot_lock_43 {
922// Tests lock canonicalization
923class Foo {
924 public:
925 Mutex *mu_;
926};
927
928class FooBar {
929 public:
930 Foo *foo_;
931 int GetA() EXCLUSIVE_LOCKS_REQUIRED(foo_->mu_) { return a_; }
932 int a_ GUARDED_BY(foo_->mu_);
933};
934
935FooBar *fb;
936
937void main()
938{
939 int x;
940 fb->foo_->mu_->Lock();
941 x = fb->GetA();
942 fb->foo_->mu_->Unlock();
943}
944} // end namespace thread_annot_lock_43
945
946namespace thread_annot_lock_49 {
947// Test the support for use of lock expression in the annotations
948class Foo {
949 public:
950 Mutex foo_mu_;
951};
952
953class Bar {
954 private:
955 Foo *foo;
956 Mutex bar_mu_ ACQUIRED_AFTER(foo->foo_mu_);
957
958 public:
959 void Test1() {
960 foo->foo_mu_.Lock();
961 bar_mu_.Lock();
962 bar_mu_.Unlock();
963 foo->foo_mu_.Unlock();
964 }
965};
966
967void main() {
968 Bar bar;
969 bar.Test1();
970}
971} // end namespace thread_annot_lock_49
972
973namespace thread_annot_lock_61_modified {
974 // Modified to fix the compiler errors
975 // Test the fix for a bug introduced by the support of pass-by-reference
976 // paramters.
977 struct Foo { Foo &operator<< (bool) {return *this;} };
978 Foo &getFoo();
979 struct Bar { Foo &func () {return getFoo();} };
980 struct Bas { void operator& (Foo &) {} };
981 void mumble()
982 {
983 Bas() & Bar().func() << "" << "";
984 Bas() & Bar().func() << "";
985 }
986} // end namespace thread_annot_lock_61_modified
987
988
989namespace thread_annot_lock_65 {
990// Test the fix for a bug in the support of allowing reader locks for
991// non-const, non-modifying overload functions. (We didn't handle the builtin
992// properly.)
993enum MyFlags {
994 Zero,
995 One,
996 Two,
997 Three,
998 Four,
999 Five,
1000 Six,
1001 Seven,
1002 Eight,
1003 Nine
1004};
1005
1006inline MyFlags
1007operator|(MyFlags a, MyFlags b)
1008{
1009 return MyFlags(static_cast<int>(a) | static_cast<int>(b));
1010}
1011
1012inline MyFlags&
1013operator|=(MyFlags& a, MyFlags b)
1014{
1015 return a = a | b;
1016}
1017} // end namespace thread_annot_lock_65
1018
1019namespace thread_annot_lock_66_modified {
1020// Modified: Moved annotation to function defn
1021// Test annotations on out-of-line definitions of member functions where the
1022// annotations refer to locks that are also data members in the class.
1023Mutex mu;
1024
1025class Foo {
1026 public:
1027 int method1(int i) SHARED_LOCKS_REQUIRED(mu1, mu, mu2);
1028 int data GUARDED_BY(mu1);
1029 Mutex *mu1;
1030 Mutex *mu2;
1031};
1032
1033int Foo::method1(int i)
1034{
1035 return data + i;
1036}
1037
1038void main()
1039{
1040 Foo a;
1041
1042 a.mu2->Lock();
1043 a.mu1->Lock();
1044 mu.Lock();
1045 a.method1(1);
1046 mu.Unlock();
1047 a.mu1->Unlock();
1048 a.mu2->Unlock();
1049}
1050} // end namespace thread_annot_lock_66_modified
1051
1052namespace thread_annot_lock_68_modified {
1053// Test a fix to a bug in the delayed name binding with nested template
1054// instantiation. We use a stack to make sure a name is not resolved to an
1055// inner context.
1056template <typename T>
1057class Bar {
1058 Mutex mu_;
1059};
1060
1061template <typename T>
1062class Foo {
1063 public:
1064 void func(T x) {
1065 mu_.Lock();
DeLesley Hutchins23323e02012-01-20 22:50:54 +00001066 count_ = x;
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001067 mu_.Unlock();
1068 }
1069
1070 private:
DeLesley Hutchins23323e02012-01-20 22:50:54 +00001071 T count_ GUARDED_BY(mu_);
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001072 Bar<T> bar_;
1073 Mutex mu_;
1074};
1075
1076void main()
1077{
1078 Foo<int> *foo;
1079 foo->func(5);
1080}
1081} // end namespace thread_annot_lock_68_modified
1082
1083namespace thread_annot_lock_30_modified {
1084// Test delay parsing of lock attribute arguments with nested classes.
1085// Modified: trylocks replaced with exclusive_lock_fun
1086int a = 0;
1087
1088class Bar {
1089 struct Foo;
1090
1091 public:
1092 void MyLock() EXCLUSIVE_LOCK_FUNCTION(mu);
1093
1094 int func() {
1095 MyLock();
1096// if (foo == 0) {
1097// return 0;
1098// }
1099 a = 5;
1100 mu.Unlock();
1101 return 1;
1102 }
1103
1104 class FooBar {
1105 int x;
1106 int y;
1107 };
1108
1109 private:
1110 Mutex mu;
1111};
1112
1113Bar *bar;
1114
1115void main()
1116{
1117 bar->func();
1118}
1119} // end namespace thread_annot_lock_30_modified
1120
1121namespace thread_annot_lock_47 {
1122// Test the support for annotations on virtual functions.
1123// This is a good test case. (i.e. There should be no warning emitted by the
1124// compiler.)
1125class Base {
1126 public:
1127 virtual void func1() EXCLUSIVE_LOCKS_REQUIRED(mu_);
1128 virtual void func2() LOCKS_EXCLUDED(mu_);
1129 Mutex mu_;
1130};
1131
1132class Child : public Base {
1133 public:
1134 virtual void func1() EXCLUSIVE_LOCKS_REQUIRED(mu_);
1135 virtual void func2() LOCKS_EXCLUDED(mu_);
1136};
1137
1138void main() {
1139 Child *c;
1140 Base *b = c;
1141
1142 b->mu_.Lock();
1143 b->func1();
1144 b->mu_.Unlock();
1145 b->func2();
1146
1147 c->mu_.Lock();
1148 c->func1();
1149 c->mu_.Unlock();
1150 c->func2();
1151}
1152} // end namespace thread_annot_lock_47
1153
1154//-----------------------------------------//
1155// Tests which produce errors
1156//-----------------------------------------//
1157
1158namespace thread_annot_lock_13 {
1159Mutex mu1;
1160Mutex mu2;
1161
1162int g GUARDED_BY(mu1);
1163int w GUARDED_BY(mu2);
1164
1165class Foo {
1166 public:
1167 void bar() LOCKS_EXCLUDED(mu_, mu1);
1168 int foo() SHARED_LOCKS_REQUIRED(mu_) EXCLUSIVE_LOCKS_REQUIRED(mu2);
1169
1170 private:
1171 int a_ GUARDED_BY(mu_);
1172 public:
1173 Mutex mu_ ACQUIRED_AFTER(mu1);
1174};
1175
1176int Foo::foo()
1177{
1178 int res;
David Blaikiee31b8fb2012-04-05 00:16:44 +00001179 w = 5;
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001180 res = a_ + 5;
1181 return res;
1182}
1183
1184void Foo::bar()
1185{
1186 int x;
1187 mu_.Lock();
1188 x = foo(); // expected-warning {{calling function 'foo' requires exclusive lock on 'mu2'}}
1189 a_ = x + 1;
1190 mu_.Unlock();
1191 if (x > 5) {
1192 mu1.Lock();
David Blaikiee31b8fb2012-04-05 00:16:44 +00001193 g = 2;
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001194 mu1.Unlock();
1195 }
1196}
1197
1198void main()
1199{
1200 Foo f1, *f2;
1201 f1.mu_.Lock();
DeLesley Hutchinsa74b7152012-08-10 20:19:55 +00001202 f1.bar(); // expected-warning {{cannot call function 'bar' while mutex 'f1.mu_' is locked}}
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001203 mu2.Lock();
1204 f1.foo();
1205 mu2.Unlock();
1206 f1.mu_.Unlock();
1207 f2->mu_.Lock();
DeLesley Hutchinsa74b7152012-08-10 20:19:55 +00001208 f2->bar(); // expected-warning {{cannot call function 'bar' while mutex 'f2->mu_' is locked}}
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001209 f2->mu_.Unlock();
1210 mu2.Lock();
David Blaikiee31b8fb2012-04-05 00:16:44 +00001211 w = 2;
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001212 mu2.Unlock();
1213}
1214} // end namespace thread_annot_lock_13
1215
1216namespace thread_annot_lock_18_modified {
1217// Modified: Trylocks removed
1218// Test the ability to distnguish between the same lock field of
1219// different objects of a class.
1220 class Bar {
1221 public:
1222 bool MyLock() EXCLUSIVE_LOCK_FUNCTION(mu1_);
1223 void MyUnlock() UNLOCK_FUNCTION(mu1_);
1224 int a_ GUARDED_BY(mu1_);
1225
1226 private:
1227 Mutex mu1_;
1228};
1229
1230Bar *b1, *b2;
1231
1232void func()
1233{
1234 b1->MyLock();
1235 b1->a_ = 5;
DeLesley Hutchinsa74b7152012-08-10 20:19:55 +00001236 b2->a_ = 3; // expected-warning {{writing variable 'a_' requires locking 'b2->mu1_' exclusively}}
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001237 b2->MyLock();
1238 b2->MyUnlock();
1239 b1->MyUnlock();
1240}
1241} // end namespace thread_annot_lock_18_modified
1242
1243namespace thread_annot_lock_21 {
1244// Test various usage of GUARDED_BY and PT_GUARDED_BY annotations, especially
1245// uses in class definitions.
1246Mutex mu;
1247
1248class Bar {
1249 public:
1250 int a_ GUARDED_BY(mu1_);
1251 int b_;
1252 int *q PT_GUARDED_BY(mu);
1253 Mutex mu1_ ACQUIRED_AFTER(mu);
1254};
1255
1256Bar b1, *b3;
1257int *p GUARDED_BY(mu) PT_GUARDED_BY(mu);
1258
1259int res GUARDED_BY(mu) = 5;
1260
1261int func(int i)
1262{
1263 int x;
1264 b3->mu1_.Lock();
DeLesley Hutchinsa74b7152012-08-10 20:19:55 +00001265 res = b1.a_ + b3->b_; // expected-warning {{reading variable 'a_' requires locking 'b1.mu1_'}} \
Caitlin Sadowski74558b42011-09-15 18:13:32 +00001266 // expected-warning {{writing variable 'res' requires locking 'mu' exclusively}}
1267 *p = i; // expected-warning {{reading variable 'p' requires locking 'mu'}} \
1268 // expected-warning {{writing the value pointed to by 'p' requires locking 'mu' exclusively}}
1269 b1.a_ = res + b3->b_; // expected-warning {{reading variable 'res' requires locking 'mu'}} \
DeLesley Hutchinsa74b7152012-08-10 20:19:55 +00001270 // expected-warning {{writing variable 'a_' requires locking 'b1.mu1_' exclusively}}
Caitlin Sadowski74558b42011-09-15 18:13:32 +00001271 b3->b_ = *b1.q; // expected-warning {{reading the value pointed to by 'q' requires locking 'mu'}}
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001272 b3->mu1_.Unlock();
Caitlin Sadowski74558b42011-09-15 18:13:32 +00001273 b1.b_ = res; // expected-warning {{reading variable 'res' requires locking 'mu'}}
1274 x = res; // expected-warning {{reading variable 'res' requires locking 'mu'}}
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001275 return x;
1276}
1277} // end namespace thread_annot_lock_21
1278
1279namespace thread_annot_lock_35_modified {
1280// Test the analyzer's ability to distinguish the lock field of different
1281// objects.
1282class Foo {
1283 private:
1284 Mutex lock_;
1285 int a_ GUARDED_BY(lock_);
1286
1287 public:
1288 void Func(Foo* child) LOCKS_EXCLUDED(lock_) {
1289 Foo *new_foo = new Foo;
1290
1291 lock_.Lock();
1292
1293 child->Func(new_foo); // There shouldn't be any warning here as the
1294 // acquired lock is not in child.
DeLesley Hutchinsa74b7152012-08-10 20:19:55 +00001295 child->bar(7); // expected-warning {{calling function 'bar' requires exclusive lock on 'child->lock_'}}
1296 child->a_ = 5; // expected-warning {{writing variable 'a_' requires locking 'child->lock_' exclusively}}
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001297 lock_.Unlock();
1298 }
1299
1300 void bar(int y) EXCLUSIVE_LOCKS_REQUIRED(lock_) {
1301 a_ = y;
1302 }
1303};
1304
1305Foo *x;
1306
1307void main() {
1308 Foo *child = new Foo;
1309 x->Func(child);
1310}
1311} // end namespace thread_annot_lock_35_modified
1312
1313namespace thread_annot_lock_36_modified {
1314// Modified to move the annotations to function defns.
1315// Test the analyzer's ability to distinguish the lock field of different
1316// objects
1317class Foo {
1318 private:
1319 Mutex lock_;
1320 int a_ GUARDED_BY(lock_);
1321
1322 public:
1323 void Func(Foo* child) LOCKS_EXCLUDED(lock_);
1324 void bar(int y) EXCLUSIVE_LOCKS_REQUIRED(lock_);
1325};
1326
1327void Foo::Func(Foo* child) {
1328 Foo *new_foo = new Foo;
1329
1330 lock_.Lock();
1331
1332 child->lock_.Lock();
DeLesley Hutchinsa74b7152012-08-10 20:19:55 +00001333 child->Func(new_foo); // expected-warning {{cannot call function 'Func' while mutex 'child->lock_' is locked}}
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001334 child->bar(7);
1335 child->a_ = 5;
1336 child->lock_.Unlock();
1337
1338 lock_.Unlock();
1339}
1340
1341void Foo::bar(int y) {
1342 a_ = y;
1343}
1344
1345
1346Foo *x;
1347
1348void main() {
1349 Foo *child = new Foo;
1350 x->Func(child);
1351}
1352} // end namespace thread_annot_lock_36_modified
1353
1354
1355namespace thread_annot_lock_42 {
1356// Test support of multiple lock attributes of the same kind on a decl.
1357class Foo {
1358 private:
1359 Mutex mu1, mu2, mu3;
1360 int x GUARDED_BY(mu1) GUARDED_BY(mu2);
1361 int y GUARDED_BY(mu2);
1362
1363 void f2() LOCKS_EXCLUDED(mu1) LOCKS_EXCLUDED(mu2) LOCKS_EXCLUDED(mu3) {
1364 mu2.Lock();
1365 y = 2;
1366 mu2.Unlock();
1367 }
1368
1369 public:
1370 void f1() EXCLUSIVE_LOCKS_REQUIRED(mu2) EXCLUSIVE_LOCKS_REQUIRED(mu1) {
1371 x = 5;
Caitlin Sadowski74558b42011-09-15 18:13:32 +00001372 f2(); // expected-warning {{cannot call function 'f2' while mutex 'mu1' is locked}} \
1373 // expected-warning {{cannot call function 'f2' while mutex 'mu2' is locked}}
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001374 }
1375};
1376
1377Foo *foo;
1378
1379void func()
1380{
DeLesley Hutchinsa74b7152012-08-10 20:19:55 +00001381 foo->f1(); // expected-warning {{calling function 'f1' requires exclusive lock on 'foo->mu2'}} \
1382 // expected-warning {{calling function 'f1' requires exclusive lock on 'foo->mu1'}}
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001383}
1384} // end namespace thread_annot_lock_42
1385
1386namespace thread_annot_lock_46 {
1387// Test the support for annotations on virtual functions.
1388class Base {
1389 public:
1390 virtual void func1() EXCLUSIVE_LOCKS_REQUIRED(mu_);
1391 virtual void func2() LOCKS_EXCLUDED(mu_);
1392 Mutex mu_;
1393};
1394
1395class Child : public Base {
1396 public:
1397 virtual void func1() EXCLUSIVE_LOCKS_REQUIRED(mu_);
1398 virtual void func2() LOCKS_EXCLUDED(mu_);
1399};
1400
1401void main() {
1402 Child *c;
1403 Base *b = c;
1404
DeLesley Hutchinsa74b7152012-08-10 20:19:55 +00001405 b->func1(); // expected-warning {{calling function 'func1' requires exclusive lock on 'b->mu_'}}
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001406 b->mu_.Lock();
DeLesley Hutchinsa74b7152012-08-10 20:19:55 +00001407 b->func2(); // expected-warning {{cannot call function 'func2' while mutex 'b->mu_' is locked}}
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001408 b->mu_.Unlock();
1409
DeLesley Hutchinsa74b7152012-08-10 20:19:55 +00001410 c->func1(); // expected-warning {{calling function 'func1' requires exclusive lock on 'c->mu_'}}
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001411 c->mu_.Lock();
DeLesley Hutchinsa74b7152012-08-10 20:19:55 +00001412 c->func2(); // expected-warning {{cannot call function 'func2' while mutex 'c->mu_' is locked}}
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001413 c->mu_.Unlock();
1414}
1415} // end namespace thread_annot_lock_46
1416
1417namespace thread_annot_lock_67_modified {
1418// Modified: attributes on definitions moved to declarations
1419// Test annotations on out-of-line definitions of member functions where the
1420// annotations refer to locks that are also data members in the class.
1421Mutex mu;
1422Mutex mu3;
1423
1424class Foo {
1425 public:
1426 int method1(int i) SHARED_LOCKS_REQUIRED(mu1, mu, mu2, mu3);
1427 int data GUARDED_BY(mu1);
1428 Mutex *mu1;
1429 Mutex *mu2;
1430};
1431
1432int Foo::method1(int i) {
1433 return data + i;
1434}
1435
1436void main()
1437{
1438 Foo a;
DeLesley Hutchinsa74b7152012-08-10 20:19:55 +00001439 a.method1(1); // expected-warning {{calling function 'method1' requires shared lock on 'a.mu1'}} \
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001440 // expected-warning {{calling function 'method1' requires shared lock on 'mu'}} \
DeLesley Hutchinsa74b7152012-08-10 20:19:55 +00001441 // expected-warning {{calling function 'method1' requires shared lock on 'a.mu2'}} \
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001442 // expected-warning {{calling function 'method1' requires shared lock on 'mu3'}}
1443}
1444} // end namespace thread_annot_lock_67_modified
1445
1446
DeLesley Hutchins81216392011-10-17 21:38:02 +00001447namespace substitution_test {
1448 class MyData {
1449 public:
1450 Mutex mu;
1451
1452 void lockData() __attribute__((exclusive_lock_function(mu))) { }
1453 void unlockData() __attribute__((unlock_function(mu))) { }
1454
1455 void doSomething() __attribute__((exclusive_locks_required(mu))) { }
1456 };
1457
1458
1459 class DataLocker {
1460 public:
1461 void lockData (MyData *d) __attribute__((exclusive_lock_function(d->mu))) { }
1462 void unlockData(MyData *d) __attribute__((unlock_function(d->mu))) { }
1463 };
1464
1465
1466 class Foo {
1467 public:
1468 void foo(MyData* d) __attribute__((exclusive_locks_required(d->mu))) { }
1469
1470 void bar1(MyData* d) {
1471 d->lockData();
1472 foo(d);
1473 d->unlockData();
1474 }
1475
1476 void bar2(MyData* d) {
1477 DataLocker dlr;
1478 dlr.lockData(d);
1479 foo(d);
1480 dlr.unlockData(d);
1481 }
1482
1483 void bar3(MyData* d1, MyData* d2) {
1484 DataLocker dlr;
Richard Smith2e515622012-02-03 04:45:26 +00001485 dlr.lockData(d1); // expected-note {{mutex acquired here}}
DeLesley Hutchins81216392011-10-17 21:38:02 +00001486 dlr.unlockData(d2); // \
DeLesley Hutchinsa74b7152012-08-10 20:19:55 +00001487 // expected-warning {{unlocking 'd2->mu' that was not locked}}
1488 } // expected-warning {{mutex 'd1->mu' is still locked at the end of function}}
DeLesley Hutchins81216392011-10-17 21:38:02 +00001489
1490 void bar4(MyData* d1, MyData* d2) {
1491 DataLocker dlr;
1492 dlr.lockData(d1);
1493 foo(d2); // \
DeLesley Hutchinsa74b7152012-08-10 20:19:55 +00001494 // expected-warning {{calling function 'foo' requires exclusive lock on 'd2->mu'}}
DeLesley Hutchins81216392011-10-17 21:38:02 +00001495 dlr.unlockData(d1);
1496 }
1497 };
1498} // end namespace substituation_test
1499
DeLesley Hutchinse0eaa852011-10-21 18:06:53 +00001500
DeLesley Hutchinsf1ac6372011-10-21 18:10:14 +00001501
DeLesley Hutchinse0eaa852011-10-21 18:06:53 +00001502namespace constructor_destructor_tests {
1503 Mutex fooMu;
1504 int myVar GUARDED_BY(fooMu);
1505
1506 class Foo {
1507 public:
1508 Foo() __attribute__((exclusive_lock_function(fooMu))) { }
1509 ~Foo() __attribute__((unlock_function(fooMu))) { }
1510 };
1511
1512 void fooTest() {
DeLesley Hutchins6db51f72011-10-21 20:51:27 +00001513 Foo foo;
DeLesley Hutchinse0eaa852011-10-21 18:06:53 +00001514 myVar = 0;
1515 }
1516}
1517
DeLesley Hutchinsf1ac6372011-10-21 18:10:14 +00001518
1519namespace invalid_lock_expression_test {
1520
1521class LOCKABLE MyLockable {
1522public:
1523 MyLockable() __attribute__((exclusive_lock_function)) { }
DeLesley Hutchins6db51f72011-10-21 20:51:27 +00001524 ~MyLockable() { }
DeLesley Hutchinsf1ac6372011-10-21 18:10:14 +00001525};
1526
1527// create an empty lock expression
1528void foo() {
1529 MyLockable lock; // \
1530 // expected-warning {{cannot resolve lock expression}}
1531}
1532
1533} // end namespace invalid_lock_expression_test
1534
Richard Smith97f9fe02011-10-25 00:41:24 +00001535namespace template_member_test {
DeLesley Hutchinsf1ac6372011-10-21 18:10:14 +00001536
Richard Smith97f9fe02011-10-25 00:41:24 +00001537 struct S { int n; };
1538 struct T {
1539 Mutex m;
1540 S *s GUARDED_BY(this->m);
1541 };
Richard Smitha01c7112011-10-25 06:33:21 +00001542 Mutex m;
1543 struct U {
1544 union {
1545 int n;
1546 };
1547 } *u GUARDED_BY(m);
Richard Smith97f9fe02011-10-25 00:41:24 +00001548
1549 template<typename U>
1550 struct IndirectLock {
1551 int DoNaughtyThings(T *t) {
Richard Smitha01c7112011-10-25 06:33:21 +00001552 u->n = 0; // expected-warning {{reading variable 'u' requires locking 'm'}}
DeLesley Hutchinsa74b7152012-08-10 20:19:55 +00001553 return t->s->n; // expected-warning {{reading variable 's' requires locking 't->m'}}
Richard Smith97f9fe02011-10-25 00:41:24 +00001554 }
1555 };
1556
Richard Smithf11e9232011-10-25 01:05:41 +00001557 template struct IndirectLock<int>; // expected-note {{here}}
Richard Smith97f9fe02011-10-25 00:41:24 +00001558
Richard Smith601d2ee2011-10-26 06:15:36 +00001559 struct V {
1560 void f(int);
1561 void f(double);
1562
1563 Mutex m;
1564 V *p GUARDED_BY(this->m);
1565 };
1566 template<typename U> struct W {
1567 V v;
1568 void f(U u) {
DeLesley Hutchinsa74b7152012-08-10 20:19:55 +00001569 v.p->f(u); // expected-warning {{reading variable 'p' requires locking 'v.m'}}
Richard Smith601d2ee2011-10-26 06:15:36 +00001570 }
1571 };
1572 template struct W<int>; // expected-note {{here}}
1573
Richard Smith97f9fe02011-10-25 00:41:24 +00001574}
DeLesley Hutchins1fa3c062011-12-08 20:23:06 +00001575
1576namespace test_scoped_lockable {
1577
1578struct TestScopedLockable {
1579 Mutex mu1;
1580 Mutex mu2;
1581 int a __attribute__((guarded_by(mu1)));
1582 int b __attribute__((guarded_by(mu2)));
1583
1584 bool getBool();
1585
1586 void foo1() {
1587 MutexLock mulock(&mu1);
1588 a = 5;
1589 }
1590
1591 void foo2() {
1592 ReaderMutexLock mulock1(&mu1);
1593 if (getBool()) {
1594 MutexLock mulock2a(&mu2);
1595 b = a + 1;
1596 }
1597 else {
1598 MutexLock mulock2b(&mu2);
1599 b = a + 2;
1600 }
1601 }
1602
1603 void foo3() {
1604 MutexLock mulock_a(&mu1);
1605 MutexLock mulock_b(&mu1); // \
1606 // expected-warning {{locking 'mu1' that is already locked}}
DeLesley Hutchinsc99a5d82012-06-28 22:42:48 +00001607 }
DeLesley Hutchins1fa3c062011-12-08 20:23:06 +00001608
1609 void foo4() {
1610 MutexLock mulock1(&mu1), mulock2(&mu2);
1611 a = b+1;
1612 b = a+1;
1613 }
1614};
1615
1616} // end namespace test_scoped_lockable
1617
1618
DeLesley Hutchinsdf497822011-12-29 00:56:48 +00001619namespace FunctionAttrTest {
1620
1621class Foo {
1622public:
1623 Mutex mu_;
1624 int a GUARDED_BY(mu_);
1625};
1626
1627Foo fooObj;
1628
1629void foo() EXCLUSIVE_LOCKS_REQUIRED(fooObj.mu_);
1630
1631void bar() {
DeLesley Hutchinsa74b7152012-08-10 20:19:55 +00001632 foo(); // expected-warning {{calling function 'foo' requires exclusive lock on 'fooObj.mu_'}}
DeLesley Hutchinsdf497822011-12-29 00:56:48 +00001633 fooObj.mu_.Lock();
1634 foo();
1635 fooObj.mu_.Unlock();
1636}
1637
1638}; // end namespace FunctionAttrTest
1639
1640
DeLesley Hutchinsb4fa4182012-01-06 19:16:50 +00001641struct TestTryLock {
1642 Mutex mu;
1643 int a GUARDED_BY(mu);
1644 bool cond;
1645
1646 void foo1() {
1647 if (mu.TryLock()) {
1648 a = 1;
1649 mu.Unlock();
1650 }
1651 }
1652
1653 void foo2() {
1654 if (!mu.TryLock()) return;
1655 a = 2;
1656 mu.Unlock();
1657 }
1658
1659 void foo3() {
1660 bool b = mu.TryLock();
1661 if (b) {
1662 a = 3;
1663 mu.Unlock();
1664 }
1665 }
1666
1667 void foo4() {
1668 bool b = mu.TryLock();
1669 if (!b) return;
1670 a = 4;
1671 mu.Unlock();
1672 }
1673
1674 void foo5() {
1675 while (mu.TryLock()) {
1676 a = a + 1;
1677 mu.Unlock();
1678 }
1679 }
1680
1681 void foo6() {
1682 bool b = mu.TryLock();
1683 b = !b;
1684 if (b) return;
1685 a = 6;
1686 mu.Unlock();
1687 }
1688
1689 void foo7() {
1690 bool b1 = mu.TryLock();
1691 bool b2 = !b1;
1692 bool b3 = !b2;
1693 if (b3) {
1694 a = 7;
1695 mu.Unlock();
1696 }
1697 }
1698
1699 // Test use-def chains: join points
1700 void foo8() {
1701 bool b = mu.TryLock();
1702 bool b2 = b;
1703 if (cond)
1704 b = true;
Sylvestre Ledru43e3dee2012-07-31 06:56:50 +00001705 if (b) { // b should be unknown at this point, because of the join point
DeLesley Hutchinsb4fa4182012-01-06 19:16:50 +00001706 a = 8; // expected-warning {{writing variable 'a' requires locking 'mu' exclusively}}
1707 }
1708 if (b2) { // b2 should be known at this point.
1709 a = 8;
1710 mu.Unlock();
1711 }
1712 }
1713
1714 // Test use-def-chains: back edges
1715 void foo9() {
1716 bool b = mu.TryLock();
1717
1718 for (int i = 0; i < 10; ++i);
1719
1720 if (b) { // b is still known, because the loop doesn't alter it
1721 a = 9;
1722 mu.Unlock();
1723 }
1724 }
1725
1726 // Test use-def chains: back edges
1727 void foo10() {
1728 bool b = mu.TryLock();
1729
1730 while (cond) {
1731 if (b) { // b should be uknown at this point b/c of the loop
1732 a = 10; // expected-warning {{writing variable 'a' requires locking 'mu' exclusively}}
1733 }
1734 b = !b;
1735 }
1736 }
1737}; // end TestTrylock
1738
1739
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +00001740namespace TestTemplateAttributeInstantiation {
1741
1742class Foo1 {
1743public:
1744 Mutex mu_;
1745 int a GUARDED_BY(mu_);
1746};
1747
1748class Foo2 {
1749public:
1750 int a GUARDED_BY(mu_);
1751 Mutex mu_;
1752};
1753
1754
1755class Bar {
1756public:
1757 // Test non-dependent expressions in attributes on template functions
1758 template <class T>
1759 void barND(Foo1 *foo, T *fooT) EXCLUSIVE_LOCKS_REQUIRED(foo->mu_) {
1760 foo->a = 0;
1761 }
1762
1763 // Test dependent expressions in attributes on template functions
1764 template <class T>
1765 void barD(Foo1 *foo, T *fooT) EXCLUSIVE_LOCKS_REQUIRED(fooT->mu_) {
1766 fooT->a = 0;
1767 }
1768};
1769
1770
1771template <class T>
1772class BarT {
1773public:
1774 Foo1 fooBase;
1775 T fooBaseT;
1776
1777 // Test non-dependent expression in ordinary method on template class
1778 void barND() EXCLUSIVE_LOCKS_REQUIRED(fooBase.mu_) {
1779 fooBase.a = 0;
1780 }
1781
1782 // Test dependent expressions in ordinary methods on template class
1783 void barD() EXCLUSIVE_LOCKS_REQUIRED(fooBaseT.mu_) {
1784 fooBaseT.a = 0;
1785 }
1786
1787 // Test dependent expressions in template method in template class
1788 template <class T2>
1789 void barTD(T2 *fooT) EXCLUSIVE_LOCKS_REQUIRED(fooBaseT.mu_, fooT->mu_) {
1790 fooBaseT.a = 0;
1791 fooT->a = 0;
1792 }
1793};
1794
1795template <class T>
1796class Cell {
1797public:
1798 Mutex mu_;
1799 // Test dependent guarded_by
1800 T data GUARDED_BY(mu_);
1801
DeLesley Hutchins23323e02012-01-20 22:50:54 +00001802 void fooEx() EXCLUSIVE_LOCKS_REQUIRED(mu_) {
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +00001803 data = 0;
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +00001804 }
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +00001805
1806 void foo() {
1807 mu_.Lock();
1808 data = 0;
1809 mu_.Unlock();
1810 }
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +00001811};
1812
1813void test() {
1814 Bar b;
1815 BarT<Foo2> bt;
1816 Foo1 f1;
1817 Foo2 f2;
1818
1819 f1.mu_.Lock();
1820 f2.mu_.Lock();
1821 bt.fooBase.mu_.Lock();
1822 bt.fooBaseT.mu_.Lock();
1823
1824 b.barND(&f1, &f2);
1825 b.barD(&f1, &f2);
1826 bt.barND();
1827 bt.barD();
1828 bt.barTD(&f2);
1829
1830 f1.mu_.Unlock();
1831 bt.barTD(&f1); // \
DeLesley Hutchinsa74b7152012-08-10 20:19:55 +00001832 // expected-warning {{calling function 'barTD' requires exclusive lock on 'f1.mu_'}}
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +00001833
1834 bt.fooBase.mu_.Unlock();
1835 bt.fooBaseT.mu_.Unlock();
1836 f2.mu_.Unlock();
1837
1838 Cell<int> cell;
1839 cell.data = 0; // \
DeLesley Hutchinsa74b7152012-08-10 20:19:55 +00001840 // expected-warning {{writing variable 'data' requires locking 'cell.mu_' exclusively}}
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +00001841 cell.foo();
DeLesley Hutchins23323e02012-01-20 22:50:54 +00001842 cell.mu_.Lock();
1843 cell.fooEx();
1844 cell.mu_.Unlock();
1845}
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +00001846
DeLesley Hutchins23323e02012-01-20 22:50:54 +00001847
1848template <class T>
1849class CellDelayed {
1850public:
1851 // Test dependent guarded_by
1852 T data GUARDED_BY(mu_);
DeLesley Hutchinsdd5756c2012-02-16 17:30:51 +00001853 static T static_data GUARDED_BY(static_mu_);
DeLesley Hutchins23323e02012-01-20 22:50:54 +00001854
1855 void fooEx(CellDelayed<T> *other) EXCLUSIVE_LOCKS_REQUIRED(mu_, other->mu_) {
1856 this->data = other->data;
1857 }
1858
1859 template <class T2>
1860 void fooExT(CellDelayed<T2> *otherT) EXCLUSIVE_LOCKS_REQUIRED(mu_, otherT->mu_) {
1861 this->data = otherT->data;
1862 }
1863
1864 void foo() {
1865 mu_.Lock();
1866 data = 0;
1867 mu_.Unlock();
1868 }
1869
1870 Mutex mu_;
DeLesley Hutchinsdd5756c2012-02-16 17:30:51 +00001871 static Mutex static_mu_;
DeLesley Hutchins23323e02012-01-20 22:50:54 +00001872};
1873
1874void testDelayed() {
1875 CellDelayed<int> celld;
1876 CellDelayed<int> celld2;
1877 celld.foo();
1878 celld.mu_.Lock();
1879 celld2.mu_.Lock();
1880
1881 celld.fooEx(&celld2);
1882 celld.fooExT(&celld2);
1883
1884 celld2.mu_.Unlock();
1885 celld.mu_.Unlock();
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +00001886}
1887
1888}; // end namespace TestTemplateAttributeInstantiation
1889
1890
DeLesley Hutchinse03b2b32012-01-20 23:24:41 +00001891namespace FunctionDeclDefTest {
1892
1893class Foo {
1894public:
1895 Mutex mu_;
1896 int a GUARDED_BY(mu_);
1897
1898 virtual void foo1(Foo *f_declared) EXCLUSIVE_LOCKS_REQUIRED(f_declared->mu_);
1899};
1900
1901// EXCLUSIVE_LOCKS_REQUIRED should be applied, and rewritten to f_defined->mu_
1902void Foo::foo1(Foo *f_defined) {
1903 f_defined->a = 0;
1904};
1905
1906void test() {
1907 Foo myfoo;
1908 myfoo.foo1(&myfoo); // \
DeLesley Hutchinsa74b7152012-08-10 20:19:55 +00001909 // expected-warning {{calling function 'foo1' requires exclusive lock on 'myfoo.mu_'}}
DeLesley Hutchinse03b2b32012-01-20 23:24:41 +00001910 myfoo.mu_.Lock();
1911 myfoo.foo1(&myfoo);
1912 myfoo.mu_.Unlock();
1913}
1914
1915};
Richard Smith2e515622012-02-03 04:45:26 +00001916
1917namespace GoingNative {
1918
1919 struct __attribute__((lockable)) mutex {
1920 void lock() __attribute__((exclusive_lock_function));
1921 void unlock() __attribute__((unlock_function));
1922 // ...
1923 };
1924 bool foo();
1925 bool bar();
1926 mutex m;
1927 void test() {
1928 m.lock();
1929 while (foo()) {
1930 m.unlock();
1931 // ...
1932 if (bar()) {
1933 // ...
1934 if (foo())
1935 continue; // expected-warning {{expecting mutex 'm' to be locked at start of each loop}}
1936 //...
1937 }
1938 // ...
1939 m.lock(); // expected-note {{mutex acquired here}}
1940 }
1941 m.unlock();
1942 }
1943
1944}
DeLesley Hutchinsc24a2332012-02-16 16:50:43 +00001945
1946
1947
1948namespace FunctionDefinitionTest {
1949
1950class Foo {
1951public:
1952 void foo1();
1953 void foo2();
1954 void foo3(Foo *other);
1955
1956 template<class T>
1957 void fooT1(const T& dummy1);
1958
1959 template<class T>
1960 void fooT2(const T& dummy2) EXCLUSIVE_LOCKS_REQUIRED(mu_);
1961
1962 Mutex mu_;
1963 int a GUARDED_BY(mu_);
1964};
1965
1966template<class T>
1967class FooT {
1968public:
1969 void foo();
1970
1971 Mutex mu_;
1972 T a GUARDED_BY(mu_);
1973};
1974
1975
1976void Foo::foo1() NO_THREAD_SAFETY_ANALYSIS {
1977 a = 1;
1978}
1979
1980void Foo::foo2() EXCLUSIVE_LOCKS_REQUIRED(mu_) {
1981 a = 2;
1982}
1983
1984void Foo::foo3(Foo *other) EXCLUSIVE_LOCKS_REQUIRED(other->mu_) {
1985 other->a = 3;
1986}
1987
1988template<class T>
1989void Foo::fooT1(const T& dummy1) EXCLUSIVE_LOCKS_REQUIRED(mu_) {
1990 a = dummy1;
1991}
1992
1993/* TODO -- uncomment with template instantiation of attributes.
1994template<class T>
1995void Foo::fooT2(const T& dummy2) {
1996 a = dummy2;
1997}
1998*/
1999
2000void fooF1(Foo *f) EXCLUSIVE_LOCKS_REQUIRED(f->mu_) {
2001 f->a = 1;
2002}
2003
2004void fooF2(Foo *f);
2005void fooF2(Foo *f) EXCLUSIVE_LOCKS_REQUIRED(f->mu_) {
2006 f->a = 2;
2007}
2008
2009void fooF3(Foo *f) EXCLUSIVE_LOCKS_REQUIRED(f->mu_);
2010void fooF3(Foo *f) {
2011 f->a = 3;
2012}
2013
2014template<class T>
2015void FooT<T>::foo() EXCLUSIVE_LOCKS_REQUIRED(mu_) {
2016 a = 0;
2017}
2018
2019void test() {
2020 int dummy = 0;
2021 Foo myFoo;
2022
2023 myFoo.foo2(); // \
DeLesley Hutchinsa74b7152012-08-10 20:19:55 +00002024 // expected-warning {{calling function 'foo2' requires exclusive lock on 'myFoo.mu_'}}
DeLesley Hutchinsc24a2332012-02-16 16:50:43 +00002025 myFoo.foo3(&myFoo); // \
DeLesley Hutchinsa74b7152012-08-10 20:19:55 +00002026 // expected-warning {{calling function 'foo3' requires exclusive lock on 'myFoo.mu_'}}
DeLesley Hutchinsc24a2332012-02-16 16:50:43 +00002027 myFoo.fooT1(dummy); // \
DeLesley Hutchinsa74b7152012-08-10 20:19:55 +00002028 // expected-warning {{calling function 'fooT1' requires exclusive lock on 'myFoo.mu_'}}
DeLesley Hutchinsc24a2332012-02-16 16:50:43 +00002029
DeLesley Hutchinsa74b7152012-08-10 20:19:55 +00002030 myFoo.fooT2(dummy); // \
2031 // expected-warning {{calling function 'fooT2' requires exclusive lock on 'myFoo.mu_'}}
DeLesley Hutchinsc24a2332012-02-16 16:50:43 +00002032
2033 fooF1(&myFoo); // \
DeLesley Hutchinsa74b7152012-08-10 20:19:55 +00002034 // expected-warning {{calling function 'fooF1' requires exclusive lock on 'myFoo.mu_'}}
DeLesley Hutchinsc24a2332012-02-16 16:50:43 +00002035 fooF2(&myFoo); // \
DeLesley Hutchinsa74b7152012-08-10 20:19:55 +00002036 // expected-warning {{calling function 'fooF2' requires exclusive lock on 'myFoo.mu_'}}
DeLesley Hutchinsc24a2332012-02-16 16:50:43 +00002037 fooF3(&myFoo); // \
DeLesley Hutchinsa74b7152012-08-10 20:19:55 +00002038 // expected-warning {{calling function 'fooF3' requires exclusive lock on 'myFoo.mu_'}}
DeLesley Hutchinsc24a2332012-02-16 16:50:43 +00002039
2040 myFoo.mu_.Lock();
2041 myFoo.foo2();
2042 myFoo.foo3(&myFoo);
2043 myFoo.fooT1(dummy);
2044
DeLesley Hutchinsa74b7152012-08-10 20:19:55 +00002045 myFoo.fooT2(dummy);
DeLesley Hutchinsc24a2332012-02-16 16:50:43 +00002046
2047 fooF1(&myFoo);
2048 fooF2(&myFoo);
2049 fooF3(&myFoo);
2050 myFoo.mu_.Unlock();
2051
2052 FooT<int> myFooT;
2053 myFooT.foo(); // \
DeLesley Hutchinsa74b7152012-08-10 20:19:55 +00002054 // expected-warning {{calling function 'foo' requires exclusive lock on 'myFooT.mu_'}}
DeLesley Hutchinsc24a2332012-02-16 16:50:43 +00002055}
2056
DeLesley Hutchins4bda3ec2012-02-16 17:03:24 +00002057} // end namespace FunctionDefinitionTest
2058
2059
2060namespace SelfLockingTest {
2061
2062class LOCKABLE MyLock {
2063public:
2064 int foo GUARDED_BY(this);
2065
2066 void lock() EXCLUSIVE_LOCK_FUNCTION();
2067 void unlock() UNLOCK_FUNCTION();
2068
2069 void doSomething() {
2070 this->lock(); // allow 'this' as a lock expression
2071 foo = 0;
2072 doSomethingElse();
2073 this->unlock();
2074 }
2075
2076 void doSomethingElse() EXCLUSIVE_LOCKS_REQUIRED(this) {
2077 foo = 1;
2078 };
2079
2080 void test() {
2081 foo = 2; // \
2082 // expected-warning {{writing variable 'foo' requires locking 'this' exclusively}}
2083 }
DeLesley Hutchinsc24a2332012-02-16 16:50:43 +00002084};
2085
DeLesley Hutchins2f13bec2012-02-16 17:13:43 +00002086
2087class LOCKABLE MyLock2 {
2088public:
2089 Mutex mu_;
2090 int foo GUARDED_BY(this);
2091
2092 // don't check inside lock and unlock functions
2093 void lock() EXCLUSIVE_LOCK_FUNCTION() { mu_.Lock(); }
2094 void unlock() UNLOCK_FUNCTION() { mu_.Unlock(); }
2095
2096 // don't check inside constructors and destructors
2097 MyLock2() { foo = 1; }
2098 ~MyLock2() { foo = 0; }
2099};
2100
2101
DeLesley Hutchins4bda3ec2012-02-16 17:03:24 +00002102} // end namespace SelfLockingTest
2103
2104
DeLesley Hutchinsd08d5992012-02-25 00:11:55 +00002105namespace InvalidNonstatic {
2106
2107// Forward decl here causes bogus "invalid use of non-static data member"
2108// on reference to mutex_ in guarded_by attribute.
2109class Foo;
2110
2111class Foo {
2112 Mutex* mutex_;
2113
2114 int foo __attribute__((guarded_by(mutex_)));
2115};
2116
2117} // end namespace InvalidNonStatic
2118
DeLesley Hutchins2a35be82012-03-02 22:02:58 +00002119
2120namespace NoReturnTest {
2121
2122bool condition();
2123void fatal() __attribute__((noreturn));
2124
2125Mutex mu_;
2126
2127void test1() {
2128 MutexLock lock(&mu_);
2129 if (condition()) {
2130 fatal();
2131 return;
2132 }
2133}
2134
DeLesley Hutchins2287c5e2012-03-02 22:12:59 +00002135} // end namespace NoReturnTest
2136
2137
2138namespace TestMultiDecl {
2139
2140class Foo {
2141public:
2142 int GUARDED_BY(mu_) a;
2143 int GUARDED_BY(mu_) b, c;
2144
2145 void foo() {
2146 a = 0; // \
2147 // expected-warning {{writing variable 'a' requires locking 'mu_' exclusively}}
2148 b = 0; // \
2149 // expected-warning {{writing variable 'b' requires locking 'mu_' exclusively}}
2150 c = 0; // \
2151 // expected-warning {{writing variable 'c' requires locking 'mu_' exclusively}}
2152 }
2153
2154private:
2155 Mutex mu_;
DeLesley Hutchins2a35be82012-03-02 22:02:58 +00002156};
DeLesley Hutchins2287c5e2012-03-02 22:12:59 +00002157
2158} // end namespace TestMultiDecl
2159
DeLesley Hutchins7ec419a2012-03-02 22:29:50 +00002160
2161namespace WarnNoDecl {
2162
2163class Foo {
2164 void foo(int a); __attribute__(( // \
2165 // expected-warning {{declaration does not declare anything}}
2166 exclusive_locks_required(a))); // \
2167 // expected-warning {{attribute exclusive_locks_required ignored}}
2168};
2169
2170} // end namespace WarnNoDecl
2171
2172
DeLesley Hutchins0d95dfc2012-03-02 23:36:05 +00002173
2174namespace MoreLockExpressions {
2175
2176class Foo {
2177public:
2178 Mutex mu_;
2179 int a GUARDED_BY(mu_);
2180};
2181
2182class Bar {
2183public:
2184 int b;
2185 Foo* f;
2186
2187 Foo& getFoo() { return *f; }
2188 Foo& getFoo2(int c) { return *f; }
2189 Foo& getFoo3(int c, int d) { return *f; }
2190
2191 Foo& getFooey() { return *f; }
2192};
2193
2194Foo& getBarFoo(Bar &bar, int c) { return bar.getFoo2(c); }
2195
2196void test() {
2197 Foo foo;
2198 Foo *fooArray;
2199 Bar bar;
2200 int a;
2201 int b;
2202 int c;
2203
2204 bar.getFoo().mu_.Lock();
2205 bar.getFoo().a = 0;
2206 bar.getFoo().mu_.Unlock();
2207
2208 (bar.getFoo().mu_).Lock(); // test parenthesis
2209 bar.getFoo().a = 0;
2210 (bar.getFoo().mu_).Unlock();
2211
2212 bar.getFoo2(a).mu_.Lock();
2213 bar.getFoo2(a).a = 0;
2214 bar.getFoo2(a).mu_.Unlock();
2215
2216 bar.getFoo3(a, b).mu_.Lock();
2217 bar.getFoo3(a, b).a = 0;
2218 bar.getFoo3(a, b).mu_.Unlock();
2219
2220 getBarFoo(bar, a).mu_.Lock();
2221 getBarFoo(bar, a).a = 0;
2222 getBarFoo(bar, a).mu_.Unlock();
2223
2224 bar.getFoo2(10).mu_.Lock();
2225 bar.getFoo2(10).a = 0;
2226 bar.getFoo2(10).mu_.Unlock();
2227
2228 bar.getFoo2(a + 1).mu_.Lock();
2229 bar.getFoo2(a + 1).a = 0;
2230 bar.getFoo2(a + 1).mu_.Unlock();
2231
2232 (a > 0 ? fooArray[1] : fooArray[b]).mu_.Lock();
2233 (a > 0 ? fooArray[1] : fooArray[b]).a = 0;
2234 (a > 0 ? fooArray[1] : fooArray[b]).mu_.Unlock();
2235
2236 bar.getFoo().mu_.Lock();
2237 bar.getFooey().a = 0; // \
DeLesley Hutchinsa74b7152012-08-10 20:19:55 +00002238 // expected-warning {{writing variable 'a' requires locking 'bar.getFooey().mu_' exclusively}}
DeLesley Hutchins0d95dfc2012-03-02 23:36:05 +00002239 bar.getFoo().mu_.Unlock();
2240
2241 bar.getFoo2(a).mu_.Lock();
2242 bar.getFoo2(b).a = 0; // \
DeLesley Hutchinsa74b7152012-08-10 20:19:55 +00002243 // expected-warning {{writing variable 'a' requires locking 'bar.getFoo2(b).mu_' exclusively}}
DeLesley Hutchins0d95dfc2012-03-02 23:36:05 +00002244 bar.getFoo2(a).mu_.Unlock();
2245
2246 bar.getFoo3(a, b).mu_.Lock();
2247 bar.getFoo3(a, c).a = 0; // \
DeLesley Hutchinsa74b7152012-08-10 20:19:55 +00002248 // expected-warning {{writing variable 'a' requires locking 'bar.getFoo3(a,c).mu_' exclusively}}
DeLesley Hutchins0d95dfc2012-03-02 23:36:05 +00002249 bar.getFoo3(a, b).mu_.Unlock();
2250
2251 getBarFoo(bar, a).mu_.Lock();
2252 getBarFoo(bar, b).a = 0; // \
DeLesley Hutchinsa74b7152012-08-10 20:19:55 +00002253 // expected-warning {{writing variable 'a' requires locking 'getBarFoo(bar,b).mu_' exclusively}}
DeLesley Hutchins0d95dfc2012-03-02 23:36:05 +00002254 getBarFoo(bar, a).mu_.Unlock();
2255
2256 (a > 0 ? fooArray[1] : fooArray[b]).mu_.Lock();
2257 (a > 0 ? fooArray[b] : fooArray[c]).a = 0; // \
DeLesley Hutchinsa74b7152012-08-10 20:19:55 +00002258 // expected-warning {{writing variable 'a' requires locking '((a#_)#_#fooArray[b]).mu_' exclusively}}
DeLesley Hutchins0d95dfc2012-03-02 23:36:05 +00002259 (a > 0 ? fooArray[1] : fooArray[b]).mu_.Unlock();
2260}
2261
2262
DeLesley Hutchins0da44142012-06-22 17:07:28 +00002263} // end namespace MoreLockExpressions
2264
2265
2266namespace TrylockJoinPoint {
2267
2268class Foo {
2269 Mutex mu;
2270 bool c;
2271
2272 void foo() {
2273 if (c) {
2274 if (!mu.TryLock())
2275 return;
2276 } else {
2277 mu.Lock();
2278 }
2279 mu.Unlock();
2280 }
2281};
2282
2283} // end namespace TrylockJoinPoint
DeLesley Hutchins0d95dfc2012-03-02 23:36:05 +00002284
2285
DeLesley Hutchinsf63797c2012-06-25 18:33:18 +00002286namespace LockReturned {
2287
2288class Foo {
2289public:
2290 int a GUARDED_BY(mu_);
2291 void foo() EXCLUSIVE_LOCKS_REQUIRED(mu_);
2292 void foo2(Foo* f) EXCLUSIVE_LOCKS_REQUIRED(mu_, f->mu_);
2293
2294 static void sfoo(Foo* f) EXCLUSIVE_LOCKS_REQUIRED(f->mu_);
2295
2296 Mutex* getMu() LOCK_RETURNED(mu_);
2297
2298 Mutex mu_;
2299
2300 static Mutex* getMu(Foo* f) LOCK_RETURNED(f->mu_);
2301};
2302
2303
2304// Calls getMu() directly to lock and unlock
2305void test1(Foo* f1, Foo* f2) {
DeLesley Hutchinsa74b7152012-08-10 20:19:55 +00002306 f1->a = 0; // expected-warning {{writing variable 'a' requires locking 'f1->mu_' exclusively}}
2307 f1->foo(); // expected-warning {{calling function 'foo' requires exclusive lock on 'f1->mu_'}}
DeLesley Hutchinsf63797c2012-06-25 18:33:18 +00002308
DeLesley Hutchinsa74b7152012-08-10 20:19:55 +00002309 f1->foo2(f2); // expected-warning {{calling function 'foo2' requires exclusive lock on 'f1->mu_'}} \
2310 // expected-warning {{calling function 'foo2' requires exclusive lock on 'f2->mu_'}}
2311 Foo::sfoo(f1); // expected-warning {{calling function 'sfoo' requires exclusive lock on 'f1->mu_'}}
DeLesley Hutchinsf63797c2012-06-25 18:33:18 +00002312
2313 f1->getMu()->Lock();
2314
2315 f1->a = 0;
2316 f1->foo();
DeLesley Hutchinsa74b7152012-08-10 20:19:55 +00002317 f1->foo2(f2); // expected-warning {{calling function 'foo2' requires exclusive lock on 'f2->mu_'}}
DeLesley Hutchinsf63797c2012-06-25 18:33:18 +00002318
2319 Foo::getMu(f2)->Lock();
2320 f1->foo2(f2);
2321 Foo::getMu(f2)->Unlock();
2322
2323 Foo::sfoo(f1);
2324
2325 f1->getMu()->Unlock();
2326}
2327
2328
2329Mutex* getFooMu(Foo* f) LOCK_RETURNED(Foo::getMu(f));
2330
2331class Bar : public Foo {
2332public:
2333 int b GUARDED_BY(getMu());
2334 void bar() EXCLUSIVE_LOCKS_REQUIRED(getMu());
2335 void bar2(Bar* g) EXCLUSIVE_LOCKS_REQUIRED(getMu(this), g->getMu());
2336
2337 static void sbar(Bar* g) EXCLUSIVE_LOCKS_REQUIRED(g->getMu());
2338 static void sbar2(Bar* g) EXCLUSIVE_LOCKS_REQUIRED(getFooMu(g));
2339};
2340
2341
2342
2343// Use getMu() within other attributes.
2344// This requires at lest levels of substitution, more in the case of
2345void test2(Bar* b1, Bar* b2) {
DeLesley Hutchinsa74b7152012-08-10 20:19:55 +00002346 b1->b = 0; // expected-warning {{writing variable 'b' requires locking 'b1->mu_' exclusively}}
2347 b1->bar(); // expected-warning {{calling function 'bar' requires exclusive lock on 'b1->mu_'}}
2348 b1->bar2(b2); // expected-warning {{calling function 'bar2' requires exclusive lock on 'b1->mu_'}} \
2349 // expected-warning {{calling function 'bar2' requires exclusive lock on 'b2->mu_'}}
2350 Bar::sbar(b1); // expected-warning {{calling function 'sbar' requires exclusive lock on 'b1->mu_'}}
2351 Bar::sbar2(b1); // expected-warning {{calling function 'sbar2' requires exclusive lock on 'b1->mu_'}}
DeLesley Hutchinsf63797c2012-06-25 18:33:18 +00002352
2353 b1->getMu()->Lock();
2354
2355 b1->b = 0;
2356 b1->bar();
DeLesley Hutchinsa74b7152012-08-10 20:19:55 +00002357 b1->bar2(b2); // expected-warning {{calling function 'bar2' requires exclusive lock on 'b2->mu_'}}
DeLesley Hutchinsf63797c2012-06-25 18:33:18 +00002358
2359 b2->getMu()->Lock();
2360 b1->bar2(b2);
2361
2362 b2->getMu()->Unlock();
2363
2364 Bar::sbar(b1);
2365 Bar::sbar2(b1);
2366
2367 b1->getMu()->Unlock();
2368}
2369
2370
2371// Sanity check -- lock the mutex directly, but use attributes that call getMu()
2372// Also lock the mutex using getFooMu, which calls a lock_returned function.
2373void test3(Bar* b1, Bar* b2) {
2374 b1->mu_.Lock();
2375 b1->b = 0;
2376 b1->bar();
2377
2378 getFooMu(b2)->Lock();
2379 b1->bar2(b2);
2380 getFooMu(b2)->Unlock();
2381
2382 Bar::sbar(b1);
2383 Bar::sbar2(b1);
2384
2385 b1->mu_.Unlock();
2386}
2387
2388} // end namespace LockReturned
2389
2390
DeLesley Hutchinsc99a5d82012-06-28 22:42:48 +00002391namespace ReleasableScopedLock {
2392
2393class Foo {
2394 Mutex mu_;
2395 bool c;
2396 int a GUARDED_BY(mu_);
2397
2398 void test1();
2399 void test2();
2400 void test3();
DeLesley Hutchins5381c052012-07-05 21:16:29 +00002401 void test4();
2402 void test5();
DeLesley Hutchinsc99a5d82012-06-28 22:42:48 +00002403};
2404
2405
2406void Foo::test1() {
2407 ReleasableMutexLock rlock(&mu_);
2408 rlock.Release();
2409}
2410
2411void Foo::test2() {
2412 ReleasableMutexLock rlock(&mu_);
2413 if (c) { // test join point -- held/not held during release
2414 rlock.Release();
2415 }
2416}
2417
2418void Foo::test3() {
2419 ReleasableMutexLock rlock(&mu_);
2420 a = 0;
2421 rlock.Release();
2422 a = 1; // expected-warning {{writing variable 'a' requires locking 'mu_' exclusively}}
2423}
2424
DeLesley Hutchins5381c052012-07-05 21:16:29 +00002425void Foo::test4() {
2426 ReleasableMutexLock rlock(&mu_);
2427 rlock.Release();
2428 rlock.Release(); // expected-warning {{unlocking 'mu_' that was not locked}}
2429}
2430
2431void Foo::test5() {
2432 ReleasableMutexLock rlock(&mu_);
2433 if (c) {
2434 rlock.Release();
2435 }
2436 // no warning on join point for managed lock.
2437 rlock.Release(); // expected-warning {{unlocking 'mu_' that was not locked}}
2438}
2439
2440
DeLesley Hutchinsc99a5d82012-06-28 22:42:48 +00002441} // end namespace ReleasableScopedLock
2442
2443
DeLesley Hutchins76f0a6e2012-07-02 21:59:24 +00002444namespace TrylockFunctionTest {
2445
2446class Foo {
2447public:
2448 Mutex mu1_;
2449 Mutex mu2_;
2450 bool c;
2451
2452 bool lockBoth() EXCLUSIVE_TRYLOCK_FUNCTION(true, mu1_, mu2_);
2453};
2454
2455bool Foo::lockBoth() {
2456 if (!mu1_.TryLock())
2457 return false;
2458
2459 mu2_.Lock();
2460 if (!c) {
2461 mu1_.Unlock();
2462 mu2_.Unlock();
2463 return false;
2464 }
2465
2466 return true;
2467}
2468
2469
2470} // end namespace TrylockFunctionTest
DeLesley Hutchinsc99a5d82012-06-28 22:42:48 +00002471
2472
2473
DeLesley Hutchinsc36eda12012-07-02 22:12:12 +00002474namespace DoubleLockBug {
2475
2476class Foo {
2477public:
2478 Mutex mu_;
2479 int a GUARDED_BY(mu_);
2480
DeLesley Hutchins5381c052012-07-05 21:16:29 +00002481 void foo1() EXCLUSIVE_LOCKS_REQUIRED(mu_);
2482 int foo2() SHARED_LOCKS_REQUIRED(mu_);
DeLesley Hutchinsc36eda12012-07-02 22:12:12 +00002483};
2484
2485
DeLesley Hutchins5381c052012-07-05 21:16:29 +00002486void Foo::foo1() EXCLUSIVE_LOCKS_REQUIRED(mu_) {
DeLesley Hutchinsc36eda12012-07-02 22:12:12 +00002487 a = 0;
2488}
2489
DeLesley Hutchins5381c052012-07-05 21:16:29 +00002490int Foo::foo2() SHARED_LOCKS_REQUIRED(mu_) {
2491 return a;
2492}
2493
2494}
2495
DeLesley Hutchinsc36eda12012-07-02 22:12:12 +00002496
2497
DeLesley Hutchins879a4332012-07-02 22:16:54 +00002498namespace UnlockBug {
DeLesley Hutchinsc36eda12012-07-02 22:12:12 +00002499
DeLesley Hutchins879a4332012-07-02 22:16:54 +00002500class Foo {
2501public:
2502 Mutex mutex_;
2503
2504 void foo1() EXCLUSIVE_LOCKS_REQUIRED(mutex_) { // expected-note {{mutex acquired here}}
2505 mutex_.Unlock();
2506 } // expected-warning {{expecting mutex 'mutex_' to be locked at the end of function}}
2507
2508
2509 void foo2() SHARED_LOCKS_REQUIRED(mutex_) { // expected-note {{mutex acquired here}}
2510 mutex_.Unlock();
2511 } // expected-warning {{expecting mutex 'mutex_' to be locked at the end of function}}
2512};
2513
2514} // end namespace UnlockBug
DeLesley Hutchinsc36eda12012-07-02 22:12:12 +00002515
DeLesley Hutchinsc99a5d82012-06-28 22:42:48 +00002516
DeLesley Hutchins5381c052012-07-05 21:16:29 +00002517
DeLesley Hutchinsbbe33412012-07-02 22:26:29 +00002518namespace FoolishScopedLockableBug {
2519
2520class SCOPED_LOCKABLE WTF_ScopedLockable {
2521public:
2522 WTF_ScopedLockable(Mutex* mu) EXCLUSIVE_LOCK_FUNCTION(mu);
2523
2524 // have to call release() manually;
2525 ~WTF_ScopedLockable();
2526
2527 void release() UNLOCK_FUNCTION();
2528};
2529
2530
2531class Foo {
2532 Mutex mu_;
2533 int a GUARDED_BY(mu_);
2534 bool c;
2535
2536 void doSomething();
2537
2538 void test1() {
2539 WTF_ScopedLockable wtf(&mu_);
2540 wtf.release();
2541 }
2542
2543 void test2() {
2544 WTF_ScopedLockable wtf(&mu_); // expected-note {{mutex acquired here}}
2545 } // expected-warning {{mutex 'mu_' is still locked at the end of function}}
2546
2547 void test3() {
2548 if (c) {
2549 WTF_ScopedLockable wtf(&mu_);
2550 wtf.release();
2551 }
2552 }
2553
2554 void test4() {
2555 if (c) {
2556 doSomething();
2557 }
2558 else {
2559 WTF_ScopedLockable wtf(&mu_);
2560 wtf.release();
2561 }
2562 }
2563
2564 void test5() {
2565 if (c) {
2566 WTF_ScopedLockable wtf(&mu_); // expected-note {{mutex acquired here}}
2567 }
2568 } // expected-warning {{mutex 'mu_' is not locked on every path through here}}
2569
2570 void test6() {
2571 if (c) {
2572 doSomething();
2573 }
2574 else {
2575 WTF_ScopedLockable wtf(&mu_); // expected-note {{mutex acquired here}}
2576 }
2577 } // expected-warning {{mutex 'mu_' is not locked on every path through here}}
2578};
2579
2580
2581} // end namespace FoolishScopedLockableBug
2582
DeLesley Hutchins9d6e7f32012-07-03 18:25:56 +00002583
DeLesley Hutchins5381c052012-07-05 21:16:29 +00002584
DeLesley Hutchins9d6e7f32012-07-03 18:25:56 +00002585namespace TemporaryCleanupExpr {
2586
2587class Foo {
2588 int a GUARDED_BY(getMutexPtr().get());
2589
2590 SmartPtr<Mutex> getMutexPtr();
2591
2592 void test();
2593};
2594
2595
2596void Foo::test() {
2597 {
2598 ReaderMutexLock lock(getMutexPtr().get());
2599 int b = a;
DeLesley Hutchins96fac6a2012-07-03 19:47:18 +00002600 }
DeLesley Hutchinsa74b7152012-08-10 20:19:55 +00002601 int b = a; // expected-warning {{reading variable 'a' requires locking 'getMutexPtr()'}}
DeLesley Hutchins9d6e7f32012-07-03 18:25:56 +00002602}
2603
2604} // end namespace TemporaryCleanupExpr
2605
2606
DeLesley Hutchins96fac6a2012-07-03 19:47:18 +00002607
2608namespace SmartPointerTests {
2609
2610class Foo {
2611public:
2612 SmartPtr<Mutex> mu_;
2613 int a GUARDED_BY(mu_);
2614 int b GUARDED_BY(mu_.get());
2615 int c GUARDED_BY(*mu_);
2616
2617 void Lock() EXCLUSIVE_LOCK_FUNCTION(mu_);
2618 void Unlock() UNLOCK_FUNCTION(mu_);
2619
2620 void test0();
2621 void test1();
2622 void test2();
2623 void test3();
2624 void test4();
2625 void test5();
2626 void test6();
2627 void test7();
2628 void test8();
2629};
2630
2631void Foo::test0() {
2632 a = 0; // expected-warning {{writing variable 'a' requires locking 'mu_' exclusively}}
2633 b = 0; // expected-warning {{writing variable 'b' requires locking 'mu_' exclusively}}
2634 c = 0; // expected-warning {{writing variable 'c' requires locking 'mu_' exclusively}}
2635}
2636
2637void Foo::test1() {
2638 mu_->Lock();
2639 a = 0;
2640 b = 0;
2641 c = 0;
2642 mu_->Unlock();
2643}
2644
2645void Foo::test2() {
2646 (*mu_).Lock();
2647 a = 0;
2648 b = 0;
2649 c = 0;
2650 (*mu_).Unlock();
2651}
2652
2653
2654void Foo::test3() {
2655 mu_.get()->Lock();
2656 a = 0;
2657 b = 0;
2658 c = 0;
2659 mu_.get()->Unlock();
2660}
2661
2662
2663void Foo::test4() {
2664 MutexLock lock(mu_.get());
2665 a = 0;
2666 b = 0;
2667 c = 0;
2668}
2669
2670
2671void Foo::test5() {
2672 MutexLock lock(&(*mu_));
2673 a = 0;
2674 b = 0;
2675 c = 0;
2676}
2677
2678
2679void Foo::test6() {
2680 Lock();
2681 a = 0;
2682 b = 0;
2683 c = 0;
2684 Unlock();
2685}
2686
2687
2688void Foo::test7() {
2689 {
2690 Lock();
2691 mu_->Unlock();
2692 }
2693 {
2694 mu_->Lock();
2695 Unlock();
2696 }
2697 {
2698 mu_.get()->Lock();
2699 mu_->Unlock();
2700 }
2701 {
2702 mu_->Lock();
2703 mu_.get()->Unlock();
2704 }
2705 {
2706 mu_.get()->Lock();
2707 (*mu_).Unlock();
2708 }
2709 {
2710 (*mu_).Lock();
2711 mu_->Unlock();
2712 }
2713}
2714
2715
2716void Foo::test8() {
2717 mu_->Lock();
2718 mu_.get()->Lock(); // expected-warning {{locking 'mu_' that is already locked}}
2719 (*mu_).Lock(); // expected-warning {{locking 'mu_' that is already locked}}
2720 mu_.get()->Unlock();
2721 Unlock(); // expected-warning {{unlocking 'mu_' that was not locked}}
2722}
2723
2724
2725class Bar {
2726 SmartPtr<Foo> foo;
2727
2728 void test0();
2729 void test1();
2730 void test2();
2731 void test3();
2732};
2733
2734
2735void Bar::test0() {
DeLesley Hutchinsa74b7152012-08-10 20:19:55 +00002736 foo->a = 0; // expected-warning {{writing variable 'a' requires locking 'foo->mu_' exclusively}}
2737 (*foo).b = 0; // expected-warning {{writing variable 'b' requires locking 'foo->mu_' exclusively}}
2738 foo.get()->c = 0; // expected-warning {{writing variable 'c' requires locking 'foo->mu_' exclusively}}
DeLesley Hutchins96fac6a2012-07-03 19:47:18 +00002739}
2740
2741
2742void Bar::test1() {
2743 foo->mu_->Lock();
2744 foo->a = 0;
2745 (*foo).b = 0;
2746 foo.get()->c = 0;
2747 foo->mu_->Unlock();
2748}
2749
2750
2751void Bar::test2() {
2752 (*foo).mu_->Lock();
2753 foo->a = 0;
2754 (*foo).b = 0;
2755 foo.get()->c = 0;
2756 foo.get()->mu_->Unlock();
2757}
2758
2759
2760void Bar::test3() {
2761 MutexLock lock(foo->mu_.get());
2762 foo->a = 0;
2763 (*foo).b = 0;
2764 foo.get()->c = 0;
2765}
2766
2767} // end namespace SmartPointerTests
2768
2769
2770
DeLesley Hutchins5381c052012-07-05 21:16:29 +00002771namespace DuplicateAttributeTest {
2772
2773class LOCKABLE Foo {
2774public:
2775 Mutex mu1_;
2776 Mutex mu2_;
2777 Mutex mu3_;
2778 int a GUARDED_BY(mu1_);
2779 int b GUARDED_BY(mu2_);
2780 int c GUARDED_BY(mu3_);
2781
2782 void lock() EXCLUSIVE_LOCK_FUNCTION();
2783 void unlock() UNLOCK_FUNCTION();
2784
2785 void lock1() EXCLUSIVE_LOCK_FUNCTION(mu1_);
2786 void slock1() SHARED_LOCK_FUNCTION(mu1_);
2787 void lock3() EXCLUSIVE_LOCK_FUNCTION(mu1_, mu2_, mu3_);
2788 void locklots()
2789 EXCLUSIVE_LOCK_FUNCTION(mu1_)
2790 EXCLUSIVE_LOCK_FUNCTION(mu2_)
2791 EXCLUSIVE_LOCK_FUNCTION(mu1_, mu2_, mu3_);
2792
2793 void unlock1() UNLOCK_FUNCTION(mu1_);
2794 void unlock3() UNLOCK_FUNCTION(mu1_, mu2_, mu3_);
2795 void unlocklots()
2796 UNLOCK_FUNCTION(mu1_)
2797 UNLOCK_FUNCTION(mu2_)
2798 UNLOCK_FUNCTION(mu1_, mu2_, mu3_);
2799};
2800
2801
2802void Foo::lock() EXCLUSIVE_LOCK_FUNCTION() { }
2803void Foo::unlock() UNLOCK_FUNCTION() { }
2804
2805void Foo::lock1() EXCLUSIVE_LOCK_FUNCTION(mu1_) {
2806 mu1_.Lock();
2807}
2808
2809void Foo::slock1() SHARED_LOCK_FUNCTION(mu1_) {
2810 mu1_.Lock();
2811}
2812
2813void Foo::lock3() EXCLUSIVE_LOCK_FUNCTION(mu1_, mu2_, mu3_) {
2814 mu1_.Lock();
2815 mu2_.Lock();
2816 mu3_.Lock();
2817}
2818
2819void Foo::locklots()
2820 EXCLUSIVE_LOCK_FUNCTION(mu1_, mu2_)
2821 EXCLUSIVE_LOCK_FUNCTION(mu2_, mu3_) {
2822 mu1_.Lock();
2823 mu2_.Lock();
2824 mu3_.Lock();
2825}
2826
2827void Foo::unlock1() UNLOCK_FUNCTION(mu1_) {
2828 mu1_.Unlock();
2829}
2830
2831void Foo::unlock3() UNLOCK_FUNCTION(mu1_, mu2_, mu3_) {
2832 mu1_.Unlock();
2833 mu2_.Unlock();
2834 mu3_.Unlock();
2835}
2836
2837void Foo::unlocklots()
2838 UNLOCK_FUNCTION(mu1_, mu2_)
2839 UNLOCK_FUNCTION(mu2_, mu3_) {
2840 mu1_.Unlock();
2841 mu2_.Unlock();
2842 mu3_.Unlock();
2843}
2844
2845
2846void test0() {
2847 Foo foo;
2848 foo.lock();
2849 foo.unlock();
2850
2851 foo.lock();
2852 foo.lock(); // expected-warning {{locking 'foo' that is already locked}}
2853 foo.unlock();
2854 foo.unlock(); // expected-warning {{unlocking 'foo' that was not locked}}
2855}
2856
2857
2858void test1() {
2859 Foo foo;
2860 foo.lock1();
2861 foo.a = 0;
2862 foo.unlock1();
2863
2864 foo.lock1();
DeLesley Hutchinsa74b7152012-08-10 20:19:55 +00002865 foo.lock1(); // expected-warning {{locking 'foo.mu1_' that is already locked}}
DeLesley Hutchins5381c052012-07-05 21:16:29 +00002866 foo.a = 0;
2867 foo.unlock1();
DeLesley Hutchinsa74b7152012-08-10 20:19:55 +00002868 foo.unlock1(); // expected-warning {{unlocking 'foo.mu1_' that was not locked}}
DeLesley Hutchins5381c052012-07-05 21:16:29 +00002869}
2870
2871
2872int test2() {
2873 Foo foo;
2874 foo.slock1();
2875 int d1 = foo.a;
2876 foo.unlock1();
2877
2878 foo.slock1();
DeLesley Hutchinsa74b7152012-08-10 20:19:55 +00002879 foo.slock1(); // expected-warning {{locking 'foo.mu1_' that is already locked}}
DeLesley Hutchins5381c052012-07-05 21:16:29 +00002880 int d2 = foo.a;
2881 foo.unlock1();
DeLesley Hutchinsa74b7152012-08-10 20:19:55 +00002882 foo.unlock1(); // expected-warning {{unlocking 'foo.mu1_' that was not locked}}
DeLesley Hutchins5381c052012-07-05 21:16:29 +00002883 return d1 + d2;
2884}
2885
2886
2887void test3() {
2888 Foo foo;
2889 foo.lock3();
2890 foo.a = 0;
2891 foo.b = 0;
2892 foo.c = 0;
2893 foo.unlock3();
2894
2895 foo.lock3();
2896 foo.lock3(); // \
DeLesley Hutchinsa74b7152012-08-10 20:19:55 +00002897 // expected-warning {{locking 'foo.mu1_' that is already locked}} \
2898 // expected-warning {{locking 'foo.mu2_' that is already locked}} \
2899 // expected-warning {{locking 'foo.mu3_' that is already locked}}
DeLesley Hutchins5381c052012-07-05 21:16:29 +00002900 foo.a = 0;
2901 foo.b = 0;
2902 foo.c = 0;
2903 foo.unlock3();
2904 foo.unlock3(); // \
DeLesley Hutchinsa74b7152012-08-10 20:19:55 +00002905 // expected-warning {{unlocking 'foo.mu1_' that was not locked}} \
2906 // expected-warning {{unlocking 'foo.mu2_' that was not locked}} \
2907 // expected-warning {{unlocking 'foo.mu3_' that was not locked}}
DeLesley Hutchins5381c052012-07-05 21:16:29 +00002908}
2909
2910
2911void testlots() {
2912 Foo foo;
2913 foo.locklots();
2914 foo.a = 0;
2915 foo.b = 0;
2916 foo.c = 0;
2917 foo.unlocklots();
2918
2919 foo.locklots();
2920 foo.locklots(); // \
DeLesley Hutchinsa74b7152012-08-10 20:19:55 +00002921 // expected-warning {{locking 'foo.mu1_' that is already locked}} \
2922 // expected-warning {{locking 'foo.mu2_' that is already locked}} \
2923 // expected-warning {{locking 'foo.mu3_' that is already locked}}
DeLesley Hutchins5381c052012-07-05 21:16:29 +00002924 foo.a = 0;
2925 foo.b = 0;
2926 foo.c = 0;
2927 foo.unlocklots();
2928 foo.unlocklots(); // \
DeLesley Hutchinsa74b7152012-08-10 20:19:55 +00002929 // expected-warning {{unlocking 'foo.mu1_' that was not locked}} \
2930 // expected-warning {{unlocking 'foo.mu2_' that was not locked}} \
2931 // expected-warning {{unlocking 'foo.mu3_' that was not locked}}
DeLesley Hutchins5381c052012-07-05 21:16:29 +00002932}
2933
2934} // end namespace DuplicateAttributeTest
2935
2936
2937
DeLesley Hutchins13106112012-07-10 21:47:55 +00002938namespace TryLockEqTest {
2939
2940class Foo {
2941 Mutex mu_;
2942 int a GUARDED_BY(mu_);
2943 bool c;
2944
2945 int tryLockMutexI() EXCLUSIVE_TRYLOCK_FUNCTION(1, mu_);
2946 Mutex* tryLockMutexP() EXCLUSIVE_TRYLOCK_FUNCTION(1, mu_);
2947 void unlock() UNLOCK_FUNCTION(mu_);
2948
2949 void test1();
2950 void test2();
2951};
2952
2953
2954void Foo::test1() {
2955 if (tryLockMutexP() == 0) {
2956 a = 0; // expected-warning {{writing variable 'a' requires locking 'mu_' exclusively}}
2957 return;
2958 }
2959 a = 0;
2960 unlock();
2961
2962 if (tryLockMutexP() != 0) {
2963 a = 0;
2964 unlock();
2965 }
2966
2967 if (0 != tryLockMutexP()) {
2968 a = 0;
2969 unlock();
2970 }
2971
2972 if (!(tryLockMutexP() == 0)) {
2973 a = 0;
2974 unlock();
2975 }
2976
2977 if (tryLockMutexI() == 0) {
2978 a = 0; // expected-warning {{writing variable 'a' requires locking 'mu_' exclusively}}
2979 return;
2980 }
2981 a = 0;
2982 unlock();
2983
2984 if (0 == tryLockMutexI()) {
2985 a = 0; // expected-warning {{writing variable 'a' requires locking 'mu_' exclusively}}
2986 return;
2987 }
2988 a = 0;
2989 unlock();
2990
2991 if (tryLockMutexI() == 1) {
2992 a = 0;
2993 unlock();
2994 }
2995
2996 if (mu_.TryLock() == false) {
2997 a = 0; // expected-warning {{writing variable 'a' requires locking 'mu_' exclusively}}
2998 return;
2999 }
3000 a = 0;
3001 unlock();
3002
3003 if (mu_.TryLock() == true) {
3004 a = 0;
3005 unlock();
3006 }
3007 else {
3008 a = 0; // expected-warning {{writing variable 'a' requires locking 'mu_' exclusively}}
3009 }
3010
3011#if __has_feature(cxx_nullptr)
3012 if (tryLockMutexP() == nullptr) {
3013 a = 0; // expected-warning {{writing variable 'a' requires locking 'mu_' exclusively}}
3014 return;
3015 }
3016 a = 0;
3017 unlock();
3018#endif
3019}
3020
3021
3022void Foo::test2() {
3023/* FIXME: these tests depend on changes to the CFG.
3024 *
3025 if (mu_.TryLock() && c) {
3026 a = 0;
3027 unlock();
3028 }
3029 else return;
3030
3031 if (c && mu_.TryLock()) {
3032 a = 0;
3033 unlock();
3034 }
3035 else return;
3036
3037 if (!(mu_.TryLock() && c))
3038 return;
3039 a = 0;
3040 unlock();
3041
3042 if (!(c && mu_.TryLock()))
3043 return;
3044 a = 0;
3045 unlock();
3046
3047 if (!(mu_.TryLock() == 0) && c) {
3048 a = 0;
3049 unlock();
3050 }
3051
3052 if (!mu_.TryLock() || c)
3053 return;
3054 a = 0;
3055 unlock();
3056*/
3057}
3058
3059
3060} // end namespace TryLockEqTest
DeLesley Hutchins5381c052012-07-05 21:16:29 +00003061
DeLesley Hutchins96fac6a2012-07-03 19:47:18 +00003062