blob: 1c47035c2b2d4ee605d406a90a65a4fae63431c1 [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
60Mutex sls_mu;
61
62Mutex sls_mu2 __attribute__((acquired_after(sls_mu)));
63int sls_guard_var __attribute__((guarded_var)) = 0;
64int sls_guardby_var __attribute__((guarded_by(sls_mu))) = 0;
65
66bool getBool();
67
68class MutexWrapper {
69public:
70 Mutex mu;
Caitlin Sadowski194418f2011-09-14 20:00:24 +000071 int x __attribute__((guarded_by(mu)));
72 void MyLock() __attribute__((exclusive_lock_function(mu)));
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +000073};
74
75MutexWrapper sls_mw;
76
77void sls_fun_0() {
78 sls_mw.mu.Lock();
Caitlin Sadowski194418f2011-09-14 20:00:24 +000079 sls_mw.x = 5;
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +000080 sls_mw.mu.Unlock();
81}
82
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +000083void sls_fun_2() {
84 sls_mu.Lock();
85 int x = sls_guard_var;
86 sls_mu.Unlock();
87}
88
89void sls_fun_3() {
90 sls_mu.Lock();
91 sls_guard_var = 2;
92 sls_mu.Unlock();
93}
94
95void sls_fun_4() {
96 sls_mu2.Lock();
97 sls_guard_var = 2;
98 sls_mu2.Unlock();
99}
100
101void sls_fun_5() {
102 sls_mu.Lock();
103 int x = sls_guardby_var;
104 sls_mu.Unlock();
105}
106
107void sls_fun_6() {
108 sls_mu.Lock();
109 sls_guardby_var = 2;
110 sls_mu.Unlock();
111}
112
113void sls_fun_7() {
114 sls_mu.Lock();
115 sls_mu2.Lock();
116 sls_mu2.Unlock();
117 sls_mu.Unlock();
118}
119
120void sls_fun_8() {
121 sls_mu.Lock();
122 if (getBool())
123 sls_mu.Unlock();
124 else
125 sls_mu.Unlock();
126}
127
128void sls_fun_9() {
129 if (getBool())
130 sls_mu.Lock();
131 else
132 sls_mu.Lock();
133 sls_mu.Unlock();
134}
135
136void sls_fun_good_6() {
137 if (getBool()) {
138 sls_mu.Lock();
139 } else {
140 if (getBool()) {
141 getBool(); // EMPTY
142 } else {
143 getBool(); // EMPTY
144 }
145 sls_mu.Lock();
146 }
147 sls_mu.Unlock();
148}
149
150void sls_fun_good_7() {
151 sls_mu.Lock();
152 while (getBool()) {
153 sls_mu.Unlock();
154 if (getBool()) {
155 if (getBool()) {
156 sls_mu.Lock();
157 continue;
158 }
159 }
160 sls_mu.Lock();
161 }
162 sls_mu.Unlock();
163}
164
Caitlin Sadowski194418f2011-09-14 20:00:24 +0000165void sls_fun_good_8() {
166 sls_mw.MyLock();
167 sls_mw.mu.Unlock();
168}
169
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000170void sls_fun_bad_1() {
171 sls_mu.Unlock(); // \
Caitlin Sadowski8bccabe2011-09-08 21:52:50 +0000172 // expected-warning{{unlocking 'sls_mu' that was not locked}}
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000173}
174
175void sls_fun_bad_2() {
176 sls_mu.Lock();
177 sls_mu.Lock(); // \
Caitlin Sadowski8bccabe2011-09-08 21:52:50 +0000178 // expected-warning{{locking 'sls_mu' that is already locked}}
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000179 sls_mu.Unlock();
180}
181
182void sls_fun_bad_3() {
Richard Smith2e515622012-02-03 04:45:26 +0000183 sls_mu.Lock(); // expected-note {{mutex acquired here}}
184} // expected-warning{{mutex 'sls_mu' is still locked at the end of function}}
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000185
186void sls_fun_bad_4() {
187 if (getBool())
DeLesley Hutchins0da44142012-06-22 17:07:28 +0000188 sls_mu.Lock(); // expected-note{{mutex acquired here}}
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000189 else
DeLesley Hutchins0da44142012-06-22 17:07:28 +0000190 sls_mu2.Lock(); // expected-note{{mutex acquired here}}
191} // expected-warning{{mutex 'sls_mu' is not locked on every path through here}} \
192 // expected-warning{{mutex 'sls_mu2' is not locked on every path through here}}
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000193
194void sls_fun_bad_5() {
Richard Smith2e515622012-02-03 04:45:26 +0000195 sls_mu.Lock(); // expected-note {{mutex acquired here}}
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000196 if (getBool())
197 sls_mu.Unlock();
Richard Smith2e515622012-02-03 04:45:26 +0000198} // expected-warning{{mutex 'sls_mu' is not locked on every path through here}}
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000199
200void sls_fun_bad_6() {
201 if (getBool()) {
Richard Smith2e515622012-02-03 04:45:26 +0000202 sls_mu.Lock(); // expected-note {{mutex acquired here}}
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000203 } else {
204 if (getBool()) {
205 getBool(); // EMPTY
206 } else {
207 getBool(); // EMPTY
208 }
209 }
210 sls_mu.Unlock(); // \
Richard Smith2e515622012-02-03 04:45:26 +0000211 expected-warning{{mutex 'sls_mu' is not locked on every path through here}}\
212 expected-warning{{unlocking 'sls_mu' that was not locked}}
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000213}
214
215void sls_fun_bad_7() {
Richard Smithaacde712012-02-03 03:30:07 +0000216 sls_mu.Lock();
Caitlin Sadowski4e4bc752011-09-15 17:25:19 +0000217 while (getBool()) {
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000218 sls_mu.Unlock();
219 if (getBool()) {
220 if (getBool()) {
Richard Smith2e515622012-02-03 04:45:26 +0000221 continue; // \
222 expected-warning{{expecting mutex 'sls_mu' to be locked at start of each loop}}
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000223 }
224 }
Richard Smith2e515622012-02-03 04:45:26 +0000225 sls_mu.Lock(); // expected-note {{mutex acquired here}}
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000226 }
227 sls_mu.Unlock();
228}
229
230void sls_fun_bad_8() {
Richard Smith2e515622012-02-03 04:45:26 +0000231 sls_mu.Lock(); // expected-note{{mutex acquired here}}
232
DeLesley Hutchins0da44142012-06-22 17:07:28 +0000233 do {
234 sls_mu.Unlock(); // expected-warning{{expecting mutex 'sls_mu' to be locked at start of each loop}}
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000235 } while (getBool());
236}
237
238void sls_fun_bad_9() {
239 do {
DeLesley Hutchins0da44142012-06-22 17:07:28 +0000240 sls_mu.Lock(); // \
Richard Smith2e515622012-02-03 04:45:26 +0000241 // expected-warning{{expecting mutex 'sls_mu' to be locked at start of each loop}} \
242 // expected-note{{mutex acquired here}}
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000243 } while (getBool());
244 sls_mu.Unlock();
245}
246
247void sls_fun_bad_10() {
DeLesley Hutchins0da44142012-06-22 17:07:28 +0000248 sls_mu.Lock(); // expected-note 2{{mutex acquired here}}
249 while(getBool()) { // expected-warning{{expecting mutex 'sls_mu' to be locked at start of each loop}}
250 sls_mu.Unlock();
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000251 }
Richard Smith2e515622012-02-03 04:45:26 +0000252} // expected-warning{{mutex 'sls_mu' is still locked at the end of function}}
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000253
254void sls_fun_bad_11() {
Richard Smith2e515622012-02-03 04:45:26 +0000255 while (getBool()) { // \
DeLesley Hutchins0da44142012-06-22 17:07:28 +0000256 expected-warning{{expecting mutex 'sls_mu' to be locked at start of each loop}}
Richard Smith2e515622012-02-03 04:45:26 +0000257 sls_mu.Lock(); // expected-note {{mutex acquired here}}
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000258 }
259 sls_mu.Unlock(); // \
Caitlin Sadowski8bccabe2011-09-08 21:52:50 +0000260 // expected-warning{{unlocking 'sls_mu' that was not locked}}
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000261}
262
Richard Smithaacde712012-02-03 03:30:07 +0000263void sls_fun_bad_12() {
Richard Smith2e515622012-02-03 04:45:26 +0000264 sls_mu.Lock(); // expected-note {{mutex acquired here}}
Richard Smithaacde712012-02-03 03:30:07 +0000265 while (getBool()) {
266 sls_mu.Unlock();
267 if (getBool()) {
268 if (getBool()) {
Richard Smith2e515622012-02-03 04:45:26 +0000269 break; // expected-warning{{mutex 'sls_mu' is not locked on every path through here}}
Richard Smithaacde712012-02-03 03:30:07 +0000270 }
271 }
272 sls_mu.Lock();
273 }
274 sls_mu.Unlock();
275}
276
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000277//-----------------------------------------//
278// Handling lock expressions in attribute args
279// -------------------------------------------//
280
281Mutex aa_mu;
282
283class GlobalLocker {
284public:
285 void globalLock() __attribute__((exclusive_lock_function(aa_mu)));
286 void globalUnlock() __attribute__((unlock_function(aa_mu)));
287};
288
289GlobalLocker glock;
290
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000291void aa_fun_1() {
292 glock.globalLock();
293 glock.globalUnlock();
294}
295
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000296void aa_fun_bad_1() {
297 glock.globalUnlock(); // \
Caitlin Sadowski8bccabe2011-09-08 21:52:50 +0000298 // expected-warning{{unlocking 'aa_mu' that was not locked}}
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000299}
300
301void aa_fun_bad_2() {
302 glock.globalLock();
303 glock.globalLock(); // \
Caitlin Sadowski8bccabe2011-09-08 21:52:50 +0000304 // expected-warning{{locking 'aa_mu' that is already locked}}
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000305 glock.globalUnlock();
306}
307
308void aa_fun_bad_3() {
Richard Smith2e515622012-02-03 04:45:26 +0000309 glock.globalLock(); // expected-note{{mutex acquired here}}
310} // expected-warning{{mutex 'aa_mu' is still locked at the end of function}}
Caitlin Sadowskib4d0a962011-08-29 17:12:27 +0000311
Caitlin Sadowskib4d0a962011-08-29 17:12:27 +0000312//--------------------------------------------------//
313// Regression tests for unusual method names
314//--------------------------------------------------//
315
316Mutex wmu;
317
318// Test diagnostics for other method names.
319class WeirdMethods {
DeLesley Hutchins2f13bec2012-02-16 17:13:43 +0000320 // FIXME: can't currently check inside constructors and destructors.
Caitlin Sadowskib4d0a962011-08-29 17:12:27 +0000321 WeirdMethods() {
DeLesley Hutchins2f13bec2012-02-16 17:13:43 +0000322 wmu.Lock(); // EXPECTED-NOTE {{mutex acquired here}}
323 } // EXPECTED-WARNING {{mutex 'wmu' is still locked at the end of function}}
Caitlin Sadowskib4d0a962011-08-29 17:12:27 +0000324 ~WeirdMethods() {
DeLesley Hutchins2f13bec2012-02-16 17:13:43 +0000325 wmu.Lock(); // EXPECTED-NOTE {{mutex acquired here}}
326 } // EXPECTED-WARNING {{mutex 'wmu' is still locked at the end of function}}
Caitlin Sadowskib4d0a962011-08-29 17:12:27 +0000327 void operator++() {
Richard Smith2e515622012-02-03 04:45:26 +0000328 wmu.Lock(); // expected-note {{mutex acquired here}}
329 } // expected-warning {{mutex 'wmu' is still locked at the end of function}}
Caitlin Sadowskib4d0a962011-08-29 17:12:27 +0000330 operator int*() {
Richard Smith2e515622012-02-03 04:45:26 +0000331 wmu.Lock(); // expected-note {{mutex acquired here}}
Caitlin Sadowskib4d0a962011-08-29 17:12:27 +0000332 return 0;
Richard Smith2e515622012-02-03 04:45:26 +0000333 } // expected-warning {{mutex 'wmu' is still locked at the end of function}}
Caitlin Sadowskib4d0a962011-08-29 17:12:27 +0000334};
335
Caitlin Sadowski05b436e2011-08-29 22:27:51 +0000336//-----------------------------------------------//
337// Errors for guarded by or guarded var variables
338// ----------------------------------------------//
339
340int *pgb_gvar __attribute__((pt_guarded_var));
341int *pgb_var __attribute__((pt_guarded_by(sls_mu)));
342
343class PGBFoo {
344 public:
345 int x;
346 int *pgb_field __attribute__((guarded_by(sls_mu2)))
347 __attribute__((pt_guarded_by(sls_mu)));
348 void testFoo() {
349 pgb_field = &x; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000350 // expected-warning {{writing variable 'pgb_field' requires locking 'sls_mu2' exclusively}}
351 *pgb_field = x; // expected-warning {{reading variable 'pgb_field' requires locking 'sls_mu2'}} \
352 // expected-warning {{writing the value pointed to by 'pgb_field' requires locking 'sls_mu' exclusively}}
353 x = *pgb_field; // expected-warning {{reading variable 'pgb_field' requires locking 'sls_mu2'}} \
354 // expected-warning {{reading the value pointed to by 'pgb_field' requires locking 'sls_mu'}}
355 (*pgb_field)++; // expected-warning {{reading variable 'pgb_field' requires locking 'sls_mu2'}} \
356 // expected-warning {{writing the value pointed to by 'pgb_field' requires locking 'sls_mu' exclusively}}
Caitlin Sadowski05b436e2011-08-29 22:27:51 +0000357 }
358};
359
360class GBFoo {
361 public:
362 int gb_field __attribute__((guarded_by(sls_mu)));
363
364 void testFoo() {
365 gb_field = 0; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000366 // expected-warning {{writing variable 'gb_field' requires locking 'sls_mu' exclusively}}
Caitlin Sadowski05b436e2011-08-29 22:27:51 +0000367 }
Caitlin Sadowskiaf370612011-09-08 18:35:21 +0000368
369 void testNoAnal() __attribute__((no_thread_safety_analysis)) {
370 gb_field = 0;
371 }
Caitlin Sadowski05b436e2011-08-29 22:27:51 +0000372};
373
374GBFoo GlobalGBFoo __attribute__((guarded_by(sls_mu)));
375
376void gb_fun_0() {
377 sls_mu.Lock();
378 int x = *pgb_var;
379 sls_mu.Unlock();
380}
381
382void gb_fun_1() {
383 sls_mu.Lock();
384 *pgb_var = 2;
385 sls_mu.Unlock();
386}
387
388void gb_fun_2() {
389 int x;
390 pgb_var = &x;
391}
392
393void gb_fun_3() {
394 int *x = pgb_var;
395}
396
397void gb_bad_0() {
398 sls_guard_var = 1; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000399 // expected-warning{{writing variable 'sls_guard_var' requires locking any mutex exclusively}}
Caitlin Sadowski05b436e2011-08-29 22:27:51 +0000400}
401
402void gb_bad_1() {
403 int x = sls_guard_var; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000404 // expected-warning{{reading variable 'sls_guard_var' requires locking any mutex}}
Caitlin Sadowski05b436e2011-08-29 22:27:51 +0000405}
406
407void gb_bad_2() {
408 sls_guardby_var = 1; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000409 // expected-warning {{writing variable 'sls_guardby_var' requires locking 'sls_mu' exclusively}}
Caitlin Sadowski05b436e2011-08-29 22:27:51 +0000410}
411
412void gb_bad_3() {
413 int x = sls_guardby_var; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000414 // expected-warning {{reading variable 'sls_guardby_var' requires locking 'sls_mu'}}
Caitlin Sadowski05b436e2011-08-29 22:27:51 +0000415}
416
417void gb_bad_4() {
418 *pgb_gvar = 1; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000419 // expected-warning {{writing the value pointed to by 'pgb_gvar' requires locking any mutex exclusively}}
Caitlin Sadowski05b436e2011-08-29 22:27:51 +0000420}
421
422void gb_bad_5() {
423 int x = *pgb_gvar; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000424 // expected-warning {{reading the value pointed to by 'pgb_gvar' requires locking any mutex}}
Caitlin Sadowski05b436e2011-08-29 22:27:51 +0000425}
426
427void gb_bad_6() {
428 *pgb_var = 1; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000429 // expected-warning {{writing the value pointed to by 'pgb_var' requires locking 'sls_mu' exclusively}}
Caitlin Sadowski05b436e2011-08-29 22:27:51 +0000430}
431
432void gb_bad_7() {
433 int x = *pgb_var; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000434 // expected-warning {{reading the value pointed to by 'pgb_var' requires locking 'sls_mu'}}
Caitlin Sadowski05b436e2011-08-29 22:27:51 +0000435}
436
437void gb_bad_8() {
438 GBFoo G;
439 G.gb_field = 0; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000440 // expected-warning {{writing variable 'gb_field' requires locking 'sls_mu'}}
Caitlin Sadowski05b436e2011-08-29 22:27:51 +0000441}
442
443void gb_bad_9() {
444 sls_guard_var++; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000445 // expected-warning{{writing variable 'sls_guard_var' requires locking any mutex exclusively}}
Caitlin Sadowski05b436e2011-08-29 22:27:51 +0000446 sls_guard_var--; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000447 // expected-warning{{writing variable 'sls_guard_var' requires locking any mutex exclusively}}
Caitlin Sadowski05b436e2011-08-29 22:27:51 +0000448 ++sls_guard_var; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000449 // expected-warning{{writing variable 'sls_guard_var' requires locking any mutex exclusively}}
Caitlin Sadowskia49d1d82011-09-09 16:07:55 +0000450 --sls_guard_var;// \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000451 // expected-warning{{writing variable 'sls_guard_var' requires locking any mutex exclusively}}
Caitlin Sadowski05b436e2011-08-29 22:27:51 +0000452}
Caitlin Sadowskib4d0a962011-08-29 17:12:27 +0000453
Caitlin Sadowskieff98fc2011-09-08 17:42:22 +0000454//-----------------------------------------------//
455// Warnings on variables with late parsed attributes
456// ----------------------------------------------//
457
458class LateFoo {
459public:
460 int a __attribute__((guarded_by(mu)));
461 int b;
462
463 void foo() __attribute__((exclusive_locks_required(mu))) { }
464
465 void test() {
466 a = 0; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000467 // expected-warning{{writing variable 'a' requires locking 'mu' exclusively}}
Caitlin Sadowskieff98fc2011-09-08 17:42:22 +0000468 b = a; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000469 // expected-warning {{reading variable 'a' requires locking 'mu'}}
Caitlin Sadowskieff98fc2011-09-08 17:42:22 +0000470 c = 0; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000471 // expected-warning {{writing variable 'c' requires locking 'mu' exclusively}}
Caitlin Sadowskieff98fc2011-09-08 17:42:22 +0000472 }
473
474 int c __attribute__((guarded_by(mu)));
475
476 Mutex mu;
477};
478
Caitlin Sadowski99107eb2011-09-09 16:21:55 +0000479class LateBar {
480 public:
481 int a_ __attribute__((guarded_by(mu1_)));
482 int b_;
483 int *q __attribute__((pt_guarded_by(mu)));
484 Mutex mu1_;
485 Mutex mu;
486 LateFoo Foo;
487 LateFoo Foo2;
488 LateFoo *FooPointer;
489};
490
491LateBar b1, *b3;
492
493void late_0() {
494 LateFoo FooA;
495 LateFoo FooB;
496 FooA.mu.Lock();
497 FooA.a = 5;
498 FooA.mu.Unlock();
499}
500
501void late_1() {
502 LateBar BarA;
503 BarA.FooPointer->mu.Lock();
504 BarA.FooPointer->a = 2;
505 BarA.FooPointer->mu.Unlock();
506}
507
508void late_bad_0() {
509 LateFoo fooA;
510 LateFoo fooB;
511 fooA.mu.Lock();
512 fooB.a = 5; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000513 // expected-warning{{writing variable 'a' requires locking 'mu' exclusively}}
Caitlin Sadowski99107eb2011-09-09 16:21:55 +0000514 fooA.mu.Unlock();
515}
516
517void late_bad_1() {
518 Mutex mu;
519 mu.Lock();
520 b1.mu1_.Lock();
521 int res = b1.a_ + b3->b_;
522 b3->b_ = *b1.q; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000523 // expected-warning{{reading the value pointed to by 'q' requires locking 'mu'}}
Caitlin Sadowski99107eb2011-09-09 16:21:55 +0000524 b1.mu1_.Unlock();
525 b1.b_ = res;
526 mu.Unlock();
527}
528
529void late_bad_2() {
530 LateBar BarA;
531 BarA.FooPointer->mu.Lock();
532 BarA.Foo.a = 2; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000533 // expected-warning{{writing variable 'a' requires locking 'mu' exclusively}}
Caitlin Sadowski99107eb2011-09-09 16:21:55 +0000534 BarA.FooPointer->mu.Unlock();
535}
536
537void late_bad_3() {
538 LateBar BarA;
539 BarA.Foo.mu.Lock();
540 BarA.FooPointer->a = 2; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000541 // expected-warning{{writing variable 'a' requires locking 'mu' exclusively}}
Caitlin Sadowski99107eb2011-09-09 16:21:55 +0000542 BarA.Foo.mu.Unlock();
543}
544
545void late_bad_4() {
546 LateBar BarA;
547 BarA.Foo.mu.Lock();
548 BarA.Foo2.a = 2; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000549 // expected-warning{{writing variable 'a' requires locking 'mu' exclusively}}
Caitlin Sadowski99107eb2011-09-09 16:21:55 +0000550 BarA.Foo.mu.Unlock();
551}
552
Caitlin Sadowskia53257c2011-09-08 18:19:38 +0000553//-----------------------------------------------//
554// Extra warnings for shared vs. exclusive locks
555// ----------------------------------------------//
556
557void shared_fun_0() {
558 sls_mu.Lock();
559 do {
560 sls_mu.Unlock();
561 sls_mu.Lock();
562 } while (getBool());
563 sls_mu.Unlock();
564}
565
566void shared_fun_1() {
Caitlin Sadowski4e4bc752011-09-15 17:25:19 +0000567 sls_mu.ReaderLock(); // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000568 // expected-warning {{mutex 'sls_mu' is locked exclusively and shared in the same scope}}
Caitlin Sadowskia53257c2011-09-08 18:19:38 +0000569 do {
570 sls_mu.Unlock();
Caitlin Sadowski4e4bc752011-09-15 17:25:19 +0000571 sls_mu.Lock(); // \
572 // expected-note {{the other lock of mutex 'sls_mu' is here}}
Caitlin Sadowskia53257c2011-09-08 18:19:38 +0000573 } while (getBool());
574 sls_mu.Unlock();
575}
576
577void shared_fun_3() {
578 if (getBool())
579 sls_mu.Lock();
580 else
581 sls_mu.Lock();
582 *pgb_var = 1;
583 sls_mu.Unlock();
584}
585
586void shared_fun_4() {
587 if (getBool())
588 sls_mu.ReaderLock();
589 else
590 sls_mu.ReaderLock();
591 int x = sls_guardby_var;
592 sls_mu.Unlock();
593}
594
595void shared_fun_8() {
596 if (getBool())
597 sls_mu.Lock(); // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000598 // expected-warning {{mutex 'sls_mu' is locked exclusively and shared in the same scope}}
Caitlin Sadowskia53257c2011-09-08 18:19:38 +0000599 else
600 sls_mu.ReaderLock(); // \
Caitlin Sadowski8bccabe2011-09-08 21:52:50 +0000601 // expected-note {{the other lock of mutex 'sls_mu' is here}}
Caitlin Sadowskia53257c2011-09-08 18:19:38 +0000602 sls_mu.Unlock();
603}
604
605void shared_bad_0() {
Caitlin Sadowski4e4bc752011-09-15 17:25:19 +0000606 sls_mu.Lock(); // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000607 // expected-warning {{mutex 'sls_mu' is locked exclusively and shared in the same scope}}
Caitlin Sadowskia53257c2011-09-08 18:19:38 +0000608 do {
609 sls_mu.Unlock();
Caitlin Sadowski4e4bc752011-09-15 17:25:19 +0000610 sls_mu.ReaderLock(); // \
611 // expected-note {{the other lock of mutex 'sls_mu' is here}}
Caitlin Sadowskia53257c2011-09-08 18:19:38 +0000612 } while (getBool());
613 sls_mu.Unlock();
614}
615
616void shared_bad_1() {
617 if (getBool())
618 sls_mu.Lock(); // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000619 // expected-warning {{mutex 'sls_mu' is locked exclusively and shared in the same scope}}
Caitlin Sadowskia53257c2011-09-08 18:19:38 +0000620 else
621 sls_mu.ReaderLock(); // \
Caitlin Sadowski8bccabe2011-09-08 21:52:50 +0000622 // expected-note {{the other lock of mutex 'sls_mu' is here}}
Caitlin Sadowskia53257c2011-09-08 18:19:38 +0000623 *pgb_var = 1;
624 sls_mu.Unlock();
625}
626
627void shared_bad_2() {
628 if (getBool())
629 sls_mu.ReaderLock(); // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000630 // expected-warning {{mutex 'sls_mu' is locked exclusively and shared in the same scope}}
Caitlin Sadowskia53257c2011-09-08 18:19:38 +0000631 else
632 sls_mu.Lock(); // \
Caitlin Sadowski8bccabe2011-09-08 21:52:50 +0000633 // expected-note {{the other lock of mutex 'sls_mu' is here}}
Caitlin Sadowskia53257c2011-09-08 18:19:38 +0000634 *pgb_var = 1;
635 sls_mu.Unlock();
636}
Caitlin Sadowski978191e2011-09-08 18:27:31 +0000637
638// FIXME: Add support for functions (not only methods)
639class LRBar {
640 public:
641 void aa_elr_fun() __attribute__((exclusive_locks_required(aa_mu)));
642 void aa_elr_fun_s() __attribute__((shared_locks_required(aa_mu)));
643 void le_fun() __attribute__((locks_excluded(sls_mu)));
644};
645
646class LRFoo {
647 public:
648 void test() __attribute__((exclusive_locks_required(sls_mu)));
649 void testShared() __attribute__((shared_locks_required(sls_mu2)));
650};
651
652void elr_fun() __attribute__((exclusive_locks_required(sls_mu)));
653void elr_fun() {}
654
655LRFoo MyLRFoo;
656LRBar Bar;
657
658void es_fun_0() {
659 aa_mu.Lock();
660 Bar.aa_elr_fun();
661 aa_mu.Unlock();
662}
663
664void es_fun_1() {
665 aa_mu.Lock();
666 Bar.aa_elr_fun_s();
667 aa_mu.Unlock();
668}
669
670void es_fun_2() {
671 aa_mu.ReaderLock();
672 Bar.aa_elr_fun_s();
673 aa_mu.Unlock();
674}
675
676void es_fun_3() {
677 sls_mu.Lock();
678 MyLRFoo.test();
679 sls_mu.Unlock();
680}
681
682void es_fun_4() {
683 sls_mu2.Lock();
684 MyLRFoo.testShared();
685 sls_mu2.Unlock();
686}
687
688void es_fun_5() {
689 sls_mu2.ReaderLock();
690 MyLRFoo.testShared();
691 sls_mu2.Unlock();
692}
693
694void es_fun_6() {
695 Bar.le_fun();
696}
697
698void es_fun_7() {
699 sls_mu.Lock();
700 elr_fun();
701 sls_mu.Unlock();
702}
703
Caitlin Sadowskiaf370612011-09-08 18:35:21 +0000704void es_fun_8() __attribute__((no_thread_safety_analysis));
705
706void es_fun_8() {
707 Bar.aa_elr_fun_s();
708}
709
Caitlin Sadowskicb967512011-09-15 17:43:08 +0000710void es_fun_9() __attribute__((shared_locks_required(aa_mu)));
711void es_fun_9() {
712 Bar.aa_elr_fun_s();
713}
714
715void es_fun_10() __attribute__((exclusive_locks_required(aa_mu)));
716void es_fun_10() {
717 Bar.aa_elr_fun_s();
718}
719
Caitlin Sadowski978191e2011-09-08 18:27:31 +0000720void es_bad_0() {
721 Bar.aa_elr_fun(); // \
Caitlin Sadowski8bccabe2011-09-08 21:52:50 +0000722 // expected-warning {{calling function 'aa_elr_fun' requires exclusive lock on 'aa_mu'}}
Caitlin Sadowski978191e2011-09-08 18:27:31 +0000723}
724
725void es_bad_1() {
726 aa_mu.ReaderLock();
727 Bar.aa_elr_fun(); // \
Caitlin Sadowski8bccabe2011-09-08 21:52:50 +0000728 // expected-warning {{calling function 'aa_elr_fun' requires exclusive lock on 'aa_mu'}}
Caitlin Sadowski978191e2011-09-08 18:27:31 +0000729 aa_mu.Unlock();
730}
731
732void es_bad_2() {
733 Bar.aa_elr_fun_s(); // \
Caitlin Sadowski8bccabe2011-09-08 21:52:50 +0000734 // expected-warning {{calling function 'aa_elr_fun_s' requires shared lock on 'aa_mu'}}
Caitlin Sadowski978191e2011-09-08 18:27:31 +0000735}
736
737void es_bad_3() {
738 MyLRFoo.test(); // \
Caitlin Sadowski8bccabe2011-09-08 21:52:50 +0000739 // expected-warning {{calling function 'test' requires exclusive lock on 'sls_mu'}}
Caitlin Sadowski978191e2011-09-08 18:27:31 +0000740}
741
742void es_bad_4() {
743 MyLRFoo.testShared(); // \
Caitlin Sadowski8bccabe2011-09-08 21:52:50 +0000744 // expected-warning {{calling function 'testShared' requires shared lock on 'sls_mu2'}}
Caitlin Sadowski978191e2011-09-08 18:27:31 +0000745}
746
747void es_bad_5() {
748 sls_mu.ReaderLock();
749 MyLRFoo.test(); // \
Caitlin Sadowski8bccabe2011-09-08 21:52:50 +0000750 // expected-warning {{calling function 'test' requires exclusive lock on 'sls_mu'}}
Caitlin Sadowski978191e2011-09-08 18:27:31 +0000751 sls_mu.Unlock();
752}
753
754void es_bad_6() {
755 sls_mu.Lock();
756 Bar.le_fun(); // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000757 // expected-warning {{cannot call function 'le_fun' while mutex 'sls_mu' is locked}}
Caitlin Sadowski978191e2011-09-08 18:27:31 +0000758 sls_mu.Unlock();
759}
760
761void es_bad_7() {
762 sls_mu.ReaderLock();
763 Bar.le_fun(); // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000764 // expected-warning {{cannot call function 'le_fun' while mutex 'sls_mu' is locked}}
Caitlin Sadowski978191e2011-09-08 18:27:31 +0000765 sls_mu.Unlock();
766}
Caitlin Sadowski194418f2011-09-14 20:00:24 +0000767
DeLesley Hutchins81216392011-10-17 21:38:02 +0000768
Caitlin Sadowski194418f2011-09-14 20:00:24 +0000769//-----------------------------------------------//
770// Unparseable lock expressions
771// ----------------------------------------------//
772
DeLesley Hutchins0d95dfc2012-03-02 23:36:05 +0000773// FIXME -- derive new tests for unhandled expressions
Caitlin Sadowski194418f2011-09-14 20:00:24 +0000774
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +0000775
776//----------------------------------------------------------------------------//
777// The following test cases are ported from the gcc thread safety implementation
778// They are each wrapped inside a namespace with the test number of the gcc test
779//
780// FIXME: add all the gcc tests, once this analysis passes them.
781//----------------------------------------------------------------------------//
782
783//-----------------------------------------//
784// Good testcases (no errors)
785//-----------------------------------------//
786
787namespace thread_annot_lock_20 {
788class Bar {
789 public:
790 static int func1() EXCLUSIVE_LOCKS_REQUIRED(mu1_);
791 static int b_ GUARDED_BY(mu1_);
792 static Mutex mu1_;
793 static int a_ GUARDED_BY(mu1_);
794};
795
796Bar b1;
797
798int Bar::func1()
799{
800 int res = 5;
801
802 if (a_ == 4)
803 res = b_;
804 return res;
805}
806} // end namespace thread_annot_lock_20
807
808namespace thread_annot_lock_22 {
809// Test various usage of GUARDED_BY and PT_GUARDED_BY annotations, especially
810// uses in class definitions.
811Mutex mu;
812
813class Bar {
814 public:
815 int a_ GUARDED_BY(mu1_);
816 int b_;
817 int *q PT_GUARDED_BY(mu);
818 Mutex mu1_ ACQUIRED_AFTER(mu);
819};
820
821Bar b1, *b3;
822int *p GUARDED_BY(mu) PT_GUARDED_BY(mu);
823int res GUARDED_BY(mu) = 5;
824
825int func(int i)
826{
827 int x;
828 mu.Lock();
829 b1.mu1_.Lock();
830 res = b1.a_ + b3->b_;
831 *p = i;
832 b1.a_ = res + b3->b_;
833 b3->b_ = *b1.q;
834 b1.mu1_.Unlock();
835 b1.b_ = res;
836 x = res;
837 mu.Unlock();
838 return x;
839}
840} // end namespace thread_annot_lock_22
841
842namespace thread_annot_lock_27_modified {
843// test lock annotations applied to function definitions
844// Modified: applied annotations only to function declarations
845Mutex mu1;
846Mutex mu2 ACQUIRED_AFTER(mu1);
847
848class Foo {
849 public:
850 int method1(int i) SHARED_LOCKS_REQUIRED(mu2) EXCLUSIVE_LOCKS_REQUIRED(mu1);
851};
852
853int Foo::method1(int i) {
854 return i;
855}
856
857
858int foo(int i) EXCLUSIVE_LOCKS_REQUIRED(mu2) SHARED_LOCKS_REQUIRED(mu1);
859int foo(int i) {
860 return i;
861}
862
863static int bar(int i) EXCLUSIVE_LOCKS_REQUIRED(mu1);
864static int bar(int i) {
865 return i;
866}
867
868void main() {
869 Foo a;
870
871 mu1.Lock();
872 mu2.Lock();
873 a.method1(1);
874 foo(2);
875 mu2.Unlock();
876 bar(3);
877 mu1.Unlock();
878}
879} // end namespace thread_annot_lock_27_modified
880
881
882namespace thread_annot_lock_38 {
883// Test the case where a template member function is annotated with lock
884// attributes in a non-template class.
885class Foo {
886 public:
887 void func1(int y) LOCKS_EXCLUDED(mu_);
888 template <typename T> void func2(T x) LOCKS_EXCLUDED(mu_);
889 private:
890 Mutex mu_;
891};
892
893Foo *foo;
894
895void main()
896{
897 foo->func1(5);
898 foo->func2(5);
899}
900} // end namespace thread_annot_lock_38
901
902namespace thread_annot_lock_43 {
903// Tests lock canonicalization
904class Foo {
905 public:
906 Mutex *mu_;
907};
908
909class FooBar {
910 public:
911 Foo *foo_;
912 int GetA() EXCLUSIVE_LOCKS_REQUIRED(foo_->mu_) { return a_; }
913 int a_ GUARDED_BY(foo_->mu_);
914};
915
916FooBar *fb;
917
918void main()
919{
920 int x;
921 fb->foo_->mu_->Lock();
922 x = fb->GetA();
923 fb->foo_->mu_->Unlock();
924}
925} // end namespace thread_annot_lock_43
926
927namespace thread_annot_lock_49 {
928// Test the support for use of lock expression in the annotations
929class Foo {
930 public:
931 Mutex foo_mu_;
932};
933
934class Bar {
935 private:
936 Foo *foo;
937 Mutex bar_mu_ ACQUIRED_AFTER(foo->foo_mu_);
938
939 public:
940 void Test1() {
941 foo->foo_mu_.Lock();
942 bar_mu_.Lock();
943 bar_mu_.Unlock();
944 foo->foo_mu_.Unlock();
945 }
946};
947
948void main() {
949 Bar bar;
950 bar.Test1();
951}
952} // end namespace thread_annot_lock_49
953
954namespace thread_annot_lock_61_modified {
955 // Modified to fix the compiler errors
956 // Test the fix for a bug introduced by the support of pass-by-reference
957 // paramters.
958 struct Foo { Foo &operator<< (bool) {return *this;} };
959 Foo &getFoo();
960 struct Bar { Foo &func () {return getFoo();} };
961 struct Bas { void operator& (Foo &) {} };
962 void mumble()
963 {
964 Bas() & Bar().func() << "" << "";
965 Bas() & Bar().func() << "";
966 }
967} // end namespace thread_annot_lock_61_modified
968
969
970namespace thread_annot_lock_65 {
971// Test the fix for a bug in the support of allowing reader locks for
972// non-const, non-modifying overload functions. (We didn't handle the builtin
973// properly.)
974enum MyFlags {
975 Zero,
976 One,
977 Two,
978 Three,
979 Four,
980 Five,
981 Six,
982 Seven,
983 Eight,
984 Nine
985};
986
987inline MyFlags
988operator|(MyFlags a, MyFlags b)
989{
990 return MyFlags(static_cast<int>(a) | static_cast<int>(b));
991}
992
993inline MyFlags&
994operator|=(MyFlags& a, MyFlags b)
995{
996 return a = a | b;
997}
998} // end namespace thread_annot_lock_65
999
1000namespace thread_annot_lock_66_modified {
1001// Modified: Moved annotation to function defn
1002// Test annotations on out-of-line definitions of member functions where the
1003// annotations refer to locks that are also data members in the class.
1004Mutex mu;
1005
1006class Foo {
1007 public:
1008 int method1(int i) SHARED_LOCKS_REQUIRED(mu1, mu, mu2);
1009 int data GUARDED_BY(mu1);
1010 Mutex *mu1;
1011 Mutex *mu2;
1012};
1013
1014int Foo::method1(int i)
1015{
1016 return data + i;
1017}
1018
1019void main()
1020{
1021 Foo a;
1022
1023 a.mu2->Lock();
1024 a.mu1->Lock();
1025 mu.Lock();
1026 a.method1(1);
1027 mu.Unlock();
1028 a.mu1->Unlock();
1029 a.mu2->Unlock();
1030}
1031} // end namespace thread_annot_lock_66_modified
1032
1033namespace thread_annot_lock_68_modified {
1034// Test a fix to a bug in the delayed name binding with nested template
1035// instantiation. We use a stack to make sure a name is not resolved to an
1036// inner context.
1037template <typename T>
1038class Bar {
1039 Mutex mu_;
1040};
1041
1042template <typename T>
1043class Foo {
1044 public:
1045 void func(T x) {
1046 mu_.Lock();
DeLesley Hutchins23323e02012-01-20 22:50:54 +00001047 count_ = x;
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001048 mu_.Unlock();
1049 }
1050
1051 private:
DeLesley Hutchins23323e02012-01-20 22:50:54 +00001052 T count_ GUARDED_BY(mu_);
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001053 Bar<T> bar_;
1054 Mutex mu_;
1055};
1056
1057void main()
1058{
1059 Foo<int> *foo;
1060 foo->func(5);
1061}
1062} // end namespace thread_annot_lock_68_modified
1063
1064namespace thread_annot_lock_30_modified {
1065// Test delay parsing of lock attribute arguments with nested classes.
1066// Modified: trylocks replaced with exclusive_lock_fun
1067int a = 0;
1068
1069class Bar {
1070 struct Foo;
1071
1072 public:
1073 void MyLock() EXCLUSIVE_LOCK_FUNCTION(mu);
1074
1075 int func() {
1076 MyLock();
1077// if (foo == 0) {
1078// return 0;
1079// }
1080 a = 5;
1081 mu.Unlock();
1082 return 1;
1083 }
1084
1085 class FooBar {
1086 int x;
1087 int y;
1088 };
1089
1090 private:
1091 Mutex mu;
1092};
1093
1094Bar *bar;
1095
1096void main()
1097{
1098 bar->func();
1099}
1100} // end namespace thread_annot_lock_30_modified
1101
1102namespace thread_annot_lock_47 {
1103// Test the support for annotations on virtual functions.
1104// This is a good test case. (i.e. There should be no warning emitted by the
1105// compiler.)
1106class Base {
1107 public:
1108 virtual void func1() EXCLUSIVE_LOCKS_REQUIRED(mu_);
1109 virtual void func2() LOCKS_EXCLUDED(mu_);
1110 Mutex mu_;
1111};
1112
1113class Child : public Base {
1114 public:
1115 virtual void func1() EXCLUSIVE_LOCKS_REQUIRED(mu_);
1116 virtual void func2() LOCKS_EXCLUDED(mu_);
1117};
1118
1119void main() {
1120 Child *c;
1121 Base *b = c;
1122
1123 b->mu_.Lock();
1124 b->func1();
1125 b->mu_.Unlock();
1126 b->func2();
1127
1128 c->mu_.Lock();
1129 c->func1();
1130 c->mu_.Unlock();
1131 c->func2();
1132}
1133} // end namespace thread_annot_lock_47
1134
1135//-----------------------------------------//
1136// Tests which produce errors
1137//-----------------------------------------//
1138
1139namespace thread_annot_lock_13 {
1140Mutex mu1;
1141Mutex mu2;
1142
1143int g GUARDED_BY(mu1);
1144int w GUARDED_BY(mu2);
1145
1146class Foo {
1147 public:
1148 void bar() LOCKS_EXCLUDED(mu_, mu1);
1149 int foo() SHARED_LOCKS_REQUIRED(mu_) EXCLUSIVE_LOCKS_REQUIRED(mu2);
1150
1151 private:
1152 int a_ GUARDED_BY(mu_);
1153 public:
1154 Mutex mu_ ACQUIRED_AFTER(mu1);
1155};
1156
1157int Foo::foo()
1158{
1159 int res;
David Blaikiee31b8fb2012-04-05 00:16:44 +00001160 w = 5;
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001161 res = a_ + 5;
1162 return res;
1163}
1164
1165void Foo::bar()
1166{
1167 int x;
1168 mu_.Lock();
1169 x = foo(); // expected-warning {{calling function 'foo' requires exclusive lock on 'mu2'}}
1170 a_ = x + 1;
1171 mu_.Unlock();
1172 if (x > 5) {
1173 mu1.Lock();
David Blaikiee31b8fb2012-04-05 00:16:44 +00001174 g = 2;
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001175 mu1.Unlock();
1176 }
1177}
1178
1179void main()
1180{
1181 Foo f1, *f2;
1182 f1.mu_.Lock();
Caitlin Sadowski74558b42011-09-15 18:13:32 +00001183 f1.bar(); // expected-warning {{cannot call function 'bar' while mutex 'mu_' is locked}}
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001184 mu2.Lock();
1185 f1.foo();
1186 mu2.Unlock();
1187 f1.mu_.Unlock();
1188 f2->mu_.Lock();
Caitlin Sadowski74558b42011-09-15 18:13:32 +00001189 f2->bar(); // expected-warning {{cannot call function 'bar' while mutex 'mu_' is locked}}
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001190 f2->mu_.Unlock();
1191 mu2.Lock();
David Blaikiee31b8fb2012-04-05 00:16:44 +00001192 w = 2;
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001193 mu2.Unlock();
1194}
1195} // end namespace thread_annot_lock_13
1196
1197namespace thread_annot_lock_18_modified {
1198// Modified: Trylocks removed
1199// Test the ability to distnguish between the same lock field of
1200// different objects of a class.
1201 class Bar {
1202 public:
1203 bool MyLock() EXCLUSIVE_LOCK_FUNCTION(mu1_);
1204 void MyUnlock() UNLOCK_FUNCTION(mu1_);
1205 int a_ GUARDED_BY(mu1_);
1206
1207 private:
1208 Mutex mu1_;
1209};
1210
1211Bar *b1, *b2;
1212
1213void func()
1214{
1215 b1->MyLock();
1216 b1->a_ = 5;
Caitlin Sadowski74558b42011-09-15 18:13:32 +00001217 b2->a_ = 3; // expected-warning {{writing variable 'a_' requires locking 'mu1_' exclusively}}
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001218 b2->MyLock();
1219 b2->MyUnlock();
1220 b1->MyUnlock();
1221}
1222} // end namespace thread_annot_lock_18_modified
1223
1224namespace thread_annot_lock_21 {
1225// Test various usage of GUARDED_BY and PT_GUARDED_BY annotations, especially
1226// uses in class definitions.
1227Mutex mu;
1228
1229class Bar {
1230 public:
1231 int a_ GUARDED_BY(mu1_);
1232 int b_;
1233 int *q PT_GUARDED_BY(mu);
1234 Mutex mu1_ ACQUIRED_AFTER(mu);
1235};
1236
1237Bar b1, *b3;
1238int *p GUARDED_BY(mu) PT_GUARDED_BY(mu);
1239
1240int res GUARDED_BY(mu) = 5;
1241
1242int func(int i)
1243{
1244 int x;
1245 b3->mu1_.Lock();
Caitlin Sadowski74558b42011-09-15 18:13:32 +00001246 res = b1.a_ + b3->b_; // expected-warning {{reading variable 'a_' requires locking 'mu1_'}} \
1247 // expected-warning {{writing variable 'res' requires locking 'mu' exclusively}}
1248 *p = i; // expected-warning {{reading variable 'p' requires locking 'mu'}} \
1249 // expected-warning {{writing the value pointed to by 'p' requires locking 'mu' exclusively}}
1250 b1.a_ = res + b3->b_; // expected-warning {{reading variable 'res' requires locking 'mu'}} \
1251 // expected-warning {{writing variable 'a_' requires locking 'mu1_' exclusively}}
1252 b3->b_ = *b1.q; // expected-warning {{reading the value pointed to by 'q' requires locking 'mu'}}
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001253 b3->mu1_.Unlock();
Caitlin Sadowski74558b42011-09-15 18:13:32 +00001254 b1.b_ = res; // expected-warning {{reading variable 'res' requires locking 'mu'}}
1255 x = res; // expected-warning {{reading variable 'res' requires locking 'mu'}}
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001256 return x;
1257}
1258} // end namespace thread_annot_lock_21
1259
1260namespace thread_annot_lock_35_modified {
1261// Test the analyzer's ability to distinguish the lock field of different
1262// objects.
1263class Foo {
1264 private:
1265 Mutex lock_;
1266 int a_ GUARDED_BY(lock_);
1267
1268 public:
1269 void Func(Foo* child) LOCKS_EXCLUDED(lock_) {
1270 Foo *new_foo = new Foo;
1271
1272 lock_.Lock();
1273
1274 child->Func(new_foo); // There shouldn't be any warning here as the
1275 // acquired lock is not in child.
1276 child->bar(7); // expected-warning {{calling function 'bar' requires exclusive lock on 'lock_'}}
Caitlin Sadowski74558b42011-09-15 18:13:32 +00001277 child->a_ = 5; // expected-warning {{writing variable 'a_' requires locking 'lock_' exclusively}}
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001278 lock_.Unlock();
1279 }
1280
1281 void bar(int y) EXCLUSIVE_LOCKS_REQUIRED(lock_) {
1282 a_ = y;
1283 }
1284};
1285
1286Foo *x;
1287
1288void main() {
1289 Foo *child = new Foo;
1290 x->Func(child);
1291}
1292} // end namespace thread_annot_lock_35_modified
1293
1294namespace thread_annot_lock_36_modified {
1295// Modified to move the annotations to function defns.
1296// Test the analyzer's ability to distinguish the lock field of different
1297// objects
1298class Foo {
1299 private:
1300 Mutex lock_;
1301 int a_ GUARDED_BY(lock_);
1302
1303 public:
1304 void Func(Foo* child) LOCKS_EXCLUDED(lock_);
1305 void bar(int y) EXCLUSIVE_LOCKS_REQUIRED(lock_);
1306};
1307
1308void Foo::Func(Foo* child) {
1309 Foo *new_foo = new Foo;
1310
1311 lock_.Lock();
1312
1313 child->lock_.Lock();
Caitlin Sadowski74558b42011-09-15 18:13:32 +00001314 child->Func(new_foo); // expected-warning {{cannot call function 'Func' while mutex 'lock_' is locked}}
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001315 child->bar(7);
1316 child->a_ = 5;
1317 child->lock_.Unlock();
1318
1319 lock_.Unlock();
1320}
1321
1322void Foo::bar(int y) {
1323 a_ = y;
1324}
1325
1326
1327Foo *x;
1328
1329void main() {
1330 Foo *child = new Foo;
1331 x->Func(child);
1332}
1333} // end namespace thread_annot_lock_36_modified
1334
1335
1336namespace thread_annot_lock_42 {
1337// Test support of multiple lock attributes of the same kind on a decl.
1338class Foo {
1339 private:
1340 Mutex mu1, mu2, mu3;
1341 int x GUARDED_BY(mu1) GUARDED_BY(mu2);
1342 int y GUARDED_BY(mu2);
1343
1344 void f2() LOCKS_EXCLUDED(mu1) LOCKS_EXCLUDED(mu2) LOCKS_EXCLUDED(mu3) {
1345 mu2.Lock();
1346 y = 2;
1347 mu2.Unlock();
1348 }
1349
1350 public:
1351 void f1() EXCLUSIVE_LOCKS_REQUIRED(mu2) EXCLUSIVE_LOCKS_REQUIRED(mu1) {
1352 x = 5;
Caitlin Sadowski74558b42011-09-15 18:13:32 +00001353 f2(); // expected-warning {{cannot call function 'f2' while mutex 'mu1' is locked}} \
1354 // expected-warning {{cannot call function 'f2' while mutex 'mu2' is locked}}
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001355 }
1356};
1357
1358Foo *foo;
1359
1360void func()
1361{
1362 foo->f1(); // expected-warning {{calling function 'f1' requires exclusive lock on 'mu2'}} \
1363 // expected-warning {{calling function 'f1' requires exclusive lock on 'mu1'}}
1364}
1365} // end namespace thread_annot_lock_42
1366
1367namespace thread_annot_lock_46 {
1368// Test the support for annotations on virtual functions.
1369class Base {
1370 public:
1371 virtual void func1() EXCLUSIVE_LOCKS_REQUIRED(mu_);
1372 virtual void func2() LOCKS_EXCLUDED(mu_);
1373 Mutex mu_;
1374};
1375
1376class Child : public Base {
1377 public:
1378 virtual void func1() EXCLUSIVE_LOCKS_REQUIRED(mu_);
1379 virtual void func2() LOCKS_EXCLUDED(mu_);
1380};
1381
1382void main() {
1383 Child *c;
1384 Base *b = c;
1385
1386 b->func1(); // expected-warning {{calling function 'func1' requires exclusive lock on 'mu_'}}
1387 b->mu_.Lock();
Caitlin Sadowski74558b42011-09-15 18:13:32 +00001388 b->func2(); // expected-warning {{cannot call function 'func2' while mutex 'mu_' is locked}}
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001389 b->mu_.Unlock();
1390
1391 c->func1(); // expected-warning {{calling function 'func1' requires exclusive lock on 'mu_'}}
1392 c->mu_.Lock();
Caitlin Sadowski74558b42011-09-15 18:13:32 +00001393 c->func2(); // expected-warning {{cannot call function 'func2' while mutex 'mu_' is locked}}
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001394 c->mu_.Unlock();
1395}
1396} // end namespace thread_annot_lock_46
1397
1398namespace thread_annot_lock_67_modified {
1399// Modified: attributes on definitions moved to declarations
1400// Test annotations on out-of-line definitions of member functions where the
1401// annotations refer to locks that are also data members in the class.
1402Mutex mu;
1403Mutex mu3;
1404
1405class Foo {
1406 public:
1407 int method1(int i) SHARED_LOCKS_REQUIRED(mu1, mu, mu2, mu3);
1408 int data GUARDED_BY(mu1);
1409 Mutex *mu1;
1410 Mutex *mu2;
1411};
1412
1413int Foo::method1(int i) {
1414 return data + i;
1415}
1416
1417void main()
1418{
1419 Foo a;
1420 a.method1(1); // expected-warning {{calling function 'method1' requires shared lock on 'mu1'}} \
1421 // expected-warning {{calling function 'method1' requires shared lock on 'mu'}} \
1422 // expected-warning {{calling function 'method1' requires shared lock on 'mu2'}} \
1423 // expected-warning {{calling function 'method1' requires shared lock on 'mu3'}}
1424}
1425} // end namespace thread_annot_lock_67_modified
1426
1427
DeLesley Hutchins81216392011-10-17 21:38:02 +00001428namespace substitution_test {
1429 class MyData {
1430 public:
1431 Mutex mu;
1432
1433 void lockData() __attribute__((exclusive_lock_function(mu))) { }
1434 void unlockData() __attribute__((unlock_function(mu))) { }
1435
1436 void doSomething() __attribute__((exclusive_locks_required(mu))) { }
1437 };
1438
1439
1440 class DataLocker {
1441 public:
1442 void lockData (MyData *d) __attribute__((exclusive_lock_function(d->mu))) { }
1443 void unlockData(MyData *d) __attribute__((unlock_function(d->mu))) { }
1444 };
1445
1446
1447 class Foo {
1448 public:
1449 void foo(MyData* d) __attribute__((exclusive_locks_required(d->mu))) { }
1450
1451 void bar1(MyData* d) {
1452 d->lockData();
1453 foo(d);
1454 d->unlockData();
1455 }
1456
1457 void bar2(MyData* d) {
1458 DataLocker dlr;
1459 dlr.lockData(d);
1460 foo(d);
1461 dlr.unlockData(d);
1462 }
1463
1464 void bar3(MyData* d1, MyData* d2) {
1465 DataLocker dlr;
Richard Smith2e515622012-02-03 04:45:26 +00001466 dlr.lockData(d1); // expected-note {{mutex acquired here}}
DeLesley Hutchins81216392011-10-17 21:38:02 +00001467 dlr.unlockData(d2); // \
1468 // expected-warning {{unlocking 'mu' that was not locked}}
Richard Smith2e515622012-02-03 04:45:26 +00001469 } // expected-warning {{mutex 'mu' is still locked at the end of function}}
DeLesley Hutchins81216392011-10-17 21:38:02 +00001470
1471 void bar4(MyData* d1, MyData* d2) {
1472 DataLocker dlr;
1473 dlr.lockData(d1);
1474 foo(d2); // \
1475 // expected-warning {{calling function 'foo' requires exclusive lock on 'mu'}}
1476 dlr.unlockData(d1);
1477 }
1478 };
1479} // end namespace substituation_test
1480
DeLesley Hutchinse0eaa852011-10-21 18:06:53 +00001481
DeLesley Hutchinsf1ac6372011-10-21 18:10:14 +00001482
DeLesley Hutchinse0eaa852011-10-21 18:06:53 +00001483namespace constructor_destructor_tests {
1484 Mutex fooMu;
1485 int myVar GUARDED_BY(fooMu);
1486
1487 class Foo {
1488 public:
1489 Foo() __attribute__((exclusive_lock_function(fooMu))) { }
1490 ~Foo() __attribute__((unlock_function(fooMu))) { }
1491 };
1492
1493 void fooTest() {
DeLesley Hutchins6db51f72011-10-21 20:51:27 +00001494 Foo foo;
DeLesley Hutchinse0eaa852011-10-21 18:06:53 +00001495 myVar = 0;
1496 }
1497}
1498
DeLesley Hutchinsf1ac6372011-10-21 18:10:14 +00001499
1500namespace invalid_lock_expression_test {
1501
1502class LOCKABLE MyLockable {
1503public:
1504 MyLockable() __attribute__((exclusive_lock_function)) { }
DeLesley Hutchins6db51f72011-10-21 20:51:27 +00001505 ~MyLockable() { }
DeLesley Hutchinsf1ac6372011-10-21 18:10:14 +00001506};
1507
1508// create an empty lock expression
1509void foo() {
1510 MyLockable lock; // \
1511 // expected-warning {{cannot resolve lock expression}}
1512}
1513
1514} // end namespace invalid_lock_expression_test
1515
Richard Smith97f9fe02011-10-25 00:41:24 +00001516namespace template_member_test {
DeLesley Hutchinsf1ac6372011-10-21 18:10:14 +00001517
Richard Smith97f9fe02011-10-25 00:41:24 +00001518 struct S { int n; };
1519 struct T {
1520 Mutex m;
1521 S *s GUARDED_BY(this->m);
1522 };
Richard Smitha01c7112011-10-25 06:33:21 +00001523 Mutex m;
1524 struct U {
1525 union {
1526 int n;
1527 };
1528 } *u GUARDED_BY(m);
Richard Smith97f9fe02011-10-25 00:41:24 +00001529
1530 template<typename U>
1531 struct IndirectLock {
1532 int DoNaughtyThings(T *t) {
Richard Smitha01c7112011-10-25 06:33:21 +00001533 u->n = 0; // expected-warning {{reading variable 'u' requires locking 'm'}}
Richard Smith97f9fe02011-10-25 00:41:24 +00001534 return t->s->n; // expected-warning {{reading variable 's' requires locking 'm'}}
1535 }
1536 };
1537
Richard Smithf11e9232011-10-25 01:05:41 +00001538 template struct IndirectLock<int>; // expected-note {{here}}
Richard Smith97f9fe02011-10-25 00:41:24 +00001539
Richard Smith601d2ee2011-10-26 06:15:36 +00001540 struct V {
1541 void f(int);
1542 void f(double);
1543
1544 Mutex m;
1545 V *p GUARDED_BY(this->m);
1546 };
1547 template<typename U> struct W {
1548 V v;
1549 void f(U u) {
1550 v.p->f(u); // expected-warning {{reading variable 'p' requires locking 'm'}}
1551 }
1552 };
1553 template struct W<int>; // expected-note {{here}}
1554
Richard Smith97f9fe02011-10-25 00:41:24 +00001555}
DeLesley Hutchins1fa3c062011-12-08 20:23:06 +00001556
1557namespace test_scoped_lockable {
1558
1559struct TestScopedLockable {
1560 Mutex mu1;
1561 Mutex mu2;
1562 int a __attribute__((guarded_by(mu1)));
1563 int b __attribute__((guarded_by(mu2)));
1564
1565 bool getBool();
1566
1567 void foo1() {
1568 MutexLock mulock(&mu1);
1569 a = 5;
1570 }
1571
1572 void foo2() {
1573 ReaderMutexLock mulock1(&mu1);
1574 if (getBool()) {
1575 MutexLock mulock2a(&mu2);
1576 b = a + 1;
1577 }
1578 else {
1579 MutexLock mulock2b(&mu2);
1580 b = a + 2;
1581 }
1582 }
1583
1584 void foo3() {
1585 MutexLock mulock_a(&mu1);
1586 MutexLock mulock_b(&mu1); // \
1587 // expected-warning {{locking 'mu1' that is already locked}}
DeLesley Hutchinsc99a5d82012-06-28 22:42:48 +00001588 }
DeLesley Hutchins1fa3c062011-12-08 20:23:06 +00001589
1590 void foo4() {
1591 MutexLock mulock1(&mu1), mulock2(&mu2);
1592 a = b+1;
1593 b = a+1;
1594 }
1595};
1596
1597} // end namespace test_scoped_lockable
1598
1599
DeLesley Hutchinsdf497822011-12-29 00:56:48 +00001600namespace FunctionAttrTest {
1601
1602class Foo {
1603public:
1604 Mutex mu_;
1605 int a GUARDED_BY(mu_);
1606};
1607
1608Foo fooObj;
1609
1610void foo() EXCLUSIVE_LOCKS_REQUIRED(fooObj.mu_);
1611
1612void bar() {
1613 foo(); // expected-warning {{calling function 'foo' requires exclusive lock on 'mu_'}}
1614 fooObj.mu_.Lock();
1615 foo();
1616 fooObj.mu_.Unlock();
1617}
1618
1619}; // end namespace FunctionAttrTest
1620
1621
DeLesley Hutchinsb4fa4182012-01-06 19:16:50 +00001622struct TestTryLock {
1623 Mutex mu;
1624 int a GUARDED_BY(mu);
1625 bool cond;
1626
1627 void foo1() {
1628 if (mu.TryLock()) {
1629 a = 1;
1630 mu.Unlock();
1631 }
1632 }
1633
1634 void foo2() {
1635 if (!mu.TryLock()) return;
1636 a = 2;
1637 mu.Unlock();
1638 }
1639
1640 void foo3() {
1641 bool b = mu.TryLock();
1642 if (b) {
1643 a = 3;
1644 mu.Unlock();
1645 }
1646 }
1647
1648 void foo4() {
1649 bool b = mu.TryLock();
1650 if (!b) return;
1651 a = 4;
1652 mu.Unlock();
1653 }
1654
1655 void foo5() {
1656 while (mu.TryLock()) {
1657 a = a + 1;
1658 mu.Unlock();
1659 }
1660 }
1661
1662 void foo6() {
1663 bool b = mu.TryLock();
1664 b = !b;
1665 if (b) return;
1666 a = 6;
1667 mu.Unlock();
1668 }
1669
1670 void foo7() {
1671 bool b1 = mu.TryLock();
1672 bool b2 = !b1;
1673 bool b3 = !b2;
1674 if (b3) {
1675 a = 7;
1676 mu.Unlock();
1677 }
1678 }
1679
1680 // Test use-def chains: join points
1681 void foo8() {
1682 bool b = mu.TryLock();
1683 bool b2 = b;
1684 if (cond)
1685 b = true;
1686 if (b) { // b should be unknown at this point, becuase of the join point
1687 a = 8; // expected-warning {{writing variable 'a' requires locking 'mu' exclusively}}
1688 }
1689 if (b2) { // b2 should be known at this point.
1690 a = 8;
1691 mu.Unlock();
1692 }
1693 }
1694
1695 // Test use-def-chains: back edges
1696 void foo9() {
1697 bool b = mu.TryLock();
1698
1699 for (int i = 0; i < 10; ++i);
1700
1701 if (b) { // b is still known, because the loop doesn't alter it
1702 a = 9;
1703 mu.Unlock();
1704 }
1705 }
1706
1707 // Test use-def chains: back edges
1708 void foo10() {
1709 bool b = mu.TryLock();
1710
1711 while (cond) {
1712 if (b) { // b should be uknown at this point b/c of the loop
1713 a = 10; // expected-warning {{writing variable 'a' requires locking 'mu' exclusively}}
1714 }
1715 b = !b;
1716 }
1717 }
1718}; // end TestTrylock
1719
1720
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +00001721namespace TestTemplateAttributeInstantiation {
1722
1723class Foo1 {
1724public:
1725 Mutex mu_;
1726 int a GUARDED_BY(mu_);
1727};
1728
1729class Foo2 {
1730public:
1731 int a GUARDED_BY(mu_);
1732 Mutex mu_;
1733};
1734
1735
1736class Bar {
1737public:
1738 // Test non-dependent expressions in attributes on template functions
1739 template <class T>
1740 void barND(Foo1 *foo, T *fooT) EXCLUSIVE_LOCKS_REQUIRED(foo->mu_) {
1741 foo->a = 0;
1742 }
1743
1744 // Test dependent expressions in attributes on template functions
1745 template <class T>
1746 void barD(Foo1 *foo, T *fooT) EXCLUSIVE_LOCKS_REQUIRED(fooT->mu_) {
1747 fooT->a = 0;
1748 }
1749};
1750
1751
1752template <class T>
1753class BarT {
1754public:
1755 Foo1 fooBase;
1756 T fooBaseT;
1757
1758 // Test non-dependent expression in ordinary method on template class
1759 void barND() EXCLUSIVE_LOCKS_REQUIRED(fooBase.mu_) {
1760 fooBase.a = 0;
1761 }
1762
1763 // Test dependent expressions in ordinary methods on template class
1764 void barD() EXCLUSIVE_LOCKS_REQUIRED(fooBaseT.mu_) {
1765 fooBaseT.a = 0;
1766 }
1767
1768 // Test dependent expressions in template method in template class
1769 template <class T2>
1770 void barTD(T2 *fooT) EXCLUSIVE_LOCKS_REQUIRED(fooBaseT.mu_, fooT->mu_) {
1771 fooBaseT.a = 0;
1772 fooT->a = 0;
1773 }
1774};
1775
1776template <class T>
1777class Cell {
1778public:
1779 Mutex mu_;
1780 // Test dependent guarded_by
1781 T data GUARDED_BY(mu_);
1782
DeLesley Hutchins23323e02012-01-20 22:50:54 +00001783 void fooEx() EXCLUSIVE_LOCKS_REQUIRED(mu_) {
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +00001784 data = 0;
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +00001785 }
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +00001786
1787 void foo() {
1788 mu_.Lock();
1789 data = 0;
1790 mu_.Unlock();
1791 }
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +00001792};
1793
1794void test() {
1795 Bar b;
1796 BarT<Foo2> bt;
1797 Foo1 f1;
1798 Foo2 f2;
1799
1800 f1.mu_.Lock();
1801 f2.mu_.Lock();
1802 bt.fooBase.mu_.Lock();
1803 bt.fooBaseT.mu_.Lock();
1804
1805 b.barND(&f1, &f2);
1806 b.barD(&f1, &f2);
1807 bt.barND();
1808 bt.barD();
1809 bt.barTD(&f2);
1810
1811 f1.mu_.Unlock();
1812 bt.barTD(&f1); // \
1813 // expected-warning {{calling function 'barTD' requires exclusive lock on 'mu_'}}
1814
1815 bt.fooBase.mu_.Unlock();
1816 bt.fooBaseT.mu_.Unlock();
1817 f2.mu_.Unlock();
1818
1819 Cell<int> cell;
1820 cell.data = 0; // \
1821 // expected-warning {{writing variable 'data' requires locking 'mu_' exclusively}}
1822 cell.foo();
DeLesley Hutchins23323e02012-01-20 22:50:54 +00001823 cell.mu_.Lock();
1824 cell.fooEx();
1825 cell.mu_.Unlock();
1826}
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +00001827
DeLesley Hutchins23323e02012-01-20 22:50:54 +00001828
1829template <class T>
1830class CellDelayed {
1831public:
1832 // Test dependent guarded_by
1833 T data GUARDED_BY(mu_);
DeLesley Hutchinsdd5756c2012-02-16 17:30:51 +00001834 static T static_data GUARDED_BY(static_mu_);
DeLesley Hutchins23323e02012-01-20 22:50:54 +00001835
1836 void fooEx(CellDelayed<T> *other) EXCLUSIVE_LOCKS_REQUIRED(mu_, other->mu_) {
1837 this->data = other->data;
1838 }
1839
1840 template <class T2>
1841 void fooExT(CellDelayed<T2> *otherT) EXCLUSIVE_LOCKS_REQUIRED(mu_, otherT->mu_) {
1842 this->data = otherT->data;
1843 }
1844
1845 void foo() {
1846 mu_.Lock();
1847 data = 0;
1848 mu_.Unlock();
1849 }
1850
1851 Mutex mu_;
DeLesley Hutchinsdd5756c2012-02-16 17:30:51 +00001852 static Mutex static_mu_;
DeLesley Hutchins23323e02012-01-20 22:50:54 +00001853};
1854
1855void testDelayed() {
1856 CellDelayed<int> celld;
1857 CellDelayed<int> celld2;
1858 celld.foo();
1859 celld.mu_.Lock();
1860 celld2.mu_.Lock();
1861
1862 celld.fooEx(&celld2);
1863 celld.fooExT(&celld2);
1864
1865 celld2.mu_.Unlock();
1866 celld.mu_.Unlock();
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +00001867}
1868
1869}; // end namespace TestTemplateAttributeInstantiation
1870
1871
DeLesley Hutchinse03b2b32012-01-20 23:24:41 +00001872namespace FunctionDeclDefTest {
1873
1874class Foo {
1875public:
1876 Mutex mu_;
1877 int a GUARDED_BY(mu_);
1878
1879 virtual void foo1(Foo *f_declared) EXCLUSIVE_LOCKS_REQUIRED(f_declared->mu_);
1880};
1881
1882// EXCLUSIVE_LOCKS_REQUIRED should be applied, and rewritten to f_defined->mu_
1883void Foo::foo1(Foo *f_defined) {
1884 f_defined->a = 0;
1885};
1886
1887void test() {
1888 Foo myfoo;
1889 myfoo.foo1(&myfoo); // \
1890 // expected-warning {{calling function 'foo1' requires exclusive lock on 'mu_'}}
1891 myfoo.mu_.Lock();
1892 myfoo.foo1(&myfoo);
1893 myfoo.mu_.Unlock();
1894}
1895
1896};
Richard Smith2e515622012-02-03 04:45:26 +00001897
1898namespace GoingNative {
1899
1900 struct __attribute__((lockable)) mutex {
1901 void lock() __attribute__((exclusive_lock_function));
1902 void unlock() __attribute__((unlock_function));
1903 // ...
1904 };
1905 bool foo();
1906 bool bar();
1907 mutex m;
1908 void test() {
1909 m.lock();
1910 while (foo()) {
1911 m.unlock();
1912 // ...
1913 if (bar()) {
1914 // ...
1915 if (foo())
1916 continue; // expected-warning {{expecting mutex 'm' to be locked at start of each loop}}
1917 //...
1918 }
1919 // ...
1920 m.lock(); // expected-note {{mutex acquired here}}
1921 }
1922 m.unlock();
1923 }
1924
1925}
DeLesley Hutchinsc24a2332012-02-16 16:50:43 +00001926
1927
1928
1929namespace FunctionDefinitionTest {
1930
1931class Foo {
1932public:
1933 void foo1();
1934 void foo2();
1935 void foo3(Foo *other);
1936
1937 template<class T>
1938 void fooT1(const T& dummy1);
1939
1940 template<class T>
1941 void fooT2(const T& dummy2) EXCLUSIVE_LOCKS_REQUIRED(mu_);
1942
1943 Mutex mu_;
1944 int a GUARDED_BY(mu_);
1945};
1946
1947template<class T>
1948class FooT {
1949public:
1950 void foo();
1951
1952 Mutex mu_;
1953 T a GUARDED_BY(mu_);
1954};
1955
1956
1957void Foo::foo1() NO_THREAD_SAFETY_ANALYSIS {
1958 a = 1;
1959}
1960
1961void Foo::foo2() EXCLUSIVE_LOCKS_REQUIRED(mu_) {
1962 a = 2;
1963}
1964
1965void Foo::foo3(Foo *other) EXCLUSIVE_LOCKS_REQUIRED(other->mu_) {
1966 other->a = 3;
1967}
1968
1969template<class T>
1970void Foo::fooT1(const T& dummy1) EXCLUSIVE_LOCKS_REQUIRED(mu_) {
1971 a = dummy1;
1972}
1973
1974/* TODO -- uncomment with template instantiation of attributes.
1975template<class T>
1976void Foo::fooT2(const T& dummy2) {
1977 a = dummy2;
1978}
1979*/
1980
1981void fooF1(Foo *f) EXCLUSIVE_LOCKS_REQUIRED(f->mu_) {
1982 f->a = 1;
1983}
1984
1985void fooF2(Foo *f);
1986void fooF2(Foo *f) EXCLUSIVE_LOCKS_REQUIRED(f->mu_) {
1987 f->a = 2;
1988}
1989
1990void fooF3(Foo *f) EXCLUSIVE_LOCKS_REQUIRED(f->mu_);
1991void fooF3(Foo *f) {
1992 f->a = 3;
1993}
1994
1995template<class T>
1996void FooT<T>::foo() EXCLUSIVE_LOCKS_REQUIRED(mu_) {
1997 a = 0;
1998}
1999
2000void test() {
2001 int dummy = 0;
2002 Foo myFoo;
2003
2004 myFoo.foo2(); // \
2005 // expected-warning {{calling function 'foo2' requires exclusive lock on 'mu_'}}
2006 myFoo.foo3(&myFoo); // \
2007 // expected-warning {{calling function 'foo3' requires exclusive lock on 'mu_'}}
2008 myFoo.fooT1(dummy); // \
2009 // expected-warning {{calling function 'fooT1' requires exclusive lock on 'mu_'}}
2010
2011 // FIXME: uncomment with template instantiation of attributes patch
2012 // myFoo.fooT2(dummy); // expected warning
2013
2014 fooF1(&myFoo); // \
2015 // expected-warning {{calling function 'fooF1' requires exclusive lock on 'mu_'}}
2016 fooF2(&myFoo); // \
2017 // expected-warning {{calling function 'fooF2' requires exclusive lock on 'mu_'}}
2018 fooF3(&myFoo); // \
2019 // expected-warning {{calling function 'fooF3' requires exclusive lock on 'mu_'}}
2020
2021 myFoo.mu_.Lock();
2022 myFoo.foo2();
2023 myFoo.foo3(&myFoo);
2024 myFoo.fooT1(dummy);
2025
2026 // FIXME: uncomment with template instantiation of attributes patch
2027 // myFoo.fooT2(dummy);
2028
2029 fooF1(&myFoo);
2030 fooF2(&myFoo);
2031 fooF3(&myFoo);
2032 myFoo.mu_.Unlock();
2033
2034 FooT<int> myFooT;
2035 myFooT.foo(); // \
2036 // expected-warning {{calling function 'foo' requires exclusive lock on 'mu_'}}
2037}
2038
DeLesley Hutchins4bda3ec2012-02-16 17:03:24 +00002039} // end namespace FunctionDefinitionTest
2040
2041
2042namespace SelfLockingTest {
2043
2044class LOCKABLE MyLock {
2045public:
2046 int foo GUARDED_BY(this);
2047
2048 void lock() EXCLUSIVE_LOCK_FUNCTION();
2049 void unlock() UNLOCK_FUNCTION();
2050
2051 void doSomething() {
2052 this->lock(); // allow 'this' as a lock expression
2053 foo = 0;
2054 doSomethingElse();
2055 this->unlock();
2056 }
2057
2058 void doSomethingElse() EXCLUSIVE_LOCKS_REQUIRED(this) {
2059 foo = 1;
2060 };
2061
2062 void test() {
2063 foo = 2; // \
2064 // expected-warning {{writing variable 'foo' requires locking 'this' exclusively}}
2065 }
DeLesley Hutchinsc24a2332012-02-16 16:50:43 +00002066};
2067
DeLesley Hutchins2f13bec2012-02-16 17:13:43 +00002068
2069class LOCKABLE MyLock2 {
2070public:
2071 Mutex mu_;
2072 int foo GUARDED_BY(this);
2073
2074 // don't check inside lock and unlock functions
2075 void lock() EXCLUSIVE_LOCK_FUNCTION() { mu_.Lock(); }
2076 void unlock() UNLOCK_FUNCTION() { mu_.Unlock(); }
2077
2078 // don't check inside constructors and destructors
2079 MyLock2() { foo = 1; }
2080 ~MyLock2() { foo = 0; }
2081};
2082
2083
DeLesley Hutchins4bda3ec2012-02-16 17:03:24 +00002084} // end namespace SelfLockingTest
2085
2086
DeLesley Hutchinsd08d5992012-02-25 00:11:55 +00002087namespace InvalidNonstatic {
2088
2089// Forward decl here causes bogus "invalid use of non-static data member"
2090// on reference to mutex_ in guarded_by attribute.
2091class Foo;
2092
2093class Foo {
2094 Mutex* mutex_;
2095
2096 int foo __attribute__((guarded_by(mutex_)));
2097};
2098
2099} // end namespace InvalidNonStatic
2100
DeLesley Hutchins2a35be82012-03-02 22:02:58 +00002101
2102namespace NoReturnTest {
2103
2104bool condition();
2105void fatal() __attribute__((noreturn));
2106
2107Mutex mu_;
2108
2109void test1() {
2110 MutexLock lock(&mu_);
2111 if (condition()) {
2112 fatal();
2113 return;
2114 }
2115}
2116
DeLesley Hutchins2287c5e2012-03-02 22:12:59 +00002117} // end namespace NoReturnTest
2118
2119
2120namespace TestMultiDecl {
2121
2122class Foo {
2123public:
2124 int GUARDED_BY(mu_) a;
2125 int GUARDED_BY(mu_) b, c;
2126
2127 void foo() {
2128 a = 0; // \
2129 // expected-warning {{writing variable 'a' requires locking 'mu_' exclusively}}
2130 b = 0; // \
2131 // expected-warning {{writing variable 'b' requires locking 'mu_' exclusively}}
2132 c = 0; // \
2133 // expected-warning {{writing variable 'c' requires locking 'mu_' exclusively}}
2134 }
2135
2136private:
2137 Mutex mu_;
DeLesley Hutchins2a35be82012-03-02 22:02:58 +00002138};
DeLesley Hutchins2287c5e2012-03-02 22:12:59 +00002139
2140} // end namespace TestMultiDecl
2141
DeLesley Hutchins7ec419a2012-03-02 22:29:50 +00002142
2143namespace WarnNoDecl {
2144
2145class Foo {
2146 void foo(int a); __attribute__(( // \
2147 // expected-warning {{declaration does not declare anything}}
2148 exclusive_locks_required(a))); // \
2149 // expected-warning {{attribute exclusive_locks_required ignored}}
2150};
2151
2152} // end namespace WarnNoDecl
2153
2154
DeLesley Hutchins0d95dfc2012-03-02 23:36:05 +00002155
2156namespace MoreLockExpressions {
2157
2158class Foo {
2159public:
2160 Mutex mu_;
2161 int a GUARDED_BY(mu_);
2162};
2163
2164class Bar {
2165public:
2166 int b;
2167 Foo* f;
2168
2169 Foo& getFoo() { return *f; }
2170 Foo& getFoo2(int c) { return *f; }
2171 Foo& getFoo3(int c, int d) { return *f; }
2172
2173 Foo& getFooey() { return *f; }
2174};
2175
2176Foo& getBarFoo(Bar &bar, int c) { return bar.getFoo2(c); }
2177
2178void test() {
2179 Foo foo;
2180 Foo *fooArray;
2181 Bar bar;
2182 int a;
2183 int b;
2184 int c;
2185
2186 bar.getFoo().mu_.Lock();
2187 bar.getFoo().a = 0;
2188 bar.getFoo().mu_.Unlock();
2189
2190 (bar.getFoo().mu_).Lock(); // test parenthesis
2191 bar.getFoo().a = 0;
2192 (bar.getFoo().mu_).Unlock();
2193
2194 bar.getFoo2(a).mu_.Lock();
2195 bar.getFoo2(a).a = 0;
2196 bar.getFoo2(a).mu_.Unlock();
2197
2198 bar.getFoo3(a, b).mu_.Lock();
2199 bar.getFoo3(a, b).a = 0;
2200 bar.getFoo3(a, b).mu_.Unlock();
2201
2202 getBarFoo(bar, a).mu_.Lock();
2203 getBarFoo(bar, a).a = 0;
2204 getBarFoo(bar, a).mu_.Unlock();
2205
2206 bar.getFoo2(10).mu_.Lock();
2207 bar.getFoo2(10).a = 0;
2208 bar.getFoo2(10).mu_.Unlock();
2209
2210 bar.getFoo2(a + 1).mu_.Lock();
2211 bar.getFoo2(a + 1).a = 0;
2212 bar.getFoo2(a + 1).mu_.Unlock();
2213
2214 (a > 0 ? fooArray[1] : fooArray[b]).mu_.Lock();
2215 (a > 0 ? fooArray[1] : fooArray[b]).a = 0;
2216 (a > 0 ? fooArray[1] : fooArray[b]).mu_.Unlock();
2217
2218 bar.getFoo().mu_.Lock();
2219 bar.getFooey().a = 0; // \
2220 // expected-warning {{writing variable 'a' requires locking 'mu_' exclusively}}
2221 bar.getFoo().mu_.Unlock();
2222
2223 bar.getFoo2(a).mu_.Lock();
2224 bar.getFoo2(b).a = 0; // \
2225 // expected-warning {{writing variable 'a' requires locking 'mu_' exclusively}}
2226 bar.getFoo2(a).mu_.Unlock();
2227
2228 bar.getFoo3(a, b).mu_.Lock();
2229 bar.getFoo3(a, c).a = 0; // \
2230 // expected-warning {{writing variable 'a' requires locking 'mu_' exclusively}}
2231 bar.getFoo3(a, b).mu_.Unlock();
2232
2233 getBarFoo(bar, a).mu_.Lock();
2234 getBarFoo(bar, b).a = 0; // \
2235 // expected-warning {{writing variable 'a' requires locking 'mu_' exclusively}}
2236 getBarFoo(bar, a).mu_.Unlock();
2237
2238 (a > 0 ? fooArray[1] : fooArray[b]).mu_.Lock();
2239 (a > 0 ? fooArray[b] : fooArray[c]).a = 0; // \
2240 // expected-warning {{writing variable 'a' requires locking 'mu_' exclusively}}
2241 (a > 0 ? fooArray[1] : fooArray[b]).mu_.Unlock();
2242}
2243
2244
DeLesley Hutchins0da44142012-06-22 17:07:28 +00002245} // end namespace MoreLockExpressions
2246
2247
2248namespace TrylockJoinPoint {
2249
2250class Foo {
2251 Mutex mu;
2252 bool c;
2253
2254 void foo() {
2255 if (c) {
2256 if (!mu.TryLock())
2257 return;
2258 } else {
2259 mu.Lock();
2260 }
2261 mu.Unlock();
2262 }
2263};
2264
2265} // end namespace TrylockJoinPoint
DeLesley Hutchins0d95dfc2012-03-02 23:36:05 +00002266
2267
DeLesley Hutchinsf63797c2012-06-25 18:33:18 +00002268namespace LockReturned {
2269
2270class Foo {
2271public:
2272 int a GUARDED_BY(mu_);
2273 void foo() EXCLUSIVE_LOCKS_REQUIRED(mu_);
2274 void foo2(Foo* f) EXCLUSIVE_LOCKS_REQUIRED(mu_, f->mu_);
2275
2276 static void sfoo(Foo* f) EXCLUSIVE_LOCKS_REQUIRED(f->mu_);
2277
2278 Mutex* getMu() LOCK_RETURNED(mu_);
2279
2280 Mutex mu_;
2281
2282 static Mutex* getMu(Foo* f) LOCK_RETURNED(f->mu_);
2283};
2284
2285
2286// Calls getMu() directly to lock and unlock
2287void test1(Foo* f1, Foo* f2) {
2288 f1->a = 0; // expected-warning {{writing variable 'a' requires locking 'mu_' exclusively}}
2289 f1->foo(); // expected-warning {{calling function 'foo' requires exclusive lock on 'mu_'}}
2290
2291 f1->foo2(f2); // expected-warning 2{{calling function 'foo2' requires exclusive lock on 'mu_'}}
2292 Foo::sfoo(f1); // expected-warning {{calling function 'sfoo' requires exclusive lock on 'mu_'}}
2293
2294 f1->getMu()->Lock();
2295
2296 f1->a = 0;
2297 f1->foo();
2298 f1->foo2(f2); // expected-warning {{calling function 'foo2' requires exclusive lock on 'mu_'}}
2299
2300 Foo::getMu(f2)->Lock();
2301 f1->foo2(f2);
2302 Foo::getMu(f2)->Unlock();
2303
2304 Foo::sfoo(f1);
2305
2306 f1->getMu()->Unlock();
2307}
2308
2309
2310Mutex* getFooMu(Foo* f) LOCK_RETURNED(Foo::getMu(f));
2311
2312class Bar : public Foo {
2313public:
2314 int b GUARDED_BY(getMu());
2315 void bar() EXCLUSIVE_LOCKS_REQUIRED(getMu());
2316 void bar2(Bar* g) EXCLUSIVE_LOCKS_REQUIRED(getMu(this), g->getMu());
2317
2318 static void sbar(Bar* g) EXCLUSIVE_LOCKS_REQUIRED(g->getMu());
2319 static void sbar2(Bar* g) EXCLUSIVE_LOCKS_REQUIRED(getFooMu(g));
2320};
2321
2322
2323
2324// Use getMu() within other attributes.
2325// This requires at lest levels of substitution, more in the case of
2326void test2(Bar* b1, Bar* b2) {
2327 b1->b = 0; // expected-warning {{writing variable 'b' requires locking 'mu_' exclusively}}
2328 b1->bar(); // expected-warning {{calling function 'bar' requires exclusive lock on 'mu_'}}
2329 b1->bar2(b2); // expected-warning 2{{calling function 'bar2' requires exclusive lock on 'mu_'}}
2330 Bar::sbar(b1); // expected-warning {{calling function 'sbar' requires exclusive lock on 'mu_'}}
2331 Bar::sbar2(b1); // expected-warning {{calling function 'sbar2' requires exclusive lock on 'mu_'}}
2332
2333 b1->getMu()->Lock();
2334
2335 b1->b = 0;
2336 b1->bar();
2337 b1->bar2(b2); // expected-warning {{calling function 'bar2' requires exclusive lock on 'mu_'}}
2338
2339 b2->getMu()->Lock();
2340 b1->bar2(b2);
2341
2342 b2->getMu()->Unlock();
2343
2344 Bar::sbar(b1);
2345 Bar::sbar2(b1);
2346
2347 b1->getMu()->Unlock();
2348}
2349
2350
2351// Sanity check -- lock the mutex directly, but use attributes that call getMu()
2352// Also lock the mutex using getFooMu, which calls a lock_returned function.
2353void test3(Bar* b1, Bar* b2) {
2354 b1->mu_.Lock();
2355 b1->b = 0;
2356 b1->bar();
2357
2358 getFooMu(b2)->Lock();
2359 b1->bar2(b2);
2360 getFooMu(b2)->Unlock();
2361
2362 Bar::sbar(b1);
2363 Bar::sbar2(b1);
2364
2365 b1->mu_.Unlock();
2366}
2367
2368} // end namespace LockReturned
2369
2370
DeLesley Hutchinsc99a5d82012-06-28 22:42:48 +00002371namespace ReleasableScopedLock {
2372
2373class Foo {
2374 Mutex mu_;
2375 bool c;
2376 int a GUARDED_BY(mu_);
2377
2378 void test1();
2379 void test2();
2380 void test3();
2381};
2382
2383
2384void Foo::test1() {
2385 ReleasableMutexLock rlock(&mu_);
2386 rlock.Release();
2387}
2388
2389void Foo::test2() {
2390 ReleasableMutexLock rlock(&mu_);
2391 if (c) { // test join point -- held/not held during release
2392 rlock.Release();
2393 }
2394}
2395
2396void Foo::test3() {
2397 ReleasableMutexLock rlock(&mu_);
2398 a = 0;
2399 rlock.Release();
2400 a = 1; // expected-warning {{writing variable 'a' requires locking 'mu_' exclusively}}
2401}
2402
2403} // end namespace ReleasableScopedLock
2404
2405
2406
2407
2408
2409