blob: de3f3213792d236721346d2670bba999faf6437a [file] [log] [blame]
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +00001// RUN: %clang_cc1 -fsyntax-only -verify -Wthread-safety %s
Richard Smithaa549862012-04-30 23:33:33 +00002// RUN: %clang_cc1 -fsyntax-only -verify -Wthread-safety -std=c++11 -Wc++98-compat %s
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +00003
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00004#define LOCKABLE __attribute__ ((lockable))
5#define SCOPED_LOCKABLE __attribute__ ((scoped_lockable))
6#define GUARDED_BY(x) __attribute__ ((guarded_by(x)))
7#define GUARDED_VAR __attribute__ ((guarded_var))
8#define PT_GUARDED_BY(x) __attribute__ ((pt_guarded_by(x)))
9#define PT_GUARDED_VAR __attribute__ ((pt_guarded_var))
10#define ACQUIRED_AFTER(...) __attribute__ ((acquired_after(__VA_ARGS__)))
11#define ACQUIRED_BEFORE(...) __attribute__ ((acquired_before(__VA_ARGS__)))
12#define EXCLUSIVE_LOCK_FUNCTION(...) __attribute__ ((exclusive_lock_function(__VA_ARGS__)))
13#define SHARED_LOCK_FUNCTION(...) __attribute__ ((shared_lock_function(__VA_ARGS__)))
14#define EXCLUSIVE_TRYLOCK_FUNCTION(...) __attribute__ ((exclusive_trylock_function(__VA_ARGS__)))
15#define SHARED_TRYLOCK_FUNCTION(...) __attribute__ ((shared_trylock_function(__VA_ARGS__)))
16#define UNLOCK_FUNCTION(...) __attribute__ ((unlock_function(__VA_ARGS__)))
17#define LOCK_RETURNED(x) __attribute__ ((lock_returned(x)))
18#define LOCKS_EXCLUDED(...) __attribute__ ((locks_excluded(__VA_ARGS__)))
19#define EXCLUSIVE_LOCKS_REQUIRED(...) \
20 __attribute__ ((exclusive_locks_required(__VA_ARGS__)))
21#define SHARED_LOCKS_REQUIRED(...) \
22 __attribute__ ((shared_locks_required(__VA_ARGS__)))
23#define NO_THREAD_SAFETY_ANALYSIS __attribute__ ((no_thread_safety_analysis))
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +000024
25//-----------------------------------------//
26// Helper fields
27//-----------------------------------------//
28
29
30class __attribute__((lockable)) Mutex {
31 public:
32 void Lock() __attribute__((exclusive_lock_function));
33 void ReaderLock() __attribute__((shared_lock_function));
34 void Unlock() __attribute__((unlock_function));
35 bool TryLock() __attribute__((exclusive_trylock_function(true)));
36 bool ReaderTryLock() __attribute__((shared_trylock_function(true)));
37 void LockWhen(const int &cond) __attribute__((exclusive_lock_function));
38};
39
DeLesley Hutchins1fa3c062011-12-08 20:23:06 +000040class __attribute__((scoped_lockable)) MutexLock {
41 public:
42 MutexLock(Mutex *mu) __attribute__((exclusive_lock_function(mu)));
43 ~MutexLock() __attribute__((unlock_function));
44};
45
46class __attribute__((scoped_lockable)) ReaderMutexLock {
47 public:
48 ReaderMutexLock(Mutex *mu) __attribute__((exclusive_lock_function(mu)));
49 ~ReaderMutexLock() __attribute__((unlock_function));
50};
51
DeLesley Hutchinsc99a5d82012-06-28 22:42:48 +000052class SCOPED_LOCKABLE ReleasableMutexLock {
53 public:
54 ReleasableMutexLock(Mutex *mu) EXCLUSIVE_LOCK_FUNCTION(mu);
55 ~ReleasableMutexLock() UNLOCK_FUNCTION();
56
57 void Release() UNLOCK_FUNCTION();
58};
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +000059
DeLesley Hutchins9d6e7f32012-07-03 18:25:56 +000060
61template<class T>
62class SmartPtr {
63public:
64 SmartPtr(T* p) : ptr_(p) { }
65 SmartPtr(const SmartPtr<T>& p) : ptr_(p.ptr_) { }
66 ~SmartPtr();
67
68 T* get() const { return ptr_; }
69 T* operator->() const { return ptr_; }
70 T& operator*() const { return ptr_; }
71
72private:
73 T* ptr_;
74};
75
76
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +000077Mutex sls_mu;
78
79Mutex sls_mu2 __attribute__((acquired_after(sls_mu)));
80int sls_guard_var __attribute__((guarded_var)) = 0;
81int sls_guardby_var __attribute__((guarded_by(sls_mu))) = 0;
82
83bool getBool();
84
85class MutexWrapper {
86public:
87 Mutex mu;
Caitlin Sadowski194418f2011-09-14 20:00:24 +000088 int x __attribute__((guarded_by(mu)));
89 void MyLock() __attribute__((exclusive_lock_function(mu)));
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +000090};
91
92MutexWrapper sls_mw;
93
94void sls_fun_0() {
95 sls_mw.mu.Lock();
Caitlin Sadowski194418f2011-09-14 20:00:24 +000096 sls_mw.x = 5;
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +000097 sls_mw.mu.Unlock();
98}
99
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000100void sls_fun_2() {
101 sls_mu.Lock();
102 int x = sls_guard_var;
103 sls_mu.Unlock();
104}
105
106void sls_fun_3() {
107 sls_mu.Lock();
108 sls_guard_var = 2;
109 sls_mu.Unlock();
110}
111
112void sls_fun_4() {
113 sls_mu2.Lock();
114 sls_guard_var = 2;
115 sls_mu2.Unlock();
116}
117
118void sls_fun_5() {
119 sls_mu.Lock();
120 int x = sls_guardby_var;
121 sls_mu.Unlock();
122}
123
124void sls_fun_6() {
125 sls_mu.Lock();
126 sls_guardby_var = 2;
127 sls_mu.Unlock();
128}
129
130void sls_fun_7() {
131 sls_mu.Lock();
132 sls_mu2.Lock();
133 sls_mu2.Unlock();
134 sls_mu.Unlock();
135}
136
137void sls_fun_8() {
138 sls_mu.Lock();
139 if (getBool())
140 sls_mu.Unlock();
141 else
142 sls_mu.Unlock();
143}
144
145void sls_fun_9() {
146 if (getBool())
147 sls_mu.Lock();
148 else
149 sls_mu.Lock();
150 sls_mu.Unlock();
151}
152
153void sls_fun_good_6() {
154 if (getBool()) {
155 sls_mu.Lock();
156 } else {
157 if (getBool()) {
158 getBool(); // EMPTY
159 } else {
160 getBool(); // EMPTY
161 }
162 sls_mu.Lock();
163 }
164 sls_mu.Unlock();
165}
166
167void sls_fun_good_7() {
168 sls_mu.Lock();
169 while (getBool()) {
170 sls_mu.Unlock();
171 if (getBool()) {
172 if (getBool()) {
173 sls_mu.Lock();
174 continue;
175 }
176 }
177 sls_mu.Lock();
178 }
179 sls_mu.Unlock();
180}
181
Caitlin Sadowski194418f2011-09-14 20:00:24 +0000182void sls_fun_good_8() {
183 sls_mw.MyLock();
184 sls_mw.mu.Unlock();
185}
186
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000187void sls_fun_bad_1() {
188 sls_mu.Unlock(); // \
Caitlin Sadowski8bccabe2011-09-08 21:52:50 +0000189 // expected-warning{{unlocking 'sls_mu' that was not locked}}
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000190}
191
192void sls_fun_bad_2() {
193 sls_mu.Lock();
194 sls_mu.Lock(); // \
Caitlin Sadowski8bccabe2011-09-08 21:52:50 +0000195 // expected-warning{{locking 'sls_mu' that is already locked}}
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000196 sls_mu.Unlock();
197}
198
199void sls_fun_bad_3() {
Richard Smith2e515622012-02-03 04:45:26 +0000200 sls_mu.Lock(); // expected-note {{mutex acquired here}}
201} // expected-warning{{mutex 'sls_mu' is still locked at the end of function}}
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000202
203void sls_fun_bad_4() {
204 if (getBool())
DeLesley Hutchins0da44142012-06-22 17:07:28 +0000205 sls_mu.Lock(); // expected-note{{mutex acquired here}}
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000206 else
DeLesley Hutchins0da44142012-06-22 17:07:28 +0000207 sls_mu2.Lock(); // expected-note{{mutex acquired here}}
208} // expected-warning{{mutex 'sls_mu' is not locked on every path through here}} \
209 // expected-warning{{mutex 'sls_mu2' is not locked on every path through here}}
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000210
211void sls_fun_bad_5() {
Richard Smith2e515622012-02-03 04:45:26 +0000212 sls_mu.Lock(); // expected-note {{mutex acquired here}}
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000213 if (getBool())
214 sls_mu.Unlock();
Richard Smith2e515622012-02-03 04:45:26 +0000215} // expected-warning{{mutex 'sls_mu' is not locked on every path through here}}
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000216
217void sls_fun_bad_6() {
218 if (getBool()) {
Richard Smith2e515622012-02-03 04:45:26 +0000219 sls_mu.Lock(); // expected-note {{mutex acquired here}}
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000220 } else {
221 if (getBool()) {
222 getBool(); // EMPTY
223 } else {
224 getBool(); // EMPTY
225 }
226 }
227 sls_mu.Unlock(); // \
Richard Smith2e515622012-02-03 04:45:26 +0000228 expected-warning{{mutex 'sls_mu' is not locked on every path through here}}\
229 expected-warning{{unlocking 'sls_mu' that was not locked}}
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000230}
231
232void sls_fun_bad_7() {
Richard Smithaacde712012-02-03 03:30:07 +0000233 sls_mu.Lock();
Caitlin Sadowski4e4bc752011-09-15 17:25:19 +0000234 while (getBool()) {
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000235 sls_mu.Unlock();
236 if (getBool()) {
237 if (getBool()) {
Richard Smith2e515622012-02-03 04:45:26 +0000238 continue; // \
239 expected-warning{{expecting mutex 'sls_mu' to be locked at start of each loop}}
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000240 }
241 }
Richard Smith2e515622012-02-03 04:45:26 +0000242 sls_mu.Lock(); // expected-note {{mutex acquired here}}
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000243 }
244 sls_mu.Unlock();
245}
246
247void sls_fun_bad_8() {
Richard Smith2e515622012-02-03 04:45:26 +0000248 sls_mu.Lock(); // expected-note{{mutex acquired here}}
249
DeLesley Hutchins0da44142012-06-22 17:07:28 +0000250 do {
251 sls_mu.Unlock(); // expected-warning{{expecting mutex 'sls_mu' to be locked at start of each loop}}
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000252 } while (getBool());
253}
254
255void sls_fun_bad_9() {
256 do {
DeLesley Hutchins0da44142012-06-22 17:07:28 +0000257 sls_mu.Lock(); // \
Richard Smith2e515622012-02-03 04:45:26 +0000258 // expected-warning{{expecting mutex 'sls_mu' to be locked at start of each loop}} \
259 // expected-note{{mutex acquired here}}
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000260 } while (getBool());
261 sls_mu.Unlock();
262}
263
264void sls_fun_bad_10() {
DeLesley Hutchins0da44142012-06-22 17:07:28 +0000265 sls_mu.Lock(); // expected-note 2{{mutex acquired here}}
266 while(getBool()) { // expected-warning{{expecting mutex 'sls_mu' to be locked at start of each loop}}
267 sls_mu.Unlock();
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000268 }
Richard Smith2e515622012-02-03 04:45:26 +0000269} // expected-warning{{mutex 'sls_mu' is still locked at the end of function}}
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000270
271void sls_fun_bad_11() {
Richard Smith2e515622012-02-03 04:45:26 +0000272 while (getBool()) { // \
DeLesley Hutchins0da44142012-06-22 17:07:28 +0000273 expected-warning{{expecting mutex 'sls_mu' to be locked at start of each loop}}
Richard Smith2e515622012-02-03 04:45:26 +0000274 sls_mu.Lock(); // expected-note {{mutex acquired here}}
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000275 }
276 sls_mu.Unlock(); // \
Caitlin Sadowski8bccabe2011-09-08 21:52:50 +0000277 // expected-warning{{unlocking 'sls_mu' that was not locked}}
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000278}
279
Richard Smithaacde712012-02-03 03:30:07 +0000280void sls_fun_bad_12() {
Richard Smith2e515622012-02-03 04:45:26 +0000281 sls_mu.Lock(); // expected-note {{mutex acquired here}}
Richard Smithaacde712012-02-03 03:30:07 +0000282 while (getBool()) {
283 sls_mu.Unlock();
284 if (getBool()) {
285 if (getBool()) {
Richard Smith2e515622012-02-03 04:45:26 +0000286 break; // expected-warning{{mutex 'sls_mu' is not locked on every path through here}}
Richard Smithaacde712012-02-03 03:30:07 +0000287 }
288 }
289 sls_mu.Lock();
290 }
291 sls_mu.Unlock();
292}
293
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000294//-----------------------------------------//
295// Handling lock expressions in attribute args
296// -------------------------------------------//
297
298Mutex aa_mu;
299
300class GlobalLocker {
301public:
302 void globalLock() __attribute__((exclusive_lock_function(aa_mu)));
303 void globalUnlock() __attribute__((unlock_function(aa_mu)));
304};
305
306GlobalLocker glock;
307
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000308void aa_fun_1() {
309 glock.globalLock();
310 glock.globalUnlock();
311}
312
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000313void aa_fun_bad_1() {
314 glock.globalUnlock(); // \
Caitlin Sadowski8bccabe2011-09-08 21:52:50 +0000315 // expected-warning{{unlocking 'aa_mu' that was not locked}}
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000316}
317
318void aa_fun_bad_2() {
319 glock.globalLock();
320 glock.globalLock(); // \
Caitlin Sadowski8bccabe2011-09-08 21:52:50 +0000321 // expected-warning{{locking 'aa_mu' that is already locked}}
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000322 glock.globalUnlock();
323}
324
325void aa_fun_bad_3() {
Richard Smith2e515622012-02-03 04:45:26 +0000326 glock.globalLock(); // expected-note{{mutex acquired here}}
327} // expected-warning{{mutex 'aa_mu' is still locked at the end of function}}
Caitlin Sadowskib4d0a962011-08-29 17:12:27 +0000328
Caitlin Sadowskib4d0a962011-08-29 17:12:27 +0000329//--------------------------------------------------//
330// Regression tests for unusual method names
331//--------------------------------------------------//
332
333Mutex wmu;
334
335// Test diagnostics for other method names.
336class WeirdMethods {
DeLesley Hutchins2f13bec2012-02-16 17:13:43 +0000337 // FIXME: can't currently check inside constructors and destructors.
Caitlin Sadowskib4d0a962011-08-29 17:12:27 +0000338 WeirdMethods() {
DeLesley Hutchins2f13bec2012-02-16 17:13:43 +0000339 wmu.Lock(); // EXPECTED-NOTE {{mutex acquired here}}
340 } // EXPECTED-WARNING {{mutex 'wmu' is still locked at the end of function}}
Caitlin Sadowskib4d0a962011-08-29 17:12:27 +0000341 ~WeirdMethods() {
DeLesley Hutchins2f13bec2012-02-16 17:13:43 +0000342 wmu.Lock(); // EXPECTED-NOTE {{mutex acquired here}}
343 } // EXPECTED-WARNING {{mutex 'wmu' is still locked at the end of function}}
Caitlin Sadowskib4d0a962011-08-29 17:12:27 +0000344 void operator++() {
Richard Smith2e515622012-02-03 04:45:26 +0000345 wmu.Lock(); // expected-note {{mutex acquired here}}
346 } // expected-warning {{mutex 'wmu' is still locked at the end of function}}
Caitlin Sadowskib4d0a962011-08-29 17:12:27 +0000347 operator int*() {
Richard Smith2e515622012-02-03 04:45:26 +0000348 wmu.Lock(); // expected-note {{mutex acquired here}}
Caitlin Sadowskib4d0a962011-08-29 17:12:27 +0000349 return 0;
Richard Smith2e515622012-02-03 04:45:26 +0000350 } // expected-warning {{mutex 'wmu' is still locked at the end of function}}
Caitlin Sadowskib4d0a962011-08-29 17:12:27 +0000351};
352
Caitlin Sadowski05b436e2011-08-29 22:27:51 +0000353//-----------------------------------------------//
354// Errors for guarded by or guarded var variables
355// ----------------------------------------------//
356
357int *pgb_gvar __attribute__((pt_guarded_var));
358int *pgb_var __attribute__((pt_guarded_by(sls_mu)));
359
360class PGBFoo {
361 public:
362 int x;
363 int *pgb_field __attribute__((guarded_by(sls_mu2)))
364 __attribute__((pt_guarded_by(sls_mu)));
365 void testFoo() {
366 pgb_field = &x; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000367 // expected-warning {{writing variable 'pgb_field' requires locking 'sls_mu2' exclusively}}
368 *pgb_field = x; // expected-warning {{reading variable 'pgb_field' requires locking 'sls_mu2'}} \
369 // expected-warning {{writing the value pointed to by 'pgb_field' requires locking 'sls_mu' exclusively}}
370 x = *pgb_field; // expected-warning {{reading variable 'pgb_field' requires locking 'sls_mu2'}} \
371 // expected-warning {{reading the value pointed to by 'pgb_field' requires locking 'sls_mu'}}
372 (*pgb_field)++; // expected-warning {{reading variable 'pgb_field' requires locking 'sls_mu2'}} \
373 // expected-warning {{writing the value pointed to by 'pgb_field' requires locking 'sls_mu' exclusively}}
Caitlin Sadowski05b436e2011-08-29 22:27:51 +0000374 }
375};
376
377class GBFoo {
378 public:
379 int gb_field __attribute__((guarded_by(sls_mu)));
380
381 void testFoo() {
382 gb_field = 0; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000383 // expected-warning {{writing variable 'gb_field' requires locking 'sls_mu' exclusively}}
Caitlin Sadowski05b436e2011-08-29 22:27:51 +0000384 }
Caitlin Sadowskiaf370612011-09-08 18:35:21 +0000385
386 void testNoAnal() __attribute__((no_thread_safety_analysis)) {
387 gb_field = 0;
388 }
Caitlin Sadowski05b436e2011-08-29 22:27:51 +0000389};
390
391GBFoo GlobalGBFoo __attribute__((guarded_by(sls_mu)));
392
393void gb_fun_0() {
394 sls_mu.Lock();
395 int x = *pgb_var;
396 sls_mu.Unlock();
397}
398
399void gb_fun_1() {
400 sls_mu.Lock();
401 *pgb_var = 2;
402 sls_mu.Unlock();
403}
404
405void gb_fun_2() {
406 int x;
407 pgb_var = &x;
408}
409
410void gb_fun_3() {
411 int *x = pgb_var;
412}
413
414void gb_bad_0() {
415 sls_guard_var = 1; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000416 // expected-warning{{writing variable 'sls_guard_var' requires locking any mutex exclusively}}
Caitlin Sadowski05b436e2011-08-29 22:27:51 +0000417}
418
419void gb_bad_1() {
420 int x = sls_guard_var; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000421 // expected-warning{{reading variable 'sls_guard_var' requires locking any mutex}}
Caitlin Sadowski05b436e2011-08-29 22:27:51 +0000422}
423
424void gb_bad_2() {
425 sls_guardby_var = 1; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000426 // expected-warning {{writing variable 'sls_guardby_var' requires locking 'sls_mu' exclusively}}
Caitlin Sadowski05b436e2011-08-29 22:27:51 +0000427}
428
429void gb_bad_3() {
430 int x = sls_guardby_var; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000431 // expected-warning {{reading variable 'sls_guardby_var' requires locking 'sls_mu'}}
Caitlin Sadowski05b436e2011-08-29 22:27:51 +0000432}
433
434void gb_bad_4() {
435 *pgb_gvar = 1; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000436 // expected-warning {{writing the value pointed to by 'pgb_gvar' requires locking any mutex exclusively}}
Caitlin Sadowski05b436e2011-08-29 22:27:51 +0000437}
438
439void gb_bad_5() {
440 int x = *pgb_gvar; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000441 // expected-warning {{reading the value pointed to by 'pgb_gvar' requires locking any mutex}}
Caitlin Sadowski05b436e2011-08-29 22:27:51 +0000442}
443
444void gb_bad_6() {
445 *pgb_var = 1; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000446 // expected-warning {{writing the value pointed to by 'pgb_var' requires locking 'sls_mu' exclusively}}
Caitlin Sadowski05b436e2011-08-29 22:27:51 +0000447}
448
449void gb_bad_7() {
450 int x = *pgb_var; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000451 // expected-warning {{reading the value pointed to by 'pgb_var' requires locking 'sls_mu'}}
Caitlin Sadowski05b436e2011-08-29 22:27:51 +0000452}
453
454void gb_bad_8() {
455 GBFoo G;
456 G.gb_field = 0; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000457 // expected-warning {{writing variable 'gb_field' requires locking 'sls_mu'}}
Caitlin Sadowski05b436e2011-08-29 22:27:51 +0000458}
459
460void gb_bad_9() {
461 sls_guard_var++; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000462 // expected-warning{{writing variable 'sls_guard_var' requires locking any mutex exclusively}}
Caitlin Sadowski05b436e2011-08-29 22:27:51 +0000463 sls_guard_var--; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000464 // expected-warning{{writing variable 'sls_guard_var' requires locking any mutex exclusively}}
Caitlin Sadowski05b436e2011-08-29 22:27:51 +0000465 ++sls_guard_var; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000466 // expected-warning{{writing variable 'sls_guard_var' requires locking any mutex exclusively}}
Caitlin Sadowskia49d1d82011-09-09 16:07:55 +0000467 --sls_guard_var;// \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000468 // expected-warning{{writing variable 'sls_guard_var' requires locking any mutex exclusively}}
Caitlin Sadowski05b436e2011-08-29 22:27:51 +0000469}
Caitlin Sadowskib4d0a962011-08-29 17:12:27 +0000470
Caitlin Sadowskieff98fc2011-09-08 17:42:22 +0000471//-----------------------------------------------//
472// Warnings on variables with late parsed attributes
473// ----------------------------------------------//
474
475class LateFoo {
476public:
477 int a __attribute__((guarded_by(mu)));
478 int b;
479
480 void foo() __attribute__((exclusive_locks_required(mu))) { }
481
482 void test() {
483 a = 0; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000484 // expected-warning{{writing variable 'a' requires locking 'mu' exclusively}}
Caitlin Sadowskieff98fc2011-09-08 17:42:22 +0000485 b = a; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000486 // expected-warning {{reading variable 'a' requires locking 'mu'}}
Caitlin Sadowskieff98fc2011-09-08 17:42:22 +0000487 c = 0; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000488 // expected-warning {{writing variable 'c' requires locking 'mu' exclusively}}
Caitlin Sadowskieff98fc2011-09-08 17:42:22 +0000489 }
490
491 int c __attribute__((guarded_by(mu)));
492
493 Mutex mu;
494};
495
Caitlin Sadowski99107eb2011-09-09 16:21:55 +0000496class LateBar {
497 public:
498 int a_ __attribute__((guarded_by(mu1_)));
499 int b_;
500 int *q __attribute__((pt_guarded_by(mu)));
501 Mutex mu1_;
502 Mutex mu;
503 LateFoo Foo;
504 LateFoo Foo2;
505 LateFoo *FooPointer;
506};
507
508LateBar b1, *b3;
509
510void late_0() {
511 LateFoo FooA;
512 LateFoo FooB;
513 FooA.mu.Lock();
514 FooA.a = 5;
515 FooA.mu.Unlock();
516}
517
518void late_1() {
519 LateBar BarA;
520 BarA.FooPointer->mu.Lock();
521 BarA.FooPointer->a = 2;
522 BarA.FooPointer->mu.Unlock();
523}
524
525void late_bad_0() {
526 LateFoo fooA;
527 LateFoo fooB;
528 fooA.mu.Lock();
529 fooB.a = 5; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000530 // expected-warning{{writing variable 'a' requires locking 'mu' exclusively}}
Caitlin Sadowski99107eb2011-09-09 16:21:55 +0000531 fooA.mu.Unlock();
532}
533
534void late_bad_1() {
535 Mutex mu;
536 mu.Lock();
537 b1.mu1_.Lock();
538 int res = b1.a_ + b3->b_;
539 b3->b_ = *b1.q; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000540 // expected-warning{{reading the value pointed to by 'q' requires locking 'mu'}}
Caitlin Sadowski99107eb2011-09-09 16:21:55 +0000541 b1.mu1_.Unlock();
542 b1.b_ = res;
543 mu.Unlock();
544}
545
546void late_bad_2() {
547 LateBar BarA;
548 BarA.FooPointer->mu.Lock();
549 BarA.Foo.a = 2; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000550 // expected-warning{{writing variable 'a' requires locking 'mu' exclusively}}
Caitlin Sadowski99107eb2011-09-09 16:21:55 +0000551 BarA.FooPointer->mu.Unlock();
552}
553
554void late_bad_3() {
555 LateBar BarA;
556 BarA.Foo.mu.Lock();
557 BarA.FooPointer->a = 2; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000558 // expected-warning{{writing variable 'a' requires locking 'mu' exclusively}}
Caitlin Sadowski99107eb2011-09-09 16:21:55 +0000559 BarA.Foo.mu.Unlock();
560}
561
562void late_bad_4() {
563 LateBar BarA;
564 BarA.Foo.mu.Lock();
565 BarA.Foo2.a = 2; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000566 // expected-warning{{writing variable 'a' requires locking 'mu' exclusively}}
Caitlin Sadowski99107eb2011-09-09 16:21:55 +0000567 BarA.Foo.mu.Unlock();
568}
569
Caitlin Sadowskia53257c2011-09-08 18:19:38 +0000570//-----------------------------------------------//
571// Extra warnings for shared vs. exclusive locks
572// ----------------------------------------------//
573
574void shared_fun_0() {
575 sls_mu.Lock();
576 do {
577 sls_mu.Unlock();
578 sls_mu.Lock();
579 } while (getBool());
580 sls_mu.Unlock();
581}
582
583void shared_fun_1() {
Caitlin Sadowski4e4bc752011-09-15 17:25:19 +0000584 sls_mu.ReaderLock(); // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000585 // expected-warning {{mutex 'sls_mu' is locked exclusively and shared in the same scope}}
Caitlin Sadowskia53257c2011-09-08 18:19:38 +0000586 do {
587 sls_mu.Unlock();
Caitlin Sadowski4e4bc752011-09-15 17:25:19 +0000588 sls_mu.Lock(); // \
589 // expected-note {{the other lock of mutex 'sls_mu' is here}}
Caitlin Sadowskia53257c2011-09-08 18:19:38 +0000590 } while (getBool());
591 sls_mu.Unlock();
592}
593
594void shared_fun_3() {
595 if (getBool())
596 sls_mu.Lock();
597 else
598 sls_mu.Lock();
599 *pgb_var = 1;
600 sls_mu.Unlock();
601}
602
603void shared_fun_4() {
604 if (getBool())
605 sls_mu.ReaderLock();
606 else
607 sls_mu.ReaderLock();
608 int x = sls_guardby_var;
609 sls_mu.Unlock();
610}
611
612void shared_fun_8() {
613 if (getBool())
614 sls_mu.Lock(); // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000615 // expected-warning {{mutex 'sls_mu' is locked exclusively and shared in the same scope}}
Caitlin Sadowskia53257c2011-09-08 18:19:38 +0000616 else
617 sls_mu.ReaderLock(); // \
Caitlin Sadowski8bccabe2011-09-08 21:52:50 +0000618 // expected-note {{the other lock of mutex 'sls_mu' is here}}
Caitlin Sadowskia53257c2011-09-08 18:19:38 +0000619 sls_mu.Unlock();
620}
621
622void shared_bad_0() {
Caitlin Sadowski4e4bc752011-09-15 17:25:19 +0000623 sls_mu.Lock(); // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000624 // expected-warning {{mutex 'sls_mu' is locked exclusively and shared in the same scope}}
Caitlin Sadowskia53257c2011-09-08 18:19:38 +0000625 do {
626 sls_mu.Unlock();
Caitlin Sadowski4e4bc752011-09-15 17:25:19 +0000627 sls_mu.ReaderLock(); // \
628 // expected-note {{the other lock of mutex 'sls_mu' is here}}
Caitlin Sadowskia53257c2011-09-08 18:19:38 +0000629 } while (getBool());
630 sls_mu.Unlock();
631}
632
633void shared_bad_1() {
634 if (getBool())
635 sls_mu.Lock(); // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000636 // expected-warning {{mutex 'sls_mu' is locked exclusively and shared in the same scope}}
Caitlin Sadowskia53257c2011-09-08 18:19:38 +0000637 else
638 sls_mu.ReaderLock(); // \
Caitlin Sadowski8bccabe2011-09-08 21:52:50 +0000639 // expected-note {{the other lock of mutex 'sls_mu' is here}}
Caitlin Sadowskia53257c2011-09-08 18:19:38 +0000640 *pgb_var = 1;
641 sls_mu.Unlock();
642}
643
644void shared_bad_2() {
645 if (getBool())
646 sls_mu.ReaderLock(); // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000647 // expected-warning {{mutex 'sls_mu' is locked exclusively and shared in the same scope}}
Caitlin Sadowskia53257c2011-09-08 18:19:38 +0000648 else
649 sls_mu.Lock(); // \
Caitlin Sadowski8bccabe2011-09-08 21:52:50 +0000650 // expected-note {{the other lock of mutex 'sls_mu' is here}}
Caitlin Sadowskia53257c2011-09-08 18:19:38 +0000651 *pgb_var = 1;
652 sls_mu.Unlock();
653}
Caitlin Sadowski978191e2011-09-08 18:27:31 +0000654
655// FIXME: Add support for functions (not only methods)
656class LRBar {
657 public:
658 void aa_elr_fun() __attribute__((exclusive_locks_required(aa_mu)));
659 void aa_elr_fun_s() __attribute__((shared_locks_required(aa_mu)));
660 void le_fun() __attribute__((locks_excluded(sls_mu)));
661};
662
663class LRFoo {
664 public:
665 void test() __attribute__((exclusive_locks_required(sls_mu)));
666 void testShared() __attribute__((shared_locks_required(sls_mu2)));
667};
668
669void elr_fun() __attribute__((exclusive_locks_required(sls_mu)));
670void elr_fun() {}
671
672LRFoo MyLRFoo;
673LRBar Bar;
674
675void es_fun_0() {
676 aa_mu.Lock();
677 Bar.aa_elr_fun();
678 aa_mu.Unlock();
679}
680
681void es_fun_1() {
682 aa_mu.Lock();
683 Bar.aa_elr_fun_s();
684 aa_mu.Unlock();
685}
686
687void es_fun_2() {
688 aa_mu.ReaderLock();
689 Bar.aa_elr_fun_s();
690 aa_mu.Unlock();
691}
692
693void es_fun_3() {
694 sls_mu.Lock();
695 MyLRFoo.test();
696 sls_mu.Unlock();
697}
698
699void es_fun_4() {
700 sls_mu2.Lock();
701 MyLRFoo.testShared();
702 sls_mu2.Unlock();
703}
704
705void es_fun_5() {
706 sls_mu2.ReaderLock();
707 MyLRFoo.testShared();
708 sls_mu2.Unlock();
709}
710
711void es_fun_6() {
712 Bar.le_fun();
713}
714
715void es_fun_7() {
716 sls_mu.Lock();
717 elr_fun();
718 sls_mu.Unlock();
719}
720
Caitlin Sadowskiaf370612011-09-08 18:35:21 +0000721void es_fun_8() __attribute__((no_thread_safety_analysis));
722
723void es_fun_8() {
724 Bar.aa_elr_fun_s();
725}
726
Caitlin Sadowskicb967512011-09-15 17:43:08 +0000727void es_fun_9() __attribute__((shared_locks_required(aa_mu)));
728void es_fun_9() {
729 Bar.aa_elr_fun_s();
730}
731
732void es_fun_10() __attribute__((exclusive_locks_required(aa_mu)));
733void es_fun_10() {
734 Bar.aa_elr_fun_s();
735}
736
Caitlin Sadowski978191e2011-09-08 18:27:31 +0000737void es_bad_0() {
738 Bar.aa_elr_fun(); // \
Caitlin Sadowski8bccabe2011-09-08 21:52:50 +0000739 // expected-warning {{calling function 'aa_elr_fun' requires exclusive lock on 'aa_mu'}}
Caitlin Sadowski978191e2011-09-08 18:27:31 +0000740}
741
742void es_bad_1() {
743 aa_mu.ReaderLock();
744 Bar.aa_elr_fun(); // \
Caitlin Sadowski8bccabe2011-09-08 21:52:50 +0000745 // expected-warning {{calling function 'aa_elr_fun' requires exclusive lock on 'aa_mu'}}
Caitlin Sadowski978191e2011-09-08 18:27:31 +0000746 aa_mu.Unlock();
747}
748
749void es_bad_2() {
750 Bar.aa_elr_fun_s(); // \
Caitlin Sadowski8bccabe2011-09-08 21:52:50 +0000751 // expected-warning {{calling function 'aa_elr_fun_s' requires shared lock on 'aa_mu'}}
Caitlin Sadowski978191e2011-09-08 18:27:31 +0000752}
753
754void es_bad_3() {
755 MyLRFoo.test(); // \
Caitlin Sadowski8bccabe2011-09-08 21:52:50 +0000756 // expected-warning {{calling function 'test' requires exclusive lock on 'sls_mu'}}
Caitlin Sadowski978191e2011-09-08 18:27:31 +0000757}
758
759void es_bad_4() {
760 MyLRFoo.testShared(); // \
Caitlin Sadowski8bccabe2011-09-08 21:52:50 +0000761 // expected-warning {{calling function 'testShared' requires shared lock on 'sls_mu2'}}
Caitlin Sadowski978191e2011-09-08 18:27:31 +0000762}
763
764void es_bad_5() {
765 sls_mu.ReaderLock();
766 MyLRFoo.test(); // \
Caitlin Sadowski8bccabe2011-09-08 21:52:50 +0000767 // expected-warning {{calling function 'test' requires exclusive lock on 'sls_mu'}}
Caitlin Sadowski978191e2011-09-08 18:27:31 +0000768 sls_mu.Unlock();
769}
770
771void es_bad_6() {
772 sls_mu.Lock();
773 Bar.le_fun(); // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000774 // expected-warning {{cannot call function 'le_fun' while mutex 'sls_mu' is locked}}
Caitlin Sadowski978191e2011-09-08 18:27:31 +0000775 sls_mu.Unlock();
776}
777
778void es_bad_7() {
779 sls_mu.ReaderLock();
780 Bar.le_fun(); // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000781 // expected-warning {{cannot call function 'le_fun' while mutex 'sls_mu' is locked}}
Caitlin Sadowski978191e2011-09-08 18:27:31 +0000782 sls_mu.Unlock();
783}
Caitlin Sadowski194418f2011-09-14 20:00:24 +0000784
DeLesley Hutchins81216392011-10-17 21:38:02 +0000785
Caitlin Sadowski194418f2011-09-14 20:00:24 +0000786//-----------------------------------------------//
787// Unparseable lock expressions
788// ----------------------------------------------//
789
DeLesley Hutchins0d95dfc2012-03-02 23:36:05 +0000790// FIXME -- derive new tests for unhandled expressions
Caitlin Sadowski194418f2011-09-14 20:00:24 +0000791
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +0000792
793//----------------------------------------------------------------------------//
794// The following test cases are ported from the gcc thread safety implementation
795// They are each wrapped inside a namespace with the test number of the gcc test
796//
797// FIXME: add all the gcc tests, once this analysis passes them.
798//----------------------------------------------------------------------------//
799
800//-----------------------------------------//
801// Good testcases (no errors)
802//-----------------------------------------//
803
804namespace thread_annot_lock_20 {
805class Bar {
806 public:
807 static int func1() EXCLUSIVE_LOCKS_REQUIRED(mu1_);
808 static int b_ GUARDED_BY(mu1_);
809 static Mutex mu1_;
810 static int a_ GUARDED_BY(mu1_);
811};
812
813Bar b1;
814
815int Bar::func1()
816{
817 int res = 5;
818
819 if (a_ == 4)
820 res = b_;
821 return res;
822}
823} // end namespace thread_annot_lock_20
824
825namespace thread_annot_lock_22 {
826// Test various usage of GUARDED_BY and PT_GUARDED_BY annotations, especially
827// uses in class definitions.
828Mutex mu;
829
830class Bar {
831 public:
832 int a_ GUARDED_BY(mu1_);
833 int b_;
834 int *q PT_GUARDED_BY(mu);
835 Mutex mu1_ ACQUIRED_AFTER(mu);
836};
837
838Bar b1, *b3;
839int *p GUARDED_BY(mu) PT_GUARDED_BY(mu);
840int res GUARDED_BY(mu) = 5;
841
842int func(int i)
843{
844 int x;
845 mu.Lock();
846 b1.mu1_.Lock();
847 res = b1.a_ + b3->b_;
848 *p = i;
849 b1.a_ = res + b3->b_;
850 b3->b_ = *b1.q;
851 b1.mu1_.Unlock();
852 b1.b_ = res;
853 x = res;
854 mu.Unlock();
855 return x;
856}
857} // end namespace thread_annot_lock_22
858
859namespace thread_annot_lock_27_modified {
860// test lock annotations applied to function definitions
861// Modified: applied annotations only to function declarations
862Mutex mu1;
863Mutex mu2 ACQUIRED_AFTER(mu1);
864
865class Foo {
866 public:
867 int method1(int i) SHARED_LOCKS_REQUIRED(mu2) EXCLUSIVE_LOCKS_REQUIRED(mu1);
868};
869
870int Foo::method1(int i) {
871 return i;
872}
873
874
875int foo(int i) EXCLUSIVE_LOCKS_REQUIRED(mu2) SHARED_LOCKS_REQUIRED(mu1);
876int foo(int i) {
877 return i;
878}
879
880static int bar(int i) EXCLUSIVE_LOCKS_REQUIRED(mu1);
881static int bar(int i) {
882 return i;
883}
884
885void main() {
886 Foo a;
887
888 mu1.Lock();
889 mu2.Lock();
890 a.method1(1);
891 foo(2);
892 mu2.Unlock();
893 bar(3);
894 mu1.Unlock();
895}
896} // end namespace thread_annot_lock_27_modified
897
898
899namespace thread_annot_lock_38 {
900// Test the case where a template member function is annotated with lock
901// attributes in a non-template class.
902class Foo {
903 public:
904 void func1(int y) LOCKS_EXCLUDED(mu_);
905 template <typename T> void func2(T x) LOCKS_EXCLUDED(mu_);
906 private:
907 Mutex mu_;
908};
909
910Foo *foo;
911
912void main()
913{
914 foo->func1(5);
915 foo->func2(5);
916}
917} // end namespace thread_annot_lock_38
918
919namespace thread_annot_lock_43 {
920// Tests lock canonicalization
921class Foo {
922 public:
923 Mutex *mu_;
924};
925
926class FooBar {
927 public:
928 Foo *foo_;
929 int GetA() EXCLUSIVE_LOCKS_REQUIRED(foo_->mu_) { return a_; }
930 int a_ GUARDED_BY(foo_->mu_);
931};
932
933FooBar *fb;
934
935void main()
936{
937 int x;
938 fb->foo_->mu_->Lock();
939 x = fb->GetA();
940 fb->foo_->mu_->Unlock();
941}
942} // end namespace thread_annot_lock_43
943
944namespace thread_annot_lock_49 {
945// Test the support for use of lock expression in the annotations
946class Foo {
947 public:
948 Mutex foo_mu_;
949};
950
951class Bar {
952 private:
953 Foo *foo;
954 Mutex bar_mu_ ACQUIRED_AFTER(foo->foo_mu_);
955
956 public:
957 void Test1() {
958 foo->foo_mu_.Lock();
959 bar_mu_.Lock();
960 bar_mu_.Unlock();
961 foo->foo_mu_.Unlock();
962 }
963};
964
965void main() {
966 Bar bar;
967 bar.Test1();
968}
969} // end namespace thread_annot_lock_49
970
971namespace thread_annot_lock_61_modified {
972 // Modified to fix the compiler errors
973 // Test the fix for a bug introduced by the support of pass-by-reference
974 // paramters.
975 struct Foo { Foo &operator<< (bool) {return *this;} };
976 Foo &getFoo();
977 struct Bar { Foo &func () {return getFoo();} };
978 struct Bas { void operator& (Foo &) {} };
979 void mumble()
980 {
981 Bas() & Bar().func() << "" << "";
982 Bas() & Bar().func() << "";
983 }
984} // end namespace thread_annot_lock_61_modified
985
986
987namespace thread_annot_lock_65 {
988// Test the fix for a bug in the support of allowing reader locks for
989// non-const, non-modifying overload functions. (We didn't handle the builtin
990// properly.)
991enum MyFlags {
992 Zero,
993 One,
994 Two,
995 Three,
996 Four,
997 Five,
998 Six,
999 Seven,
1000 Eight,
1001 Nine
1002};
1003
1004inline MyFlags
1005operator|(MyFlags a, MyFlags b)
1006{
1007 return MyFlags(static_cast<int>(a) | static_cast<int>(b));
1008}
1009
1010inline MyFlags&
1011operator|=(MyFlags& a, MyFlags b)
1012{
1013 return a = a | b;
1014}
1015} // end namespace thread_annot_lock_65
1016
1017namespace thread_annot_lock_66_modified {
1018// Modified: Moved annotation to function defn
1019// Test annotations on out-of-line definitions of member functions where the
1020// annotations refer to locks that are also data members in the class.
1021Mutex mu;
1022
1023class Foo {
1024 public:
1025 int method1(int i) SHARED_LOCKS_REQUIRED(mu1, mu, mu2);
1026 int data GUARDED_BY(mu1);
1027 Mutex *mu1;
1028 Mutex *mu2;
1029};
1030
1031int Foo::method1(int i)
1032{
1033 return data + i;
1034}
1035
1036void main()
1037{
1038 Foo a;
1039
1040 a.mu2->Lock();
1041 a.mu1->Lock();
1042 mu.Lock();
1043 a.method1(1);
1044 mu.Unlock();
1045 a.mu1->Unlock();
1046 a.mu2->Unlock();
1047}
1048} // end namespace thread_annot_lock_66_modified
1049
1050namespace thread_annot_lock_68_modified {
1051// Test a fix to a bug in the delayed name binding with nested template
1052// instantiation. We use a stack to make sure a name is not resolved to an
1053// inner context.
1054template <typename T>
1055class Bar {
1056 Mutex mu_;
1057};
1058
1059template <typename T>
1060class Foo {
1061 public:
1062 void func(T x) {
1063 mu_.Lock();
DeLesley Hutchins23323e02012-01-20 22:50:54 +00001064 count_ = x;
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001065 mu_.Unlock();
1066 }
1067
1068 private:
DeLesley Hutchins23323e02012-01-20 22:50:54 +00001069 T count_ GUARDED_BY(mu_);
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001070 Bar<T> bar_;
1071 Mutex mu_;
1072};
1073
1074void main()
1075{
1076 Foo<int> *foo;
1077 foo->func(5);
1078}
1079} // end namespace thread_annot_lock_68_modified
1080
1081namespace thread_annot_lock_30_modified {
1082// Test delay parsing of lock attribute arguments with nested classes.
1083// Modified: trylocks replaced with exclusive_lock_fun
1084int a = 0;
1085
1086class Bar {
1087 struct Foo;
1088
1089 public:
1090 void MyLock() EXCLUSIVE_LOCK_FUNCTION(mu);
1091
1092 int func() {
1093 MyLock();
1094// if (foo == 0) {
1095// return 0;
1096// }
1097 a = 5;
1098 mu.Unlock();
1099 return 1;
1100 }
1101
1102 class FooBar {
1103 int x;
1104 int y;
1105 };
1106
1107 private:
1108 Mutex mu;
1109};
1110
1111Bar *bar;
1112
1113void main()
1114{
1115 bar->func();
1116}
1117} // end namespace thread_annot_lock_30_modified
1118
1119namespace thread_annot_lock_47 {
1120// Test the support for annotations on virtual functions.
1121// This is a good test case. (i.e. There should be no warning emitted by the
1122// compiler.)
1123class Base {
1124 public:
1125 virtual void func1() EXCLUSIVE_LOCKS_REQUIRED(mu_);
1126 virtual void func2() LOCKS_EXCLUDED(mu_);
1127 Mutex mu_;
1128};
1129
1130class Child : public Base {
1131 public:
1132 virtual void func1() EXCLUSIVE_LOCKS_REQUIRED(mu_);
1133 virtual void func2() LOCKS_EXCLUDED(mu_);
1134};
1135
1136void main() {
1137 Child *c;
1138 Base *b = c;
1139
1140 b->mu_.Lock();
1141 b->func1();
1142 b->mu_.Unlock();
1143 b->func2();
1144
1145 c->mu_.Lock();
1146 c->func1();
1147 c->mu_.Unlock();
1148 c->func2();
1149}
1150} // end namespace thread_annot_lock_47
1151
1152//-----------------------------------------//
1153// Tests which produce errors
1154//-----------------------------------------//
1155
1156namespace thread_annot_lock_13 {
1157Mutex mu1;
1158Mutex mu2;
1159
1160int g GUARDED_BY(mu1);
1161int w GUARDED_BY(mu2);
1162
1163class Foo {
1164 public:
1165 void bar() LOCKS_EXCLUDED(mu_, mu1);
1166 int foo() SHARED_LOCKS_REQUIRED(mu_) EXCLUSIVE_LOCKS_REQUIRED(mu2);
1167
1168 private:
1169 int a_ GUARDED_BY(mu_);
1170 public:
1171 Mutex mu_ ACQUIRED_AFTER(mu1);
1172};
1173
1174int Foo::foo()
1175{
1176 int res;
David Blaikiee31b8fb2012-04-05 00:16:44 +00001177 w = 5;
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001178 res = a_ + 5;
1179 return res;
1180}
1181
1182void Foo::bar()
1183{
1184 int x;
1185 mu_.Lock();
1186 x = foo(); // expected-warning {{calling function 'foo' requires exclusive lock on 'mu2'}}
1187 a_ = x + 1;
1188 mu_.Unlock();
1189 if (x > 5) {
1190 mu1.Lock();
David Blaikiee31b8fb2012-04-05 00:16:44 +00001191 g = 2;
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001192 mu1.Unlock();
1193 }
1194}
1195
1196void main()
1197{
1198 Foo f1, *f2;
1199 f1.mu_.Lock();
Caitlin Sadowski74558b42011-09-15 18:13:32 +00001200 f1.bar(); // expected-warning {{cannot call function 'bar' while mutex 'mu_' is locked}}
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001201 mu2.Lock();
1202 f1.foo();
1203 mu2.Unlock();
1204 f1.mu_.Unlock();
1205 f2->mu_.Lock();
Caitlin Sadowski74558b42011-09-15 18:13:32 +00001206 f2->bar(); // expected-warning {{cannot call function 'bar' while mutex 'mu_' is locked}}
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001207 f2->mu_.Unlock();
1208 mu2.Lock();
David Blaikiee31b8fb2012-04-05 00:16:44 +00001209 w = 2;
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001210 mu2.Unlock();
1211}
1212} // end namespace thread_annot_lock_13
1213
1214namespace thread_annot_lock_18_modified {
1215// Modified: Trylocks removed
1216// Test the ability to distnguish between the same lock field of
1217// different objects of a class.
1218 class Bar {
1219 public:
1220 bool MyLock() EXCLUSIVE_LOCK_FUNCTION(mu1_);
1221 void MyUnlock() UNLOCK_FUNCTION(mu1_);
1222 int a_ GUARDED_BY(mu1_);
1223
1224 private:
1225 Mutex mu1_;
1226};
1227
1228Bar *b1, *b2;
1229
1230void func()
1231{
1232 b1->MyLock();
1233 b1->a_ = 5;
Caitlin Sadowski74558b42011-09-15 18:13:32 +00001234 b2->a_ = 3; // expected-warning {{writing variable 'a_' requires locking 'mu1_' exclusively}}
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001235 b2->MyLock();
1236 b2->MyUnlock();
1237 b1->MyUnlock();
1238}
1239} // end namespace thread_annot_lock_18_modified
1240
1241namespace thread_annot_lock_21 {
1242// Test various usage of GUARDED_BY and PT_GUARDED_BY annotations, especially
1243// uses in class definitions.
1244Mutex mu;
1245
1246class Bar {
1247 public:
1248 int a_ GUARDED_BY(mu1_);
1249 int b_;
1250 int *q PT_GUARDED_BY(mu);
1251 Mutex mu1_ ACQUIRED_AFTER(mu);
1252};
1253
1254Bar b1, *b3;
1255int *p GUARDED_BY(mu) PT_GUARDED_BY(mu);
1256
1257int res GUARDED_BY(mu) = 5;
1258
1259int func(int i)
1260{
1261 int x;
1262 b3->mu1_.Lock();
Caitlin Sadowski74558b42011-09-15 18:13:32 +00001263 res = b1.a_ + b3->b_; // expected-warning {{reading variable 'a_' requires locking 'mu1_'}} \
1264 // expected-warning {{writing variable 'res' requires locking 'mu' exclusively}}
1265 *p = i; // expected-warning {{reading variable 'p' requires locking 'mu'}} \
1266 // expected-warning {{writing the value pointed to by 'p' requires locking 'mu' exclusively}}
1267 b1.a_ = res + b3->b_; // expected-warning {{reading variable 'res' requires locking 'mu'}} \
1268 // expected-warning {{writing variable 'a_' requires locking 'mu1_' exclusively}}
1269 b3->b_ = *b1.q; // expected-warning {{reading the value pointed to by 'q' requires locking 'mu'}}
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001270 b3->mu1_.Unlock();
Caitlin Sadowski74558b42011-09-15 18:13:32 +00001271 b1.b_ = res; // expected-warning {{reading variable 'res' requires locking 'mu'}}
1272 x = res; // expected-warning {{reading variable 'res' requires locking 'mu'}}
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001273 return x;
1274}
1275} // end namespace thread_annot_lock_21
1276
1277namespace thread_annot_lock_35_modified {
1278// Test the analyzer's ability to distinguish the lock field of different
1279// objects.
1280class Foo {
1281 private:
1282 Mutex lock_;
1283 int a_ GUARDED_BY(lock_);
1284
1285 public:
1286 void Func(Foo* child) LOCKS_EXCLUDED(lock_) {
1287 Foo *new_foo = new Foo;
1288
1289 lock_.Lock();
1290
1291 child->Func(new_foo); // There shouldn't be any warning here as the
1292 // acquired lock is not in child.
1293 child->bar(7); // expected-warning {{calling function 'bar' requires exclusive lock on 'lock_'}}
Caitlin Sadowski74558b42011-09-15 18:13:32 +00001294 child->a_ = 5; // expected-warning {{writing variable 'a_' requires locking 'lock_' exclusively}}
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001295 lock_.Unlock();
1296 }
1297
1298 void bar(int y) EXCLUSIVE_LOCKS_REQUIRED(lock_) {
1299 a_ = y;
1300 }
1301};
1302
1303Foo *x;
1304
1305void main() {
1306 Foo *child = new Foo;
1307 x->Func(child);
1308}
1309} // end namespace thread_annot_lock_35_modified
1310
1311namespace thread_annot_lock_36_modified {
1312// Modified to move the annotations to function defns.
1313// Test the analyzer's ability to distinguish the lock field of different
1314// objects
1315class Foo {
1316 private:
1317 Mutex lock_;
1318 int a_ GUARDED_BY(lock_);
1319
1320 public:
1321 void Func(Foo* child) LOCKS_EXCLUDED(lock_);
1322 void bar(int y) EXCLUSIVE_LOCKS_REQUIRED(lock_);
1323};
1324
1325void Foo::Func(Foo* child) {
1326 Foo *new_foo = new Foo;
1327
1328 lock_.Lock();
1329
1330 child->lock_.Lock();
Caitlin Sadowski74558b42011-09-15 18:13:32 +00001331 child->Func(new_foo); // expected-warning {{cannot call function 'Func' while mutex 'lock_' is locked}}
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001332 child->bar(7);
1333 child->a_ = 5;
1334 child->lock_.Unlock();
1335
1336 lock_.Unlock();
1337}
1338
1339void Foo::bar(int y) {
1340 a_ = y;
1341}
1342
1343
1344Foo *x;
1345
1346void main() {
1347 Foo *child = new Foo;
1348 x->Func(child);
1349}
1350} // end namespace thread_annot_lock_36_modified
1351
1352
1353namespace thread_annot_lock_42 {
1354// Test support of multiple lock attributes of the same kind on a decl.
1355class Foo {
1356 private:
1357 Mutex mu1, mu2, mu3;
1358 int x GUARDED_BY(mu1) GUARDED_BY(mu2);
1359 int y GUARDED_BY(mu2);
1360
1361 void f2() LOCKS_EXCLUDED(mu1) LOCKS_EXCLUDED(mu2) LOCKS_EXCLUDED(mu3) {
1362 mu2.Lock();
1363 y = 2;
1364 mu2.Unlock();
1365 }
1366
1367 public:
1368 void f1() EXCLUSIVE_LOCKS_REQUIRED(mu2) EXCLUSIVE_LOCKS_REQUIRED(mu1) {
1369 x = 5;
Caitlin Sadowski74558b42011-09-15 18:13:32 +00001370 f2(); // expected-warning {{cannot call function 'f2' while mutex 'mu1' is locked}} \
1371 // expected-warning {{cannot call function 'f2' while mutex 'mu2' is locked}}
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001372 }
1373};
1374
1375Foo *foo;
1376
1377void func()
1378{
1379 foo->f1(); // expected-warning {{calling function 'f1' requires exclusive lock on 'mu2'}} \
1380 // expected-warning {{calling function 'f1' requires exclusive lock on 'mu1'}}
1381}
1382} // end namespace thread_annot_lock_42
1383
1384namespace thread_annot_lock_46 {
1385// Test the support for annotations on virtual functions.
1386class Base {
1387 public:
1388 virtual void func1() EXCLUSIVE_LOCKS_REQUIRED(mu_);
1389 virtual void func2() LOCKS_EXCLUDED(mu_);
1390 Mutex mu_;
1391};
1392
1393class Child : public Base {
1394 public:
1395 virtual void func1() EXCLUSIVE_LOCKS_REQUIRED(mu_);
1396 virtual void func2() LOCKS_EXCLUDED(mu_);
1397};
1398
1399void main() {
1400 Child *c;
1401 Base *b = c;
1402
1403 b->func1(); // expected-warning {{calling function 'func1' requires exclusive lock on 'mu_'}}
1404 b->mu_.Lock();
Caitlin Sadowski74558b42011-09-15 18:13:32 +00001405 b->func2(); // expected-warning {{cannot call function 'func2' while mutex 'mu_' is locked}}
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001406 b->mu_.Unlock();
1407
1408 c->func1(); // expected-warning {{calling function 'func1' requires exclusive lock on 'mu_'}}
1409 c->mu_.Lock();
Caitlin Sadowski74558b42011-09-15 18:13:32 +00001410 c->func2(); // expected-warning {{cannot call function 'func2' while mutex 'mu_' is locked}}
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001411 c->mu_.Unlock();
1412}
1413} // end namespace thread_annot_lock_46
1414
1415namespace thread_annot_lock_67_modified {
1416// Modified: attributes on definitions moved to declarations
1417// Test annotations on out-of-line definitions of member functions where the
1418// annotations refer to locks that are also data members in the class.
1419Mutex mu;
1420Mutex mu3;
1421
1422class Foo {
1423 public:
1424 int method1(int i) SHARED_LOCKS_REQUIRED(mu1, mu, mu2, mu3);
1425 int data GUARDED_BY(mu1);
1426 Mutex *mu1;
1427 Mutex *mu2;
1428};
1429
1430int Foo::method1(int i) {
1431 return data + i;
1432}
1433
1434void main()
1435{
1436 Foo a;
1437 a.method1(1); // expected-warning {{calling function 'method1' requires shared lock on 'mu1'}} \
1438 // expected-warning {{calling function 'method1' requires shared lock on 'mu'}} \
1439 // expected-warning {{calling function 'method1' requires shared lock on 'mu2'}} \
1440 // expected-warning {{calling function 'method1' requires shared lock on 'mu3'}}
1441}
1442} // end namespace thread_annot_lock_67_modified
1443
1444
DeLesley Hutchins81216392011-10-17 21:38:02 +00001445namespace substitution_test {
1446 class MyData {
1447 public:
1448 Mutex mu;
1449
1450 void lockData() __attribute__((exclusive_lock_function(mu))) { }
1451 void unlockData() __attribute__((unlock_function(mu))) { }
1452
1453 void doSomething() __attribute__((exclusive_locks_required(mu))) { }
1454 };
1455
1456
1457 class DataLocker {
1458 public:
1459 void lockData (MyData *d) __attribute__((exclusive_lock_function(d->mu))) { }
1460 void unlockData(MyData *d) __attribute__((unlock_function(d->mu))) { }
1461 };
1462
1463
1464 class Foo {
1465 public:
1466 void foo(MyData* d) __attribute__((exclusive_locks_required(d->mu))) { }
1467
1468 void bar1(MyData* d) {
1469 d->lockData();
1470 foo(d);
1471 d->unlockData();
1472 }
1473
1474 void bar2(MyData* d) {
1475 DataLocker dlr;
1476 dlr.lockData(d);
1477 foo(d);
1478 dlr.unlockData(d);
1479 }
1480
1481 void bar3(MyData* d1, MyData* d2) {
1482 DataLocker dlr;
Richard Smith2e515622012-02-03 04:45:26 +00001483 dlr.lockData(d1); // expected-note {{mutex acquired here}}
DeLesley Hutchins81216392011-10-17 21:38:02 +00001484 dlr.unlockData(d2); // \
1485 // expected-warning {{unlocking 'mu' that was not locked}}
Richard Smith2e515622012-02-03 04:45:26 +00001486 } // expected-warning {{mutex 'mu' is still locked at the end of function}}
DeLesley Hutchins81216392011-10-17 21:38:02 +00001487
1488 void bar4(MyData* d1, MyData* d2) {
1489 DataLocker dlr;
1490 dlr.lockData(d1);
1491 foo(d2); // \
1492 // expected-warning {{calling function 'foo' requires exclusive lock on 'mu'}}
1493 dlr.unlockData(d1);
1494 }
1495 };
1496} // end namespace substituation_test
1497
DeLesley Hutchinse0eaa852011-10-21 18:06:53 +00001498
DeLesley Hutchinsf1ac6372011-10-21 18:10:14 +00001499
DeLesley Hutchinse0eaa852011-10-21 18:06:53 +00001500namespace constructor_destructor_tests {
1501 Mutex fooMu;
1502 int myVar GUARDED_BY(fooMu);
1503
1504 class Foo {
1505 public:
1506 Foo() __attribute__((exclusive_lock_function(fooMu))) { }
1507 ~Foo() __attribute__((unlock_function(fooMu))) { }
1508 };
1509
1510 void fooTest() {
DeLesley Hutchins6db51f72011-10-21 20:51:27 +00001511 Foo foo;
DeLesley Hutchinse0eaa852011-10-21 18:06:53 +00001512 myVar = 0;
1513 }
1514}
1515
DeLesley Hutchinsf1ac6372011-10-21 18:10:14 +00001516
1517namespace invalid_lock_expression_test {
1518
1519class LOCKABLE MyLockable {
1520public:
1521 MyLockable() __attribute__((exclusive_lock_function)) { }
DeLesley Hutchins6db51f72011-10-21 20:51:27 +00001522 ~MyLockable() { }
DeLesley Hutchinsf1ac6372011-10-21 18:10:14 +00001523};
1524
1525// create an empty lock expression
1526void foo() {
1527 MyLockable lock; // \
1528 // expected-warning {{cannot resolve lock expression}}
1529}
1530
1531} // end namespace invalid_lock_expression_test
1532
Richard Smith97f9fe02011-10-25 00:41:24 +00001533namespace template_member_test {
DeLesley Hutchinsf1ac6372011-10-21 18:10:14 +00001534
Richard Smith97f9fe02011-10-25 00:41:24 +00001535 struct S { int n; };
1536 struct T {
1537 Mutex m;
1538 S *s GUARDED_BY(this->m);
1539 };
Richard Smitha01c7112011-10-25 06:33:21 +00001540 Mutex m;
1541 struct U {
1542 union {
1543 int n;
1544 };
1545 } *u GUARDED_BY(m);
Richard Smith97f9fe02011-10-25 00:41:24 +00001546
1547 template<typename U>
1548 struct IndirectLock {
1549 int DoNaughtyThings(T *t) {
Richard Smitha01c7112011-10-25 06:33:21 +00001550 u->n = 0; // expected-warning {{reading variable 'u' requires locking 'm'}}
Richard Smith97f9fe02011-10-25 00:41:24 +00001551 return t->s->n; // expected-warning {{reading variable 's' requires locking 'm'}}
1552 }
1553 };
1554
Richard Smithf11e9232011-10-25 01:05:41 +00001555 template struct IndirectLock<int>; // expected-note {{here}}
Richard Smith97f9fe02011-10-25 00:41:24 +00001556
Richard Smith601d2ee2011-10-26 06:15:36 +00001557 struct V {
1558 void f(int);
1559 void f(double);
1560
1561 Mutex m;
1562 V *p GUARDED_BY(this->m);
1563 };
1564 template<typename U> struct W {
1565 V v;
1566 void f(U u) {
1567 v.p->f(u); // expected-warning {{reading variable 'p' requires locking 'm'}}
1568 }
1569 };
1570 template struct W<int>; // expected-note {{here}}
1571
Richard Smith97f9fe02011-10-25 00:41:24 +00001572}
DeLesley Hutchins1fa3c062011-12-08 20:23:06 +00001573
1574namespace test_scoped_lockable {
1575
1576struct TestScopedLockable {
1577 Mutex mu1;
1578 Mutex mu2;
1579 int a __attribute__((guarded_by(mu1)));
1580 int b __attribute__((guarded_by(mu2)));
1581
1582 bool getBool();
1583
1584 void foo1() {
1585 MutexLock mulock(&mu1);
1586 a = 5;
1587 }
1588
1589 void foo2() {
1590 ReaderMutexLock mulock1(&mu1);
1591 if (getBool()) {
1592 MutexLock mulock2a(&mu2);
1593 b = a + 1;
1594 }
1595 else {
1596 MutexLock mulock2b(&mu2);
1597 b = a + 2;
1598 }
1599 }
1600
1601 void foo3() {
1602 MutexLock mulock_a(&mu1);
1603 MutexLock mulock_b(&mu1); // \
1604 // expected-warning {{locking 'mu1' that is already locked}}
DeLesley Hutchinsc99a5d82012-06-28 22:42:48 +00001605 }
DeLesley Hutchins1fa3c062011-12-08 20:23:06 +00001606
1607 void foo4() {
1608 MutexLock mulock1(&mu1), mulock2(&mu2);
1609 a = b+1;
1610 b = a+1;
1611 }
1612};
1613
1614} // end namespace test_scoped_lockable
1615
1616
DeLesley Hutchinsdf497822011-12-29 00:56:48 +00001617namespace FunctionAttrTest {
1618
1619class Foo {
1620public:
1621 Mutex mu_;
1622 int a GUARDED_BY(mu_);
1623};
1624
1625Foo fooObj;
1626
1627void foo() EXCLUSIVE_LOCKS_REQUIRED(fooObj.mu_);
1628
1629void bar() {
1630 foo(); // expected-warning {{calling function 'foo' requires exclusive lock on 'mu_'}}
1631 fooObj.mu_.Lock();
1632 foo();
1633 fooObj.mu_.Unlock();
1634}
1635
1636}; // end namespace FunctionAttrTest
1637
1638
DeLesley Hutchinsb4fa4182012-01-06 19:16:50 +00001639struct TestTryLock {
1640 Mutex mu;
1641 int a GUARDED_BY(mu);
1642 bool cond;
1643
1644 void foo1() {
1645 if (mu.TryLock()) {
1646 a = 1;
1647 mu.Unlock();
1648 }
1649 }
1650
1651 void foo2() {
1652 if (!mu.TryLock()) return;
1653 a = 2;
1654 mu.Unlock();
1655 }
1656
1657 void foo3() {
1658 bool b = mu.TryLock();
1659 if (b) {
1660 a = 3;
1661 mu.Unlock();
1662 }
1663 }
1664
1665 void foo4() {
1666 bool b = mu.TryLock();
1667 if (!b) return;
1668 a = 4;
1669 mu.Unlock();
1670 }
1671
1672 void foo5() {
1673 while (mu.TryLock()) {
1674 a = a + 1;
1675 mu.Unlock();
1676 }
1677 }
1678
1679 void foo6() {
1680 bool b = mu.TryLock();
1681 b = !b;
1682 if (b) return;
1683 a = 6;
1684 mu.Unlock();
1685 }
1686
1687 void foo7() {
1688 bool b1 = mu.TryLock();
1689 bool b2 = !b1;
1690 bool b3 = !b2;
1691 if (b3) {
1692 a = 7;
1693 mu.Unlock();
1694 }
1695 }
1696
1697 // Test use-def chains: join points
1698 void foo8() {
1699 bool b = mu.TryLock();
1700 bool b2 = b;
1701 if (cond)
1702 b = true;
1703 if (b) { // b should be unknown at this point, becuase of the join point
1704 a = 8; // expected-warning {{writing variable 'a' requires locking 'mu' exclusively}}
1705 }
1706 if (b2) { // b2 should be known at this point.
1707 a = 8;
1708 mu.Unlock();
1709 }
1710 }
1711
1712 // Test use-def-chains: back edges
1713 void foo9() {
1714 bool b = mu.TryLock();
1715
1716 for (int i = 0; i < 10; ++i);
1717
1718 if (b) { // b is still known, because the loop doesn't alter it
1719 a = 9;
1720 mu.Unlock();
1721 }
1722 }
1723
1724 // Test use-def chains: back edges
1725 void foo10() {
1726 bool b = mu.TryLock();
1727
1728 while (cond) {
1729 if (b) { // b should be uknown at this point b/c of the loop
1730 a = 10; // expected-warning {{writing variable 'a' requires locking 'mu' exclusively}}
1731 }
1732 b = !b;
1733 }
1734 }
1735}; // end TestTrylock
1736
1737
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +00001738namespace TestTemplateAttributeInstantiation {
1739
1740class Foo1 {
1741public:
1742 Mutex mu_;
1743 int a GUARDED_BY(mu_);
1744};
1745
1746class Foo2 {
1747public:
1748 int a GUARDED_BY(mu_);
1749 Mutex mu_;
1750};
1751
1752
1753class Bar {
1754public:
1755 // Test non-dependent expressions in attributes on template functions
1756 template <class T>
1757 void barND(Foo1 *foo, T *fooT) EXCLUSIVE_LOCKS_REQUIRED(foo->mu_) {
1758 foo->a = 0;
1759 }
1760
1761 // Test dependent expressions in attributes on template functions
1762 template <class T>
1763 void barD(Foo1 *foo, T *fooT) EXCLUSIVE_LOCKS_REQUIRED(fooT->mu_) {
1764 fooT->a = 0;
1765 }
1766};
1767
1768
1769template <class T>
1770class BarT {
1771public:
1772 Foo1 fooBase;
1773 T fooBaseT;
1774
1775 // Test non-dependent expression in ordinary method on template class
1776 void barND() EXCLUSIVE_LOCKS_REQUIRED(fooBase.mu_) {
1777 fooBase.a = 0;
1778 }
1779
1780 // Test dependent expressions in ordinary methods on template class
1781 void barD() EXCLUSIVE_LOCKS_REQUIRED(fooBaseT.mu_) {
1782 fooBaseT.a = 0;
1783 }
1784
1785 // Test dependent expressions in template method in template class
1786 template <class T2>
1787 void barTD(T2 *fooT) EXCLUSIVE_LOCKS_REQUIRED(fooBaseT.mu_, fooT->mu_) {
1788 fooBaseT.a = 0;
1789 fooT->a = 0;
1790 }
1791};
1792
1793template <class T>
1794class Cell {
1795public:
1796 Mutex mu_;
1797 // Test dependent guarded_by
1798 T data GUARDED_BY(mu_);
1799
DeLesley Hutchins23323e02012-01-20 22:50:54 +00001800 void fooEx() EXCLUSIVE_LOCKS_REQUIRED(mu_) {
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +00001801 data = 0;
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +00001802 }
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +00001803
1804 void foo() {
1805 mu_.Lock();
1806 data = 0;
1807 mu_.Unlock();
1808 }
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +00001809};
1810
1811void test() {
1812 Bar b;
1813 BarT<Foo2> bt;
1814 Foo1 f1;
1815 Foo2 f2;
1816
1817 f1.mu_.Lock();
1818 f2.mu_.Lock();
1819 bt.fooBase.mu_.Lock();
1820 bt.fooBaseT.mu_.Lock();
1821
1822 b.barND(&f1, &f2);
1823 b.barD(&f1, &f2);
1824 bt.barND();
1825 bt.barD();
1826 bt.barTD(&f2);
1827
1828 f1.mu_.Unlock();
1829 bt.barTD(&f1); // \
1830 // expected-warning {{calling function 'barTD' requires exclusive lock on 'mu_'}}
1831
1832 bt.fooBase.mu_.Unlock();
1833 bt.fooBaseT.mu_.Unlock();
1834 f2.mu_.Unlock();
1835
1836 Cell<int> cell;
1837 cell.data = 0; // \
1838 // expected-warning {{writing variable 'data' requires locking 'mu_' exclusively}}
1839 cell.foo();
DeLesley Hutchins23323e02012-01-20 22:50:54 +00001840 cell.mu_.Lock();
1841 cell.fooEx();
1842 cell.mu_.Unlock();
1843}
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +00001844
DeLesley Hutchins23323e02012-01-20 22:50:54 +00001845
1846template <class T>
1847class CellDelayed {
1848public:
1849 // Test dependent guarded_by
1850 T data GUARDED_BY(mu_);
DeLesley Hutchinsdd5756c2012-02-16 17:30:51 +00001851 static T static_data GUARDED_BY(static_mu_);
DeLesley Hutchins23323e02012-01-20 22:50:54 +00001852
1853 void fooEx(CellDelayed<T> *other) EXCLUSIVE_LOCKS_REQUIRED(mu_, other->mu_) {
1854 this->data = other->data;
1855 }
1856
1857 template <class T2>
1858 void fooExT(CellDelayed<T2> *otherT) EXCLUSIVE_LOCKS_REQUIRED(mu_, otherT->mu_) {
1859 this->data = otherT->data;
1860 }
1861
1862 void foo() {
1863 mu_.Lock();
1864 data = 0;
1865 mu_.Unlock();
1866 }
1867
1868 Mutex mu_;
DeLesley Hutchinsdd5756c2012-02-16 17:30:51 +00001869 static Mutex static_mu_;
DeLesley Hutchins23323e02012-01-20 22:50:54 +00001870};
1871
1872void testDelayed() {
1873 CellDelayed<int> celld;
1874 CellDelayed<int> celld2;
1875 celld.foo();
1876 celld.mu_.Lock();
1877 celld2.mu_.Lock();
1878
1879 celld.fooEx(&celld2);
1880 celld.fooExT(&celld2);
1881
1882 celld2.mu_.Unlock();
1883 celld.mu_.Unlock();
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +00001884}
1885
1886}; // end namespace TestTemplateAttributeInstantiation
1887
1888
DeLesley Hutchinse03b2b32012-01-20 23:24:41 +00001889namespace FunctionDeclDefTest {
1890
1891class Foo {
1892public:
1893 Mutex mu_;
1894 int a GUARDED_BY(mu_);
1895
1896 virtual void foo1(Foo *f_declared) EXCLUSIVE_LOCKS_REQUIRED(f_declared->mu_);
1897};
1898
1899// EXCLUSIVE_LOCKS_REQUIRED should be applied, and rewritten to f_defined->mu_
1900void Foo::foo1(Foo *f_defined) {
1901 f_defined->a = 0;
1902};
1903
1904void test() {
1905 Foo myfoo;
1906 myfoo.foo1(&myfoo); // \
1907 // expected-warning {{calling function 'foo1' requires exclusive lock on 'mu_'}}
1908 myfoo.mu_.Lock();
1909 myfoo.foo1(&myfoo);
1910 myfoo.mu_.Unlock();
1911}
1912
1913};
Richard Smith2e515622012-02-03 04:45:26 +00001914
1915namespace GoingNative {
1916
1917 struct __attribute__((lockable)) mutex {
1918 void lock() __attribute__((exclusive_lock_function));
1919 void unlock() __attribute__((unlock_function));
1920 // ...
1921 };
1922 bool foo();
1923 bool bar();
1924 mutex m;
1925 void test() {
1926 m.lock();
1927 while (foo()) {
1928 m.unlock();
1929 // ...
1930 if (bar()) {
1931 // ...
1932 if (foo())
1933 continue; // expected-warning {{expecting mutex 'm' to be locked at start of each loop}}
1934 //...
1935 }
1936 // ...
1937 m.lock(); // expected-note {{mutex acquired here}}
1938 }
1939 m.unlock();
1940 }
1941
1942}
DeLesley Hutchinsc24a2332012-02-16 16:50:43 +00001943
1944
1945
1946namespace FunctionDefinitionTest {
1947
1948class Foo {
1949public:
1950 void foo1();
1951 void foo2();
1952 void foo3(Foo *other);
1953
1954 template<class T>
1955 void fooT1(const T& dummy1);
1956
1957 template<class T>
1958 void fooT2(const T& dummy2) EXCLUSIVE_LOCKS_REQUIRED(mu_);
1959
1960 Mutex mu_;
1961 int a GUARDED_BY(mu_);
1962};
1963
1964template<class T>
1965class FooT {
1966public:
1967 void foo();
1968
1969 Mutex mu_;
1970 T a GUARDED_BY(mu_);
1971};
1972
1973
1974void Foo::foo1() NO_THREAD_SAFETY_ANALYSIS {
1975 a = 1;
1976}
1977
1978void Foo::foo2() EXCLUSIVE_LOCKS_REQUIRED(mu_) {
1979 a = 2;
1980}
1981
1982void Foo::foo3(Foo *other) EXCLUSIVE_LOCKS_REQUIRED(other->mu_) {
1983 other->a = 3;
1984}
1985
1986template<class T>
1987void Foo::fooT1(const T& dummy1) EXCLUSIVE_LOCKS_REQUIRED(mu_) {
1988 a = dummy1;
1989}
1990
1991/* TODO -- uncomment with template instantiation of attributes.
1992template<class T>
1993void Foo::fooT2(const T& dummy2) {
1994 a = dummy2;
1995}
1996*/
1997
1998void fooF1(Foo *f) EXCLUSIVE_LOCKS_REQUIRED(f->mu_) {
1999 f->a = 1;
2000}
2001
2002void fooF2(Foo *f);
2003void fooF2(Foo *f) EXCLUSIVE_LOCKS_REQUIRED(f->mu_) {
2004 f->a = 2;
2005}
2006
2007void fooF3(Foo *f) EXCLUSIVE_LOCKS_REQUIRED(f->mu_);
2008void fooF3(Foo *f) {
2009 f->a = 3;
2010}
2011
2012template<class T>
2013void FooT<T>::foo() EXCLUSIVE_LOCKS_REQUIRED(mu_) {
2014 a = 0;
2015}
2016
2017void test() {
2018 int dummy = 0;
2019 Foo myFoo;
2020
2021 myFoo.foo2(); // \
2022 // expected-warning {{calling function 'foo2' requires exclusive lock on 'mu_'}}
2023 myFoo.foo3(&myFoo); // \
2024 // expected-warning {{calling function 'foo3' requires exclusive lock on 'mu_'}}
2025 myFoo.fooT1(dummy); // \
2026 // expected-warning {{calling function 'fooT1' requires exclusive lock on 'mu_'}}
2027
2028 // FIXME: uncomment with template instantiation of attributes patch
2029 // myFoo.fooT2(dummy); // expected warning
2030
2031 fooF1(&myFoo); // \
2032 // expected-warning {{calling function 'fooF1' requires exclusive lock on 'mu_'}}
2033 fooF2(&myFoo); // \
2034 // expected-warning {{calling function 'fooF2' requires exclusive lock on 'mu_'}}
2035 fooF3(&myFoo); // \
2036 // expected-warning {{calling function 'fooF3' requires exclusive lock on 'mu_'}}
2037
2038 myFoo.mu_.Lock();
2039 myFoo.foo2();
2040 myFoo.foo3(&myFoo);
2041 myFoo.fooT1(dummy);
2042
2043 // FIXME: uncomment with template instantiation of attributes patch
2044 // myFoo.fooT2(dummy);
2045
2046 fooF1(&myFoo);
2047 fooF2(&myFoo);
2048 fooF3(&myFoo);
2049 myFoo.mu_.Unlock();
2050
2051 FooT<int> myFooT;
2052 myFooT.foo(); // \
2053 // expected-warning {{calling function 'foo' requires exclusive lock on 'mu_'}}
2054}
2055
DeLesley Hutchins4bda3ec2012-02-16 17:03:24 +00002056} // end namespace FunctionDefinitionTest
2057
2058
2059namespace SelfLockingTest {
2060
2061class LOCKABLE MyLock {
2062public:
2063 int foo GUARDED_BY(this);
2064
2065 void lock() EXCLUSIVE_LOCK_FUNCTION();
2066 void unlock() UNLOCK_FUNCTION();
2067
2068 void doSomething() {
2069 this->lock(); // allow 'this' as a lock expression
2070 foo = 0;
2071 doSomethingElse();
2072 this->unlock();
2073 }
2074
2075 void doSomethingElse() EXCLUSIVE_LOCKS_REQUIRED(this) {
2076 foo = 1;
2077 };
2078
2079 void test() {
2080 foo = 2; // \
2081 // expected-warning {{writing variable 'foo' requires locking 'this' exclusively}}
2082 }
DeLesley Hutchinsc24a2332012-02-16 16:50:43 +00002083};
2084
DeLesley Hutchins2f13bec2012-02-16 17:13:43 +00002085
2086class LOCKABLE MyLock2 {
2087public:
2088 Mutex mu_;
2089 int foo GUARDED_BY(this);
2090
2091 // don't check inside lock and unlock functions
2092 void lock() EXCLUSIVE_LOCK_FUNCTION() { mu_.Lock(); }
2093 void unlock() UNLOCK_FUNCTION() { mu_.Unlock(); }
2094
2095 // don't check inside constructors and destructors
2096 MyLock2() { foo = 1; }
2097 ~MyLock2() { foo = 0; }
2098};
2099
2100
DeLesley Hutchins4bda3ec2012-02-16 17:03:24 +00002101} // end namespace SelfLockingTest
2102
2103
DeLesley Hutchinsd08d5992012-02-25 00:11:55 +00002104namespace InvalidNonstatic {
2105
2106// Forward decl here causes bogus "invalid use of non-static data member"
2107// on reference to mutex_ in guarded_by attribute.
2108class Foo;
2109
2110class Foo {
2111 Mutex* mutex_;
2112
2113 int foo __attribute__((guarded_by(mutex_)));
2114};
2115
2116} // end namespace InvalidNonStatic
2117
DeLesley Hutchins2a35be82012-03-02 22:02:58 +00002118
2119namespace NoReturnTest {
2120
2121bool condition();
2122void fatal() __attribute__((noreturn));
2123
2124Mutex mu_;
2125
2126void test1() {
2127 MutexLock lock(&mu_);
2128 if (condition()) {
2129 fatal();
2130 return;
2131 }
2132}
2133
DeLesley Hutchins2287c5e2012-03-02 22:12:59 +00002134} // end namespace NoReturnTest
2135
2136
2137namespace TestMultiDecl {
2138
2139class Foo {
2140public:
2141 int GUARDED_BY(mu_) a;
2142 int GUARDED_BY(mu_) b, c;
2143
2144 void foo() {
2145 a = 0; // \
2146 // expected-warning {{writing variable 'a' requires locking 'mu_' exclusively}}
2147 b = 0; // \
2148 // expected-warning {{writing variable 'b' requires locking 'mu_' exclusively}}
2149 c = 0; // \
2150 // expected-warning {{writing variable 'c' requires locking 'mu_' exclusively}}
2151 }
2152
2153private:
2154 Mutex mu_;
DeLesley Hutchins2a35be82012-03-02 22:02:58 +00002155};
DeLesley Hutchins2287c5e2012-03-02 22:12:59 +00002156
2157} // end namespace TestMultiDecl
2158
DeLesley Hutchins7ec419a2012-03-02 22:29:50 +00002159
2160namespace WarnNoDecl {
2161
2162class Foo {
2163 void foo(int a); __attribute__(( // \
2164 // expected-warning {{declaration does not declare anything}}
2165 exclusive_locks_required(a))); // \
2166 // expected-warning {{attribute exclusive_locks_required ignored}}
2167};
2168
2169} // end namespace WarnNoDecl
2170
2171
DeLesley Hutchins0d95dfc2012-03-02 23:36:05 +00002172
2173namespace MoreLockExpressions {
2174
2175class Foo {
2176public:
2177 Mutex mu_;
2178 int a GUARDED_BY(mu_);
2179};
2180
2181class Bar {
2182public:
2183 int b;
2184 Foo* f;
2185
2186 Foo& getFoo() { return *f; }
2187 Foo& getFoo2(int c) { return *f; }
2188 Foo& getFoo3(int c, int d) { return *f; }
2189
2190 Foo& getFooey() { return *f; }
2191};
2192
2193Foo& getBarFoo(Bar &bar, int c) { return bar.getFoo2(c); }
2194
2195void test() {
2196 Foo foo;
2197 Foo *fooArray;
2198 Bar bar;
2199 int a;
2200 int b;
2201 int c;
2202
2203 bar.getFoo().mu_.Lock();
2204 bar.getFoo().a = 0;
2205 bar.getFoo().mu_.Unlock();
2206
2207 (bar.getFoo().mu_).Lock(); // test parenthesis
2208 bar.getFoo().a = 0;
2209 (bar.getFoo().mu_).Unlock();
2210
2211 bar.getFoo2(a).mu_.Lock();
2212 bar.getFoo2(a).a = 0;
2213 bar.getFoo2(a).mu_.Unlock();
2214
2215 bar.getFoo3(a, b).mu_.Lock();
2216 bar.getFoo3(a, b).a = 0;
2217 bar.getFoo3(a, b).mu_.Unlock();
2218
2219 getBarFoo(bar, a).mu_.Lock();
2220 getBarFoo(bar, a).a = 0;
2221 getBarFoo(bar, a).mu_.Unlock();
2222
2223 bar.getFoo2(10).mu_.Lock();
2224 bar.getFoo2(10).a = 0;
2225 bar.getFoo2(10).mu_.Unlock();
2226
2227 bar.getFoo2(a + 1).mu_.Lock();
2228 bar.getFoo2(a + 1).a = 0;
2229 bar.getFoo2(a + 1).mu_.Unlock();
2230
2231 (a > 0 ? fooArray[1] : fooArray[b]).mu_.Lock();
2232 (a > 0 ? fooArray[1] : fooArray[b]).a = 0;
2233 (a > 0 ? fooArray[1] : fooArray[b]).mu_.Unlock();
2234
2235 bar.getFoo().mu_.Lock();
2236 bar.getFooey().a = 0; // \
2237 // expected-warning {{writing variable 'a' requires locking 'mu_' exclusively}}
2238 bar.getFoo().mu_.Unlock();
2239
2240 bar.getFoo2(a).mu_.Lock();
2241 bar.getFoo2(b).a = 0; // \
2242 // expected-warning {{writing variable 'a' requires locking 'mu_' exclusively}}
2243 bar.getFoo2(a).mu_.Unlock();
2244
2245 bar.getFoo3(a, b).mu_.Lock();
2246 bar.getFoo3(a, c).a = 0; // \
2247 // expected-warning {{writing variable 'a' requires locking 'mu_' exclusively}}
2248 bar.getFoo3(a, b).mu_.Unlock();
2249
2250 getBarFoo(bar, a).mu_.Lock();
2251 getBarFoo(bar, b).a = 0; // \
2252 // expected-warning {{writing variable 'a' requires locking 'mu_' exclusively}}
2253 getBarFoo(bar, a).mu_.Unlock();
2254
2255 (a > 0 ? fooArray[1] : fooArray[b]).mu_.Lock();
2256 (a > 0 ? fooArray[b] : fooArray[c]).a = 0; // \
2257 // expected-warning {{writing variable 'a' requires locking 'mu_' exclusively}}
2258 (a > 0 ? fooArray[1] : fooArray[b]).mu_.Unlock();
2259}
2260
2261
DeLesley Hutchins0da44142012-06-22 17:07:28 +00002262} // end namespace MoreLockExpressions
2263
2264
2265namespace TrylockJoinPoint {
2266
2267class Foo {
2268 Mutex mu;
2269 bool c;
2270
2271 void foo() {
2272 if (c) {
2273 if (!mu.TryLock())
2274 return;
2275 } else {
2276 mu.Lock();
2277 }
2278 mu.Unlock();
2279 }
2280};
2281
2282} // end namespace TrylockJoinPoint
DeLesley Hutchins0d95dfc2012-03-02 23:36:05 +00002283
2284
DeLesley Hutchinsf63797c2012-06-25 18:33:18 +00002285namespace LockReturned {
2286
2287class Foo {
2288public:
2289 int a GUARDED_BY(mu_);
2290 void foo() EXCLUSIVE_LOCKS_REQUIRED(mu_);
2291 void foo2(Foo* f) EXCLUSIVE_LOCKS_REQUIRED(mu_, f->mu_);
2292
2293 static void sfoo(Foo* f) EXCLUSIVE_LOCKS_REQUIRED(f->mu_);
2294
2295 Mutex* getMu() LOCK_RETURNED(mu_);
2296
2297 Mutex mu_;
2298
2299 static Mutex* getMu(Foo* f) LOCK_RETURNED(f->mu_);
2300};
2301
2302
2303// Calls getMu() directly to lock and unlock
2304void test1(Foo* f1, Foo* f2) {
2305 f1->a = 0; // expected-warning {{writing variable 'a' requires locking 'mu_' exclusively}}
2306 f1->foo(); // expected-warning {{calling function 'foo' requires exclusive lock on 'mu_'}}
2307
2308 f1->foo2(f2); // expected-warning 2{{calling function 'foo2' requires exclusive lock on 'mu_'}}
2309 Foo::sfoo(f1); // expected-warning {{calling function 'sfoo' requires exclusive lock on 'mu_'}}
2310
2311 f1->getMu()->Lock();
2312
2313 f1->a = 0;
2314 f1->foo();
2315 f1->foo2(f2); // expected-warning {{calling function 'foo2' requires exclusive lock on 'mu_'}}
2316
2317 Foo::getMu(f2)->Lock();
2318 f1->foo2(f2);
2319 Foo::getMu(f2)->Unlock();
2320
2321 Foo::sfoo(f1);
2322
2323 f1->getMu()->Unlock();
2324}
2325
2326
2327Mutex* getFooMu(Foo* f) LOCK_RETURNED(Foo::getMu(f));
2328
2329class Bar : public Foo {
2330public:
2331 int b GUARDED_BY(getMu());
2332 void bar() EXCLUSIVE_LOCKS_REQUIRED(getMu());
2333 void bar2(Bar* g) EXCLUSIVE_LOCKS_REQUIRED(getMu(this), g->getMu());
2334
2335 static void sbar(Bar* g) EXCLUSIVE_LOCKS_REQUIRED(g->getMu());
2336 static void sbar2(Bar* g) EXCLUSIVE_LOCKS_REQUIRED(getFooMu(g));
2337};
2338
2339
2340
2341// Use getMu() within other attributes.
2342// This requires at lest levels of substitution, more in the case of
2343void test2(Bar* b1, Bar* b2) {
2344 b1->b = 0; // expected-warning {{writing variable 'b' requires locking 'mu_' exclusively}}
2345 b1->bar(); // expected-warning {{calling function 'bar' requires exclusive lock on 'mu_'}}
2346 b1->bar2(b2); // expected-warning 2{{calling function 'bar2' requires exclusive lock on 'mu_'}}
2347 Bar::sbar(b1); // expected-warning {{calling function 'sbar' requires exclusive lock on 'mu_'}}
2348 Bar::sbar2(b1); // expected-warning {{calling function 'sbar2' requires exclusive lock on 'mu_'}}
2349
2350 b1->getMu()->Lock();
2351
2352 b1->b = 0;
2353 b1->bar();
2354 b1->bar2(b2); // expected-warning {{calling function 'bar2' requires exclusive lock on 'mu_'}}
2355
2356 b2->getMu()->Lock();
2357 b1->bar2(b2);
2358
2359 b2->getMu()->Unlock();
2360
2361 Bar::sbar(b1);
2362 Bar::sbar2(b1);
2363
2364 b1->getMu()->Unlock();
2365}
2366
2367
2368// Sanity check -- lock the mutex directly, but use attributes that call getMu()
2369// Also lock the mutex using getFooMu, which calls a lock_returned function.
2370void test3(Bar* b1, Bar* b2) {
2371 b1->mu_.Lock();
2372 b1->b = 0;
2373 b1->bar();
2374
2375 getFooMu(b2)->Lock();
2376 b1->bar2(b2);
2377 getFooMu(b2)->Unlock();
2378
2379 Bar::sbar(b1);
2380 Bar::sbar2(b1);
2381
2382 b1->mu_.Unlock();
2383}
2384
2385} // end namespace LockReturned
2386
2387
DeLesley Hutchinsc99a5d82012-06-28 22:42:48 +00002388namespace ReleasableScopedLock {
2389
2390class Foo {
2391 Mutex mu_;
2392 bool c;
2393 int a GUARDED_BY(mu_);
2394
2395 void test1();
2396 void test2();
2397 void test3();
2398};
2399
2400
2401void Foo::test1() {
2402 ReleasableMutexLock rlock(&mu_);
2403 rlock.Release();
2404}
2405
2406void Foo::test2() {
2407 ReleasableMutexLock rlock(&mu_);
2408 if (c) { // test join point -- held/not held during release
2409 rlock.Release();
2410 }
2411}
2412
2413void Foo::test3() {
2414 ReleasableMutexLock rlock(&mu_);
2415 a = 0;
2416 rlock.Release();
2417 a = 1; // expected-warning {{writing variable 'a' requires locking 'mu_' exclusively}}
2418}
2419
2420} // end namespace ReleasableScopedLock
2421
2422
DeLesley Hutchins76f0a6e2012-07-02 21:59:24 +00002423namespace TrylockFunctionTest {
2424
2425class Foo {
2426public:
2427 Mutex mu1_;
2428 Mutex mu2_;
2429 bool c;
2430
2431 bool lockBoth() EXCLUSIVE_TRYLOCK_FUNCTION(true, mu1_, mu2_);
2432};
2433
2434bool Foo::lockBoth() {
2435 if (!mu1_.TryLock())
2436 return false;
2437
2438 mu2_.Lock();
2439 if (!c) {
2440 mu1_.Unlock();
2441 mu2_.Unlock();
2442 return false;
2443 }
2444
2445 return true;
2446}
2447
2448
2449} // end namespace TrylockFunctionTest
DeLesley Hutchinsc99a5d82012-06-28 22:42:48 +00002450
2451
2452
DeLesley Hutchinsc36eda12012-07-02 22:12:12 +00002453namespace DoubleLockBug {
2454
2455class Foo {
2456public:
2457 Mutex mu_;
2458 int a GUARDED_BY(mu_);
2459
2460 void foo() EXCLUSIVE_LOCKS_REQUIRED(mu_);
2461};
2462
2463
2464void Foo::foo() EXCLUSIVE_LOCKS_REQUIRED(mu_) {
2465 a = 0;
2466}
2467
2468};
2469
2470
DeLesley Hutchins879a4332012-07-02 22:16:54 +00002471namespace UnlockBug {
DeLesley Hutchinsc36eda12012-07-02 22:12:12 +00002472
DeLesley Hutchins879a4332012-07-02 22:16:54 +00002473class Foo {
2474public:
2475 Mutex mutex_;
2476
2477 void foo1() EXCLUSIVE_LOCKS_REQUIRED(mutex_) { // expected-note {{mutex acquired here}}
2478 mutex_.Unlock();
2479 } // expected-warning {{expecting mutex 'mutex_' to be locked at the end of function}}
2480
2481
2482 void foo2() SHARED_LOCKS_REQUIRED(mutex_) { // expected-note {{mutex acquired here}}
2483 mutex_.Unlock();
2484 } // expected-warning {{expecting mutex 'mutex_' to be locked at the end of function}}
2485};
2486
2487} // end namespace UnlockBug
DeLesley Hutchinsc36eda12012-07-02 22:12:12 +00002488
DeLesley Hutchinsc99a5d82012-06-28 22:42:48 +00002489
DeLesley Hutchinsbbe33412012-07-02 22:26:29 +00002490namespace FoolishScopedLockableBug {
2491
2492class SCOPED_LOCKABLE WTF_ScopedLockable {
2493public:
2494 WTF_ScopedLockable(Mutex* mu) EXCLUSIVE_LOCK_FUNCTION(mu);
2495
2496 // have to call release() manually;
2497 ~WTF_ScopedLockable();
2498
2499 void release() UNLOCK_FUNCTION();
2500};
2501
2502
2503class Foo {
2504 Mutex mu_;
2505 int a GUARDED_BY(mu_);
2506 bool c;
2507
2508 void doSomething();
2509
2510 void test1() {
2511 WTF_ScopedLockable wtf(&mu_);
2512 wtf.release();
2513 }
2514
2515 void test2() {
2516 WTF_ScopedLockable wtf(&mu_); // expected-note {{mutex acquired here}}
2517 } // expected-warning {{mutex 'mu_' is still locked at the end of function}}
2518
2519 void test3() {
2520 if (c) {
2521 WTF_ScopedLockable wtf(&mu_);
2522 wtf.release();
2523 }
2524 }
2525
2526 void test4() {
2527 if (c) {
2528 doSomething();
2529 }
2530 else {
2531 WTF_ScopedLockable wtf(&mu_);
2532 wtf.release();
2533 }
2534 }
2535
2536 void test5() {
2537 if (c) {
2538 WTF_ScopedLockable wtf(&mu_); // expected-note {{mutex acquired here}}
2539 }
2540 } // expected-warning {{mutex 'mu_' is not locked on every path through here}}
2541
2542 void test6() {
2543 if (c) {
2544 doSomething();
2545 }
2546 else {
2547 WTF_ScopedLockable wtf(&mu_); // expected-note {{mutex acquired here}}
2548 }
2549 } // expected-warning {{mutex 'mu_' is not locked on every path through here}}
2550};
2551
2552
2553} // end namespace FoolishScopedLockableBug
2554
DeLesley Hutchins9d6e7f32012-07-03 18:25:56 +00002555
2556namespace TemporaryCleanupExpr {
2557
2558class Foo {
2559 int a GUARDED_BY(getMutexPtr().get());
2560
2561 SmartPtr<Mutex> getMutexPtr();
2562
2563 void test();
2564};
2565
2566
2567void Foo::test() {
2568 {
2569 ReaderMutexLock lock(getMutexPtr().get());
2570 int b = a;
2571 } // FIXME: handle smart pointers better.
2572 int b = a; // expected-warning {{reading variable 'a' requires locking 'get'}}
2573}
2574
2575} // end namespace TemporaryCleanupExpr
2576
2577