blob: 19e2aa15fd8eed9cfaa962a6096abd8e8f2d8058 [file] [log] [blame]
DeLesley Hutchins91e20612012-12-05 01:20:45 +00001// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 -Wthread-safety -Wthread-safety-beta %s
DeLesley Hutchins13106112012-07-10 21:47:55 +00002
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
Richard Smith97f9fe02011-10-25 00:41:24 +00001546namespace template_member_test {
DeLesley Hutchinsf1ac6372011-10-21 18:10:14 +00001547
Richard Smith97f9fe02011-10-25 00:41:24 +00001548 struct S { int n; };
1549 struct T {
1550 Mutex m;
1551 S *s GUARDED_BY(this->m);
1552 };
Richard Smitha01c7112011-10-25 06:33:21 +00001553 Mutex m;
1554 struct U {
1555 union {
1556 int n;
1557 };
1558 } *u GUARDED_BY(m);
Richard Smith97f9fe02011-10-25 00:41:24 +00001559
1560 template<typename U>
1561 struct IndirectLock {
1562 int DoNaughtyThings(T *t) {
Richard Smitha01c7112011-10-25 06:33:21 +00001563 u->n = 0; // expected-warning {{reading variable 'u' requires locking 'm'}}
DeLesley Hutchinsa74b7152012-08-10 20:19:55 +00001564 return t->s->n; // expected-warning {{reading variable 's' requires locking 't->m'}}
Richard Smith97f9fe02011-10-25 00:41:24 +00001565 }
1566 };
1567
Richard Smithf11e9232011-10-25 01:05:41 +00001568 template struct IndirectLock<int>; // expected-note {{here}}
Richard Smith97f9fe02011-10-25 00:41:24 +00001569
Richard Smith601d2ee2011-10-26 06:15:36 +00001570 struct V {
1571 void f(int);
1572 void f(double);
1573
1574 Mutex m;
1575 V *p GUARDED_BY(this->m);
1576 };
1577 template<typename U> struct W {
1578 V v;
1579 void f(U u) {
DeLesley Hutchinsa74b7152012-08-10 20:19:55 +00001580 v.p->f(u); // expected-warning {{reading variable 'p' requires locking 'v.m'}}
Richard Smith601d2ee2011-10-26 06:15:36 +00001581 }
1582 };
1583 template struct W<int>; // expected-note {{here}}
1584
Richard Smith97f9fe02011-10-25 00:41:24 +00001585}
DeLesley Hutchins1fa3c062011-12-08 20:23:06 +00001586
1587namespace test_scoped_lockable {
1588
1589struct TestScopedLockable {
1590 Mutex mu1;
1591 Mutex mu2;
1592 int a __attribute__((guarded_by(mu1)));
1593 int b __attribute__((guarded_by(mu2)));
1594
1595 bool getBool();
1596
1597 void foo1() {
1598 MutexLock mulock(&mu1);
1599 a = 5;
1600 }
1601
1602 void foo2() {
1603 ReaderMutexLock mulock1(&mu1);
1604 if (getBool()) {
1605 MutexLock mulock2a(&mu2);
1606 b = a + 1;
1607 }
1608 else {
1609 MutexLock mulock2b(&mu2);
1610 b = a + 2;
1611 }
1612 }
1613
1614 void foo3() {
1615 MutexLock mulock_a(&mu1);
1616 MutexLock mulock_b(&mu1); // \
1617 // expected-warning {{locking 'mu1' that is already locked}}
DeLesley Hutchinsc99a5d82012-06-28 22:42:48 +00001618 }
DeLesley Hutchins1fa3c062011-12-08 20:23:06 +00001619
1620 void foo4() {
1621 MutexLock mulock1(&mu1), mulock2(&mu2);
1622 a = b+1;
1623 b = a+1;
1624 }
1625};
1626
1627} // end namespace test_scoped_lockable
1628
1629
DeLesley Hutchinsdf497822011-12-29 00:56:48 +00001630namespace FunctionAttrTest {
1631
1632class Foo {
1633public:
1634 Mutex mu_;
1635 int a GUARDED_BY(mu_);
1636};
1637
1638Foo fooObj;
1639
1640void foo() EXCLUSIVE_LOCKS_REQUIRED(fooObj.mu_);
1641
1642void bar() {
DeLesley Hutchinsa74b7152012-08-10 20:19:55 +00001643 foo(); // expected-warning {{calling function 'foo' requires exclusive lock on 'fooObj.mu_'}}
DeLesley Hutchinsdf497822011-12-29 00:56:48 +00001644 fooObj.mu_.Lock();
1645 foo();
1646 fooObj.mu_.Unlock();
1647}
1648
1649}; // end namespace FunctionAttrTest
1650
1651
DeLesley Hutchins60ff1982012-09-20 23:14:43 +00001652namespace TryLockTest {
1653
DeLesley Hutchinsb4fa4182012-01-06 19:16:50 +00001654struct TestTryLock {
1655 Mutex mu;
1656 int a GUARDED_BY(mu);
1657 bool cond;
1658
1659 void foo1() {
1660 if (mu.TryLock()) {
1661 a = 1;
1662 mu.Unlock();
1663 }
1664 }
1665
1666 void foo2() {
1667 if (!mu.TryLock()) return;
1668 a = 2;
1669 mu.Unlock();
1670 }
1671
1672 void foo3() {
1673 bool b = mu.TryLock();
1674 if (b) {
1675 a = 3;
1676 mu.Unlock();
1677 }
1678 }
1679
1680 void foo4() {
1681 bool b = mu.TryLock();
1682 if (!b) return;
1683 a = 4;
1684 mu.Unlock();
1685 }
1686
1687 void foo5() {
1688 while (mu.TryLock()) {
1689 a = a + 1;
1690 mu.Unlock();
1691 }
1692 }
1693
1694 void foo6() {
1695 bool b = mu.TryLock();
1696 b = !b;
1697 if (b) return;
1698 a = 6;
1699 mu.Unlock();
1700 }
1701
1702 void foo7() {
1703 bool b1 = mu.TryLock();
1704 bool b2 = !b1;
1705 bool b3 = !b2;
1706 if (b3) {
1707 a = 7;
1708 mu.Unlock();
1709 }
1710 }
1711
1712 // Test use-def chains: join points
1713 void foo8() {
1714 bool b = mu.TryLock();
1715 bool b2 = b;
1716 if (cond)
1717 b = true;
Sylvestre Ledru43e3dee2012-07-31 06:56:50 +00001718 if (b) { // b should be unknown at this point, because of the join point
DeLesley Hutchinsb4fa4182012-01-06 19:16:50 +00001719 a = 8; // expected-warning {{writing variable 'a' requires locking 'mu' exclusively}}
1720 }
1721 if (b2) { // b2 should be known at this point.
1722 a = 8;
1723 mu.Unlock();
1724 }
1725 }
1726
1727 // Test use-def-chains: back edges
1728 void foo9() {
1729 bool b = mu.TryLock();
1730
1731 for (int i = 0; i < 10; ++i);
1732
1733 if (b) { // b is still known, because the loop doesn't alter it
1734 a = 9;
1735 mu.Unlock();
1736 }
1737 }
1738
1739 // Test use-def chains: back edges
1740 void foo10() {
1741 bool b = mu.TryLock();
1742
1743 while (cond) {
1744 if (b) { // b should be uknown at this point b/c of the loop
1745 a = 10; // expected-warning {{writing variable 'a' requires locking 'mu' exclusively}}
1746 }
1747 b = !b;
1748 }
1749 }
DeLesley Hutchins60ff1982012-09-20 23:14:43 +00001750
1751 // Test merge of exclusive trylock
1752 void foo11() {
1753 if (cond) {
1754 if (!mu.TryLock())
1755 return;
1756 }
1757 else {
1758 mu.Lock();
1759 }
1760 a = 10;
1761 mu.Unlock();
1762 }
1763
1764 // Test merge of shared trylock
1765 void foo12() {
1766 if (cond) {
1767 if (!mu.ReaderTryLock())
1768 return;
1769 }
1770 else {
1771 mu.ReaderLock();
1772 }
1773 int i = a;
1774 mu.Unlock();
1775 }
DeLesley Hutchinsb4fa4182012-01-06 19:16:50 +00001776}; // end TestTrylock
1777
DeLesley Hutchins60ff1982012-09-20 23:14:43 +00001778} // end namespace TrylockTest
1779
DeLesley Hutchinsb4fa4182012-01-06 19:16:50 +00001780
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +00001781namespace TestTemplateAttributeInstantiation {
1782
1783class Foo1 {
1784public:
1785 Mutex mu_;
1786 int a GUARDED_BY(mu_);
1787};
1788
1789class Foo2 {
1790public:
1791 int a GUARDED_BY(mu_);
1792 Mutex mu_;
1793};
1794
1795
1796class Bar {
1797public:
1798 // Test non-dependent expressions in attributes on template functions
1799 template <class T>
1800 void barND(Foo1 *foo, T *fooT) EXCLUSIVE_LOCKS_REQUIRED(foo->mu_) {
1801 foo->a = 0;
1802 }
1803
1804 // Test dependent expressions in attributes on template functions
1805 template <class T>
1806 void barD(Foo1 *foo, T *fooT) EXCLUSIVE_LOCKS_REQUIRED(fooT->mu_) {
1807 fooT->a = 0;
1808 }
1809};
1810
1811
1812template <class T>
1813class BarT {
1814public:
1815 Foo1 fooBase;
1816 T fooBaseT;
1817
1818 // Test non-dependent expression in ordinary method on template class
1819 void barND() EXCLUSIVE_LOCKS_REQUIRED(fooBase.mu_) {
1820 fooBase.a = 0;
1821 }
1822
1823 // Test dependent expressions in ordinary methods on template class
1824 void barD() EXCLUSIVE_LOCKS_REQUIRED(fooBaseT.mu_) {
1825 fooBaseT.a = 0;
1826 }
1827
1828 // Test dependent expressions in template method in template class
1829 template <class T2>
1830 void barTD(T2 *fooT) EXCLUSIVE_LOCKS_REQUIRED(fooBaseT.mu_, fooT->mu_) {
1831 fooBaseT.a = 0;
1832 fooT->a = 0;
1833 }
1834};
1835
1836template <class T>
1837class Cell {
1838public:
1839 Mutex mu_;
1840 // Test dependent guarded_by
1841 T data GUARDED_BY(mu_);
1842
DeLesley Hutchins23323e02012-01-20 22:50:54 +00001843 void fooEx() EXCLUSIVE_LOCKS_REQUIRED(mu_) {
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +00001844 data = 0;
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +00001845 }
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +00001846
1847 void foo() {
1848 mu_.Lock();
1849 data = 0;
1850 mu_.Unlock();
1851 }
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +00001852};
1853
1854void test() {
1855 Bar b;
1856 BarT<Foo2> bt;
1857 Foo1 f1;
1858 Foo2 f2;
1859
1860 f1.mu_.Lock();
1861 f2.mu_.Lock();
1862 bt.fooBase.mu_.Lock();
1863 bt.fooBaseT.mu_.Lock();
1864
1865 b.barND(&f1, &f2);
1866 b.barD(&f1, &f2);
1867 bt.barND();
1868 bt.barD();
1869 bt.barTD(&f2);
1870
1871 f1.mu_.Unlock();
1872 bt.barTD(&f1); // \
DeLesley Hutchins3f0ec522012-09-10 19:58:23 +00001873 // expected-warning {{calling function 'barTD' requires exclusive lock on 'f1.mu_'}} \
1874 // expected-note {{found near match 'bt.fooBase.mu_'}}
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +00001875
1876 bt.fooBase.mu_.Unlock();
1877 bt.fooBaseT.mu_.Unlock();
1878 f2.mu_.Unlock();
1879
1880 Cell<int> cell;
1881 cell.data = 0; // \
DeLesley Hutchinsa74b7152012-08-10 20:19:55 +00001882 // expected-warning {{writing variable 'data' requires locking 'cell.mu_' exclusively}}
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +00001883 cell.foo();
DeLesley Hutchins23323e02012-01-20 22:50:54 +00001884 cell.mu_.Lock();
1885 cell.fooEx();
1886 cell.mu_.Unlock();
1887}
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +00001888
DeLesley Hutchins23323e02012-01-20 22:50:54 +00001889
1890template <class T>
1891class CellDelayed {
1892public:
1893 // Test dependent guarded_by
1894 T data GUARDED_BY(mu_);
DeLesley Hutchinsdd5756c2012-02-16 17:30:51 +00001895 static T static_data GUARDED_BY(static_mu_);
DeLesley Hutchins23323e02012-01-20 22:50:54 +00001896
1897 void fooEx(CellDelayed<T> *other) EXCLUSIVE_LOCKS_REQUIRED(mu_, other->mu_) {
1898 this->data = other->data;
1899 }
1900
1901 template <class T2>
1902 void fooExT(CellDelayed<T2> *otherT) EXCLUSIVE_LOCKS_REQUIRED(mu_, otherT->mu_) {
1903 this->data = otherT->data;
1904 }
1905
1906 void foo() {
1907 mu_.Lock();
1908 data = 0;
1909 mu_.Unlock();
1910 }
1911
1912 Mutex mu_;
DeLesley Hutchinsdd5756c2012-02-16 17:30:51 +00001913 static Mutex static_mu_;
DeLesley Hutchins23323e02012-01-20 22:50:54 +00001914};
1915
1916void testDelayed() {
1917 CellDelayed<int> celld;
1918 CellDelayed<int> celld2;
1919 celld.foo();
1920 celld.mu_.Lock();
1921 celld2.mu_.Lock();
1922
1923 celld.fooEx(&celld2);
1924 celld.fooExT(&celld2);
1925
1926 celld2.mu_.Unlock();
1927 celld.mu_.Unlock();
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +00001928}
1929
1930}; // end namespace TestTemplateAttributeInstantiation
1931
1932
DeLesley Hutchinse03b2b32012-01-20 23:24:41 +00001933namespace FunctionDeclDefTest {
1934
1935class Foo {
1936public:
1937 Mutex mu_;
1938 int a GUARDED_BY(mu_);
1939
1940 virtual void foo1(Foo *f_declared) EXCLUSIVE_LOCKS_REQUIRED(f_declared->mu_);
1941};
1942
1943// EXCLUSIVE_LOCKS_REQUIRED should be applied, and rewritten to f_defined->mu_
1944void Foo::foo1(Foo *f_defined) {
1945 f_defined->a = 0;
1946};
1947
1948void test() {
1949 Foo myfoo;
1950 myfoo.foo1(&myfoo); // \
DeLesley Hutchinsa74b7152012-08-10 20:19:55 +00001951 // expected-warning {{calling function 'foo1' requires exclusive lock on 'myfoo.mu_'}}
DeLesley Hutchinse03b2b32012-01-20 23:24:41 +00001952 myfoo.mu_.Lock();
1953 myfoo.foo1(&myfoo);
1954 myfoo.mu_.Unlock();
1955}
1956
1957};
Richard Smith2e515622012-02-03 04:45:26 +00001958
1959namespace GoingNative {
1960
1961 struct __attribute__((lockable)) mutex {
1962 void lock() __attribute__((exclusive_lock_function));
1963 void unlock() __attribute__((unlock_function));
1964 // ...
1965 };
1966 bool foo();
1967 bool bar();
1968 mutex m;
1969 void test() {
1970 m.lock();
1971 while (foo()) {
1972 m.unlock();
1973 // ...
1974 if (bar()) {
1975 // ...
1976 if (foo())
1977 continue; // expected-warning {{expecting mutex 'm' to be locked at start of each loop}}
1978 //...
1979 }
1980 // ...
1981 m.lock(); // expected-note {{mutex acquired here}}
1982 }
1983 m.unlock();
1984 }
1985
1986}
DeLesley Hutchinsc24a2332012-02-16 16:50:43 +00001987
1988
1989
1990namespace FunctionDefinitionTest {
1991
1992class Foo {
1993public:
1994 void foo1();
1995 void foo2();
1996 void foo3(Foo *other);
1997
1998 template<class T>
1999 void fooT1(const T& dummy1);
2000
2001 template<class T>
2002 void fooT2(const T& dummy2) EXCLUSIVE_LOCKS_REQUIRED(mu_);
2003
2004 Mutex mu_;
2005 int a GUARDED_BY(mu_);
2006};
2007
2008template<class T>
2009class FooT {
2010public:
2011 void foo();
2012
2013 Mutex mu_;
2014 T a GUARDED_BY(mu_);
2015};
2016
2017
2018void Foo::foo1() NO_THREAD_SAFETY_ANALYSIS {
2019 a = 1;
2020}
2021
2022void Foo::foo2() EXCLUSIVE_LOCKS_REQUIRED(mu_) {
2023 a = 2;
2024}
2025
2026void Foo::foo3(Foo *other) EXCLUSIVE_LOCKS_REQUIRED(other->mu_) {
2027 other->a = 3;
2028}
2029
2030template<class T>
2031void Foo::fooT1(const T& dummy1) EXCLUSIVE_LOCKS_REQUIRED(mu_) {
2032 a = dummy1;
2033}
2034
2035/* TODO -- uncomment with template instantiation of attributes.
2036template<class T>
2037void Foo::fooT2(const T& dummy2) {
2038 a = dummy2;
2039}
2040*/
2041
2042void fooF1(Foo *f) EXCLUSIVE_LOCKS_REQUIRED(f->mu_) {
2043 f->a = 1;
2044}
2045
2046void fooF2(Foo *f);
2047void fooF2(Foo *f) EXCLUSIVE_LOCKS_REQUIRED(f->mu_) {
2048 f->a = 2;
2049}
2050
2051void fooF3(Foo *f) EXCLUSIVE_LOCKS_REQUIRED(f->mu_);
2052void fooF3(Foo *f) {
2053 f->a = 3;
2054}
2055
2056template<class T>
2057void FooT<T>::foo() EXCLUSIVE_LOCKS_REQUIRED(mu_) {
2058 a = 0;
2059}
2060
2061void test() {
2062 int dummy = 0;
2063 Foo myFoo;
2064
2065 myFoo.foo2(); // \
DeLesley Hutchinsa74b7152012-08-10 20:19:55 +00002066 // expected-warning {{calling function 'foo2' requires exclusive lock on 'myFoo.mu_'}}
DeLesley Hutchinsc24a2332012-02-16 16:50:43 +00002067 myFoo.foo3(&myFoo); // \
DeLesley Hutchinsa74b7152012-08-10 20:19:55 +00002068 // expected-warning {{calling function 'foo3' requires exclusive lock on 'myFoo.mu_'}}
DeLesley Hutchinsc24a2332012-02-16 16:50:43 +00002069 myFoo.fooT1(dummy); // \
DeLesley Hutchinsa74b7152012-08-10 20:19:55 +00002070 // expected-warning {{calling function 'fooT1' requires exclusive lock on 'myFoo.mu_'}}
DeLesley Hutchinsc24a2332012-02-16 16:50:43 +00002071
DeLesley Hutchinsa74b7152012-08-10 20:19:55 +00002072 myFoo.fooT2(dummy); // \
2073 // expected-warning {{calling function 'fooT2' requires exclusive lock on 'myFoo.mu_'}}
DeLesley Hutchinsc24a2332012-02-16 16:50:43 +00002074
2075 fooF1(&myFoo); // \
DeLesley Hutchinsa74b7152012-08-10 20:19:55 +00002076 // expected-warning {{calling function 'fooF1' requires exclusive lock on 'myFoo.mu_'}}
DeLesley Hutchinsc24a2332012-02-16 16:50:43 +00002077 fooF2(&myFoo); // \
DeLesley Hutchinsa74b7152012-08-10 20:19:55 +00002078 // expected-warning {{calling function 'fooF2' requires exclusive lock on 'myFoo.mu_'}}
DeLesley Hutchinsc24a2332012-02-16 16:50:43 +00002079 fooF3(&myFoo); // \
DeLesley Hutchinsa74b7152012-08-10 20:19:55 +00002080 // expected-warning {{calling function 'fooF3' requires exclusive lock on 'myFoo.mu_'}}
DeLesley Hutchinsc24a2332012-02-16 16:50:43 +00002081
2082 myFoo.mu_.Lock();
2083 myFoo.foo2();
2084 myFoo.foo3(&myFoo);
2085 myFoo.fooT1(dummy);
2086
DeLesley Hutchinsa74b7152012-08-10 20:19:55 +00002087 myFoo.fooT2(dummy);
DeLesley Hutchinsc24a2332012-02-16 16:50:43 +00002088
2089 fooF1(&myFoo);
2090 fooF2(&myFoo);
2091 fooF3(&myFoo);
2092 myFoo.mu_.Unlock();
2093
2094 FooT<int> myFooT;
2095 myFooT.foo(); // \
DeLesley Hutchinsa74b7152012-08-10 20:19:55 +00002096 // expected-warning {{calling function 'foo' requires exclusive lock on 'myFooT.mu_'}}
DeLesley Hutchinsc24a2332012-02-16 16:50:43 +00002097}
2098
DeLesley Hutchins4bda3ec2012-02-16 17:03:24 +00002099} // end namespace FunctionDefinitionTest
2100
2101
2102namespace SelfLockingTest {
2103
2104class LOCKABLE MyLock {
2105public:
2106 int foo GUARDED_BY(this);
2107
2108 void lock() EXCLUSIVE_LOCK_FUNCTION();
2109 void unlock() UNLOCK_FUNCTION();
2110
2111 void doSomething() {
2112 this->lock(); // allow 'this' as a lock expression
2113 foo = 0;
2114 doSomethingElse();
2115 this->unlock();
2116 }
2117
2118 void doSomethingElse() EXCLUSIVE_LOCKS_REQUIRED(this) {
2119 foo = 1;
2120 };
2121
2122 void test() {
2123 foo = 2; // \
2124 // expected-warning {{writing variable 'foo' requires locking 'this' exclusively}}
2125 }
DeLesley Hutchinsc24a2332012-02-16 16:50:43 +00002126};
2127
DeLesley Hutchins2f13bec2012-02-16 17:13:43 +00002128
2129class LOCKABLE MyLock2 {
2130public:
2131 Mutex mu_;
2132 int foo GUARDED_BY(this);
2133
2134 // don't check inside lock and unlock functions
2135 void lock() EXCLUSIVE_LOCK_FUNCTION() { mu_.Lock(); }
2136 void unlock() UNLOCK_FUNCTION() { mu_.Unlock(); }
2137
2138 // don't check inside constructors and destructors
2139 MyLock2() { foo = 1; }
2140 ~MyLock2() { foo = 0; }
2141};
2142
2143
DeLesley Hutchins4bda3ec2012-02-16 17:03:24 +00002144} // end namespace SelfLockingTest
2145
2146
DeLesley Hutchinsd08d5992012-02-25 00:11:55 +00002147namespace InvalidNonstatic {
2148
2149// Forward decl here causes bogus "invalid use of non-static data member"
2150// on reference to mutex_ in guarded_by attribute.
2151class Foo;
2152
2153class Foo {
2154 Mutex* mutex_;
2155
2156 int foo __attribute__((guarded_by(mutex_)));
2157};
2158
2159} // end namespace InvalidNonStatic
2160
DeLesley Hutchins2a35be82012-03-02 22:02:58 +00002161
2162namespace NoReturnTest {
2163
2164bool condition();
2165void fatal() __attribute__((noreturn));
2166
2167Mutex mu_;
2168
2169void test1() {
2170 MutexLock lock(&mu_);
2171 if (condition()) {
2172 fatal();
2173 return;
2174 }
2175}
2176
DeLesley Hutchins2287c5e2012-03-02 22:12:59 +00002177} // end namespace NoReturnTest
2178
2179
2180namespace TestMultiDecl {
2181
2182class Foo {
2183public:
2184 int GUARDED_BY(mu_) a;
2185 int GUARDED_BY(mu_) b, c;
2186
2187 void foo() {
2188 a = 0; // \
2189 // expected-warning {{writing variable 'a' requires locking 'mu_' exclusively}}
2190 b = 0; // \
2191 // expected-warning {{writing variable 'b' requires locking 'mu_' exclusively}}
2192 c = 0; // \
2193 // expected-warning {{writing variable 'c' requires locking 'mu_' exclusively}}
2194 }
2195
2196private:
2197 Mutex mu_;
DeLesley Hutchins2a35be82012-03-02 22:02:58 +00002198};
DeLesley Hutchins2287c5e2012-03-02 22:12:59 +00002199
2200} // end namespace TestMultiDecl
2201
DeLesley Hutchins7ec419a2012-03-02 22:29:50 +00002202
2203namespace WarnNoDecl {
2204
2205class Foo {
2206 void foo(int a); __attribute__(( // \
2207 // expected-warning {{declaration does not declare anything}}
2208 exclusive_locks_required(a))); // \
2209 // expected-warning {{attribute exclusive_locks_required ignored}}
2210};
2211
2212} // end namespace WarnNoDecl
2213
2214
DeLesley Hutchins0d95dfc2012-03-02 23:36:05 +00002215
2216namespace MoreLockExpressions {
2217
2218class Foo {
2219public:
2220 Mutex mu_;
2221 int a GUARDED_BY(mu_);
2222};
2223
2224class Bar {
2225public:
2226 int b;
2227 Foo* f;
2228
2229 Foo& getFoo() { return *f; }
2230 Foo& getFoo2(int c) { return *f; }
2231 Foo& getFoo3(int c, int d) { return *f; }
2232
2233 Foo& getFooey() { return *f; }
2234};
2235
2236Foo& getBarFoo(Bar &bar, int c) { return bar.getFoo2(c); }
2237
2238void test() {
2239 Foo foo;
2240 Foo *fooArray;
2241 Bar bar;
2242 int a;
2243 int b;
2244 int c;
2245
2246 bar.getFoo().mu_.Lock();
2247 bar.getFoo().a = 0;
2248 bar.getFoo().mu_.Unlock();
2249
2250 (bar.getFoo().mu_).Lock(); // test parenthesis
2251 bar.getFoo().a = 0;
2252 (bar.getFoo().mu_).Unlock();
2253
2254 bar.getFoo2(a).mu_.Lock();
2255 bar.getFoo2(a).a = 0;
2256 bar.getFoo2(a).mu_.Unlock();
2257
2258 bar.getFoo3(a, b).mu_.Lock();
2259 bar.getFoo3(a, b).a = 0;
2260 bar.getFoo3(a, b).mu_.Unlock();
2261
2262 getBarFoo(bar, a).mu_.Lock();
2263 getBarFoo(bar, a).a = 0;
2264 getBarFoo(bar, a).mu_.Unlock();
2265
2266 bar.getFoo2(10).mu_.Lock();
2267 bar.getFoo2(10).a = 0;
2268 bar.getFoo2(10).mu_.Unlock();
2269
2270 bar.getFoo2(a + 1).mu_.Lock();
2271 bar.getFoo2(a + 1).a = 0;
2272 bar.getFoo2(a + 1).mu_.Unlock();
2273
2274 (a > 0 ? fooArray[1] : fooArray[b]).mu_.Lock();
2275 (a > 0 ? fooArray[1] : fooArray[b]).a = 0;
2276 (a > 0 ? fooArray[1] : fooArray[b]).mu_.Unlock();
2277
2278 bar.getFoo().mu_.Lock();
2279 bar.getFooey().a = 0; // \
DeLesley Hutchins3f0ec522012-09-10 19:58:23 +00002280 // expected-warning {{writing variable 'a' requires locking 'bar.getFooey().mu_' exclusively}} \
2281 // expected-note {{found near match 'bar.getFoo().mu_'}}
DeLesley Hutchins0d95dfc2012-03-02 23:36:05 +00002282 bar.getFoo().mu_.Unlock();
2283
2284 bar.getFoo2(a).mu_.Lock();
2285 bar.getFoo2(b).a = 0; // \
DeLesley Hutchins3f0ec522012-09-10 19:58:23 +00002286 // expected-warning {{writing variable 'a' requires locking 'bar.getFoo2(b).mu_' exclusively}} \
2287 // expected-note {{found near match 'bar.getFoo2(a).mu_'}}
DeLesley Hutchins0d95dfc2012-03-02 23:36:05 +00002288 bar.getFoo2(a).mu_.Unlock();
2289
2290 bar.getFoo3(a, b).mu_.Lock();
2291 bar.getFoo3(a, c).a = 0; // \
DeLesley Hutchins3f0ec522012-09-10 19:58:23 +00002292 // expected-warning {{writing variable 'a' requires locking 'bar.getFoo3(a,c).mu_' exclusively}} \
2293 // expected-note {{'bar.getFoo3(a,b).mu_'}}
DeLesley Hutchins0d95dfc2012-03-02 23:36:05 +00002294 bar.getFoo3(a, b).mu_.Unlock();
2295
2296 getBarFoo(bar, a).mu_.Lock();
2297 getBarFoo(bar, b).a = 0; // \
DeLesley Hutchins3f0ec522012-09-10 19:58:23 +00002298 // expected-warning {{writing variable 'a' requires locking 'getBarFoo(bar,b).mu_' exclusively}} \
2299 // expected-note {{'getBarFoo(bar,a).mu_'}}
DeLesley Hutchins0d95dfc2012-03-02 23:36:05 +00002300 getBarFoo(bar, a).mu_.Unlock();
2301
2302 (a > 0 ? fooArray[1] : fooArray[b]).mu_.Lock();
2303 (a > 0 ? fooArray[b] : fooArray[c]).a = 0; // \
DeLesley Hutchins3f0ec522012-09-10 19:58:23 +00002304 // expected-warning {{writing variable 'a' requires locking '((a#_)#_#fooArray[b]).mu_' exclusively}} \
2305 // expected-note {{'((a#_)#_#fooArray[_]).mu_'}}
DeLesley Hutchins0d95dfc2012-03-02 23:36:05 +00002306 (a > 0 ? fooArray[1] : fooArray[b]).mu_.Unlock();
2307}
2308
2309
DeLesley Hutchins0da44142012-06-22 17:07:28 +00002310} // end namespace MoreLockExpressions
2311
2312
2313namespace TrylockJoinPoint {
2314
2315class Foo {
2316 Mutex mu;
2317 bool c;
2318
2319 void foo() {
2320 if (c) {
2321 if (!mu.TryLock())
2322 return;
2323 } else {
2324 mu.Lock();
2325 }
2326 mu.Unlock();
2327 }
2328};
2329
2330} // end namespace TrylockJoinPoint
DeLesley Hutchins0d95dfc2012-03-02 23:36:05 +00002331
2332
DeLesley Hutchinsf63797c2012-06-25 18:33:18 +00002333namespace LockReturned {
2334
2335class Foo {
2336public:
2337 int a GUARDED_BY(mu_);
2338 void foo() EXCLUSIVE_LOCKS_REQUIRED(mu_);
2339 void foo2(Foo* f) EXCLUSIVE_LOCKS_REQUIRED(mu_, f->mu_);
2340
2341 static void sfoo(Foo* f) EXCLUSIVE_LOCKS_REQUIRED(f->mu_);
2342
2343 Mutex* getMu() LOCK_RETURNED(mu_);
2344
2345 Mutex mu_;
2346
2347 static Mutex* getMu(Foo* f) LOCK_RETURNED(f->mu_);
2348};
2349
2350
2351// Calls getMu() directly to lock and unlock
2352void test1(Foo* f1, Foo* f2) {
DeLesley Hutchinsa74b7152012-08-10 20:19:55 +00002353 f1->a = 0; // expected-warning {{writing variable 'a' requires locking 'f1->mu_' exclusively}}
2354 f1->foo(); // expected-warning {{calling function 'foo' requires exclusive lock on 'f1->mu_'}}
DeLesley Hutchinsf63797c2012-06-25 18:33:18 +00002355
DeLesley Hutchinsa74b7152012-08-10 20:19:55 +00002356 f1->foo2(f2); // expected-warning {{calling function 'foo2' requires exclusive lock on 'f1->mu_'}} \
2357 // expected-warning {{calling function 'foo2' requires exclusive lock on 'f2->mu_'}}
2358 Foo::sfoo(f1); // expected-warning {{calling function 'sfoo' requires exclusive lock on 'f1->mu_'}}
DeLesley Hutchinsf63797c2012-06-25 18:33:18 +00002359
2360 f1->getMu()->Lock();
2361
2362 f1->a = 0;
2363 f1->foo();
DeLesley Hutchins3f0ec522012-09-10 19:58:23 +00002364 f1->foo2(f2); // \
2365 // expected-warning {{calling function 'foo2' requires exclusive lock on 'f2->mu_'}} \
2366 // expected-note {{found near match 'f1->mu_'}}
DeLesley Hutchinsf63797c2012-06-25 18:33:18 +00002367
2368 Foo::getMu(f2)->Lock();
2369 f1->foo2(f2);
2370 Foo::getMu(f2)->Unlock();
2371
2372 Foo::sfoo(f1);
2373
2374 f1->getMu()->Unlock();
2375}
2376
2377
2378Mutex* getFooMu(Foo* f) LOCK_RETURNED(Foo::getMu(f));
2379
2380class Bar : public Foo {
2381public:
2382 int b GUARDED_BY(getMu());
2383 void bar() EXCLUSIVE_LOCKS_REQUIRED(getMu());
2384 void bar2(Bar* g) EXCLUSIVE_LOCKS_REQUIRED(getMu(this), g->getMu());
2385
2386 static void sbar(Bar* g) EXCLUSIVE_LOCKS_REQUIRED(g->getMu());
2387 static void sbar2(Bar* g) EXCLUSIVE_LOCKS_REQUIRED(getFooMu(g));
2388};
2389
2390
2391
2392// Use getMu() within other attributes.
2393// This requires at lest levels of substitution, more in the case of
2394void test2(Bar* b1, Bar* b2) {
DeLesley Hutchinsa74b7152012-08-10 20:19:55 +00002395 b1->b = 0; // expected-warning {{writing variable 'b' requires locking 'b1->mu_' exclusively}}
2396 b1->bar(); // expected-warning {{calling function 'bar' requires exclusive lock on 'b1->mu_'}}
2397 b1->bar2(b2); // expected-warning {{calling function 'bar2' requires exclusive lock on 'b1->mu_'}} \
2398 // expected-warning {{calling function 'bar2' requires exclusive lock on 'b2->mu_'}}
2399 Bar::sbar(b1); // expected-warning {{calling function 'sbar' requires exclusive lock on 'b1->mu_'}}
2400 Bar::sbar2(b1); // expected-warning {{calling function 'sbar2' requires exclusive lock on 'b1->mu_'}}
DeLesley Hutchinsf63797c2012-06-25 18:33:18 +00002401
2402 b1->getMu()->Lock();
2403
2404 b1->b = 0;
2405 b1->bar();
DeLesley Hutchins3f0ec522012-09-10 19:58:23 +00002406 b1->bar2(b2); // \
2407 // expected-warning {{calling function 'bar2' requires exclusive lock on 'b2->mu_'}} \
2408 // // expected-note {{found near match 'b1->mu_'}}
DeLesley Hutchinsf63797c2012-06-25 18:33:18 +00002409
2410 b2->getMu()->Lock();
2411 b1->bar2(b2);
2412
2413 b2->getMu()->Unlock();
2414
2415 Bar::sbar(b1);
2416 Bar::sbar2(b1);
2417
2418 b1->getMu()->Unlock();
2419}
2420
2421
2422// Sanity check -- lock the mutex directly, but use attributes that call getMu()
2423// Also lock the mutex using getFooMu, which calls a lock_returned function.
2424void test3(Bar* b1, Bar* b2) {
2425 b1->mu_.Lock();
2426 b1->b = 0;
2427 b1->bar();
2428
2429 getFooMu(b2)->Lock();
2430 b1->bar2(b2);
2431 getFooMu(b2)->Unlock();
2432
2433 Bar::sbar(b1);
2434 Bar::sbar2(b1);
2435
2436 b1->mu_.Unlock();
2437}
2438
2439} // end namespace LockReturned
2440
2441
DeLesley Hutchinsc99a5d82012-06-28 22:42:48 +00002442namespace ReleasableScopedLock {
2443
2444class Foo {
2445 Mutex mu_;
2446 bool c;
2447 int a GUARDED_BY(mu_);
2448
2449 void test1();
2450 void test2();
2451 void test3();
DeLesley Hutchins5381c052012-07-05 21:16:29 +00002452 void test4();
2453 void test5();
DeLesley Hutchinsc99a5d82012-06-28 22:42:48 +00002454};
2455
2456
2457void Foo::test1() {
2458 ReleasableMutexLock rlock(&mu_);
2459 rlock.Release();
2460}
2461
2462void Foo::test2() {
2463 ReleasableMutexLock rlock(&mu_);
2464 if (c) { // test join point -- held/not held during release
2465 rlock.Release();
2466 }
2467}
2468
2469void Foo::test3() {
2470 ReleasableMutexLock rlock(&mu_);
2471 a = 0;
2472 rlock.Release();
2473 a = 1; // expected-warning {{writing variable 'a' requires locking 'mu_' exclusively}}
2474}
2475
DeLesley Hutchins5381c052012-07-05 21:16:29 +00002476void Foo::test4() {
2477 ReleasableMutexLock rlock(&mu_);
2478 rlock.Release();
2479 rlock.Release(); // expected-warning {{unlocking 'mu_' that was not locked}}
2480}
2481
2482void Foo::test5() {
2483 ReleasableMutexLock rlock(&mu_);
2484 if (c) {
2485 rlock.Release();
2486 }
2487 // no warning on join point for managed lock.
2488 rlock.Release(); // expected-warning {{unlocking 'mu_' that was not locked}}
2489}
2490
2491
DeLesley Hutchinsc99a5d82012-06-28 22:42:48 +00002492} // end namespace ReleasableScopedLock
2493
2494
DeLesley Hutchins76f0a6e2012-07-02 21:59:24 +00002495namespace TrylockFunctionTest {
2496
2497class Foo {
2498public:
2499 Mutex mu1_;
2500 Mutex mu2_;
2501 bool c;
2502
2503 bool lockBoth() EXCLUSIVE_TRYLOCK_FUNCTION(true, mu1_, mu2_);
2504};
2505
2506bool Foo::lockBoth() {
2507 if (!mu1_.TryLock())
2508 return false;
2509
2510 mu2_.Lock();
2511 if (!c) {
2512 mu1_.Unlock();
2513 mu2_.Unlock();
2514 return false;
2515 }
2516
2517 return true;
2518}
2519
2520
2521} // end namespace TrylockFunctionTest
DeLesley Hutchinsc99a5d82012-06-28 22:42:48 +00002522
2523
2524
DeLesley Hutchinsc36eda12012-07-02 22:12:12 +00002525namespace DoubleLockBug {
2526
2527class Foo {
2528public:
2529 Mutex mu_;
2530 int a GUARDED_BY(mu_);
2531
DeLesley Hutchins5381c052012-07-05 21:16:29 +00002532 void foo1() EXCLUSIVE_LOCKS_REQUIRED(mu_);
2533 int foo2() SHARED_LOCKS_REQUIRED(mu_);
DeLesley Hutchinsc36eda12012-07-02 22:12:12 +00002534};
2535
2536
DeLesley Hutchins5381c052012-07-05 21:16:29 +00002537void Foo::foo1() EXCLUSIVE_LOCKS_REQUIRED(mu_) {
DeLesley Hutchinsc36eda12012-07-02 22:12:12 +00002538 a = 0;
2539}
2540
DeLesley Hutchins5381c052012-07-05 21:16:29 +00002541int Foo::foo2() SHARED_LOCKS_REQUIRED(mu_) {
2542 return a;
2543}
2544
2545}
2546
DeLesley Hutchinsc36eda12012-07-02 22:12:12 +00002547
2548
DeLesley Hutchins879a4332012-07-02 22:16:54 +00002549namespace UnlockBug {
DeLesley Hutchinsc36eda12012-07-02 22:12:12 +00002550
DeLesley Hutchins879a4332012-07-02 22:16:54 +00002551class Foo {
2552public:
2553 Mutex mutex_;
2554
2555 void foo1() EXCLUSIVE_LOCKS_REQUIRED(mutex_) { // expected-note {{mutex acquired here}}
2556 mutex_.Unlock();
2557 } // expected-warning {{expecting mutex 'mutex_' to be locked at the end of function}}
2558
2559
2560 void foo2() SHARED_LOCKS_REQUIRED(mutex_) { // expected-note {{mutex acquired here}}
2561 mutex_.Unlock();
2562 } // expected-warning {{expecting mutex 'mutex_' to be locked at the end of function}}
2563};
2564
2565} // end namespace UnlockBug
DeLesley Hutchinsc36eda12012-07-02 22:12:12 +00002566
DeLesley Hutchinsc99a5d82012-06-28 22:42:48 +00002567
DeLesley Hutchins5381c052012-07-05 21:16:29 +00002568
DeLesley Hutchinsbbe33412012-07-02 22:26:29 +00002569namespace FoolishScopedLockableBug {
2570
2571class SCOPED_LOCKABLE WTF_ScopedLockable {
2572public:
2573 WTF_ScopedLockable(Mutex* mu) EXCLUSIVE_LOCK_FUNCTION(mu);
2574
2575 // have to call release() manually;
2576 ~WTF_ScopedLockable();
2577
2578 void release() UNLOCK_FUNCTION();
2579};
2580
2581
2582class Foo {
2583 Mutex mu_;
2584 int a GUARDED_BY(mu_);
2585 bool c;
2586
2587 void doSomething();
2588
2589 void test1() {
2590 WTF_ScopedLockable wtf(&mu_);
2591 wtf.release();
2592 }
2593
2594 void test2() {
2595 WTF_ScopedLockable wtf(&mu_); // expected-note {{mutex acquired here}}
2596 } // expected-warning {{mutex 'mu_' is still locked at the end of function}}
2597
2598 void test3() {
2599 if (c) {
2600 WTF_ScopedLockable wtf(&mu_);
2601 wtf.release();
2602 }
2603 }
2604
2605 void test4() {
2606 if (c) {
2607 doSomething();
2608 }
2609 else {
2610 WTF_ScopedLockable wtf(&mu_);
2611 wtf.release();
2612 }
2613 }
2614
2615 void test5() {
2616 if (c) {
2617 WTF_ScopedLockable wtf(&mu_); // expected-note {{mutex acquired here}}
2618 }
2619 } // expected-warning {{mutex 'mu_' is not locked on every path through here}}
2620
2621 void test6() {
2622 if (c) {
2623 doSomething();
2624 }
2625 else {
2626 WTF_ScopedLockable wtf(&mu_); // expected-note {{mutex acquired here}}
2627 }
2628 } // expected-warning {{mutex 'mu_' is not locked on every path through here}}
2629};
2630
2631
2632} // end namespace FoolishScopedLockableBug
2633
DeLesley Hutchins9d6e7f32012-07-03 18:25:56 +00002634
DeLesley Hutchins5381c052012-07-05 21:16:29 +00002635
DeLesley Hutchins9d6e7f32012-07-03 18:25:56 +00002636namespace TemporaryCleanupExpr {
2637
2638class Foo {
2639 int a GUARDED_BY(getMutexPtr().get());
2640
2641 SmartPtr<Mutex> getMutexPtr();
2642
2643 void test();
2644};
2645
2646
2647void Foo::test() {
2648 {
2649 ReaderMutexLock lock(getMutexPtr().get());
2650 int b = a;
DeLesley Hutchins96fac6a2012-07-03 19:47:18 +00002651 }
DeLesley Hutchinsa74b7152012-08-10 20:19:55 +00002652 int b = a; // expected-warning {{reading variable 'a' requires locking 'getMutexPtr()'}}
DeLesley Hutchins9d6e7f32012-07-03 18:25:56 +00002653}
2654
2655} // end namespace TemporaryCleanupExpr
2656
2657
DeLesley Hutchins96fac6a2012-07-03 19:47:18 +00002658
2659namespace SmartPointerTests {
2660
2661class Foo {
2662public:
2663 SmartPtr<Mutex> mu_;
2664 int a GUARDED_BY(mu_);
2665 int b GUARDED_BY(mu_.get());
2666 int c GUARDED_BY(*mu_);
2667
2668 void Lock() EXCLUSIVE_LOCK_FUNCTION(mu_);
2669 void Unlock() UNLOCK_FUNCTION(mu_);
2670
2671 void test0();
2672 void test1();
2673 void test2();
2674 void test3();
2675 void test4();
2676 void test5();
2677 void test6();
2678 void test7();
2679 void test8();
2680};
2681
2682void Foo::test0() {
2683 a = 0; // expected-warning {{writing variable 'a' requires locking 'mu_' exclusively}}
2684 b = 0; // expected-warning {{writing variable 'b' requires locking 'mu_' exclusively}}
2685 c = 0; // expected-warning {{writing variable 'c' requires locking 'mu_' exclusively}}
2686}
2687
2688void Foo::test1() {
2689 mu_->Lock();
2690 a = 0;
2691 b = 0;
2692 c = 0;
2693 mu_->Unlock();
2694}
2695
2696void Foo::test2() {
2697 (*mu_).Lock();
2698 a = 0;
2699 b = 0;
2700 c = 0;
2701 (*mu_).Unlock();
2702}
2703
2704
2705void Foo::test3() {
2706 mu_.get()->Lock();
2707 a = 0;
2708 b = 0;
2709 c = 0;
2710 mu_.get()->Unlock();
2711}
2712
2713
2714void Foo::test4() {
2715 MutexLock lock(mu_.get());
2716 a = 0;
2717 b = 0;
2718 c = 0;
2719}
2720
2721
2722void Foo::test5() {
2723 MutexLock lock(&(*mu_));
2724 a = 0;
2725 b = 0;
2726 c = 0;
2727}
2728
2729
2730void Foo::test6() {
2731 Lock();
2732 a = 0;
2733 b = 0;
2734 c = 0;
2735 Unlock();
2736}
2737
2738
2739void Foo::test7() {
2740 {
2741 Lock();
2742 mu_->Unlock();
2743 }
2744 {
2745 mu_->Lock();
2746 Unlock();
2747 }
2748 {
2749 mu_.get()->Lock();
2750 mu_->Unlock();
2751 }
2752 {
2753 mu_->Lock();
2754 mu_.get()->Unlock();
2755 }
2756 {
2757 mu_.get()->Lock();
2758 (*mu_).Unlock();
2759 }
2760 {
2761 (*mu_).Lock();
2762 mu_->Unlock();
2763 }
2764}
2765
2766
2767void Foo::test8() {
2768 mu_->Lock();
2769 mu_.get()->Lock(); // expected-warning {{locking 'mu_' that is already locked}}
2770 (*mu_).Lock(); // expected-warning {{locking 'mu_' that is already locked}}
2771 mu_.get()->Unlock();
2772 Unlock(); // expected-warning {{unlocking 'mu_' that was not locked}}
2773}
2774
2775
2776class Bar {
2777 SmartPtr<Foo> foo;
2778
2779 void test0();
2780 void test1();
2781 void test2();
2782 void test3();
2783};
2784
2785
2786void Bar::test0() {
DeLesley Hutchinsa74b7152012-08-10 20:19:55 +00002787 foo->a = 0; // expected-warning {{writing variable 'a' requires locking 'foo->mu_' exclusively}}
2788 (*foo).b = 0; // expected-warning {{writing variable 'b' requires locking 'foo->mu_' exclusively}}
2789 foo.get()->c = 0; // expected-warning {{writing variable 'c' requires locking 'foo->mu_' exclusively}}
DeLesley Hutchins96fac6a2012-07-03 19:47:18 +00002790}
2791
2792
2793void Bar::test1() {
2794 foo->mu_->Lock();
2795 foo->a = 0;
2796 (*foo).b = 0;
2797 foo.get()->c = 0;
2798 foo->mu_->Unlock();
2799}
2800
2801
2802void Bar::test2() {
2803 (*foo).mu_->Lock();
2804 foo->a = 0;
2805 (*foo).b = 0;
2806 foo.get()->c = 0;
2807 foo.get()->mu_->Unlock();
2808}
2809
2810
2811void Bar::test3() {
2812 MutexLock lock(foo->mu_.get());
2813 foo->a = 0;
2814 (*foo).b = 0;
2815 foo.get()->c = 0;
2816}
2817
2818} // end namespace SmartPointerTests
2819
2820
2821
DeLesley Hutchins5381c052012-07-05 21:16:29 +00002822namespace DuplicateAttributeTest {
2823
2824class LOCKABLE Foo {
2825public:
2826 Mutex mu1_;
2827 Mutex mu2_;
2828 Mutex mu3_;
2829 int a GUARDED_BY(mu1_);
2830 int b GUARDED_BY(mu2_);
2831 int c GUARDED_BY(mu3_);
2832
2833 void lock() EXCLUSIVE_LOCK_FUNCTION();
2834 void unlock() UNLOCK_FUNCTION();
2835
2836 void lock1() EXCLUSIVE_LOCK_FUNCTION(mu1_);
2837 void slock1() SHARED_LOCK_FUNCTION(mu1_);
2838 void lock3() EXCLUSIVE_LOCK_FUNCTION(mu1_, mu2_, mu3_);
2839 void locklots()
2840 EXCLUSIVE_LOCK_FUNCTION(mu1_)
2841 EXCLUSIVE_LOCK_FUNCTION(mu2_)
2842 EXCLUSIVE_LOCK_FUNCTION(mu1_, mu2_, mu3_);
2843
2844 void unlock1() UNLOCK_FUNCTION(mu1_);
2845 void unlock3() UNLOCK_FUNCTION(mu1_, mu2_, mu3_);
2846 void unlocklots()
2847 UNLOCK_FUNCTION(mu1_)
2848 UNLOCK_FUNCTION(mu2_)
2849 UNLOCK_FUNCTION(mu1_, mu2_, mu3_);
2850};
2851
2852
2853void Foo::lock() EXCLUSIVE_LOCK_FUNCTION() { }
2854void Foo::unlock() UNLOCK_FUNCTION() { }
2855
2856void Foo::lock1() EXCLUSIVE_LOCK_FUNCTION(mu1_) {
2857 mu1_.Lock();
2858}
2859
2860void Foo::slock1() SHARED_LOCK_FUNCTION(mu1_) {
2861 mu1_.Lock();
2862}
2863
2864void Foo::lock3() EXCLUSIVE_LOCK_FUNCTION(mu1_, mu2_, mu3_) {
2865 mu1_.Lock();
2866 mu2_.Lock();
2867 mu3_.Lock();
2868}
2869
2870void Foo::locklots()
2871 EXCLUSIVE_LOCK_FUNCTION(mu1_, mu2_)
2872 EXCLUSIVE_LOCK_FUNCTION(mu2_, mu3_) {
2873 mu1_.Lock();
2874 mu2_.Lock();
2875 mu3_.Lock();
2876}
2877
2878void Foo::unlock1() UNLOCK_FUNCTION(mu1_) {
2879 mu1_.Unlock();
2880}
2881
2882void Foo::unlock3() UNLOCK_FUNCTION(mu1_, mu2_, mu3_) {
2883 mu1_.Unlock();
2884 mu2_.Unlock();
2885 mu3_.Unlock();
2886}
2887
2888void Foo::unlocklots()
2889 UNLOCK_FUNCTION(mu1_, mu2_)
2890 UNLOCK_FUNCTION(mu2_, mu3_) {
2891 mu1_.Unlock();
2892 mu2_.Unlock();
2893 mu3_.Unlock();
2894}
2895
2896
2897void test0() {
2898 Foo foo;
2899 foo.lock();
2900 foo.unlock();
2901
2902 foo.lock();
2903 foo.lock(); // expected-warning {{locking 'foo' that is already locked}}
2904 foo.unlock();
2905 foo.unlock(); // expected-warning {{unlocking 'foo' that was not locked}}
2906}
2907
2908
2909void test1() {
2910 Foo foo;
2911 foo.lock1();
2912 foo.a = 0;
2913 foo.unlock1();
2914
2915 foo.lock1();
DeLesley Hutchinsa74b7152012-08-10 20:19:55 +00002916 foo.lock1(); // expected-warning {{locking 'foo.mu1_' that is already locked}}
DeLesley Hutchins5381c052012-07-05 21:16:29 +00002917 foo.a = 0;
2918 foo.unlock1();
DeLesley Hutchinsa74b7152012-08-10 20:19:55 +00002919 foo.unlock1(); // expected-warning {{unlocking 'foo.mu1_' that was not locked}}
DeLesley Hutchins5381c052012-07-05 21:16:29 +00002920}
2921
2922
2923int test2() {
2924 Foo foo;
2925 foo.slock1();
2926 int d1 = foo.a;
2927 foo.unlock1();
2928
2929 foo.slock1();
DeLesley Hutchinsa74b7152012-08-10 20:19:55 +00002930 foo.slock1(); // expected-warning {{locking 'foo.mu1_' that is already locked}}
DeLesley Hutchins5381c052012-07-05 21:16:29 +00002931 int d2 = foo.a;
2932 foo.unlock1();
DeLesley Hutchinsa74b7152012-08-10 20:19:55 +00002933 foo.unlock1(); // expected-warning {{unlocking 'foo.mu1_' that was not locked}}
DeLesley Hutchins5381c052012-07-05 21:16:29 +00002934 return d1 + d2;
2935}
2936
2937
2938void test3() {
2939 Foo foo;
2940 foo.lock3();
2941 foo.a = 0;
2942 foo.b = 0;
2943 foo.c = 0;
2944 foo.unlock3();
2945
2946 foo.lock3();
2947 foo.lock3(); // \
DeLesley Hutchinsa74b7152012-08-10 20:19:55 +00002948 // expected-warning {{locking 'foo.mu1_' that is already locked}} \
2949 // expected-warning {{locking 'foo.mu2_' that is already locked}} \
2950 // expected-warning {{locking 'foo.mu3_' that is already locked}}
DeLesley Hutchins5381c052012-07-05 21:16:29 +00002951 foo.a = 0;
2952 foo.b = 0;
2953 foo.c = 0;
2954 foo.unlock3();
2955 foo.unlock3(); // \
DeLesley Hutchinsa74b7152012-08-10 20:19:55 +00002956 // expected-warning {{unlocking 'foo.mu1_' that was not locked}} \
2957 // expected-warning {{unlocking 'foo.mu2_' that was not locked}} \
2958 // expected-warning {{unlocking 'foo.mu3_' that was not locked}}
DeLesley Hutchins5381c052012-07-05 21:16:29 +00002959}
2960
2961
2962void testlots() {
2963 Foo foo;
2964 foo.locklots();
2965 foo.a = 0;
2966 foo.b = 0;
2967 foo.c = 0;
2968 foo.unlocklots();
2969
2970 foo.locklots();
2971 foo.locklots(); // \
DeLesley Hutchinsa74b7152012-08-10 20:19:55 +00002972 // expected-warning {{locking 'foo.mu1_' that is already locked}} \
2973 // expected-warning {{locking 'foo.mu2_' that is already locked}} \
2974 // expected-warning {{locking 'foo.mu3_' that is already locked}}
DeLesley Hutchins5381c052012-07-05 21:16:29 +00002975 foo.a = 0;
2976 foo.b = 0;
2977 foo.c = 0;
2978 foo.unlocklots();
2979 foo.unlocklots(); // \
DeLesley Hutchinsa74b7152012-08-10 20:19:55 +00002980 // expected-warning {{unlocking 'foo.mu1_' that was not locked}} \
2981 // expected-warning {{unlocking 'foo.mu2_' that was not locked}} \
2982 // expected-warning {{unlocking 'foo.mu3_' that was not locked}}
DeLesley Hutchins5381c052012-07-05 21:16:29 +00002983}
2984
2985} // end namespace DuplicateAttributeTest
2986
2987
2988
DeLesley Hutchins13106112012-07-10 21:47:55 +00002989namespace TryLockEqTest {
2990
2991class Foo {
2992 Mutex mu_;
2993 int a GUARDED_BY(mu_);
2994 bool c;
2995
2996 int tryLockMutexI() EXCLUSIVE_TRYLOCK_FUNCTION(1, mu_);
2997 Mutex* tryLockMutexP() EXCLUSIVE_TRYLOCK_FUNCTION(1, mu_);
2998 void unlock() UNLOCK_FUNCTION(mu_);
2999
3000 void test1();
3001 void test2();
3002};
3003
3004
3005void Foo::test1() {
3006 if (tryLockMutexP() == 0) {
3007 a = 0; // expected-warning {{writing variable 'a' requires locking 'mu_' exclusively}}
3008 return;
3009 }
3010 a = 0;
3011 unlock();
3012
3013 if (tryLockMutexP() != 0) {
3014 a = 0;
3015 unlock();
3016 }
3017
3018 if (0 != tryLockMutexP()) {
3019 a = 0;
3020 unlock();
3021 }
3022
3023 if (!(tryLockMutexP() == 0)) {
3024 a = 0;
3025 unlock();
3026 }
3027
3028 if (tryLockMutexI() == 0) {
3029 a = 0; // expected-warning {{writing variable 'a' requires locking 'mu_' exclusively}}
3030 return;
3031 }
3032 a = 0;
3033 unlock();
3034
3035 if (0 == tryLockMutexI()) {
3036 a = 0; // expected-warning {{writing variable 'a' requires locking 'mu_' exclusively}}
3037 return;
3038 }
3039 a = 0;
3040 unlock();
3041
3042 if (tryLockMutexI() == 1) {
3043 a = 0;
3044 unlock();
3045 }
3046
3047 if (mu_.TryLock() == false) {
3048 a = 0; // expected-warning {{writing variable 'a' requires locking 'mu_' exclusively}}
3049 return;
3050 }
3051 a = 0;
3052 unlock();
3053
3054 if (mu_.TryLock() == true) {
3055 a = 0;
3056 unlock();
3057 }
3058 else {
3059 a = 0; // expected-warning {{writing variable 'a' requires locking 'mu_' exclusively}}
3060 }
3061
3062#if __has_feature(cxx_nullptr)
3063 if (tryLockMutexP() == nullptr) {
3064 a = 0; // expected-warning {{writing variable 'a' requires locking 'mu_' exclusively}}
3065 return;
3066 }
3067 a = 0;
3068 unlock();
3069#endif
3070}
3071
3072
3073void Foo::test2() {
3074/* FIXME: these tests depend on changes to the CFG.
3075 *
3076 if (mu_.TryLock() && c) {
3077 a = 0;
3078 unlock();
3079 }
3080 else return;
3081
3082 if (c && mu_.TryLock()) {
3083 a = 0;
3084 unlock();
3085 }
3086 else return;
3087
3088 if (!(mu_.TryLock() && c))
3089 return;
3090 a = 0;
3091 unlock();
3092
3093 if (!(c && mu_.TryLock()))
3094 return;
3095 a = 0;
3096 unlock();
3097
3098 if (!(mu_.TryLock() == 0) && c) {
3099 a = 0;
3100 unlock();
3101 }
3102
3103 if (!mu_.TryLock() || c)
3104 return;
3105 a = 0;
3106 unlock();
3107*/
3108}
3109
DeLesley Hutchins13106112012-07-10 21:47:55 +00003110} // end namespace TryLockEqTest
DeLesley Hutchins5381c052012-07-05 21:16:29 +00003111
DeLesley Hutchins96fac6a2012-07-03 19:47:18 +00003112
DeLesley Hutchinsee2f0322012-08-10 20:29:46 +00003113namespace ExistentialPatternMatching {
3114
3115class Graph {
3116public:
3117 Mutex mu_;
3118};
3119
3120void LockAllGraphs() EXCLUSIVE_LOCK_FUNCTION(&Graph::mu_);
3121void UnlockAllGraphs() UNLOCK_FUNCTION(&Graph::mu_);
3122
3123class Node {
3124public:
3125 int a GUARDED_BY(&Graph::mu_);
3126
3127 void foo() EXCLUSIVE_LOCKS_REQUIRED(&Graph::mu_) {
3128 a = 0;
3129 }
3130 void foo2() LOCKS_EXCLUDED(&Graph::mu_);
3131};
3132
3133void test() {
3134 Graph g1;
3135 Graph g2;
3136 Node n1;
3137
3138 n1.a = 0; // expected-warning {{writing variable 'a' requires locking '&ExistentialPatternMatching::Graph::mu_' exclusively}}
3139 n1.foo(); // expected-warning {{calling function 'foo' requires exclusive lock on '&ExistentialPatternMatching::Graph::mu_'}}
3140 n1.foo2();
3141
3142 g1.mu_.Lock();
3143 n1.a = 0;
3144 n1.foo();
3145 n1.foo2(); // expected-warning {{cannot call function 'foo2' while mutex '&ExistentialPatternMatching::Graph::mu_' is locked}}
3146 g1.mu_.Unlock();
3147
3148 g2.mu_.Lock();
3149 n1.a = 0;
3150 n1.foo();
3151 n1.foo2(); // expected-warning {{cannot call function 'foo2' while mutex '&ExistentialPatternMatching::Graph::mu_' is locked}}
3152 g2.mu_.Unlock();
3153
3154 LockAllGraphs();
3155 n1.a = 0;
3156 n1.foo();
3157 n1.foo2(); // expected-warning {{cannot call function 'foo2' while mutex '&ExistentialPatternMatching::Graph::mu_' is locked}}
3158 UnlockAllGraphs();
3159
3160 LockAllGraphs();
3161 g1.mu_.Unlock();
3162
3163 LockAllGraphs();
3164 g2.mu_.Unlock();
3165
3166 LockAllGraphs();
3167 g1.mu_.Lock(); // expected-warning {{locking 'g1.mu_' that is already locked}}
3168 g1.mu_.Unlock();
3169}
3170
3171} // end namespace ExistentialPatternMatching
3172
DeLesley Hutchins4e4c1572012-08-31 21:57:32 +00003173
3174namespace StringIgnoreTest {
3175
3176class Foo {
3177public:
3178 Mutex mu_;
3179 void lock() EXCLUSIVE_LOCK_FUNCTION("");
3180 void unlock() UNLOCK_FUNCTION("");
3181 void goober() EXCLUSIVE_LOCKS_REQUIRED("");
3182 void roober() SHARED_LOCKS_REQUIRED("");
3183};
3184
3185
3186class Bar : public Foo {
3187public:
3188 void bar(Foo* f) {
3189 f->unlock();
3190 f->goober();
3191 f->roober();
3192 f->lock();
3193 };
3194};
3195
3196} // end namespace StringIgnoreTest
3197
3198
DeLesley Hutchins54081532012-08-31 22:09:53 +00003199namespace LockReturnedScopeFix {
3200
3201class Base {
3202protected:
3203 struct Inner;
3204 bool c;
3205
3206 const Mutex& getLock(const Inner* i);
3207
3208 void lockInner (Inner* i) EXCLUSIVE_LOCK_FUNCTION(getLock(i));
3209 void unlockInner(Inner* i) UNLOCK_FUNCTION(getLock(i));
3210 void foo(Inner* i) EXCLUSIVE_LOCKS_REQUIRED(getLock(i));
3211
3212 void bar(Inner* i);
3213};
3214
3215
3216struct Base::Inner {
3217 Mutex lock_;
3218 void doSomething() EXCLUSIVE_LOCKS_REQUIRED(lock_);
3219};
3220
3221
3222const Mutex& Base::getLock(const Inner* i) LOCK_RETURNED(i->lock_) {
3223 return i->lock_;
3224}
3225
3226
3227void Base::foo(Inner* i) {
3228 i->doSomething();
3229}
3230
3231void Base::bar(Inner* i) {
3232 if (c) {
3233 i->lock_.Lock();
3234 unlockInner(i);
3235 }
3236 else {
3237 lockInner(i);
3238 i->lock_.Unlock();
3239 }
3240}
3241
3242} // end namespace LockReturnedScopeFix
3243
DeLesley Hutchinsfd0f11c2012-09-05 20:01:16 +00003244
3245namespace TrylockWithCleanups {
3246
DeLesley Hutchinsfd0f11c2012-09-05 20:01:16 +00003247struct Foo {
3248 Mutex mu_;
3249 int a GUARDED_BY(mu_);
3250};
3251
3252Foo* GetAndLockFoo(const MyString& s)
3253 EXCLUSIVE_TRYLOCK_FUNCTION(true, &Foo::mu_);
3254
3255static void test() {
3256 Foo* lt = GetAndLockFoo("foo");
3257 if (!lt) return;
3258 int a = lt->a;
3259 lt->mu_.Unlock();
3260}
3261
DeLesley Hutchins24a6c942012-09-11 18:27:46 +00003262} // end namespace TrylockWithCleanups
DeLesley Hutchinsfd0f11c2012-09-05 20:01:16 +00003263
3264
DeLesley Hutchins0b4db3e2012-09-07 17:34:53 +00003265namespace UniversalLock {
3266
3267class Foo {
3268 Mutex mu_;
3269 bool c;
3270
3271 int a GUARDED_BY(mu_);
3272 void r_foo() SHARED_LOCKS_REQUIRED(mu_);
3273 void w_foo() EXCLUSIVE_LOCKS_REQUIRED(mu_);
3274
3275 void test1() {
3276 int b;
3277
3278 beginNoWarnOnReads();
3279 b = a;
3280 r_foo();
3281 endNoWarnOnReads();
3282
3283 beginNoWarnOnWrites();
3284 a = 0;
3285 w_foo();
3286 endNoWarnOnWrites();
3287 }
3288
3289 // don't warn on joins with universal lock
3290 void test2() {
3291 if (c) {
3292 beginNoWarnOnWrites();
3293 }
3294 a = 0; // \
3295 // expected-warning {{writing variable 'a' requires locking 'mu_' exclusively}}
3296 endNoWarnOnWrites(); // \
3297 // expected-warning {{unlocking '*' that was not locked}}
3298 }
3299
3300
3301 // make sure the universal lock joins properly
3302 void test3() {
3303 if (c) {
3304 mu_.Lock();
3305 beginNoWarnOnWrites();
3306 }
3307 else {
3308 beginNoWarnOnWrites();
3309 mu_.Lock();
3310 }
3311 a = 0;
3312 endNoWarnOnWrites();
3313 mu_.Unlock();
3314 }
3315
3316
3317 // combine universal lock with other locks
3318 void test4() {
3319 beginNoWarnOnWrites();
3320 mu_.Lock();
3321 mu_.Unlock();
3322 endNoWarnOnWrites();
3323
3324 mu_.Lock();
3325 beginNoWarnOnWrites();
3326 endNoWarnOnWrites();
3327 mu_.Unlock();
3328
3329 mu_.Lock();
3330 beginNoWarnOnWrites();
3331 mu_.Unlock();
3332 endNoWarnOnWrites();
3333 }
3334};
3335
DeLesley Hutchins24a6c942012-09-11 18:27:46 +00003336} // end namespace UniversalLock
3337
3338
3339namespace TemplateLockReturned {
3340
3341template<class T>
3342class BaseT {
3343public:
3344 virtual void baseMethod() = 0;
3345 Mutex* get_mutex() LOCK_RETURNED(mutex_) { return &mutex_; }
3346
3347 Mutex mutex_;
3348 int a GUARDED_BY(mutex_);
3349};
3350
3351
3352class Derived : public BaseT<int> {
3353public:
3354 void baseMethod() EXCLUSIVE_LOCKS_REQUIRED(get_mutex()) {
3355 a = 0;
3356 }
3357};
3358
3359} // end namespace TemplateLockReturned
3360
3361
DeLesley Hutchinsf9ee0ba2012-09-11 23:04:49 +00003362namespace ExprMatchingBugFix {
3363
3364class Foo {
3365public:
3366 Mutex mu_;
3367};
3368
3369
3370class Bar {
3371public:
3372 bool c;
3373 Foo* foo;
3374 Bar(Foo* f) : foo(f) { }
3375
3376 struct Nested {
3377 Foo* foo;
3378 Nested(Foo* f) : foo(f) { }
3379
3380 void unlockFoo() UNLOCK_FUNCTION(&Foo::mu_);
3381 };
3382
3383 void test();
3384};
3385
3386
3387void Bar::test() {
3388 foo->mu_.Lock();
3389 if (c) {
3390 Nested *n = new Nested(foo);
3391 n->unlockFoo();
3392 }
3393 else {
3394 foo->mu_.Unlock();
3395 }
3396}
3397
3398}; // end namespace ExprMatchingBugfix
3399
3400
DeLesley Hutchins5b280f22012-09-19 19:18:29 +00003401namespace ComplexNameTest {
DeLesley Hutchinsf9ee0ba2012-09-11 23:04:49 +00003402
DeLesley Hutchins5b280f22012-09-19 19:18:29 +00003403class Foo {
3404public:
3405 static Mutex mu_;
3406
3407 Foo() EXCLUSIVE_LOCKS_REQUIRED(mu_) { }
3408 ~Foo() EXCLUSIVE_LOCKS_REQUIRED(mu_) { }
3409
3410 int operator[](int i) EXCLUSIVE_LOCKS_REQUIRED(mu_) { return 0; }
3411};
3412
3413class Bar {
3414public:
3415 static Mutex mu_;
3416
3417 Bar() LOCKS_EXCLUDED(mu_) { }
3418 ~Bar() LOCKS_EXCLUDED(mu_) { }
3419
3420 int operator[](int i) LOCKS_EXCLUDED(mu_) { return 0; }
3421};
3422
3423
3424void test1() {
3425 Foo f; // expected-warning {{calling function 'Foo' requires exclusive lock on 'mu_'}}
3426 int a = f[0]; // expected-warning {{calling function 'operator[]' requires exclusive lock on 'mu_'}}
3427} // expected-warning {{calling function '~Foo' requires exclusive lock on 'mu_'}}
3428
3429
3430void test2() {
3431 Bar::mu_.Lock();
3432 {
3433 Bar b; // expected-warning {{cannot call function 'Bar' while mutex 'mu_' is locked}}
3434 int a = b[0]; // expected-warning {{cannot call function 'operator[]' while mutex 'mu_' is locked}}
3435 } // expected-warning {{cannot call function '~Bar' while mutex 'mu_' is locked}}
3436 Bar::mu_.Unlock();
3437}
3438
3439}; // end namespace ComplexNameTest
DeLesley Hutchins2a237e02012-09-19 19:49:40 +00003440
3441
3442namespace UnreachableExitTest {
3443
3444class FemmeFatale {
3445public:
3446 FemmeFatale();
3447 ~FemmeFatale() __attribute__((noreturn));
3448};
3449
3450void exitNow() __attribute__((noreturn));
DeLesley Hutchinsd2f38822012-09-21 17:57:00 +00003451void exitDestruct(const MyString& ms) __attribute__((noreturn));
DeLesley Hutchins2a237e02012-09-19 19:49:40 +00003452
3453Mutex fatalmu_;
3454
3455void test1() EXCLUSIVE_LOCKS_REQUIRED(fatalmu_) {
3456 exitNow();
3457}
3458
3459void test2() EXCLUSIVE_LOCKS_REQUIRED(fatalmu_) {
3460 FemmeFatale femme;
3461}
3462
3463bool c;
3464
3465void test3() EXCLUSIVE_LOCKS_REQUIRED(fatalmu_) {
3466 if (c) {
3467 exitNow();
3468 }
3469 else {
3470 FemmeFatale femme;
3471 }
3472}
3473
DeLesley Hutchinsd2f38822012-09-21 17:57:00 +00003474void test4() EXCLUSIVE_LOCKS_REQUIRED(fatalmu_) {
3475 exitDestruct("foo");
3476}
3477
DeLesley Hutchins2a237e02012-09-19 19:49:40 +00003478} // end namespace UnreachableExitTest
DeLesley Hutchins186af2d2012-09-20 22:18:02 +00003479
3480
3481namespace VirtualMethodCanonicalizationTest {
3482
3483class Base {
3484public:
3485 virtual Mutex* getMutex() = 0;
3486};
3487
3488class Base2 : public Base {
3489public:
3490 Mutex* getMutex();
3491};
3492
3493class Base3 : public Base2 {
3494public:
3495 Mutex* getMutex();
3496};
3497
3498class Derived : public Base3 {
3499public:
3500 Mutex* getMutex(); // overrides Base::getMutex()
3501};
3502
3503void baseFun(Base *b) EXCLUSIVE_LOCKS_REQUIRED(b->getMutex()) { }
3504
3505void derivedFun(Derived *d) EXCLUSIVE_LOCKS_REQUIRED(d->getMutex()) {
3506 baseFun(d);
3507}
3508
3509} // end namespace VirtualMethodCanonicalizationTest
3510
DeLesley Hutchinsd278dbe2012-09-26 17:57:31 +00003511
3512namespace TemplateFunctionParamRemapTest {
3513
3514template <class T>
3515struct Cell {
3516 T dummy_;
3517 Mutex* mu_;
3518};
3519
3520class Foo {
3521public:
3522 template <class T>
3523 void elr(Cell<T>* c) __attribute__((exclusive_locks_required(c->mu_)));
3524
3525 void test();
3526};
3527
3528template<class T>
3529void Foo::elr(Cell<T>* c1) { }
3530
3531void Foo::test() {
3532 Cell<int> cell;
3533 elr(&cell); // \
3534 // expected-warning {{calling function 'elr' requires exclusive lock on 'cell.mu_'}}
3535}
3536
3537
3538template<class T>
3539void globalELR(Cell<T>* c) __attribute__((exclusive_locks_required(c->mu_)));
3540
3541template<class T>
3542void globalELR(Cell<T>* c1) { }
3543
3544void globalTest() {
3545 Cell<int> cell;
3546 globalELR(&cell); // \
3547 // expected-warning {{calling function 'globalELR' requires exclusive lock on 'cell.mu_'}}
3548}
3549
3550
3551template<class T>
3552void globalELR2(Cell<T>* c) __attribute__((exclusive_locks_required(c->mu_)));
3553
3554// second declaration
3555template<class T>
3556void globalELR2(Cell<T>* c2);
3557
3558template<class T>
3559void globalELR2(Cell<T>* c3) { }
3560
3561// re-declaration after definition
3562template<class T>
3563void globalELR2(Cell<T>* c4);
3564
3565void globalTest2() {
3566 Cell<int> cell;
3567 globalELR2(&cell); // \
3568 // expected-warning {{calling function 'globalELR2' requires exclusive lock on 'cell.mu_'}}
3569}
3570
3571
3572template<class T>
3573class FooT {
3574public:
3575 void elr(Cell<T>* c) __attribute__((exclusive_locks_required(c->mu_)));
3576};
3577
3578template<class T>
3579void FooT<T>::elr(Cell<T>* c1) { }
3580
3581void testFooT() {
3582 Cell<int> cell;
3583 FooT<int> foo;
3584 foo.elr(&cell); // \
3585 // expected-warning {{calling function 'elr' requires exclusive lock on 'cell.mu_'}}
3586}
3587
3588} // end namespace TemplateFunctionParamRemapTest
3589
DeLesley Hutchinsef2388b2012-10-05 22:38:19 +00003590
3591namespace SelfConstructorTest {
3592
3593class SelfLock {
3594public:
3595 SelfLock() EXCLUSIVE_LOCK_FUNCTION(mu_);
3596 ~SelfLock() UNLOCK_FUNCTION(mu_);
3597
3598 void foo() EXCLUSIVE_LOCKS_REQUIRED(mu_);
3599
3600 Mutex mu_;
3601};
3602
3603class LOCKABLE SelfLock2 {
3604public:
3605 SelfLock2() EXCLUSIVE_LOCK_FUNCTION();
3606 ~SelfLock2() UNLOCK_FUNCTION();
3607
3608 void foo() EXCLUSIVE_LOCKS_REQUIRED(this);
3609};
3610
3611
3612void test() {
3613 SelfLock s;
3614 s.foo();
3615}
3616
3617void test2() {
3618 SelfLock2 s2;
3619 s2.foo();
3620}
3621
3622} // end namespace SelfConstructorTest
3623
DeLesley Hutchins3ce9fae2012-10-12 21:38:12 +00003624
3625namespace MultipleAttributeTest {
3626
3627class Foo {
3628 Mutex mu1_;
3629 Mutex mu2_;
3630 int a GUARDED_BY(mu1_);
3631 int b GUARDED_BY(mu2_);
3632 int c GUARDED_BY(mu1_) GUARDED_BY(mu2_);
3633 int* d PT_GUARDED_BY(mu1_) PT_GUARDED_BY(mu2_);
3634
3635 void foo1() EXCLUSIVE_LOCKS_REQUIRED(mu1_)
3636 EXCLUSIVE_LOCKS_REQUIRED(mu2_);
3637 void foo2() SHARED_LOCKS_REQUIRED(mu1_)
3638 SHARED_LOCKS_REQUIRED(mu2_);
3639 void foo3() LOCKS_EXCLUDED(mu1_)
3640 LOCKS_EXCLUDED(mu2_);
3641 void lock() EXCLUSIVE_LOCK_FUNCTION(mu1_)
3642 EXCLUSIVE_LOCK_FUNCTION(mu2_);
3643 void readerlock() EXCLUSIVE_LOCK_FUNCTION(mu1_)
3644 EXCLUSIVE_LOCK_FUNCTION(mu2_);
3645 void unlock() UNLOCK_FUNCTION(mu1_)
3646 UNLOCK_FUNCTION(mu2_);
3647 bool trylock() EXCLUSIVE_TRYLOCK_FUNCTION(true, mu1_)
3648 EXCLUSIVE_TRYLOCK_FUNCTION(true, mu2_);
3649 bool readertrylock() SHARED_TRYLOCK_FUNCTION(true, mu1_)
3650 SHARED_TRYLOCK_FUNCTION(true, mu2_);
3651
3652 void test();
3653};
3654
3655
3656void Foo::foo1() {
3657 a = 1;
3658 b = 2;
3659}
3660
3661void Foo::foo2() {
3662 int result = a + b;
3663}
3664
3665void Foo::foo3() { }
3666void Foo::lock() { }
3667void Foo::readerlock() { }
3668void Foo::unlock() { }
3669bool Foo::trylock() { return true; }
3670bool Foo::readertrylock() { return true; }
3671
3672
3673void Foo::test() {
3674 mu1_.Lock();
3675 foo1(); // expected-warning {{}}
3676 c = 0; // expected-warning {{}}
3677 *d = 0; // expected-warning {{}}
3678 mu1_.Unlock();
3679
3680 mu1_.ReaderLock();
3681 foo2(); // expected-warning {{}}
3682 int x = c; // expected-warning {{}}
3683 int y = *d; // expected-warning {{}}
3684 mu1_.Unlock();
3685
3686 mu2_.Lock();
3687 foo3(); // expected-warning {{}}
3688 mu2_.Unlock();
3689
3690 lock();
3691 a = 0;
3692 b = 0;
3693 unlock();
3694
3695 readerlock();
3696 int z = a + b;
3697 unlock();
3698
3699 if (trylock()) {
3700 a = 0;
3701 b = 0;
3702 unlock();
3703 }
3704
3705 if (readertrylock()) {
3706 int zz = a + b;
3707 unlock();
3708 }
3709}
3710
3711
3712} // end namespace MultipleAttributeTest
3713
3714
DeLesley Hutchins91e20612012-12-05 01:20:45 +00003715namespace GuardedNonPrimitiveTypeTest {
3716
3717
3718class Data {
3719public:
3720 Data(int i) : dat(i) { }
3721
3722 int getValue() const { return dat; }
3723 void setValue(int i) { dat = i; }
3724
3725 int operator[](int i) const { return dat; }
3726 int& operator[](int i) { return dat; }
3727
3728 void operator()() { }
3729
3730private:
3731 int dat;
3732};
3733
3734
3735class DataCell {
3736public:
3737 DataCell(const Data& d) : dat(d) { }
3738
3739private:
3740 Data dat;
3741};
3742
3743
3744void showDataCell(const DataCell& dc);
3745
3746
3747class Foo {
3748public:
3749 // method call tests
3750 void test() {
3751 data_.setValue(0); // FIXME -- should be writing \
3752 // expected-warning {{reading variable 'data_' requires locking 'mu_'}}
3753 int a = data_.getValue(); // \
3754 // expected-warning {{reading variable 'data_' requires locking 'mu_'}}
3755
3756 datap1_->setValue(0); // FIXME -- should be writing \
3757 // expected-warning {{reading variable 'datap1_' requires locking 'mu_'}}
3758 a = datap1_->getValue(); // \
3759 // expected-warning {{reading variable 'datap1_' requires locking 'mu_'}}
3760
3761 datap2_->setValue(0); // FIXME -- should be writing \
3762 // expected-warning {{reading the value pointed to by 'datap2_' requires locking 'mu_'}}
3763 a = datap2_->getValue(); // \
3764 // expected-warning {{reading the value pointed to by 'datap2_' requires locking 'mu_'}}
3765
3766 (*datap2_).setValue(0); // FIXME -- should be writing \
3767 // expected-warning {{reading the value pointed to by 'datap2_' requires locking 'mu_'}}
3768 a = (*datap2_).getValue(); // \
3769 // expected-warning {{reading the value pointed to by 'datap2_' requires locking 'mu_'}}
3770
3771 mu_.Lock();
3772 data_.setValue(1);
3773 datap1_->setValue(1);
3774 datap2_->setValue(1);
3775 mu_.Unlock();
3776
3777 mu_.ReaderLock();
3778 a = data_.getValue();
3779 datap1_->setValue(0); // reads datap1_, writes *datap1_
3780 a = datap1_->getValue();
3781 a = datap2_->getValue();
3782 mu_.Unlock();
3783 }
3784
3785 // operator tests
3786 void test2() {
3787 data_ = Data(1); // expected-warning {{writing variable 'data_' requires locking 'mu_' exclusively}}
3788 *datap1_ = data_; // expected-warning {{reading variable 'datap1_' requires locking 'mu_'}} \
3789 // expected-warning {{reading variable 'data_' requires locking 'mu_'}}
3790 *datap2_ = data_; // expected-warning {{writing the value pointed to by 'datap2_' requires locking 'mu_' exclusively}} \
3791 // expected-warning {{reading variable 'data_' requires locking 'mu_'}}
3792 data_ = *datap1_; // expected-warning {{writing variable 'data_' requires locking 'mu_' exclusively}} \
3793 // expected-warning {{reading variable 'datap1_' requires locking 'mu_'}}
3794 data_ = *datap2_; // expected-warning {{writing variable 'data_' requires locking 'mu_' exclusively}} \
3795 // expected-warning {{reading the value pointed to by 'datap2_' requires locking 'mu_'}}
3796
3797 data_[0] = 0; // expected-warning {{reading variable 'data_' requires locking 'mu_'}}
3798 (*datap2_)[0] = 0; // expected-warning {{reading the value pointed to by 'datap2_' requires locking 'mu_'}}
3799
3800 data_(); // expected-warning {{reading variable 'data_' requires locking 'mu_'}}
3801 }
3802
3803 // const operator tests
3804 void test3() const {
3805 Data mydat(data_); // expected-warning {{reading variable 'data_' requires locking 'mu_'}}
3806
3807 //FIXME
3808 //showDataCell(data_); // xpected-warning {{reading variable 'data_' requires locking 'mu_'}}
3809 //showDataCell(*datap2_); // xpected-warning {{reading the value pointed to by 'datap2_' requires locking 'mu_'}}
3810
3811 int a = data_[0]; // expected-warning {{reading variable 'data_' requires locking 'mu_'}}
3812 }
3813
3814private:
3815 Mutex mu_;
3816 Data data_ GUARDED_BY(mu_);
3817 Data* datap1_ GUARDED_BY(mu_);
3818 Data* datap2_ PT_GUARDED_BY(mu_);
3819};
3820
DeLesley Hutchins91e20612012-12-05 01:20:45 +00003821} // end namespace GuardedNonPrimitiveTypeTest
3822
DeLesley Hutchins93699d22012-12-08 03:46:30 +00003823
3824namespace GuardedNonPrimitive_MemberAccess {
3825
3826class Cell {
3827public:
3828 Cell(int i);
3829
3830 void cellMethod();
3831
3832 int a;
3833};
3834
3835
3836class Foo {
3837public:
3838 int a;
3839 Cell c GUARDED_BY(cell_mu_);
3840 Cell* cp PT_GUARDED_BY(cell_mu_);
3841
3842 void myMethod();
3843
3844 Mutex cell_mu_;
3845};
3846
3847
3848class Bar {
3849private:
3850 Mutex mu_;
3851 Foo foo GUARDED_BY(mu_);
3852 Foo* foop PT_GUARDED_BY(mu_);
3853
3854 void test() {
3855 foo.myMethod(); // expected-warning {{reading variable 'foo' requires locking 'mu_'}}
3856
3857 int fa = foo.a; // expected-warning {{reading variable 'foo' requires locking 'mu_'}}
3858 foo.a = fa; // expected-warning {{writing variable 'foo' requires locking 'mu_' exclusively}}
3859
3860 fa = foop->a; // expected-warning {{reading the value pointed to by 'foop' requires locking 'mu_'}}
3861 foop->a = fa; // expected-warning {{writing the value pointed to by 'foop' requires locking 'mu_' exclusively}}
3862
3863 fa = (*foop).a; // expected-warning {{reading the value pointed to by 'foop' requires locking 'mu_'}}
3864 (*foop).a = fa; // expected-warning {{writing the value pointed to by 'foop' requires locking 'mu_' exclusively}}
3865
3866 foo.c = Cell(0); // expected-warning {{writing variable 'foo' requires locking 'mu_'}} \
3867 // expected-warning {{writing variable 'c' requires locking 'foo.cell_mu_' exclusively}}
3868 foo.c.cellMethod(); // expected-warning {{reading variable 'foo' requires locking 'mu_'}} \
3869 // expected-warning {{reading variable 'c' requires locking 'foo.cell_mu_'}}
3870
3871 foop->c = Cell(0); // expected-warning {{writing the value pointed to by 'foop' requires locking 'mu_'}} \
3872 // expected-warning {{writing variable 'c' requires locking 'foop->cell_mu_' exclusively}}
3873 foop->c.cellMethod(); // expected-warning {{reading the value pointed to by 'foop' requires locking 'mu_'}} \
3874 // expected-warning {{reading variable 'c' requires locking 'foop->cell_mu_'}}
3875
3876 (*foop).c = Cell(0); // expected-warning {{writing the value pointed to by 'foop' requires locking 'mu_'}} \
3877 // expected-warning {{writing variable 'c' requires locking 'foop->cell_mu_' exclusively}}
3878 (*foop).c.cellMethod(); // expected-warning {{reading the value pointed to by 'foop' requires locking 'mu_'}} \
3879 // expected-warning {{reading variable 'c' requires locking 'foop->cell_mu_'}}
3880 };
3881};
3882
3883} // namespace GuardedNonPrimitive_MemberAccess
3884