blob: 9523d43b9fc0051cdebb535300e55d3008da32e8 [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; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000532 // expected-warning{{writing variable 'a' requires locking '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; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000542 // expected-warning{{reading the value pointed to by 'q' requires locking '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; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000552 // expected-warning{{writing variable 'a' requires locking '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; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000560 // expected-warning{{writing variable 'a' requires locking '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; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000568 // expected-warning{{writing variable 'a' requires locking '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();
Caitlin Sadowski74558b42011-09-15 18:13:32 +00001202 f1.bar(); // expected-warning {{cannot call function 'bar' while mutex '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();
Caitlin Sadowski74558b42011-09-15 18:13:32 +00001208 f2->bar(); // expected-warning {{cannot call function 'bar' while mutex '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;
Caitlin Sadowski74558b42011-09-15 18:13:32 +00001236 b2->a_ = 3; // expected-warning {{writing variable 'a_' requires locking '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();
Caitlin Sadowski74558b42011-09-15 18:13:32 +00001265 res = b1.a_ + b3->b_; // expected-warning {{reading variable 'a_' requires locking 'mu1_'}} \
1266 // 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'}} \
1270 // expected-warning {{writing variable 'a_' requires locking 'mu1_' exclusively}}
1271 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.
1295 child->bar(7); // expected-warning {{calling function 'bar' requires exclusive lock on 'lock_'}}
Caitlin Sadowski74558b42011-09-15 18:13:32 +00001296 child->a_ = 5; // expected-warning {{writing variable 'a_' requires locking '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();
Caitlin Sadowski74558b42011-09-15 18:13:32 +00001333 child->Func(new_foo); // expected-warning {{cannot call function 'Func' while mutex '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{
1381 foo->f1(); // expected-warning {{calling function 'f1' requires exclusive lock on 'mu2'}} \
1382 // expected-warning {{calling function 'f1' requires exclusive lock on 'mu1'}}
1383}
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
1405 b->func1(); // expected-warning {{calling function 'func1' requires exclusive lock on 'mu_'}}
1406 b->mu_.Lock();
Caitlin Sadowski74558b42011-09-15 18:13:32 +00001407 b->func2(); // expected-warning {{cannot call function 'func2' while mutex 'mu_' is locked}}
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001408 b->mu_.Unlock();
1409
1410 c->func1(); // expected-warning {{calling function 'func1' requires exclusive lock on 'mu_'}}
1411 c->mu_.Lock();
Caitlin Sadowski74558b42011-09-15 18:13:32 +00001412 c->func2(); // expected-warning {{cannot call function 'func2' while mutex '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;
1439 a.method1(1); // expected-warning {{calling function 'method1' requires shared lock on 'mu1'}} \
1440 // expected-warning {{calling function 'method1' requires shared lock on 'mu'}} \
1441 // expected-warning {{calling function 'method1' requires shared lock on 'mu2'}} \
1442 // 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); // \
1487 // expected-warning {{unlocking 'mu' that was not locked}}
Richard Smith2e515622012-02-03 04:45:26 +00001488 } // expected-warning {{mutex '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); // \
1494 // expected-warning {{calling function 'foo' requires exclusive lock on 'mu'}}
1495 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'}}
Richard Smith97f9fe02011-10-25 00:41:24 +00001553 return t->s->n; // expected-warning {{reading variable 's' requires locking 'm'}}
1554 }
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) {
1569 v.p->f(u); // expected-warning {{reading variable 'p' requires locking 'm'}}
1570 }
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() {
1632 foo(); // expected-warning {{calling function 'foo' requires exclusive lock on 'mu_'}}
1633 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;
1705 if (b) { // b should be unknown at this point, becuase of the join point
1706 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); // \
1832 // expected-warning {{calling function 'barTD' requires exclusive lock on 'mu_'}}
1833
1834 bt.fooBase.mu_.Unlock();
1835 bt.fooBaseT.mu_.Unlock();
1836 f2.mu_.Unlock();
1837
1838 Cell<int> cell;
1839 cell.data = 0; // \
1840 // expected-warning {{writing variable 'data' requires locking 'mu_' exclusively}}
1841 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); // \
1909 // expected-warning {{calling function 'foo1' requires exclusive lock on 'mu_'}}
1910 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(); // \
2024 // expected-warning {{calling function 'foo2' requires exclusive lock on 'mu_'}}
2025 myFoo.foo3(&myFoo); // \
2026 // expected-warning {{calling function 'foo3' requires exclusive lock on 'mu_'}}
2027 myFoo.fooT1(dummy); // \
2028 // expected-warning {{calling function 'fooT1' requires exclusive lock on 'mu_'}}
2029
2030 // FIXME: uncomment with template instantiation of attributes patch
2031 // myFoo.fooT2(dummy); // expected warning
2032
2033 fooF1(&myFoo); // \
2034 // expected-warning {{calling function 'fooF1' requires exclusive lock on 'mu_'}}
2035 fooF2(&myFoo); // \
2036 // expected-warning {{calling function 'fooF2' requires exclusive lock on 'mu_'}}
2037 fooF3(&myFoo); // \
2038 // expected-warning {{calling function 'fooF3' requires exclusive lock on 'mu_'}}
2039
2040 myFoo.mu_.Lock();
2041 myFoo.foo2();
2042 myFoo.foo3(&myFoo);
2043 myFoo.fooT1(dummy);
2044
2045 // FIXME: uncomment with template instantiation of attributes patch
2046 // myFoo.fooT2(dummy);
2047
2048 fooF1(&myFoo);
2049 fooF2(&myFoo);
2050 fooF3(&myFoo);
2051 myFoo.mu_.Unlock();
2052
2053 FooT<int> myFooT;
2054 myFooT.foo(); // \
2055 // expected-warning {{calling function 'foo' requires exclusive lock on 'mu_'}}
2056}
2057
DeLesley Hutchins4bda3ec2012-02-16 17:03:24 +00002058} // end namespace FunctionDefinitionTest
2059
2060
2061namespace SelfLockingTest {
2062
2063class LOCKABLE MyLock {
2064public:
2065 int foo GUARDED_BY(this);
2066
2067 void lock() EXCLUSIVE_LOCK_FUNCTION();
2068 void unlock() UNLOCK_FUNCTION();
2069
2070 void doSomething() {
2071 this->lock(); // allow 'this' as a lock expression
2072 foo = 0;
2073 doSomethingElse();
2074 this->unlock();
2075 }
2076
2077 void doSomethingElse() EXCLUSIVE_LOCKS_REQUIRED(this) {
2078 foo = 1;
2079 };
2080
2081 void test() {
2082 foo = 2; // \
2083 // expected-warning {{writing variable 'foo' requires locking 'this' exclusively}}
2084 }
DeLesley Hutchinsc24a2332012-02-16 16:50:43 +00002085};
2086
DeLesley Hutchins2f13bec2012-02-16 17:13:43 +00002087
2088class LOCKABLE MyLock2 {
2089public:
2090 Mutex mu_;
2091 int foo GUARDED_BY(this);
2092
2093 // don't check inside lock and unlock functions
2094 void lock() EXCLUSIVE_LOCK_FUNCTION() { mu_.Lock(); }
2095 void unlock() UNLOCK_FUNCTION() { mu_.Unlock(); }
2096
2097 // don't check inside constructors and destructors
2098 MyLock2() { foo = 1; }
2099 ~MyLock2() { foo = 0; }
2100};
2101
2102
DeLesley Hutchins4bda3ec2012-02-16 17:03:24 +00002103} // end namespace SelfLockingTest
2104
2105
DeLesley Hutchinsd08d5992012-02-25 00:11:55 +00002106namespace InvalidNonstatic {
2107
2108// Forward decl here causes bogus "invalid use of non-static data member"
2109// on reference to mutex_ in guarded_by attribute.
2110class Foo;
2111
2112class Foo {
2113 Mutex* mutex_;
2114
2115 int foo __attribute__((guarded_by(mutex_)));
2116};
2117
2118} // end namespace InvalidNonStatic
2119
DeLesley Hutchins2a35be82012-03-02 22:02:58 +00002120
2121namespace NoReturnTest {
2122
2123bool condition();
2124void fatal() __attribute__((noreturn));
2125
2126Mutex mu_;
2127
2128void test1() {
2129 MutexLock lock(&mu_);
2130 if (condition()) {
2131 fatal();
2132 return;
2133 }
2134}
2135
DeLesley Hutchins2287c5e2012-03-02 22:12:59 +00002136} // end namespace NoReturnTest
2137
2138
2139namespace TestMultiDecl {
2140
2141class Foo {
2142public:
2143 int GUARDED_BY(mu_) a;
2144 int GUARDED_BY(mu_) b, c;
2145
2146 void foo() {
2147 a = 0; // \
2148 // expected-warning {{writing variable 'a' requires locking 'mu_' exclusively}}
2149 b = 0; // \
2150 // expected-warning {{writing variable 'b' requires locking 'mu_' exclusively}}
2151 c = 0; // \
2152 // expected-warning {{writing variable 'c' requires locking 'mu_' exclusively}}
2153 }
2154
2155private:
2156 Mutex mu_;
DeLesley Hutchins2a35be82012-03-02 22:02:58 +00002157};
DeLesley Hutchins2287c5e2012-03-02 22:12:59 +00002158
2159} // end namespace TestMultiDecl
2160
DeLesley Hutchins7ec419a2012-03-02 22:29:50 +00002161
2162namespace WarnNoDecl {
2163
2164class Foo {
2165 void foo(int a); __attribute__(( // \
2166 // expected-warning {{declaration does not declare anything}}
2167 exclusive_locks_required(a))); // \
2168 // expected-warning {{attribute exclusive_locks_required ignored}}
2169};
2170
2171} // end namespace WarnNoDecl
2172
2173
DeLesley Hutchins0d95dfc2012-03-02 23:36:05 +00002174
2175namespace MoreLockExpressions {
2176
2177class Foo {
2178public:
2179 Mutex mu_;
2180 int a GUARDED_BY(mu_);
2181};
2182
2183class Bar {
2184public:
2185 int b;
2186 Foo* f;
2187
2188 Foo& getFoo() { return *f; }
2189 Foo& getFoo2(int c) { return *f; }
2190 Foo& getFoo3(int c, int d) { return *f; }
2191
2192 Foo& getFooey() { return *f; }
2193};
2194
2195Foo& getBarFoo(Bar &bar, int c) { return bar.getFoo2(c); }
2196
2197void test() {
2198 Foo foo;
2199 Foo *fooArray;
2200 Bar bar;
2201 int a;
2202 int b;
2203 int c;
2204
2205 bar.getFoo().mu_.Lock();
2206 bar.getFoo().a = 0;
2207 bar.getFoo().mu_.Unlock();
2208
2209 (bar.getFoo().mu_).Lock(); // test parenthesis
2210 bar.getFoo().a = 0;
2211 (bar.getFoo().mu_).Unlock();
2212
2213 bar.getFoo2(a).mu_.Lock();
2214 bar.getFoo2(a).a = 0;
2215 bar.getFoo2(a).mu_.Unlock();
2216
2217 bar.getFoo3(a, b).mu_.Lock();
2218 bar.getFoo3(a, b).a = 0;
2219 bar.getFoo3(a, b).mu_.Unlock();
2220
2221 getBarFoo(bar, a).mu_.Lock();
2222 getBarFoo(bar, a).a = 0;
2223 getBarFoo(bar, a).mu_.Unlock();
2224
2225 bar.getFoo2(10).mu_.Lock();
2226 bar.getFoo2(10).a = 0;
2227 bar.getFoo2(10).mu_.Unlock();
2228
2229 bar.getFoo2(a + 1).mu_.Lock();
2230 bar.getFoo2(a + 1).a = 0;
2231 bar.getFoo2(a + 1).mu_.Unlock();
2232
2233 (a > 0 ? fooArray[1] : fooArray[b]).mu_.Lock();
2234 (a > 0 ? fooArray[1] : fooArray[b]).a = 0;
2235 (a > 0 ? fooArray[1] : fooArray[b]).mu_.Unlock();
2236
2237 bar.getFoo().mu_.Lock();
2238 bar.getFooey().a = 0; // \
2239 // expected-warning {{writing variable 'a' requires locking 'mu_' exclusively}}
2240 bar.getFoo().mu_.Unlock();
2241
2242 bar.getFoo2(a).mu_.Lock();
2243 bar.getFoo2(b).a = 0; // \
2244 // expected-warning {{writing variable 'a' requires locking 'mu_' exclusively}}
2245 bar.getFoo2(a).mu_.Unlock();
2246
2247 bar.getFoo3(a, b).mu_.Lock();
2248 bar.getFoo3(a, c).a = 0; // \
2249 // expected-warning {{writing variable 'a' requires locking 'mu_' exclusively}}
2250 bar.getFoo3(a, b).mu_.Unlock();
2251
2252 getBarFoo(bar, a).mu_.Lock();
2253 getBarFoo(bar, b).a = 0; // \
2254 // expected-warning {{writing variable 'a' requires locking 'mu_' exclusively}}
2255 getBarFoo(bar, a).mu_.Unlock();
2256
2257 (a > 0 ? fooArray[1] : fooArray[b]).mu_.Lock();
2258 (a > 0 ? fooArray[b] : fooArray[c]).a = 0; // \
2259 // expected-warning {{writing variable 'a' requires locking 'mu_' exclusively}}
2260 (a > 0 ? fooArray[1] : fooArray[b]).mu_.Unlock();
2261}
2262
2263
DeLesley Hutchins0da44142012-06-22 17:07:28 +00002264} // end namespace MoreLockExpressions
2265
2266
2267namespace TrylockJoinPoint {
2268
2269class Foo {
2270 Mutex mu;
2271 bool c;
2272
2273 void foo() {
2274 if (c) {
2275 if (!mu.TryLock())
2276 return;
2277 } else {
2278 mu.Lock();
2279 }
2280 mu.Unlock();
2281 }
2282};
2283
2284} // end namespace TrylockJoinPoint
DeLesley Hutchins0d95dfc2012-03-02 23:36:05 +00002285
2286
DeLesley Hutchinsf63797c2012-06-25 18:33:18 +00002287namespace LockReturned {
2288
2289class Foo {
2290public:
2291 int a GUARDED_BY(mu_);
2292 void foo() EXCLUSIVE_LOCKS_REQUIRED(mu_);
2293 void foo2(Foo* f) EXCLUSIVE_LOCKS_REQUIRED(mu_, f->mu_);
2294
2295 static void sfoo(Foo* f) EXCLUSIVE_LOCKS_REQUIRED(f->mu_);
2296
2297 Mutex* getMu() LOCK_RETURNED(mu_);
2298
2299 Mutex mu_;
2300
2301 static Mutex* getMu(Foo* f) LOCK_RETURNED(f->mu_);
2302};
2303
2304
2305// Calls getMu() directly to lock and unlock
2306void test1(Foo* f1, Foo* f2) {
2307 f1->a = 0; // expected-warning {{writing variable 'a' requires locking 'mu_' exclusively}}
2308 f1->foo(); // expected-warning {{calling function 'foo' requires exclusive lock on 'mu_'}}
2309
2310 f1->foo2(f2); // expected-warning 2{{calling function 'foo2' requires exclusive lock on 'mu_'}}
2311 Foo::sfoo(f1); // expected-warning {{calling function 'sfoo' requires exclusive lock on 'mu_'}}
2312
2313 f1->getMu()->Lock();
2314
2315 f1->a = 0;
2316 f1->foo();
2317 f1->foo2(f2); // expected-warning {{calling function 'foo2' requires exclusive lock on 'mu_'}}
2318
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) {
2346 b1->b = 0; // expected-warning {{writing variable 'b' requires locking 'mu_' exclusively}}
2347 b1->bar(); // expected-warning {{calling function 'bar' requires exclusive lock on 'mu_'}}
2348 b1->bar2(b2); // expected-warning 2{{calling function 'bar2' requires exclusive lock on 'mu_'}}
2349 Bar::sbar(b1); // expected-warning {{calling function 'sbar' requires exclusive lock on 'mu_'}}
2350 Bar::sbar2(b1); // expected-warning {{calling function 'sbar2' requires exclusive lock on 'mu_'}}
2351
2352 b1->getMu()->Lock();
2353
2354 b1->b = 0;
2355 b1->bar();
2356 b1->bar2(b2); // expected-warning {{calling function 'bar2' requires exclusive lock on 'mu_'}}
2357
2358 b2->getMu()->Lock();
2359 b1->bar2(b2);
2360
2361 b2->getMu()->Unlock();
2362
2363 Bar::sbar(b1);
2364 Bar::sbar2(b1);
2365
2366 b1->getMu()->Unlock();
2367}
2368
2369
2370// Sanity check -- lock the mutex directly, but use attributes that call getMu()
2371// Also lock the mutex using getFooMu, which calls a lock_returned function.
2372void test3(Bar* b1, Bar* b2) {
2373 b1->mu_.Lock();
2374 b1->b = 0;
2375 b1->bar();
2376
2377 getFooMu(b2)->Lock();
2378 b1->bar2(b2);
2379 getFooMu(b2)->Unlock();
2380
2381 Bar::sbar(b1);
2382 Bar::sbar2(b1);
2383
2384 b1->mu_.Unlock();
2385}
2386
2387} // end namespace LockReturned
2388
2389
DeLesley Hutchinsc99a5d82012-06-28 22:42:48 +00002390namespace ReleasableScopedLock {
2391
2392class Foo {
2393 Mutex mu_;
2394 bool c;
2395 int a GUARDED_BY(mu_);
2396
2397 void test1();
2398 void test2();
2399 void test3();
DeLesley Hutchins5381c052012-07-05 21:16:29 +00002400 void test4();
2401 void test5();
DeLesley Hutchinsc99a5d82012-06-28 22:42:48 +00002402};
2403
2404
2405void Foo::test1() {
2406 ReleasableMutexLock rlock(&mu_);
2407 rlock.Release();
2408}
2409
2410void Foo::test2() {
2411 ReleasableMutexLock rlock(&mu_);
2412 if (c) { // test join point -- held/not held during release
2413 rlock.Release();
2414 }
2415}
2416
2417void Foo::test3() {
2418 ReleasableMutexLock rlock(&mu_);
2419 a = 0;
2420 rlock.Release();
2421 a = 1; // expected-warning {{writing variable 'a' requires locking 'mu_' exclusively}}
2422}
2423
DeLesley Hutchins5381c052012-07-05 21:16:29 +00002424void Foo::test4() {
2425 ReleasableMutexLock rlock(&mu_);
2426 rlock.Release();
2427 rlock.Release(); // expected-warning {{unlocking 'mu_' that was not locked}}
2428}
2429
2430void Foo::test5() {
2431 ReleasableMutexLock rlock(&mu_);
2432 if (c) {
2433 rlock.Release();
2434 }
2435 // no warning on join point for managed lock.
2436 rlock.Release(); // expected-warning {{unlocking 'mu_' that was not locked}}
2437}
2438
2439
DeLesley Hutchinsc99a5d82012-06-28 22:42:48 +00002440} // end namespace ReleasableScopedLock
2441
2442
DeLesley Hutchins76f0a6e2012-07-02 21:59:24 +00002443namespace TrylockFunctionTest {
2444
2445class Foo {
2446public:
2447 Mutex mu1_;
2448 Mutex mu2_;
2449 bool c;
2450
2451 bool lockBoth() EXCLUSIVE_TRYLOCK_FUNCTION(true, mu1_, mu2_);
2452};
2453
2454bool Foo::lockBoth() {
2455 if (!mu1_.TryLock())
2456 return false;
2457
2458 mu2_.Lock();
2459 if (!c) {
2460 mu1_.Unlock();
2461 mu2_.Unlock();
2462 return false;
2463 }
2464
2465 return true;
2466}
2467
2468
2469} // end namespace TrylockFunctionTest
DeLesley Hutchinsc99a5d82012-06-28 22:42:48 +00002470
2471
2472
DeLesley Hutchinsc36eda12012-07-02 22:12:12 +00002473namespace DoubleLockBug {
2474
2475class Foo {
2476public:
2477 Mutex mu_;
2478 int a GUARDED_BY(mu_);
2479
DeLesley Hutchins5381c052012-07-05 21:16:29 +00002480 void foo1() EXCLUSIVE_LOCKS_REQUIRED(mu_);
2481 int foo2() SHARED_LOCKS_REQUIRED(mu_);
DeLesley Hutchinsc36eda12012-07-02 22:12:12 +00002482};
2483
2484
DeLesley Hutchins5381c052012-07-05 21:16:29 +00002485void Foo::foo1() EXCLUSIVE_LOCKS_REQUIRED(mu_) {
DeLesley Hutchinsc36eda12012-07-02 22:12:12 +00002486 a = 0;
2487}
2488
DeLesley Hutchins5381c052012-07-05 21:16:29 +00002489int Foo::foo2() SHARED_LOCKS_REQUIRED(mu_) {
2490 return a;
2491}
2492
2493}
2494
DeLesley Hutchinsc36eda12012-07-02 22:12:12 +00002495
2496
DeLesley Hutchins879a4332012-07-02 22:16:54 +00002497namespace UnlockBug {
DeLesley Hutchinsc36eda12012-07-02 22:12:12 +00002498
DeLesley Hutchins879a4332012-07-02 22:16:54 +00002499class Foo {
2500public:
2501 Mutex mutex_;
2502
2503 void foo1() EXCLUSIVE_LOCKS_REQUIRED(mutex_) { // expected-note {{mutex acquired here}}
2504 mutex_.Unlock();
2505 } // expected-warning {{expecting mutex 'mutex_' to be locked at the end of function}}
2506
2507
2508 void foo2() SHARED_LOCKS_REQUIRED(mutex_) { // expected-note {{mutex acquired here}}
2509 mutex_.Unlock();
2510 } // expected-warning {{expecting mutex 'mutex_' to be locked at the end of function}}
2511};
2512
2513} // end namespace UnlockBug
DeLesley Hutchinsc36eda12012-07-02 22:12:12 +00002514
DeLesley Hutchinsc99a5d82012-06-28 22:42:48 +00002515
DeLesley Hutchins5381c052012-07-05 21:16:29 +00002516
DeLesley Hutchinsbbe33412012-07-02 22:26:29 +00002517namespace FoolishScopedLockableBug {
2518
2519class SCOPED_LOCKABLE WTF_ScopedLockable {
2520public:
2521 WTF_ScopedLockable(Mutex* mu) EXCLUSIVE_LOCK_FUNCTION(mu);
2522
2523 // have to call release() manually;
2524 ~WTF_ScopedLockable();
2525
2526 void release() UNLOCK_FUNCTION();
2527};
2528
2529
2530class Foo {
2531 Mutex mu_;
2532 int a GUARDED_BY(mu_);
2533 bool c;
2534
2535 void doSomething();
2536
2537 void test1() {
2538 WTF_ScopedLockable wtf(&mu_);
2539 wtf.release();
2540 }
2541
2542 void test2() {
2543 WTF_ScopedLockable wtf(&mu_); // expected-note {{mutex acquired here}}
2544 } // expected-warning {{mutex 'mu_' is still locked at the end of function}}
2545
2546 void test3() {
2547 if (c) {
2548 WTF_ScopedLockable wtf(&mu_);
2549 wtf.release();
2550 }
2551 }
2552
2553 void test4() {
2554 if (c) {
2555 doSomething();
2556 }
2557 else {
2558 WTF_ScopedLockable wtf(&mu_);
2559 wtf.release();
2560 }
2561 }
2562
2563 void test5() {
2564 if (c) {
2565 WTF_ScopedLockable wtf(&mu_); // expected-note {{mutex acquired here}}
2566 }
2567 } // expected-warning {{mutex 'mu_' is not locked on every path through here}}
2568
2569 void test6() {
2570 if (c) {
2571 doSomething();
2572 }
2573 else {
2574 WTF_ScopedLockable wtf(&mu_); // expected-note {{mutex acquired here}}
2575 }
2576 } // expected-warning {{mutex 'mu_' is not locked on every path through here}}
2577};
2578
2579
2580} // end namespace FoolishScopedLockableBug
2581
DeLesley Hutchins9d6e7f32012-07-03 18:25:56 +00002582
DeLesley Hutchins5381c052012-07-05 21:16:29 +00002583
DeLesley Hutchins9d6e7f32012-07-03 18:25:56 +00002584namespace TemporaryCleanupExpr {
2585
2586class Foo {
2587 int a GUARDED_BY(getMutexPtr().get());
2588
2589 SmartPtr<Mutex> getMutexPtr();
2590
2591 void test();
2592};
2593
2594
2595void Foo::test() {
2596 {
2597 ReaderMutexLock lock(getMutexPtr().get());
2598 int b = a;
DeLesley Hutchins96fac6a2012-07-03 19:47:18 +00002599 }
2600 int b = a; // expected-warning {{reading variable 'a' requires locking 'getMutexPtr'}}
DeLesley Hutchins9d6e7f32012-07-03 18:25:56 +00002601}
2602
2603} // end namespace TemporaryCleanupExpr
2604
2605
DeLesley Hutchins96fac6a2012-07-03 19:47:18 +00002606
2607namespace SmartPointerTests {
2608
2609class Foo {
2610public:
2611 SmartPtr<Mutex> mu_;
2612 int a GUARDED_BY(mu_);
2613 int b GUARDED_BY(mu_.get());
2614 int c GUARDED_BY(*mu_);
2615
2616 void Lock() EXCLUSIVE_LOCK_FUNCTION(mu_);
2617 void Unlock() UNLOCK_FUNCTION(mu_);
2618
2619 void test0();
2620 void test1();
2621 void test2();
2622 void test3();
2623 void test4();
2624 void test5();
2625 void test6();
2626 void test7();
2627 void test8();
2628};
2629
2630void Foo::test0() {
2631 a = 0; // expected-warning {{writing variable 'a' requires locking 'mu_' exclusively}}
2632 b = 0; // expected-warning {{writing variable 'b' requires locking 'mu_' exclusively}}
2633 c = 0; // expected-warning {{writing variable 'c' requires locking 'mu_' exclusively}}
2634}
2635
2636void Foo::test1() {
2637 mu_->Lock();
2638 a = 0;
2639 b = 0;
2640 c = 0;
2641 mu_->Unlock();
2642}
2643
2644void Foo::test2() {
2645 (*mu_).Lock();
2646 a = 0;
2647 b = 0;
2648 c = 0;
2649 (*mu_).Unlock();
2650}
2651
2652
2653void Foo::test3() {
2654 mu_.get()->Lock();
2655 a = 0;
2656 b = 0;
2657 c = 0;
2658 mu_.get()->Unlock();
2659}
2660
2661
2662void Foo::test4() {
2663 MutexLock lock(mu_.get());
2664 a = 0;
2665 b = 0;
2666 c = 0;
2667}
2668
2669
2670void Foo::test5() {
2671 MutexLock lock(&(*mu_));
2672 a = 0;
2673 b = 0;
2674 c = 0;
2675}
2676
2677
2678void Foo::test6() {
2679 Lock();
2680 a = 0;
2681 b = 0;
2682 c = 0;
2683 Unlock();
2684}
2685
2686
2687void Foo::test7() {
2688 {
2689 Lock();
2690 mu_->Unlock();
2691 }
2692 {
2693 mu_->Lock();
2694 Unlock();
2695 }
2696 {
2697 mu_.get()->Lock();
2698 mu_->Unlock();
2699 }
2700 {
2701 mu_->Lock();
2702 mu_.get()->Unlock();
2703 }
2704 {
2705 mu_.get()->Lock();
2706 (*mu_).Unlock();
2707 }
2708 {
2709 (*mu_).Lock();
2710 mu_->Unlock();
2711 }
2712}
2713
2714
2715void Foo::test8() {
2716 mu_->Lock();
2717 mu_.get()->Lock(); // expected-warning {{locking 'mu_' that is already locked}}
2718 (*mu_).Lock(); // expected-warning {{locking 'mu_' that is already locked}}
2719 mu_.get()->Unlock();
2720 Unlock(); // expected-warning {{unlocking 'mu_' that was not locked}}
2721}
2722
2723
2724class Bar {
2725 SmartPtr<Foo> foo;
2726
2727 void test0();
2728 void test1();
2729 void test2();
2730 void test3();
2731};
2732
2733
2734void Bar::test0() {
2735 foo->a = 0; // expected-warning {{writing variable 'a' requires locking 'mu_' exclusively}}
2736 (*foo).b = 0; // expected-warning {{writing variable 'b' requires locking 'mu_' exclusively}}
2737 foo.get()->c = 0; // expected-warning {{writing variable 'c' requires locking 'mu_' exclusively}}
2738}
2739
2740
2741void Bar::test1() {
2742 foo->mu_->Lock();
2743 foo->a = 0;
2744 (*foo).b = 0;
2745 foo.get()->c = 0;
2746 foo->mu_->Unlock();
2747}
2748
2749
2750void Bar::test2() {
2751 (*foo).mu_->Lock();
2752 foo->a = 0;
2753 (*foo).b = 0;
2754 foo.get()->c = 0;
2755 foo.get()->mu_->Unlock();
2756}
2757
2758
2759void Bar::test3() {
2760 MutexLock lock(foo->mu_.get());
2761 foo->a = 0;
2762 (*foo).b = 0;
2763 foo.get()->c = 0;
2764}
2765
2766} // end namespace SmartPointerTests
2767
2768
2769
DeLesley Hutchins5381c052012-07-05 21:16:29 +00002770namespace DuplicateAttributeTest {
2771
2772class LOCKABLE Foo {
2773public:
2774 Mutex mu1_;
2775 Mutex mu2_;
2776 Mutex mu3_;
2777 int a GUARDED_BY(mu1_);
2778 int b GUARDED_BY(mu2_);
2779 int c GUARDED_BY(mu3_);
2780
2781 void lock() EXCLUSIVE_LOCK_FUNCTION();
2782 void unlock() UNLOCK_FUNCTION();
2783
2784 void lock1() EXCLUSIVE_LOCK_FUNCTION(mu1_);
2785 void slock1() SHARED_LOCK_FUNCTION(mu1_);
2786 void lock3() EXCLUSIVE_LOCK_FUNCTION(mu1_, mu2_, mu3_);
2787 void locklots()
2788 EXCLUSIVE_LOCK_FUNCTION(mu1_)
2789 EXCLUSIVE_LOCK_FUNCTION(mu2_)
2790 EXCLUSIVE_LOCK_FUNCTION(mu1_, mu2_, mu3_);
2791
2792 void unlock1() UNLOCK_FUNCTION(mu1_);
2793 void unlock3() UNLOCK_FUNCTION(mu1_, mu2_, mu3_);
2794 void unlocklots()
2795 UNLOCK_FUNCTION(mu1_)
2796 UNLOCK_FUNCTION(mu2_)
2797 UNLOCK_FUNCTION(mu1_, mu2_, mu3_);
2798};
2799
2800
2801void Foo::lock() EXCLUSIVE_LOCK_FUNCTION() { }
2802void Foo::unlock() UNLOCK_FUNCTION() { }
2803
2804void Foo::lock1() EXCLUSIVE_LOCK_FUNCTION(mu1_) {
2805 mu1_.Lock();
2806}
2807
2808void Foo::slock1() SHARED_LOCK_FUNCTION(mu1_) {
2809 mu1_.Lock();
2810}
2811
2812void Foo::lock3() EXCLUSIVE_LOCK_FUNCTION(mu1_, mu2_, mu3_) {
2813 mu1_.Lock();
2814 mu2_.Lock();
2815 mu3_.Lock();
2816}
2817
2818void Foo::locklots()
2819 EXCLUSIVE_LOCK_FUNCTION(mu1_, mu2_)
2820 EXCLUSIVE_LOCK_FUNCTION(mu2_, mu3_) {
2821 mu1_.Lock();
2822 mu2_.Lock();
2823 mu3_.Lock();
2824}
2825
2826void Foo::unlock1() UNLOCK_FUNCTION(mu1_) {
2827 mu1_.Unlock();
2828}
2829
2830void Foo::unlock3() UNLOCK_FUNCTION(mu1_, mu2_, mu3_) {
2831 mu1_.Unlock();
2832 mu2_.Unlock();
2833 mu3_.Unlock();
2834}
2835
2836void Foo::unlocklots()
2837 UNLOCK_FUNCTION(mu1_, mu2_)
2838 UNLOCK_FUNCTION(mu2_, mu3_) {
2839 mu1_.Unlock();
2840 mu2_.Unlock();
2841 mu3_.Unlock();
2842}
2843
2844
2845void test0() {
2846 Foo foo;
2847 foo.lock();
2848 foo.unlock();
2849
2850 foo.lock();
2851 foo.lock(); // expected-warning {{locking 'foo' that is already locked}}
2852 foo.unlock();
2853 foo.unlock(); // expected-warning {{unlocking 'foo' that was not locked}}
2854}
2855
2856
2857void test1() {
2858 Foo foo;
2859 foo.lock1();
2860 foo.a = 0;
2861 foo.unlock1();
2862
2863 foo.lock1();
2864 foo.lock1(); // expected-warning {{locking 'mu1_' that is already locked}}
2865 foo.a = 0;
2866 foo.unlock1();
2867 foo.unlock1(); // expected-warning {{unlocking 'mu1_' that was not locked}}
2868}
2869
2870
2871int test2() {
2872 Foo foo;
2873 foo.slock1();
2874 int d1 = foo.a;
2875 foo.unlock1();
2876
2877 foo.slock1();
2878 foo.slock1(); // expected-warning {{locking 'mu1_' that is already locked}}
2879 int d2 = foo.a;
2880 foo.unlock1();
2881 foo.unlock1(); // expected-warning {{unlocking 'mu1_' that was not locked}}
2882 return d1 + d2;
2883}
2884
2885
2886void test3() {
2887 Foo foo;
2888 foo.lock3();
2889 foo.a = 0;
2890 foo.b = 0;
2891 foo.c = 0;
2892 foo.unlock3();
2893
2894 foo.lock3();
2895 foo.lock3(); // \
2896 // expected-warning {{locking 'mu1_' that is already locked}} \
2897 // expected-warning {{locking 'mu2_' that is already locked}} \
2898 // expected-warning {{locking 'mu3_' that is already locked}}
2899 foo.a = 0;
2900 foo.b = 0;
2901 foo.c = 0;
2902 foo.unlock3();
2903 foo.unlock3(); // \
2904 // expected-warning {{unlocking 'mu1_' that was not locked}} \
2905 // expected-warning {{unlocking 'mu2_' that was not locked}} \
2906 // expected-warning {{unlocking 'mu3_' that was not locked}}
2907}
2908
2909
2910void testlots() {
2911 Foo foo;
2912 foo.locklots();
2913 foo.a = 0;
2914 foo.b = 0;
2915 foo.c = 0;
2916 foo.unlocklots();
2917
2918 foo.locklots();
2919 foo.locklots(); // \
2920 // expected-warning {{locking 'mu1_' that is already locked}} \
2921 // expected-warning {{locking 'mu2_' that is already locked}} \
2922 // expected-warning {{locking 'mu3_' that is already locked}}
2923 foo.a = 0;
2924 foo.b = 0;
2925 foo.c = 0;
2926 foo.unlocklots();
2927 foo.unlocklots(); // \
2928 // expected-warning {{unlocking 'mu1_' that was not locked}} \
2929 // expected-warning {{unlocking 'mu2_' that was not locked}} \
2930 // expected-warning {{unlocking 'mu3_' that was not locked}}
2931}
2932
2933} // end namespace DuplicateAttributeTest
2934
2935
2936
DeLesley Hutchins13106112012-07-10 21:47:55 +00002937namespace TryLockEqTest {
2938
2939class Foo {
2940 Mutex mu_;
2941 int a GUARDED_BY(mu_);
2942 bool c;
2943
2944 int tryLockMutexI() EXCLUSIVE_TRYLOCK_FUNCTION(1, mu_);
2945 Mutex* tryLockMutexP() EXCLUSIVE_TRYLOCK_FUNCTION(1, mu_);
2946 void unlock() UNLOCK_FUNCTION(mu_);
2947
2948 void test1();
2949 void test2();
2950};
2951
2952
2953void Foo::test1() {
2954 if (tryLockMutexP() == 0) {
2955 a = 0; // expected-warning {{writing variable 'a' requires locking 'mu_' exclusively}}
2956 return;
2957 }
2958 a = 0;
2959 unlock();
2960
2961 if (tryLockMutexP() != 0) {
2962 a = 0;
2963 unlock();
2964 }
2965
2966 if (0 != tryLockMutexP()) {
2967 a = 0;
2968 unlock();
2969 }
2970
2971 if (!(tryLockMutexP() == 0)) {
2972 a = 0;
2973 unlock();
2974 }
2975
2976 if (tryLockMutexI() == 0) {
2977 a = 0; // expected-warning {{writing variable 'a' requires locking 'mu_' exclusively}}
2978 return;
2979 }
2980 a = 0;
2981 unlock();
2982
2983 if (0 == tryLockMutexI()) {
2984 a = 0; // expected-warning {{writing variable 'a' requires locking 'mu_' exclusively}}
2985 return;
2986 }
2987 a = 0;
2988 unlock();
2989
2990 if (tryLockMutexI() == 1) {
2991 a = 0;
2992 unlock();
2993 }
2994
2995 if (mu_.TryLock() == false) {
2996 a = 0; // expected-warning {{writing variable 'a' requires locking 'mu_' exclusively}}
2997 return;
2998 }
2999 a = 0;
3000 unlock();
3001
3002 if (mu_.TryLock() == true) {
3003 a = 0;
3004 unlock();
3005 }
3006 else {
3007 a = 0; // expected-warning {{writing variable 'a' requires locking 'mu_' exclusively}}
3008 }
3009
3010#if __has_feature(cxx_nullptr)
3011 if (tryLockMutexP() == nullptr) {
3012 a = 0; // expected-warning {{writing variable 'a' requires locking 'mu_' exclusively}}
3013 return;
3014 }
3015 a = 0;
3016 unlock();
3017#endif
3018}
3019
3020
3021void Foo::test2() {
3022/* FIXME: these tests depend on changes to the CFG.
3023 *
3024 if (mu_.TryLock() && c) {
3025 a = 0;
3026 unlock();
3027 }
3028 else return;
3029
3030 if (c && mu_.TryLock()) {
3031 a = 0;
3032 unlock();
3033 }
3034 else return;
3035
3036 if (!(mu_.TryLock() && c))
3037 return;
3038 a = 0;
3039 unlock();
3040
3041 if (!(c && mu_.TryLock()))
3042 return;
3043 a = 0;
3044 unlock();
3045
3046 if (!(mu_.TryLock() == 0) && c) {
3047 a = 0;
3048 unlock();
3049 }
3050
3051 if (!mu_.TryLock() || c)
3052 return;
3053 a = 0;
3054 unlock();
3055*/
3056}
3057
3058
3059} // end namespace TryLockEqTest
DeLesley Hutchins5381c052012-07-05 21:16:29 +00003060
DeLesley Hutchins96fac6a2012-07-03 19:47:18 +00003061