blob: a82d265a7e39180f9bea1e8f389ca348bcd6dbd3 [file] [log] [blame]
DeLesley Hutchins13106112012-07-10 21:47:55 +00001// RUN: %clang_cc1 -fsyntax-only -verify -Wthread-safety -std=c++11 %s
2
3// FIXME: should also run %clang_cc1 -fsyntax-only -verify -Wthread-safety -std=c++11 -Wc++98-compat %s
4// FIXME: should also run %clang_cc1 -fsyntax-only -verify -Wthread-safety %s
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +00005
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00006#define LOCKABLE __attribute__ ((lockable))
7#define SCOPED_LOCKABLE __attribute__ ((scoped_lockable))
8#define GUARDED_BY(x) __attribute__ ((guarded_by(x)))
9#define GUARDED_VAR __attribute__ ((guarded_var))
10#define PT_GUARDED_BY(x) __attribute__ ((pt_guarded_by(x)))
11#define PT_GUARDED_VAR __attribute__ ((pt_guarded_var))
12#define ACQUIRED_AFTER(...) __attribute__ ((acquired_after(__VA_ARGS__)))
13#define ACQUIRED_BEFORE(...) __attribute__ ((acquired_before(__VA_ARGS__)))
14#define EXCLUSIVE_LOCK_FUNCTION(...) __attribute__ ((exclusive_lock_function(__VA_ARGS__)))
15#define SHARED_LOCK_FUNCTION(...) __attribute__ ((shared_lock_function(__VA_ARGS__)))
16#define EXCLUSIVE_TRYLOCK_FUNCTION(...) __attribute__ ((exclusive_trylock_function(__VA_ARGS__)))
17#define SHARED_TRYLOCK_FUNCTION(...) __attribute__ ((shared_trylock_function(__VA_ARGS__)))
18#define UNLOCK_FUNCTION(...) __attribute__ ((unlock_function(__VA_ARGS__)))
19#define LOCK_RETURNED(x) __attribute__ ((lock_returned(x)))
20#define LOCKS_EXCLUDED(...) __attribute__ ((locks_excluded(__VA_ARGS__)))
21#define EXCLUSIVE_LOCKS_REQUIRED(...) \
22 __attribute__ ((exclusive_locks_required(__VA_ARGS__)))
23#define SHARED_LOCKS_REQUIRED(...) \
24 __attribute__ ((shared_locks_required(__VA_ARGS__)))
25#define NO_THREAD_SAFETY_ANALYSIS __attribute__ ((no_thread_safety_analysis))
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +000026
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +000027
28class __attribute__((lockable)) Mutex {
29 public:
30 void Lock() __attribute__((exclusive_lock_function));
31 void ReaderLock() __attribute__((shared_lock_function));
32 void Unlock() __attribute__((unlock_function));
33 bool TryLock() __attribute__((exclusive_trylock_function(true)));
34 bool ReaderTryLock() __attribute__((shared_trylock_function(true)));
35 void LockWhen(const int &cond) __attribute__((exclusive_lock_function));
36};
37
DeLesley Hutchins1fa3c062011-12-08 20:23:06 +000038class __attribute__((scoped_lockable)) MutexLock {
39 public:
40 MutexLock(Mutex *mu) __attribute__((exclusive_lock_function(mu)));
41 ~MutexLock() __attribute__((unlock_function));
42};
43
44class __attribute__((scoped_lockable)) ReaderMutexLock {
45 public:
46 ReaderMutexLock(Mutex *mu) __attribute__((exclusive_lock_function(mu)));
47 ~ReaderMutexLock() __attribute__((unlock_function));
48};
49
DeLesley Hutchinsc99a5d82012-06-28 22:42:48 +000050class SCOPED_LOCKABLE ReleasableMutexLock {
51 public:
52 ReleasableMutexLock(Mutex *mu) EXCLUSIVE_LOCK_FUNCTION(mu);
53 ~ReleasableMutexLock() UNLOCK_FUNCTION();
54
55 void Release() UNLOCK_FUNCTION();
56};
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +000057
DeLesley Hutchins9d6e7f32012-07-03 18:25:56 +000058
DeLesley Hutchins0b4db3e2012-09-07 17:34:53 +000059// The universal lock, written "*", allows checking to be selectively turned
60// off for a particular piece of code.
61void beginNoWarnOnReads() SHARED_LOCK_FUNCTION("*");
62void endNoWarnOnReads() UNLOCK_FUNCTION("*");
63void beginNoWarnOnWrites() EXCLUSIVE_LOCK_FUNCTION("*");
64void endNoWarnOnWrites() UNLOCK_FUNCTION("*");
65
66
DeLesley Hutchinsd2f38822012-09-21 17:57:00 +000067// For testing handling of smart pointers.
DeLesley Hutchins9d6e7f32012-07-03 18:25:56 +000068template<class T>
69class SmartPtr {
70public:
71 SmartPtr(T* p) : ptr_(p) { }
72 SmartPtr(const SmartPtr<T>& p) : ptr_(p.ptr_) { }
73 ~SmartPtr();
74
75 T* get() const { return ptr_; }
76 T* operator->() const { return ptr_; }
DeLesley Hutchins96fac6a2012-07-03 19:47:18 +000077 T& operator*() const { return *ptr_; }
DeLesley Hutchins9d6e7f32012-07-03 18:25:56 +000078
79private:
80 T* ptr_;
81};
82
83
DeLesley Hutchinsd2f38822012-09-21 17:57:00 +000084// For testing destructor calls and cleanup.
85class MyString {
86public:
87 MyString(const char* s);
88 ~MyString();
89};
90
91
92
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +000093Mutex sls_mu;
94
95Mutex sls_mu2 __attribute__((acquired_after(sls_mu)));
96int sls_guard_var __attribute__((guarded_var)) = 0;
97int sls_guardby_var __attribute__((guarded_by(sls_mu))) = 0;
98
99bool getBool();
100
101class MutexWrapper {
102public:
103 Mutex mu;
Caitlin Sadowski194418f2011-09-14 20:00:24 +0000104 int x __attribute__((guarded_by(mu)));
105 void MyLock() __attribute__((exclusive_lock_function(mu)));
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000106};
107
108MutexWrapper sls_mw;
109
110void sls_fun_0() {
111 sls_mw.mu.Lock();
Caitlin Sadowski194418f2011-09-14 20:00:24 +0000112 sls_mw.x = 5;
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000113 sls_mw.mu.Unlock();
114}
115
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000116void sls_fun_2() {
117 sls_mu.Lock();
118 int x = sls_guard_var;
119 sls_mu.Unlock();
120}
121
122void sls_fun_3() {
123 sls_mu.Lock();
124 sls_guard_var = 2;
125 sls_mu.Unlock();
126}
127
128void sls_fun_4() {
129 sls_mu2.Lock();
130 sls_guard_var = 2;
131 sls_mu2.Unlock();
132}
133
134void sls_fun_5() {
135 sls_mu.Lock();
136 int x = sls_guardby_var;
137 sls_mu.Unlock();
138}
139
140void sls_fun_6() {
141 sls_mu.Lock();
142 sls_guardby_var = 2;
143 sls_mu.Unlock();
144}
145
146void sls_fun_7() {
147 sls_mu.Lock();
148 sls_mu2.Lock();
149 sls_mu2.Unlock();
150 sls_mu.Unlock();
151}
152
153void sls_fun_8() {
154 sls_mu.Lock();
155 if (getBool())
156 sls_mu.Unlock();
157 else
158 sls_mu.Unlock();
159}
160
161void sls_fun_9() {
162 if (getBool())
163 sls_mu.Lock();
164 else
165 sls_mu.Lock();
166 sls_mu.Unlock();
167}
168
169void sls_fun_good_6() {
170 if (getBool()) {
171 sls_mu.Lock();
172 } else {
173 if (getBool()) {
174 getBool(); // EMPTY
175 } else {
176 getBool(); // EMPTY
177 }
178 sls_mu.Lock();
179 }
180 sls_mu.Unlock();
181}
182
183void sls_fun_good_7() {
184 sls_mu.Lock();
185 while (getBool()) {
186 sls_mu.Unlock();
187 if (getBool()) {
188 if (getBool()) {
189 sls_mu.Lock();
190 continue;
191 }
192 }
193 sls_mu.Lock();
194 }
195 sls_mu.Unlock();
196}
197
Caitlin Sadowski194418f2011-09-14 20:00:24 +0000198void sls_fun_good_8() {
199 sls_mw.MyLock();
200 sls_mw.mu.Unlock();
201}
202
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000203void sls_fun_bad_1() {
204 sls_mu.Unlock(); // \
Caitlin Sadowski8bccabe2011-09-08 21:52:50 +0000205 // expected-warning{{unlocking 'sls_mu' that was not locked}}
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000206}
207
208void sls_fun_bad_2() {
209 sls_mu.Lock();
210 sls_mu.Lock(); // \
Caitlin Sadowski8bccabe2011-09-08 21:52:50 +0000211 // expected-warning{{locking 'sls_mu' that is already locked}}
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000212 sls_mu.Unlock();
213}
214
215void sls_fun_bad_3() {
Richard Smith2e515622012-02-03 04:45:26 +0000216 sls_mu.Lock(); // expected-note {{mutex acquired here}}
217} // expected-warning{{mutex 'sls_mu' is still locked at the end of function}}
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000218
219void sls_fun_bad_4() {
220 if (getBool())
DeLesley Hutchins0da44142012-06-22 17:07:28 +0000221 sls_mu.Lock(); // expected-note{{mutex acquired here}}
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000222 else
DeLesley Hutchins0da44142012-06-22 17:07:28 +0000223 sls_mu2.Lock(); // expected-note{{mutex acquired here}}
224} // expected-warning{{mutex 'sls_mu' is not locked on every path through here}} \
225 // expected-warning{{mutex 'sls_mu2' is not locked on every path through here}}
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000226
227void sls_fun_bad_5() {
Richard Smith2e515622012-02-03 04:45:26 +0000228 sls_mu.Lock(); // expected-note {{mutex acquired here}}
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000229 if (getBool())
230 sls_mu.Unlock();
Richard Smith2e515622012-02-03 04:45:26 +0000231} // expected-warning{{mutex 'sls_mu' is not locked on every path through here}}
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000232
233void sls_fun_bad_6() {
234 if (getBool()) {
Richard Smith2e515622012-02-03 04:45:26 +0000235 sls_mu.Lock(); // expected-note {{mutex acquired here}}
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000236 } else {
237 if (getBool()) {
238 getBool(); // EMPTY
239 } else {
240 getBool(); // EMPTY
241 }
242 }
243 sls_mu.Unlock(); // \
Richard Smith2e515622012-02-03 04:45:26 +0000244 expected-warning{{mutex 'sls_mu' is not locked on every path through here}}\
245 expected-warning{{unlocking 'sls_mu' that was not locked}}
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000246}
247
248void sls_fun_bad_7() {
Richard Smithaacde712012-02-03 03:30:07 +0000249 sls_mu.Lock();
Caitlin Sadowski4e4bc752011-09-15 17:25:19 +0000250 while (getBool()) {
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000251 sls_mu.Unlock();
252 if (getBool()) {
253 if (getBool()) {
Richard Smith2e515622012-02-03 04:45:26 +0000254 continue; // \
255 expected-warning{{expecting mutex 'sls_mu' to be locked at start of each loop}}
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000256 }
257 }
Richard Smith2e515622012-02-03 04:45:26 +0000258 sls_mu.Lock(); // expected-note {{mutex acquired here}}
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000259 }
260 sls_mu.Unlock();
261}
262
263void sls_fun_bad_8() {
Richard Smith2e515622012-02-03 04:45:26 +0000264 sls_mu.Lock(); // expected-note{{mutex acquired here}}
265
DeLesley Hutchins0da44142012-06-22 17:07:28 +0000266 do {
267 sls_mu.Unlock(); // expected-warning{{expecting mutex 'sls_mu' to be locked at start of each loop}}
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000268 } while (getBool());
269}
270
271void sls_fun_bad_9() {
272 do {
DeLesley Hutchins0da44142012-06-22 17:07:28 +0000273 sls_mu.Lock(); // \
Richard Smith2e515622012-02-03 04:45:26 +0000274 // expected-warning{{expecting mutex 'sls_mu' to be locked at start of each loop}} \
275 // expected-note{{mutex acquired here}}
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000276 } while (getBool());
277 sls_mu.Unlock();
278}
279
280void sls_fun_bad_10() {
DeLesley Hutchins0da44142012-06-22 17:07:28 +0000281 sls_mu.Lock(); // expected-note 2{{mutex acquired here}}
282 while(getBool()) { // expected-warning{{expecting mutex 'sls_mu' to be locked at start of each loop}}
283 sls_mu.Unlock();
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000284 }
Richard Smith2e515622012-02-03 04:45:26 +0000285} // expected-warning{{mutex 'sls_mu' is still locked at the end of function}}
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000286
287void sls_fun_bad_11() {
Richard Smith2e515622012-02-03 04:45:26 +0000288 while (getBool()) { // \
DeLesley Hutchins0da44142012-06-22 17:07:28 +0000289 expected-warning{{expecting mutex 'sls_mu' to be locked at start of each loop}}
Richard Smith2e515622012-02-03 04:45:26 +0000290 sls_mu.Lock(); // expected-note {{mutex acquired here}}
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000291 }
292 sls_mu.Unlock(); // \
Caitlin Sadowski8bccabe2011-09-08 21:52:50 +0000293 // expected-warning{{unlocking 'sls_mu' that was not locked}}
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000294}
295
Richard Smithaacde712012-02-03 03:30:07 +0000296void sls_fun_bad_12() {
Richard Smith2e515622012-02-03 04:45:26 +0000297 sls_mu.Lock(); // expected-note {{mutex acquired here}}
Richard Smithaacde712012-02-03 03:30:07 +0000298 while (getBool()) {
299 sls_mu.Unlock();
300 if (getBool()) {
301 if (getBool()) {
Richard Smith2e515622012-02-03 04:45:26 +0000302 break; // expected-warning{{mutex 'sls_mu' is not locked on every path through here}}
Richard Smithaacde712012-02-03 03:30:07 +0000303 }
304 }
305 sls_mu.Lock();
306 }
307 sls_mu.Unlock();
308}
309
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000310//-----------------------------------------//
311// Handling lock expressions in attribute args
312// -------------------------------------------//
313
314Mutex aa_mu;
315
316class GlobalLocker {
317public:
318 void globalLock() __attribute__((exclusive_lock_function(aa_mu)));
319 void globalUnlock() __attribute__((unlock_function(aa_mu)));
320};
321
322GlobalLocker glock;
323
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000324void aa_fun_1() {
325 glock.globalLock();
326 glock.globalUnlock();
327}
328
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000329void aa_fun_bad_1() {
330 glock.globalUnlock(); // \
Caitlin Sadowski8bccabe2011-09-08 21:52:50 +0000331 // expected-warning{{unlocking 'aa_mu' that was not locked}}
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000332}
333
334void aa_fun_bad_2() {
335 glock.globalLock();
336 glock.globalLock(); // \
Caitlin Sadowski8bccabe2011-09-08 21:52:50 +0000337 // expected-warning{{locking 'aa_mu' that is already locked}}
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000338 glock.globalUnlock();
339}
340
341void aa_fun_bad_3() {
Richard Smith2e515622012-02-03 04:45:26 +0000342 glock.globalLock(); // expected-note{{mutex acquired here}}
343} // expected-warning{{mutex 'aa_mu' is still locked at the end of function}}
Caitlin Sadowskib4d0a962011-08-29 17:12:27 +0000344
Caitlin Sadowskib4d0a962011-08-29 17:12:27 +0000345//--------------------------------------------------//
346// Regression tests for unusual method names
347//--------------------------------------------------//
348
349Mutex wmu;
350
351// Test diagnostics for other method names.
352class WeirdMethods {
DeLesley Hutchins2f13bec2012-02-16 17:13:43 +0000353 // FIXME: can't currently check inside constructors and destructors.
Caitlin Sadowskib4d0a962011-08-29 17:12:27 +0000354 WeirdMethods() {
DeLesley Hutchins2f13bec2012-02-16 17:13:43 +0000355 wmu.Lock(); // EXPECTED-NOTE {{mutex acquired here}}
356 } // EXPECTED-WARNING {{mutex 'wmu' is still locked at the end of function}}
Caitlin Sadowskib4d0a962011-08-29 17:12:27 +0000357 ~WeirdMethods() {
DeLesley Hutchins2f13bec2012-02-16 17:13:43 +0000358 wmu.Lock(); // EXPECTED-NOTE {{mutex acquired here}}
359 } // EXPECTED-WARNING {{mutex 'wmu' is still locked at the end of function}}
Caitlin Sadowskib4d0a962011-08-29 17:12:27 +0000360 void operator++() {
Richard Smith2e515622012-02-03 04:45:26 +0000361 wmu.Lock(); // expected-note {{mutex acquired here}}
362 } // expected-warning {{mutex 'wmu' is still locked at the end of function}}
Caitlin Sadowskib4d0a962011-08-29 17:12:27 +0000363 operator int*() {
Richard Smith2e515622012-02-03 04:45:26 +0000364 wmu.Lock(); // expected-note {{mutex acquired here}}
Caitlin Sadowskib4d0a962011-08-29 17:12:27 +0000365 return 0;
Richard Smith2e515622012-02-03 04:45:26 +0000366 } // expected-warning {{mutex 'wmu' is still locked at the end of function}}
Caitlin Sadowskib4d0a962011-08-29 17:12:27 +0000367};
368
Caitlin Sadowski05b436e2011-08-29 22:27:51 +0000369//-----------------------------------------------//
370// Errors for guarded by or guarded var variables
371// ----------------------------------------------//
372
373int *pgb_gvar __attribute__((pt_guarded_var));
374int *pgb_var __attribute__((pt_guarded_by(sls_mu)));
375
376class PGBFoo {
377 public:
378 int x;
379 int *pgb_field __attribute__((guarded_by(sls_mu2)))
380 __attribute__((pt_guarded_by(sls_mu)));
381 void testFoo() {
382 pgb_field = &x; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000383 // expected-warning {{writing variable 'pgb_field' requires locking 'sls_mu2' exclusively}}
384 *pgb_field = x; // expected-warning {{reading variable 'pgb_field' requires locking 'sls_mu2'}} \
385 // expected-warning {{writing the value pointed to by 'pgb_field' requires locking 'sls_mu' exclusively}}
386 x = *pgb_field; // expected-warning {{reading variable 'pgb_field' requires locking 'sls_mu2'}} \
387 // expected-warning {{reading the value pointed to by 'pgb_field' requires locking 'sls_mu'}}
388 (*pgb_field)++; // expected-warning {{reading variable 'pgb_field' requires locking 'sls_mu2'}} \
389 // expected-warning {{writing the value pointed to by 'pgb_field' requires locking 'sls_mu' exclusively}}
Caitlin Sadowski05b436e2011-08-29 22:27:51 +0000390 }
391};
392
393class GBFoo {
394 public:
395 int gb_field __attribute__((guarded_by(sls_mu)));
396
397 void testFoo() {
398 gb_field = 0; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000399 // expected-warning {{writing variable 'gb_field' requires locking 'sls_mu' exclusively}}
Caitlin Sadowski05b436e2011-08-29 22:27:51 +0000400 }
Caitlin Sadowskiaf370612011-09-08 18:35:21 +0000401
402 void testNoAnal() __attribute__((no_thread_safety_analysis)) {
403 gb_field = 0;
404 }
Caitlin Sadowski05b436e2011-08-29 22:27:51 +0000405};
406
407GBFoo GlobalGBFoo __attribute__((guarded_by(sls_mu)));
408
409void gb_fun_0() {
410 sls_mu.Lock();
411 int x = *pgb_var;
412 sls_mu.Unlock();
413}
414
415void gb_fun_1() {
416 sls_mu.Lock();
417 *pgb_var = 2;
418 sls_mu.Unlock();
419}
420
421void gb_fun_2() {
422 int x;
423 pgb_var = &x;
424}
425
426void gb_fun_3() {
427 int *x = pgb_var;
428}
429
430void gb_bad_0() {
431 sls_guard_var = 1; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000432 // expected-warning{{writing variable 'sls_guard_var' requires locking any mutex exclusively}}
Caitlin Sadowski05b436e2011-08-29 22:27:51 +0000433}
434
435void gb_bad_1() {
436 int x = sls_guard_var; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000437 // expected-warning{{reading variable 'sls_guard_var' requires locking any mutex}}
Caitlin Sadowski05b436e2011-08-29 22:27:51 +0000438}
439
440void gb_bad_2() {
441 sls_guardby_var = 1; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000442 // expected-warning {{writing variable 'sls_guardby_var' requires locking 'sls_mu' exclusively}}
Caitlin Sadowski05b436e2011-08-29 22:27:51 +0000443}
444
445void gb_bad_3() {
446 int x = sls_guardby_var; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000447 // expected-warning {{reading variable 'sls_guardby_var' requires locking 'sls_mu'}}
Caitlin Sadowski05b436e2011-08-29 22:27:51 +0000448}
449
450void gb_bad_4() {
451 *pgb_gvar = 1; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000452 // expected-warning {{writing the value pointed to by 'pgb_gvar' requires locking any mutex exclusively}}
Caitlin Sadowski05b436e2011-08-29 22:27:51 +0000453}
454
455void gb_bad_5() {
456 int x = *pgb_gvar; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000457 // expected-warning {{reading the value pointed to by 'pgb_gvar' requires locking any mutex}}
Caitlin Sadowski05b436e2011-08-29 22:27:51 +0000458}
459
460void gb_bad_6() {
461 *pgb_var = 1; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000462 // expected-warning {{writing the value pointed to by 'pgb_var' requires locking 'sls_mu' exclusively}}
Caitlin Sadowski05b436e2011-08-29 22:27:51 +0000463}
464
465void gb_bad_7() {
466 int x = *pgb_var; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000467 // expected-warning {{reading the value pointed to by 'pgb_var' requires locking 'sls_mu'}}
Caitlin Sadowski05b436e2011-08-29 22:27:51 +0000468}
469
470void gb_bad_8() {
471 GBFoo G;
472 G.gb_field = 0; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000473 // expected-warning {{writing variable 'gb_field' requires locking 'sls_mu'}}
Caitlin Sadowski05b436e2011-08-29 22:27:51 +0000474}
475
476void gb_bad_9() {
477 sls_guard_var++; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000478 // expected-warning{{writing variable 'sls_guard_var' requires locking any mutex exclusively}}
Caitlin Sadowski05b436e2011-08-29 22:27:51 +0000479 sls_guard_var--; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000480 // expected-warning{{writing variable 'sls_guard_var' requires locking any mutex exclusively}}
Caitlin Sadowski05b436e2011-08-29 22:27:51 +0000481 ++sls_guard_var; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000482 // expected-warning{{writing variable 'sls_guard_var' requires locking any mutex exclusively}}
Caitlin Sadowskia49d1d82011-09-09 16:07:55 +0000483 --sls_guard_var;// \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000484 // expected-warning{{writing variable 'sls_guard_var' requires locking any mutex exclusively}}
Caitlin Sadowski05b436e2011-08-29 22:27:51 +0000485}
Caitlin Sadowskib4d0a962011-08-29 17:12:27 +0000486
Caitlin Sadowskieff98fc2011-09-08 17:42:22 +0000487//-----------------------------------------------//
488// Warnings on variables with late parsed attributes
489// ----------------------------------------------//
490
491class LateFoo {
492public:
493 int a __attribute__((guarded_by(mu)));
494 int b;
495
496 void foo() __attribute__((exclusive_locks_required(mu))) { }
497
498 void test() {
499 a = 0; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000500 // expected-warning{{writing variable 'a' requires locking 'mu' exclusively}}
Caitlin Sadowskieff98fc2011-09-08 17:42:22 +0000501 b = a; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000502 // expected-warning {{reading variable 'a' requires locking 'mu'}}
Caitlin Sadowskieff98fc2011-09-08 17:42:22 +0000503 c = 0; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000504 // expected-warning {{writing variable 'c' requires locking 'mu' exclusively}}
Caitlin Sadowskieff98fc2011-09-08 17:42:22 +0000505 }
506
507 int c __attribute__((guarded_by(mu)));
508
509 Mutex mu;
510};
511
Caitlin Sadowski99107eb2011-09-09 16:21:55 +0000512class LateBar {
513 public:
514 int a_ __attribute__((guarded_by(mu1_)));
515 int b_;
516 int *q __attribute__((pt_guarded_by(mu)));
517 Mutex mu1_;
518 Mutex mu;
519 LateFoo Foo;
520 LateFoo Foo2;
521 LateFoo *FooPointer;
522};
523
524LateBar b1, *b3;
525
526void late_0() {
527 LateFoo FooA;
528 LateFoo FooB;
529 FooA.mu.Lock();
530 FooA.a = 5;
531 FooA.mu.Unlock();
532}
533
534void late_1() {
535 LateBar BarA;
536 BarA.FooPointer->mu.Lock();
537 BarA.FooPointer->a = 2;
538 BarA.FooPointer->mu.Unlock();
539}
540
541void late_bad_0() {
542 LateFoo fooA;
543 LateFoo fooB;
544 fooA.mu.Lock();
545 fooB.a = 5; // \
DeLesley Hutchins3f0ec522012-09-10 19:58:23 +0000546 // expected-warning{{writing variable 'a' requires locking 'fooB.mu' exclusively}} \
547 // expected-note{{found near match 'fooA.mu'}}
Caitlin Sadowski99107eb2011-09-09 16:21:55 +0000548 fooA.mu.Unlock();
549}
550
551void late_bad_1() {
552 Mutex mu;
553 mu.Lock();
554 b1.mu1_.Lock();
555 int res = b1.a_ + b3->b_;
556 b3->b_ = *b1.q; // \
DeLesley Hutchinsa74b7152012-08-10 20:19:55 +0000557 // expected-warning{{reading the value pointed to by 'q' requires locking 'b1.mu'}}
Caitlin Sadowski99107eb2011-09-09 16:21:55 +0000558 b1.mu1_.Unlock();
559 b1.b_ = res;
560 mu.Unlock();
561}
562
563void late_bad_2() {
564 LateBar BarA;
565 BarA.FooPointer->mu.Lock();
566 BarA.Foo.a = 2; // \
DeLesley Hutchins3f0ec522012-09-10 19:58:23 +0000567 // expected-warning{{writing variable 'a' requires locking 'BarA.Foo.mu' exclusively}} \
568 // expected-note{{found near match 'BarA.FooPointer->mu'}}
Caitlin Sadowski99107eb2011-09-09 16:21:55 +0000569 BarA.FooPointer->mu.Unlock();
570}
571
572void late_bad_3() {
573 LateBar BarA;
574 BarA.Foo.mu.Lock();
575 BarA.FooPointer->a = 2; // \
DeLesley Hutchins3f0ec522012-09-10 19:58:23 +0000576 // expected-warning{{writing variable 'a' requires locking 'BarA.FooPointer->mu' exclusively}} \
577 // expected-note{{found near match 'BarA.Foo.mu'}}
Caitlin Sadowski99107eb2011-09-09 16:21:55 +0000578 BarA.Foo.mu.Unlock();
579}
580
581void late_bad_4() {
582 LateBar BarA;
583 BarA.Foo.mu.Lock();
584 BarA.Foo2.a = 2; // \
DeLesley Hutchins3f0ec522012-09-10 19:58:23 +0000585 // expected-warning{{writing variable 'a' requires locking 'BarA.Foo2.mu' exclusively}} \
586 // expected-note{{found near match 'BarA.Foo.mu'}}
Caitlin Sadowski99107eb2011-09-09 16:21:55 +0000587 BarA.Foo.mu.Unlock();
588}
589
Caitlin Sadowskia53257c2011-09-08 18:19:38 +0000590//-----------------------------------------------//
591// Extra warnings for shared vs. exclusive locks
592// ----------------------------------------------//
593
594void shared_fun_0() {
595 sls_mu.Lock();
596 do {
597 sls_mu.Unlock();
598 sls_mu.Lock();
599 } while (getBool());
600 sls_mu.Unlock();
601}
602
603void shared_fun_1() {
Caitlin Sadowski4e4bc752011-09-15 17:25:19 +0000604 sls_mu.ReaderLock(); // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000605 // expected-warning {{mutex 'sls_mu' is locked exclusively and shared in the same scope}}
Caitlin Sadowskia53257c2011-09-08 18:19:38 +0000606 do {
607 sls_mu.Unlock();
Caitlin Sadowski4e4bc752011-09-15 17:25:19 +0000608 sls_mu.Lock(); // \
609 // expected-note {{the other lock of mutex 'sls_mu' is here}}
Caitlin Sadowskia53257c2011-09-08 18:19:38 +0000610 } while (getBool());
611 sls_mu.Unlock();
612}
613
614void shared_fun_3() {
615 if (getBool())
616 sls_mu.Lock();
617 else
618 sls_mu.Lock();
619 *pgb_var = 1;
620 sls_mu.Unlock();
621}
622
623void shared_fun_4() {
624 if (getBool())
625 sls_mu.ReaderLock();
626 else
627 sls_mu.ReaderLock();
628 int x = sls_guardby_var;
629 sls_mu.Unlock();
630}
631
632void shared_fun_8() {
633 if (getBool())
634 sls_mu.Lock(); // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000635 // expected-warning {{mutex 'sls_mu' is locked exclusively and shared in the same scope}}
Caitlin Sadowskia53257c2011-09-08 18:19:38 +0000636 else
637 sls_mu.ReaderLock(); // \
Caitlin Sadowski8bccabe2011-09-08 21:52:50 +0000638 // expected-note {{the other lock of mutex 'sls_mu' is here}}
Caitlin Sadowskia53257c2011-09-08 18:19:38 +0000639 sls_mu.Unlock();
640}
641
642void shared_bad_0() {
Caitlin Sadowski4e4bc752011-09-15 17:25:19 +0000643 sls_mu.Lock(); // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000644 // expected-warning {{mutex 'sls_mu' is locked exclusively and shared in the same scope}}
Caitlin Sadowskia53257c2011-09-08 18:19:38 +0000645 do {
646 sls_mu.Unlock();
Caitlin Sadowski4e4bc752011-09-15 17:25:19 +0000647 sls_mu.ReaderLock(); // \
648 // expected-note {{the other lock of mutex 'sls_mu' is here}}
Caitlin Sadowskia53257c2011-09-08 18:19:38 +0000649 } while (getBool());
650 sls_mu.Unlock();
651}
652
653void shared_bad_1() {
654 if (getBool())
655 sls_mu.Lock(); // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000656 // expected-warning {{mutex 'sls_mu' is locked exclusively and shared in the same scope}}
Caitlin Sadowskia53257c2011-09-08 18:19:38 +0000657 else
658 sls_mu.ReaderLock(); // \
Caitlin Sadowski8bccabe2011-09-08 21:52:50 +0000659 // expected-note {{the other lock of mutex 'sls_mu' is here}}
Caitlin Sadowskia53257c2011-09-08 18:19:38 +0000660 *pgb_var = 1;
661 sls_mu.Unlock();
662}
663
664void shared_bad_2() {
665 if (getBool())
666 sls_mu.ReaderLock(); // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000667 // expected-warning {{mutex 'sls_mu' is locked exclusively and shared in the same scope}}
Caitlin Sadowskia53257c2011-09-08 18:19:38 +0000668 else
669 sls_mu.Lock(); // \
Caitlin Sadowski8bccabe2011-09-08 21:52:50 +0000670 // expected-note {{the other lock of mutex 'sls_mu' is here}}
Caitlin Sadowskia53257c2011-09-08 18:19:38 +0000671 *pgb_var = 1;
672 sls_mu.Unlock();
673}
Caitlin Sadowski978191e2011-09-08 18:27:31 +0000674
675// FIXME: Add support for functions (not only methods)
676class LRBar {
677 public:
678 void aa_elr_fun() __attribute__((exclusive_locks_required(aa_mu)));
679 void aa_elr_fun_s() __attribute__((shared_locks_required(aa_mu)));
680 void le_fun() __attribute__((locks_excluded(sls_mu)));
681};
682
683class LRFoo {
684 public:
685 void test() __attribute__((exclusive_locks_required(sls_mu)));
686 void testShared() __attribute__((shared_locks_required(sls_mu2)));
687};
688
689void elr_fun() __attribute__((exclusive_locks_required(sls_mu)));
690void elr_fun() {}
691
692LRFoo MyLRFoo;
693LRBar Bar;
694
695void es_fun_0() {
696 aa_mu.Lock();
697 Bar.aa_elr_fun();
698 aa_mu.Unlock();
699}
700
701void es_fun_1() {
702 aa_mu.Lock();
703 Bar.aa_elr_fun_s();
704 aa_mu.Unlock();
705}
706
707void es_fun_2() {
708 aa_mu.ReaderLock();
709 Bar.aa_elr_fun_s();
710 aa_mu.Unlock();
711}
712
713void es_fun_3() {
714 sls_mu.Lock();
715 MyLRFoo.test();
716 sls_mu.Unlock();
717}
718
719void es_fun_4() {
720 sls_mu2.Lock();
721 MyLRFoo.testShared();
722 sls_mu2.Unlock();
723}
724
725void es_fun_5() {
726 sls_mu2.ReaderLock();
727 MyLRFoo.testShared();
728 sls_mu2.Unlock();
729}
730
731void es_fun_6() {
732 Bar.le_fun();
733}
734
735void es_fun_7() {
736 sls_mu.Lock();
737 elr_fun();
738 sls_mu.Unlock();
739}
740
Caitlin Sadowskiaf370612011-09-08 18:35:21 +0000741void es_fun_8() __attribute__((no_thread_safety_analysis));
742
743void es_fun_8() {
744 Bar.aa_elr_fun_s();
745}
746
Caitlin Sadowskicb967512011-09-15 17:43:08 +0000747void es_fun_9() __attribute__((shared_locks_required(aa_mu)));
748void es_fun_9() {
749 Bar.aa_elr_fun_s();
750}
751
752void es_fun_10() __attribute__((exclusive_locks_required(aa_mu)));
753void es_fun_10() {
754 Bar.aa_elr_fun_s();
755}
756
Caitlin Sadowski978191e2011-09-08 18:27:31 +0000757void es_bad_0() {
758 Bar.aa_elr_fun(); // \
Caitlin Sadowski8bccabe2011-09-08 21:52:50 +0000759 // expected-warning {{calling function 'aa_elr_fun' requires exclusive lock on 'aa_mu'}}
Caitlin Sadowski978191e2011-09-08 18:27:31 +0000760}
761
762void es_bad_1() {
763 aa_mu.ReaderLock();
764 Bar.aa_elr_fun(); // \
Caitlin Sadowski8bccabe2011-09-08 21:52:50 +0000765 // expected-warning {{calling function 'aa_elr_fun' requires exclusive lock on 'aa_mu'}}
Caitlin Sadowski978191e2011-09-08 18:27:31 +0000766 aa_mu.Unlock();
767}
768
769void es_bad_2() {
770 Bar.aa_elr_fun_s(); // \
Caitlin Sadowski8bccabe2011-09-08 21:52:50 +0000771 // expected-warning {{calling function 'aa_elr_fun_s' requires shared lock on 'aa_mu'}}
Caitlin Sadowski978191e2011-09-08 18:27:31 +0000772}
773
774void es_bad_3() {
775 MyLRFoo.test(); // \
Caitlin Sadowski8bccabe2011-09-08 21:52:50 +0000776 // expected-warning {{calling function 'test' requires exclusive lock on 'sls_mu'}}
Caitlin Sadowski978191e2011-09-08 18:27:31 +0000777}
778
779void es_bad_4() {
780 MyLRFoo.testShared(); // \
Caitlin Sadowski8bccabe2011-09-08 21:52:50 +0000781 // expected-warning {{calling function 'testShared' requires shared lock on 'sls_mu2'}}
Caitlin Sadowski978191e2011-09-08 18:27:31 +0000782}
783
784void es_bad_5() {
785 sls_mu.ReaderLock();
786 MyLRFoo.test(); // \
Caitlin Sadowski8bccabe2011-09-08 21:52:50 +0000787 // expected-warning {{calling function 'test' requires exclusive lock on 'sls_mu'}}
Caitlin Sadowski978191e2011-09-08 18:27:31 +0000788 sls_mu.Unlock();
789}
790
791void es_bad_6() {
792 sls_mu.Lock();
793 Bar.le_fun(); // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000794 // expected-warning {{cannot call function 'le_fun' while mutex 'sls_mu' is locked}}
Caitlin Sadowski978191e2011-09-08 18:27:31 +0000795 sls_mu.Unlock();
796}
797
798void es_bad_7() {
799 sls_mu.ReaderLock();
800 Bar.le_fun(); // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000801 // expected-warning {{cannot call function 'le_fun' while mutex 'sls_mu' is locked}}
Caitlin Sadowski978191e2011-09-08 18:27:31 +0000802 sls_mu.Unlock();
803}
Caitlin Sadowski194418f2011-09-14 20:00:24 +0000804
DeLesley Hutchins81216392011-10-17 21:38:02 +0000805
Caitlin Sadowski194418f2011-09-14 20:00:24 +0000806//-----------------------------------------------//
807// Unparseable lock expressions
808// ----------------------------------------------//
809
DeLesley Hutchins0d95dfc2012-03-02 23:36:05 +0000810// FIXME -- derive new tests for unhandled expressions
Caitlin Sadowski194418f2011-09-14 20:00:24 +0000811
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +0000812
813//----------------------------------------------------------------------------//
814// The following test cases are ported from the gcc thread safety implementation
815// They are each wrapped inside a namespace with the test number of the gcc test
816//
817// FIXME: add all the gcc tests, once this analysis passes them.
818//----------------------------------------------------------------------------//
819
820//-----------------------------------------//
821// Good testcases (no errors)
822//-----------------------------------------//
823
824namespace thread_annot_lock_20 {
825class Bar {
826 public:
827 static int func1() EXCLUSIVE_LOCKS_REQUIRED(mu1_);
828 static int b_ GUARDED_BY(mu1_);
829 static Mutex mu1_;
830 static int a_ GUARDED_BY(mu1_);
831};
832
833Bar b1;
834
835int Bar::func1()
836{
837 int res = 5;
838
839 if (a_ == 4)
840 res = b_;
841 return res;
842}
843} // end namespace thread_annot_lock_20
844
845namespace thread_annot_lock_22 {
846// Test various usage of GUARDED_BY and PT_GUARDED_BY annotations, especially
847// uses in class definitions.
848Mutex mu;
849
850class Bar {
851 public:
852 int a_ GUARDED_BY(mu1_);
853 int b_;
854 int *q PT_GUARDED_BY(mu);
855 Mutex mu1_ ACQUIRED_AFTER(mu);
856};
857
858Bar b1, *b3;
859int *p GUARDED_BY(mu) PT_GUARDED_BY(mu);
860int res GUARDED_BY(mu) = 5;
861
862int func(int i)
863{
864 int x;
865 mu.Lock();
866 b1.mu1_.Lock();
867 res = b1.a_ + b3->b_;
868 *p = i;
869 b1.a_ = res + b3->b_;
870 b3->b_ = *b1.q;
871 b1.mu1_.Unlock();
872 b1.b_ = res;
873 x = res;
874 mu.Unlock();
875 return x;
876}
877} // end namespace thread_annot_lock_22
878
879namespace thread_annot_lock_27_modified {
880// test lock annotations applied to function definitions
881// Modified: applied annotations only to function declarations
882Mutex mu1;
883Mutex mu2 ACQUIRED_AFTER(mu1);
884
885class Foo {
886 public:
887 int method1(int i) SHARED_LOCKS_REQUIRED(mu2) EXCLUSIVE_LOCKS_REQUIRED(mu1);
888};
889
890int Foo::method1(int i) {
891 return i;
892}
893
894
895int foo(int i) EXCLUSIVE_LOCKS_REQUIRED(mu2) SHARED_LOCKS_REQUIRED(mu1);
896int foo(int i) {
897 return i;
898}
899
900static int bar(int i) EXCLUSIVE_LOCKS_REQUIRED(mu1);
901static int bar(int i) {
902 return i;
903}
904
905void main() {
906 Foo a;
907
908 mu1.Lock();
909 mu2.Lock();
910 a.method1(1);
911 foo(2);
912 mu2.Unlock();
913 bar(3);
914 mu1.Unlock();
915}
916} // end namespace thread_annot_lock_27_modified
917
918
919namespace thread_annot_lock_38 {
920// Test the case where a template member function is annotated with lock
921// attributes in a non-template class.
922class Foo {
923 public:
924 void func1(int y) LOCKS_EXCLUDED(mu_);
925 template <typename T> void func2(T x) LOCKS_EXCLUDED(mu_);
926 private:
927 Mutex mu_;
928};
929
930Foo *foo;
931
932void main()
933{
934 foo->func1(5);
935 foo->func2(5);
936}
937} // end namespace thread_annot_lock_38
938
939namespace thread_annot_lock_43 {
940// Tests lock canonicalization
941class Foo {
942 public:
943 Mutex *mu_;
944};
945
946class FooBar {
947 public:
948 Foo *foo_;
949 int GetA() EXCLUSIVE_LOCKS_REQUIRED(foo_->mu_) { return a_; }
950 int a_ GUARDED_BY(foo_->mu_);
951};
952
953FooBar *fb;
954
955void main()
956{
957 int x;
958 fb->foo_->mu_->Lock();
959 x = fb->GetA();
960 fb->foo_->mu_->Unlock();
961}
962} // end namespace thread_annot_lock_43
963
964namespace thread_annot_lock_49 {
965// Test the support for use of lock expression in the annotations
966class Foo {
967 public:
968 Mutex foo_mu_;
969};
970
971class Bar {
972 private:
973 Foo *foo;
974 Mutex bar_mu_ ACQUIRED_AFTER(foo->foo_mu_);
975
976 public:
977 void Test1() {
978 foo->foo_mu_.Lock();
979 bar_mu_.Lock();
980 bar_mu_.Unlock();
981 foo->foo_mu_.Unlock();
982 }
983};
984
985void main() {
986 Bar bar;
987 bar.Test1();
988}
989} // end namespace thread_annot_lock_49
990
991namespace thread_annot_lock_61_modified {
992 // Modified to fix the compiler errors
993 // Test the fix for a bug introduced by the support of pass-by-reference
994 // paramters.
995 struct Foo { Foo &operator<< (bool) {return *this;} };
996 Foo &getFoo();
997 struct Bar { Foo &func () {return getFoo();} };
998 struct Bas { void operator& (Foo &) {} };
999 void mumble()
1000 {
1001 Bas() & Bar().func() << "" << "";
1002 Bas() & Bar().func() << "";
1003 }
1004} // end namespace thread_annot_lock_61_modified
1005
1006
1007namespace thread_annot_lock_65 {
1008// Test the fix for a bug in the support of allowing reader locks for
1009// non-const, non-modifying overload functions. (We didn't handle the builtin
1010// properly.)
1011enum MyFlags {
1012 Zero,
1013 One,
1014 Two,
1015 Three,
1016 Four,
1017 Five,
1018 Six,
1019 Seven,
1020 Eight,
1021 Nine
1022};
1023
1024inline MyFlags
1025operator|(MyFlags a, MyFlags b)
1026{
1027 return MyFlags(static_cast<int>(a) | static_cast<int>(b));
1028}
1029
1030inline MyFlags&
1031operator|=(MyFlags& a, MyFlags b)
1032{
1033 return a = a | b;
1034}
1035} // end namespace thread_annot_lock_65
1036
1037namespace thread_annot_lock_66_modified {
1038// Modified: Moved annotation to function defn
1039// Test annotations on out-of-line definitions of member functions where the
1040// annotations refer to locks that are also data members in the class.
1041Mutex mu;
1042
1043class Foo {
1044 public:
1045 int method1(int i) SHARED_LOCKS_REQUIRED(mu1, mu, mu2);
1046 int data GUARDED_BY(mu1);
1047 Mutex *mu1;
1048 Mutex *mu2;
1049};
1050
1051int Foo::method1(int i)
1052{
1053 return data + i;
1054}
1055
1056void main()
1057{
1058 Foo a;
1059
1060 a.mu2->Lock();
1061 a.mu1->Lock();
1062 mu.Lock();
1063 a.method1(1);
1064 mu.Unlock();
1065 a.mu1->Unlock();
1066 a.mu2->Unlock();
1067}
1068} // end namespace thread_annot_lock_66_modified
1069
1070namespace thread_annot_lock_68_modified {
1071// Test a fix to a bug in the delayed name binding with nested template
1072// instantiation. We use a stack to make sure a name is not resolved to an
1073// inner context.
1074template <typename T>
1075class Bar {
1076 Mutex mu_;
1077};
1078
1079template <typename T>
1080class Foo {
1081 public:
1082 void func(T x) {
1083 mu_.Lock();
DeLesley Hutchins23323e02012-01-20 22:50:54 +00001084 count_ = x;
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001085 mu_.Unlock();
1086 }
1087
1088 private:
DeLesley Hutchins23323e02012-01-20 22:50:54 +00001089 T count_ GUARDED_BY(mu_);
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001090 Bar<T> bar_;
1091 Mutex mu_;
1092};
1093
1094void main()
1095{
1096 Foo<int> *foo;
1097 foo->func(5);
1098}
1099} // end namespace thread_annot_lock_68_modified
1100
1101namespace thread_annot_lock_30_modified {
1102// Test delay parsing of lock attribute arguments with nested classes.
1103// Modified: trylocks replaced with exclusive_lock_fun
1104int a = 0;
1105
1106class Bar {
1107 struct Foo;
1108
1109 public:
1110 void MyLock() EXCLUSIVE_LOCK_FUNCTION(mu);
1111
1112 int func() {
1113 MyLock();
1114// if (foo == 0) {
1115// return 0;
1116// }
1117 a = 5;
1118 mu.Unlock();
1119 return 1;
1120 }
1121
1122 class FooBar {
1123 int x;
1124 int y;
1125 };
1126
1127 private:
1128 Mutex mu;
1129};
1130
1131Bar *bar;
1132
1133void main()
1134{
1135 bar->func();
1136}
1137} // end namespace thread_annot_lock_30_modified
1138
1139namespace thread_annot_lock_47 {
1140// Test the support for annotations on virtual functions.
1141// This is a good test case. (i.e. There should be no warning emitted by the
1142// compiler.)
1143class Base {
1144 public:
1145 virtual void func1() EXCLUSIVE_LOCKS_REQUIRED(mu_);
1146 virtual void func2() LOCKS_EXCLUDED(mu_);
1147 Mutex mu_;
1148};
1149
1150class Child : public Base {
1151 public:
1152 virtual void func1() EXCLUSIVE_LOCKS_REQUIRED(mu_);
1153 virtual void func2() LOCKS_EXCLUDED(mu_);
1154};
1155
1156void main() {
1157 Child *c;
1158 Base *b = c;
1159
1160 b->mu_.Lock();
1161 b->func1();
1162 b->mu_.Unlock();
1163 b->func2();
1164
1165 c->mu_.Lock();
1166 c->func1();
1167 c->mu_.Unlock();
1168 c->func2();
1169}
1170} // end namespace thread_annot_lock_47
1171
1172//-----------------------------------------//
1173// Tests which produce errors
1174//-----------------------------------------//
1175
1176namespace thread_annot_lock_13 {
1177Mutex mu1;
1178Mutex mu2;
1179
1180int g GUARDED_BY(mu1);
1181int w GUARDED_BY(mu2);
1182
1183class Foo {
1184 public:
1185 void bar() LOCKS_EXCLUDED(mu_, mu1);
1186 int foo() SHARED_LOCKS_REQUIRED(mu_) EXCLUSIVE_LOCKS_REQUIRED(mu2);
1187
1188 private:
1189 int a_ GUARDED_BY(mu_);
1190 public:
1191 Mutex mu_ ACQUIRED_AFTER(mu1);
1192};
1193
1194int Foo::foo()
1195{
1196 int res;
David Blaikiee31b8fb2012-04-05 00:16:44 +00001197 w = 5;
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001198 res = a_ + 5;
1199 return res;
1200}
1201
1202void Foo::bar()
1203{
1204 int x;
1205 mu_.Lock();
1206 x = foo(); // expected-warning {{calling function 'foo' requires exclusive lock on 'mu2'}}
1207 a_ = x + 1;
1208 mu_.Unlock();
1209 if (x > 5) {
1210 mu1.Lock();
David Blaikiee31b8fb2012-04-05 00:16:44 +00001211 g = 2;
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001212 mu1.Unlock();
1213 }
1214}
1215
1216void main()
1217{
1218 Foo f1, *f2;
1219 f1.mu_.Lock();
DeLesley Hutchinsa74b7152012-08-10 20:19:55 +00001220 f1.bar(); // expected-warning {{cannot call function 'bar' while mutex 'f1.mu_' is locked}}
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001221 mu2.Lock();
1222 f1.foo();
1223 mu2.Unlock();
1224 f1.mu_.Unlock();
1225 f2->mu_.Lock();
DeLesley Hutchinsa74b7152012-08-10 20:19:55 +00001226 f2->bar(); // expected-warning {{cannot call function 'bar' while mutex 'f2->mu_' is locked}}
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001227 f2->mu_.Unlock();
1228 mu2.Lock();
David Blaikiee31b8fb2012-04-05 00:16:44 +00001229 w = 2;
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001230 mu2.Unlock();
1231}
1232} // end namespace thread_annot_lock_13
1233
1234namespace thread_annot_lock_18_modified {
1235// Modified: Trylocks removed
1236// Test the ability to distnguish between the same lock field of
1237// different objects of a class.
1238 class Bar {
1239 public:
1240 bool MyLock() EXCLUSIVE_LOCK_FUNCTION(mu1_);
1241 void MyUnlock() UNLOCK_FUNCTION(mu1_);
1242 int a_ GUARDED_BY(mu1_);
1243
1244 private:
1245 Mutex mu1_;
1246};
1247
1248Bar *b1, *b2;
1249
1250void func()
1251{
1252 b1->MyLock();
1253 b1->a_ = 5;
DeLesley Hutchins3f0ec522012-09-10 19:58:23 +00001254 b2->a_ = 3; // \
1255 // expected-warning {{writing variable 'a_' requires locking 'b2->mu1_' exclusively}} \
1256 // expected-note {{found near match 'b1->mu1_'}}
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001257 b2->MyLock();
1258 b2->MyUnlock();
1259 b1->MyUnlock();
1260}
1261} // end namespace thread_annot_lock_18_modified
1262
1263namespace thread_annot_lock_21 {
1264// Test various usage of GUARDED_BY and PT_GUARDED_BY annotations, especially
1265// uses in class definitions.
1266Mutex mu;
1267
1268class Bar {
1269 public:
1270 int a_ GUARDED_BY(mu1_);
1271 int b_;
1272 int *q PT_GUARDED_BY(mu);
1273 Mutex mu1_ ACQUIRED_AFTER(mu);
1274};
1275
1276Bar b1, *b3;
1277int *p GUARDED_BY(mu) PT_GUARDED_BY(mu);
1278
1279int res GUARDED_BY(mu) = 5;
1280
1281int func(int i)
1282{
1283 int x;
1284 b3->mu1_.Lock();
DeLesley Hutchinsa74b7152012-08-10 20:19:55 +00001285 res = b1.a_ + b3->b_; // expected-warning {{reading variable 'a_' requires locking 'b1.mu1_'}} \
DeLesley Hutchins3f0ec522012-09-10 19:58:23 +00001286 // expected-warning {{writing variable 'res' requires locking 'mu' exclusively}} \
1287 // expected-note {{found near match 'b3->mu1_'}}
Caitlin Sadowski74558b42011-09-15 18:13:32 +00001288 *p = i; // expected-warning {{reading variable 'p' requires locking 'mu'}} \
1289 // expected-warning {{writing the value pointed to by 'p' requires locking 'mu' exclusively}}
1290 b1.a_ = res + b3->b_; // expected-warning {{reading variable 'res' requires locking 'mu'}} \
DeLesley Hutchins3f0ec522012-09-10 19:58:23 +00001291 // expected-warning {{writing variable 'a_' requires locking 'b1.mu1_' exclusively}} \
1292 // expected-note {{found near match 'b3->mu1_'}}
Caitlin Sadowski74558b42011-09-15 18:13:32 +00001293 b3->b_ = *b1.q; // expected-warning {{reading the value pointed to by 'q' requires locking 'mu'}}
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001294 b3->mu1_.Unlock();
Caitlin Sadowski74558b42011-09-15 18:13:32 +00001295 b1.b_ = res; // expected-warning {{reading variable 'res' requires locking 'mu'}}
1296 x = res; // expected-warning {{reading variable 'res' requires locking 'mu'}}
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001297 return x;
1298}
1299} // end namespace thread_annot_lock_21
1300
1301namespace thread_annot_lock_35_modified {
1302// Test the analyzer's ability to distinguish the lock field of different
1303// objects.
1304class Foo {
1305 private:
1306 Mutex lock_;
1307 int a_ GUARDED_BY(lock_);
1308
1309 public:
1310 void Func(Foo* child) LOCKS_EXCLUDED(lock_) {
1311 Foo *new_foo = new Foo;
1312
1313 lock_.Lock();
1314
1315 child->Func(new_foo); // There shouldn't be any warning here as the
1316 // acquired lock is not in child.
DeLesley Hutchins3f0ec522012-09-10 19:58:23 +00001317 child->bar(7); // \
1318 // expected-warning {{calling function 'bar' requires exclusive lock on 'child->lock_'}} \
1319 // expected-note {{found near match 'lock_'}}
1320 child->a_ = 5; // \
1321 // expected-warning {{writing variable 'a_' requires locking 'child->lock_' exclusively}} \
1322 // expected-note {{found near match 'lock_'}}
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001323 lock_.Unlock();
1324 }
1325
1326 void bar(int y) EXCLUSIVE_LOCKS_REQUIRED(lock_) {
1327 a_ = y;
1328 }
1329};
1330
1331Foo *x;
1332
1333void main() {
1334 Foo *child = new Foo;
1335 x->Func(child);
1336}
1337} // end namespace thread_annot_lock_35_modified
1338
1339namespace thread_annot_lock_36_modified {
1340// Modified to move the annotations to function defns.
1341// Test the analyzer's ability to distinguish the lock field of different
1342// objects
1343class Foo {
1344 private:
1345 Mutex lock_;
1346 int a_ GUARDED_BY(lock_);
1347
1348 public:
1349 void Func(Foo* child) LOCKS_EXCLUDED(lock_);
1350 void bar(int y) EXCLUSIVE_LOCKS_REQUIRED(lock_);
1351};
1352
1353void Foo::Func(Foo* child) {
1354 Foo *new_foo = new Foo;
1355
1356 lock_.Lock();
1357
1358 child->lock_.Lock();
DeLesley Hutchinsa74b7152012-08-10 20:19:55 +00001359 child->Func(new_foo); // expected-warning {{cannot call function 'Func' while mutex 'child->lock_' is locked}}
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001360 child->bar(7);
1361 child->a_ = 5;
1362 child->lock_.Unlock();
1363
1364 lock_.Unlock();
1365}
1366
1367void Foo::bar(int y) {
1368 a_ = y;
1369}
1370
1371
1372Foo *x;
1373
1374void main() {
1375 Foo *child = new Foo;
1376 x->Func(child);
1377}
1378} // end namespace thread_annot_lock_36_modified
1379
1380
1381namespace thread_annot_lock_42 {
1382// Test support of multiple lock attributes of the same kind on a decl.
1383class Foo {
1384 private:
1385 Mutex mu1, mu2, mu3;
1386 int x GUARDED_BY(mu1) GUARDED_BY(mu2);
1387 int y GUARDED_BY(mu2);
1388
1389 void f2() LOCKS_EXCLUDED(mu1) LOCKS_EXCLUDED(mu2) LOCKS_EXCLUDED(mu3) {
1390 mu2.Lock();
1391 y = 2;
1392 mu2.Unlock();
1393 }
1394
1395 public:
1396 void f1() EXCLUSIVE_LOCKS_REQUIRED(mu2) EXCLUSIVE_LOCKS_REQUIRED(mu1) {
1397 x = 5;
Caitlin Sadowski74558b42011-09-15 18:13:32 +00001398 f2(); // expected-warning {{cannot call function 'f2' while mutex 'mu1' is locked}} \
1399 // expected-warning {{cannot call function 'f2' while mutex 'mu2' is locked}}
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001400 }
1401};
1402
1403Foo *foo;
1404
1405void func()
1406{
DeLesley Hutchinsa74b7152012-08-10 20:19:55 +00001407 foo->f1(); // expected-warning {{calling function 'f1' requires exclusive lock on 'foo->mu2'}} \
1408 // expected-warning {{calling function 'f1' requires exclusive lock on 'foo->mu1'}}
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001409}
1410} // end namespace thread_annot_lock_42
1411
1412namespace thread_annot_lock_46 {
1413// Test the support for annotations on virtual functions.
1414class Base {
1415 public:
1416 virtual void func1() EXCLUSIVE_LOCKS_REQUIRED(mu_);
1417 virtual void func2() LOCKS_EXCLUDED(mu_);
1418 Mutex mu_;
1419};
1420
1421class Child : public Base {
1422 public:
1423 virtual void func1() EXCLUSIVE_LOCKS_REQUIRED(mu_);
1424 virtual void func2() LOCKS_EXCLUDED(mu_);
1425};
1426
1427void main() {
1428 Child *c;
1429 Base *b = c;
1430
DeLesley Hutchinsa74b7152012-08-10 20:19:55 +00001431 b->func1(); // expected-warning {{calling function 'func1' requires exclusive lock on 'b->mu_'}}
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001432 b->mu_.Lock();
DeLesley Hutchinsa74b7152012-08-10 20:19:55 +00001433 b->func2(); // expected-warning {{cannot call function 'func2' while mutex 'b->mu_' is locked}}
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001434 b->mu_.Unlock();
1435
DeLesley Hutchinsa74b7152012-08-10 20:19:55 +00001436 c->func1(); // expected-warning {{calling function 'func1' requires exclusive lock on 'c->mu_'}}
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001437 c->mu_.Lock();
DeLesley Hutchinsa74b7152012-08-10 20:19:55 +00001438 c->func2(); // expected-warning {{cannot call function 'func2' while mutex 'c->mu_' is locked}}
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001439 c->mu_.Unlock();
1440}
1441} // end namespace thread_annot_lock_46
1442
1443namespace thread_annot_lock_67_modified {
1444// Modified: attributes on definitions moved to declarations
1445// Test annotations on out-of-line definitions of member functions where the
1446// annotations refer to locks that are also data members in the class.
1447Mutex mu;
1448Mutex mu3;
1449
1450class Foo {
1451 public:
1452 int method1(int i) SHARED_LOCKS_REQUIRED(mu1, mu, mu2, mu3);
1453 int data GUARDED_BY(mu1);
1454 Mutex *mu1;
1455 Mutex *mu2;
1456};
1457
1458int Foo::method1(int i) {
1459 return data + i;
1460}
1461
1462void main()
1463{
1464 Foo a;
DeLesley Hutchinsa74b7152012-08-10 20:19:55 +00001465 a.method1(1); // expected-warning {{calling function 'method1' requires shared lock on 'a.mu1'}} \
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001466 // expected-warning {{calling function 'method1' requires shared lock on 'mu'}} \
DeLesley Hutchinsa74b7152012-08-10 20:19:55 +00001467 // expected-warning {{calling function 'method1' requires shared lock on 'a.mu2'}} \
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001468 // expected-warning {{calling function 'method1' requires shared lock on 'mu3'}}
1469}
1470} // end namespace thread_annot_lock_67_modified
1471
1472
DeLesley Hutchins81216392011-10-17 21:38:02 +00001473namespace substitution_test {
1474 class MyData {
1475 public:
1476 Mutex mu;
1477
1478 void lockData() __attribute__((exclusive_lock_function(mu))) { }
1479 void unlockData() __attribute__((unlock_function(mu))) { }
1480
1481 void doSomething() __attribute__((exclusive_locks_required(mu))) { }
1482 };
1483
1484
1485 class DataLocker {
1486 public:
1487 void lockData (MyData *d) __attribute__((exclusive_lock_function(d->mu))) { }
1488 void unlockData(MyData *d) __attribute__((unlock_function(d->mu))) { }
1489 };
1490
1491
1492 class Foo {
1493 public:
1494 void foo(MyData* d) __attribute__((exclusive_locks_required(d->mu))) { }
1495
1496 void bar1(MyData* d) {
1497 d->lockData();
1498 foo(d);
1499 d->unlockData();
1500 }
1501
1502 void bar2(MyData* d) {
1503 DataLocker dlr;
1504 dlr.lockData(d);
1505 foo(d);
1506 dlr.unlockData(d);
1507 }
1508
1509 void bar3(MyData* d1, MyData* d2) {
1510 DataLocker dlr;
Richard Smith2e515622012-02-03 04:45:26 +00001511 dlr.lockData(d1); // expected-note {{mutex acquired here}}
DeLesley Hutchins81216392011-10-17 21:38:02 +00001512 dlr.unlockData(d2); // \
DeLesley Hutchinsa74b7152012-08-10 20:19:55 +00001513 // expected-warning {{unlocking 'd2->mu' that was not locked}}
1514 } // expected-warning {{mutex 'd1->mu' is still locked at the end of function}}
DeLesley Hutchins81216392011-10-17 21:38:02 +00001515
1516 void bar4(MyData* d1, MyData* d2) {
1517 DataLocker dlr;
1518 dlr.lockData(d1);
1519 foo(d2); // \
DeLesley Hutchins3f0ec522012-09-10 19:58:23 +00001520 // expected-warning {{calling function 'foo' requires exclusive lock on 'd2->mu'}} \
1521 // expected-note {{found near match 'd1->mu'}}
DeLesley Hutchins81216392011-10-17 21:38:02 +00001522 dlr.unlockData(d1);
1523 }
1524 };
1525} // end namespace substituation_test
1526
DeLesley Hutchinse0eaa852011-10-21 18:06:53 +00001527
DeLesley Hutchinsf1ac6372011-10-21 18:10:14 +00001528
DeLesley Hutchinse0eaa852011-10-21 18:06:53 +00001529namespace constructor_destructor_tests {
1530 Mutex fooMu;
1531 int myVar GUARDED_BY(fooMu);
1532
1533 class Foo {
1534 public:
1535 Foo() __attribute__((exclusive_lock_function(fooMu))) { }
1536 ~Foo() __attribute__((unlock_function(fooMu))) { }
1537 };
1538
1539 void fooTest() {
DeLesley Hutchins6db51f72011-10-21 20:51:27 +00001540 Foo foo;
DeLesley Hutchinse0eaa852011-10-21 18:06:53 +00001541 myVar = 0;
1542 }
1543}
1544
DeLesley Hutchinsf1ac6372011-10-21 18:10:14 +00001545
1546namespace invalid_lock_expression_test {
1547
1548class LOCKABLE MyLockable {
1549public:
1550 MyLockable() __attribute__((exclusive_lock_function)) { }
DeLesley Hutchins6db51f72011-10-21 20:51:27 +00001551 ~MyLockable() { }
DeLesley Hutchinsf1ac6372011-10-21 18:10:14 +00001552};
1553
1554// create an empty lock expression
1555void foo() {
1556 MyLockable lock; // \
1557 // expected-warning {{cannot resolve lock expression}}
1558}
1559
1560} // end namespace invalid_lock_expression_test
1561
Richard Smith97f9fe02011-10-25 00:41:24 +00001562namespace template_member_test {
DeLesley Hutchinsf1ac6372011-10-21 18:10:14 +00001563
Richard Smith97f9fe02011-10-25 00:41:24 +00001564 struct S { int n; };
1565 struct T {
1566 Mutex m;
1567 S *s GUARDED_BY(this->m);
1568 };
Richard Smitha01c7112011-10-25 06:33:21 +00001569 Mutex m;
1570 struct U {
1571 union {
1572 int n;
1573 };
1574 } *u GUARDED_BY(m);
Richard Smith97f9fe02011-10-25 00:41:24 +00001575
1576 template<typename U>
1577 struct IndirectLock {
1578 int DoNaughtyThings(T *t) {
Richard Smitha01c7112011-10-25 06:33:21 +00001579 u->n = 0; // expected-warning {{reading variable 'u' requires locking 'm'}}
DeLesley Hutchinsa74b7152012-08-10 20:19:55 +00001580 return t->s->n; // expected-warning {{reading variable 's' requires locking 't->m'}}
Richard Smith97f9fe02011-10-25 00:41:24 +00001581 }
1582 };
1583
Richard Smithf11e9232011-10-25 01:05:41 +00001584 template struct IndirectLock<int>; // expected-note {{here}}
Richard Smith97f9fe02011-10-25 00:41:24 +00001585
Richard Smith601d2ee2011-10-26 06:15:36 +00001586 struct V {
1587 void f(int);
1588 void f(double);
1589
1590 Mutex m;
1591 V *p GUARDED_BY(this->m);
1592 };
1593 template<typename U> struct W {
1594 V v;
1595 void f(U u) {
DeLesley Hutchinsa74b7152012-08-10 20:19:55 +00001596 v.p->f(u); // expected-warning {{reading variable 'p' requires locking 'v.m'}}
Richard Smith601d2ee2011-10-26 06:15:36 +00001597 }
1598 };
1599 template struct W<int>; // expected-note {{here}}
1600
Richard Smith97f9fe02011-10-25 00:41:24 +00001601}
DeLesley Hutchins1fa3c062011-12-08 20:23:06 +00001602
1603namespace test_scoped_lockable {
1604
1605struct TestScopedLockable {
1606 Mutex mu1;
1607 Mutex mu2;
1608 int a __attribute__((guarded_by(mu1)));
1609 int b __attribute__((guarded_by(mu2)));
1610
1611 bool getBool();
1612
1613 void foo1() {
1614 MutexLock mulock(&mu1);
1615 a = 5;
1616 }
1617
1618 void foo2() {
1619 ReaderMutexLock mulock1(&mu1);
1620 if (getBool()) {
1621 MutexLock mulock2a(&mu2);
1622 b = a + 1;
1623 }
1624 else {
1625 MutexLock mulock2b(&mu2);
1626 b = a + 2;
1627 }
1628 }
1629
1630 void foo3() {
1631 MutexLock mulock_a(&mu1);
1632 MutexLock mulock_b(&mu1); // \
1633 // expected-warning {{locking 'mu1' that is already locked}}
DeLesley Hutchinsc99a5d82012-06-28 22:42:48 +00001634 }
DeLesley Hutchins1fa3c062011-12-08 20:23:06 +00001635
1636 void foo4() {
1637 MutexLock mulock1(&mu1), mulock2(&mu2);
1638 a = b+1;
1639 b = a+1;
1640 }
1641};
1642
1643} // end namespace test_scoped_lockable
1644
1645
DeLesley Hutchinsdf497822011-12-29 00:56:48 +00001646namespace FunctionAttrTest {
1647
1648class Foo {
1649public:
1650 Mutex mu_;
1651 int a GUARDED_BY(mu_);
1652};
1653
1654Foo fooObj;
1655
1656void foo() EXCLUSIVE_LOCKS_REQUIRED(fooObj.mu_);
1657
1658void bar() {
DeLesley Hutchinsa74b7152012-08-10 20:19:55 +00001659 foo(); // expected-warning {{calling function 'foo' requires exclusive lock on 'fooObj.mu_'}}
DeLesley Hutchinsdf497822011-12-29 00:56:48 +00001660 fooObj.mu_.Lock();
1661 foo();
1662 fooObj.mu_.Unlock();
1663}
1664
1665}; // end namespace FunctionAttrTest
1666
1667
DeLesley Hutchins60ff1982012-09-20 23:14:43 +00001668namespace TryLockTest {
1669
DeLesley Hutchinsb4fa4182012-01-06 19:16:50 +00001670struct TestTryLock {
1671 Mutex mu;
1672 int a GUARDED_BY(mu);
1673 bool cond;
1674
1675 void foo1() {
1676 if (mu.TryLock()) {
1677 a = 1;
1678 mu.Unlock();
1679 }
1680 }
1681
1682 void foo2() {
1683 if (!mu.TryLock()) return;
1684 a = 2;
1685 mu.Unlock();
1686 }
1687
1688 void foo3() {
1689 bool b = mu.TryLock();
1690 if (b) {
1691 a = 3;
1692 mu.Unlock();
1693 }
1694 }
1695
1696 void foo4() {
1697 bool b = mu.TryLock();
1698 if (!b) return;
1699 a = 4;
1700 mu.Unlock();
1701 }
1702
1703 void foo5() {
1704 while (mu.TryLock()) {
1705 a = a + 1;
1706 mu.Unlock();
1707 }
1708 }
1709
1710 void foo6() {
1711 bool b = mu.TryLock();
1712 b = !b;
1713 if (b) return;
1714 a = 6;
1715 mu.Unlock();
1716 }
1717
1718 void foo7() {
1719 bool b1 = mu.TryLock();
1720 bool b2 = !b1;
1721 bool b3 = !b2;
1722 if (b3) {
1723 a = 7;
1724 mu.Unlock();
1725 }
1726 }
1727
1728 // Test use-def chains: join points
1729 void foo8() {
1730 bool b = mu.TryLock();
1731 bool b2 = b;
1732 if (cond)
1733 b = true;
Sylvestre Ledru43e3dee2012-07-31 06:56:50 +00001734 if (b) { // b should be unknown at this point, because of the join point
DeLesley Hutchinsb4fa4182012-01-06 19:16:50 +00001735 a = 8; // expected-warning {{writing variable 'a' requires locking 'mu' exclusively}}
1736 }
1737 if (b2) { // b2 should be known at this point.
1738 a = 8;
1739 mu.Unlock();
1740 }
1741 }
1742
1743 // Test use-def-chains: back edges
1744 void foo9() {
1745 bool b = mu.TryLock();
1746
1747 for (int i = 0; i < 10; ++i);
1748
1749 if (b) { // b is still known, because the loop doesn't alter it
1750 a = 9;
1751 mu.Unlock();
1752 }
1753 }
1754
1755 // Test use-def chains: back edges
1756 void foo10() {
1757 bool b = mu.TryLock();
1758
1759 while (cond) {
1760 if (b) { // b should be uknown at this point b/c of the loop
1761 a = 10; // expected-warning {{writing variable 'a' requires locking 'mu' exclusively}}
1762 }
1763 b = !b;
1764 }
1765 }
DeLesley Hutchins60ff1982012-09-20 23:14:43 +00001766
1767 // Test merge of exclusive trylock
1768 void foo11() {
1769 if (cond) {
1770 if (!mu.TryLock())
1771 return;
1772 }
1773 else {
1774 mu.Lock();
1775 }
1776 a = 10;
1777 mu.Unlock();
1778 }
1779
1780 // Test merge of shared trylock
1781 void foo12() {
1782 if (cond) {
1783 if (!mu.ReaderTryLock())
1784 return;
1785 }
1786 else {
1787 mu.ReaderLock();
1788 }
1789 int i = a;
1790 mu.Unlock();
1791 }
DeLesley Hutchinsb4fa4182012-01-06 19:16:50 +00001792}; // end TestTrylock
1793
DeLesley Hutchins60ff1982012-09-20 23:14:43 +00001794} // end namespace TrylockTest
1795
DeLesley Hutchinsb4fa4182012-01-06 19:16:50 +00001796
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +00001797namespace TestTemplateAttributeInstantiation {
1798
1799class Foo1 {
1800public:
1801 Mutex mu_;
1802 int a GUARDED_BY(mu_);
1803};
1804
1805class Foo2 {
1806public:
1807 int a GUARDED_BY(mu_);
1808 Mutex mu_;
1809};
1810
1811
1812class Bar {
1813public:
1814 // Test non-dependent expressions in attributes on template functions
1815 template <class T>
1816 void barND(Foo1 *foo, T *fooT) EXCLUSIVE_LOCKS_REQUIRED(foo->mu_) {
1817 foo->a = 0;
1818 }
1819
1820 // Test dependent expressions in attributes on template functions
1821 template <class T>
1822 void barD(Foo1 *foo, T *fooT) EXCLUSIVE_LOCKS_REQUIRED(fooT->mu_) {
1823 fooT->a = 0;
1824 }
1825};
1826
1827
1828template <class T>
1829class BarT {
1830public:
1831 Foo1 fooBase;
1832 T fooBaseT;
1833
1834 // Test non-dependent expression in ordinary method on template class
1835 void barND() EXCLUSIVE_LOCKS_REQUIRED(fooBase.mu_) {
1836 fooBase.a = 0;
1837 }
1838
1839 // Test dependent expressions in ordinary methods on template class
1840 void barD() EXCLUSIVE_LOCKS_REQUIRED(fooBaseT.mu_) {
1841 fooBaseT.a = 0;
1842 }
1843
1844 // Test dependent expressions in template method in template class
1845 template <class T2>
1846 void barTD(T2 *fooT) EXCLUSIVE_LOCKS_REQUIRED(fooBaseT.mu_, fooT->mu_) {
1847 fooBaseT.a = 0;
1848 fooT->a = 0;
1849 }
1850};
1851
1852template <class T>
1853class Cell {
1854public:
1855 Mutex mu_;
1856 // Test dependent guarded_by
1857 T data GUARDED_BY(mu_);
1858
DeLesley Hutchins23323e02012-01-20 22:50:54 +00001859 void fooEx() EXCLUSIVE_LOCKS_REQUIRED(mu_) {
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +00001860 data = 0;
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +00001861 }
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +00001862
1863 void foo() {
1864 mu_.Lock();
1865 data = 0;
1866 mu_.Unlock();
1867 }
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +00001868};
1869
1870void test() {
1871 Bar b;
1872 BarT<Foo2> bt;
1873 Foo1 f1;
1874 Foo2 f2;
1875
1876 f1.mu_.Lock();
1877 f2.mu_.Lock();
1878 bt.fooBase.mu_.Lock();
1879 bt.fooBaseT.mu_.Lock();
1880
1881 b.barND(&f1, &f2);
1882 b.barD(&f1, &f2);
1883 bt.barND();
1884 bt.barD();
1885 bt.barTD(&f2);
1886
1887 f1.mu_.Unlock();
1888 bt.barTD(&f1); // \
DeLesley Hutchins3f0ec522012-09-10 19:58:23 +00001889 // expected-warning {{calling function 'barTD' requires exclusive lock on 'f1.mu_'}} \
1890 // expected-note {{found near match 'bt.fooBase.mu_'}}
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +00001891
1892 bt.fooBase.mu_.Unlock();
1893 bt.fooBaseT.mu_.Unlock();
1894 f2.mu_.Unlock();
1895
1896 Cell<int> cell;
1897 cell.data = 0; // \
DeLesley Hutchinsa74b7152012-08-10 20:19:55 +00001898 // expected-warning {{writing variable 'data' requires locking 'cell.mu_' exclusively}}
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +00001899 cell.foo();
DeLesley Hutchins23323e02012-01-20 22:50:54 +00001900 cell.mu_.Lock();
1901 cell.fooEx();
1902 cell.mu_.Unlock();
1903}
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +00001904
DeLesley Hutchins23323e02012-01-20 22:50:54 +00001905
1906template <class T>
1907class CellDelayed {
1908public:
1909 // Test dependent guarded_by
1910 T data GUARDED_BY(mu_);
DeLesley Hutchinsdd5756c2012-02-16 17:30:51 +00001911 static T static_data GUARDED_BY(static_mu_);
DeLesley Hutchins23323e02012-01-20 22:50:54 +00001912
1913 void fooEx(CellDelayed<T> *other) EXCLUSIVE_LOCKS_REQUIRED(mu_, other->mu_) {
1914 this->data = other->data;
1915 }
1916
1917 template <class T2>
1918 void fooExT(CellDelayed<T2> *otherT) EXCLUSIVE_LOCKS_REQUIRED(mu_, otherT->mu_) {
1919 this->data = otherT->data;
1920 }
1921
1922 void foo() {
1923 mu_.Lock();
1924 data = 0;
1925 mu_.Unlock();
1926 }
1927
1928 Mutex mu_;
DeLesley Hutchinsdd5756c2012-02-16 17:30:51 +00001929 static Mutex static_mu_;
DeLesley Hutchins23323e02012-01-20 22:50:54 +00001930};
1931
1932void testDelayed() {
1933 CellDelayed<int> celld;
1934 CellDelayed<int> celld2;
1935 celld.foo();
1936 celld.mu_.Lock();
1937 celld2.mu_.Lock();
1938
1939 celld.fooEx(&celld2);
1940 celld.fooExT(&celld2);
1941
1942 celld2.mu_.Unlock();
1943 celld.mu_.Unlock();
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +00001944}
1945
1946}; // end namespace TestTemplateAttributeInstantiation
1947
1948
DeLesley Hutchinse03b2b32012-01-20 23:24:41 +00001949namespace FunctionDeclDefTest {
1950
1951class Foo {
1952public:
1953 Mutex mu_;
1954 int a GUARDED_BY(mu_);
1955
1956 virtual void foo1(Foo *f_declared) EXCLUSIVE_LOCKS_REQUIRED(f_declared->mu_);
1957};
1958
1959// EXCLUSIVE_LOCKS_REQUIRED should be applied, and rewritten to f_defined->mu_
1960void Foo::foo1(Foo *f_defined) {
1961 f_defined->a = 0;
1962};
1963
1964void test() {
1965 Foo myfoo;
1966 myfoo.foo1(&myfoo); // \
DeLesley Hutchinsa74b7152012-08-10 20:19:55 +00001967 // expected-warning {{calling function 'foo1' requires exclusive lock on 'myfoo.mu_'}}
DeLesley Hutchinse03b2b32012-01-20 23:24:41 +00001968 myfoo.mu_.Lock();
1969 myfoo.foo1(&myfoo);
1970 myfoo.mu_.Unlock();
1971}
1972
1973};
Richard Smith2e515622012-02-03 04:45:26 +00001974
1975namespace GoingNative {
1976
1977 struct __attribute__((lockable)) mutex {
1978 void lock() __attribute__((exclusive_lock_function));
1979 void unlock() __attribute__((unlock_function));
1980 // ...
1981 };
1982 bool foo();
1983 bool bar();
1984 mutex m;
1985 void test() {
1986 m.lock();
1987 while (foo()) {
1988 m.unlock();
1989 // ...
1990 if (bar()) {
1991 // ...
1992 if (foo())
1993 continue; // expected-warning {{expecting mutex 'm' to be locked at start of each loop}}
1994 //...
1995 }
1996 // ...
1997 m.lock(); // expected-note {{mutex acquired here}}
1998 }
1999 m.unlock();
2000 }
2001
2002}
DeLesley Hutchinsc24a2332012-02-16 16:50:43 +00002003
2004
2005
2006namespace FunctionDefinitionTest {
2007
2008class Foo {
2009public:
2010 void foo1();
2011 void foo2();
2012 void foo3(Foo *other);
2013
2014 template<class T>
2015 void fooT1(const T& dummy1);
2016
2017 template<class T>
2018 void fooT2(const T& dummy2) EXCLUSIVE_LOCKS_REQUIRED(mu_);
2019
2020 Mutex mu_;
2021 int a GUARDED_BY(mu_);
2022};
2023
2024template<class T>
2025class FooT {
2026public:
2027 void foo();
2028
2029 Mutex mu_;
2030 T a GUARDED_BY(mu_);
2031};
2032
2033
2034void Foo::foo1() NO_THREAD_SAFETY_ANALYSIS {
2035 a = 1;
2036}
2037
2038void Foo::foo2() EXCLUSIVE_LOCKS_REQUIRED(mu_) {
2039 a = 2;
2040}
2041
2042void Foo::foo3(Foo *other) EXCLUSIVE_LOCKS_REQUIRED(other->mu_) {
2043 other->a = 3;
2044}
2045
2046template<class T>
2047void Foo::fooT1(const T& dummy1) EXCLUSIVE_LOCKS_REQUIRED(mu_) {
2048 a = dummy1;
2049}
2050
2051/* TODO -- uncomment with template instantiation of attributes.
2052template<class T>
2053void Foo::fooT2(const T& dummy2) {
2054 a = dummy2;
2055}
2056*/
2057
2058void fooF1(Foo *f) EXCLUSIVE_LOCKS_REQUIRED(f->mu_) {
2059 f->a = 1;
2060}
2061
2062void fooF2(Foo *f);
2063void fooF2(Foo *f) EXCLUSIVE_LOCKS_REQUIRED(f->mu_) {
2064 f->a = 2;
2065}
2066
2067void fooF3(Foo *f) EXCLUSIVE_LOCKS_REQUIRED(f->mu_);
2068void fooF3(Foo *f) {
2069 f->a = 3;
2070}
2071
2072template<class T>
2073void FooT<T>::foo() EXCLUSIVE_LOCKS_REQUIRED(mu_) {
2074 a = 0;
2075}
2076
2077void test() {
2078 int dummy = 0;
2079 Foo myFoo;
2080
2081 myFoo.foo2(); // \
DeLesley Hutchinsa74b7152012-08-10 20:19:55 +00002082 // expected-warning {{calling function 'foo2' requires exclusive lock on 'myFoo.mu_'}}
DeLesley Hutchinsc24a2332012-02-16 16:50:43 +00002083 myFoo.foo3(&myFoo); // \
DeLesley Hutchinsa74b7152012-08-10 20:19:55 +00002084 // expected-warning {{calling function 'foo3' requires exclusive lock on 'myFoo.mu_'}}
DeLesley Hutchinsc24a2332012-02-16 16:50:43 +00002085 myFoo.fooT1(dummy); // \
DeLesley Hutchinsa74b7152012-08-10 20:19:55 +00002086 // expected-warning {{calling function 'fooT1' requires exclusive lock on 'myFoo.mu_'}}
DeLesley Hutchinsc24a2332012-02-16 16:50:43 +00002087
DeLesley Hutchinsa74b7152012-08-10 20:19:55 +00002088 myFoo.fooT2(dummy); // \
2089 // expected-warning {{calling function 'fooT2' requires exclusive lock on 'myFoo.mu_'}}
DeLesley Hutchinsc24a2332012-02-16 16:50:43 +00002090
2091 fooF1(&myFoo); // \
DeLesley Hutchinsa74b7152012-08-10 20:19:55 +00002092 // expected-warning {{calling function 'fooF1' requires exclusive lock on 'myFoo.mu_'}}
DeLesley Hutchinsc24a2332012-02-16 16:50:43 +00002093 fooF2(&myFoo); // \
DeLesley Hutchinsa74b7152012-08-10 20:19:55 +00002094 // expected-warning {{calling function 'fooF2' requires exclusive lock on 'myFoo.mu_'}}
DeLesley Hutchinsc24a2332012-02-16 16:50:43 +00002095 fooF3(&myFoo); // \
DeLesley Hutchinsa74b7152012-08-10 20:19:55 +00002096 // expected-warning {{calling function 'fooF3' requires exclusive lock on 'myFoo.mu_'}}
DeLesley Hutchinsc24a2332012-02-16 16:50:43 +00002097
2098 myFoo.mu_.Lock();
2099 myFoo.foo2();
2100 myFoo.foo3(&myFoo);
2101 myFoo.fooT1(dummy);
2102
DeLesley Hutchinsa74b7152012-08-10 20:19:55 +00002103 myFoo.fooT2(dummy);
DeLesley Hutchinsc24a2332012-02-16 16:50:43 +00002104
2105 fooF1(&myFoo);
2106 fooF2(&myFoo);
2107 fooF3(&myFoo);
2108 myFoo.mu_.Unlock();
2109
2110 FooT<int> myFooT;
2111 myFooT.foo(); // \
DeLesley Hutchinsa74b7152012-08-10 20:19:55 +00002112 // expected-warning {{calling function 'foo' requires exclusive lock on 'myFooT.mu_'}}
DeLesley Hutchinsc24a2332012-02-16 16:50:43 +00002113}
2114
DeLesley Hutchins4bda3ec2012-02-16 17:03:24 +00002115} // end namespace FunctionDefinitionTest
2116
2117
2118namespace SelfLockingTest {
2119
2120class LOCKABLE MyLock {
2121public:
2122 int foo GUARDED_BY(this);
2123
2124 void lock() EXCLUSIVE_LOCK_FUNCTION();
2125 void unlock() UNLOCK_FUNCTION();
2126
2127 void doSomething() {
2128 this->lock(); // allow 'this' as a lock expression
2129 foo = 0;
2130 doSomethingElse();
2131 this->unlock();
2132 }
2133
2134 void doSomethingElse() EXCLUSIVE_LOCKS_REQUIRED(this) {
2135 foo = 1;
2136 };
2137
2138 void test() {
2139 foo = 2; // \
2140 // expected-warning {{writing variable 'foo' requires locking 'this' exclusively}}
2141 }
DeLesley Hutchinsc24a2332012-02-16 16:50:43 +00002142};
2143
DeLesley Hutchins2f13bec2012-02-16 17:13:43 +00002144
2145class LOCKABLE MyLock2 {
2146public:
2147 Mutex mu_;
2148 int foo GUARDED_BY(this);
2149
2150 // don't check inside lock and unlock functions
2151 void lock() EXCLUSIVE_LOCK_FUNCTION() { mu_.Lock(); }
2152 void unlock() UNLOCK_FUNCTION() { mu_.Unlock(); }
2153
2154 // don't check inside constructors and destructors
2155 MyLock2() { foo = 1; }
2156 ~MyLock2() { foo = 0; }
2157};
2158
2159
DeLesley Hutchins4bda3ec2012-02-16 17:03:24 +00002160} // end namespace SelfLockingTest
2161
2162
DeLesley Hutchinsd08d5992012-02-25 00:11:55 +00002163namespace InvalidNonstatic {
2164
2165// Forward decl here causes bogus "invalid use of non-static data member"
2166// on reference to mutex_ in guarded_by attribute.
2167class Foo;
2168
2169class Foo {
2170 Mutex* mutex_;
2171
2172 int foo __attribute__((guarded_by(mutex_)));
2173};
2174
2175} // end namespace InvalidNonStatic
2176
DeLesley Hutchins2a35be82012-03-02 22:02:58 +00002177
2178namespace NoReturnTest {
2179
2180bool condition();
2181void fatal() __attribute__((noreturn));
2182
2183Mutex mu_;
2184
2185void test1() {
2186 MutexLock lock(&mu_);
2187 if (condition()) {
2188 fatal();
2189 return;
2190 }
2191}
2192
DeLesley Hutchins2287c5e2012-03-02 22:12:59 +00002193} // end namespace NoReturnTest
2194
2195
2196namespace TestMultiDecl {
2197
2198class Foo {
2199public:
2200 int GUARDED_BY(mu_) a;
2201 int GUARDED_BY(mu_) b, c;
2202
2203 void foo() {
2204 a = 0; // \
2205 // expected-warning {{writing variable 'a' requires locking 'mu_' exclusively}}
2206 b = 0; // \
2207 // expected-warning {{writing variable 'b' requires locking 'mu_' exclusively}}
2208 c = 0; // \
2209 // expected-warning {{writing variable 'c' requires locking 'mu_' exclusively}}
2210 }
2211
2212private:
2213 Mutex mu_;
DeLesley Hutchins2a35be82012-03-02 22:02:58 +00002214};
DeLesley Hutchins2287c5e2012-03-02 22:12:59 +00002215
2216} // end namespace TestMultiDecl
2217
DeLesley Hutchins7ec419a2012-03-02 22:29:50 +00002218
2219namespace WarnNoDecl {
2220
2221class Foo {
2222 void foo(int a); __attribute__(( // \
2223 // expected-warning {{declaration does not declare anything}}
2224 exclusive_locks_required(a))); // \
2225 // expected-warning {{attribute exclusive_locks_required ignored}}
2226};
2227
2228} // end namespace WarnNoDecl
2229
2230
DeLesley Hutchins0d95dfc2012-03-02 23:36:05 +00002231
2232namespace MoreLockExpressions {
2233
2234class Foo {
2235public:
2236 Mutex mu_;
2237 int a GUARDED_BY(mu_);
2238};
2239
2240class Bar {
2241public:
2242 int b;
2243 Foo* f;
2244
2245 Foo& getFoo() { return *f; }
2246 Foo& getFoo2(int c) { return *f; }
2247 Foo& getFoo3(int c, int d) { return *f; }
2248
2249 Foo& getFooey() { return *f; }
2250};
2251
2252Foo& getBarFoo(Bar &bar, int c) { return bar.getFoo2(c); }
2253
2254void test() {
2255 Foo foo;
2256 Foo *fooArray;
2257 Bar bar;
2258 int a;
2259 int b;
2260 int c;
2261
2262 bar.getFoo().mu_.Lock();
2263 bar.getFoo().a = 0;
2264 bar.getFoo().mu_.Unlock();
2265
2266 (bar.getFoo().mu_).Lock(); // test parenthesis
2267 bar.getFoo().a = 0;
2268 (bar.getFoo().mu_).Unlock();
2269
2270 bar.getFoo2(a).mu_.Lock();
2271 bar.getFoo2(a).a = 0;
2272 bar.getFoo2(a).mu_.Unlock();
2273
2274 bar.getFoo3(a, b).mu_.Lock();
2275 bar.getFoo3(a, b).a = 0;
2276 bar.getFoo3(a, b).mu_.Unlock();
2277
2278 getBarFoo(bar, a).mu_.Lock();
2279 getBarFoo(bar, a).a = 0;
2280 getBarFoo(bar, a).mu_.Unlock();
2281
2282 bar.getFoo2(10).mu_.Lock();
2283 bar.getFoo2(10).a = 0;
2284 bar.getFoo2(10).mu_.Unlock();
2285
2286 bar.getFoo2(a + 1).mu_.Lock();
2287 bar.getFoo2(a + 1).a = 0;
2288 bar.getFoo2(a + 1).mu_.Unlock();
2289
2290 (a > 0 ? fooArray[1] : fooArray[b]).mu_.Lock();
2291 (a > 0 ? fooArray[1] : fooArray[b]).a = 0;
2292 (a > 0 ? fooArray[1] : fooArray[b]).mu_.Unlock();
2293
2294 bar.getFoo().mu_.Lock();
2295 bar.getFooey().a = 0; // \
DeLesley Hutchins3f0ec522012-09-10 19:58:23 +00002296 // expected-warning {{writing variable 'a' requires locking 'bar.getFooey().mu_' exclusively}} \
2297 // expected-note {{found near match 'bar.getFoo().mu_'}}
DeLesley Hutchins0d95dfc2012-03-02 23:36:05 +00002298 bar.getFoo().mu_.Unlock();
2299
2300 bar.getFoo2(a).mu_.Lock();
2301 bar.getFoo2(b).a = 0; // \
DeLesley Hutchins3f0ec522012-09-10 19:58:23 +00002302 // expected-warning {{writing variable 'a' requires locking 'bar.getFoo2(b).mu_' exclusively}} \
2303 // expected-note {{found near match 'bar.getFoo2(a).mu_'}}
DeLesley Hutchins0d95dfc2012-03-02 23:36:05 +00002304 bar.getFoo2(a).mu_.Unlock();
2305
2306 bar.getFoo3(a, b).mu_.Lock();
2307 bar.getFoo3(a, c).a = 0; // \
DeLesley Hutchins3f0ec522012-09-10 19:58:23 +00002308 // expected-warning {{writing variable 'a' requires locking 'bar.getFoo3(a,c).mu_' exclusively}} \
2309 // expected-note {{'bar.getFoo3(a,b).mu_'}}
DeLesley Hutchins0d95dfc2012-03-02 23:36:05 +00002310 bar.getFoo3(a, b).mu_.Unlock();
2311
2312 getBarFoo(bar, a).mu_.Lock();
2313 getBarFoo(bar, b).a = 0; // \
DeLesley Hutchins3f0ec522012-09-10 19:58:23 +00002314 // expected-warning {{writing variable 'a' requires locking 'getBarFoo(bar,b).mu_' exclusively}} \
2315 // expected-note {{'getBarFoo(bar,a).mu_'}}
DeLesley Hutchins0d95dfc2012-03-02 23:36:05 +00002316 getBarFoo(bar, a).mu_.Unlock();
2317
2318 (a > 0 ? fooArray[1] : fooArray[b]).mu_.Lock();
2319 (a > 0 ? fooArray[b] : fooArray[c]).a = 0; // \
DeLesley Hutchins3f0ec522012-09-10 19:58:23 +00002320 // expected-warning {{writing variable 'a' requires locking '((a#_)#_#fooArray[b]).mu_' exclusively}} \
2321 // expected-note {{'((a#_)#_#fooArray[_]).mu_'}}
DeLesley Hutchins0d95dfc2012-03-02 23:36:05 +00002322 (a > 0 ? fooArray[1] : fooArray[b]).mu_.Unlock();
2323}
2324
2325
DeLesley Hutchins0da44142012-06-22 17:07:28 +00002326} // end namespace MoreLockExpressions
2327
2328
2329namespace TrylockJoinPoint {
2330
2331class Foo {
2332 Mutex mu;
2333 bool c;
2334
2335 void foo() {
2336 if (c) {
2337 if (!mu.TryLock())
2338 return;
2339 } else {
2340 mu.Lock();
2341 }
2342 mu.Unlock();
2343 }
2344};
2345
2346} // end namespace TrylockJoinPoint
DeLesley Hutchins0d95dfc2012-03-02 23:36:05 +00002347
2348
DeLesley Hutchinsf63797c2012-06-25 18:33:18 +00002349namespace LockReturned {
2350
2351class Foo {
2352public:
2353 int a GUARDED_BY(mu_);
2354 void foo() EXCLUSIVE_LOCKS_REQUIRED(mu_);
2355 void foo2(Foo* f) EXCLUSIVE_LOCKS_REQUIRED(mu_, f->mu_);
2356
2357 static void sfoo(Foo* f) EXCLUSIVE_LOCKS_REQUIRED(f->mu_);
2358
2359 Mutex* getMu() LOCK_RETURNED(mu_);
2360
2361 Mutex mu_;
2362
2363 static Mutex* getMu(Foo* f) LOCK_RETURNED(f->mu_);
2364};
2365
2366
2367// Calls getMu() directly to lock and unlock
2368void test1(Foo* f1, Foo* f2) {
DeLesley Hutchinsa74b7152012-08-10 20:19:55 +00002369 f1->a = 0; // expected-warning {{writing variable 'a' requires locking 'f1->mu_' exclusively}}
2370 f1->foo(); // expected-warning {{calling function 'foo' requires exclusive lock on 'f1->mu_'}}
DeLesley Hutchinsf63797c2012-06-25 18:33:18 +00002371
DeLesley Hutchinsa74b7152012-08-10 20:19:55 +00002372 f1->foo2(f2); // expected-warning {{calling function 'foo2' requires exclusive lock on 'f1->mu_'}} \
2373 // expected-warning {{calling function 'foo2' requires exclusive lock on 'f2->mu_'}}
2374 Foo::sfoo(f1); // expected-warning {{calling function 'sfoo' requires exclusive lock on 'f1->mu_'}}
DeLesley Hutchinsf63797c2012-06-25 18:33:18 +00002375
2376 f1->getMu()->Lock();
2377
2378 f1->a = 0;
2379 f1->foo();
DeLesley Hutchins3f0ec522012-09-10 19:58:23 +00002380 f1->foo2(f2); // \
2381 // expected-warning {{calling function 'foo2' requires exclusive lock on 'f2->mu_'}} \
2382 // expected-note {{found near match 'f1->mu_'}}
DeLesley Hutchinsf63797c2012-06-25 18:33:18 +00002383
2384 Foo::getMu(f2)->Lock();
2385 f1->foo2(f2);
2386 Foo::getMu(f2)->Unlock();
2387
2388 Foo::sfoo(f1);
2389
2390 f1->getMu()->Unlock();
2391}
2392
2393
2394Mutex* getFooMu(Foo* f) LOCK_RETURNED(Foo::getMu(f));
2395
2396class Bar : public Foo {
2397public:
2398 int b GUARDED_BY(getMu());
2399 void bar() EXCLUSIVE_LOCKS_REQUIRED(getMu());
2400 void bar2(Bar* g) EXCLUSIVE_LOCKS_REQUIRED(getMu(this), g->getMu());
2401
2402 static void sbar(Bar* g) EXCLUSIVE_LOCKS_REQUIRED(g->getMu());
2403 static void sbar2(Bar* g) EXCLUSIVE_LOCKS_REQUIRED(getFooMu(g));
2404};
2405
2406
2407
2408// Use getMu() within other attributes.
2409// This requires at lest levels of substitution, more in the case of
2410void test2(Bar* b1, Bar* b2) {
DeLesley Hutchinsa74b7152012-08-10 20:19:55 +00002411 b1->b = 0; // expected-warning {{writing variable 'b' requires locking 'b1->mu_' exclusively}}
2412 b1->bar(); // expected-warning {{calling function 'bar' requires exclusive lock on 'b1->mu_'}}
2413 b1->bar2(b2); // expected-warning {{calling function 'bar2' requires exclusive lock on 'b1->mu_'}} \
2414 // expected-warning {{calling function 'bar2' requires exclusive lock on 'b2->mu_'}}
2415 Bar::sbar(b1); // expected-warning {{calling function 'sbar' requires exclusive lock on 'b1->mu_'}}
2416 Bar::sbar2(b1); // expected-warning {{calling function 'sbar2' requires exclusive lock on 'b1->mu_'}}
DeLesley Hutchinsf63797c2012-06-25 18:33:18 +00002417
2418 b1->getMu()->Lock();
2419
2420 b1->b = 0;
2421 b1->bar();
DeLesley Hutchins3f0ec522012-09-10 19:58:23 +00002422 b1->bar2(b2); // \
2423 // expected-warning {{calling function 'bar2' requires exclusive lock on 'b2->mu_'}} \
2424 // // expected-note {{found near match 'b1->mu_'}}
DeLesley Hutchinsf63797c2012-06-25 18:33:18 +00002425
2426 b2->getMu()->Lock();
2427 b1->bar2(b2);
2428
2429 b2->getMu()->Unlock();
2430
2431 Bar::sbar(b1);
2432 Bar::sbar2(b1);
2433
2434 b1->getMu()->Unlock();
2435}
2436
2437
2438// Sanity check -- lock the mutex directly, but use attributes that call getMu()
2439// Also lock the mutex using getFooMu, which calls a lock_returned function.
2440void test3(Bar* b1, Bar* b2) {
2441 b1->mu_.Lock();
2442 b1->b = 0;
2443 b1->bar();
2444
2445 getFooMu(b2)->Lock();
2446 b1->bar2(b2);
2447 getFooMu(b2)->Unlock();
2448
2449 Bar::sbar(b1);
2450 Bar::sbar2(b1);
2451
2452 b1->mu_.Unlock();
2453}
2454
2455} // end namespace LockReturned
2456
2457
DeLesley Hutchinsc99a5d82012-06-28 22:42:48 +00002458namespace ReleasableScopedLock {
2459
2460class Foo {
2461 Mutex mu_;
2462 bool c;
2463 int a GUARDED_BY(mu_);
2464
2465 void test1();
2466 void test2();
2467 void test3();
DeLesley Hutchins5381c052012-07-05 21:16:29 +00002468 void test4();
2469 void test5();
DeLesley Hutchinsc99a5d82012-06-28 22:42:48 +00002470};
2471
2472
2473void Foo::test1() {
2474 ReleasableMutexLock rlock(&mu_);
2475 rlock.Release();
2476}
2477
2478void Foo::test2() {
2479 ReleasableMutexLock rlock(&mu_);
2480 if (c) { // test join point -- held/not held during release
2481 rlock.Release();
2482 }
2483}
2484
2485void Foo::test3() {
2486 ReleasableMutexLock rlock(&mu_);
2487 a = 0;
2488 rlock.Release();
2489 a = 1; // expected-warning {{writing variable 'a' requires locking 'mu_' exclusively}}
2490}
2491
DeLesley Hutchins5381c052012-07-05 21:16:29 +00002492void Foo::test4() {
2493 ReleasableMutexLock rlock(&mu_);
2494 rlock.Release();
2495 rlock.Release(); // expected-warning {{unlocking 'mu_' that was not locked}}
2496}
2497
2498void Foo::test5() {
2499 ReleasableMutexLock rlock(&mu_);
2500 if (c) {
2501 rlock.Release();
2502 }
2503 // no warning on join point for managed lock.
2504 rlock.Release(); // expected-warning {{unlocking 'mu_' that was not locked}}
2505}
2506
2507
DeLesley Hutchinsc99a5d82012-06-28 22:42:48 +00002508} // end namespace ReleasableScopedLock
2509
2510
DeLesley Hutchins76f0a6e2012-07-02 21:59:24 +00002511namespace TrylockFunctionTest {
2512
2513class Foo {
2514public:
2515 Mutex mu1_;
2516 Mutex mu2_;
2517 bool c;
2518
2519 bool lockBoth() EXCLUSIVE_TRYLOCK_FUNCTION(true, mu1_, mu2_);
2520};
2521
2522bool Foo::lockBoth() {
2523 if (!mu1_.TryLock())
2524 return false;
2525
2526 mu2_.Lock();
2527 if (!c) {
2528 mu1_.Unlock();
2529 mu2_.Unlock();
2530 return false;
2531 }
2532
2533 return true;
2534}
2535
2536
2537} // end namespace TrylockFunctionTest
DeLesley Hutchinsc99a5d82012-06-28 22:42:48 +00002538
2539
2540
DeLesley Hutchinsc36eda12012-07-02 22:12:12 +00002541namespace DoubleLockBug {
2542
2543class Foo {
2544public:
2545 Mutex mu_;
2546 int a GUARDED_BY(mu_);
2547
DeLesley Hutchins5381c052012-07-05 21:16:29 +00002548 void foo1() EXCLUSIVE_LOCKS_REQUIRED(mu_);
2549 int foo2() SHARED_LOCKS_REQUIRED(mu_);
DeLesley Hutchinsc36eda12012-07-02 22:12:12 +00002550};
2551
2552
DeLesley Hutchins5381c052012-07-05 21:16:29 +00002553void Foo::foo1() EXCLUSIVE_LOCKS_REQUIRED(mu_) {
DeLesley Hutchinsc36eda12012-07-02 22:12:12 +00002554 a = 0;
2555}
2556
DeLesley Hutchins5381c052012-07-05 21:16:29 +00002557int Foo::foo2() SHARED_LOCKS_REQUIRED(mu_) {
2558 return a;
2559}
2560
2561}
2562
DeLesley Hutchinsc36eda12012-07-02 22:12:12 +00002563
2564
DeLesley Hutchins879a4332012-07-02 22:16:54 +00002565namespace UnlockBug {
DeLesley Hutchinsc36eda12012-07-02 22:12:12 +00002566
DeLesley Hutchins879a4332012-07-02 22:16:54 +00002567class Foo {
2568public:
2569 Mutex mutex_;
2570
2571 void foo1() EXCLUSIVE_LOCKS_REQUIRED(mutex_) { // expected-note {{mutex acquired here}}
2572 mutex_.Unlock();
2573 } // expected-warning {{expecting mutex 'mutex_' to be locked at the end of function}}
2574
2575
2576 void foo2() SHARED_LOCKS_REQUIRED(mutex_) { // expected-note {{mutex acquired here}}
2577 mutex_.Unlock();
2578 } // expected-warning {{expecting mutex 'mutex_' to be locked at the end of function}}
2579};
2580
2581} // end namespace UnlockBug
DeLesley Hutchinsc36eda12012-07-02 22:12:12 +00002582
DeLesley Hutchinsc99a5d82012-06-28 22:42:48 +00002583
DeLesley Hutchins5381c052012-07-05 21:16:29 +00002584
DeLesley Hutchinsbbe33412012-07-02 22:26:29 +00002585namespace FoolishScopedLockableBug {
2586
2587class SCOPED_LOCKABLE WTF_ScopedLockable {
2588public:
2589 WTF_ScopedLockable(Mutex* mu) EXCLUSIVE_LOCK_FUNCTION(mu);
2590
2591 // have to call release() manually;
2592 ~WTF_ScopedLockable();
2593
2594 void release() UNLOCK_FUNCTION();
2595};
2596
2597
2598class Foo {
2599 Mutex mu_;
2600 int a GUARDED_BY(mu_);
2601 bool c;
2602
2603 void doSomething();
2604
2605 void test1() {
2606 WTF_ScopedLockable wtf(&mu_);
2607 wtf.release();
2608 }
2609
2610 void test2() {
2611 WTF_ScopedLockable wtf(&mu_); // expected-note {{mutex acquired here}}
2612 } // expected-warning {{mutex 'mu_' is still locked at the end of function}}
2613
2614 void test3() {
2615 if (c) {
2616 WTF_ScopedLockable wtf(&mu_);
2617 wtf.release();
2618 }
2619 }
2620
2621 void test4() {
2622 if (c) {
2623 doSomething();
2624 }
2625 else {
2626 WTF_ScopedLockable wtf(&mu_);
2627 wtf.release();
2628 }
2629 }
2630
2631 void test5() {
2632 if (c) {
2633 WTF_ScopedLockable wtf(&mu_); // expected-note {{mutex acquired here}}
2634 }
2635 } // expected-warning {{mutex 'mu_' is not locked on every path through here}}
2636
2637 void test6() {
2638 if (c) {
2639 doSomething();
2640 }
2641 else {
2642 WTF_ScopedLockable wtf(&mu_); // expected-note {{mutex acquired here}}
2643 }
2644 } // expected-warning {{mutex 'mu_' is not locked on every path through here}}
2645};
2646
2647
2648} // end namespace FoolishScopedLockableBug
2649
DeLesley Hutchins9d6e7f32012-07-03 18:25:56 +00002650
DeLesley Hutchins5381c052012-07-05 21:16:29 +00002651
DeLesley Hutchins9d6e7f32012-07-03 18:25:56 +00002652namespace TemporaryCleanupExpr {
2653
2654class Foo {
2655 int a GUARDED_BY(getMutexPtr().get());
2656
2657 SmartPtr<Mutex> getMutexPtr();
2658
2659 void test();
2660};
2661
2662
2663void Foo::test() {
2664 {
2665 ReaderMutexLock lock(getMutexPtr().get());
2666 int b = a;
DeLesley Hutchins96fac6a2012-07-03 19:47:18 +00002667 }
DeLesley Hutchinsa74b7152012-08-10 20:19:55 +00002668 int b = a; // expected-warning {{reading variable 'a' requires locking 'getMutexPtr()'}}
DeLesley Hutchins9d6e7f32012-07-03 18:25:56 +00002669}
2670
2671} // end namespace TemporaryCleanupExpr
2672
2673
DeLesley Hutchins96fac6a2012-07-03 19:47:18 +00002674
2675namespace SmartPointerTests {
2676
2677class Foo {
2678public:
2679 SmartPtr<Mutex> mu_;
2680 int a GUARDED_BY(mu_);
2681 int b GUARDED_BY(mu_.get());
2682 int c GUARDED_BY(*mu_);
2683
2684 void Lock() EXCLUSIVE_LOCK_FUNCTION(mu_);
2685 void Unlock() UNLOCK_FUNCTION(mu_);
2686
2687 void test0();
2688 void test1();
2689 void test2();
2690 void test3();
2691 void test4();
2692 void test5();
2693 void test6();
2694 void test7();
2695 void test8();
2696};
2697
2698void Foo::test0() {
2699 a = 0; // expected-warning {{writing variable 'a' requires locking 'mu_' exclusively}}
2700 b = 0; // expected-warning {{writing variable 'b' requires locking 'mu_' exclusively}}
2701 c = 0; // expected-warning {{writing variable 'c' requires locking 'mu_' exclusively}}
2702}
2703
2704void Foo::test1() {
2705 mu_->Lock();
2706 a = 0;
2707 b = 0;
2708 c = 0;
2709 mu_->Unlock();
2710}
2711
2712void Foo::test2() {
2713 (*mu_).Lock();
2714 a = 0;
2715 b = 0;
2716 c = 0;
2717 (*mu_).Unlock();
2718}
2719
2720
2721void Foo::test3() {
2722 mu_.get()->Lock();
2723 a = 0;
2724 b = 0;
2725 c = 0;
2726 mu_.get()->Unlock();
2727}
2728
2729
2730void Foo::test4() {
2731 MutexLock lock(mu_.get());
2732 a = 0;
2733 b = 0;
2734 c = 0;
2735}
2736
2737
2738void Foo::test5() {
2739 MutexLock lock(&(*mu_));
2740 a = 0;
2741 b = 0;
2742 c = 0;
2743}
2744
2745
2746void Foo::test6() {
2747 Lock();
2748 a = 0;
2749 b = 0;
2750 c = 0;
2751 Unlock();
2752}
2753
2754
2755void Foo::test7() {
2756 {
2757 Lock();
2758 mu_->Unlock();
2759 }
2760 {
2761 mu_->Lock();
2762 Unlock();
2763 }
2764 {
2765 mu_.get()->Lock();
2766 mu_->Unlock();
2767 }
2768 {
2769 mu_->Lock();
2770 mu_.get()->Unlock();
2771 }
2772 {
2773 mu_.get()->Lock();
2774 (*mu_).Unlock();
2775 }
2776 {
2777 (*mu_).Lock();
2778 mu_->Unlock();
2779 }
2780}
2781
2782
2783void Foo::test8() {
2784 mu_->Lock();
2785 mu_.get()->Lock(); // expected-warning {{locking 'mu_' that is already locked}}
2786 (*mu_).Lock(); // expected-warning {{locking 'mu_' that is already locked}}
2787 mu_.get()->Unlock();
2788 Unlock(); // expected-warning {{unlocking 'mu_' that was not locked}}
2789}
2790
2791
2792class Bar {
2793 SmartPtr<Foo> foo;
2794
2795 void test0();
2796 void test1();
2797 void test2();
2798 void test3();
2799};
2800
2801
2802void Bar::test0() {
DeLesley Hutchinsa74b7152012-08-10 20:19:55 +00002803 foo->a = 0; // expected-warning {{writing variable 'a' requires locking 'foo->mu_' exclusively}}
2804 (*foo).b = 0; // expected-warning {{writing variable 'b' requires locking 'foo->mu_' exclusively}}
2805 foo.get()->c = 0; // expected-warning {{writing variable 'c' requires locking 'foo->mu_' exclusively}}
DeLesley Hutchins96fac6a2012-07-03 19:47:18 +00002806}
2807
2808
2809void Bar::test1() {
2810 foo->mu_->Lock();
2811 foo->a = 0;
2812 (*foo).b = 0;
2813 foo.get()->c = 0;
2814 foo->mu_->Unlock();
2815}
2816
2817
2818void Bar::test2() {
2819 (*foo).mu_->Lock();
2820 foo->a = 0;
2821 (*foo).b = 0;
2822 foo.get()->c = 0;
2823 foo.get()->mu_->Unlock();
2824}
2825
2826
2827void Bar::test3() {
2828 MutexLock lock(foo->mu_.get());
2829 foo->a = 0;
2830 (*foo).b = 0;
2831 foo.get()->c = 0;
2832}
2833
2834} // end namespace SmartPointerTests
2835
2836
2837
DeLesley Hutchins5381c052012-07-05 21:16:29 +00002838namespace DuplicateAttributeTest {
2839
2840class LOCKABLE Foo {
2841public:
2842 Mutex mu1_;
2843 Mutex mu2_;
2844 Mutex mu3_;
2845 int a GUARDED_BY(mu1_);
2846 int b GUARDED_BY(mu2_);
2847 int c GUARDED_BY(mu3_);
2848
2849 void lock() EXCLUSIVE_LOCK_FUNCTION();
2850 void unlock() UNLOCK_FUNCTION();
2851
2852 void lock1() EXCLUSIVE_LOCK_FUNCTION(mu1_);
2853 void slock1() SHARED_LOCK_FUNCTION(mu1_);
2854 void lock3() EXCLUSIVE_LOCK_FUNCTION(mu1_, mu2_, mu3_);
2855 void locklots()
2856 EXCLUSIVE_LOCK_FUNCTION(mu1_)
2857 EXCLUSIVE_LOCK_FUNCTION(mu2_)
2858 EXCLUSIVE_LOCK_FUNCTION(mu1_, mu2_, mu3_);
2859
2860 void unlock1() UNLOCK_FUNCTION(mu1_);
2861 void unlock3() UNLOCK_FUNCTION(mu1_, mu2_, mu3_);
2862 void unlocklots()
2863 UNLOCK_FUNCTION(mu1_)
2864 UNLOCK_FUNCTION(mu2_)
2865 UNLOCK_FUNCTION(mu1_, mu2_, mu3_);
2866};
2867
2868
2869void Foo::lock() EXCLUSIVE_LOCK_FUNCTION() { }
2870void Foo::unlock() UNLOCK_FUNCTION() { }
2871
2872void Foo::lock1() EXCLUSIVE_LOCK_FUNCTION(mu1_) {
2873 mu1_.Lock();
2874}
2875
2876void Foo::slock1() SHARED_LOCK_FUNCTION(mu1_) {
2877 mu1_.Lock();
2878}
2879
2880void Foo::lock3() EXCLUSIVE_LOCK_FUNCTION(mu1_, mu2_, mu3_) {
2881 mu1_.Lock();
2882 mu2_.Lock();
2883 mu3_.Lock();
2884}
2885
2886void Foo::locklots()
2887 EXCLUSIVE_LOCK_FUNCTION(mu1_, mu2_)
2888 EXCLUSIVE_LOCK_FUNCTION(mu2_, mu3_) {
2889 mu1_.Lock();
2890 mu2_.Lock();
2891 mu3_.Lock();
2892}
2893
2894void Foo::unlock1() UNLOCK_FUNCTION(mu1_) {
2895 mu1_.Unlock();
2896}
2897
2898void Foo::unlock3() UNLOCK_FUNCTION(mu1_, mu2_, mu3_) {
2899 mu1_.Unlock();
2900 mu2_.Unlock();
2901 mu3_.Unlock();
2902}
2903
2904void Foo::unlocklots()
2905 UNLOCK_FUNCTION(mu1_, mu2_)
2906 UNLOCK_FUNCTION(mu2_, mu3_) {
2907 mu1_.Unlock();
2908 mu2_.Unlock();
2909 mu3_.Unlock();
2910}
2911
2912
2913void test0() {
2914 Foo foo;
2915 foo.lock();
2916 foo.unlock();
2917
2918 foo.lock();
2919 foo.lock(); // expected-warning {{locking 'foo' that is already locked}}
2920 foo.unlock();
2921 foo.unlock(); // expected-warning {{unlocking 'foo' that was not locked}}
2922}
2923
2924
2925void test1() {
2926 Foo foo;
2927 foo.lock1();
2928 foo.a = 0;
2929 foo.unlock1();
2930
2931 foo.lock1();
DeLesley Hutchinsa74b7152012-08-10 20:19:55 +00002932 foo.lock1(); // expected-warning {{locking 'foo.mu1_' that is already locked}}
DeLesley Hutchins5381c052012-07-05 21:16:29 +00002933 foo.a = 0;
2934 foo.unlock1();
DeLesley Hutchinsa74b7152012-08-10 20:19:55 +00002935 foo.unlock1(); // expected-warning {{unlocking 'foo.mu1_' that was not locked}}
DeLesley Hutchins5381c052012-07-05 21:16:29 +00002936}
2937
2938
2939int test2() {
2940 Foo foo;
2941 foo.slock1();
2942 int d1 = foo.a;
2943 foo.unlock1();
2944
2945 foo.slock1();
DeLesley Hutchinsa74b7152012-08-10 20:19:55 +00002946 foo.slock1(); // expected-warning {{locking 'foo.mu1_' that is already locked}}
DeLesley Hutchins5381c052012-07-05 21:16:29 +00002947 int d2 = foo.a;
2948 foo.unlock1();
DeLesley Hutchinsa74b7152012-08-10 20:19:55 +00002949 foo.unlock1(); // expected-warning {{unlocking 'foo.mu1_' that was not locked}}
DeLesley Hutchins5381c052012-07-05 21:16:29 +00002950 return d1 + d2;
2951}
2952
2953
2954void test3() {
2955 Foo foo;
2956 foo.lock3();
2957 foo.a = 0;
2958 foo.b = 0;
2959 foo.c = 0;
2960 foo.unlock3();
2961
2962 foo.lock3();
2963 foo.lock3(); // \
DeLesley Hutchinsa74b7152012-08-10 20:19:55 +00002964 // expected-warning {{locking 'foo.mu1_' that is already locked}} \
2965 // expected-warning {{locking 'foo.mu2_' that is already locked}} \
2966 // expected-warning {{locking 'foo.mu3_' that is already locked}}
DeLesley Hutchins5381c052012-07-05 21:16:29 +00002967 foo.a = 0;
2968 foo.b = 0;
2969 foo.c = 0;
2970 foo.unlock3();
2971 foo.unlock3(); // \
DeLesley Hutchinsa74b7152012-08-10 20:19:55 +00002972 // expected-warning {{unlocking 'foo.mu1_' that was not locked}} \
2973 // expected-warning {{unlocking 'foo.mu2_' that was not locked}} \
2974 // expected-warning {{unlocking 'foo.mu3_' that was not locked}}
DeLesley Hutchins5381c052012-07-05 21:16:29 +00002975}
2976
2977
2978void testlots() {
2979 Foo foo;
2980 foo.locklots();
2981 foo.a = 0;
2982 foo.b = 0;
2983 foo.c = 0;
2984 foo.unlocklots();
2985
2986 foo.locklots();
2987 foo.locklots(); // \
DeLesley Hutchinsa74b7152012-08-10 20:19:55 +00002988 // expected-warning {{locking 'foo.mu1_' that is already locked}} \
2989 // expected-warning {{locking 'foo.mu2_' that is already locked}} \
2990 // expected-warning {{locking 'foo.mu3_' that is already locked}}
DeLesley Hutchins5381c052012-07-05 21:16:29 +00002991 foo.a = 0;
2992 foo.b = 0;
2993 foo.c = 0;
2994 foo.unlocklots();
2995 foo.unlocklots(); // \
DeLesley Hutchinsa74b7152012-08-10 20:19:55 +00002996 // expected-warning {{unlocking 'foo.mu1_' that was not locked}} \
2997 // expected-warning {{unlocking 'foo.mu2_' that was not locked}} \
2998 // expected-warning {{unlocking 'foo.mu3_' that was not locked}}
DeLesley Hutchins5381c052012-07-05 21:16:29 +00002999}
3000
3001} // end namespace DuplicateAttributeTest
3002
3003
3004
DeLesley Hutchins13106112012-07-10 21:47:55 +00003005namespace TryLockEqTest {
3006
3007class Foo {
3008 Mutex mu_;
3009 int a GUARDED_BY(mu_);
3010 bool c;
3011
3012 int tryLockMutexI() EXCLUSIVE_TRYLOCK_FUNCTION(1, mu_);
3013 Mutex* tryLockMutexP() EXCLUSIVE_TRYLOCK_FUNCTION(1, mu_);
3014 void unlock() UNLOCK_FUNCTION(mu_);
3015
3016 void test1();
3017 void test2();
3018};
3019
3020
3021void Foo::test1() {
3022 if (tryLockMutexP() == 0) {
3023 a = 0; // expected-warning {{writing variable 'a' requires locking 'mu_' exclusively}}
3024 return;
3025 }
3026 a = 0;
3027 unlock();
3028
3029 if (tryLockMutexP() != 0) {
3030 a = 0;
3031 unlock();
3032 }
3033
3034 if (0 != tryLockMutexP()) {
3035 a = 0;
3036 unlock();
3037 }
3038
3039 if (!(tryLockMutexP() == 0)) {
3040 a = 0;
3041 unlock();
3042 }
3043
3044 if (tryLockMutexI() == 0) {
3045 a = 0; // expected-warning {{writing variable 'a' requires locking 'mu_' exclusively}}
3046 return;
3047 }
3048 a = 0;
3049 unlock();
3050
3051 if (0 == tryLockMutexI()) {
3052 a = 0; // expected-warning {{writing variable 'a' requires locking 'mu_' exclusively}}
3053 return;
3054 }
3055 a = 0;
3056 unlock();
3057
3058 if (tryLockMutexI() == 1) {
3059 a = 0;
3060 unlock();
3061 }
3062
3063 if (mu_.TryLock() == false) {
3064 a = 0; // expected-warning {{writing variable 'a' requires locking 'mu_' exclusively}}
3065 return;
3066 }
3067 a = 0;
3068 unlock();
3069
3070 if (mu_.TryLock() == true) {
3071 a = 0;
3072 unlock();
3073 }
3074 else {
3075 a = 0; // expected-warning {{writing variable 'a' requires locking 'mu_' exclusively}}
3076 }
3077
3078#if __has_feature(cxx_nullptr)
3079 if (tryLockMutexP() == nullptr) {
3080 a = 0; // expected-warning {{writing variable 'a' requires locking 'mu_' exclusively}}
3081 return;
3082 }
3083 a = 0;
3084 unlock();
3085#endif
3086}
3087
3088
3089void Foo::test2() {
3090/* FIXME: these tests depend on changes to the CFG.
3091 *
3092 if (mu_.TryLock() && c) {
3093 a = 0;
3094 unlock();
3095 }
3096 else return;
3097
3098 if (c && mu_.TryLock()) {
3099 a = 0;
3100 unlock();
3101 }
3102 else return;
3103
3104 if (!(mu_.TryLock() && c))
3105 return;
3106 a = 0;
3107 unlock();
3108
3109 if (!(c && mu_.TryLock()))
3110 return;
3111 a = 0;
3112 unlock();
3113
3114 if (!(mu_.TryLock() == 0) && c) {
3115 a = 0;
3116 unlock();
3117 }
3118
3119 if (!mu_.TryLock() || c)
3120 return;
3121 a = 0;
3122 unlock();
3123*/
3124}
3125
DeLesley Hutchins13106112012-07-10 21:47:55 +00003126} // end namespace TryLockEqTest
DeLesley Hutchins5381c052012-07-05 21:16:29 +00003127
DeLesley Hutchins96fac6a2012-07-03 19:47:18 +00003128
DeLesley Hutchinsee2f0322012-08-10 20:29:46 +00003129namespace ExistentialPatternMatching {
3130
3131class Graph {
3132public:
3133 Mutex mu_;
3134};
3135
3136void LockAllGraphs() EXCLUSIVE_LOCK_FUNCTION(&Graph::mu_);
3137void UnlockAllGraphs() UNLOCK_FUNCTION(&Graph::mu_);
3138
3139class Node {
3140public:
3141 int a GUARDED_BY(&Graph::mu_);
3142
3143 void foo() EXCLUSIVE_LOCKS_REQUIRED(&Graph::mu_) {
3144 a = 0;
3145 }
3146 void foo2() LOCKS_EXCLUDED(&Graph::mu_);
3147};
3148
3149void test() {
3150 Graph g1;
3151 Graph g2;
3152 Node n1;
3153
3154 n1.a = 0; // expected-warning {{writing variable 'a' requires locking '&ExistentialPatternMatching::Graph::mu_' exclusively}}
3155 n1.foo(); // expected-warning {{calling function 'foo' requires exclusive lock on '&ExistentialPatternMatching::Graph::mu_'}}
3156 n1.foo2();
3157
3158 g1.mu_.Lock();
3159 n1.a = 0;
3160 n1.foo();
3161 n1.foo2(); // expected-warning {{cannot call function 'foo2' while mutex '&ExistentialPatternMatching::Graph::mu_' is locked}}
3162 g1.mu_.Unlock();
3163
3164 g2.mu_.Lock();
3165 n1.a = 0;
3166 n1.foo();
3167 n1.foo2(); // expected-warning {{cannot call function 'foo2' while mutex '&ExistentialPatternMatching::Graph::mu_' is locked}}
3168 g2.mu_.Unlock();
3169
3170 LockAllGraphs();
3171 n1.a = 0;
3172 n1.foo();
3173 n1.foo2(); // expected-warning {{cannot call function 'foo2' while mutex '&ExistentialPatternMatching::Graph::mu_' is locked}}
3174 UnlockAllGraphs();
3175
3176 LockAllGraphs();
3177 g1.mu_.Unlock();
3178
3179 LockAllGraphs();
3180 g2.mu_.Unlock();
3181
3182 LockAllGraphs();
3183 g1.mu_.Lock(); // expected-warning {{locking 'g1.mu_' that is already locked}}
3184 g1.mu_.Unlock();
3185}
3186
3187} // end namespace ExistentialPatternMatching
3188
DeLesley Hutchins4e4c1572012-08-31 21:57:32 +00003189
3190namespace StringIgnoreTest {
3191
3192class Foo {
3193public:
3194 Mutex mu_;
3195 void lock() EXCLUSIVE_LOCK_FUNCTION("");
3196 void unlock() UNLOCK_FUNCTION("");
3197 void goober() EXCLUSIVE_LOCKS_REQUIRED("");
3198 void roober() SHARED_LOCKS_REQUIRED("");
3199};
3200
3201
3202class Bar : public Foo {
3203public:
3204 void bar(Foo* f) {
3205 f->unlock();
3206 f->goober();
3207 f->roober();
3208 f->lock();
3209 };
3210};
3211
3212} // end namespace StringIgnoreTest
3213
3214
DeLesley Hutchins54081532012-08-31 22:09:53 +00003215namespace LockReturnedScopeFix {
3216
3217class Base {
3218protected:
3219 struct Inner;
3220 bool c;
3221
3222 const Mutex& getLock(const Inner* i);
3223
3224 void lockInner (Inner* i) EXCLUSIVE_LOCK_FUNCTION(getLock(i));
3225 void unlockInner(Inner* i) UNLOCK_FUNCTION(getLock(i));
3226 void foo(Inner* i) EXCLUSIVE_LOCKS_REQUIRED(getLock(i));
3227
3228 void bar(Inner* i);
3229};
3230
3231
3232struct Base::Inner {
3233 Mutex lock_;
3234 void doSomething() EXCLUSIVE_LOCKS_REQUIRED(lock_);
3235};
3236
3237
3238const Mutex& Base::getLock(const Inner* i) LOCK_RETURNED(i->lock_) {
3239 return i->lock_;
3240}
3241
3242
3243void Base::foo(Inner* i) {
3244 i->doSomething();
3245}
3246
3247void Base::bar(Inner* i) {
3248 if (c) {
3249 i->lock_.Lock();
3250 unlockInner(i);
3251 }
3252 else {
3253 lockInner(i);
3254 i->lock_.Unlock();
3255 }
3256}
3257
3258} // end namespace LockReturnedScopeFix
3259
DeLesley Hutchinsfd0f11c2012-09-05 20:01:16 +00003260
3261namespace TrylockWithCleanups {
3262
DeLesley Hutchinsfd0f11c2012-09-05 20:01:16 +00003263struct Foo {
3264 Mutex mu_;
3265 int a GUARDED_BY(mu_);
3266};
3267
3268Foo* GetAndLockFoo(const MyString& s)
3269 EXCLUSIVE_TRYLOCK_FUNCTION(true, &Foo::mu_);
3270
3271static void test() {
3272 Foo* lt = GetAndLockFoo("foo");
3273 if (!lt) return;
3274 int a = lt->a;
3275 lt->mu_.Unlock();
3276}
3277
DeLesley Hutchins24a6c942012-09-11 18:27:46 +00003278} // end namespace TrylockWithCleanups
DeLesley Hutchinsfd0f11c2012-09-05 20:01:16 +00003279
3280
DeLesley Hutchins0b4db3e2012-09-07 17:34:53 +00003281namespace UniversalLock {
3282
3283class Foo {
3284 Mutex mu_;
3285 bool c;
3286
3287 int a GUARDED_BY(mu_);
3288 void r_foo() SHARED_LOCKS_REQUIRED(mu_);
3289 void w_foo() EXCLUSIVE_LOCKS_REQUIRED(mu_);
3290
3291 void test1() {
3292 int b;
3293
3294 beginNoWarnOnReads();
3295 b = a;
3296 r_foo();
3297 endNoWarnOnReads();
3298
3299 beginNoWarnOnWrites();
3300 a = 0;
3301 w_foo();
3302 endNoWarnOnWrites();
3303 }
3304
3305 // don't warn on joins with universal lock
3306 void test2() {
3307 if (c) {
3308 beginNoWarnOnWrites();
3309 }
3310 a = 0; // \
3311 // expected-warning {{writing variable 'a' requires locking 'mu_' exclusively}}
3312 endNoWarnOnWrites(); // \
3313 // expected-warning {{unlocking '*' that was not locked}}
3314 }
3315
3316
3317 // make sure the universal lock joins properly
3318 void test3() {
3319 if (c) {
3320 mu_.Lock();
3321 beginNoWarnOnWrites();
3322 }
3323 else {
3324 beginNoWarnOnWrites();
3325 mu_.Lock();
3326 }
3327 a = 0;
3328 endNoWarnOnWrites();
3329 mu_.Unlock();
3330 }
3331
3332
3333 // combine universal lock with other locks
3334 void test4() {
3335 beginNoWarnOnWrites();
3336 mu_.Lock();
3337 mu_.Unlock();
3338 endNoWarnOnWrites();
3339
3340 mu_.Lock();
3341 beginNoWarnOnWrites();
3342 endNoWarnOnWrites();
3343 mu_.Unlock();
3344
3345 mu_.Lock();
3346 beginNoWarnOnWrites();
3347 mu_.Unlock();
3348 endNoWarnOnWrites();
3349 }
3350};
3351
DeLesley Hutchins24a6c942012-09-11 18:27:46 +00003352} // end namespace UniversalLock
3353
3354
3355namespace TemplateLockReturned {
3356
3357template<class T>
3358class BaseT {
3359public:
3360 virtual void baseMethod() = 0;
3361 Mutex* get_mutex() LOCK_RETURNED(mutex_) { return &mutex_; }
3362
3363 Mutex mutex_;
3364 int a GUARDED_BY(mutex_);
3365};
3366
3367
3368class Derived : public BaseT<int> {
3369public:
3370 void baseMethod() EXCLUSIVE_LOCKS_REQUIRED(get_mutex()) {
3371 a = 0;
3372 }
3373};
3374
3375} // end namespace TemplateLockReturned
3376
3377
DeLesley Hutchinsf9ee0ba2012-09-11 23:04:49 +00003378namespace ExprMatchingBugFix {
3379
3380class Foo {
3381public:
3382 Mutex mu_;
3383};
3384
3385
3386class Bar {
3387public:
3388 bool c;
3389 Foo* foo;
3390 Bar(Foo* f) : foo(f) { }
3391
3392 struct Nested {
3393 Foo* foo;
3394 Nested(Foo* f) : foo(f) { }
3395
3396 void unlockFoo() UNLOCK_FUNCTION(&Foo::mu_);
3397 };
3398
3399 void test();
3400};
3401
3402
3403void Bar::test() {
3404 foo->mu_.Lock();
3405 if (c) {
3406 Nested *n = new Nested(foo);
3407 n->unlockFoo();
3408 }
3409 else {
3410 foo->mu_.Unlock();
3411 }
3412}
3413
3414}; // end namespace ExprMatchingBugfix
3415
3416
DeLesley Hutchins5b280f22012-09-19 19:18:29 +00003417namespace ComplexNameTest {
DeLesley Hutchinsf9ee0ba2012-09-11 23:04:49 +00003418
DeLesley Hutchins5b280f22012-09-19 19:18:29 +00003419class Foo {
3420public:
3421 static Mutex mu_;
3422
3423 Foo() EXCLUSIVE_LOCKS_REQUIRED(mu_) { }
3424 ~Foo() EXCLUSIVE_LOCKS_REQUIRED(mu_) { }
3425
3426 int operator[](int i) EXCLUSIVE_LOCKS_REQUIRED(mu_) { return 0; }
3427};
3428
3429class Bar {
3430public:
3431 static Mutex mu_;
3432
3433 Bar() LOCKS_EXCLUDED(mu_) { }
3434 ~Bar() LOCKS_EXCLUDED(mu_) { }
3435
3436 int operator[](int i) LOCKS_EXCLUDED(mu_) { return 0; }
3437};
3438
3439
3440void test1() {
3441 Foo f; // expected-warning {{calling function 'Foo' requires exclusive lock on 'mu_'}}
3442 int a = f[0]; // expected-warning {{calling function 'operator[]' requires exclusive lock on 'mu_'}}
3443} // expected-warning {{calling function '~Foo' requires exclusive lock on 'mu_'}}
3444
3445
3446void test2() {
3447 Bar::mu_.Lock();
3448 {
3449 Bar b; // expected-warning {{cannot call function 'Bar' while mutex 'mu_' is locked}}
3450 int a = b[0]; // expected-warning {{cannot call function 'operator[]' while mutex 'mu_' is locked}}
3451 } // expected-warning {{cannot call function '~Bar' while mutex 'mu_' is locked}}
3452 Bar::mu_.Unlock();
3453}
3454
3455}; // end namespace ComplexNameTest
DeLesley Hutchins2a237e02012-09-19 19:49:40 +00003456
3457
3458namespace UnreachableExitTest {
3459
3460class FemmeFatale {
3461public:
3462 FemmeFatale();
3463 ~FemmeFatale() __attribute__((noreturn));
3464};
3465
3466void exitNow() __attribute__((noreturn));
DeLesley Hutchinsd2f38822012-09-21 17:57:00 +00003467void exitDestruct(const MyString& ms) __attribute__((noreturn));
DeLesley Hutchins2a237e02012-09-19 19:49:40 +00003468
3469Mutex fatalmu_;
3470
3471void test1() EXCLUSIVE_LOCKS_REQUIRED(fatalmu_) {
3472 exitNow();
3473}
3474
3475void test2() EXCLUSIVE_LOCKS_REQUIRED(fatalmu_) {
3476 FemmeFatale femme;
3477}
3478
3479bool c;
3480
3481void test3() EXCLUSIVE_LOCKS_REQUIRED(fatalmu_) {
3482 if (c) {
3483 exitNow();
3484 }
3485 else {
3486 FemmeFatale femme;
3487 }
3488}
3489
DeLesley Hutchinsd2f38822012-09-21 17:57:00 +00003490void test4() EXCLUSIVE_LOCKS_REQUIRED(fatalmu_) {
3491 exitDestruct("foo");
3492}
3493
DeLesley Hutchins2a237e02012-09-19 19:49:40 +00003494} // end namespace UnreachableExitTest
DeLesley Hutchins186af2d2012-09-20 22:18:02 +00003495
3496
3497namespace VirtualMethodCanonicalizationTest {
3498
3499class Base {
3500public:
3501 virtual Mutex* getMutex() = 0;
3502};
3503
3504class Base2 : public Base {
3505public:
3506 Mutex* getMutex();
3507};
3508
3509class Base3 : public Base2 {
3510public:
3511 Mutex* getMutex();
3512};
3513
3514class Derived : public Base3 {
3515public:
3516 Mutex* getMutex(); // overrides Base::getMutex()
3517};
3518
3519void baseFun(Base *b) EXCLUSIVE_LOCKS_REQUIRED(b->getMutex()) { }
3520
3521void derivedFun(Derived *d) EXCLUSIVE_LOCKS_REQUIRED(d->getMutex()) {
3522 baseFun(d);
3523}
3524
3525} // end namespace VirtualMethodCanonicalizationTest
3526
DeLesley Hutchinsd278dbe2012-09-26 17:57:31 +00003527
3528namespace TemplateFunctionParamRemapTest {
3529
3530template <class T>
3531struct Cell {
3532 T dummy_;
3533 Mutex* mu_;
3534};
3535
3536class Foo {
3537public:
3538 template <class T>
3539 void elr(Cell<T>* c) __attribute__((exclusive_locks_required(c->mu_)));
3540
3541 void test();
3542};
3543
3544template<class T>
3545void Foo::elr(Cell<T>* c1) { }
3546
3547void Foo::test() {
3548 Cell<int> cell;
3549 elr(&cell); // \
3550 // expected-warning {{calling function 'elr' requires exclusive lock on 'cell.mu_'}}
3551}
3552
3553
3554template<class T>
3555void globalELR(Cell<T>* c) __attribute__((exclusive_locks_required(c->mu_)));
3556
3557template<class T>
3558void globalELR(Cell<T>* c1) { }
3559
3560void globalTest() {
3561 Cell<int> cell;
3562 globalELR(&cell); // \
3563 // expected-warning {{calling function 'globalELR' requires exclusive lock on 'cell.mu_'}}
3564}
3565
3566
3567template<class T>
3568void globalELR2(Cell<T>* c) __attribute__((exclusive_locks_required(c->mu_)));
3569
3570// second declaration
3571template<class T>
3572void globalELR2(Cell<T>* c2);
3573
3574template<class T>
3575void globalELR2(Cell<T>* c3) { }
3576
3577// re-declaration after definition
3578template<class T>
3579void globalELR2(Cell<T>* c4);
3580
3581void globalTest2() {
3582 Cell<int> cell;
3583 globalELR2(&cell); // \
3584 // expected-warning {{calling function 'globalELR2' requires exclusive lock on 'cell.mu_'}}
3585}
3586
3587
3588template<class T>
3589class FooT {
3590public:
3591 void elr(Cell<T>* c) __attribute__((exclusive_locks_required(c->mu_)));
3592};
3593
3594template<class T>
3595void FooT<T>::elr(Cell<T>* c1) { }
3596
3597void testFooT() {
3598 Cell<int> cell;
3599 FooT<int> foo;
3600 foo.elr(&cell); // \
3601 // expected-warning {{calling function 'elr' requires exclusive lock on 'cell.mu_'}}
3602}
3603
3604} // end namespace TemplateFunctionParamRemapTest
3605