blob: 47d844d00337c077c0a24a6c20de1fbd7e6ed826 [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())
181 sls_mu.Lock(); // \
Richard Smith2e515622012-02-03 04:45:26 +0000182 expected-warning{{mutex 'sls_mu2' is not locked on every path through here}} \
183 expected-note{{mutex acquired here}}
184
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000185 else
186 sls_mu2.Lock(); // \
Richard Smith2e515622012-02-03 04:45:26 +0000187 expected-note{{mutex acquired here}}
188} // expected-warning{{mutex 'sls_mu' is not locked on every path through here}}
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000189
190void sls_fun_bad_5() {
Richard Smith2e515622012-02-03 04:45:26 +0000191 sls_mu.Lock(); // expected-note {{mutex acquired here}}
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000192 if (getBool())
193 sls_mu.Unlock();
Richard Smith2e515622012-02-03 04:45:26 +0000194} // expected-warning{{mutex 'sls_mu' is not locked on every path through here}}
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000195
196void sls_fun_bad_6() {
197 if (getBool()) {
Richard Smith2e515622012-02-03 04:45:26 +0000198 sls_mu.Lock(); // expected-note {{mutex acquired here}}
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000199 } else {
200 if (getBool()) {
201 getBool(); // EMPTY
202 } else {
203 getBool(); // EMPTY
204 }
205 }
206 sls_mu.Unlock(); // \
Richard Smith2e515622012-02-03 04:45:26 +0000207 expected-warning{{mutex 'sls_mu' is not locked on every path through here}}\
208 expected-warning{{unlocking 'sls_mu' that was not locked}}
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000209}
210
211void sls_fun_bad_7() {
Richard Smithaacde712012-02-03 03:30:07 +0000212 sls_mu.Lock();
Caitlin Sadowski4e4bc752011-09-15 17:25:19 +0000213 while (getBool()) {
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000214 sls_mu.Unlock();
215 if (getBool()) {
216 if (getBool()) {
Richard Smith2e515622012-02-03 04:45:26 +0000217 continue; // \
218 expected-warning{{expecting mutex 'sls_mu' to be locked at start of each loop}}
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000219 }
220 }
Richard Smith2e515622012-02-03 04:45:26 +0000221 sls_mu.Lock(); // expected-note {{mutex acquired here}}
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000222 }
223 sls_mu.Unlock();
224}
225
226void sls_fun_bad_8() {
Richard Smith2e515622012-02-03 04:45:26 +0000227 sls_mu.Lock(); // expected-note{{mutex acquired here}}
228
229 // FIXME: TERRIBLE SOURCE LOCATION!
230 do { // expected-warning{{expecting mutex 'sls_mu' to be locked at start of each loop}}
Caitlin Sadowski4e4bc752011-09-15 17:25:19 +0000231 sls_mu.Unlock();
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000232 } while (getBool());
233}
234
235void sls_fun_bad_9() {
236 do {
237 sls_mu.Lock(); // \
Richard Smith2e515622012-02-03 04:45:26 +0000238 // expected-warning{{expecting mutex 'sls_mu' to be locked at start of each loop}} \
239 // expected-note{{mutex acquired here}}
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000240 } while (getBool());
241 sls_mu.Unlock();
242}
243
244void sls_fun_bad_10() {
Richard Smith2e515622012-02-03 04:45:26 +0000245 sls_mu.Lock(); // expected-note 2{{mutex acquired here}}
Caitlin Sadowski4e4bc752011-09-15 17:25:19 +0000246 while(getBool()) {
Richard Smith2e515622012-02-03 04:45:26 +0000247 sls_mu.Unlock(); // expected-warning{{expecting mutex 'sls_mu' to be locked at start of each loop}}
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000248 }
Richard Smith2e515622012-02-03 04:45:26 +0000249} // expected-warning{{mutex 'sls_mu' is still locked at the end of function}}
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000250
251void sls_fun_bad_11() {
Richard Smith2e515622012-02-03 04:45:26 +0000252 while (getBool()) { // \
253 expected-warning{{expecting mutex 'sls_mu' to be locked at start of each loop}}
254 sls_mu.Lock(); // expected-note {{mutex acquired here}}
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000255 }
256 sls_mu.Unlock(); // \
Caitlin Sadowski8bccabe2011-09-08 21:52:50 +0000257 // expected-warning{{unlocking 'sls_mu' that was not locked}}
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000258}
259
Richard Smithaacde712012-02-03 03:30:07 +0000260void sls_fun_bad_12() {
Richard Smith2e515622012-02-03 04:45:26 +0000261 sls_mu.Lock(); // expected-note {{mutex acquired here}}
Richard Smithaacde712012-02-03 03:30:07 +0000262 while (getBool()) {
263 sls_mu.Unlock();
264 if (getBool()) {
265 if (getBool()) {
Richard Smith2e515622012-02-03 04:45:26 +0000266 break; // expected-warning{{mutex 'sls_mu' is not locked on every path through here}}
Richard Smithaacde712012-02-03 03:30:07 +0000267 }
268 }
269 sls_mu.Lock();
270 }
271 sls_mu.Unlock();
272}
273
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000274//-----------------------------------------//
275// Handling lock expressions in attribute args
276// -------------------------------------------//
277
278Mutex aa_mu;
279
280class GlobalLocker {
281public:
282 void globalLock() __attribute__((exclusive_lock_function(aa_mu)));
283 void globalUnlock() __attribute__((unlock_function(aa_mu)));
284};
285
286GlobalLocker glock;
287
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000288void aa_fun_1() {
289 glock.globalLock();
290 glock.globalUnlock();
291}
292
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000293void aa_fun_bad_1() {
294 glock.globalUnlock(); // \
Caitlin Sadowski8bccabe2011-09-08 21:52:50 +0000295 // expected-warning{{unlocking 'aa_mu' that was not locked}}
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000296}
297
298void aa_fun_bad_2() {
299 glock.globalLock();
300 glock.globalLock(); // \
Caitlin Sadowski8bccabe2011-09-08 21:52:50 +0000301 // expected-warning{{locking 'aa_mu' that is already locked}}
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000302 glock.globalUnlock();
303}
304
305void aa_fun_bad_3() {
Richard Smith2e515622012-02-03 04:45:26 +0000306 glock.globalLock(); // expected-note{{mutex acquired here}}
307} // expected-warning{{mutex 'aa_mu' is still locked at the end of function}}
Caitlin Sadowskib4d0a962011-08-29 17:12:27 +0000308
Caitlin Sadowskib4d0a962011-08-29 17:12:27 +0000309//--------------------------------------------------//
310// Regression tests for unusual method names
311//--------------------------------------------------//
312
313Mutex wmu;
314
315// Test diagnostics for other method names.
316class WeirdMethods {
DeLesley Hutchins2f13bec2012-02-16 17:13:43 +0000317 // FIXME: can't currently check inside constructors and destructors.
Caitlin Sadowskib4d0a962011-08-29 17:12:27 +0000318 WeirdMethods() {
DeLesley Hutchins2f13bec2012-02-16 17:13:43 +0000319 wmu.Lock(); // EXPECTED-NOTE {{mutex acquired here}}
320 } // EXPECTED-WARNING {{mutex 'wmu' is still locked at the end of function}}
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 void operator++() {
Richard Smith2e515622012-02-03 04:45:26 +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 operator int*() {
Richard Smith2e515622012-02-03 04:45:26 +0000328 wmu.Lock(); // expected-note {{mutex acquired here}}
Caitlin Sadowskib4d0a962011-08-29 17:12:27 +0000329 return 0;
Richard Smith2e515622012-02-03 04:45:26 +0000330 } // expected-warning {{mutex 'wmu' is still locked at the end of function}}
Caitlin Sadowskib4d0a962011-08-29 17:12:27 +0000331};
332
Caitlin Sadowski05b436e2011-08-29 22:27:51 +0000333//-----------------------------------------------//
334// Errors for guarded by or guarded var variables
335// ----------------------------------------------//
336
337int *pgb_gvar __attribute__((pt_guarded_var));
338int *pgb_var __attribute__((pt_guarded_by(sls_mu)));
339
340class PGBFoo {
341 public:
342 int x;
343 int *pgb_field __attribute__((guarded_by(sls_mu2)))
344 __attribute__((pt_guarded_by(sls_mu)));
345 void testFoo() {
346 pgb_field = &x; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000347 // expected-warning {{writing variable 'pgb_field' requires locking 'sls_mu2' exclusively}}
348 *pgb_field = x; // 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}}
350 x = *pgb_field; // expected-warning {{reading variable 'pgb_field' requires locking 'sls_mu2'}} \
351 // expected-warning {{reading the value pointed to by 'pgb_field' requires locking 'sls_mu'}}
352 (*pgb_field)++; // expected-warning {{reading variable 'pgb_field' requires locking 'sls_mu2'}} \
353 // expected-warning {{writing the value pointed to by 'pgb_field' requires locking 'sls_mu' exclusively}}
Caitlin Sadowski05b436e2011-08-29 22:27:51 +0000354 }
355};
356
357class GBFoo {
358 public:
359 int gb_field __attribute__((guarded_by(sls_mu)));
360
361 void testFoo() {
362 gb_field = 0; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000363 // expected-warning {{writing variable 'gb_field' requires locking 'sls_mu' exclusively}}
Caitlin Sadowski05b436e2011-08-29 22:27:51 +0000364 }
Caitlin Sadowskiaf370612011-09-08 18:35:21 +0000365
366 void testNoAnal() __attribute__((no_thread_safety_analysis)) {
367 gb_field = 0;
368 }
Caitlin Sadowski05b436e2011-08-29 22:27:51 +0000369};
370
371GBFoo GlobalGBFoo __attribute__((guarded_by(sls_mu)));
372
373void gb_fun_0() {
374 sls_mu.Lock();
375 int x = *pgb_var;
376 sls_mu.Unlock();
377}
378
379void gb_fun_1() {
380 sls_mu.Lock();
381 *pgb_var = 2;
382 sls_mu.Unlock();
383}
384
385void gb_fun_2() {
386 int x;
387 pgb_var = &x;
388}
389
390void gb_fun_3() {
391 int *x = pgb_var;
392}
393
394void gb_bad_0() {
395 sls_guard_var = 1; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000396 // expected-warning{{writing variable 'sls_guard_var' requires locking any mutex exclusively}}
Caitlin Sadowski05b436e2011-08-29 22:27:51 +0000397}
398
399void gb_bad_1() {
400 int x = sls_guard_var; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000401 // expected-warning{{reading variable 'sls_guard_var' requires locking any mutex}}
Caitlin Sadowski05b436e2011-08-29 22:27:51 +0000402}
403
404void gb_bad_2() {
405 sls_guardby_var = 1; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000406 // expected-warning {{writing variable 'sls_guardby_var' requires locking 'sls_mu' exclusively}}
Caitlin Sadowski05b436e2011-08-29 22:27:51 +0000407}
408
409void gb_bad_3() {
410 int x = sls_guardby_var; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000411 // expected-warning {{reading variable 'sls_guardby_var' requires locking 'sls_mu'}}
Caitlin Sadowski05b436e2011-08-29 22:27:51 +0000412}
413
414void gb_bad_4() {
415 *pgb_gvar = 1; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000416 // expected-warning {{writing the value pointed to by 'pgb_gvar' requires locking any mutex exclusively}}
Caitlin Sadowski05b436e2011-08-29 22:27:51 +0000417}
418
419void gb_bad_5() {
420 int x = *pgb_gvar; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000421 // expected-warning {{reading the value pointed to by 'pgb_gvar' requires locking any mutex}}
Caitlin Sadowski05b436e2011-08-29 22:27:51 +0000422}
423
424void gb_bad_6() {
425 *pgb_var = 1; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000426 // expected-warning {{writing the value pointed to by 'pgb_var' requires locking 'sls_mu' exclusively}}
Caitlin Sadowski05b436e2011-08-29 22:27:51 +0000427}
428
429void gb_bad_7() {
430 int x = *pgb_var; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000431 // expected-warning {{reading the value pointed to by 'pgb_var' requires locking 'sls_mu'}}
Caitlin Sadowski05b436e2011-08-29 22:27:51 +0000432}
433
434void gb_bad_8() {
435 GBFoo G;
436 G.gb_field = 0; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000437 // expected-warning {{writing variable 'gb_field' requires locking 'sls_mu'}}
Caitlin Sadowski05b436e2011-08-29 22:27:51 +0000438}
439
440void gb_bad_9() {
441 sls_guard_var++; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000442 // expected-warning{{writing variable 'sls_guard_var' requires locking any mutex exclusively}}
Caitlin Sadowski05b436e2011-08-29 22:27:51 +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 ++sls_guard_var; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000446 // expected-warning{{writing variable 'sls_guard_var' requires locking any mutex exclusively}}
Caitlin Sadowskia49d1d82011-09-09 16:07:55 +0000447 --sls_guard_var;// \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000448 // expected-warning{{writing variable 'sls_guard_var' requires locking any mutex exclusively}}
Caitlin Sadowski05b436e2011-08-29 22:27:51 +0000449}
Caitlin Sadowskib4d0a962011-08-29 17:12:27 +0000450
Caitlin Sadowskieff98fc2011-09-08 17:42:22 +0000451//-----------------------------------------------//
452// Warnings on variables with late parsed attributes
453// ----------------------------------------------//
454
455class LateFoo {
456public:
457 int a __attribute__((guarded_by(mu)));
458 int b;
459
460 void foo() __attribute__((exclusive_locks_required(mu))) { }
461
462 void test() {
463 a = 0; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000464 // expected-warning{{writing variable 'a' requires locking 'mu' exclusively}}
Caitlin Sadowskieff98fc2011-09-08 17:42:22 +0000465 b = a; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000466 // expected-warning {{reading variable 'a' requires locking 'mu'}}
Caitlin Sadowskieff98fc2011-09-08 17:42:22 +0000467 c = 0; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000468 // expected-warning {{writing variable 'c' requires locking 'mu' exclusively}}
Caitlin Sadowskieff98fc2011-09-08 17:42:22 +0000469 }
470
471 int c __attribute__((guarded_by(mu)));
472
473 Mutex mu;
474};
475
Caitlin Sadowski99107eb2011-09-09 16:21:55 +0000476class LateBar {
477 public:
478 int a_ __attribute__((guarded_by(mu1_)));
479 int b_;
480 int *q __attribute__((pt_guarded_by(mu)));
481 Mutex mu1_;
482 Mutex mu;
483 LateFoo Foo;
484 LateFoo Foo2;
485 LateFoo *FooPointer;
486};
487
488LateBar b1, *b3;
489
490void late_0() {
491 LateFoo FooA;
492 LateFoo FooB;
493 FooA.mu.Lock();
494 FooA.a = 5;
495 FooA.mu.Unlock();
496}
497
498void late_1() {
499 LateBar BarA;
500 BarA.FooPointer->mu.Lock();
501 BarA.FooPointer->a = 2;
502 BarA.FooPointer->mu.Unlock();
503}
504
505void late_bad_0() {
506 LateFoo fooA;
507 LateFoo fooB;
508 fooA.mu.Lock();
509 fooB.a = 5; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000510 // expected-warning{{writing variable 'a' requires locking 'mu' exclusively}}
Caitlin Sadowski99107eb2011-09-09 16:21:55 +0000511 fooA.mu.Unlock();
512}
513
514void late_bad_1() {
515 Mutex mu;
516 mu.Lock();
517 b1.mu1_.Lock();
518 int res = b1.a_ + b3->b_;
519 b3->b_ = *b1.q; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000520 // expected-warning{{reading the value pointed to by 'q' requires locking 'mu'}}
Caitlin Sadowski99107eb2011-09-09 16:21:55 +0000521 b1.mu1_.Unlock();
522 b1.b_ = res;
523 mu.Unlock();
524}
525
526void late_bad_2() {
527 LateBar BarA;
528 BarA.FooPointer->mu.Lock();
529 BarA.Foo.a = 2; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000530 // expected-warning{{writing variable 'a' requires locking 'mu' exclusively}}
Caitlin Sadowski99107eb2011-09-09 16:21:55 +0000531 BarA.FooPointer->mu.Unlock();
532}
533
534void late_bad_3() {
535 LateBar BarA;
536 BarA.Foo.mu.Lock();
537 BarA.FooPointer->a = 2; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000538 // expected-warning{{writing variable 'a' requires locking 'mu' exclusively}}
Caitlin Sadowski99107eb2011-09-09 16:21:55 +0000539 BarA.Foo.mu.Unlock();
540}
541
542void late_bad_4() {
543 LateBar BarA;
544 BarA.Foo.mu.Lock();
545 BarA.Foo2.a = 2; // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000546 // expected-warning{{writing variable 'a' requires locking 'mu' exclusively}}
Caitlin Sadowski99107eb2011-09-09 16:21:55 +0000547 BarA.Foo.mu.Unlock();
548}
549
Caitlin Sadowskia53257c2011-09-08 18:19:38 +0000550//-----------------------------------------------//
551// Extra warnings for shared vs. exclusive locks
552// ----------------------------------------------//
553
554void shared_fun_0() {
555 sls_mu.Lock();
556 do {
557 sls_mu.Unlock();
558 sls_mu.Lock();
559 } while (getBool());
560 sls_mu.Unlock();
561}
562
563void shared_fun_1() {
Caitlin Sadowski4e4bc752011-09-15 17:25:19 +0000564 sls_mu.ReaderLock(); // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000565 // expected-warning {{mutex 'sls_mu' is locked exclusively and shared in the same scope}}
Caitlin Sadowskia53257c2011-09-08 18:19:38 +0000566 do {
567 sls_mu.Unlock();
Caitlin Sadowski4e4bc752011-09-15 17:25:19 +0000568 sls_mu.Lock(); // \
569 // expected-note {{the other lock of mutex 'sls_mu' is here}}
Caitlin Sadowskia53257c2011-09-08 18:19:38 +0000570 } while (getBool());
571 sls_mu.Unlock();
572}
573
574void shared_fun_3() {
575 if (getBool())
576 sls_mu.Lock();
577 else
578 sls_mu.Lock();
579 *pgb_var = 1;
580 sls_mu.Unlock();
581}
582
583void shared_fun_4() {
584 if (getBool())
585 sls_mu.ReaderLock();
586 else
587 sls_mu.ReaderLock();
588 int x = sls_guardby_var;
589 sls_mu.Unlock();
590}
591
592void shared_fun_8() {
593 if (getBool())
594 sls_mu.Lock(); // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000595 // expected-warning {{mutex 'sls_mu' is locked exclusively and shared in the same scope}}
Caitlin Sadowskia53257c2011-09-08 18:19:38 +0000596 else
597 sls_mu.ReaderLock(); // \
Caitlin Sadowski8bccabe2011-09-08 21:52:50 +0000598 // expected-note {{the other lock of mutex 'sls_mu' is here}}
Caitlin Sadowskia53257c2011-09-08 18:19:38 +0000599 sls_mu.Unlock();
600}
601
602void shared_bad_0() {
Caitlin Sadowski4e4bc752011-09-15 17:25:19 +0000603 sls_mu.Lock(); // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000604 // expected-warning {{mutex 'sls_mu' is locked exclusively and shared in the same scope}}
Caitlin Sadowskia53257c2011-09-08 18:19:38 +0000605 do {
606 sls_mu.Unlock();
Caitlin Sadowski4e4bc752011-09-15 17:25:19 +0000607 sls_mu.ReaderLock(); // \
608 // expected-note {{the other lock of mutex 'sls_mu' is here}}
Caitlin Sadowskia53257c2011-09-08 18:19:38 +0000609 } while (getBool());
610 sls_mu.Unlock();
611}
612
613void shared_bad_1() {
614 if (getBool())
615 sls_mu.Lock(); // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000616 // expected-warning {{mutex 'sls_mu' is locked exclusively and shared in the same scope}}
Caitlin Sadowskia53257c2011-09-08 18:19:38 +0000617 else
618 sls_mu.ReaderLock(); // \
Caitlin Sadowski8bccabe2011-09-08 21:52:50 +0000619 // expected-note {{the other lock of mutex 'sls_mu' is here}}
Caitlin Sadowskia53257c2011-09-08 18:19:38 +0000620 *pgb_var = 1;
621 sls_mu.Unlock();
622}
623
624void shared_bad_2() {
625 if (getBool())
626 sls_mu.ReaderLock(); // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000627 // expected-warning {{mutex 'sls_mu' is locked exclusively and shared in the same scope}}
Caitlin Sadowskia53257c2011-09-08 18:19:38 +0000628 else
629 sls_mu.Lock(); // \
Caitlin Sadowski8bccabe2011-09-08 21:52:50 +0000630 // expected-note {{the other lock of mutex 'sls_mu' is here}}
Caitlin Sadowskia53257c2011-09-08 18:19:38 +0000631 *pgb_var = 1;
632 sls_mu.Unlock();
633}
Caitlin Sadowski978191e2011-09-08 18:27:31 +0000634
635// FIXME: Add support for functions (not only methods)
636class LRBar {
637 public:
638 void aa_elr_fun() __attribute__((exclusive_locks_required(aa_mu)));
639 void aa_elr_fun_s() __attribute__((shared_locks_required(aa_mu)));
640 void le_fun() __attribute__((locks_excluded(sls_mu)));
641};
642
643class LRFoo {
644 public:
645 void test() __attribute__((exclusive_locks_required(sls_mu)));
646 void testShared() __attribute__((shared_locks_required(sls_mu2)));
647};
648
649void elr_fun() __attribute__((exclusive_locks_required(sls_mu)));
650void elr_fun() {}
651
652LRFoo MyLRFoo;
653LRBar Bar;
654
655void es_fun_0() {
656 aa_mu.Lock();
657 Bar.aa_elr_fun();
658 aa_mu.Unlock();
659}
660
661void es_fun_1() {
662 aa_mu.Lock();
663 Bar.aa_elr_fun_s();
664 aa_mu.Unlock();
665}
666
667void es_fun_2() {
668 aa_mu.ReaderLock();
669 Bar.aa_elr_fun_s();
670 aa_mu.Unlock();
671}
672
673void es_fun_3() {
674 sls_mu.Lock();
675 MyLRFoo.test();
676 sls_mu.Unlock();
677}
678
679void es_fun_4() {
680 sls_mu2.Lock();
681 MyLRFoo.testShared();
682 sls_mu2.Unlock();
683}
684
685void es_fun_5() {
686 sls_mu2.ReaderLock();
687 MyLRFoo.testShared();
688 sls_mu2.Unlock();
689}
690
691void es_fun_6() {
692 Bar.le_fun();
693}
694
695void es_fun_7() {
696 sls_mu.Lock();
697 elr_fun();
698 sls_mu.Unlock();
699}
700
Caitlin Sadowskiaf370612011-09-08 18:35:21 +0000701void es_fun_8() __attribute__((no_thread_safety_analysis));
702
703void es_fun_8() {
704 Bar.aa_elr_fun_s();
705}
706
Caitlin Sadowskicb967512011-09-15 17:43:08 +0000707void es_fun_9() __attribute__((shared_locks_required(aa_mu)));
708void es_fun_9() {
709 Bar.aa_elr_fun_s();
710}
711
712void es_fun_10() __attribute__((exclusive_locks_required(aa_mu)));
713void es_fun_10() {
714 Bar.aa_elr_fun_s();
715}
716
Caitlin Sadowski978191e2011-09-08 18:27:31 +0000717void es_bad_0() {
718 Bar.aa_elr_fun(); // \
Caitlin Sadowski8bccabe2011-09-08 21:52:50 +0000719 // expected-warning {{calling function 'aa_elr_fun' requires exclusive lock on 'aa_mu'}}
Caitlin Sadowski978191e2011-09-08 18:27:31 +0000720}
721
722void es_bad_1() {
723 aa_mu.ReaderLock();
724 Bar.aa_elr_fun(); // \
Caitlin Sadowski8bccabe2011-09-08 21:52:50 +0000725 // expected-warning {{calling function 'aa_elr_fun' requires exclusive lock on 'aa_mu'}}
Caitlin Sadowski978191e2011-09-08 18:27:31 +0000726 aa_mu.Unlock();
727}
728
729void es_bad_2() {
730 Bar.aa_elr_fun_s(); // \
Caitlin Sadowski8bccabe2011-09-08 21:52:50 +0000731 // expected-warning {{calling function 'aa_elr_fun_s' requires shared lock on 'aa_mu'}}
Caitlin Sadowski978191e2011-09-08 18:27:31 +0000732}
733
734void es_bad_3() {
735 MyLRFoo.test(); // \
Caitlin Sadowski8bccabe2011-09-08 21:52:50 +0000736 // expected-warning {{calling function 'test' requires exclusive lock on 'sls_mu'}}
Caitlin Sadowski978191e2011-09-08 18:27:31 +0000737}
738
739void es_bad_4() {
740 MyLRFoo.testShared(); // \
Caitlin Sadowski8bccabe2011-09-08 21:52:50 +0000741 // expected-warning {{calling function 'testShared' requires shared lock on 'sls_mu2'}}
Caitlin Sadowski978191e2011-09-08 18:27:31 +0000742}
743
744void es_bad_5() {
745 sls_mu.ReaderLock();
746 MyLRFoo.test(); // \
Caitlin Sadowski8bccabe2011-09-08 21:52:50 +0000747 // expected-warning {{calling function 'test' requires exclusive lock on 'sls_mu'}}
Caitlin Sadowski978191e2011-09-08 18:27:31 +0000748 sls_mu.Unlock();
749}
750
751void es_bad_6() {
752 sls_mu.Lock();
753 Bar.le_fun(); // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000754 // expected-warning {{cannot call function 'le_fun' while mutex 'sls_mu' is locked}}
Caitlin Sadowski978191e2011-09-08 18:27:31 +0000755 sls_mu.Unlock();
756}
757
758void es_bad_7() {
759 sls_mu.ReaderLock();
760 Bar.le_fun(); // \
Caitlin Sadowski74558b42011-09-15 18:13:32 +0000761 // expected-warning {{cannot call function 'le_fun' while mutex 'sls_mu' is locked}}
Caitlin Sadowski978191e2011-09-08 18:27:31 +0000762 sls_mu.Unlock();
763}
Caitlin Sadowski194418f2011-09-14 20:00:24 +0000764
DeLesley Hutchins81216392011-10-17 21:38:02 +0000765
Caitlin Sadowski194418f2011-09-14 20:00:24 +0000766//-----------------------------------------------//
767// Unparseable lock expressions
768// ----------------------------------------------//
769
DeLesley Hutchins0d95dfc2012-03-02 23:36:05 +0000770// FIXME -- derive new tests for unhandled expressions
Caitlin Sadowski194418f2011-09-14 20:00:24 +0000771
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +0000772
773//----------------------------------------------------------------------------//
774// The following test cases are ported from the gcc thread safety implementation
775// They are each wrapped inside a namespace with the test number of the gcc test
776//
777// FIXME: add all the gcc tests, once this analysis passes them.
778//----------------------------------------------------------------------------//
779
780//-----------------------------------------//
781// Good testcases (no errors)
782//-----------------------------------------//
783
784namespace thread_annot_lock_20 {
785class Bar {
786 public:
787 static int func1() EXCLUSIVE_LOCKS_REQUIRED(mu1_);
788 static int b_ GUARDED_BY(mu1_);
789 static Mutex mu1_;
790 static int a_ GUARDED_BY(mu1_);
791};
792
793Bar b1;
794
795int Bar::func1()
796{
797 int res = 5;
798
799 if (a_ == 4)
800 res = b_;
801 return res;
802}
803} // end namespace thread_annot_lock_20
804
805namespace thread_annot_lock_22 {
806// Test various usage of GUARDED_BY and PT_GUARDED_BY annotations, especially
807// uses in class definitions.
808Mutex mu;
809
810class Bar {
811 public:
812 int a_ GUARDED_BY(mu1_);
813 int b_;
814 int *q PT_GUARDED_BY(mu);
815 Mutex mu1_ ACQUIRED_AFTER(mu);
816};
817
818Bar b1, *b3;
819int *p GUARDED_BY(mu) PT_GUARDED_BY(mu);
820int res GUARDED_BY(mu) = 5;
821
822int func(int i)
823{
824 int x;
825 mu.Lock();
826 b1.mu1_.Lock();
827 res = b1.a_ + b3->b_;
828 *p = i;
829 b1.a_ = res + b3->b_;
830 b3->b_ = *b1.q;
831 b1.mu1_.Unlock();
832 b1.b_ = res;
833 x = res;
834 mu.Unlock();
835 return x;
836}
837} // end namespace thread_annot_lock_22
838
839namespace thread_annot_lock_27_modified {
840// test lock annotations applied to function definitions
841// Modified: applied annotations only to function declarations
842Mutex mu1;
843Mutex mu2 ACQUIRED_AFTER(mu1);
844
845class Foo {
846 public:
847 int method1(int i) SHARED_LOCKS_REQUIRED(mu2) EXCLUSIVE_LOCKS_REQUIRED(mu1);
848};
849
850int Foo::method1(int i) {
851 return i;
852}
853
854
855int foo(int i) EXCLUSIVE_LOCKS_REQUIRED(mu2) SHARED_LOCKS_REQUIRED(mu1);
856int foo(int i) {
857 return i;
858}
859
860static int bar(int i) EXCLUSIVE_LOCKS_REQUIRED(mu1);
861static int bar(int i) {
862 return i;
863}
864
865void main() {
866 Foo a;
867
868 mu1.Lock();
869 mu2.Lock();
870 a.method1(1);
871 foo(2);
872 mu2.Unlock();
873 bar(3);
874 mu1.Unlock();
875}
876} // end namespace thread_annot_lock_27_modified
877
878
879namespace thread_annot_lock_38 {
880// Test the case where a template member function is annotated with lock
881// attributes in a non-template class.
882class Foo {
883 public:
884 void func1(int y) LOCKS_EXCLUDED(mu_);
885 template <typename T> void func2(T x) LOCKS_EXCLUDED(mu_);
886 private:
887 Mutex mu_;
888};
889
890Foo *foo;
891
892void main()
893{
894 foo->func1(5);
895 foo->func2(5);
896}
897} // end namespace thread_annot_lock_38
898
899namespace thread_annot_lock_43 {
900// Tests lock canonicalization
901class Foo {
902 public:
903 Mutex *mu_;
904};
905
906class FooBar {
907 public:
908 Foo *foo_;
909 int GetA() EXCLUSIVE_LOCKS_REQUIRED(foo_->mu_) { return a_; }
910 int a_ GUARDED_BY(foo_->mu_);
911};
912
913FooBar *fb;
914
915void main()
916{
917 int x;
918 fb->foo_->mu_->Lock();
919 x = fb->GetA();
920 fb->foo_->mu_->Unlock();
921}
922} // end namespace thread_annot_lock_43
923
924namespace thread_annot_lock_49 {
925// Test the support for use of lock expression in the annotations
926class Foo {
927 public:
928 Mutex foo_mu_;
929};
930
931class Bar {
932 private:
933 Foo *foo;
934 Mutex bar_mu_ ACQUIRED_AFTER(foo->foo_mu_);
935
936 public:
937 void Test1() {
938 foo->foo_mu_.Lock();
939 bar_mu_.Lock();
940 bar_mu_.Unlock();
941 foo->foo_mu_.Unlock();
942 }
943};
944
945void main() {
946 Bar bar;
947 bar.Test1();
948}
949} // end namespace thread_annot_lock_49
950
951namespace thread_annot_lock_61_modified {
952 // Modified to fix the compiler errors
953 // Test the fix for a bug introduced by the support of pass-by-reference
954 // paramters.
955 struct Foo { Foo &operator<< (bool) {return *this;} };
956 Foo &getFoo();
957 struct Bar { Foo &func () {return getFoo();} };
958 struct Bas { void operator& (Foo &) {} };
959 void mumble()
960 {
961 Bas() & Bar().func() << "" << "";
962 Bas() & Bar().func() << "";
963 }
964} // end namespace thread_annot_lock_61_modified
965
966
967namespace thread_annot_lock_65 {
968// Test the fix for a bug in the support of allowing reader locks for
969// non-const, non-modifying overload functions. (We didn't handle the builtin
970// properly.)
971enum MyFlags {
972 Zero,
973 One,
974 Two,
975 Three,
976 Four,
977 Five,
978 Six,
979 Seven,
980 Eight,
981 Nine
982};
983
984inline MyFlags
985operator|(MyFlags a, MyFlags b)
986{
987 return MyFlags(static_cast<int>(a) | static_cast<int>(b));
988}
989
990inline MyFlags&
991operator|=(MyFlags& a, MyFlags b)
992{
993 return a = a | b;
994}
995} // end namespace thread_annot_lock_65
996
997namespace thread_annot_lock_66_modified {
998// Modified: Moved annotation to function defn
999// Test annotations on out-of-line definitions of member functions where the
1000// annotations refer to locks that are also data members in the class.
1001Mutex mu;
1002
1003class Foo {
1004 public:
1005 int method1(int i) SHARED_LOCKS_REQUIRED(mu1, mu, mu2);
1006 int data GUARDED_BY(mu1);
1007 Mutex *mu1;
1008 Mutex *mu2;
1009};
1010
1011int Foo::method1(int i)
1012{
1013 return data + i;
1014}
1015
1016void main()
1017{
1018 Foo a;
1019
1020 a.mu2->Lock();
1021 a.mu1->Lock();
1022 mu.Lock();
1023 a.method1(1);
1024 mu.Unlock();
1025 a.mu1->Unlock();
1026 a.mu2->Unlock();
1027}
1028} // end namespace thread_annot_lock_66_modified
1029
1030namespace thread_annot_lock_68_modified {
1031// Test a fix to a bug in the delayed name binding with nested template
1032// instantiation. We use a stack to make sure a name is not resolved to an
1033// inner context.
1034template <typename T>
1035class Bar {
1036 Mutex mu_;
1037};
1038
1039template <typename T>
1040class Foo {
1041 public:
1042 void func(T x) {
1043 mu_.Lock();
DeLesley Hutchins23323e02012-01-20 22:50:54 +00001044 count_ = x;
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001045 mu_.Unlock();
1046 }
1047
1048 private:
DeLesley Hutchins23323e02012-01-20 22:50:54 +00001049 T count_ GUARDED_BY(mu_);
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001050 Bar<T> bar_;
1051 Mutex mu_;
1052};
1053
1054void main()
1055{
1056 Foo<int> *foo;
1057 foo->func(5);
1058}
1059} // end namespace thread_annot_lock_68_modified
1060
1061namespace thread_annot_lock_30_modified {
1062// Test delay parsing of lock attribute arguments with nested classes.
1063// Modified: trylocks replaced with exclusive_lock_fun
1064int a = 0;
1065
1066class Bar {
1067 struct Foo;
1068
1069 public:
1070 void MyLock() EXCLUSIVE_LOCK_FUNCTION(mu);
1071
1072 int func() {
1073 MyLock();
1074// if (foo == 0) {
1075// return 0;
1076// }
1077 a = 5;
1078 mu.Unlock();
1079 return 1;
1080 }
1081
1082 class FooBar {
1083 int x;
1084 int y;
1085 };
1086
1087 private:
1088 Mutex mu;
1089};
1090
1091Bar *bar;
1092
1093void main()
1094{
1095 bar->func();
1096}
1097} // end namespace thread_annot_lock_30_modified
1098
1099namespace thread_annot_lock_47 {
1100// Test the support for annotations on virtual functions.
1101// This is a good test case. (i.e. There should be no warning emitted by the
1102// compiler.)
1103class Base {
1104 public:
1105 virtual void func1() EXCLUSIVE_LOCKS_REQUIRED(mu_);
1106 virtual void func2() LOCKS_EXCLUDED(mu_);
1107 Mutex mu_;
1108};
1109
1110class Child : public Base {
1111 public:
1112 virtual void func1() EXCLUSIVE_LOCKS_REQUIRED(mu_);
1113 virtual void func2() LOCKS_EXCLUDED(mu_);
1114};
1115
1116void main() {
1117 Child *c;
1118 Base *b = c;
1119
1120 b->mu_.Lock();
1121 b->func1();
1122 b->mu_.Unlock();
1123 b->func2();
1124
1125 c->mu_.Lock();
1126 c->func1();
1127 c->mu_.Unlock();
1128 c->func2();
1129}
1130} // end namespace thread_annot_lock_47
1131
1132//-----------------------------------------//
1133// Tests which produce errors
1134//-----------------------------------------//
1135
1136namespace thread_annot_lock_13 {
1137Mutex mu1;
1138Mutex mu2;
1139
1140int g GUARDED_BY(mu1);
1141int w GUARDED_BY(mu2);
1142
1143class Foo {
1144 public:
1145 void bar() LOCKS_EXCLUDED(mu_, mu1);
1146 int foo() SHARED_LOCKS_REQUIRED(mu_) EXCLUSIVE_LOCKS_REQUIRED(mu2);
1147
1148 private:
1149 int a_ GUARDED_BY(mu_);
1150 public:
1151 Mutex mu_ ACQUIRED_AFTER(mu1);
1152};
1153
1154int Foo::foo()
1155{
1156 int res;
David Blaikiee31b8fb2012-04-05 00:16:44 +00001157 w = 5;
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001158 res = a_ + 5;
1159 return res;
1160}
1161
1162void Foo::bar()
1163{
1164 int x;
1165 mu_.Lock();
1166 x = foo(); // expected-warning {{calling function 'foo' requires exclusive lock on 'mu2'}}
1167 a_ = x + 1;
1168 mu_.Unlock();
1169 if (x > 5) {
1170 mu1.Lock();
David Blaikiee31b8fb2012-04-05 00:16:44 +00001171 g = 2;
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001172 mu1.Unlock();
1173 }
1174}
1175
1176void main()
1177{
1178 Foo f1, *f2;
1179 f1.mu_.Lock();
Caitlin Sadowski74558b42011-09-15 18:13:32 +00001180 f1.bar(); // expected-warning {{cannot call function 'bar' while mutex 'mu_' is locked}}
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001181 mu2.Lock();
1182 f1.foo();
1183 mu2.Unlock();
1184 f1.mu_.Unlock();
1185 f2->mu_.Lock();
Caitlin Sadowski74558b42011-09-15 18:13:32 +00001186 f2->bar(); // expected-warning {{cannot call function 'bar' while mutex 'mu_' is locked}}
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001187 f2->mu_.Unlock();
1188 mu2.Lock();
David Blaikiee31b8fb2012-04-05 00:16:44 +00001189 w = 2;
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001190 mu2.Unlock();
1191}
1192} // end namespace thread_annot_lock_13
1193
1194namespace thread_annot_lock_18_modified {
1195// Modified: Trylocks removed
1196// Test the ability to distnguish between the same lock field of
1197// different objects of a class.
1198 class Bar {
1199 public:
1200 bool MyLock() EXCLUSIVE_LOCK_FUNCTION(mu1_);
1201 void MyUnlock() UNLOCK_FUNCTION(mu1_);
1202 int a_ GUARDED_BY(mu1_);
1203
1204 private:
1205 Mutex mu1_;
1206};
1207
1208Bar *b1, *b2;
1209
1210void func()
1211{
1212 b1->MyLock();
1213 b1->a_ = 5;
Caitlin Sadowski74558b42011-09-15 18:13:32 +00001214 b2->a_ = 3; // expected-warning {{writing variable 'a_' requires locking 'mu1_' exclusively}}
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001215 b2->MyLock();
1216 b2->MyUnlock();
1217 b1->MyUnlock();
1218}
1219} // end namespace thread_annot_lock_18_modified
1220
1221namespace thread_annot_lock_21 {
1222// Test various usage of GUARDED_BY and PT_GUARDED_BY annotations, especially
1223// uses in class definitions.
1224Mutex mu;
1225
1226class Bar {
1227 public:
1228 int a_ GUARDED_BY(mu1_);
1229 int b_;
1230 int *q PT_GUARDED_BY(mu);
1231 Mutex mu1_ ACQUIRED_AFTER(mu);
1232};
1233
1234Bar b1, *b3;
1235int *p GUARDED_BY(mu) PT_GUARDED_BY(mu);
1236
1237int res GUARDED_BY(mu) = 5;
1238
1239int func(int i)
1240{
1241 int x;
1242 b3->mu1_.Lock();
Caitlin Sadowski74558b42011-09-15 18:13:32 +00001243 res = b1.a_ + b3->b_; // expected-warning {{reading variable 'a_' requires locking 'mu1_'}} \
1244 // expected-warning {{writing variable 'res' requires locking 'mu' exclusively}}
1245 *p = i; // expected-warning {{reading variable 'p' requires locking 'mu'}} \
1246 // expected-warning {{writing the value pointed to by 'p' requires locking 'mu' exclusively}}
1247 b1.a_ = res + b3->b_; // expected-warning {{reading variable 'res' requires locking 'mu'}} \
1248 // expected-warning {{writing variable 'a_' requires locking 'mu1_' exclusively}}
1249 b3->b_ = *b1.q; // expected-warning {{reading the value pointed to by 'q' requires locking 'mu'}}
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001250 b3->mu1_.Unlock();
Caitlin Sadowski74558b42011-09-15 18:13:32 +00001251 b1.b_ = res; // expected-warning {{reading variable 'res' requires locking 'mu'}}
1252 x = res; // expected-warning {{reading variable 'res' requires locking 'mu'}}
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001253 return x;
1254}
1255} // end namespace thread_annot_lock_21
1256
1257namespace thread_annot_lock_35_modified {
1258// Test the analyzer's ability to distinguish the lock field of different
1259// objects.
1260class Foo {
1261 private:
1262 Mutex lock_;
1263 int a_ GUARDED_BY(lock_);
1264
1265 public:
1266 void Func(Foo* child) LOCKS_EXCLUDED(lock_) {
1267 Foo *new_foo = new Foo;
1268
1269 lock_.Lock();
1270
1271 child->Func(new_foo); // There shouldn't be any warning here as the
1272 // acquired lock is not in child.
1273 child->bar(7); // expected-warning {{calling function 'bar' requires exclusive lock on 'lock_'}}
Caitlin Sadowski74558b42011-09-15 18:13:32 +00001274 child->a_ = 5; // expected-warning {{writing variable 'a_' requires locking 'lock_' exclusively}}
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001275 lock_.Unlock();
1276 }
1277
1278 void bar(int y) EXCLUSIVE_LOCKS_REQUIRED(lock_) {
1279 a_ = y;
1280 }
1281};
1282
1283Foo *x;
1284
1285void main() {
1286 Foo *child = new Foo;
1287 x->Func(child);
1288}
1289} // end namespace thread_annot_lock_35_modified
1290
1291namespace thread_annot_lock_36_modified {
1292// Modified to move the annotations to function defns.
1293// Test the analyzer's ability to distinguish the lock field of different
1294// objects
1295class Foo {
1296 private:
1297 Mutex lock_;
1298 int a_ GUARDED_BY(lock_);
1299
1300 public:
1301 void Func(Foo* child) LOCKS_EXCLUDED(lock_);
1302 void bar(int y) EXCLUSIVE_LOCKS_REQUIRED(lock_);
1303};
1304
1305void Foo::Func(Foo* child) {
1306 Foo *new_foo = new Foo;
1307
1308 lock_.Lock();
1309
1310 child->lock_.Lock();
Caitlin Sadowski74558b42011-09-15 18:13:32 +00001311 child->Func(new_foo); // expected-warning {{cannot call function 'Func' while mutex 'lock_' is locked}}
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001312 child->bar(7);
1313 child->a_ = 5;
1314 child->lock_.Unlock();
1315
1316 lock_.Unlock();
1317}
1318
1319void Foo::bar(int y) {
1320 a_ = y;
1321}
1322
1323
1324Foo *x;
1325
1326void main() {
1327 Foo *child = new Foo;
1328 x->Func(child);
1329}
1330} // end namespace thread_annot_lock_36_modified
1331
1332
1333namespace thread_annot_lock_42 {
1334// Test support of multiple lock attributes of the same kind on a decl.
1335class Foo {
1336 private:
1337 Mutex mu1, mu2, mu3;
1338 int x GUARDED_BY(mu1) GUARDED_BY(mu2);
1339 int y GUARDED_BY(mu2);
1340
1341 void f2() LOCKS_EXCLUDED(mu1) LOCKS_EXCLUDED(mu2) LOCKS_EXCLUDED(mu3) {
1342 mu2.Lock();
1343 y = 2;
1344 mu2.Unlock();
1345 }
1346
1347 public:
1348 void f1() EXCLUSIVE_LOCKS_REQUIRED(mu2) EXCLUSIVE_LOCKS_REQUIRED(mu1) {
1349 x = 5;
Caitlin Sadowski74558b42011-09-15 18:13:32 +00001350 f2(); // expected-warning {{cannot call function 'f2' while mutex 'mu1' is locked}} \
1351 // expected-warning {{cannot call function 'f2' while mutex 'mu2' is locked}}
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001352 }
1353};
1354
1355Foo *foo;
1356
1357void func()
1358{
1359 foo->f1(); // expected-warning {{calling function 'f1' requires exclusive lock on 'mu2'}} \
1360 // expected-warning {{calling function 'f1' requires exclusive lock on 'mu1'}}
1361}
1362} // end namespace thread_annot_lock_42
1363
1364namespace thread_annot_lock_46 {
1365// Test the support for annotations on virtual functions.
1366class Base {
1367 public:
1368 virtual void func1() EXCLUSIVE_LOCKS_REQUIRED(mu_);
1369 virtual void func2() LOCKS_EXCLUDED(mu_);
1370 Mutex mu_;
1371};
1372
1373class Child : public Base {
1374 public:
1375 virtual void func1() EXCLUSIVE_LOCKS_REQUIRED(mu_);
1376 virtual void func2() LOCKS_EXCLUDED(mu_);
1377};
1378
1379void main() {
1380 Child *c;
1381 Base *b = c;
1382
1383 b->func1(); // expected-warning {{calling function 'func1' requires exclusive lock on 'mu_'}}
1384 b->mu_.Lock();
Caitlin Sadowski74558b42011-09-15 18:13:32 +00001385 b->func2(); // expected-warning {{cannot call function 'func2' while mutex 'mu_' is locked}}
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001386 b->mu_.Unlock();
1387
1388 c->func1(); // expected-warning {{calling function 'func1' requires exclusive lock on 'mu_'}}
1389 c->mu_.Lock();
Caitlin Sadowski74558b42011-09-15 18:13:32 +00001390 c->func2(); // expected-warning {{cannot call function 'func2' while mutex 'mu_' is locked}}
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001391 c->mu_.Unlock();
1392}
1393} // end namespace thread_annot_lock_46
1394
1395namespace thread_annot_lock_67_modified {
1396// Modified: attributes on definitions moved to declarations
1397// Test annotations on out-of-line definitions of member functions where the
1398// annotations refer to locks that are also data members in the class.
1399Mutex mu;
1400Mutex mu3;
1401
1402class Foo {
1403 public:
1404 int method1(int i) SHARED_LOCKS_REQUIRED(mu1, mu, mu2, mu3);
1405 int data GUARDED_BY(mu1);
1406 Mutex *mu1;
1407 Mutex *mu2;
1408};
1409
1410int Foo::method1(int i) {
1411 return data + i;
1412}
1413
1414void main()
1415{
1416 Foo a;
1417 a.method1(1); // expected-warning {{calling function 'method1' requires shared lock on 'mu1'}} \
1418 // expected-warning {{calling function 'method1' requires shared lock on 'mu'}} \
1419 // expected-warning {{calling function 'method1' requires shared lock on 'mu2'}} \
1420 // expected-warning {{calling function 'method1' requires shared lock on 'mu3'}}
1421}
1422} // end namespace thread_annot_lock_67_modified
1423
1424
DeLesley Hutchins81216392011-10-17 21:38:02 +00001425namespace substitution_test {
1426 class MyData {
1427 public:
1428 Mutex mu;
1429
1430 void lockData() __attribute__((exclusive_lock_function(mu))) { }
1431 void unlockData() __attribute__((unlock_function(mu))) { }
1432
1433 void doSomething() __attribute__((exclusive_locks_required(mu))) { }
1434 };
1435
1436
1437 class DataLocker {
1438 public:
1439 void lockData (MyData *d) __attribute__((exclusive_lock_function(d->mu))) { }
1440 void unlockData(MyData *d) __attribute__((unlock_function(d->mu))) { }
1441 };
1442
1443
1444 class Foo {
1445 public:
1446 void foo(MyData* d) __attribute__((exclusive_locks_required(d->mu))) { }
1447
1448 void bar1(MyData* d) {
1449 d->lockData();
1450 foo(d);
1451 d->unlockData();
1452 }
1453
1454 void bar2(MyData* d) {
1455 DataLocker dlr;
1456 dlr.lockData(d);
1457 foo(d);
1458 dlr.unlockData(d);
1459 }
1460
1461 void bar3(MyData* d1, MyData* d2) {
1462 DataLocker dlr;
Richard Smith2e515622012-02-03 04:45:26 +00001463 dlr.lockData(d1); // expected-note {{mutex acquired here}}
DeLesley Hutchins81216392011-10-17 21:38:02 +00001464 dlr.unlockData(d2); // \
1465 // expected-warning {{unlocking 'mu' that was not locked}}
Richard Smith2e515622012-02-03 04:45:26 +00001466 } // expected-warning {{mutex 'mu' is still locked at the end of function}}
DeLesley Hutchins81216392011-10-17 21:38:02 +00001467
1468 void bar4(MyData* d1, MyData* d2) {
1469 DataLocker dlr;
1470 dlr.lockData(d1);
1471 foo(d2); // \
1472 // expected-warning {{calling function 'foo' requires exclusive lock on 'mu'}}
1473 dlr.unlockData(d1);
1474 }
1475 };
1476} // end namespace substituation_test
1477
DeLesley Hutchinse0eaa852011-10-21 18:06:53 +00001478
DeLesley Hutchinsf1ac6372011-10-21 18:10:14 +00001479
DeLesley Hutchinse0eaa852011-10-21 18:06:53 +00001480namespace constructor_destructor_tests {
1481 Mutex fooMu;
1482 int myVar GUARDED_BY(fooMu);
1483
1484 class Foo {
1485 public:
1486 Foo() __attribute__((exclusive_lock_function(fooMu))) { }
1487 ~Foo() __attribute__((unlock_function(fooMu))) { }
1488 };
1489
1490 void fooTest() {
DeLesley Hutchins6db51f72011-10-21 20:51:27 +00001491 Foo foo;
DeLesley Hutchinse0eaa852011-10-21 18:06:53 +00001492 myVar = 0;
1493 }
1494}
1495
DeLesley Hutchinsf1ac6372011-10-21 18:10:14 +00001496
1497namespace invalid_lock_expression_test {
1498
1499class LOCKABLE MyLockable {
1500public:
1501 MyLockable() __attribute__((exclusive_lock_function)) { }
DeLesley Hutchins6db51f72011-10-21 20:51:27 +00001502 ~MyLockable() { }
DeLesley Hutchinsf1ac6372011-10-21 18:10:14 +00001503};
1504
1505// create an empty lock expression
1506void foo() {
1507 MyLockable lock; // \
1508 // expected-warning {{cannot resolve lock expression}}
1509}
1510
1511} // end namespace invalid_lock_expression_test
1512
Richard Smith97f9fe02011-10-25 00:41:24 +00001513namespace template_member_test {
DeLesley Hutchinsf1ac6372011-10-21 18:10:14 +00001514
Richard Smith97f9fe02011-10-25 00:41:24 +00001515 struct S { int n; };
1516 struct T {
1517 Mutex m;
1518 S *s GUARDED_BY(this->m);
1519 };
Richard Smitha01c7112011-10-25 06:33:21 +00001520 Mutex m;
1521 struct U {
1522 union {
1523 int n;
1524 };
1525 } *u GUARDED_BY(m);
Richard Smith97f9fe02011-10-25 00:41:24 +00001526
1527 template<typename U>
1528 struct IndirectLock {
1529 int DoNaughtyThings(T *t) {
Richard Smitha01c7112011-10-25 06:33:21 +00001530 u->n = 0; // expected-warning {{reading variable 'u' requires locking 'm'}}
Richard Smith97f9fe02011-10-25 00:41:24 +00001531 return t->s->n; // expected-warning {{reading variable 's' requires locking 'm'}}
1532 }
1533 };
1534
Richard Smithf11e9232011-10-25 01:05:41 +00001535 template struct IndirectLock<int>; // expected-note {{here}}
Richard Smith97f9fe02011-10-25 00:41:24 +00001536
Richard Smith601d2ee2011-10-26 06:15:36 +00001537 struct V {
1538 void f(int);
1539 void f(double);
1540
1541 Mutex m;
1542 V *p GUARDED_BY(this->m);
1543 };
1544 template<typename U> struct W {
1545 V v;
1546 void f(U u) {
1547 v.p->f(u); // expected-warning {{reading variable 'p' requires locking 'm'}}
1548 }
1549 };
1550 template struct W<int>; // expected-note {{here}}
1551
Richard Smith97f9fe02011-10-25 00:41:24 +00001552}
DeLesley Hutchins1fa3c062011-12-08 20:23:06 +00001553
1554namespace test_scoped_lockable {
1555
1556struct TestScopedLockable {
1557 Mutex mu1;
1558 Mutex mu2;
1559 int a __attribute__((guarded_by(mu1)));
1560 int b __attribute__((guarded_by(mu2)));
1561
1562 bool getBool();
1563
1564 void foo1() {
1565 MutexLock mulock(&mu1);
1566 a = 5;
1567 }
1568
1569 void foo2() {
1570 ReaderMutexLock mulock1(&mu1);
1571 if (getBool()) {
1572 MutexLock mulock2a(&mu2);
1573 b = a + 1;
1574 }
1575 else {
1576 MutexLock mulock2b(&mu2);
1577 b = a + 2;
1578 }
1579 }
1580
1581 void foo3() {
1582 MutexLock mulock_a(&mu1);
1583 MutexLock mulock_b(&mu1); // \
1584 // expected-warning {{locking 'mu1' that is already locked}}
1585 } // expected-warning {{unlocking 'mu1' that was not locked}}
1586
1587 void foo4() {
1588 MutexLock mulock1(&mu1), mulock2(&mu2);
1589 a = b+1;
1590 b = a+1;
1591 }
1592};
1593
1594} // end namespace test_scoped_lockable
1595
1596
DeLesley Hutchinsdf497822011-12-29 00:56:48 +00001597namespace FunctionAttrTest {
1598
1599class Foo {
1600public:
1601 Mutex mu_;
1602 int a GUARDED_BY(mu_);
1603};
1604
1605Foo fooObj;
1606
1607void foo() EXCLUSIVE_LOCKS_REQUIRED(fooObj.mu_);
1608
1609void bar() {
1610 foo(); // expected-warning {{calling function 'foo' requires exclusive lock on 'mu_'}}
1611 fooObj.mu_.Lock();
1612 foo();
1613 fooObj.mu_.Unlock();
1614}
1615
1616}; // end namespace FunctionAttrTest
1617
1618
DeLesley Hutchinsb4fa4182012-01-06 19:16:50 +00001619struct TestTryLock {
1620 Mutex mu;
1621 int a GUARDED_BY(mu);
1622 bool cond;
1623
1624 void foo1() {
1625 if (mu.TryLock()) {
1626 a = 1;
1627 mu.Unlock();
1628 }
1629 }
1630
1631 void foo2() {
1632 if (!mu.TryLock()) return;
1633 a = 2;
1634 mu.Unlock();
1635 }
1636
1637 void foo3() {
1638 bool b = mu.TryLock();
1639 if (b) {
1640 a = 3;
1641 mu.Unlock();
1642 }
1643 }
1644
1645 void foo4() {
1646 bool b = mu.TryLock();
1647 if (!b) return;
1648 a = 4;
1649 mu.Unlock();
1650 }
1651
1652 void foo5() {
1653 while (mu.TryLock()) {
1654 a = a + 1;
1655 mu.Unlock();
1656 }
1657 }
1658
1659 void foo6() {
1660 bool b = mu.TryLock();
1661 b = !b;
1662 if (b) return;
1663 a = 6;
1664 mu.Unlock();
1665 }
1666
1667 void foo7() {
1668 bool b1 = mu.TryLock();
1669 bool b2 = !b1;
1670 bool b3 = !b2;
1671 if (b3) {
1672 a = 7;
1673 mu.Unlock();
1674 }
1675 }
1676
1677 // Test use-def chains: join points
1678 void foo8() {
1679 bool b = mu.TryLock();
1680 bool b2 = b;
1681 if (cond)
1682 b = true;
1683 if (b) { // b should be unknown at this point, becuase of the join point
1684 a = 8; // expected-warning {{writing variable 'a' requires locking 'mu' exclusively}}
1685 }
1686 if (b2) { // b2 should be known at this point.
1687 a = 8;
1688 mu.Unlock();
1689 }
1690 }
1691
1692 // Test use-def-chains: back edges
1693 void foo9() {
1694 bool b = mu.TryLock();
1695
1696 for (int i = 0; i < 10; ++i);
1697
1698 if (b) { // b is still known, because the loop doesn't alter it
1699 a = 9;
1700 mu.Unlock();
1701 }
1702 }
1703
1704 // Test use-def chains: back edges
1705 void foo10() {
1706 bool b = mu.TryLock();
1707
1708 while (cond) {
1709 if (b) { // b should be uknown at this point b/c of the loop
1710 a = 10; // expected-warning {{writing variable 'a' requires locking 'mu' exclusively}}
1711 }
1712 b = !b;
1713 }
1714 }
1715}; // end TestTrylock
1716
1717
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +00001718namespace TestTemplateAttributeInstantiation {
1719
1720class Foo1 {
1721public:
1722 Mutex mu_;
1723 int a GUARDED_BY(mu_);
1724};
1725
1726class Foo2 {
1727public:
1728 int a GUARDED_BY(mu_);
1729 Mutex mu_;
1730};
1731
1732
1733class Bar {
1734public:
1735 // Test non-dependent expressions in attributes on template functions
1736 template <class T>
1737 void barND(Foo1 *foo, T *fooT) EXCLUSIVE_LOCKS_REQUIRED(foo->mu_) {
1738 foo->a = 0;
1739 }
1740
1741 // Test dependent expressions in attributes on template functions
1742 template <class T>
1743 void barD(Foo1 *foo, T *fooT) EXCLUSIVE_LOCKS_REQUIRED(fooT->mu_) {
1744 fooT->a = 0;
1745 }
1746};
1747
1748
1749template <class T>
1750class BarT {
1751public:
1752 Foo1 fooBase;
1753 T fooBaseT;
1754
1755 // Test non-dependent expression in ordinary method on template class
1756 void barND() EXCLUSIVE_LOCKS_REQUIRED(fooBase.mu_) {
1757 fooBase.a = 0;
1758 }
1759
1760 // Test dependent expressions in ordinary methods on template class
1761 void barD() EXCLUSIVE_LOCKS_REQUIRED(fooBaseT.mu_) {
1762 fooBaseT.a = 0;
1763 }
1764
1765 // Test dependent expressions in template method in template class
1766 template <class T2>
1767 void barTD(T2 *fooT) EXCLUSIVE_LOCKS_REQUIRED(fooBaseT.mu_, fooT->mu_) {
1768 fooBaseT.a = 0;
1769 fooT->a = 0;
1770 }
1771};
1772
1773template <class T>
1774class Cell {
1775public:
1776 Mutex mu_;
1777 // Test dependent guarded_by
1778 T data GUARDED_BY(mu_);
1779
DeLesley Hutchins23323e02012-01-20 22:50:54 +00001780 void fooEx() EXCLUSIVE_LOCKS_REQUIRED(mu_) {
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +00001781 data = 0;
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +00001782 }
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +00001783
1784 void foo() {
1785 mu_.Lock();
1786 data = 0;
1787 mu_.Unlock();
1788 }
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +00001789};
1790
1791void test() {
1792 Bar b;
1793 BarT<Foo2> bt;
1794 Foo1 f1;
1795 Foo2 f2;
1796
1797 f1.mu_.Lock();
1798 f2.mu_.Lock();
1799 bt.fooBase.mu_.Lock();
1800 bt.fooBaseT.mu_.Lock();
1801
1802 b.barND(&f1, &f2);
1803 b.barD(&f1, &f2);
1804 bt.barND();
1805 bt.barD();
1806 bt.barTD(&f2);
1807
1808 f1.mu_.Unlock();
1809 bt.barTD(&f1); // \
1810 // expected-warning {{calling function 'barTD' requires exclusive lock on 'mu_'}}
1811
1812 bt.fooBase.mu_.Unlock();
1813 bt.fooBaseT.mu_.Unlock();
1814 f2.mu_.Unlock();
1815
1816 Cell<int> cell;
1817 cell.data = 0; // \
1818 // expected-warning {{writing variable 'data' requires locking 'mu_' exclusively}}
1819 cell.foo();
DeLesley Hutchins23323e02012-01-20 22:50:54 +00001820 cell.mu_.Lock();
1821 cell.fooEx();
1822 cell.mu_.Unlock();
1823}
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +00001824
DeLesley Hutchins23323e02012-01-20 22:50:54 +00001825
1826template <class T>
1827class CellDelayed {
1828public:
1829 // Test dependent guarded_by
1830 T data GUARDED_BY(mu_);
DeLesley Hutchinsdd5756c2012-02-16 17:30:51 +00001831 static T static_data GUARDED_BY(static_mu_);
DeLesley Hutchins23323e02012-01-20 22:50:54 +00001832
1833 void fooEx(CellDelayed<T> *other) EXCLUSIVE_LOCKS_REQUIRED(mu_, other->mu_) {
1834 this->data = other->data;
1835 }
1836
1837 template <class T2>
1838 void fooExT(CellDelayed<T2> *otherT) EXCLUSIVE_LOCKS_REQUIRED(mu_, otherT->mu_) {
1839 this->data = otherT->data;
1840 }
1841
1842 void foo() {
1843 mu_.Lock();
1844 data = 0;
1845 mu_.Unlock();
1846 }
1847
1848 Mutex mu_;
DeLesley Hutchinsdd5756c2012-02-16 17:30:51 +00001849 static Mutex static_mu_;
DeLesley Hutchins23323e02012-01-20 22:50:54 +00001850};
1851
1852void testDelayed() {
1853 CellDelayed<int> celld;
1854 CellDelayed<int> celld2;
1855 celld.foo();
1856 celld.mu_.Lock();
1857 celld2.mu_.Lock();
1858
1859 celld.fooEx(&celld2);
1860 celld.fooExT(&celld2);
1861
1862 celld2.mu_.Unlock();
1863 celld.mu_.Unlock();
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +00001864}
1865
1866}; // end namespace TestTemplateAttributeInstantiation
1867
1868
DeLesley Hutchinse03b2b32012-01-20 23:24:41 +00001869namespace FunctionDeclDefTest {
1870
1871class Foo {
1872public:
1873 Mutex mu_;
1874 int a GUARDED_BY(mu_);
1875
1876 virtual void foo1(Foo *f_declared) EXCLUSIVE_LOCKS_REQUIRED(f_declared->mu_);
1877};
1878
1879// EXCLUSIVE_LOCKS_REQUIRED should be applied, and rewritten to f_defined->mu_
1880void Foo::foo1(Foo *f_defined) {
1881 f_defined->a = 0;
1882};
1883
1884void test() {
1885 Foo myfoo;
1886 myfoo.foo1(&myfoo); // \
1887 // expected-warning {{calling function 'foo1' requires exclusive lock on 'mu_'}}
1888 myfoo.mu_.Lock();
1889 myfoo.foo1(&myfoo);
1890 myfoo.mu_.Unlock();
1891}
1892
1893};
Richard Smith2e515622012-02-03 04:45:26 +00001894
1895namespace GoingNative {
1896
1897 struct __attribute__((lockable)) mutex {
1898 void lock() __attribute__((exclusive_lock_function));
1899 void unlock() __attribute__((unlock_function));
1900 // ...
1901 };
1902 bool foo();
1903 bool bar();
1904 mutex m;
1905 void test() {
1906 m.lock();
1907 while (foo()) {
1908 m.unlock();
1909 // ...
1910 if (bar()) {
1911 // ...
1912 if (foo())
1913 continue; // expected-warning {{expecting mutex 'm' to be locked at start of each loop}}
1914 //...
1915 }
1916 // ...
1917 m.lock(); // expected-note {{mutex acquired here}}
1918 }
1919 m.unlock();
1920 }
1921
1922}
DeLesley Hutchinsc24a2332012-02-16 16:50:43 +00001923
1924
1925
1926namespace FunctionDefinitionTest {
1927
1928class Foo {
1929public:
1930 void foo1();
1931 void foo2();
1932 void foo3(Foo *other);
1933
1934 template<class T>
1935 void fooT1(const T& dummy1);
1936
1937 template<class T>
1938 void fooT2(const T& dummy2) EXCLUSIVE_LOCKS_REQUIRED(mu_);
1939
1940 Mutex mu_;
1941 int a GUARDED_BY(mu_);
1942};
1943
1944template<class T>
1945class FooT {
1946public:
1947 void foo();
1948
1949 Mutex mu_;
1950 T a GUARDED_BY(mu_);
1951};
1952
1953
1954void Foo::foo1() NO_THREAD_SAFETY_ANALYSIS {
1955 a = 1;
1956}
1957
1958void Foo::foo2() EXCLUSIVE_LOCKS_REQUIRED(mu_) {
1959 a = 2;
1960}
1961
1962void Foo::foo3(Foo *other) EXCLUSIVE_LOCKS_REQUIRED(other->mu_) {
1963 other->a = 3;
1964}
1965
1966template<class T>
1967void Foo::fooT1(const T& dummy1) EXCLUSIVE_LOCKS_REQUIRED(mu_) {
1968 a = dummy1;
1969}
1970
1971/* TODO -- uncomment with template instantiation of attributes.
1972template<class T>
1973void Foo::fooT2(const T& dummy2) {
1974 a = dummy2;
1975}
1976*/
1977
1978void fooF1(Foo *f) EXCLUSIVE_LOCKS_REQUIRED(f->mu_) {
1979 f->a = 1;
1980}
1981
1982void fooF2(Foo *f);
1983void fooF2(Foo *f) EXCLUSIVE_LOCKS_REQUIRED(f->mu_) {
1984 f->a = 2;
1985}
1986
1987void fooF3(Foo *f) EXCLUSIVE_LOCKS_REQUIRED(f->mu_);
1988void fooF3(Foo *f) {
1989 f->a = 3;
1990}
1991
1992template<class T>
1993void FooT<T>::foo() EXCLUSIVE_LOCKS_REQUIRED(mu_) {
1994 a = 0;
1995}
1996
1997void test() {
1998 int dummy = 0;
1999 Foo myFoo;
2000
2001 myFoo.foo2(); // \
2002 // expected-warning {{calling function 'foo2' requires exclusive lock on 'mu_'}}
2003 myFoo.foo3(&myFoo); // \
2004 // expected-warning {{calling function 'foo3' requires exclusive lock on 'mu_'}}
2005 myFoo.fooT1(dummy); // \
2006 // expected-warning {{calling function 'fooT1' requires exclusive lock on 'mu_'}}
2007
2008 // FIXME: uncomment with template instantiation of attributes patch
2009 // myFoo.fooT2(dummy); // expected warning
2010
2011 fooF1(&myFoo); // \
2012 // expected-warning {{calling function 'fooF1' requires exclusive lock on 'mu_'}}
2013 fooF2(&myFoo); // \
2014 // expected-warning {{calling function 'fooF2' requires exclusive lock on 'mu_'}}
2015 fooF3(&myFoo); // \
2016 // expected-warning {{calling function 'fooF3' requires exclusive lock on 'mu_'}}
2017
2018 myFoo.mu_.Lock();
2019 myFoo.foo2();
2020 myFoo.foo3(&myFoo);
2021 myFoo.fooT1(dummy);
2022
2023 // FIXME: uncomment with template instantiation of attributes patch
2024 // myFoo.fooT2(dummy);
2025
2026 fooF1(&myFoo);
2027 fooF2(&myFoo);
2028 fooF3(&myFoo);
2029 myFoo.mu_.Unlock();
2030
2031 FooT<int> myFooT;
2032 myFooT.foo(); // \
2033 // expected-warning {{calling function 'foo' requires exclusive lock on 'mu_'}}
2034}
2035
DeLesley Hutchins4bda3ec2012-02-16 17:03:24 +00002036} // end namespace FunctionDefinitionTest
2037
2038
2039namespace SelfLockingTest {
2040
2041class LOCKABLE MyLock {
2042public:
2043 int foo GUARDED_BY(this);
2044
2045 void lock() EXCLUSIVE_LOCK_FUNCTION();
2046 void unlock() UNLOCK_FUNCTION();
2047
2048 void doSomething() {
2049 this->lock(); // allow 'this' as a lock expression
2050 foo = 0;
2051 doSomethingElse();
2052 this->unlock();
2053 }
2054
2055 void doSomethingElse() EXCLUSIVE_LOCKS_REQUIRED(this) {
2056 foo = 1;
2057 };
2058
2059 void test() {
2060 foo = 2; // \
2061 // expected-warning {{writing variable 'foo' requires locking 'this' exclusively}}
2062 }
DeLesley Hutchinsc24a2332012-02-16 16:50:43 +00002063};
2064
DeLesley Hutchins2f13bec2012-02-16 17:13:43 +00002065
2066class LOCKABLE MyLock2 {
2067public:
2068 Mutex mu_;
2069 int foo GUARDED_BY(this);
2070
2071 // don't check inside lock and unlock functions
2072 void lock() EXCLUSIVE_LOCK_FUNCTION() { mu_.Lock(); }
2073 void unlock() UNLOCK_FUNCTION() { mu_.Unlock(); }
2074
2075 // don't check inside constructors and destructors
2076 MyLock2() { foo = 1; }
2077 ~MyLock2() { foo = 0; }
2078};
2079
2080
DeLesley Hutchins4bda3ec2012-02-16 17:03:24 +00002081} // end namespace SelfLockingTest
2082
2083
DeLesley Hutchinsd08d5992012-02-25 00:11:55 +00002084namespace InvalidNonstatic {
2085
2086// Forward decl here causes bogus "invalid use of non-static data member"
2087// on reference to mutex_ in guarded_by attribute.
2088class Foo;
2089
2090class Foo {
2091 Mutex* mutex_;
2092
2093 int foo __attribute__((guarded_by(mutex_)));
2094};
2095
2096} // end namespace InvalidNonStatic
2097
DeLesley Hutchins2a35be82012-03-02 22:02:58 +00002098
2099namespace NoReturnTest {
2100
2101bool condition();
2102void fatal() __attribute__((noreturn));
2103
2104Mutex mu_;
2105
2106void test1() {
2107 MutexLock lock(&mu_);
2108 if (condition()) {
2109 fatal();
2110 return;
2111 }
2112}
2113
DeLesley Hutchins2287c5e2012-03-02 22:12:59 +00002114} // end namespace NoReturnTest
2115
2116
2117namespace TestMultiDecl {
2118
2119class Foo {
2120public:
2121 int GUARDED_BY(mu_) a;
2122 int GUARDED_BY(mu_) b, c;
2123
2124 void foo() {
2125 a = 0; // \
2126 // expected-warning {{writing variable 'a' requires locking 'mu_' exclusively}}
2127 b = 0; // \
2128 // expected-warning {{writing variable 'b' requires locking 'mu_' exclusively}}
2129 c = 0; // \
2130 // expected-warning {{writing variable 'c' requires locking 'mu_' exclusively}}
2131 }
2132
2133private:
2134 Mutex mu_;
DeLesley Hutchins2a35be82012-03-02 22:02:58 +00002135};
DeLesley Hutchins2287c5e2012-03-02 22:12:59 +00002136
2137} // end namespace TestMultiDecl
2138
DeLesley Hutchins7ec419a2012-03-02 22:29:50 +00002139
2140namespace WarnNoDecl {
2141
2142class Foo {
2143 void foo(int a); __attribute__(( // \
2144 // expected-warning {{declaration does not declare anything}}
2145 exclusive_locks_required(a))); // \
2146 // expected-warning {{attribute exclusive_locks_required ignored}}
2147};
2148
2149} // end namespace WarnNoDecl
2150
2151
DeLesley Hutchins0d95dfc2012-03-02 23:36:05 +00002152
2153namespace MoreLockExpressions {
2154
2155class Foo {
2156public:
2157 Mutex mu_;
2158 int a GUARDED_BY(mu_);
2159};
2160
2161class Bar {
2162public:
2163 int b;
2164 Foo* f;
2165
2166 Foo& getFoo() { return *f; }
2167 Foo& getFoo2(int c) { return *f; }
2168 Foo& getFoo3(int c, int d) { return *f; }
2169
2170 Foo& getFooey() { return *f; }
2171};
2172
2173Foo& getBarFoo(Bar &bar, int c) { return bar.getFoo2(c); }
2174
2175void test() {
2176 Foo foo;
2177 Foo *fooArray;
2178 Bar bar;
2179 int a;
2180 int b;
2181 int c;
2182
2183 bar.getFoo().mu_.Lock();
2184 bar.getFoo().a = 0;
2185 bar.getFoo().mu_.Unlock();
2186
2187 (bar.getFoo().mu_).Lock(); // test parenthesis
2188 bar.getFoo().a = 0;
2189 (bar.getFoo().mu_).Unlock();
2190
2191 bar.getFoo2(a).mu_.Lock();
2192 bar.getFoo2(a).a = 0;
2193 bar.getFoo2(a).mu_.Unlock();
2194
2195 bar.getFoo3(a, b).mu_.Lock();
2196 bar.getFoo3(a, b).a = 0;
2197 bar.getFoo3(a, b).mu_.Unlock();
2198
2199 getBarFoo(bar, a).mu_.Lock();
2200 getBarFoo(bar, a).a = 0;
2201 getBarFoo(bar, a).mu_.Unlock();
2202
2203 bar.getFoo2(10).mu_.Lock();
2204 bar.getFoo2(10).a = 0;
2205 bar.getFoo2(10).mu_.Unlock();
2206
2207 bar.getFoo2(a + 1).mu_.Lock();
2208 bar.getFoo2(a + 1).a = 0;
2209 bar.getFoo2(a + 1).mu_.Unlock();
2210
2211 (a > 0 ? fooArray[1] : fooArray[b]).mu_.Lock();
2212 (a > 0 ? fooArray[1] : fooArray[b]).a = 0;
2213 (a > 0 ? fooArray[1] : fooArray[b]).mu_.Unlock();
2214
2215 bar.getFoo().mu_.Lock();
2216 bar.getFooey().a = 0; // \
2217 // expected-warning {{writing variable 'a' requires locking 'mu_' exclusively}}
2218 bar.getFoo().mu_.Unlock();
2219
2220 bar.getFoo2(a).mu_.Lock();
2221 bar.getFoo2(b).a = 0; // \
2222 // expected-warning {{writing variable 'a' requires locking 'mu_' exclusively}}
2223 bar.getFoo2(a).mu_.Unlock();
2224
2225 bar.getFoo3(a, b).mu_.Lock();
2226 bar.getFoo3(a, c).a = 0; // \
2227 // expected-warning {{writing variable 'a' requires locking 'mu_' exclusively}}
2228 bar.getFoo3(a, b).mu_.Unlock();
2229
2230 getBarFoo(bar, a).mu_.Lock();
2231 getBarFoo(bar, b).a = 0; // \
2232 // expected-warning {{writing variable 'a' requires locking 'mu_' exclusively}}
2233 getBarFoo(bar, a).mu_.Unlock();
2234
2235 (a > 0 ? fooArray[1] : fooArray[b]).mu_.Lock();
2236 (a > 0 ? fooArray[b] : fooArray[c]).a = 0; // \
2237 // expected-warning {{writing variable 'a' requires locking 'mu_' exclusively}}
2238 (a > 0 ? fooArray[1] : fooArray[b]).mu_.Unlock();
2239}
2240
2241
2242} // end namespace
2243
2244