blob: 4755daa6e30b61194358c1b30b47b4e64175bced [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
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +000052
53Mutex sls_mu;
54
55Mutex sls_mu2 __attribute__((acquired_after(sls_mu)));
56int sls_guard_var __attribute__((guarded_var)) = 0;
57int sls_guardby_var __attribute__((guarded_by(sls_mu))) = 0;
58
59bool getBool();
60
61class MutexWrapper {
62public:
63 Mutex mu;
Caitlin Sadowski194418f2011-09-14 20:00:24 +000064 int x __attribute__((guarded_by(mu)));
65 void MyLock() __attribute__((exclusive_lock_function(mu)));
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +000066};
67
68MutexWrapper sls_mw;
69
70void sls_fun_0() {
71 sls_mw.mu.Lock();
Caitlin Sadowski194418f2011-09-14 20:00:24 +000072 sls_mw.x = 5;
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +000073 sls_mw.mu.Unlock();
74}
75
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +000076void sls_fun_2() {
77 sls_mu.Lock();
78 int x = sls_guard_var;
79 sls_mu.Unlock();
80}
81
82void sls_fun_3() {
83 sls_mu.Lock();
84 sls_guard_var = 2;
85 sls_mu.Unlock();
86}
87
88void sls_fun_4() {
89 sls_mu2.Lock();
90 sls_guard_var = 2;
91 sls_mu2.Unlock();
92}
93
94void sls_fun_5() {
95 sls_mu.Lock();
96 int x = sls_guardby_var;
97 sls_mu.Unlock();
98}
99
100void sls_fun_6() {
101 sls_mu.Lock();
102 sls_guardby_var = 2;
103 sls_mu.Unlock();
104}
105
106void sls_fun_7() {
107 sls_mu.Lock();
108 sls_mu2.Lock();
109 sls_mu2.Unlock();
110 sls_mu.Unlock();
111}
112
113void sls_fun_8() {
114 sls_mu.Lock();
115 if (getBool())
116 sls_mu.Unlock();
117 else
118 sls_mu.Unlock();
119}
120
121void sls_fun_9() {
122 if (getBool())
123 sls_mu.Lock();
124 else
125 sls_mu.Lock();
126 sls_mu.Unlock();
127}
128
129void sls_fun_good_6() {
130 if (getBool()) {
131 sls_mu.Lock();
132 } else {
133 if (getBool()) {
134 getBool(); // EMPTY
135 } else {
136 getBool(); // EMPTY
137 }
138 sls_mu.Lock();
139 }
140 sls_mu.Unlock();
141}
142
143void sls_fun_good_7() {
144 sls_mu.Lock();
145 while (getBool()) {
146 sls_mu.Unlock();
147 if (getBool()) {
148 if (getBool()) {
149 sls_mu.Lock();
150 continue;
151 }
152 }
153 sls_mu.Lock();
154 }
155 sls_mu.Unlock();
156}
157
Caitlin Sadowski194418f2011-09-14 20:00:24 +0000158void sls_fun_good_8() {
159 sls_mw.MyLock();
160 sls_mw.mu.Unlock();
161}
162
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000163void sls_fun_bad_1() {
164 sls_mu.Unlock(); // \
Caitlin Sadowski8bccabe2011-09-08 21:52:50 +0000165 // expected-warning{{unlocking 'sls_mu' that was not locked}}
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000166}
167
168void sls_fun_bad_2() {
169 sls_mu.Lock();
170 sls_mu.Lock(); // \
Caitlin Sadowski8bccabe2011-09-08 21:52:50 +0000171 // expected-warning{{locking 'sls_mu' that is already locked}}
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000172 sls_mu.Unlock();
173}
174
175void sls_fun_bad_3() {
Richard Smith2e515622012-02-03 04:45:26 +0000176 sls_mu.Lock(); // expected-note {{mutex acquired here}}
177} // expected-warning{{mutex 'sls_mu' is still locked at the end of function}}
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000178
179void sls_fun_bad_4() {
180 if (getBool())
DeLesley Hutchins0da44142012-06-22 17:07:28 +0000181 sls_mu.Lock(); // expected-note{{mutex acquired here}}
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000182 else
DeLesley Hutchins0da44142012-06-22 17:07:28 +0000183 sls_mu2.Lock(); // expected-note{{mutex acquired here}}
184} // expected-warning{{mutex 'sls_mu' is not locked on every path through here}} \
185 // expected-warning{{mutex 'sls_mu2' is not locked on every path through here}}
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000186
187void sls_fun_bad_5() {
Richard Smith2e515622012-02-03 04:45:26 +0000188 sls_mu.Lock(); // expected-note {{mutex acquired here}}
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000189 if (getBool())
190 sls_mu.Unlock();
Richard Smith2e515622012-02-03 04:45:26 +0000191} // expected-warning{{mutex 'sls_mu' is not locked on every path through here}}
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000192
193void sls_fun_bad_6() {
194 if (getBool()) {
Richard Smith2e515622012-02-03 04:45:26 +0000195 sls_mu.Lock(); // expected-note {{mutex acquired here}}
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000196 } else {
197 if (getBool()) {
198 getBool(); // EMPTY
199 } else {
200 getBool(); // EMPTY
201 }
202 }
203 sls_mu.Unlock(); // \
Richard Smith2e515622012-02-03 04:45:26 +0000204 expected-warning{{mutex 'sls_mu' is not locked on every path through here}}\
205 expected-warning{{unlocking 'sls_mu' that was not locked}}
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000206}
207
208void sls_fun_bad_7() {
Richard Smithaacde712012-02-03 03:30:07 +0000209 sls_mu.Lock();
Caitlin Sadowski4e4bc752011-09-15 17:25:19 +0000210 while (getBool()) {
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000211 sls_mu.Unlock();
212 if (getBool()) {
213 if (getBool()) {
Richard Smith2e515622012-02-03 04:45:26 +0000214 continue; // \
215 expected-warning{{expecting mutex 'sls_mu' to be locked at start of each loop}}
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000216 }
217 }
Richard Smith2e515622012-02-03 04:45:26 +0000218 sls_mu.Lock(); // expected-note {{mutex acquired here}}
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000219 }
220 sls_mu.Unlock();
221}
222
223void sls_fun_bad_8() {
Richard Smith2e515622012-02-03 04:45:26 +0000224 sls_mu.Lock(); // expected-note{{mutex acquired here}}
225
DeLesley Hutchins0da44142012-06-22 17:07:28 +0000226 do {
227 sls_mu.Unlock(); // expected-warning{{expecting mutex 'sls_mu' to be locked at start of each loop}}
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000228 } while (getBool());
229}
230
231void sls_fun_bad_9() {
232 do {
DeLesley Hutchins0da44142012-06-22 17:07:28 +0000233 sls_mu.Lock(); // \
Richard Smith2e515622012-02-03 04:45:26 +0000234 // expected-warning{{expecting mutex 'sls_mu' to be locked at start of each loop}} \
235 // expected-note{{mutex acquired here}}
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000236 } while (getBool());
237 sls_mu.Unlock();
238}
239
240void sls_fun_bad_10() {
DeLesley Hutchins0da44142012-06-22 17:07:28 +0000241 sls_mu.Lock(); // expected-note 2{{mutex acquired here}}
242 while(getBool()) { // expected-warning{{expecting mutex 'sls_mu' to be locked at start of each loop}}
243 sls_mu.Unlock();
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000244 }
Richard Smith2e515622012-02-03 04:45:26 +0000245} // expected-warning{{mutex 'sls_mu' is still locked at the end of function}}
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000246
247void sls_fun_bad_11() {
Richard Smith2e515622012-02-03 04:45:26 +0000248 while (getBool()) { // \
DeLesley Hutchins0da44142012-06-22 17:07:28 +0000249 expected-warning{{expecting mutex 'sls_mu' to be locked at start of each loop}}
Richard Smith2e515622012-02-03 04:45:26 +0000250 sls_mu.Lock(); // expected-note {{mutex acquired here}}
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000251 }
252 sls_mu.Unlock(); // \
Caitlin Sadowski8bccabe2011-09-08 21:52:50 +0000253 // expected-warning{{unlocking 'sls_mu' that was not locked}}
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000254}
255
Richard Smithaacde712012-02-03 03:30:07 +0000256void sls_fun_bad_12() {
Richard Smith2e515622012-02-03 04:45:26 +0000257 sls_mu.Lock(); // expected-note {{mutex acquired here}}
Richard Smithaacde712012-02-03 03:30:07 +0000258 while (getBool()) {
259 sls_mu.Unlock();
260 if (getBool()) {
261 if (getBool()) {
Richard Smith2e515622012-02-03 04:45:26 +0000262 break; // expected-warning{{mutex 'sls_mu' is not locked on every path through here}}
Richard Smithaacde712012-02-03 03:30:07 +0000263 }
264 }
265 sls_mu.Lock();
266 }
267 sls_mu.Unlock();
268}
269
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000270//-----------------------------------------//
271// Handling lock expressions in attribute args
272// -------------------------------------------//
273
274Mutex aa_mu;
275
276class GlobalLocker {
277public:
278 void globalLock() __attribute__((exclusive_lock_function(aa_mu)));
279 void globalUnlock() __attribute__((unlock_function(aa_mu)));
280};
281
282GlobalLocker glock;
283
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000284void aa_fun_1() {
285 glock.globalLock();
286 glock.globalUnlock();
287}
288
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000289void aa_fun_bad_1() {
290 glock.globalUnlock(); // \
Caitlin Sadowski8bccabe2011-09-08 21:52:50 +0000291 // expected-warning{{unlocking 'aa_mu' that was not locked}}
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000292}
293
294void aa_fun_bad_2() {
295 glock.globalLock();
296 glock.globalLock(); // \
Caitlin Sadowski8bccabe2011-09-08 21:52:50 +0000297 // expected-warning{{locking 'aa_mu' that is already locked}}
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000298 glock.globalUnlock();
299}
300
301void aa_fun_bad_3() {
Richard Smith2e515622012-02-03 04:45:26 +0000302 glock.globalLock(); // expected-note{{mutex acquired here}}
303} // expected-warning{{mutex 'aa_mu' is still locked at the end of function}}
Caitlin Sadowskib4d0a962011-08-29 17:12:27 +0000304
Caitlin Sadowskib4d0a962011-08-29 17:12:27 +0000305//--------------------------------------------------//
306// Regression tests for unusual method names
307//--------------------------------------------------//
308
309Mutex wmu;
310
311// Test diagnostics for other method names.
312class WeirdMethods {
DeLesley Hutchins2f13bec2012-02-16 17:13:43 +0000313 // FIXME: can't currently check inside constructors and destructors.
Caitlin Sadowskib4d0a962011-08-29 17:12:27 +0000314 WeirdMethods() {
DeLesley Hutchins2f13bec2012-02-16 17:13:43 +0000315 wmu.Lock(); // EXPECTED-NOTE {{mutex acquired here}}
316 } // EXPECTED-WARNING {{mutex 'wmu' is still locked at the end of function}}
Caitlin Sadowskib4d0a962011-08-29 17:12:27 +0000317 ~WeirdMethods() {
DeLesley Hutchins2f13bec2012-02-16 17:13:43 +0000318 wmu.Lock(); // EXPECTED-NOTE {{mutex acquired here}}
319 } // EXPECTED-WARNING {{mutex 'wmu' is still locked at the end of function}}
Caitlin Sadowskib4d0a962011-08-29 17:12:27 +0000320 void operator++() {
Richard Smith2e515622012-02-03 04:45:26 +0000321 wmu.Lock(); // expected-note {{mutex acquired here}}
322 } // expected-warning {{mutex 'wmu' is still locked at the end of function}}
Caitlin Sadowskib4d0a962011-08-29 17:12:27 +0000323 operator int*() {
Richard Smith2e515622012-02-03 04:45:26 +0000324 wmu.Lock(); // expected-note {{mutex acquired here}}
Caitlin Sadowskib4d0a962011-08-29 17:12:27 +0000325 return 0;
Richard Smith2e515622012-02-03 04:45:26 +0000326 } // expected-warning {{mutex 'wmu' is still locked at the end of function}}
Caitlin Sadowskib4d0a962011-08-29 17:12:27 +0000327};
328
Caitlin Sadowski05b436e2011-08-29 22:27:51 +0000329//-----------------------------------------------//
330// Errors for guarded by or guarded var variables
331// ----------------------------------------------//
332
333int *pgb_gvar __attribute__((pt_guarded_var));
334int *pgb_var __attribute__((pt_guarded_by(sls_mu)));
335
336class PGBFoo {
337 public:
338 int x;
339 int *pgb_field __attribute__((guarded_by(sls_mu2)))
340 __attribute__((pt_guarded_by(sls_mu)));
341 void testFoo() {
342 pgb_field = &x; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000343 // expected-warning {{writing variable 'pgb_field' requires locking 'sls_mu2' exclusively}}
344 *pgb_field = x; // expected-warning {{reading variable 'pgb_field' requires locking 'sls_mu2'}} \
345 // expected-warning {{writing the value pointed to by 'pgb_field' requires locking 'sls_mu' exclusively}}
346 x = *pgb_field; // expected-warning {{reading variable 'pgb_field' requires locking 'sls_mu2'}} \
347 // expected-warning {{reading the value pointed to by 'pgb_field' requires locking 'sls_mu'}}
348 (*pgb_field)++; // expected-warning {{reading variable 'pgb_field' requires locking 'sls_mu2'}} \
349 // expected-warning {{writing the value pointed to by 'pgb_field' requires locking 'sls_mu' exclusively}}
Caitlin Sadowski05b436e2011-08-29 22:27:51 +0000350 }
351};
352
353class GBFoo {
354 public:
355 int gb_field __attribute__((guarded_by(sls_mu)));
356
357 void testFoo() {
358 gb_field = 0; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000359 // expected-warning {{writing variable 'gb_field' requires locking 'sls_mu' exclusively}}
Caitlin Sadowski05b436e2011-08-29 22:27:51 +0000360 }
Caitlin Sadowskiaf370612011-09-08 18:35:21 +0000361
362 void testNoAnal() __attribute__((no_thread_safety_analysis)) {
363 gb_field = 0;
364 }
Caitlin Sadowski05b436e2011-08-29 22:27:51 +0000365};
366
367GBFoo GlobalGBFoo __attribute__((guarded_by(sls_mu)));
368
369void gb_fun_0() {
370 sls_mu.Lock();
371 int x = *pgb_var;
372 sls_mu.Unlock();
373}
374
375void gb_fun_1() {
376 sls_mu.Lock();
377 *pgb_var = 2;
378 sls_mu.Unlock();
379}
380
381void gb_fun_2() {
382 int x;
383 pgb_var = &x;
384}
385
386void gb_fun_3() {
387 int *x = pgb_var;
388}
389
390void gb_bad_0() {
391 sls_guard_var = 1; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000392 // expected-warning{{writing variable 'sls_guard_var' requires locking any mutex exclusively}}
Caitlin Sadowski05b436e2011-08-29 22:27:51 +0000393}
394
395void gb_bad_1() {
396 int x = sls_guard_var; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000397 // expected-warning{{reading variable 'sls_guard_var' requires locking any mutex}}
Caitlin Sadowski05b436e2011-08-29 22:27:51 +0000398}
399
400void gb_bad_2() {
401 sls_guardby_var = 1; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000402 // expected-warning {{writing variable 'sls_guardby_var' requires locking 'sls_mu' exclusively}}
Caitlin Sadowski05b436e2011-08-29 22:27:51 +0000403}
404
405void gb_bad_3() {
406 int x = sls_guardby_var; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000407 // expected-warning {{reading variable 'sls_guardby_var' requires locking 'sls_mu'}}
Caitlin Sadowski05b436e2011-08-29 22:27:51 +0000408}
409
410void gb_bad_4() {
411 *pgb_gvar = 1; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000412 // expected-warning {{writing the value pointed to by 'pgb_gvar' requires locking any mutex exclusively}}
Caitlin Sadowski05b436e2011-08-29 22:27:51 +0000413}
414
415void gb_bad_5() {
416 int x = *pgb_gvar; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000417 // expected-warning {{reading the value pointed to by 'pgb_gvar' requires locking any mutex}}
Caitlin Sadowski05b436e2011-08-29 22:27:51 +0000418}
419
420void gb_bad_6() {
421 *pgb_var = 1; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000422 // expected-warning {{writing the value pointed to by 'pgb_var' requires locking 'sls_mu' exclusively}}
Caitlin Sadowski05b436e2011-08-29 22:27:51 +0000423}
424
425void gb_bad_7() {
426 int x = *pgb_var; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000427 // expected-warning {{reading the value pointed to by 'pgb_var' requires locking 'sls_mu'}}
Caitlin Sadowski05b436e2011-08-29 22:27:51 +0000428}
429
430void gb_bad_8() {
431 GBFoo G;
432 G.gb_field = 0; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000433 // expected-warning {{writing variable 'gb_field' requires locking 'sls_mu'}}
Caitlin Sadowski05b436e2011-08-29 22:27:51 +0000434}
435
436void gb_bad_9() {
437 sls_guard_var++; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000438 // expected-warning{{writing variable 'sls_guard_var' requires locking any mutex exclusively}}
Caitlin Sadowski05b436e2011-08-29 22:27:51 +0000439 sls_guard_var--; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000440 // expected-warning{{writing variable 'sls_guard_var' requires locking any mutex exclusively}}
Caitlin Sadowski05b436e2011-08-29 22:27:51 +0000441 ++sls_guard_var; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000442 // expected-warning{{writing variable 'sls_guard_var' requires locking any mutex exclusively}}
Caitlin Sadowskia49d1d82011-09-09 16:07:55 +0000443 --sls_guard_var;// \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000444 // expected-warning{{writing variable 'sls_guard_var' requires locking any mutex exclusively}}
Caitlin Sadowski05b436e2011-08-29 22:27:51 +0000445}
Caitlin Sadowskib4d0a962011-08-29 17:12:27 +0000446
Caitlin Sadowskieff98fc2011-09-08 17:42:22 +0000447//-----------------------------------------------//
448// Warnings on variables with late parsed attributes
449// ----------------------------------------------//
450
451class LateFoo {
452public:
453 int a __attribute__((guarded_by(mu)));
454 int b;
455
456 void foo() __attribute__((exclusive_locks_required(mu))) { }
457
458 void test() {
459 a = 0; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000460 // expected-warning{{writing variable 'a' requires locking 'mu' exclusively}}
Caitlin Sadowskieff98fc2011-09-08 17:42:22 +0000461 b = a; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000462 // expected-warning {{reading variable 'a' requires locking 'mu'}}
Caitlin Sadowskieff98fc2011-09-08 17:42:22 +0000463 c = 0; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000464 // expected-warning {{writing variable 'c' requires locking 'mu' exclusively}}
Caitlin Sadowskieff98fc2011-09-08 17:42:22 +0000465 }
466
467 int c __attribute__((guarded_by(mu)));
468
469 Mutex mu;
470};
471
Caitlin Sadowski99107eb2011-09-09 16:21:55 +0000472class LateBar {
473 public:
474 int a_ __attribute__((guarded_by(mu1_)));
475 int b_;
476 int *q __attribute__((pt_guarded_by(mu)));
477 Mutex mu1_;
478 Mutex mu;
479 LateFoo Foo;
480 LateFoo Foo2;
481 LateFoo *FooPointer;
482};
483
484LateBar b1, *b3;
485
486void late_0() {
487 LateFoo FooA;
488 LateFoo FooB;
489 FooA.mu.Lock();
490 FooA.a = 5;
491 FooA.mu.Unlock();
492}
493
494void late_1() {
495 LateBar BarA;
496 BarA.FooPointer->mu.Lock();
497 BarA.FooPointer->a = 2;
498 BarA.FooPointer->mu.Unlock();
499}
500
501void late_bad_0() {
502 LateFoo fooA;
503 LateFoo fooB;
504 fooA.mu.Lock();
505 fooB.a = 5; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000506 // expected-warning{{writing variable 'a' requires locking 'mu' exclusively}}
Caitlin Sadowski99107eb2011-09-09 16:21:55 +0000507 fooA.mu.Unlock();
508}
509
510void late_bad_1() {
511 Mutex mu;
512 mu.Lock();
513 b1.mu1_.Lock();
514 int res = b1.a_ + b3->b_;
515 b3->b_ = *b1.q; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000516 // expected-warning{{reading the value pointed to by 'q' requires locking 'mu'}}
Caitlin Sadowski99107eb2011-09-09 16:21:55 +0000517 b1.mu1_.Unlock();
518 b1.b_ = res;
519 mu.Unlock();
520}
521
522void late_bad_2() {
523 LateBar BarA;
524 BarA.FooPointer->mu.Lock();
525 BarA.Foo.a = 2; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000526 // expected-warning{{writing variable 'a' requires locking 'mu' exclusively}}
Caitlin Sadowski99107eb2011-09-09 16:21:55 +0000527 BarA.FooPointer->mu.Unlock();
528}
529
530void late_bad_3() {
531 LateBar BarA;
532 BarA.Foo.mu.Lock();
533 BarA.FooPointer->a = 2; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000534 // expected-warning{{writing variable 'a' requires locking 'mu' exclusively}}
Caitlin Sadowski99107eb2011-09-09 16:21:55 +0000535 BarA.Foo.mu.Unlock();
536}
537
538void late_bad_4() {
539 LateBar BarA;
540 BarA.Foo.mu.Lock();
541 BarA.Foo2.a = 2; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000542 // expected-warning{{writing variable 'a' requires locking 'mu' exclusively}}
Caitlin Sadowski99107eb2011-09-09 16:21:55 +0000543 BarA.Foo.mu.Unlock();
544}
545
Caitlin Sadowskia53257c2011-09-08 18:19:38 +0000546//-----------------------------------------------//
547// Extra warnings for shared vs. exclusive locks
548// ----------------------------------------------//
549
550void shared_fun_0() {
551 sls_mu.Lock();
552 do {
553 sls_mu.Unlock();
554 sls_mu.Lock();
555 } while (getBool());
556 sls_mu.Unlock();
557}
558
559void shared_fun_1() {
Caitlin Sadowski4e4bc752011-09-15 17:25:19 +0000560 sls_mu.ReaderLock(); // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000561 // expected-warning {{mutex 'sls_mu' is locked exclusively and shared in the same scope}}
Caitlin Sadowskia53257c2011-09-08 18:19:38 +0000562 do {
563 sls_mu.Unlock();
Caitlin Sadowski4e4bc752011-09-15 17:25:19 +0000564 sls_mu.Lock(); // \
565 // expected-note {{the other lock of mutex 'sls_mu' is here}}
Caitlin Sadowskia53257c2011-09-08 18:19:38 +0000566 } while (getBool());
567 sls_mu.Unlock();
568}
569
570void shared_fun_3() {
571 if (getBool())
572 sls_mu.Lock();
573 else
574 sls_mu.Lock();
575 *pgb_var = 1;
576 sls_mu.Unlock();
577}
578
579void shared_fun_4() {
580 if (getBool())
581 sls_mu.ReaderLock();
582 else
583 sls_mu.ReaderLock();
584 int x = sls_guardby_var;
585 sls_mu.Unlock();
586}
587
588void shared_fun_8() {
589 if (getBool())
590 sls_mu.Lock(); // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000591 // expected-warning {{mutex 'sls_mu' is locked exclusively and shared in the same scope}}
Caitlin Sadowskia53257c2011-09-08 18:19:38 +0000592 else
593 sls_mu.ReaderLock(); // \
Caitlin Sadowski8bccabe2011-09-08 21:52:50 +0000594 // expected-note {{the other lock of mutex 'sls_mu' is here}}
Caitlin Sadowskia53257c2011-09-08 18:19:38 +0000595 sls_mu.Unlock();
596}
597
598void shared_bad_0() {
Caitlin Sadowski4e4bc752011-09-15 17:25:19 +0000599 sls_mu.Lock(); // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000600 // expected-warning {{mutex 'sls_mu' is locked exclusively and shared in the same scope}}
Caitlin Sadowskia53257c2011-09-08 18:19:38 +0000601 do {
602 sls_mu.Unlock();
Caitlin Sadowski4e4bc752011-09-15 17:25:19 +0000603 sls_mu.ReaderLock(); // \
604 // expected-note {{the other lock of mutex 'sls_mu' is here}}
Caitlin Sadowskia53257c2011-09-08 18:19:38 +0000605 } while (getBool());
606 sls_mu.Unlock();
607}
608
609void shared_bad_1() {
610 if (getBool())
611 sls_mu.Lock(); // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000612 // expected-warning {{mutex 'sls_mu' is locked exclusively and shared in the same scope}}
Caitlin Sadowskia53257c2011-09-08 18:19:38 +0000613 else
614 sls_mu.ReaderLock(); // \
Caitlin Sadowski8bccabe2011-09-08 21:52:50 +0000615 // expected-note {{the other lock of mutex 'sls_mu' is here}}
Caitlin Sadowskia53257c2011-09-08 18:19:38 +0000616 *pgb_var = 1;
617 sls_mu.Unlock();
618}
619
620void shared_bad_2() {
621 if (getBool())
622 sls_mu.ReaderLock(); // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000623 // expected-warning {{mutex 'sls_mu' is locked exclusively and shared in the same scope}}
Caitlin Sadowskia53257c2011-09-08 18:19:38 +0000624 else
625 sls_mu.Lock(); // \
Caitlin Sadowski8bccabe2011-09-08 21:52:50 +0000626 // expected-note {{the other lock of mutex 'sls_mu' is here}}
Caitlin Sadowskia53257c2011-09-08 18:19:38 +0000627 *pgb_var = 1;
628 sls_mu.Unlock();
629}
Caitlin Sadowski978191e2011-09-08 18:27:31 +0000630
631// FIXME: Add support for functions (not only methods)
632class LRBar {
633 public:
634 void aa_elr_fun() __attribute__((exclusive_locks_required(aa_mu)));
635 void aa_elr_fun_s() __attribute__((shared_locks_required(aa_mu)));
636 void le_fun() __attribute__((locks_excluded(sls_mu)));
637};
638
639class LRFoo {
640 public:
641 void test() __attribute__((exclusive_locks_required(sls_mu)));
642 void testShared() __attribute__((shared_locks_required(sls_mu2)));
643};
644
645void elr_fun() __attribute__((exclusive_locks_required(sls_mu)));
646void elr_fun() {}
647
648LRFoo MyLRFoo;
649LRBar Bar;
650
651void es_fun_0() {
652 aa_mu.Lock();
653 Bar.aa_elr_fun();
654 aa_mu.Unlock();
655}
656
657void es_fun_1() {
658 aa_mu.Lock();
659 Bar.aa_elr_fun_s();
660 aa_mu.Unlock();
661}
662
663void es_fun_2() {
664 aa_mu.ReaderLock();
665 Bar.aa_elr_fun_s();
666 aa_mu.Unlock();
667}
668
669void es_fun_3() {
670 sls_mu.Lock();
671 MyLRFoo.test();
672 sls_mu.Unlock();
673}
674
675void es_fun_4() {
676 sls_mu2.Lock();
677 MyLRFoo.testShared();
678 sls_mu2.Unlock();
679}
680
681void es_fun_5() {
682 sls_mu2.ReaderLock();
683 MyLRFoo.testShared();
684 sls_mu2.Unlock();
685}
686
687void es_fun_6() {
688 Bar.le_fun();
689}
690
691void es_fun_7() {
692 sls_mu.Lock();
693 elr_fun();
694 sls_mu.Unlock();
695}
696
Caitlin Sadowskiaf370612011-09-08 18:35:21 +0000697void es_fun_8() __attribute__((no_thread_safety_analysis));
698
699void es_fun_8() {
700 Bar.aa_elr_fun_s();
701}
702
Caitlin Sadowskicb967512011-09-15 17:43:08 +0000703void es_fun_9() __attribute__((shared_locks_required(aa_mu)));
704void es_fun_9() {
705 Bar.aa_elr_fun_s();
706}
707
708void es_fun_10() __attribute__((exclusive_locks_required(aa_mu)));
709void es_fun_10() {
710 Bar.aa_elr_fun_s();
711}
712
Caitlin Sadowski978191e2011-09-08 18:27:31 +0000713void es_bad_0() {
714 Bar.aa_elr_fun(); // \
Caitlin Sadowski8bccabe2011-09-08 21:52:50 +0000715 // expected-warning {{calling function 'aa_elr_fun' requires exclusive lock on 'aa_mu'}}
Caitlin Sadowski978191e2011-09-08 18:27:31 +0000716}
717
718void es_bad_1() {
719 aa_mu.ReaderLock();
720 Bar.aa_elr_fun(); // \
Caitlin Sadowski8bccabe2011-09-08 21:52:50 +0000721 // expected-warning {{calling function 'aa_elr_fun' requires exclusive lock on 'aa_mu'}}
Caitlin Sadowski978191e2011-09-08 18:27:31 +0000722 aa_mu.Unlock();
723}
724
725void es_bad_2() {
726 Bar.aa_elr_fun_s(); // \
Caitlin Sadowski8bccabe2011-09-08 21:52:50 +0000727 // expected-warning {{calling function 'aa_elr_fun_s' requires shared lock on 'aa_mu'}}
Caitlin Sadowski978191e2011-09-08 18:27:31 +0000728}
729
730void es_bad_3() {
731 MyLRFoo.test(); // \
Caitlin Sadowski8bccabe2011-09-08 21:52:50 +0000732 // expected-warning {{calling function 'test' requires exclusive lock on 'sls_mu'}}
Caitlin Sadowski978191e2011-09-08 18:27:31 +0000733}
734
735void es_bad_4() {
736 MyLRFoo.testShared(); // \
Caitlin Sadowski8bccabe2011-09-08 21:52:50 +0000737 // expected-warning {{calling function 'testShared' requires shared lock on 'sls_mu2'}}
Caitlin Sadowski978191e2011-09-08 18:27:31 +0000738}
739
740void es_bad_5() {
741 sls_mu.ReaderLock();
742 MyLRFoo.test(); // \
Caitlin Sadowski8bccabe2011-09-08 21:52:50 +0000743 // expected-warning {{calling function 'test' requires exclusive lock on 'sls_mu'}}
Caitlin Sadowski978191e2011-09-08 18:27:31 +0000744 sls_mu.Unlock();
745}
746
747void es_bad_6() {
748 sls_mu.Lock();
749 Bar.le_fun(); // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000750 // expected-warning {{cannot call function 'le_fun' while mutex 'sls_mu' is locked}}
Caitlin Sadowski978191e2011-09-08 18:27:31 +0000751 sls_mu.Unlock();
752}
753
754void es_bad_7() {
755 sls_mu.ReaderLock();
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}
Caitlin Sadowski194418f2011-09-14 20:00:24 +0000760
DeLesley Hutchins81216392011-10-17 21:38:02 +0000761
Caitlin Sadowski194418f2011-09-14 20:00:24 +0000762//-----------------------------------------------//
763// Unparseable lock expressions
764// ----------------------------------------------//
765
DeLesley Hutchins0d95dfc2012-03-02 23:36:05 +0000766// FIXME -- derive new tests for unhandled expressions
Caitlin Sadowski194418f2011-09-14 20:00:24 +0000767
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +0000768
769//----------------------------------------------------------------------------//
770// The following test cases are ported from the gcc thread safety implementation
771// They are each wrapped inside a namespace with the test number of the gcc test
772//
773// FIXME: add all the gcc tests, once this analysis passes them.
774//----------------------------------------------------------------------------//
775
776//-----------------------------------------//
777// Good testcases (no errors)
778//-----------------------------------------//
779
780namespace thread_annot_lock_20 {
781class Bar {
782 public:
783 static int func1() EXCLUSIVE_LOCKS_REQUIRED(mu1_);
784 static int b_ GUARDED_BY(mu1_);
785 static Mutex mu1_;
786 static int a_ GUARDED_BY(mu1_);
787};
788
789Bar b1;
790
791int Bar::func1()
792{
793 int res = 5;
794
795 if (a_ == 4)
796 res = b_;
797 return res;
798}
799} // end namespace thread_annot_lock_20
800
801namespace thread_annot_lock_22 {
802// Test various usage of GUARDED_BY and PT_GUARDED_BY annotations, especially
803// uses in class definitions.
804Mutex mu;
805
806class Bar {
807 public:
808 int a_ GUARDED_BY(mu1_);
809 int b_;
810 int *q PT_GUARDED_BY(mu);
811 Mutex mu1_ ACQUIRED_AFTER(mu);
812};
813
814Bar b1, *b3;
815int *p GUARDED_BY(mu) PT_GUARDED_BY(mu);
816int res GUARDED_BY(mu) = 5;
817
818int func(int i)
819{
820 int x;
821 mu.Lock();
822 b1.mu1_.Lock();
823 res = b1.a_ + b3->b_;
824 *p = i;
825 b1.a_ = res + b3->b_;
826 b3->b_ = *b1.q;
827 b1.mu1_.Unlock();
828 b1.b_ = res;
829 x = res;
830 mu.Unlock();
831 return x;
832}
833} // end namespace thread_annot_lock_22
834
835namespace thread_annot_lock_27_modified {
836// test lock annotations applied to function definitions
837// Modified: applied annotations only to function declarations
838Mutex mu1;
839Mutex mu2 ACQUIRED_AFTER(mu1);
840
841class Foo {
842 public:
843 int method1(int i) SHARED_LOCKS_REQUIRED(mu2) EXCLUSIVE_LOCKS_REQUIRED(mu1);
844};
845
846int Foo::method1(int i) {
847 return i;
848}
849
850
851int foo(int i) EXCLUSIVE_LOCKS_REQUIRED(mu2) SHARED_LOCKS_REQUIRED(mu1);
852int foo(int i) {
853 return i;
854}
855
856static int bar(int i) EXCLUSIVE_LOCKS_REQUIRED(mu1);
857static int bar(int i) {
858 return i;
859}
860
861void main() {
862 Foo a;
863
864 mu1.Lock();
865 mu2.Lock();
866 a.method1(1);
867 foo(2);
868 mu2.Unlock();
869 bar(3);
870 mu1.Unlock();
871}
872} // end namespace thread_annot_lock_27_modified
873
874
875namespace thread_annot_lock_38 {
876// Test the case where a template member function is annotated with lock
877// attributes in a non-template class.
878class Foo {
879 public:
880 void func1(int y) LOCKS_EXCLUDED(mu_);
881 template <typename T> void func2(T x) LOCKS_EXCLUDED(mu_);
882 private:
883 Mutex mu_;
884};
885
886Foo *foo;
887
888void main()
889{
890 foo->func1(5);
891 foo->func2(5);
892}
893} // end namespace thread_annot_lock_38
894
895namespace thread_annot_lock_43 {
896// Tests lock canonicalization
897class Foo {
898 public:
899 Mutex *mu_;
900};
901
902class FooBar {
903 public:
904 Foo *foo_;
905 int GetA() EXCLUSIVE_LOCKS_REQUIRED(foo_->mu_) { return a_; }
906 int a_ GUARDED_BY(foo_->mu_);
907};
908
909FooBar *fb;
910
911void main()
912{
913 int x;
914 fb->foo_->mu_->Lock();
915 x = fb->GetA();
916 fb->foo_->mu_->Unlock();
917}
918} // end namespace thread_annot_lock_43
919
920namespace thread_annot_lock_49 {
921// Test the support for use of lock expression in the annotations
922class Foo {
923 public:
924 Mutex foo_mu_;
925};
926
927class Bar {
928 private:
929 Foo *foo;
930 Mutex bar_mu_ ACQUIRED_AFTER(foo->foo_mu_);
931
932 public:
933 void Test1() {
934 foo->foo_mu_.Lock();
935 bar_mu_.Lock();
936 bar_mu_.Unlock();
937 foo->foo_mu_.Unlock();
938 }
939};
940
941void main() {
942 Bar bar;
943 bar.Test1();
944}
945} // end namespace thread_annot_lock_49
946
947namespace thread_annot_lock_61_modified {
948 // Modified to fix the compiler errors
949 // Test the fix for a bug introduced by the support of pass-by-reference
950 // paramters.
951 struct Foo { Foo &operator<< (bool) {return *this;} };
952 Foo &getFoo();
953 struct Bar { Foo &func () {return getFoo();} };
954 struct Bas { void operator& (Foo &) {} };
955 void mumble()
956 {
957 Bas() & Bar().func() << "" << "";
958 Bas() & Bar().func() << "";
959 }
960} // end namespace thread_annot_lock_61_modified
961
962
963namespace thread_annot_lock_65 {
964// Test the fix for a bug in the support of allowing reader locks for
965// non-const, non-modifying overload functions. (We didn't handle the builtin
966// properly.)
967enum MyFlags {
968 Zero,
969 One,
970 Two,
971 Three,
972 Four,
973 Five,
974 Six,
975 Seven,
976 Eight,
977 Nine
978};
979
980inline MyFlags
981operator|(MyFlags a, MyFlags b)
982{
983 return MyFlags(static_cast<int>(a) | static_cast<int>(b));
984}
985
986inline MyFlags&
987operator|=(MyFlags& a, MyFlags b)
988{
989 return a = a | b;
990}
991} // end namespace thread_annot_lock_65
992
993namespace thread_annot_lock_66_modified {
994// Modified: Moved annotation to function defn
995// Test annotations on out-of-line definitions of member functions where the
996// annotations refer to locks that are also data members in the class.
997Mutex mu;
998
999class Foo {
1000 public:
1001 int method1(int i) SHARED_LOCKS_REQUIRED(mu1, mu, mu2);
1002 int data GUARDED_BY(mu1);
1003 Mutex *mu1;
1004 Mutex *mu2;
1005};
1006
1007int Foo::method1(int i)
1008{
1009 return data + i;
1010}
1011
1012void main()
1013{
1014 Foo a;
1015
1016 a.mu2->Lock();
1017 a.mu1->Lock();
1018 mu.Lock();
1019 a.method1(1);
1020 mu.Unlock();
1021 a.mu1->Unlock();
1022 a.mu2->Unlock();
1023}
1024} // end namespace thread_annot_lock_66_modified
1025
1026namespace thread_annot_lock_68_modified {
1027// Test a fix to a bug in the delayed name binding with nested template
1028// instantiation. We use a stack to make sure a name is not resolved to an
1029// inner context.
1030template <typename T>
1031class Bar {
1032 Mutex mu_;
1033};
1034
1035template <typename T>
1036class Foo {
1037 public:
1038 void func(T x) {
1039 mu_.Lock();
DeLesley Hutchins23323e02012-01-20 22:50:54 +00001040 count_ = x;
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001041 mu_.Unlock();
1042 }
1043
1044 private:
DeLesley Hutchins23323e02012-01-20 22:50:54 +00001045 T count_ GUARDED_BY(mu_);
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001046 Bar<T> bar_;
1047 Mutex mu_;
1048};
1049
1050void main()
1051{
1052 Foo<int> *foo;
1053 foo->func(5);
1054}
1055} // end namespace thread_annot_lock_68_modified
1056
1057namespace thread_annot_lock_30_modified {
1058// Test delay parsing of lock attribute arguments with nested classes.
1059// Modified: trylocks replaced with exclusive_lock_fun
1060int a = 0;
1061
1062class Bar {
1063 struct Foo;
1064
1065 public:
1066 void MyLock() EXCLUSIVE_LOCK_FUNCTION(mu);
1067
1068 int func() {
1069 MyLock();
1070// if (foo == 0) {
1071// return 0;
1072// }
1073 a = 5;
1074 mu.Unlock();
1075 return 1;
1076 }
1077
1078 class FooBar {
1079 int x;
1080 int y;
1081 };
1082
1083 private:
1084 Mutex mu;
1085};
1086
1087Bar *bar;
1088
1089void main()
1090{
1091 bar->func();
1092}
1093} // end namespace thread_annot_lock_30_modified
1094
1095namespace thread_annot_lock_47 {
1096// Test the support for annotations on virtual functions.
1097// This is a good test case. (i.e. There should be no warning emitted by the
1098// compiler.)
1099class Base {
1100 public:
1101 virtual void func1() EXCLUSIVE_LOCKS_REQUIRED(mu_);
1102 virtual void func2() LOCKS_EXCLUDED(mu_);
1103 Mutex mu_;
1104};
1105
1106class Child : public Base {
1107 public:
1108 virtual void func1() EXCLUSIVE_LOCKS_REQUIRED(mu_);
1109 virtual void func2() LOCKS_EXCLUDED(mu_);
1110};
1111
1112void main() {
1113 Child *c;
1114 Base *b = c;
1115
1116 b->mu_.Lock();
1117 b->func1();
1118 b->mu_.Unlock();
1119 b->func2();
1120
1121 c->mu_.Lock();
1122 c->func1();
1123 c->mu_.Unlock();
1124 c->func2();
1125}
1126} // end namespace thread_annot_lock_47
1127
1128//-----------------------------------------//
1129// Tests which produce errors
1130//-----------------------------------------//
1131
1132namespace thread_annot_lock_13 {
1133Mutex mu1;
1134Mutex mu2;
1135
1136int g GUARDED_BY(mu1);
1137int w GUARDED_BY(mu2);
1138
1139class Foo {
1140 public:
1141 void bar() LOCKS_EXCLUDED(mu_, mu1);
1142 int foo() SHARED_LOCKS_REQUIRED(mu_) EXCLUSIVE_LOCKS_REQUIRED(mu2);
1143
1144 private:
1145 int a_ GUARDED_BY(mu_);
1146 public:
1147 Mutex mu_ ACQUIRED_AFTER(mu1);
1148};
1149
1150int Foo::foo()
1151{
1152 int res;
David Blaikiee31b8fb2012-04-05 00:16:44 +00001153 w = 5;
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001154 res = a_ + 5;
1155 return res;
1156}
1157
1158void Foo::bar()
1159{
1160 int x;
1161 mu_.Lock();
1162 x = foo(); // expected-warning {{calling function 'foo' requires exclusive lock on 'mu2'}}
1163 a_ = x + 1;
1164 mu_.Unlock();
1165 if (x > 5) {
1166 mu1.Lock();
David Blaikiee31b8fb2012-04-05 00:16:44 +00001167 g = 2;
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001168 mu1.Unlock();
1169 }
1170}
1171
1172void main()
1173{
1174 Foo f1, *f2;
1175 f1.mu_.Lock();
Caitlin Sadowski74558b42011-09-15 18:13:32 +00001176 f1.bar(); // expected-warning {{cannot call function 'bar' while mutex 'mu_' is locked}}
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001177 mu2.Lock();
1178 f1.foo();
1179 mu2.Unlock();
1180 f1.mu_.Unlock();
1181 f2->mu_.Lock();
Caitlin Sadowski74558b42011-09-15 18:13:32 +00001182 f2->bar(); // expected-warning {{cannot call function 'bar' while mutex 'mu_' is locked}}
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001183 f2->mu_.Unlock();
1184 mu2.Lock();
David Blaikiee31b8fb2012-04-05 00:16:44 +00001185 w = 2;
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001186 mu2.Unlock();
1187}
1188} // end namespace thread_annot_lock_13
1189
1190namespace thread_annot_lock_18_modified {
1191// Modified: Trylocks removed
1192// Test the ability to distnguish between the same lock field of
1193// different objects of a class.
1194 class Bar {
1195 public:
1196 bool MyLock() EXCLUSIVE_LOCK_FUNCTION(mu1_);
1197 void MyUnlock() UNLOCK_FUNCTION(mu1_);
1198 int a_ GUARDED_BY(mu1_);
1199
1200 private:
1201 Mutex mu1_;
1202};
1203
1204Bar *b1, *b2;
1205
1206void func()
1207{
1208 b1->MyLock();
1209 b1->a_ = 5;
Caitlin Sadowski74558b42011-09-15 18:13:32 +00001210 b2->a_ = 3; // expected-warning {{writing variable 'a_' requires locking 'mu1_' exclusively}}
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001211 b2->MyLock();
1212 b2->MyUnlock();
1213 b1->MyUnlock();
1214}
1215} // end namespace thread_annot_lock_18_modified
1216
1217namespace thread_annot_lock_21 {
1218// Test various usage of GUARDED_BY and PT_GUARDED_BY annotations, especially
1219// uses in class definitions.
1220Mutex mu;
1221
1222class Bar {
1223 public:
1224 int a_ GUARDED_BY(mu1_);
1225 int b_;
1226 int *q PT_GUARDED_BY(mu);
1227 Mutex mu1_ ACQUIRED_AFTER(mu);
1228};
1229
1230Bar b1, *b3;
1231int *p GUARDED_BY(mu) PT_GUARDED_BY(mu);
1232
1233int res GUARDED_BY(mu) = 5;
1234
1235int func(int i)
1236{
1237 int x;
1238 b3->mu1_.Lock();
Caitlin Sadowski74558b42011-09-15 18:13:32 +00001239 res = b1.a_ + b3->b_; // expected-warning {{reading variable 'a_' requires locking 'mu1_'}} \
1240 // expected-warning {{writing variable 'res' requires locking 'mu' exclusively}}
1241 *p = i; // expected-warning {{reading variable 'p' requires locking 'mu'}} \
1242 // expected-warning {{writing the value pointed to by 'p' requires locking 'mu' exclusively}}
1243 b1.a_ = res + b3->b_; // expected-warning {{reading variable 'res' requires locking 'mu'}} \
1244 // expected-warning {{writing variable 'a_' requires locking 'mu1_' exclusively}}
1245 b3->b_ = *b1.q; // expected-warning {{reading the value pointed to by 'q' requires locking 'mu'}}
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001246 b3->mu1_.Unlock();
Caitlin Sadowski74558b42011-09-15 18:13:32 +00001247 b1.b_ = res; // expected-warning {{reading variable 'res' requires locking 'mu'}}
1248 x = res; // expected-warning {{reading variable 'res' requires locking 'mu'}}
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001249 return x;
1250}
1251} // end namespace thread_annot_lock_21
1252
1253namespace thread_annot_lock_35_modified {
1254// Test the analyzer's ability to distinguish the lock field of different
1255// objects.
1256class Foo {
1257 private:
1258 Mutex lock_;
1259 int a_ GUARDED_BY(lock_);
1260
1261 public:
1262 void Func(Foo* child) LOCKS_EXCLUDED(lock_) {
1263 Foo *new_foo = new Foo;
1264
1265 lock_.Lock();
1266
1267 child->Func(new_foo); // There shouldn't be any warning here as the
1268 // acquired lock is not in child.
1269 child->bar(7); // expected-warning {{calling function 'bar' requires exclusive lock on 'lock_'}}
Caitlin Sadowski74558b42011-09-15 18:13:32 +00001270 child->a_ = 5; // expected-warning {{writing variable 'a_' requires locking 'lock_' exclusively}}
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001271 lock_.Unlock();
1272 }
1273
1274 void bar(int y) EXCLUSIVE_LOCKS_REQUIRED(lock_) {
1275 a_ = y;
1276 }
1277};
1278
1279Foo *x;
1280
1281void main() {
1282 Foo *child = new Foo;
1283 x->Func(child);
1284}
1285} // end namespace thread_annot_lock_35_modified
1286
1287namespace thread_annot_lock_36_modified {
1288// Modified to move the annotations to function defns.
1289// Test the analyzer's ability to distinguish the lock field of different
1290// objects
1291class Foo {
1292 private:
1293 Mutex lock_;
1294 int a_ GUARDED_BY(lock_);
1295
1296 public:
1297 void Func(Foo* child) LOCKS_EXCLUDED(lock_);
1298 void bar(int y) EXCLUSIVE_LOCKS_REQUIRED(lock_);
1299};
1300
1301void Foo::Func(Foo* child) {
1302 Foo *new_foo = new Foo;
1303
1304 lock_.Lock();
1305
1306 child->lock_.Lock();
Caitlin Sadowski74558b42011-09-15 18:13:32 +00001307 child->Func(new_foo); // expected-warning {{cannot call function 'Func' while mutex 'lock_' is locked}}
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001308 child->bar(7);
1309 child->a_ = 5;
1310 child->lock_.Unlock();
1311
1312 lock_.Unlock();
1313}
1314
1315void Foo::bar(int y) {
1316 a_ = y;
1317}
1318
1319
1320Foo *x;
1321
1322void main() {
1323 Foo *child = new Foo;
1324 x->Func(child);
1325}
1326} // end namespace thread_annot_lock_36_modified
1327
1328
1329namespace thread_annot_lock_42 {
1330// Test support of multiple lock attributes of the same kind on a decl.
1331class Foo {
1332 private:
1333 Mutex mu1, mu2, mu3;
1334 int x GUARDED_BY(mu1) GUARDED_BY(mu2);
1335 int y GUARDED_BY(mu2);
1336
1337 void f2() LOCKS_EXCLUDED(mu1) LOCKS_EXCLUDED(mu2) LOCKS_EXCLUDED(mu3) {
1338 mu2.Lock();
1339 y = 2;
1340 mu2.Unlock();
1341 }
1342
1343 public:
1344 void f1() EXCLUSIVE_LOCKS_REQUIRED(mu2) EXCLUSIVE_LOCKS_REQUIRED(mu1) {
1345 x = 5;
Caitlin Sadowski74558b42011-09-15 18:13:32 +00001346 f2(); // expected-warning {{cannot call function 'f2' while mutex 'mu1' is locked}} \
1347 // expected-warning {{cannot call function 'f2' while mutex 'mu2' is locked}}
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001348 }
1349};
1350
1351Foo *foo;
1352
1353void func()
1354{
1355 foo->f1(); // expected-warning {{calling function 'f1' requires exclusive lock on 'mu2'}} \
1356 // expected-warning {{calling function 'f1' requires exclusive lock on 'mu1'}}
1357}
1358} // end namespace thread_annot_lock_42
1359
1360namespace thread_annot_lock_46 {
1361// Test the support for annotations on virtual functions.
1362class Base {
1363 public:
1364 virtual void func1() EXCLUSIVE_LOCKS_REQUIRED(mu_);
1365 virtual void func2() LOCKS_EXCLUDED(mu_);
1366 Mutex mu_;
1367};
1368
1369class Child : public Base {
1370 public:
1371 virtual void func1() EXCLUSIVE_LOCKS_REQUIRED(mu_);
1372 virtual void func2() LOCKS_EXCLUDED(mu_);
1373};
1374
1375void main() {
1376 Child *c;
1377 Base *b = c;
1378
1379 b->func1(); // expected-warning {{calling function 'func1' requires exclusive lock on 'mu_'}}
1380 b->mu_.Lock();
Caitlin Sadowski74558b42011-09-15 18:13:32 +00001381 b->func2(); // expected-warning {{cannot call function 'func2' while mutex 'mu_' is locked}}
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001382 b->mu_.Unlock();
1383
1384 c->func1(); // expected-warning {{calling function 'func1' requires exclusive lock on 'mu_'}}
1385 c->mu_.Lock();
Caitlin Sadowski74558b42011-09-15 18:13:32 +00001386 c->func2(); // expected-warning {{cannot call function 'func2' while mutex 'mu_' is locked}}
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001387 c->mu_.Unlock();
1388}
1389} // end namespace thread_annot_lock_46
1390
1391namespace thread_annot_lock_67_modified {
1392// Modified: attributes on definitions moved to declarations
1393// Test annotations on out-of-line definitions of member functions where the
1394// annotations refer to locks that are also data members in the class.
1395Mutex mu;
1396Mutex mu3;
1397
1398class Foo {
1399 public:
1400 int method1(int i) SHARED_LOCKS_REQUIRED(mu1, mu, mu2, mu3);
1401 int data GUARDED_BY(mu1);
1402 Mutex *mu1;
1403 Mutex *mu2;
1404};
1405
1406int Foo::method1(int i) {
1407 return data + i;
1408}
1409
1410void main()
1411{
1412 Foo a;
1413 a.method1(1); // expected-warning {{calling function 'method1' requires shared lock on 'mu1'}} \
1414 // expected-warning {{calling function 'method1' requires shared lock on 'mu'}} \
1415 // expected-warning {{calling function 'method1' requires shared lock on 'mu2'}} \
1416 // expected-warning {{calling function 'method1' requires shared lock on 'mu3'}}
1417}
1418} // end namespace thread_annot_lock_67_modified
1419
1420
DeLesley Hutchins81216392011-10-17 21:38:02 +00001421namespace substitution_test {
1422 class MyData {
1423 public:
1424 Mutex mu;
1425
1426 void lockData() __attribute__((exclusive_lock_function(mu))) { }
1427 void unlockData() __attribute__((unlock_function(mu))) { }
1428
1429 void doSomething() __attribute__((exclusive_locks_required(mu))) { }
1430 };
1431
1432
1433 class DataLocker {
1434 public:
1435 void lockData (MyData *d) __attribute__((exclusive_lock_function(d->mu))) { }
1436 void unlockData(MyData *d) __attribute__((unlock_function(d->mu))) { }
1437 };
1438
1439
1440 class Foo {
1441 public:
1442 void foo(MyData* d) __attribute__((exclusive_locks_required(d->mu))) { }
1443
1444 void bar1(MyData* d) {
1445 d->lockData();
1446 foo(d);
1447 d->unlockData();
1448 }
1449
1450 void bar2(MyData* d) {
1451 DataLocker dlr;
1452 dlr.lockData(d);
1453 foo(d);
1454 dlr.unlockData(d);
1455 }
1456
1457 void bar3(MyData* d1, MyData* d2) {
1458 DataLocker dlr;
Richard Smith2e515622012-02-03 04:45:26 +00001459 dlr.lockData(d1); // expected-note {{mutex acquired here}}
DeLesley Hutchins81216392011-10-17 21:38:02 +00001460 dlr.unlockData(d2); // \
1461 // expected-warning {{unlocking 'mu' that was not locked}}
Richard Smith2e515622012-02-03 04:45:26 +00001462 } // expected-warning {{mutex 'mu' is still locked at the end of function}}
DeLesley Hutchins81216392011-10-17 21:38:02 +00001463
1464 void bar4(MyData* d1, MyData* d2) {
1465 DataLocker dlr;
1466 dlr.lockData(d1);
1467 foo(d2); // \
1468 // expected-warning {{calling function 'foo' requires exclusive lock on 'mu'}}
1469 dlr.unlockData(d1);
1470 }
1471 };
1472} // end namespace substituation_test
1473
DeLesley Hutchinse0eaa852011-10-21 18:06:53 +00001474
DeLesley Hutchinsf1ac6372011-10-21 18:10:14 +00001475
DeLesley Hutchinse0eaa852011-10-21 18:06:53 +00001476namespace constructor_destructor_tests {
1477 Mutex fooMu;
1478 int myVar GUARDED_BY(fooMu);
1479
1480 class Foo {
1481 public:
1482 Foo() __attribute__((exclusive_lock_function(fooMu))) { }
1483 ~Foo() __attribute__((unlock_function(fooMu))) { }
1484 };
1485
1486 void fooTest() {
DeLesley Hutchins6db51f72011-10-21 20:51:27 +00001487 Foo foo;
DeLesley Hutchinse0eaa852011-10-21 18:06:53 +00001488 myVar = 0;
1489 }
1490}
1491
DeLesley Hutchinsf1ac6372011-10-21 18:10:14 +00001492
1493namespace invalid_lock_expression_test {
1494
1495class LOCKABLE MyLockable {
1496public:
1497 MyLockable() __attribute__((exclusive_lock_function)) { }
DeLesley Hutchins6db51f72011-10-21 20:51:27 +00001498 ~MyLockable() { }
DeLesley Hutchinsf1ac6372011-10-21 18:10:14 +00001499};
1500
1501// create an empty lock expression
1502void foo() {
1503 MyLockable lock; // \
1504 // expected-warning {{cannot resolve lock expression}}
1505}
1506
1507} // end namespace invalid_lock_expression_test
1508
Richard Smith97f9fe02011-10-25 00:41:24 +00001509namespace template_member_test {
DeLesley Hutchinsf1ac6372011-10-21 18:10:14 +00001510
Richard Smith97f9fe02011-10-25 00:41:24 +00001511 struct S { int n; };
1512 struct T {
1513 Mutex m;
1514 S *s GUARDED_BY(this->m);
1515 };
Richard Smitha01c7112011-10-25 06:33:21 +00001516 Mutex m;
1517 struct U {
1518 union {
1519 int n;
1520 };
1521 } *u GUARDED_BY(m);
Richard Smith97f9fe02011-10-25 00:41:24 +00001522
1523 template<typename U>
1524 struct IndirectLock {
1525 int DoNaughtyThings(T *t) {
Richard Smitha01c7112011-10-25 06:33:21 +00001526 u->n = 0; // expected-warning {{reading variable 'u' requires locking 'm'}}
Richard Smith97f9fe02011-10-25 00:41:24 +00001527 return t->s->n; // expected-warning {{reading variable 's' requires locking 'm'}}
1528 }
1529 };
1530
Richard Smithf11e9232011-10-25 01:05:41 +00001531 template struct IndirectLock<int>; // expected-note {{here}}
Richard Smith97f9fe02011-10-25 00:41:24 +00001532
Richard Smith601d2ee2011-10-26 06:15:36 +00001533 struct V {
1534 void f(int);
1535 void f(double);
1536
1537 Mutex m;
1538 V *p GUARDED_BY(this->m);
1539 };
1540 template<typename U> struct W {
1541 V v;
1542 void f(U u) {
1543 v.p->f(u); // expected-warning {{reading variable 'p' requires locking 'm'}}
1544 }
1545 };
1546 template struct W<int>; // expected-note {{here}}
1547
Richard Smith97f9fe02011-10-25 00:41:24 +00001548}
DeLesley Hutchins1fa3c062011-12-08 20:23:06 +00001549
1550namespace test_scoped_lockable {
1551
1552struct TestScopedLockable {
1553 Mutex mu1;
1554 Mutex mu2;
1555 int a __attribute__((guarded_by(mu1)));
1556 int b __attribute__((guarded_by(mu2)));
1557
1558 bool getBool();
1559
1560 void foo1() {
1561 MutexLock mulock(&mu1);
1562 a = 5;
1563 }
1564
1565 void foo2() {
1566 ReaderMutexLock mulock1(&mu1);
1567 if (getBool()) {
1568 MutexLock mulock2a(&mu2);
1569 b = a + 1;
1570 }
1571 else {
1572 MutexLock mulock2b(&mu2);
1573 b = a + 2;
1574 }
1575 }
1576
1577 void foo3() {
1578 MutexLock mulock_a(&mu1);
1579 MutexLock mulock_b(&mu1); // \
1580 // expected-warning {{locking 'mu1' that is already locked}}
1581 } // expected-warning {{unlocking 'mu1' that was not locked}}
1582
1583 void foo4() {
1584 MutexLock mulock1(&mu1), mulock2(&mu2);
1585 a = b+1;
1586 b = a+1;
1587 }
1588};
1589
1590} // end namespace test_scoped_lockable
1591
1592
DeLesley Hutchinsdf497822011-12-29 00:56:48 +00001593namespace FunctionAttrTest {
1594
1595class Foo {
1596public:
1597 Mutex mu_;
1598 int a GUARDED_BY(mu_);
1599};
1600
1601Foo fooObj;
1602
1603void foo() EXCLUSIVE_LOCKS_REQUIRED(fooObj.mu_);
1604
1605void bar() {
1606 foo(); // expected-warning {{calling function 'foo' requires exclusive lock on 'mu_'}}
1607 fooObj.mu_.Lock();
1608 foo();
1609 fooObj.mu_.Unlock();
1610}
1611
1612}; // end namespace FunctionAttrTest
1613
1614
DeLesley Hutchinsb4fa4182012-01-06 19:16:50 +00001615struct TestTryLock {
1616 Mutex mu;
1617 int a GUARDED_BY(mu);
1618 bool cond;
1619
1620 void foo1() {
1621 if (mu.TryLock()) {
1622 a = 1;
1623 mu.Unlock();
1624 }
1625 }
1626
1627 void foo2() {
1628 if (!mu.TryLock()) return;
1629 a = 2;
1630 mu.Unlock();
1631 }
1632
1633 void foo3() {
1634 bool b = mu.TryLock();
1635 if (b) {
1636 a = 3;
1637 mu.Unlock();
1638 }
1639 }
1640
1641 void foo4() {
1642 bool b = mu.TryLock();
1643 if (!b) return;
1644 a = 4;
1645 mu.Unlock();
1646 }
1647
1648 void foo5() {
1649 while (mu.TryLock()) {
1650 a = a + 1;
1651 mu.Unlock();
1652 }
1653 }
1654
1655 void foo6() {
1656 bool b = mu.TryLock();
1657 b = !b;
1658 if (b) return;
1659 a = 6;
1660 mu.Unlock();
1661 }
1662
1663 void foo7() {
1664 bool b1 = mu.TryLock();
1665 bool b2 = !b1;
1666 bool b3 = !b2;
1667 if (b3) {
1668 a = 7;
1669 mu.Unlock();
1670 }
1671 }
1672
1673 // Test use-def chains: join points
1674 void foo8() {
1675 bool b = mu.TryLock();
1676 bool b2 = b;
1677 if (cond)
1678 b = true;
1679 if (b) { // b should be unknown at this point, becuase of the join point
1680 a = 8; // expected-warning {{writing variable 'a' requires locking 'mu' exclusively}}
1681 }
1682 if (b2) { // b2 should be known at this point.
1683 a = 8;
1684 mu.Unlock();
1685 }
1686 }
1687
1688 // Test use-def-chains: back edges
1689 void foo9() {
1690 bool b = mu.TryLock();
1691
1692 for (int i = 0; i < 10; ++i);
1693
1694 if (b) { // b is still known, because the loop doesn't alter it
1695 a = 9;
1696 mu.Unlock();
1697 }
1698 }
1699
1700 // Test use-def chains: back edges
1701 void foo10() {
1702 bool b = mu.TryLock();
1703
1704 while (cond) {
1705 if (b) { // b should be uknown at this point b/c of the loop
1706 a = 10; // expected-warning {{writing variable 'a' requires locking 'mu' exclusively}}
1707 }
1708 b = !b;
1709 }
1710 }
1711}; // end TestTrylock
1712
1713
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +00001714namespace TestTemplateAttributeInstantiation {
1715
1716class Foo1 {
1717public:
1718 Mutex mu_;
1719 int a GUARDED_BY(mu_);
1720};
1721
1722class Foo2 {
1723public:
1724 int a GUARDED_BY(mu_);
1725 Mutex mu_;
1726};
1727
1728
1729class Bar {
1730public:
1731 // Test non-dependent expressions in attributes on template functions
1732 template <class T>
1733 void barND(Foo1 *foo, T *fooT) EXCLUSIVE_LOCKS_REQUIRED(foo->mu_) {
1734 foo->a = 0;
1735 }
1736
1737 // Test dependent expressions in attributes on template functions
1738 template <class T>
1739 void barD(Foo1 *foo, T *fooT) EXCLUSIVE_LOCKS_REQUIRED(fooT->mu_) {
1740 fooT->a = 0;
1741 }
1742};
1743
1744
1745template <class T>
1746class BarT {
1747public:
1748 Foo1 fooBase;
1749 T fooBaseT;
1750
1751 // Test non-dependent expression in ordinary method on template class
1752 void barND() EXCLUSIVE_LOCKS_REQUIRED(fooBase.mu_) {
1753 fooBase.a = 0;
1754 }
1755
1756 // Test dependent expressions in ordinary methods on template class
1757 void barD() EXCLUSIVE_LOCKS_REQUIRED(fooBaseT.mu_) {
1758 fooBaseT.a = 0;
1759 }
1760
1761 // Test dependent expressions in template method in template class
1762 template <class T2>
1763 void barTD(T2 *fooT) EXCLUSIVE_LOCKS_REQUIRED(fooBaseT.mu_, fooT->mu_) {
1764 fooBaseT.a = 0;
1765 fooT->a = 0;
1766 }
1767};
1768
1769template <class T>
1770class Cell {
1771public:
1772 Mutex mu_;
1773 // Test dependent guarded_by
1774 T data GUARDED_BY(mu_);
1775
DeLesley Hutchins23323e02012-01-20 22:50:54 +00001776 void fooEx() EXCLUSIVE_LOCKS_REQUIRED(mu_) {
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +00001777 data = 0;
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +00001778 }
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +00001779
1780 void foo() {
1781 mu_.Lock();
1782 data = 0;
1783 mu_.Unlock();
1784 }
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +00001785};
1786
1787void test() {
1788 Bar b;
1789 BarT<Foo2> bt;
1790 Foo1 f1;
1791 Foo2 f2;
1792
1793 f1.mu_.Lock();
1794 f2.mu_.Lock();
1795 bt.fooBase.mu_.Lock();
1796 bt.fooBaseT.mu_.Lock();
1797
1798 b.barND(&f1, &f2);
1799 b.barD(&f1, &f2);
1800 bt.barND();
1801 bt.barD();
1802 bt.barTD(&f2);
1803
1804 f1.mu_.Unlock();
1805 bt.barTD(&f1); // \
1806 // expected-warning {{calling function 'barTD' requires exclusive lock on 'mu_'}}
1807
1808 bt.fooBase.mu_.Unlock();
1809 bt.fooBaseT.mu_.Unlock();
1810 f2.mu_.Unlock();
1811
1812 Cell<int> cell;
1813 cell.data = 0; // \
1814 // expected-warning {{writing variable 'data' requires locking 'mu_' exclusively}}
1815 cell.foo();
DeLesley Hutchins23323e02012-01-20 22:50:54 +00001816 cell.mu_.Lock();
1817 cell.fooEx();
1818 cell.mu_.Unlock();
1819}
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +00001820
DeLesley Hutchins23323e02012-01-20 22:50:54 +00001821
1822template <class T>
1823class CellDelayed {
1824public:
1825 // Test dependent guarded_by
1826 T data GUARDED_BY(mu_);
DeLesley Hutchinsdd5756c2012-02-16 17:30:51 +00001827 static T static_data GUARDED_BY(static_mu_);
DeLesley Hutchins23323e02012-01-20 22:50:54 +00001828
1829 void fooEx(CellDelayed<T> *other) EXCLUSIVE_LOCKS_REQUIRED(mu_, other->mu_) {
1830 this->data = other->data;
1831 }
1832
1833 template <class T2>
1834 void fooExT(CellDelayed<T2> *otherT) EXCLUSIVE_LOCKS_REQUIRED(mu_, otherT->mu_) {
1835 this->data = otherT->data;
1836 }
1837
1838 void foo() {
1839 mu_.Lock();
1840 data = 0;
1841 mu_.Unlock();
1842 }
1843
1844 Mutex mu_;
DeLesley Hutchinsdd5756c2012-02-16 17:30:51 +00001845 static Mutex static_mu_;
DeLesley Hutchins23323e02012-01-20 22:50:54 +00001846};
1847
1848void testDelayed() {
1849 CellDelayed<int> celld;
1850 CellDelayed<int> celld2;
1851 celld.foo();
1852 celld.mu_.Lock();
1853 celld2.mu_.Lock();
1854
1855 celld.fooEx(&celld2);
1856 celld.fooExT(&celld2);
1857
1858 celld2.mu_.Unlock();
1859 celld.mu_.Unlock();
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +00001860}
1861
1862}; // end namespace TestTemplateAttributeInstantiation
1863
1864
DeLesley Hutchinse03b2b32012-01-20 23:24:41 +00001865namespace FunctionDeclDefTest {
1866
1867class Foo {
1868public:
1869 Mutex mu_;
1870 int a GUARDED_BY(mu_);
1871
1872 virtual void foo1(Foo *f_declared) EXCLUSIVE_LOCKS_REQUIRED(f_declared->mu_);
1873};
1874
1875// EXCLUSIVE_LOCKS_REQUIRED should be applied, and rewritten to f_defined->mu_
1876void Foo::foo1(Foo *f_defined) {
1877 f_defined->a = 0;
1878};
1879
1880void test() {
1881 Foo myfoo;
1882 myfoo.foo1(&myfoo); // \
1883 // expected-warning {{calling function 'foo1' requires exclusive lock on 'mu_'}}
1884 myfoo.mu_.Lock();
1885 myfoo.foo1(&myfoo);
1886 myfoo.mu_.Unlock();
1887}
1888
1889};
Richard Smith2e515622012-02-03 04:45:26 +00001890
1891namespace GoingNative {
1892
1893 struct __attribute__((lockable)) mutex {
1894 void lock() __attribute__((exclusive_lock_function));
1895 void unlock() __attribute__((unlock_function));
1896 // ...
1897 };
1898 bool foo();
1899 bool bar();
1900 mutex m;
1901 void test() {
1902 m.lock();
1903 while (foo()) {
1904 m.unlock();
1905 // ...
1906 if (bar()) {
1907 // ...
1908 if (foo())
1909 continue; // expected-warning {{expecting mutex 'm' to be locked at start of each loop}}
1910 //...
1911 }
1912 // ...
1913 m.lock(); // expected-note {{mutex acquired here}}
1914 }
1915 m.unlock();
1916 }
1917
1918}
DeLesley Hutchinsc24a2332012-02-16 16:50:43 +00001919
1920
1921
1922namespace FunctionDefinitionTest {
1923
1924class Foo {
1925public:
1926 void foo1();
1927 void foo2();
1928 void foo3(Foo *other);
1929
1930 template<class T>
1931 void fooT1(const T& dummy1);
1932
1933 template<class T>
1934 void fooT2(const T& dummy2) EXCLUSIVE_LOCKS_REQUIRED(mu_);
1935
1936 Mutex mu_;
1937 int a GUARDED_BY(mu_);
1938};
1939
1940template<class T>
1941class FooT {
1942public:
1943 void foo();
1944
1945 Mutex mu_;
1946 T a GUARDED_BY(mu_);
1947};
1948
1949
1950void Foo::foo1() NO_THREAD_SAFETY_ANALYSIS {
1951 a = 1;
1952}
1953
1954void Foo::foo2() EXCLUSIVE_LOCKS_REQUIRED(mu_) {
1955 a = 2;
1956}
1957
1958void Foo::foo3(Foo *other) EXCLUSIVE_LOCKS_REQUIRED(other->mu_) {
1959 other->a = 3;
1960}
1961
1962template<class T>
1963void Foo::fooT1(const T& dummy1) EXCLUSIVE_LOCKS_REQUIRED(mu_) {
1964 a = dummy1;
1965}
1966
1967/* TODO -- uncomment with template instantiation of attributes.
1968template<class T>
1969void Foo::fooT2(const T& dummy2) {
1970 a = dummy2;
1971}
1972*/
1973
1974void fooF1(Foo *f) EXCLUSIVE_LOCKS_REQUIRED(f->mu_) {
1975 f->a = 1;
1976}
1977
1978void fooF2(Foo *f);
1979void fooF2(Foo *f) EXCLUSIVE_LOCKS_REQUIRED(f->mu_) {
1980 f->a = 2;
1981}
1982
1983void fooF3(Foo *f) EXCLUSIVE_LOCKS_REQUIRED(f->mu_);
1984void fooF3(Foo *f) {
1985 f->a = 3;
1986}
1987
1988template<class T>
1989void FooT<T>::foo() EXCLUSIVE_LOCKS_REQUIRED(mu_) {
1990 a = 0;
1991}
1992
1993void test() {
1994 int dummy = 0;
1995 Foo myFoo;
1996
1997 myFoo.foo2(); // \
1998 // expected-warning {{calling function 'foo2' requires exclusive lock on 'mu_'}}
1999 myFoo.foo3(&myFoo); // \
2000 // expected-warning {{calling function 'foo3' requires exclusive lock on 'mu_'}}
2001 myFoo.fooT1(dummy); // \
2002 // expected-warning {{calling function 'fooT1' requires exclusive lock on 'mu_'}}
2003
2004 // FIXME: uncomment with template instantiation of attributes patch
2005 // myFoo.fooT2(dummy); // expected warning
2006
2007 fooF1(&myFoo); // \
2008 // expected-warning {{calling function 'fooF1' requires exclusive lock on 'mu_'}}
2009 fooF2(&myFoo); // \
2010 // expected-warning {{calling function 'fooF2' requires exclusive lock on 'mu_'}}
2011 fooF3(&myFoo); // \
2012 // expected-warning {{calling function 'fooF3' requires exclusive lock on 'mu_'}}
2013
2014 myFoo.mu_.Lock();
2015 myFoo.foo2();
2016 myFoo.foo3(&myFoo);
2017 myFoo.fooT1(dummy);
2018
2019 // FIXME: uncomment with template instantiation of attributes patch
2020 // myFoo.fooT2(dummy);
2021
2022 fooF1(&myFoo);
2023 fooF2(&myFoo);
2024 fooF3(&myFoo);
2025 myFoo.mu_.Unlock();
2026
2027 FooT<int> myFooT;
2028 myFooT.foo(); // \
2029 // expected-warning {{calling function 'foo' requires exclusive lock on 'mu_'}}
2030}
2031
DeLesley Hutchins4bda3ec2012-02-16 17:03:24 +00002032} // end namespace FunctionDefinitionTest
2033
2034
2035namespace SelfLockingTest {
2036
2037class LOCKABLE MyLock {
2038public:
2039 int foo GUARDED_BY(this);
2040
2041 void lock() EXCLUSIVE_LOCK_FUNCTION();
2042 void unlock() UNLOCK_FUNCTION();
2043
2044 void doSomething() {
2045 this->lock(); // allow 'this' as a lock expression
2046 foo = 0;
2047 doSomethingElse();
2048 this->unlock();
2049 }
2050
2051 void doSomethingElse() EXCLUSIVE_LOCKS_REQUIRED(this) {
2052 foo = 1;
2053 };
2054
2055 void test() {
2056 foo = 2; // \
2057 // expected-warning {{writing variable 'foo' requires locking 'this' exclusively}}
2058 }
DeLesley Hutchinsc24a2332012-02-16 16:50:43 +00002059};
2060
DeLesley Hutchins2f13bec2012-02-16 17:13:43 +00002061
2062class LOCKABLE MyLock2 {
2063public:
2064 Mutex mu_;
2065 int foo GUARDED_BY(this);
2066
2067 // don't check inside lock and unlock functions
2068 void lock() EXCLUSIVE_LOCK_FUNCTION() { mu_.Lock(); }
2069 void unlock() UNLOCK_FUNCTION() { mu_.Unlock(); }
2070
2071 // don't check inside constructors and destructors
2072 MyLock2() { foo = 1; }
2073 ~MyLock2() { foo = 0; }
2074};
2075
2076
DeLesley Hutchins4bda3ec2012-02-16 17:03:24 +00002077} // end namespace SelfLockingTest
2078
2079
DeLesley Hutchinsd08d5992012-02-25 00:11:55 +00002080namespace InvalidNonstatic {
2081
2082// Forward decl here causes bogus "invalid use of non-static data member"
2083// on reference to mutex_ in guarded_by attribute.
2084class Foo;
2085
2086class Foo {
2087 Mutex* mutex_;
2088
2089 int foo __attribute__((guarded_by(mutex_)));
2090};
2091
2092} // end namespace InvalidNonStatic
2093
DeLesley Hutchins2a35be82012-03-02 22:02:58 +00002094
2095namespace NoReturnTest {
2096
2097bool condition();
2098void fatal() __attribute__((noreturn));
2099
2100Mutex mu_;
2101
2102void test1() {
2103 MutexLock lock(&mu_);
2104 if (condition()) {
2105 fatal();
2106 return;
2107 }
2108}
2109
DeLesley Hutchins2287c5e2012-03-02 22:12:59 +00002110} // end namespace NoReturnTest
2111
2112
2113namespace TestMultiDecl {
2114
2115class Foo {
2116public:
2117 int GUARDED_BY(mu_) a;
2118 int GUARDED_BY(mu_) b, c;
2119
2120 void foo() {
2121 a = 0; // \
2122 // expected-warning {{writing variable 'a' requires locking 'mu_' exclusively}}
2123 b = 0; // \
2124 // expected-warning {{writing variable 'b' requires locking 'mu_' exclusively}}
2125 c = 0; // \
2126 // expected-warning {{writing variable 'c' requires locking 'mu_' exclusively}}
2127 }
2128
2129private:
2130 Mutex mu_;
DeLesley Hutchins2a35be82012-03-02 22:02:58 +00002131};
DeLesley Hutchins2287c5e2012-03-02 22:12:59 +00002132
2133} // end namespace TestMultiDecl
2134
DeLesley Hutchins7ec419a2012-03-02 22:29:50 +00002135
2136namespace WarnNoDecl {
2137
2138class Foo {
2139 void foo(int a); __attribute__(( // \
2140 // expected-warning {{declaration does not declare anything}}
2141 exclusive_locks_required(a))); // \
2142 // expected-warning {{attribute exclusive_locks_required ignored}}
2143};
2144
2145} // end namespace WarnNoDecl
2146
2147
DeLesley Hutchins0d95dfc2012-03-02 23:36:05 +00002148
2149namespace MoreLockExpressions {
2150
2151class Foo {
2152public:
2153 Mutex mu_;
2154 int a GUARDED_BY(mu_);
2155};
2156
2157class Bar {
2158public:
2159 int b;
2160 Foo* f;
2161
2162 Foo& getFoo() { return *f; }
2163 Foo& getFoo2(int c) { return *f; }
2164 Foo& getFoo3(int c, int d) { return *f; }
2165
2166 Foo& getFooey() { return *f; }
2167};
2168
2169Foo& getBarFoo(Bar &bar, int c) { return bar.getFoo2(c); }
2170
2171void test() {
2172 Foo foo;
2173 Foo *fooArray;
2174 Bar bar;
2175 int a;
2176 int b;
2177 int c;
2178
2179 bar.getFoo().mu_.Lock();
2180 bar.getFoo().a = 0;
2181 bar.getFoo().mu_.Unlock();
2182
2183 (bar.getFoo().mu_).Lock(); // test parenthesis
2184 bar.getFoo().a = 0;
2185 (bar.getFoo().mu_).Unlock();
2186
2187 bar.getFoo2(a).mu_.Lock();
2188 bar.getFoo2(a).a = 0;
2189 bar.getFoo2(a).mu_.Unlock();
2190
2191 bar.getFoo3(a, b).mu_.Lock();
2192 bar.getFoo3(a, b).a = 0;
2193 bar.getFoo3(a, b).mu_.Unlock();
2194
2195 getBarFoo(bar, a).mu_.Lock();
2196 getBarFoo(bar, a).a = 0;
2197 getBarFoo(bar, a).mu_.Unlock();
2198
2199 bar.getFoo2(10).mu_.Lock();
2200 bar.getFoo2(10).a = 0;
2201 bar.getFoo2(10).mu_.Unlock();
2202
2203 bar.getFoo2(a + 1).mu_.Lock();
2204 bar.getFoo2(a + 1).a = 0;
2205 bar.getFoo2(a + 1).mu_.Unlock();
2206
2207 (a > 0 ? fooArray[1] : fooArray[b]).mu_.Lock();
2208 (a > 0 ? fooArray[1] : fooArray[b]).a = 0;
2209 (a > 0 ? fooArray[1] : fooArray[b]).mu_.Unlock();
2210
2211 bar.getFoo().mu_.Lock();
2212 bar.getFooey().a = 0; // \
2213 // expected-warning {{writing variable 'a' requires locking 'mu_' exclusively}}
2214 bar.getFoo().mu_.Unlock();
2215
2216 bar.getFoo2(a).mu_.Lock();
2217 bar.getFoo2(b).a = 0; // \
2218 // expected-warning {{writing variable 'a' requires locking 'mu_' exclusively}}
2219 bar.getFoo2(a).mu_.Unlock();
2220
2221 bar.getFoo3(a, b).mu_.Lock();
2222 bar.getFoo3(a, c).a = 0; // \
2223 // expected-warning {{writing variable 'a' requires locking 'mu_' exclusively}}
2224 bar.getFoo3(a, b).mu_.Unlock();
2225
2226 getBarFoo(bar, a).mu_.Lock();
2227 getBarFoo(bar, b).a = 0; // \
2228 // expected-warning {{writing variable 'a' requires locking 'mu_' exclusively}}
2229 getBarFoo(bar, a).mu_.Unlock();
2230
2231 (a > 0 ? fooArray[1] : fooArray[b]).mu_.Lock();
2232 (a > 0 ? fooArray[b] : fooArray[c]).a = 0; // \
2233 // expected-warning {{writing variable 'a' requires locking 'mu_' exclusively}}
2234 (a > 0 ? fooArray[1] : fooArray[b]).mu_.Unlock();
2235}
2236
2237
DeLesley Hutchins0da44142012-06-22 17:07:28 +00002238} // end namespace MoreLockExpressions
2239
2240
2241namespace TrylockJoinPoint {
2242
2243class Foo {
2244 Mutex mu;
2245 bool c;
2246
2247 void foo() {
2248 if (c) {
2249 if (!mu.TryLock())
2250 return;
2251 } else {
2252 mu.Lock();
2253 }
2254 mu.Unlock();
2255 }
2256};
2257
2258} // end namespace TrylockJoinPoint
DeLesley Hutchins0d95dfc2012-03-02 23:36:05 +00002259
2260