blob: 4f31d406b5fbc2d6d6ab4999654786bc3e21a664 [file] [log] [blame]
Stephen Hines176edba2014-12-01 14:53:08 -08001// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 -Wthread-safety -Wthread-safety-beta -Wno-thread-safety-negative -fcxx-exceptions %s
DeLesley Hutchins13106112012-07-10 21:47:55 +00002
3// FIXME: should also run %clang_cc1 -fsyntax-only -verify -Wthread-safety -std=c++11 -Wc++98-compat %s
4// FIXME: should also run %clang_cc1 -fsyntax-only -verify -Wthread-safety %s
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +00005
Stephen Hines0e2c34f2015-03-23 12:09:02 -07006#define LOCKABLE __attribute__((lockable))
7#define SCOPED_LOCKABLE __attribute__((scoped_lockable))
8#define GUARDED_BY(x) __attribute__((guarded_by(x)))
9#define GUARDED_VAR __attribute__((guarded_var))
10#define PT_GUARDED_BY(x) __attribute__((pt_guarded_by(x)))
11#define PT_GUARDED_VAR __attribute__((pt_guarded_var))
12#define ACQUIRED_AFTER(...) __attribute__((acquired_after(__VA_ARGS__)))
13#define ACQUIRED_BEFORE(...) __attribute__((acquired_before(__VA_ARGS__)))
14#define EXCLUSIVE_LOCK_FUNCTION(...) __attribute__((exclusive_lock_function(__VA_ARGS__)))
15#define SHARED_LOCK_FUNCTION(...) __attribute__((shared_lock_function(__VA_ARGS__)))
16#define ASSERT_EXCLUSIVE_LOCK(...) __attribute__((assert_exclusive_lock(__VA_ARGS__)))
17#define ASSERT_SHARED_LOCK(...) __attribute__((assert_shared_lock(__VA_ARGS__)))
18#define EXCLUSIVE_TRYLOCK_FUNCTION(...) __attribute__((exclusive_trylock_function(__VA_ARGS__)))
19#define SHARED_TRYLOCK_FUNCTION(...) __attribute__((shared_trylock_function(__VA_ARGS__)))
20#define UNLOCK_FUNCTION(...) __attribute__((unlock_function(__VA_ARGS__)))
21#define EXCLUSIVE_UNLOCK_FUNCTION(...) __attribute__((release_capability(__VA_ARGS__)))
22#define SHARED_UNLOCK_FUNCTION(...) __attribute__((release_shared_capability(__VA_ARGS__)))
23#define LOCK_RETURNED(x) __attribute__((lock_returned(x)))
24#define LOCKS_EXCLUDED(...) __attribute__((locks_excluded(__VA_ARGS__)))
25#define EXCLUSIVE_LOCKS_REQUIRED(...) __attribute__((exclusive_locks_required(__VA_ARGS__)))
26#define SHARED_LOCKS_REQUIRED(...) __attribute__((shared_locks_required(__VA_ARGS__)))
27#define NO_THREAD_SAFETY_ANALYSIS __attribute__((no_thread_safety_analysis))
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +000028
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +000029
Stephen Hines0e2c34f2015-03-23 12:09:02 -070030class LOCKABLE Mutex {
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +000031 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));
DeLesley Hutchins5c6134f2013-05-17 23:02:59 +000038
Stephen Hines176edba2014-12-01 14:53:08 -080039 // for negative capabilities
40 const Mutex& operator!() const { return *this; }
41
DeLesley Hutchins5c6134f2013-05-17 23:02:59 +000042 void AssertHeld() ASSERT_EXCLUSIVE_LOCK();
43 void AssertReaderHeld() ASSERT_SHARED_LOCK();
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +000044};
45
Stephen Hines0e2c34f2015-03-23 12:09:02 -070046class SCOPED_LOCKABLE MutexLock {
DeLesley Hutchins1fa3c062011-12-08 20:23:06 +000047 public:
Stephen Hines0e2c34f2015-03-23 12:09:02 -070048 MutexLock(Mutex *mu) EXCLUSIVE_LOCK_FUNCTION(mu);
49 MutexLock(Mutex *mu, bool adopt) EXCLUSIVE_LOCKS_REQUIRED(mu);
50 ~MutexLock() UNLOCK_FUNCTION();
DeLesley Hutchins1fa3c062011-12-08 20:23:06 +000051};
52
Stephen Hines0e2c34f2015-03-23 12:09:02 -070053class SCOPED_LOCKABLE ReaderMutexLock {
DeLesley Hutchins1fa3c062011-12-08 20:23:06 +000054 public:
Stephen Hines0e2c34f2015-03-23 12:09:02 -070055 ReaderMutexLock(Mutex *mu) SHARED_LOCK_FUNCTION(mu);
56 ReaderMutexLock(Mutex *mu, bool adopt) SHARED_LOCKS_REQUIRED(mu);
57 ~ReaderMutexLock() UNLOCK_FUNCTION();
DeLesley Hutchins1fa3c062011-12-08 20:23:06 +000058};
59
DeLesley Hutchinsc99a5d82012-06-28 22:42:48 +000060class SCOPED_LOCKABLE ReleasableMutexLock {
61 public:
62 ReleasableMutexLock(Mutex *mu) EXCLUSIVE_LOCK_FUNCTION(mu);
63 ~ReleasableMutexLock() UNLOCK_FUNCTION();
64
65 void Release() UNLOCK_FUNCTION();
66};
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +000067
Stephen Hines176edba2014-12-01 14:53:08 -080068class __attribute__((scoped_lockable)) DoubleMutexLock {
69public:
70 DoubleMutexLock(Mutex *mu1, Mutex *mu2)
71 __attribute__((exclusive_lock_function(mu1, mu2)));
72 ~DoubleMutexLock() __attribute__((unlock_function));
73};
DeLesley Hutchins9d6e7f32012-07-03 18:25:56 +000074
DeLesley Hutchins0b4db3e2012-09-07 17:34:53 +000075// The universal lock, written "*", allows checking to be selectively turned
76// off for a particular piece of code.
77void beginNoWarnOnReads() SHARED_LOCK_FUNCTION("*");
78void endNoWarnOnReads() UNLOCK_FUNCTION("*");
79void beginNoWarnOnWrites() EXCLUSIVE_LOCK_FUNCTION("*");
80void endNoWarnOnWrites() UNLOCK_FUNCTION("*");
81
82
DeLesley Hutchinsd2f38822012-09-21 17:57:00 +000083// For testing handling of smart pointers.
DeLesley Hutchins9d6e7f32012-07-03 18:25:56 +000084template<class T>
85class SmartPtr {
86public:
87 SmartPtr(T* p) : ptr_(p) { }
88 SmartPtr(const SmartPtr<T>& p) : ptr_(p.ptr_) { }
89 ~SmartPtr();
90
91 T* get() const { return ptr_; }
92 T* operator->() const { return ptr_; }
DeLesley Hutchins96fac6a2012-07-03 19:47:18 +000093 T& operator*() const { return *ptr_; }
DeLesley Hutchinsf9495912013-11-08 19:42:01 +000094 T& operator[](int i) const { return ptr_[i]; }
DeLesley Hutchins9d6e7f32012-07-03 18:25:56 +000095
96private:
97 T* ptr_;
98};
99
100
DeLesley Hutchinsd2f38822012-09-21 17:57:00 +0000101// For testing destructor calls and cleanup.
102class MyString {
103public:
104 MyString(const char* s);
105 ~MyString();
106};
107
108
Stephen Hines176edba2014-12-01 14:53:08 -0800109// For testing operator overloading
110template <class K, class T>
111class MyMap {
112public:
113 T& operator[](const K& k);
114};
115
116
117// For testing handling of containers.
118template <class T>
119class MyContainer {
120public:
121 MyContainer();
122
123 typedef T* iterator;
124 typedef const T* const_iterator;
125
126 T* begin();
127 T* end();
128
129 const T* cbegin();
130 const T* cend();
131
132 T& operator[](int i);
133 const T& operator[](int i) const;
134
135private:
136 T* ptr_;
137};
138
139
DeLesley Hutchinsd2f38822012-09-21 17:57:00 +0000140
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000141Mutex sls_mu;
142
143Mutex sls_mu2 __attribute__((acquired_after(sls_mu)));
144int sls_guard_var __attribute__((guarded_var)) = 0;
145int sls_guardby_var __attribute__((guarded_by(sls_mu))) = 0;
146
147bool getBool();
148
149class MutexWrapper {
150public:
151 Mutex mu;
Caitlin Sadowski194418f2011-09-14 20:00:24 +0000152 int x __attribute__((guarded_by(mu)));
DeLesley Hutchins7336b9f2013-08-15 23:06:33 +0000153 void MyLock() __attribute__((exclusive_lock_function(mu)));
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000154};
155
156MutexWrapper sls_mw;
157
158void sls_fun_0() {
159 sls_mw.mu.Lock();
DeLesley Hutchins7336b9f2013-08-15 23:06:33 +0000160 sls_mw.x = 5;
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000161 sls_mw.mu.Unlock();
162}
163
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000164void sls_fun_2() {
165 sls_mu.Lock();
166 int x = sls_guard_var;
167 sls_mu.Unlock();
168}
169
170void sls_fun_3() {
171 sls_mu.Lock();
172 sls_guard_var = 2;
173 sls_mu.Unlock();
174}
175
176void sls_fun_4() {
177 sls_mu2.Lock();
178 sls_guard_var = 2;
179 sls_mu2.Unlock();
180}
181
182void sls_fun_5() {
183 sls_mu.Lock();
184 int x = sls_guardby_var;
185 sls_mu.Unlock();
186}
187
188void sls_fun_6() {
189 sls_mu.Lock();
190 sls_guardby_var = 2;
191 sls_mu.Unlock();
192}
193
194void sls_fun_7() {
195 sls_mu.Lock();
196 sls_mu2.Lock();
197 sls_mu2.Unlock();
198 sls_mu.Unlock();
199}
200
201void sls_fun_8() {
202 sls_mu.Lock();
203 if (getBool())
204 sls_mu.Unlock();
205 else
206 sls_mu.Unlock();
207}
208
209void sls_fun_9() {
210 if (getBool())
211 sls_mu.Lock();
212 else
213 sls_mu.Lock();
214 sls_mu.Unlock();
215}
216
217void sls_fun_good_6() {
218 if (getBool()) {
219 sls_mu.Lock();
220 } else {
221 if (getBool()) {
222 getBool(); // EMPTY
223 } else {
224 getBool(); // EMPTY
225 }
226 sls_mu.Lock();
227 }
228 sls_mu.Unlock();
229}
230
231void sls_fun_good_7() {
232 sls_mu.Lock();
233 while (getBool()) {
234 sls_mu.Unlock();
235 if (getBool()) {
236 if (getBool()) {
237 sls_mu.Lock();
238 continue;
239 }
240 }
241 sls_mu.Lock();
242 }
243 sls_mu.Unlock();
244}
245
Caitlin Sadowski194418f2011-09-14 20:00:24 +0000246void sls_fun_good_8() {
247 sls_mw.MyLock();
248 sls_mw.mu.Unlock();
249}
250
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000251void sls_fun_bad_1() {
252 sls_mu.Unlock(); // \
Stephen Hines651f13c2014-04-23 16:59:28 -0700253 // expected-warning{{releasing mutex 'sls_mu' that was not held}}
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000254}
255
256void sls_fun_bad_2() {
257 sls_mu.Lock();
258 sls_mu.Lock(); // \
Stephen Hines651f13c2014-04-23 16:59:28 -0700259 // expected-warning{{acquiring mutex 'sls_mu' that is already held}}
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000260 sls_mu.Unlock();
261}
262
263void sls_fun_bad_3() {
Richard Smith2e515622012-02-03 04:45:26 +0000264 sls_mu.Lock(); // expected-note {{mutex acquired here}}
Stephen Hines651f13c2014-04-23 16:59:28 -0700265} // expected-warning{{mutex 'sls_mu' is still held at the end of function}}
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000266
267void sls_fun_bad_4() {
268 if (getBool())
DeLesley Hutchins0da44142012-06-22 17:07:28 +0000269 sls_mu.Lock(); // expected-note{{mutex acquired here}}
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000270 else
DeLesley Hutchins0da44142012-06-22 17:07:28 +0000271 sls_mu2.Lock(); // expected-note{{mutex acquired here}}
Stephen Hines651f13c2014-04-23 16:59:28 -0700272} // expected-warning{{mutex 'sls_mu' is not held on every path through here}} \
273 // expected-warning{{mutex 'sls_mu2' is not held on every path through here}}
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000274
275void sls_fun_bad_5() {
Richard Smith2e515622012-02-03 04:45:26 +0000276 sls_mu.Lock(); // expected-note {{mutex acquired here}}
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000277 if (getBool())
278 sls_mu.Unlock();
Stephen Hines651f13c2014-04-23 16:59:28 -0700279} // expected-warning{{mutex 'sls_mu' is not held on every path through here}}
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000280
281void sls_fun_bad_6() {
282 if (getBool()) {
Richard Smith2e515622012-02-03 04:45:26 +0000283 sls_mu.Lock(); // expected-note {{mutex acquired here}}
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000284 } else {
285 if (getBool()) {
286 getBool(); // EMPTY
287 } else {
288 getBool(); // EMPTY
289 }
290 }
291 sls_mu.Unlock(); // \
Stephen Hines651f13c2014-04-23 16:59:28 -0700292 expected-warning{{mutex 'sls_mu' is not held on every path through here}}\
293 expected-warning{{releasing mutex 'sls_mu' that was not held}}
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000294}
295
296void sls_fun_bad_7() {
Richard Smithaacde712012-02-03 03:30:07 +0000297 sls_mu.Lock();
Caitlin Sadowski4e4bc752011-09-15 17:25:19 +0000298 while (getBool()) {
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000299 sls_mu.Unlock();
300 if (getBool()) {
301 if (getBool()) {
Richard Smith2e515622012-02-03 04:45:26 +0000302 continue; // \
Stephen Hines651f13c2014-04-23 16:59:28 -0700303 expected-warning{{expecting mutex 'sls_mu' to be held at start of each loop}}
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000304 }
305 }
Richard Smith2e515622012-02-03 04:45:26 +0000306 sls_mu.Lock(); // expected-note {{mutex acquired here}}
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000307 }
308 sls_mu.Unlock();
309}
310
311void sls_fun_bad_8() {
Richard Smith2e515622012-02-03 04:45:26 +0000312 sls_mu.Lock(); // expected-note{{mutex acquired here}}
313
DeLesley Hutchins0da44142012-06-22 17:07:28 +0000314 do {
Stephen Hines651f13c2014-04-23 16:59:28 -0700315 sls_mu.Unlock(); // expected-warning{{expecting mutex 'sls_mu' to be held at start of each loop}}
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000316 } while (getBool());
317}
318
319void sls_fun_bad_9() {
320 do {
DeLesley Hutchins0da44142012-06-22 17:07:28 +0000321 sls_mu.Lock(); // \
Stephen Hines651f13c2014-04-23 16:59:28 -0700322 // expected-warning{{expecting mutex 'sls_mu' to be held at start of each loop}} \
Richard Smith2e515622012-02-03 04:45:26 +0000323 // expected-note{{mutex acquired here}}
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000324 } while (getBool());
325 sls_mu.Unlock();
326}
327
328void sls_fun_bad_10() {
DeLesley Hutchins0da44142012-06-22 17:07:28 +0000329 sls_mu.Lock(); // expected-note 2{{mutex acquired here}}
Stephen Hines651f13c2014-04-23 16:59:28 -0700330 while(getBool()) { // expected-warning{{expecting mutex 'sls_mu' to be held at start of each loop}}
DeLesley Hutchins0da44142012-06-22 17:07:28 +0000331 sls_mu.Unlock();
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000332 }
Stephen Hines651f13c2014-04-23 16:59:28 -0700333} // expected-warning{{mutex 'sls_mu' is still held at the end of function}}
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000334
335void sls_fun_bad_11() {
Richard Smith2e515622012-02-03 04:45:26 +0000336 while (getBool()) { // \
Stephen Hines651f13c2014-04-23 16:59:28 -0700337 expected-warning{{expecting mutex 'sls_mu' to be held at start of each loop}}
Richard Smith2e515622012-02-03 04:45:26 +0000338 sls_mu.Lock(); // expected-note {{mutex acquired here}}
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000339 }
340 sls_mu.Unlock(); // \
Stephen Hines651f13c2014-04-23 16:59:28 -0700341 // expected-warning{{releasing mutex 'sls_mu' that was not held}}
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000342}
343
Richard Smithaacde712012-02-03 03:30:07 +0000344void sls_fun_bad_12() {
Richard Smith2e515622012-02-03 04:45:26 +0000345 sls_mu.Lock(); // expected-note {{mutex acquired here}}
Richard Smithaacde712012-02-03 03:30:07 +0000346 while (getBool()) {
347 sls_mu.Unlock();
348 if (getBool()) {
349 if (getBool()) {
Stephen Hines651f13c2014-04-23 16:59:28 -0700350 break; // expected-warning{{mutex 'sls_mu' is not held on every path through here}}
Richard Smithaacde712012-02-03 03:30:07 +0000351 }
352 }
353 sls_mu.Lock();
354 }
355 sls_mu.Unlock();
356}
357
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000358//-----------------------------------------//
359// Handling lock expressions in attribute args
360// -------------------------------------------//
361
362Mutex aa_mu;
363
364class GlobalLocker {
365public:
366 void globalLock() __attribute__((exclusive_lock_function(aa_mu)));
367 void globalUnlock() __attribute__((unlock_function(aa_mu)));
368};
369
370GlobalLocker glock;
371
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000372void aa_fun_1() {
373 glock.globalLock();
374 glock.globalUnlock();
375}
376
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000377void aa_fun_bad_1() {
378 glock.globalUnlock(); // \
Stephen Hines651f13c2014-04-23 16:59:28 -0700379 // expected-warning{{releasing mutex 'aa_mu' that was not held}}
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000380}
381
382void aa_fun_bad_2() {
383 glock.globalLock();
384 glock.globalLock(); // \
Stephen Hines651f13c2014-04-23 16:59:28 -0700385 // expected-warning{{acquiring mutex 'aa_mu' that is already held}}
Caitlin Sadowski3ac1fbc2011-08-23 18:46:34 +0000386 glock.globalUnlock();
387}
388
389void aa_fun_bad_3() {
Richard Smith2e515622012-02-03 04:45:26 +0000390 glock.globalLock(); // expected-note{{mutex acquired here}}
Stephen Hines651f13c2014-04-23 16:59:28 -0700391} // expected-warning{{mutex 'aa_mu' is still held at the end of function}}
Caitlin Sadowskib4d0a962011-08-29 17:12:27 +0000392
Caitlin Sadowskib4d0a962011-08-29 17:12:27 +0000393//--------------------------------------------------//
394// Regression tests for unusual method names
395//--------------------------------------------------//
396
397Mutex wmu;
398
399// Test diagnostics for other method names.
400class WeirdMethods {
DeLesley Hutchins2f13bec2012-02-16 17:13:43 +0000401 // FIXME: can't currently check inside constructors and destructors.
Caitlin Sadowskib4d0a962011-08-29 17:12:27 +0000402 WeirdMethods() {
DeLesley Hutchins2f13bec2012-02-16 17:13:43 +0000403 wmu.Lock(); // EXPECTED-NOTE {{mutex acquired here}}
Stephen Hines651f13c2014-04-23 16:59:28 -0700404 } // EXPECTED-WARNING {{mutex 'wmu' is still held at the end of function}}
Caitlin Sadowskib4d0a962011-08-29 17:12:27 +0000405 ~WeirdMethods() {
DeLesley Hutchins2f13bec2012-02-16 17:13:43 +0000406 wmu.Lock(); // EXPECTED-NOTE {{mutex acquired here}}
Stephen Hines651f13c2014-04-23 16:59:28 -0700407 } // EXPECTED-WARNING {{mutex 'wmu' is still held at the end of function}}
Caitlin Sadowskib4d0a962011-08-29 17:12:27 +0000408 void operator++() {
Richard Smith2e515622012-02-03 04:45:26 +0000409 wmu.Lock(); // expected-note {{mutex acquired here}}
Stephen Hines651f13c2014-04-23 16:59:28 -0700410 } // expected-warning {{mutex 'wmu' is still held at the end of function}}
Caitlin Sadowskib4d0a962011-08-29 17:12:27 +0000411 operator int*() {
Richard Smith2e515622012-02-03 04:45:26 +0000412 wmu.Lock(); // expected-note {{mutex acquired here}}
Caitlin Sadowskib4d0a962011-08-29 17:12:27 +0000413 return 0;
Stephen Hines651f13c2014-04-23 16:59:28 -0700414 } // expected-warning {{mutex 'wmu' is still held at the end of function}}
Caitlin Sadowskib4d0a962011-08-29 17:12:27 +0000415};
416
Caitlin Sadowski05b436e2011-08-29 22:27:51 +0000417//-----------------------------------------------//
418// Errors for guarded by or guarded var variables
419// ----------------------------------------------//
420
421int *pgb_gvar __attribute__((pt_guarded_var));
422int *pgb_var __attribute__((pt_guarded_by(sls_mu)));
423
424class PGBFoo {
425 public:
426 int x;
427 int *pgb_field __attribute__((guarded_by(sls_mu2)))
428 __attribute__((pt_guarded_by(sls_mu)));
429 void testFoo() {
430 pgb_field = &x; // \
Stephen Hines651f13c2014-04-23 16:59:28 -0700431 // expected-warning {{writing variable 'pgb_field' requires holding mutex 'sls_mu2' exclusively}}
432 *pgb_field = x; // expected-warning {{reading variable 'pgb_field' requires holding mutex 'sls_mu2'}} \
433 // expected-warning {{writing the value pointed to by 'pgb_field' requires holding mutex 'sls_mu' exclusively}}
434 x = *pgb_field; // expected-warning {{reading variable 'pgb_field' requires holding mutex 'sls_mu2'}} \
435 // expected-warning {{reading the value pointed to by 'pgb_field' requires holding mutex 'sls_mu'}}
436 (*pgb_field)++; // expected-warning {{reading variable 'pgb_field' requires holding mutex 'sls_mu2'}} \
437 // expected-warning {{writing the value pointed to by 'pgb_field' requires holding mutex 'sls_mu' exclusively}}
Caitlin Sadowski05b436e2011-08-29 22:27:51 +0000438 }
439};
440
441class GBFoo {
442 public:
443 int gb_field __attribute__((guarded_by(sls_mu)));
444
445 void testFoo() {
446 gb_field = 0; // \
Stephen Hines651f13c2014-04-23 16:59:28 -0700447 // expected-warning {{writing variable 'gb_field' requires holding mutex 'sls_mu' exclusively}}
Caitlin Sadowski05b436e2011-08-29 22:27:51 +0000448 }
Caitlin Sadowskiaf370612011-09-08 18:35:21 +0000449
450 void testNoAnal() __attribute__((no_thread_safety_analysis)) {
451 gb_field = 0;
452 }
Caitlin Sadowski05b436e2011-08-29 22:27:51 +0000453};
454
455GBFoo GlobalGBFoo __attribute__((guarded_by(sls_mu)));
456
457void gb_fun_0() {
458 sls_mu.Lock();
459 int x = *pgb_var;
460 sls_mu.Unlock();
461}
462
463void gb_fun_1() {
464 sls_mu.Lock();
465 *pgb_var = 2;
466 sls_mu.Unlock();
467}
468
469void gb_fun_2() {
470 int x;
471 pgb_var = &x;
472}
473
474void gb_fun_3() {
475 int *x = pgb_var;
476}
477
478void gb_bad_0() {
479 sls_guard_var = 1; // \
Stephen Hines651f13c2014-04-23 16:59:28 -0700480 // expected-warning{{writing variable 'sls_guard_var' requires holding any mutex exclusively}}
Caitlin Sadowski05b436e2011-08-29 22:27:51 +0000481}
482
483void gb_bad_1() {
484 int x = sls_guard_var; // \
Stephen Hines651f13c2014-04-23 16:59:28 -0700485 // expected-warning{{reading variable 'sls_guard_var' requires holding any mutex}}
Caitlin Sadowski05b436e2011-08-29 22:27:51 +0000486}
487
488void gb_bad_2() {
489 sls_guardby_var = 1; // \
Stephen Hines651f13c2014-04-23 16:59:28 -0700490 // expected-warning {{writing variable 'sls_guardby_var' requires holding mutex 'sls_mu' exclusively}}
Caitlin Sadowski05b436e2011-08-29 22:27:51 +0000491}
492
493void gb_bad_3() {
494 int x = sls_guardby_var; // \
Stephen Hines651f13c2014-04-23 16:59:28 -0700495 // expected-warning {{reading variable 'sls_guardby_var' requires holding mutex 'sls_mu'}}
Caitlin Sadowski05b436e2011-08-29 22:27:51 +0000496}
497
498void gb_bad_4() {
499 *pgb_gvar = 1; // \
Stephen Hines651f13c2014-04-23 16:59:28 -0700500 // expected-warning {{writing the value pointed to by 'pgb_gvar' requires holding any mutex exclusively}}
Caitlin Sadowski05b436e2011-08-29 22:27:51 +0000501}
502
503void gb_bad_5() {
504 int x = *pgb_gvar; // \
Stephen Hines651f13c2014-04-23 16:59:28 -0700505 // expected-warning {{reading the value pointed to by 'pgb_gvar' requires holding any mutex}}
Caitlin Sadowski05b436e2011-08-29 22:27:51 +0000506}
507
508void gb_bad_6() {
509 *pgb_var = 1; // \
Stephen Hines651f13c2014-04-23 16:59:28 -0700510 // expected-warning {{writing the value pointed to by 'pgb_var' requires holding mutex 'sls_mu' exclusively}}
Caitlin Sadowski05b436e2011-08-29 22:27:51 +0000511}
512
513void gb_bad_7() {
514 int x = *pgb_var; // \
Stephen Hines651f13c2014-04-23 16:59:28 -0700515 // expected-warning {{reading the value pointed to by 'pgb_var' requires holding mutex 'sls_mu'}}
Caitlin Sadowski05b436e2011-08-29 22:27:51 +0000516}
517
518void gb_bad_8() {
519 GBFoo G;
520 G.gb_field = 0; // \
Stephen Hines651f13c2014-04-23 16:59:28 -0700521 // expected-warning {{writing variable 'gb_field' requires holding mutex 'sls_mu'}}
Caitlin Sadowski05b436e2011-08-29 22:27:51 +0000522}
523
524void gb_bad_9() {
525 sls_guard_var++; // \
Stephen Hines651f13c2014-04-23 16:59:28 -0700526 // expected-warning{{writing variable 'sls_guard_var' requires holding any mutex exclusively}}
Caitlin Sadowski05b436e2011-08-29 22:27:51 +0000527 sls_guard_var--; // \
Stephen Hines651f13c2014-04-23 16:59:28 -0700528 // expected-warning{{writing variable 'sls_guard_var' requires holding any mutex exclusively}}
Caitlin Sadowski05b436e2011-08-29 22:27:51 +0000529 ++sls_guard_var; // \
Stephen Hines651f13c2014-04-23 16:59:28 -0700530 // expected-warning{{writing variable 'sls_guard_var' requires holding any mutex exclusively}}
Caitlin Sadowskia49d1d82011-09-09 16:07:55 +0000531 --sls_guard_var;// \
Stephen Hines651f13c2014-04-23 16:59:28 -0700532 // expected-warning{{writing variable 'sls_guard_var' requires holding any mutex exclusively}}
Caitlin Sadowski05b436e2011-08-29 22:27:51 +0000533}
Caitlin Sadowskib4d0a962011-08-29 17:12:27 +0000534
Caitlin Sadowskieff98fc2011-09-08 17:42:22 +0000535//-----------------------------------------------//
536// Warnings on variables with late parsed attributes
537// ----------------------------------------------//
538
539class LateFoo {
540public:
541 int a __attribute__((guarded_by(mu)));
542 int b;
543
544 void foo() __attribute__((exclusive_locks_required(mu))) { }
545
546 void test() {
547 a = 0; // \
Stephen Hines651f13c2014-04-23 16:59:28 -0700548 // expected-warning{{writing variable 'a' requires holding mutex 'mu' exclusively}}
Caitlin Sadowskieff98fc2011-09-08 17:42:22 +0000549 b = a; // \
Stephen Hines651f13c2014-04-23 16:59:28 -0700550 // expected-warning {{reading variable 'a' requires holding mutex 'mu'}}
Caitlin Sadowskieff98fc2011-09-08 17:42:22 +0000551 c = 0; // \
Stephen Hines651f13c2014-04-23 16:59:28 -0700552 // expected-warning {{writing variable 'c' requires holding mutex 'mu' exclusively}}
Caitlin Sadowskieff98fc2011-09-08 17:42:22 +0000553 }
554
555 int c __attribute__((guarded_by(mu)));
556
557 Mutex mu;
558};
559
Caitlin Sadowski99107eb2011-09-09 16:21:55 +0000560class LateBar {
561 public:
562 int a_ __attribute__((guarded_by(mu1_)));
563 int b_;
564 int *q __attribute__((pt_guarded_by(mu)));
565 Mutex mu1_;
566 Mutex mu;
567 LateFoo Foo;
568 LateFoo Foo2;
569 LateFoo *FooPointer;
570};
571
572LateBar b1, *b3;
573
574void late_0() {
575 LateFoo FooA;
576 LateFoo FooB;
577 FooA.mu.Lock();
578 FooA.a = 5;
579 FooA.mu.Unlock();
580}
581
582void late_1() {
583 LateBar BarA;
584 BarA.FooPointer->mu.Lock();
585 BarA.FooPointer->a = 2;
586 BarA.FooPointer->mu.Unlock();
587}
588
589void late_bad_0() {
590 LateFoo fooA;
591 LateFoo fooB;
592 fooA.mu.Lock();
593 fooB.a = 5; // \
Stephen Hines651f13c2014-04-23 16:59:28 -0700594 // expected-warning{{writing variable 'a' requires holding mutex 'fooB.mu' exclusively}} \
DeLesley Hutchins3f0ec522012-09-10 19:58:23 +0000595 // expected-note{{found near match 'fooA.mu'}}
Caitlin Sadowski99107eb2011-09-09 16:21:55 +0000596 fooA.mu.Unlock();
597}
598
599void late_bad_1() {
600 Mutex mu;
601 mu.Lock();
602 b1.mu1_.Lock();
603 int res = b1.a_ + b3->b_;
604 b3->b_ = *b1.q; // \
Stephen Hines651f13c2014-04-23 16:59:28 -0700605 // expected-warning{{reading the value pointed to by 'q' requires holding mutex 'b1.mu'}}
Caitlin Sadowski99107eb2011-09-09 16:21:55 +0000606 b1.mu1_.Unlock();
607 b1.b_ = res;
608 mu.Unlock();
609}
610
611void late_bad_2() {
612 LateBar BarA;
613 BarA.FooPointer->mu.Lock();
614 BarA.Foo.a = 2; // \
Stephen Hines651f13c2014-04-23 16:59:28 -0700615 // expected-warning{{writing variable 'a' requires holding mutex 'BarA.Foo.mu' exclusively}} \
DeLesley Hutchins3f0ec522012-09-10 19:58:23 +0000616 // expected-note{{found near match 'BarA.FooPointer->mu'}}
Caitlin Sadowski99107eb2011-09-09 16:21:55 +0000617 BarA.FooPointer->mu.Unlock();
618}
619
620void late_bad_3() {
621 LateBar BarA;
622 BarA.Foo.mu.Lock();
623 BarA.FooPointer->a = 2; // \
Stephen Hines651f13c2014-04-23 16:59:28 -0700624 // expected-warning{{writing variable 'a' requires holding mutex 'BarA.FooPointer->mu' exclusively}} \
DeLesley Hutchins3f0ec522012-09-10 19:58:23 +0000625 // expected-note{{found near match 'BarA.Foo.mu'}}
Caitlin Sadowski99107eb2011-09-09 16:21:55 +0000626 BarA.Foo.mu.Unlock();
627}
628
629void late_bad_4() {
630 LateBar BarA;
631 BarA.Foo.mu.Lock();
632 BarA.Foo2.a = 2; // \
Stephen Hines651f13c2014-04-23 16:59:28 -0700633 // expected-warning{{writing variable 'a' requires holding mutex 'BarA.Foo2.mu' exclusively}} \
DeLesley Hutchins3f0ec522012-09-10 19:58:23 +0000634 // expected-note{{found near match 'BarA.Foo.mu'}}
Caitlin Sadowski99107eb2011-09-09 16:21:55 +0000635 BarA.Foo.mu.Unlock();
636}
637
Caitlin Sadowskia53257c2011-09-08 18:19:38 +0000638//-----------------------------------------------//
639// Extra warnings for shared vs. exclusive locks
640// ----------------------------------------------//
641
642void shared_fun_0() {
643 sls_mu.Lock();
644 do {
645 sls_mu.Unlock();
646 sls_mu.Lock();
647 } while (getBool());
648 sls_mu.Unlock();
649}
650
651void shared_fun_1() {
Caitlin Sadowski4e4bc752011-09-15 17:25:19 +0000652 sls_mu.ReaderLock(); // \
Stephen Hines651f13c2014-04-23 16:59:28 -0700653 // expected-warning {{mutex 'sls_mu' is acquired exclusively and shared in the same scope}}
Caitlin Sadowskia53257c2011-09-08 18:19:38 +0000654 do {
655 sls_mu.Unlock();
Caitlin Sadowski4e4bc752011-09-15 17:25:19 +0000656 sls_mu.Lock(); // \
Stephen Hines651f13c2014-04-23 16:59:28 -0700657 // expected-note {{the other acquisition of mutex 'sls_mu' is here}}
Caitlin Sadowskia53257c2011-09-08 18:19:38 +0000658 } while (getBool());
659 sls_mu.Unlock();
660}
661
662void shared_fun_3() {
663 if (getBool())
664 sls_mu.Lock();
665 else
666 sls_mu.Lock();
667 *pgb_var = 1;
668 sls_mu.Unlock();
669}
670
671void shared_fun_4() {
672 if (getBool())
673 sls_mu.ReaderLock();
674 else
675 sls_mu.ReaderLock();
676 int x = sls_guardby_var;
677 sls_mu.Unlock();
678}
679
680void shared_fun_8() {
681 if (getBool())
682 sls_mu.Lock(); // \
Stephen Hines651f13c2014-04-23 16:59:28 -0700683 // expected-warning {{mutex 'sls_mu' is acquired exclusively and shared in the same scope}}
Caitlin Sadowskia53257c2011-09-08 18:19:38 +0000684 else
685 sls_mu.ReaderLock(); // \
Stephen Hines651f13c2014-04-23 16:59:28 -0700686 // expected-note {{the other acquisition of mutex 'sls_mu' is here}}
Caitlin Sadowskia53257c2011-09-08 18:19:38 +0000687 sls_mu.Unlock();
688}
689
690void shared_bad_0() {
Caitlin Sadowski4e4bc752011-09-15 17:25:19 +0000691 sls_mu.Lock(); // \
Stephen Hines651f13c2014-04-23 16:59:28 -0700692 // expected-warning {{mutex 'sls_mu' is acquired exclusively and shared in the same scope}}
Caitlin Sadowskia53257c2011-09-08 18:19:38 +0000693 do {
694 sls_mu.Unlock();
Caitlin Sadowski4e4bc752011-09-15 17:25:19 +0000695 sls_mu.ReaderLock(); // \
Stephen Hines651f13c2014-04-23 16:59:28 -0700696 // expected-note {{the other acquisition of mutex 'sls_mu' is here}}
Caitlin Sadowskia53257c2011-09-08 18:19:38 +0000697 } while (getBool());
698 sls_mu.Unlock();
699}
700
701void shared_bad_1() {
702 if (getBool())
703 sls_mu.Lock(); // \
Stephen Hines651f13c2014-04-23 16:59:28 -0700704 // expected-warning {{mutex 'sls_mu' is acquired exclusively and shared in the same scope}}
Caitlin Sadowskia53257c2011-09-08 18:19:38 +0000705 else
706 sls_mu.ReaderLock(); // \
Stephen Hines651f13c2014-04-23 16:59:28 -0700707 // expected-note {{the other acquisition of mutex 'sls_mu' is here}}
Caitlin Sadowskia53257c2011-09-08 18:19:38 +0000708 *pgb_var = 1;
709 sls_mu.Unlock();
710}
711
712void shared_bad_2() {
713 if (getBool())
714 sls_mu.ReaderLock(); // \
Stephen Hines651f13c2014-04-23 16:59:28 -0700715 // expected-warning {{mutex 'sls_mu' is acquired exclusively and shared in the same scope}}
Caitlin Sadowskia53257c2011-09-08 18:19:38 +0000716 else
717 sls_mu.Lock(); // \
Stephen Hines651f13c2014-04-23 16:59:28 -0700718 // expected-note {{the other acquisition of mutex 'sls_mu' is here}}
Caitlin Sadowskia53257c2011-09-08 18:19:38 +0000719 *pgb_var = 1;
720 sls_mu.Unlock();
721}
Caitlin Sadowski978191e2011-09-08 18:27:31 +0000722
723// FIXME: Add support for functions (not only methods)
724class LRBar {
725 public:
726 void aa_elr_fun() __attribute__((exclusive_locks_required(aa_mu)));
727 void aa_elr_fun_s() __attribute__((shared_locks_required(aa_mu)));
728 void le_fun() __attribute__((locks_excluded(sls_mu)));
729};
730
731class LRFoo {
732 public:
733 void test() __attribute__((exclusive_locks_required(sls_mu)));
734 void testShared() __attribute__((shared_locks_required(sls_mu2)));
735};
736
737void elr_fun() __attribute__((exclusive_locks_required(sls_mu)));
738void elr_fun() {}
739
740LRFoo MyLRFoo;
741LRBar Bar;
742
743void es_fun_0() {
744 aa_mu.Lock();
745 Bar.aa_elr_fun();
746 aa_mu.Unlock();
747}
748
749void es_fun_1() {
750 aa_mu.Lock();
751 Bar.aa_elr_fun_s();
752 aa_mu.Unlock();
753}
754
755void es_fun_2() {
756 aa_mu.ReaderLock();
757 Bar.aa_elr_fun_s();
758 aa_mu.Unlock();
759}
760
761void es_fun_3() {
762 sls_mu.Lock();
763 MyLRFoo.test();
764 sls_mu.Unlock();
765}
766
767void es_fun_4() {
768 sls_mu2.Lock();
769 MyLRFoo.testShared();
770 sls_mu2.Unlock();
771}
772
773void es_fun_5() {
774 sls_mu2.ReaderLock();
775 MyLRFoo.testShared();
776 sls_mu2.Unlock();
777}
778
779void es_fun_6() {
780 Bar.le_fun();
781}
782
783void es_fun_7() {
784 sls_mu.Lock();
785 elr_fun();
786 sls_mu.Unlock();
787}
788
Caitlin Sadowskiaf370612011-09-08 18:35:21 +0000789void es_fun_8() __attribute__((no_thread_safety_analysis));
790
791void es_fun_8() {
792 Bar.aa_elr_fun_s();
793}
794
Caitlin Sadowskicb967512011-09-15 17:43:08 +0000795void es_fun_9() __attribute__((shared_locks_required(aa_mu)));
796void es_fun_9() {
797 Bar.aa_elr_fun_s();
798}
799
800void es_fun_10() __attribute__((exclusive_locks_required(aa_mu)));
801void es_fun_10() {
802 Bar.aa_elr_fun_s();
803}
804
Caitlin Sadowski978191e2011-09-08 18:27:31 +0000805void es_bad_0() {
806 Bar.aa_elr_fun(); // \
Stephen Hines651f13c2014-04-23 16:59:28 -0700807 // expected-warning {{calling function 'aa_elr_fun' requires holding mutex 'aa_mu' exclusively}}
Caitlin Sadowski978191e2011-09-08 18:27:31 +0000808}
809
810void es_bad_1() {
811 aa_mu.ReaderLock();
812 Bar.aa_elr_fun(); // \
Stephen Hines651f13c2014-04-23 16:59:28 -0700813 // expected-warning {{calling function 'aa_elr_fun' requires holding mutex 'aa_mu' exclusively}}
Caitlin Sadowski978191e2011-09-08 18:27:31 +0000814 aa_mu.Unlock();
815}
816
817void es_bad_2() {
818 Bar.aa_elr_fun_s(); // \
Stephen Hines651f13c2014-04-23 16:59:28 -0700819 // expected-warning {{calling function 'aa_elr_fun_s' requires holding mutex 'aa_mu'}}
Caitlin Sadowski978191e2011-09-08 18:27:31 +0000820}
821
822void es_bad_3() {
823 MyLRFoo.test(); // \
Stephen Hines651f13c2014-04-23 16:59:28 -0700824 // expected-warning {{calling function 'test' requires holding mutex 'sls_mu' exclusively}}
Caitlin Sadowski978191e2011-09-08 18:27:31 +0000825}
826
827void es_bad_4() {
828 MyLRFoo.testShared(); // \
Stephen Hines651f13c2014-04-23 16:59:28 -0700829 // expected-warning {{calling function 'testShared' requires holding mutex 'sls_mu2'}}
Caitlin Sadowski978191e2011-09-08 18:27:31 +0000830}
831
832void es_bad_5() {
833 sls_mu.ReaderLock();
834 MyLRFoo.test(); // \
Stephen Hines651f13c2014-04-23 16:59:28 -0700835 // expected-warning {{calling function 'test' requires holding mutex 'sls_mu' exclusively}}
Caitlin Sadowski978191e2011-09-08 18:27:31 +0000836 sls_mu.Unlock();
837}
838
839void es_bad_6() {
840 sls_mu.Lock();
841 Bar.le_fun(); // \
Stephen Hines651f13c2014-04-23 16:59:28 -0700842 // expected-warning {{cannot call function 'le_fun' while mutex 'sls_mu' is held}}
Caitlin Sadowski978191e2011-09-08 18:27:31 +0000843 sls_mu.Unlock();
844}
845
846void es_bad_7() {
847 sls_mu.ReaderLock();
848 Bar.le_fun(); // \
Stephen Hines651f13c2014-04-23 16:59:28 -0700849 // expected-warning {{cannot call function 'le_fun' while mutex 'sls_mu' is held}}
Caitlin Sadowski978191e2011-09-08 18:27:31 +0000850 sls_mu.Unlock();
851}
Caitlin Sadowski194418f2011-09-14 20:00:24 +0000852
DeLesley Hutchins81216392011-10-17 21:38:02 +0000853
Caitlin Sadowski194418f2011-09-14 20:00:24 +0000854//-----------------------------------------------//
855// Unparseable lock expressions
856// ----------------------------------------------//
857
DeLesley Hutchins0d95dfc2012-03-02 23:36:05 +0000858// FIXME -- derive new tests for unhandled expressions
Caitlin Sadowski194418f2011-09-14 20:00:24 +0000859
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +0000860
861//----------------------------------------------------------------------------//
862// The following test cases are ported from the gcc thread safety implementation
863// They are each wrapped inside a namespace with the test number of the gcc test
864//
865// FIXME: add all the gcc tests, once this analysis passes them.
866//----------------------------------------------------------------------------//
867
868//-----------------------------------------//
869// Good testcases (no errors)
870//-----------------------------------------//
871
872namespace thread_annot_lock_20 {
873class Bar {
874 public:
875 static int func1() EXCLUSIVE_LOCKS_REQUIRED(mu1_);
876 static int b_ GUARDED_BY(mu1_);
877 static Mutex mu1_;
878 static int a_ GUARDED_BY(mu1_);
879};
880
881Bar b1;
882
883int Bar::func1()
884{
885 int res = 5;
886
887 if (a_ == 4)
888 res = b_;
889 return res;
890}
891} // end namespace thread_annot_lock_20
892
893namespace thread_annot_lock_22 {
894// Test various usage of GUARDED_BY and PT_GUARDED_BY annotations, especially
895// uses in class definitions.
896Mutex mu;
897
898class Bar {
899 public:
900 int a_ GUARDED_BY(mu1_);
901 int b_;
902 int *q PT_GUARDED_BY(mu);
903 Mutex mu1_ ACQUIRED_AFTER(mu);
904};
905
906Bar b1, *b3;
907int *p GUARDED_BY(mu) PT_GUARDED_BY(mu);
908int res GUARDED_BY(mu) = 5;
909
910int func(int i)
911{
912 int x;
913 mu.Lock();
914 b1.mu1_.Lock();
915 res = b1.a_ + b3->b_;
916 *p = i;
917 b1.a_ = res + b3->b_;
918 b3->b_ = *b1.q;
919 b1.mu1_.Unlock();
920 b1.b_ = res;
921 x = res;
922 mu.Unlock();
923 return x;
924}
925} // end namespace thread_annot_lock_22
926
927namespace thread_annot_lock_27_modified {
928// test lock annotations applied to function definitions
929// Modified: applied annotations only to function declarations
930Mutex mu1;
931Mutex mu2 ACQUIRED_AFTER(mu1);
932
933class Foo {
934 public:
935 int method1(int i) SHARED_LOCKS_REQUIRED(mu2) EXCLUSIVE_LOCKS_REQUIRED(mu1);
936};
937
938int Foo::method1(int i) {
939 return i;
940}
941
942
943int foo(int i) EXCLUSIVE_LOCKS_REQUIRED(mu2) SHARED_LOCKS_REQUIRED(mu1);
944int foo(int i) {
945 return i;
946}
947
948static int bar(int i) EXCLUSIVE_LOCKS_REQUIRED(mu1);
949static int bar(int i) {
950 return i;
951}
952
953void main() {
954 Foo a;
955
956 mu1.Lock();
957 mu2.Lock();
958 a.method1(1);
959 foo(2);
960 mu2.Unlock();
961 bar(3);
962 mu1.Unlock();
963}
964} // end namespace thread_annot_lock_27_modified
965
966
967namespace thread_annot_lock_38 {
968// Test the case where a template member function is annotated with lock
969// attributes in a non-template class.
970class Foo {
971 public:
972 void func1(int y) LOCKS_EXCLUDED(mu_);
973 template <typename T> void func2(T x) LOCKS_EXCLUDED(mu_);
974 private:
975 Mutex mu_;
976};
977
978Foo *foo;
979
980void main()
981{
982 foo->func1(5);
983 foo->func2(5);
984}
985} // end namespace thread_annot_lock_38
986
987namespace thread_annot_lock_43 {
988// Tests lock canonicalization
989class Foo {
990 public:
991 Mutex *mu_;
992};
993
994class FooBar {
995 public:
996 Foo *foo_;
997 int GetA() EXCLUSIVE_LOCKS_REQUIRED(foo_->mu_) { return a_; }
998 int a_ GUARDED_BY(foo_->mu_);
999};
1000
1001FooBar *fb;
1002
1003void main()
1004{
1005 int x;
1006 fb->foo_->mu_->Lock();
1007 x = fb->GetA();
1008 fb->foo_->mu_->Unlock();
1009}
1010} // end namespace thread_annot_lock_43
1011
1012namespace thread_annot_lock_49 {
1013// Test the support for use of lock expression in the annotations
1014class Foo {
1015 public:
1016 Mutex foo_mu_;
1017};
1018
1019class Bar {
1020 private:
1021 Foo *foo;
1022 Mutex bar_mu_ ACQUIRED_AFTER(foo->foo_mu_);
1023
1024 public:
1025 void Test1() {
1026 foo->foo_mu_.Lock();
1027 bar_mu_.Lock();
1028 bar_mu_.Unlock();
1029 foo->foo_mu_.Unlock();
1030 }
1031};
1032
1033void main() {
1034 Bar bar;
1035 bar.Test1();
1036}
1037} // end namespace thread_annot_lock_49
1038
1039namespace thread_annot_lock_61_modified {
1040 // Modified to fix the compiler errors
1041 // Test the fix for a bug introduced by the support of pass-by-reference
1042 // paramters.
1043 struct Foo { Foo &operator<< (bool) {return *this;} };
1044 Foo &getFoo();
1045 struct Bar { Foo &func () {return getFoo();} };
1046 struct Bas { void operator& (Foo &) {} };
1047 void mumble()
1048 {
1049 Bas() & Bar().func() << "" << "";
1050 Bas() & Bar().func() << "";
1051 }
1052} // end namespace thread_annot_lock_61_modified
1053
1054
1055namespace thread_annot_lock_65 {
1056// Test the fix for a bug in the support of allowing reader locks for
1057// non-const, non-modifying overload functions. (We didn't handle the builtin
1058// properly.)
1059enum MyFlags {
1060 Zero,
1061 One,
1062 Two,
1063 Three,
1064 Four,
1065 Five,
1066 Six,
1067 Seven,
1068 Eight,
1069 Nine
1070};
1071
1072inline MyFlags
1073operator|(MyFlags a, MyFlags b)
1074{
1075 return MyFlags(static_cast<int>(a) | static_cast<int>(b));
1076}
1077
1078inline MyFlags&
1079operator|=(MyFlags& a, MyFlags b)
1080{
1081 return a = a | b;
1082}
1083} // end namespace thread_annot_lock_65
1084
1085namespace thread_annot_lock_66_modified {
1086// Modified: Moved annotation to function defn
1087// Test annotations on out-of-line definitions of member functions where the
1088// annotations refer to locks that are also data members in the class.
1089Mutex mu;
1090
1091class Foo {
1092 public:
1093 int method1(int i) SHARED_LOCKS_REQUIRED(mu1, mu, mu2);
1094 int data GUARDED_BY(mu1);
1095 Mutex *mu1;
1096 Mutex *mu2;
1097};
1098
1099int Foo::method1(int i)
1100{
1101 return data + i;
1102}
1103
1104void main()
1105{
1106 Foo a;
1107
1108 a.mu2->Lock();
1109 a.mu1->Lock();
1110 mu.Lock();
1111 a.method1(1);
1112 mu.Unlock();
1113 a.mu1->Unlock();
1114 a.mu2->Unlock();
1115}
1116} // end namespace thread_annot_lock_66_modified
1117
1118namespace thread_annot_lock_68_modified {
1119// Test a fix to a bug in the delayed name binding with nested template
1120// instantiation. We use a stack to make sure a name is not resolved to an
1121// inner context.
1122template <typename T>
1123class Bar {
1124 Mutex mu_;
1125};
1126
1127template <typename T>
1128class Foo {
1129 public:
1130 void func(T x) {
1131 mu_.Lock();
DeLesley Hutchins23323e02012-01-20 22:50:54 +00001132 count_ = x;
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001133 mu_.Unlock();
1134 }
1135
1136 private:
DeLesley Hutchins23323e02012-01-20 22:50:54 +00001137 T count_ GUARDED_BY(mu_);
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001138 Bar<T> bar_;
1139 Mutex mu_;
1140};
1141
1142void main()
1143{
1144 Foo<int> *foo;
1145 foo->func(5);
1146}
1147} // end namespace thread_annot_lock_68_modified
1148
1149namespace thread_annot_lock_30_modified {
1150// Test delay parsing of lock attribute arguments with nested classes.
1151// Modified: trylocks replaced with exclusive_lock_fun
1152int a = 0;
1153
1154class Bar {
1155 struct Foo;
1156
1157 public:
1158 void MyLock() EXCLUSIVE_LOCK_FUNCTION(mu);
1159
1160 int func() {
1161 MyLock();
1162// if (foo == 0) {
1163// return 0;
1164// }
1165 a = 5;
1166 mu.Unlock();
1167 return 1;
1168 }
1169
1170 class FooBar {
1171 int x;
1172 int y;
1173 };
1174
1175 private:
1176 Mutex mu;
1177};
1178
1179Bar *bar;
1180
1181void main()
1182{
1183 bar->func();
1184}
1185} // end namespace thread_annot_lock_30_modified
1186
1187namespace thread_annot_lock_47 {
1188// Test the support for annotations on virtual functions.
1189// This is a good test case. (i.e. There should be no warning emitted by the
1190// compiler.)
1191class Base {
1192 public:
1193 virtual void func1() EXCLUSIVE_LOCKS_REQUIRED(mu_);
1194 virtual void func2() LOCKS_EXCLUDED(mu_);
1195 Mutex mu_;
1196};
1197
1198class Child : public Base {
1199 public:
1200 virtual void func1() EXCLUSIVE_LOCKS_REQUIRED(mu_);
1201 virtual void func2() LOCKS_EXCLUDED(mu_);
1202};
1203
1204void main() {
1205 Child *c;
1206 Base *b = c;
1207
1208 b->mu_.Lock();
1209 b->func1();
1210 b->mu_.Unlock();
1211 b->func2();
1212
1213 c->mu_.Lock();
1214 c->func1();
1215 c->mu_.Unlock();
1216 c->func2();
1217}
1218} // end namespace thread_annot_lock_47
1219
1220//-----------------------------------------//
1221// Tests which produce errors
1222//-----------------------------------------//
1223
1224namespace thread_annot_lock_13 {
1225Mutex mu1;
1226Mutex mu2;
1227
1228int g GUARDED_BY(mu1);
1229int w GUARDED_BY(mu2);
1230
1231class Foo {
1232 public:
1233 void bar() LOCKS_EXCLUDED(mu_, mu1);
1234 int foo() SHARED_LOCKS_REQUIRED(mu_) EXCLUSIVE_LOCKS_REQUIRED(mu2);
1235
1236 private:
1237 int a_ GUARDED_BY(mu_);
1238 public:
1239 Mutex mu_ ACQUIRED_AFTER(mu1);
1240};
1241
1242int Foo::foo()
1243{
1244 int res;
David Blaikiee31b8fb2012-04-05 00:16:44 +00001245 w = 5;
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001246 res = a_ + 5;
1247 return res;
1248}
1249
1250void Foo::bar()
1251{
1252 int x;
1253 mu_.Lock();
Stephen Hines651f13c2014-04-23 16:59:28 -07001254 x = foo(); // expected-warning {{calling function 'foo' requires holding mutex 'mu2' exclusively}}
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001255 a_ = x + 1;
1256 mu_.Unlock();
1257 if (x > 5) {
1258 mu1.Lock();
David Blaikiee31b8fb2012-04-05 00:16:44 +00001259 g = 2;
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001260 mu1.Unlock();
1261 }
1262}
1263
1264void main()
1265{
1266 Foo f1, *f2;
1267 f1.mu_.Lock();
Stephen Hines651f13c2014-04-23 16:59:28 -07001268 f1.bar(); // expected-warning {{cannot call function 'bar' while mutex 'f1.mu_' is held}}
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001269 mu2.Lock();
1270 f1.foo();
1271 mu2.Unlock();
1272 f1.mu_.Unlock();
1273 f2->mu_.Lock();
Stephen Hines651f13c2014-04-23 16:59:28 -07001274 f2->bar(); // expected-warning {{cannot call function 'bar' while mutex 'f2->mu_' is held}}
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001275 f2->mu_.Unlock();
1276 mu2.Lock();
David Blaikiee31b8fb2012-04-05 00:16:44 +00001277 w = 2;
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001278 mu2.Unlock();
1279}
1280} // end namespace thread_annot_lock_13
1281
1282namespace thread_annot_lock_18_modified {
1283// Modified: Trylocks removed
1284// Test the ability to distnguish between the same lock field of
1285// different objects of a class.
1286 class Bar {
1287 public:
1288 bool MyLock() EXCLUSIVE_LOCK_FUNCTION(mu1_);
1289 void MyUnlock() UNLOCK_FUNCTION(mu1_);
1290 int a_ GUARDED_BY(mu1_);
1291
1292 private:
1293 Mutex mu1_;
1294};
1295
1296Bar *b1, *b2;
1297
1298void func()
1299{
1300 b1->MyLock();
1301 b1->a_ = 5;
DeLesley Hutchins3f0ec522012-09-10 19:58:23 +00001302 b2->a_ = 3; // \
Stephen Hines651f13c2014-04-23 16:59:28 -07001303 // expected-warning {{writing variable 'a_' requires holding mutex 'b2->mu1_' exclusively}} \
DeLesley Hutchins3f0ec522012-09-10 19:58:23 +00001304 // expected-note {{found near match 'b1->mu1_'}}
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001305 b2->MyLock();
1306 b2->MyUnlock();
1307 b1->MyUnlock();
1308}
1309} // end namespace thread_annot_lock_18_modified
1310
1311namespace thread_annot_lock_21 {
1312// Test various usage of GUARDED_BY and PT_GUARDED_BY annotations, especially
1313// uses in class definitions.
1314Mutex mu;
1315
1316class Bar {
1317 public:
1318 int a_ GUARDED_BY(mu1_);
1319 int b_;
1320 int *q PT_GUARDED_BY(mu);
1321 Mutex mu1_ ACQUIRED_AFTER(mu);
1322};
1323
1324Bar b1, *b3;
1325int *p GUARDED_BY(mu) PT_GUARDED_BY(mu);
1326
1327int res GUARDED_BY(mu) = 5;
1328
1329int func(int i)
1330{
1331 int x;
1332 b3->mu1_.Lock();
Stephen Hines651f13c2014-04-23 16:59:28 -07001333 res = b1.a_ + b3->b_; // expected-warning {{reading variable 'a_' requires holding mutex 'b1.mu1_'}} \
1334 // expected-warning {{writing variable 'res' requires holding mutex 'mu' exclusively}} \
DeLesley Hutchins3f0ec522012-09-10 19:58:23 +00001335 // expected-note {{found near match 'b3->mu1_'}}
Stephen Hines651f13c2014-04-23 16:59:28 -07001336 *p = i; // expected-warning {{reading variable 'p' requires holding mutex 'mu'}} \
1337 // expected-warning {{writing the value pointed to by 'p' requires holding mutex 'mu' exclusively}}
1338 b1.a_ = res + b3->b_; // expected-warning {{reading variable 'res' requires holding mutex 'mu'}} \
1339 // expected-warning {{writing variable 'a_' requires holding mutex 'b1.mu1_' exclusively}} \
DeLesley Hutchins3f0ec522012-09-10 19:58:23 +00001340 // expected-note {{found near match 'b3->mu1_'}}
Stephen Hines651f13c2014-04-23 16:59:28 -07001341 b3->b_ = *b1.q; // expected-warning {{reading the value pointed to by 'q' requires holding mutex 'mu'}}
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001342 b3->mu1_.Unlock();
Stephen Hines651f13c2014-04-23 16:59:28 -07001343 b1.b_ = res; // expected-warning {{reading variable 'res' requires holding mutex 'mu'}}
1344 x = res; // expected-warning {{reading variable 'res' requires holding mutex 'mu'}}
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001345 return x;
1346}
1347} // end namespace thread_annot_lock_21
1348
1349namespace thread_annot_lock_35_modified {
1350// Test the analyzer's ability to distinguish the lock field of different
1351// objects.
1352class Foo {
1353 private:
1354 Mutex lock_;
1355 int a_ GUARDED_BY(lock_);
1356
1357 public:
1358 void Func(Foo* child) LOCKS_EXCLUDED(lock_) {
1359 Foo *new_foo = new Foo;
1360
1361 lock_.Lock();
1362
1363 child->Func(new_foo); // There shouldn't be any warning here as the
1364 // acquired lock is not in child.
DeLesley Hutchins3f0ec522012-09-10 19:58:23 +00001365 child->bar(7); // \
Stephen Hines651f13c2014-04-23 16:59:28 -07001366 // expected-warning {{calling function 'bar' requires holding mutex 'child->lock_' exclusively}} \
DeLesley Hutchins3f0ec522012-09-10 19:58:23 +00001367 // expected-note {{found near match 'lock_'}}
1368 child->a_ = 5; // \
Stephen Hines651f13c2014-04-23 16:59:28 -07001369 // expected-warning {{writing variable 'a_' requires holding mutex 'child->lock_' exclusively}} \
DeLesley Hutchins3f0ec522012-09-10 19:58:23 +00001370 // expected-note {{found near match 'lock_'}}
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001371 lock_.Unlock();
1372 }
1373
1374 void bar(int y) EXCLUSIVE_LOCKS_REQUIRED(lock_) {
1375 a_ = y;
1376 }
1377};
1378
1379Foo *x;
1380
1381void main() {
1382 Foo *child = new Foo;
1383 x->Func(child);
1384}
1385} // end namespace thread_annot_lock_35_modified
1386
1387namespace thread_annot_lock_36_modified {
1388// Modified to move the annotations to function defns.
1389// Test the analyzer's ability to distinguish the lock field of different
1390// objects
1391class Foo {
1392 private:
1393 Mutex lock_;
1394 int a_ GUARDED_BY(lock_);
1395
1396 public:
1397 void Func(Foo* child) LOCKS_EXCLUDED(lock_);
1398 void bar(int y) EXCLUSIVE_LOCKS_REQUIRED(lock_);
1399};
1400
1401void Foo::Func(Foo* child) {
1402 Foo *new_foo = new Foo;
1403
1404 lock_.Lock();
1405
1406 child->lock_.Lock();
Stephen Hines651f13c2014-04-23 16:59:28 -07001407 child->Func(new_foo); // expected-warning {{cannot call function 'Func' while mutex 'child->lock_' is held}}
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001408 child->bar(7);
1409 child->a_ = 5;
1410 child->lock_.Unlock();
1411
1412 lock_.Unlock();
1413}
1414
1415void Foo::bar(int y) {
1416 a_ = y;
1417}
1418
1419
1420Foo *x;
1421
1422void main() {
1423 Foo *child = new Foo;
1424 x->Func(child);
1425}
1426} // end namespace thread_annot_lock_36_modified
1427
1428
1429namespace thread_annot_lock_42 {
1430// Test support of multiple lock attributes of the same kind on a decl.
1431class Foo {
1432 private:
1433 Mutex mu1, mu2, mu3;
1434 int x GUARDED_BY(mu1) GUARDED_BY(mu2);
1435 int y GUARDED_BY(mu2);
1436
1437 void f2() LOCKS_EXCLUDED(mu1) LOCKS_EXCLUDED(mu2) LOCKS_EXCLUDED(mu3) {
1438 mu2.Lock();
1439 y = 2;
1440 mu2.Unlock();
1441 }
1442
1443 public:
1444 void f1() EXCLUSIVE_LOCKS_REQUIRED(mu2) EXCLUSIVE_LOCKS_REQUIRED(mu1) {
1445 x = 5;
Stephen Hines651f13c2014-04-23 16:59:28 -07001446 f2(); // expected-warning {{cannot call function 'f2' while mutex 'mu1' is held}} \
1447 // expected-warning {{cannot call function 'f2' while mutex 'mu2' is held}}
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001448 }
1449};
1450
1451Foo *foo;
1452
1453void func()
1454{
Stephen Hines651f13c2014-04-23 16:59:28 -07001455 foo->f1(); // expected-warning {{calling function 'f1' requires holding mutex 'foo->mu2' exclusively}} \
1456 // expected-warning {{calling function 'f1' requires holding mutex 'foo->mu1' exclusively}}
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001457}
1458} // end namespace thread_annot_lock_42
1459
1460namespace thread_annot_lock_46 {
1461// Test the support for annotations on virtual functions.
1462class Base {
1463 public:
1464 virtual void func1() EXCLUSIVE_LOCKS_REQUIRED(mu_);
1465 virtual void func2() LOCKS_EXCLUDED(mu_);
1466 Mutex mu_;
1467};
1468
1469class Child : public Base {
1470 public:
1471 virtual void func1() EXCLUSIVE_LOCKS_REQUIRED(mu_);
1472 virtual void func2() LOCKS_EXCLUDED(mu_);
1473};
1474
1475void main() {
1476 Child *c;
1477 Base *b = c;
1478
Stephen Hines651f13c2014-04-23 16:59:28 -07001479 b->func1(); // expected-warning {{calling function 'func1' requires holding mutex 'b->mu_' exclusively}}
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001480 b->mu_.Lock();
Stephen Hines651f13c2014-04-23 16:59:28 -07001481 b->func2(); // expected-warning {{cannot call function 'func2' while mutex 'b->mu_' is held}}
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001482 b->mu_.Unlock();
1483
Stephen Hines651f13c2014-04-23 16:59:28 -07001484 c->func1(); // expected-warning {{calling function 'func1' requires holding mutex 'c->mu_' exclusively}}
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001485 c->mu_.Lock();
Stephen Hines651f13c2014-04-23 16:59:28 -07001486 c->func2(); // expected-warning {{cannot call function 'func2' while mutex 'c->mu_' is held}}
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001487 c->mu_.Unlock();
1488}
1489} // end namespace thread_annot_lock_46
1490
1491namespace thread_annot_lock_67_modified {
1492// Modified: attributes on definitions moved to declarations
1493// Test annotations on out-of-line definitions of member functions where the
1494// annotations refer to locks that are also data members in the class.
1495Mutex mu;
1496Mutex mu3;
1497
1498class Foo {
1499 public:
1500 int method1(int i) SHARED_LOCKS_REQUIRED(mu1, mu, mu2, mu3);
1501 int data GUARDED_BY(mu1);
1502 Mutex *mu1;
1503 Mutex *mu2;
1504};
1505
1506int Foo::method1(int i) {
1507 return data + i;
1508}
1509
1510void main()
1511{
1512 Foo a;
Stephen Hines651f13c2014-04-23 16:59:28 -07001513 a.method1(1); // expected-warning {{calling function 'method1' requires holding mutex 'a.mu1'}} \
1514 // expected-warning {{calling function 'method1' requires holding mutex 'mu'}} \
1515 // expected-warning {{calling function 'method1' requires holding mutex 'a.mu2'}} \
1516 // expected-warning {{calling function 'method1' requires holding mutex 'mu3'}}
Caitlin Sadowski988b5ae2011-09-15 18:07:32 +00001517}
1518} // end namespace thread_annot_lock_67_modified
1519
1520
DeLesley Hutchins81216392011-10-17 21:38:02 +00001521namespace substitution_test {
1522 class MyData {
1523 public:
1524 Mutex mu;
1525
DeLesley Hutchins56968842013-04-08 20:11:11 +00001526 void lockData() __attribute__((exclusive_lock_function(mu)));
1527 void unlockData() __attribute__((unlock_function(mu)));
DeLesley Hutchins81216392011-10-17 21:38:02 +00001528
1529 void doSomething() __attribute__((exclusive_locks_required(mu))) { }
1530 };
1531
1532
1533 class DataLocker {
1534 public:
DeLesley Hutchins56968842013-04-08 20:11:11 +00001535 void lockData (MyData *d) __attribute__((exclusive_lock_function(d->mu)));
1536 void unlockData(MyData *d) __attribute__((unlock_function(d->mu)));
DeLesley Hutchins81216392011-10-17 21:38:02 +00001537 };
1538
1539
1540 class Foo {
1541 public:
1542 void foo(MyData* d) __attribute__((exclusive_locks_required(d->mu))) { }
1543
1544 void bar1(MyData* d) {
1545 d->lockData();
1546 foo(d);
1547 d->unlockData();
1548 }
1549
1550 void bar2(MyData* d) {
1551 DataLocker dlr;
1552 dlr.lockData(d);
1553 foo(d);
1554 dlr.unlockData(d);
1555 }
1556
1557 void bar3(MyData* d1, MyData* d2) {
1558 DataLocker dlr;
Richard Smith2e515622012-02-03 04:45:26 +00001559 dlr.lockData(d1); // expected-note {{mutex acquired here}}
DeLesley Hutchins81216392011-10-17 21:38:02 +00001560 dlr.unlockData(d2); // \
Stephen Hines651f13c2014-04-23 16:59:28 -07001561 // expected-warning {{releasing mutex 'd2->mu' that was not held}}
1562 } // expected-warning {{mutex 'd1->mu' is still held at the end of function}}
DeLesley Hutchins81216392011-10-17 21:38:02 +00001563
1564 void bar4(MyData* d1, MyData* d2) {
1565 DataLocker dlr;
1566 dlr.lockData(d1);
1567 foo(d2); // \
Stephen Hines651f13c2014-04-23 16:59:28 -07001568 // expected-warning {{calling function 'foo' requires holding mutex 'd2->mu' exclusively}} \
DeLesley Hutchins3f0ec522012-09-10 19:58:23 +00001569 // expected-note {{found near match 'd1->mu'}}
DeLesley Hutchins81216392011-10-17 21:38:02 +00001570 dlr.unlockData(d1);
1571 }
1572 };
1573} // end namespace substituation_test
1574
DeLesley Hutchinse0eaa852011-10-21 18:06:53 +00001575
DeLesley Hutchinsf1ac6372011-10-21 18:10:14 +00001576
DeLesley Hutchinse0eaa852011-10-21 18:06:53 +00001577namespace constructor_destructor_tests {
1578 Mutex fooMu;
1579 int myVar GUARDED_BY(fooMu);
1580
1581 class Foo {
1582 public:
1583 Foo() __attribute__((exclusive_lock_function(fooMu))) { }
1584 ~Foo() __attribute__((unlock_function(fooMu))) { }
1585 };
1586
1587 void fooTest() {
DeLesley Hutchins6db51f72011-10-21 20:51:27 +00001588 Foo foo;
DeLesley Hutchinse0eaa852011-10-21 18:06:53 +00001589 myVar = 0;
1590 }
1591}
1592
DeLesley Hutchinsf1ac6372011-10-21 18:10:14 +00001593
Richard Smith97f9fe02011-10-25 00:41:24 +00001594namespace template_member_test {
DeLesley Hutchinsf1ac6372011-10-21 18:10:14 +00001595
Richard Smith97f9fe02011-10-25 00:41:24 +00001596 struct S { int n; };
1597 struct T {
1598 Mutex m;
1599 S *s GUARDED_BY(this->m);
1600 };
Richard Smitha01c7112011-10-25 06:33:21 +00001601 Mutex m;
1602 struct U {
1603 union {
1604 int n;
1605 };
1606 } *u GUARDED_BY(m);
Richard Smith97f9fe02011-10-25 00:41:24 +00001607
1608 template<typename U>
1609 struct IndirectLock {
1610 int DoNaughtyThings(T *t) {
Stephen Hines651f13c2014-04-23 16:59:28 -07001611 u->n = 0; // expected-warning {{reading variable 'u' requires holding mutex 'm'}}
1612 return t->s->n; // expected-warning {{reading variable 's' requires holding mutex 't->m'}}
Richard Smith97f9fe02011-10-25 00:41:24 +00001613 }
1614 };
1615
Richard Smithf11e9232011-10-25 01:05:41 +00001616 template struct IndirectLock<int>; // expected-note {{here}}
Richard Smith97f9fe02011-10-25 00:41:24 +00001617
Richard Smith601d2ee2011-10-26 06:15:36 +00001618 struct V {
1619 void f(int);
1620 void f(double);
1621
1622 Mutex m;
1623 V *p GUARDED_BY(this->m);
1624 };
1625 template<typename U> struct W {
1626 V v;
1627 void f(U u) {
Stephen Hines651f13c2014-04-23 16:59:28 -07001628 v.p->f(u); // expected-warning {{reading variable 'p' requires holding mutex 'v.m'}}
Richard Smith601d2ee2011-10-26 06:15:36 +00001629 }
1630 };
1631 template struct W<int>; // expected-note {{here}}
1632
Richard Smith97f9fe02011-10-25 00:41:24 +00001633}
DeLesley Hutchins1fa3c062011-12-08 20:23:06 +00001634
1635namespace test_scoped_lockable {
1636
1637struct TestScopedLockable {
1638 Mutex mu1;
1639 Mutex mu2;
1640 int a __attribute__((guarded_by(mu1)));
1641 int b __attribute__((guarded_by(mu2)));
1642
1643 bool getBool();
1644
1645 void foo1() {
1646 MutexLock mulock(&mu1);
1647 a = 5;
1648 }
1649
1650 void foo2() {
1651 ReaderMutexLock mulock1(&mu1);
1652 if (getBool()) {
1653 MutexLock mulock2a(&mu2);
1654 b = a + 1;
1655 }
1656 else {
1657 MutexLock mulock2b(&mu2);
1658 b = a + 2;
1659 }
1660 }
1661
1662 void foo3() {
1663 MutexLock mulock_a(&mu1);
1664 MutexLock mulock_b(&mu1); // \
Stephen Hines651f13c2014-04-23 16:59:28 -07001665 // expected-warning {{acquiring mutex 'mu1' that is already held}}
DeLesley Hutchinsc99a5d82012-06-28 22:42:48 +00001666 }
DeLesley Hutchins1fa3c062011-12-08 20:23:06 +00001667
1668 void foo4() {
1669 MutexLock mulock1(&mu1), mulock2(&mu2);
1670 a = b+1;
1671 b = a+1;
1672 }
Stephen Hines176edba2014-12-01 14:53:08 -08001673
1674 void foo5() {
1675 DoubleMutexLock mulock(&mu1, &mu2);
1676 a = b + 1;
1677 b = a + 1;
1678 }
DeLesley Hutchins1fa3c062011-12-08 20:23:06 +00001679};
1680
1681} // end namespace test_scoped_lockable
1682
1683
DeLesley Hutchinsdf497822011-12-29 00:56:48 +00001684namespace FunctionAttrTest {
1685
1686class Foo {
1687public:
1688 Mutex mu_;
1689 int a GUARDED_BY(mu_);
1690};
1691
1692Foo fooObj;
1693
1694void foo() EXCLUSIVE_LOCKS_REQUIRED(fooObj.mu_);
1695
1696void bar() {
Stephen Hines651f13c2014-04-23 16:59:28 -07001697 foo(); // expected-warning {{calling function 'foo' requires holding mutex 'fooObj.mu_' exclusively}}
DeLesley Hutchinsdf497822011-12-29 00:56:48 +00001698 fooObj.mu_.Lock();
1699 foo();
1700 fooObj.mu_.Unlock();
1701}
1702
1703}; // end namespace FunctionAttrTest
1704
1705
DeLesley Hutchins60ff1982012-09-20 23:14:43 +00001706namespace TryLockTest {
1707
DeLesley Hutchinsb4fa4182012-01-06 19:16:50 +00001708struct TestTryLock {
1709 Mutex mu;
1710 int a GUARDED_BY(mu);
1711 bool cond;
1712
1713 void foo1() {
1714 if (mu.TryLock()) {
1715 a = 1;
1716 mu.Unlock();
1717 }
1718 }
1719
1720 void foo2() {
1721 if (!mu.TryLock()) return;
1722 a = 2;
1723 mu.Unlock();
1724 }
1725
1726 void foo3() {
1727 bool b = mu.TryLock();
1728 if (b) {
1729 a = 3;
1730 mu.Unlock();
1731 }
1732 }
1733
1734 void foo4() {
1735 bool b = mu.TryLock();
1736 if (!b) return;
1737 a = 4;
1738 mu.Unlock();
1739 }
1740
1741 void foo5() {
1742 while (mu.TryLock()) {
1743 a = a + 1;
1744 mu.Unlock();
1745 }
1746 }
1747
1748 void foo6() {
1749 bool b = mu.TryLock();
1750 b = !b;
1751 if (b) return;
1752 a = 6;
1753 mu.Unlock();
1754 }
1755
1756 void foo7() {
1757 bool b1 = mu.TryLock();
1758 bool b2 = !b1;
1759 bool b3 = !b2;
1760 if (b3) {
1761 a = 7;
1762 mu.Unlock();
1763 }
1764 }
1765
1766 // Test use-def chains: join points
1767 void foo8() {
1768 bool b = mu.TryLock();
1769 bool b2 = b;
1770 if (cond)
1771 b = true;
Sylvestre Ledru43e3dee2012-07-31 06:56:50 +00001772 if (b) { // b should be unknown at this point, because of the join point
Stephen Hines651f13c2014-04-23 16:59:28 -07001773 a = 8; // expected-warning {{writing variable 'a' requires holding mutex 'mu' exclusively}}
DeLesley Hutchinsb4fa4182012-01-06 19:16:50 +00001774 }
1775 if (b2) { // b2 should be known at this point.
1776 a = 8;
1777 mu.Unlock();
1778 }
1779 }
1780
1781 // Test use-def-chains: back edges
1782 void foo9() {
1783 bool b = mu.TryLock();
1784
1785 for (int i = 0; i < 10; ++i);
1786
1787 if (b) { // b is still known, because the loop doesn't alter it
1788 a = 9;
1789 mu.Unlock();
1790 }
1791 }
1792
1793 // Test use-def chains: back edges
1794 void foo10() {
1795 bool b = mu.TryLock();
1796
1797 while (cond) {
1798 if (b) { // b should be uknown at this point b/c of the loop
Stephen Hines651f13c2014-04-23 16:59:28 -07001799 a = 10; // expected-warning {{writing variable 'a' requires holding mutex 'mu' exclusively}}
DeLesley Hutchinsb4fa4182012-01-06 19:16:50 +00001800 }
1801 b = !b;
1802 }
1803 }
DeLesley Hutchins60ff1982012-09-20 23:14:43 +00001804
1805 // Test merge of exclusive trylock
1806 void foo11() {
1807 if (cond) {
1808 if (!mu.TryLock())
1809 return;
1810 }
1811 else {
1812 mu.Lock();
1813 }
1814 a = 10;
1815 mu.Unlock();
1816 }
1817
1818 // Test merge of shared trylock
1819 void foo12() {
1820 if (cond) {
1821 if (!mu.ReaderTryLock())
1822 return;
1823 }
1824 else {
1825 mu.ReaderLock();
1826 }
1827 int i = a;
1828 mu.Unlock();
1829 }
DeLesley Hutchinsb4fa4182012-01-06 19:16:50 +00001830}; // end TestTrylock
1831
DeLesley Hutchins60ff1982012-09-20 23:14:43 +00001832} // end namespace TrylockTest
1833
DeLesley Hutchinsb4fa4182012-01-06 19:16:50 +00001834
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +00001835namespace TestTemplateAttributeInstantiation {
1836
1837class Foo1 {
1838public:
1839 Mutex mu_;
1840 int a GUARDED_BY(mu_);
1841};
1842
1843class Foo2 {
1844public:
1845 int a GUARDED_BY(mu_);
1846 Mutex mu_;
1847};
1848
1849
1850class Bar {
1851public:
1852 // Test non-dependent expressions in attributes on template functions
1853 template <class T>
1854 void barND(Foo1 *foo, T *fooT) EXCLUSIVE_LOCKS_REQUIRED(foo->mu_) {
1855 foo->a = 0;
1856 }
1857
1858 // Test dependent expressions in attributes on template functions
1859 template <class T>
1860 void barD(Foo1 *foo, T *fooT) EXCLUSIVE_LOCKS_REQUIRED(fooT->mu_) {
1861 fooT->a = 0;
1862 }
1863};
1864
1865
1866template <class T>
1867class BarT {
1868public:
1869 Foo1 fooBase;
1870 T fooBaseT;
1871
1872 // Test non-dependent expression in ordinary method on template class
1873 void barND() EXCLUSIVE_LOCKS_REQUIRED(fooBase.mu_) {
1874 fooBase.a = 0;
1875 }
1876
1877 // Test dependent expressions in ordinary methods on template class
1878 void barD() EXCLUSIVE_LOCKS_REQUIRED(fooBaseT.mu_) {
1879 fooBaseT.a = 0;
1880 }
1881
1882 // Test dependent expressions in template method in template class
1883 template <class T2>
1884 void barTD(T2 *fooT) EXCLUSIVE_LOCKS_REQUIRED(fooBaseT.mu_, fooT->mu_) {
1885 fooBaseT.a = 0;
1886 fooT->a = 0;
1887 }
1888};
1889
1890template <class T>
1891class Cell {
1892public:
1893 Mutex mu_;
1894 // Test dependent guarded_by
1895 T data GUARDED_BY(mu_);
1896
DeLesley Hutchins23323e02012-01-20 22:50:54 +00001897 void fooEx() EXCLUSIVE_LOCKS_REQUIRED(mu_) {
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +00001898 data = 0;
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +00001899 }
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +00001900
1901 void foo() {
1902 mu_.Lock();
1903 data = 0;
1904 mu_.Unlock();
1905 }
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +00001906};
1907
1908void test() {
1909 Bar b;
1910 BarT<Foo2> bt;
1911 Foo1 f1;
1912 Foo2 f2;
1913
1914 f1.mu_.Lock();
1915 f2.mu_.Lock();
1916 bt.fooBase.mu_.Lock();
1917 bt.fooBaseT.mu_.Lock();
1918
1919 b.barND(&f1, &f2);
1920 b.barD(&f1, &f2);
1921 bt.barND();
1922 bt.barD();
1923 bt.barTD(&f2);
1924
1925 f1.mu_.Unlock();
1926 bt.barTD(&f1); // \
Stephen Hines651f13c2014-04-23 16:59:28 -07001927 // expected-warning {{calling function 'barTD' requires holding mutex 'f1.mu_' exclusively}} \
DeLesley Hutchins3f0ec522012-09-10 19:58:23 +00001928 // expected-note {{found near match 'bt.fooBase.mu_'}}
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +00001929
1930 bt.fooBase.mu_.Unlock();
1931 bt.fooBaseT.mu_.Unlock();
1932 f2.mu_.Unlock();
1933
1934 Cell<int> cell;
1935 cell.data = 0; // \
Stephen Hines651f13c2014-04-23 16:59:28 -07001936 // expected-warning {{writing variable 'data' requires holding mutex 'cell.mu_' exclusively}}
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +00001937 cell.foo();
DeLesley Hutchins23323e02012-01-20 22:50:54 +00001938 cell.mu_.Lock();
1939 cell.fooEx();
1940 cell.mu_.Unlock();
1941}
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +00001942
DeLesley Hutchins23323e02012-01-20 22:50:54 +00001943
1944template <class T>
1945class CellDelayed {
1946public:
1947 // Test dependent guarded_by
1948 T data GUARDED_BY(mu_);
DeLesley Hutchinsdd5756c2012-02-16 17:30:51 +00001949 static T static_data GUARDED_BY(static_mu_);
DeLesley Hutchins23323e02012-01-20 22:50:54 +00001950
1951 void fooEx(CellDelayed<T> *other) EXCLUSIVE_LOCKS_REQUIRED(mu_, other->mu_) {
1952 this->data = other->data;
1953 }
1954
1955 template <class T2>
1956 void fooExT(CellDelayed<T2> *otherT) EXCLUSIVE_LOCKS_REQUIRED(mu_, otherT->mu_) {
1957 this->data = otherT->data;
1958 }
1959
1960 void foo() {
1961 mu_.Lock();
1962 data = 0;
1963 mu_.Unlock();
1964 }
1965
1966 Mutex mu_;
DeLesley Hutchinsdd5756c2012-02-16 17:30:51 +00001967 static Mutex static_mu_;
DeLesley Hutchins23323e02012-01-20 22:50:54 +00001968};
1969
1970void testDelayed() {
1971 CellDelayed<int> celld;
1972 CellDelayed<int> celld2;
1973 celld.foo();
1974 celld.mu_.Lock();
1975 celld2.mu_.Lock();
1976
1977 celld.fooEx(&celld2);
1978 celld.fooExT(&celld2);
1979
1980 celld2.mu_.Unlock();
1981 celld.mu_.Unlock();
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +00001982}
1983
1984}; // end namespace TestTemplateAttributeInstantiation
1985
1986
DeLesley Hutchinse03b2b32012-01-20 23:24:41 +00001987namespace FunctionDeclDefTest {
1988
1989class Foo {
1990public:
1991 Mutex mu_;
1992 int a GUARDED_BY(mu_);
1993
1994 virtual void foo1(Foo *f_declared) EXCLUSIVE_LOCKS_REQUIRED(f_declared->mu_);
1995};
1996
1997// EXCLUSIVE_LOCKS_REQUIRED should be applied, and rewritten to f_defined->mu_
1998void Foo::foo1(Foo *f_defined) {
1999 f_defined->a = 0;
2000};
2001
2002void test() {
2003 Foo myfoo;
2004 myfoo.foo1(&myfoo); // \
Stephen Hines651f13c2014-04-23 16:59:28 -07002005 // expected-warning {{calling function 'foo1' requires holding mutex 'myfoo.mu_' exclusively}}
DeLesley Hutchinse03b2b32012-01-20 23:24:41 +00002006 myfoo.mu_.Lock();
2007 myfoo.foo1(&myfoo);
2008 myfoo.mu_.Unlock();
2009}
2010
2011};
Richard Smith2e515622012-02-03 04:45:26 +00002012
2013namespace GoingNative {
2014
2015 struct __attribute__((lockable)) mutex {
2016 void lock() __attribute__((exclusive_lock_function));
2017 void unlock() __attribute__((unlock_function));
2018 // ...
2019 };
2020 bool foo();
2021 bool bar();
2022 mutex m;
2023 void test() {
2024 m.lock();
2025 while (foo()) {
2026 m.unlock();
2027 // ...
2028 if (bar()) {
2029 // ...
2030 if (foo())
Stephen Hines651f13c2014-04-23 16:59:28 -07002031 continue; // expected-warning {{expecting mutex 'm' to be held at start of each loop}}
Richard Smith2e515622012-02-03 04:45:26 +00002032 //...
2033 }
2034 // ...
2035 m.lock(); // expected-note {{mutex acquired here}}
2036 }
2037 m.unlock();
2038 }
2039
2040}
DeLesley Hutchinsc24a2332012-02-16 16:50:43 +00002041
2042
2043
2044namespace FunctionDefinitionTest {
2045
2046class Foo {
2047public:
2048 void foo1();
2049 void foo2();
2050 void foo3(Foo *other);
2051
2052 template<class T>
2053 void fooT1(const T& dummy1);
2054
2055 template<class T>
2056 void fooT2(const T& dummy2) EXCLUSIVE_LOCKS_REQUIRED(mu_);
2057
2058 Mutex mu_;
2059 int a GUARDED_BY(mu_);
2060};
2061
2062template<class T>
2063class FooT {
2064public:
2065 void foo();
2066
2067 Mutex mu_;
2068 T a GUARDED_BY(mu_);
2069};
2070
2071
2072void Foo::foo1() NO_THREAD_SAFETY_ANALYSIS {
2073 a = 1;
2074}
2075
2076void Foo::foo2() EXCLUSIVE_LOCKS_REQUIRED(mu_) {
2077 a = 2;
2078}
2079
2080void Foo::foo3(Foo *other) EXCLUSIVE_LOCKS_REQUIRED(other->mu_) {
2081 other->a = 3;
2082}
2083
2084template<class T>
2085void Foo::fooT1(const T& dummy1) EXCLUSIVE_LOCKS_REQUIRED(mu_) {
2086 a = dummy1;
2087}
2088
2089/* TODO -- uncomment with template instantiation of attributes.
2090template<class T>
2091void Foo::fooT2(const T& dummy2) {
2092 a = dummy2;
2093}
2094*/
2095
2096void fooF1(Foo *f) EXCLUSIVE_LOCKS_REQUIRED(f->mu_) {
2097 f->a = 1;
2098}
2099
2100void fooF2(Foo *f);
2101void fooF2(Foo *f) EXCLUSIVE_LOCKS_REQUIRED(f->mu_) {
2102 f->a = 2;
2103}
2104
2105void fooF3(Foo *f) EXCLUSIVE_LOCKS_REQUIRED(f->mu_);
2106void fooF3(Foo *f) {
2107 f->a = 3;
2108}
2109
2110template<class T>
2111void FooT<T>::foo() EXCLUSIVE_LOCKS_REQUIRED(mu_) {
2112 a = 0;
2113}
2114
2115void test() {
2116 int dummy = 0;
2117 Foo myFoo;
2118
2119 myFoo.foo2(); // \
Stephen Hines651f13c2014-04-23 16:59:28 -07002120 // expected-warning {{calling function 'foo2' requires holding mutex 'myFoo.mu_' exclusively}}
DeLesley Hutchinsc24a2332012-02-16 16:50:43 +00002121 myFoo.foo3(&myFoo); // \
Stephen Hines651f13c2014-04-23 16:59:28 -07002122 // expected-warning {{calling function 'foo3' requires holding mutex 'myFoo.mu_' exclusively}}
DeLesley Hutchinsc24a2332012-02-16 16:50:43 +00002123 myFoo.fooT1(dummy); // \
Stephen Hines651f13c2014-04-23 16:59:28 -07002124 // expected-warning {{calling function 'fooT1' requires holding mutex 'myFoo.mu_' exclusively}}
DeLesley Hutchinsc24a2332012-02-16 16:50:43 +00002125
DeLesley Hutchinsa74b7152012-08-10 20:19:55 +00002126 myFoo.fooT2(dummy); // \
Stephen Hines651f13c2014-04-23 16:59:28 -07002127 // expected-warning {{calling function 'fooT2' requires holding mutex 'myFoo.mu_' exclusively}}
DeLesley Hutchinsc24a2332012-02-16 16:50:43 +00002128
2129 fooF1(&myFoo); // \
Stephen Hines651f13c2014-04-23 16:59:28 -07002130 // expected-warning {{calling function 'fooF1' requires holding mutex 'myFoo.mu_' exclusively}}
DeLesley Hutchinsc24a2332012-02-16 16:50:43 +00002131 fooF2(&myFoo); // \
Stephen Hines651f13c2014-04-23 16:59:28 -07002132 // expected-warning {{calling function 'fooF2' requires holding mutex 'myFoo.mu_' exclusively}}
DeLesley Hutchinsc24a2332012-02-16 16:50:43 +00002133 fooF3(&myFoo); // \
Stephen Hines651f13c2014-04-23 16:59:28 -07002134 // expected-warning {{calling function 'fooF3' requires holding mutex 'myFoo.mu_' exclusively}}
DeLesley Hutchinsc24a2332012-02-16 16:50:43 +00002135
2136 myFoo.mu_.Lock();
2137 myFoo.foo2();
2138 myFoo.foo3(&myFoo);
2139 myFoo.fooT1(dummy);
2140
DeLesley Hutchinsa74b7152012-08-10 20:19:55 +00002141 myFoo.fooT2(dummy);
DeLesley Hutchinsc24a2332012-02-16 16:50:43 +00002142
2143 fooF1(&myFoo);
2144 fooF2(&myFoo);
2145 fooF3(&myFoo);
2146 myFoo.mu_.Unlock();
2147
2148 FooT<int> myFooT;
2149 myFooT.foo(); // \
Stephen Hines651f13c2014-04-23 16:59:28 -07002150 // expected-warning {{calling function 'foo' requires holding mutex 'myFooT.mu_' exclusively}}
DeLesley Hutchinsc24a2332012-02-16 16:50:43 +00002151}
2152
DeLesley Hutchins4bda3ec2012-02-16 17:03:24 +00002153} // end namespace FunctionDefinitionTest
2154
2155
2156namespace SelfLockingTest {
2157
2158class LOCKABLE MyLock {
2159public:
2160 int foo GUARDED_BY(this);
2161
2162 void lock() EXCLUSIVE_LOCK_FUNCTION();
2163 void unlock() UNLOCK_FUNCTION();
2164
2165 void doSomething() {
2166 this->lock(); // allow 'this' as a lock expression
2167 foo = 0;
2168 doSomethingElse();
2169 this->unlock();
2170 }
2171
2172 void doSomethingElse() EXCLUSIVE_LOCKS_REQUIRED(this) {
2173 foo = 1;
2174 };
2175
2176 void test() {
2177 foo = 2; // \
Stephen Hines651f13c2014-04-23 16:59:28 -07002178 // expected-warning {{writing variable 'foo' requires holding mutex 'this' exclusively}}
DeLesley Hutchins4bda3ec2012-02-16 17:03:24 +00002179 }
DeLesley Hutchinsc24a2332012-02-16 16:50:43 +00002180};
2181
DeLesley Hutchins2f13bec2012-02-16 17:13:43 +00002182
2183class LOCKABLE MyLock2 {
2184public:
2185 Mutex mu_;
2186 int foo GUARDED_BY(this);
2187
2188 // don't check inside lock and unlock functions
2189 void lock() EXCLUSIVE_LOCK_FUNCTION() { mu_.Lock(); }
2190 void unlock() UNLOCK_FUNCTION() { mu_.Unlock(); }
2191
2192 // don't check inside constructors and destructors
2193 MyLock2() { foo = 1; }
2194 ~MyLock2() { foo = 0; }
2195};
2196
2197
DeLesley Hutchins4bda3ec2012-02-16 17:03:24 +00002198} // end namespace SelfLockingTest
2199
2200
DeLesley Hutchinsd08d5992012-02-25 00:11:55 +00002201namespace InvalidNonstatic {
2202
2203// Forward decl here causes bogus "invalid use of non-static data member"
2204// on reference to mutex_ in guarded_by attribute.
2205class Foo;
2206
2207class Foo {
2208 Mutex* mutex_;
2209
2210 int foo __attribute__((guarded_by(mutex_)));
2211};
2212
2213} // end namespace InvalidNonStatic
2214
DeLesley Hutchins2a35be82012-03-02 22:02:58 +00002215
2216namespace NoReturnTest {
2217
2218bool condition();
2219void fatal() __attribute__((noreturn));
2220
2221Mutex mu_;
2222
2223void test1() {
2224 MutexLock lock(&mu_);
2225 if (condition()) {
2226 fatal();
2227 return;
2228 }
2229}
2230
DeLesley Hutchins2287c5e2012-03-02 22:12:59 +00002231} // end namespace NoReturnTest
2232
2233
2234namespace TestMultiDecl {
2235
2236class Foo {
2237public:
2238 int GUARDED_BY(mu_) a;
2239 int GUARDED_BY(mu_) b, c;
2240
2241 void foo() {
2242 a = 0; // \
Stephen Hines651f13c2014-04-23 16:59:28 -07002243 // expected-warning {{writing variable 'a' requires holding mutex 'mu_' exclusively}}
DeLesley Hutchins2287c5e2012-03-02 22:12:59 +00002244 b = 0; // \
Stephen Hines651f13c2014-04-23 16:59:28 -07002245 // expected-warning {{writing variable 'b' requires holding mutex 'mu_' exclusively}}
DeLesley Hutchins2287c5e2012-03-02 22:12:59 +00002246 c = 0; // \
Stephen Hines651f13c2014-04-23 16:59:28 -07002247 // expected-warning {{writing variable 'c' requires holding mutex 'mu_' exclusively}}
DeLesley Hutchins2287c5e2012-03-02 22:12:59 +00002248 }
2249
2250private:
2251 Mutex mu_;
DeLesley Hutchins2a35be82012-03-02 22:02:58 +00002252};
DeLesley Hutchins2287c5e2012-03-02 22:12:59 +00002253
2254} // end namespace TestMultiDecl
2255
DeLesley Hutchins7ec419a2012-03-02 22:29:50 +00002256
2257namespace WarnNoDecl {
2258
2259class Foo {
2260 void foo(int a); __attribute__(( // \
2261 // expected-warning {{declaration does not declare anything}}
2262 exclusive_locks_required(a))); // \
2263 // expected-warning {{attribute exclusive_locks_required ignored}}
2264};
2265
2266} // end namespace WarnNoDecl
2267
2268
DeLesley Hutchins0d95dfc2012-03-02 23:36:05 +00002269
2270namespace MoreLockExpressions {
2271
2272class Foo {
2273public:
2274 Mutex mu_;
2275 int a GUARDED_BY(mu_);
2276};
2277
2278class Bar {
2279public:
2280 int b;
2281 Foo* f;
2282
2283 Foo& getFoo() { return *f; }
2284 Foo& getFoo2(int c) { return *f; }
2285 Foo& getFoo3(int c, int d) { return *f; }
2286
2287 Foo& getFooey() { return *f; }
2288};
2289
2290Foo& getBarFoo(Bar &bar, int c) { return bar.getFoo2(c); }
2291
2292void test() {
2293 Foo foo;
2294 Foo *fooArray;
2295 Bar bar;
2296 int a;
2297 int b;
2298 int c;
2299
2300 bar.getFoo().mu_.Lock();
2301 bar.getFoo().a = 0;
2302 bar.getFoo().mu_.Unlock();
2303
2304 (bar.getFoo().mu_).Lock(); // test parenthesis
2305 bar.getFoo().a = 0;
2306 (bar.getFoo().mu_).Unlock();
2307
2308 bar.getFoo2(a).mu_.Lock();
2309 bar.getFoo2(a).a = 0;
2310 bar.getFoo2(a).mu_.Unlock();
2311
2312 bar.getFoo3(a, b).mu_.Lock();
2313 bar.getFoo3(a, b).a = 0;
2314 bar.getFoo3(a, b).mu_.Unlock();
2315
2316 getBarFoo(bar, a).mu_.Lock();
2317 getBarFoo(bar, a).a = 0;
2318 getBarFoo(bar, a).mu_.Unlock();
2319
2320 bar.getFoo2(10).mu_.Lock();
2321 bar.getFoo2(10).a = 0;
2322 bar.getFoo2(10).mu_.Unlock();
2323
2324 bar.getFoo2(a + 1).mu_.Lock();
2325 bar.getFoo2(a + 1).a = 0;
2326 bar.getFoo2(a + 1).mu_.Unlock();
2327
2328 (a > 0 ? fooArray[1] : fooArray[b]).mu_.Lock();
2329 (a > 0 ? fooArray[1] : fooArray[b]).a = 0;
2330 (a > 0 ? fooArray[1] : fooArray[b]).mu_.Unlock();
Stephen Hines176edba2014-12-01 14:53:08 -08002331}
2332
2333
2334void test2() {
2335 Foo *fooArray;
2336 Bar bar;
2337 int a;
2338 int b;
2339 int c;
DeLesley Hutchins0d95dfc2012-03-02 23:36:05 +00002340
2341 bar.getFoo().mu_.Lock();
2342 bar.getFooey().a = 0; // \
Stephen Hines651f13c2014-04-23 16:59:28 -07002343 // expected-warning {{writing variable 'a' requires holding mutex 'bar.getFooey().mu_' exclusively}} \
DeLesley Hutchins3f0ec522012-09-10 19:58:23 +00002344 // expected-note {{found near match 'bar.getFoo().mu_'}}
DeLesley Hutchins0d95dfc2012-03-02 23:36:05 +00002345 bar.getFoo().mu_.Unlock();
2346
2347 bar.getFoo2(a).mu_.Lock();
2348 bar.getFoo2(b).a = 0; // \
Stephen Hines651f13c2014-04-23 16:59:28 -07002349 // expected-warning {{writing variable 'a' requires holding mutex 'bar.getFoo2(b).mu_' exclusively}} \
DeLesley Hutchins3f0ec522012-09-10 19:58:23 +00002350 // expected-note {{found near match 'bar.getFoo2(a).mu_'}}
DeLesley Hutchins0d95dfc2012-03-02 23:36:05 +00002351 bar.getFoo2(a).mu_.Unlock();
2352
2353 bar.getFoo3(a, b).mu_.Lock();
2354 bar.getFoo3(a, c).a = 0; // \
Stephen Hines176edba2014-12-01 14:53:08 -08002355 // expected-warning {{writing variable 'a' requires holding mutex 'bar.getFoo3(a, c).mu_' exclusively}} \
2356 // expected-note {{found near match 'bar.getFoo3(a, b).mu_'}}
DeLesley Hutchins0d95dfc2012-03-02 23:36:05 +00002357 bar.getFoo3(a, b).mu_.Unlock();
2358
2359 getBarFoo(bar, a).mu_.Lock();
2360 getBarFoo(bar, b).a = 0; // \
Stephen Hines176edba2014-12-01 14:53:08 -08002361 // expected-warning {{writing variable 'a' requires holding mutex 'getBarFoo(bar, b).mu_' exclusively}} \
2362 // expected-note {{found near match 'getBarFoo(bar, a).mu_'}}
DeLesley Hutchins0d95dfc2012-03-02 23:36:05 +00002363 getBarFoo(bar, a).mu_.Unlock();
2364
2365 (a > 0 ? fooArray[1] : fooArray[b]).mu_.Lock();
2366 (a > 0 ? fooArray[b] : fooArray[c]).a = 0; // \
Stephen Hines176edba2014-12-01 14:53:08 -08002367 // expected-warning {{writing variable 'a' requires holding mutex '((0 < a) ? fooArray[b] : fooArray[c]).mu_' exclusively}} \
2368 // expected-note {{found near match '((0 < a) ? fooArray[1] : fooArray[b]).mu_'}}
DeLesley Hutchins0d95dfc2012-03-02 23:36:05 +00002369 (a > 0 ? fooArray[1] : fooArray[b]).mu_.Unlock();
2370}
2371
2372
DeLesley Hutchins0da44142012-06-22 17:07:28 +00002373} // end namespace MoreLockExpressions
2374
2375
2376namespace TrylockJoinPoint {
2377
2378class Foo {
2379 Mutex mu;
2380 bool c;
2381
2382 void foo() {
2383 if (c) {
2384 if (!mu.TryLock())
2385 return;
2386 } else {
2387 mu.Lock();
2388 }
2389 mu.Unlock();
2390 }
2391};
2392
2393} // end namespace TrylockJoinPoint
DeLesley Hutchins0d95dfc2012-03-02 23:36:05 +00002394
2395
DeLesley Hutchinsf63797c2012-06-25 18:33:18 +00002396namespace LockReturned {
2397
2398class Foo {
2399public:
2400 int a GUARDED_BY(mu_);
2401 void foo() EXCLUSIVE_LOCKS_REQUIRED(mu_);
2402 void foo2(Foo* f) EXCLUSIVE_LOCKS_REQUIRED(mu_, f->mu_);
2403
2404 static void sfoo(Foo* f) EXCLUSIVE_LOCKS_REQUIRED(f->mu_);
2405
2406 Mutex* getMu() LOCK_RETURNED(mu_);
2407
2408 Mutex mu_;
2409
2410 static Mutex* getMu(Foo* f) LOCK_RETURNED(f->mu_);
2411};
2412
2413
2414// Calls getMu() directly to lock and unlock
2415void test1(Foo* f1, Foo* f2) {
Stephen Hines651f13c2014-04-23 16:59:28 -07002416 f1->a = 0; // expected-warning {{writing variable 'a' requires holding mutex 'f1->mu_' exclusively}}
2417 f1->foo(); // expected-warning {{calling function 'foo' requires holding mutex 'f1->mu_' exclusively}}
DeLesley Hutchinsf63797c2012-06-25 18:33:18 +00002418
Stephen Hines651f13c2014-04-23 16:59:28 -07002419 f1->foo2(f2); // expected-warning {{calling function 'foo2' requires holding mutex 'f1->mu_' exclusively}} \
2420 // expected-warning {{calling function 'foo2' requires holding mutex 'f2->mu_' exclusively}}
2421 Foo::sfoo(f1); // expected-warning {{calling function 'sfoo' requires holding mutex 'f1->mu_' exclusively}}
DeLesley Hutchinsf63797c2012-06-25 18:33:18 +00002422
2423 f1->getMu()->Lock();
2424
2425 f1->a = 0;
2426 f1->foo();
DeLesley Hutchins3f0ec522012-09-10 19:58:23 +00002427 f1->foo2(f2); // \
Stephen Hines651f13c2014-04-23 16:59:28 -07002428 // expected-warning {{calling function 'foo2' requires holding mutex 'f2->mu_' exclusively}} \
DeLesley Hutchins3f0ec522012-09-10 19:58:23 +00002429 // expected-note {{found near match 'f1->mu_'}}
DeLesley Hutchinsf63797c2012-06-25 18:33:18 +00002430
2431 Foo::getMu(f2)->Lock();
2432 f1->foo2(f2);
2433 Foo::getMu(f2)->Unlock();
2434
2435 Foo::sfoo(f1);
2436
2437 f1->getMu()->Unlock();
2438}
2439
2440
2441Mutex* getFooMu(Foo* f) LOCK_RETURNED(Foo::getMu(f));
2442
2443class Bar : public Foo {
2444public:
2445 int b GUARDED_BY(getMu());
2446 void bar() EXCLUSIVE_LOCKS_REQUIRED(getMu());
2447 void bar2(Bar* g) EXCLUSIVE_LOCKS_REQUIRED(getMu(this), g->getMu());
2448
2449 static void sbar(Bar* g) EXCLUSIVE_LOCKS_REQUIRED(g->getMu());
2450 static void sbar2(Bar* g) EXCLUSIVE_LOCKS_REQUIRED(getFooMu(g));
2451};
2452
2453
2454
2455// Use getMu() within other attributes.
2456// This requires at lest levels of substitution, more in the case of
2457void test2(Bar* b1, Bar* b2) {
Stephen Hines651f13c2014-04-23 16:59:28 -07002458 b1->b = 0; // expected-warning {{writing variable 'b' requires holding mutex 'b1->mu_' exclusively}}
2459 b1->bar(); // expected-warning {{calling function 'bar' requires holding mutex 'b1->mu_' exclusively}}
2460 b1->bar2(b2); // expected-warning {{calling function 'bar2' requires holding mutex 'b1->mu_' exclusively}} \
2461 // expected-warning {{calling function 'bar2' requires holding mutex 'b2->mu_' exclusively}}
2462 Bar::sbar(b1); // expected-warning {{calling function 'sbar' requires holding mutex 'b1->mu_' exclusively}}
2463 Bar::sbar2(b1); // expected-warning {{calling function 'sbar2' requires holding mutex 'b1->mu_' exclusively}}
DeLesley Hutchinsf63797c2012-06-25 18:33:18 +00002464
2465 b1->getMu()->Lock();
2466
2467 b1->b = 0;
2468 b1->bar();
DeLesley Hutchins3f0ec522012-09-10 19:58:23 +00002469 b1->bar2(b2); // \
Stephen Hines651f13c2014-04-23 16:59:28 -07002470 // expected-warning {{calling function 'bar2' requires holding mutex 'b2->mu_' exclusively}} \
DeLesley Hutchins3f0ec522012-09-10 19:58:23 +00002471 // // expected-note {{found near match 'b1->mu_'}}
DeLesley Hutchinsf63797c2012-06-25 18:33:18 +00002472
2473 b2->getMu()->Lock();
2474 b1->bar2(b2);
2475
2476 b2->getMu()->Unlock();
2477
2478 Bar::sbar(b1);
2479 Bar::sbar2(b1);
2480
2481 b1->getMu()->Unlock();
2482}
2483
2484
2485// Sanity check -- lock the mutex directly, but use attributes that call getMu()
2486// Also lock the mutex using getFooMu, which calls a lock_returned function.
2487void test3(Bar* b1, Bar* b2) {
2488 b1->mu_.Lock();
2489 b1->b = 0;
2490 b1->bar();
2491
2492 getFooMu(b2)->Lock();
2493 b1->bar2(b2);
2494 getFooMu(b2)->Unlock();
2495
2496 Bar::sbar(b1);
2497 Bar::sbar2(b1);
2498
2499 b1->mu_.Unlock();
2500}
2501
2502} // end namespace LockReturned
2503
2504
DeLesley Hutchinsc99a5d82012-06-28 22:42:48 +00002505namespace ReleasableScopedLock {
2506
2507class Foo {
2508 Mutex mu_;
2509 bool c;
2510 int a GUARDED_BY(mu_);
2511
2512 void test1();
2513 void test2();
2514 void test3();
DeLesley Hutchins5381c052012-07-05 21:16:29 +00002515 void test4();
2516 void test5();
DeLesley Hutchinsc99a5d82012-06-28 22:42:48 +00002517};
2518
2519
2520void Foo::test1() {
2521 ReleasableMutexLock rlock(&mu_);
2522 rlock.Release();
2523}
2524
2525void Foo::test2() {
2526 ReleasableMutexLock rlock(&mu_);
2527 if (c) { // test join point -- held/not held during release
2528 rlock.Release();
2529 }
2530}
2531
2532void Foo::test3() {
2533 ReleasableMutexLock rlock(&mu_);
2534 a = 0;
2535 rlock.Release();
Stephen Hines651f13c2014-04-23 16:59:28 -07002536 a = 1; // expected-warning {{writing variable 'a' requires holding mutex 'mu_' exclusively}}
DeLesley Hutchinsc99a5d82012-06-28 22:42:48 +00002537}
2538
DeLesley Hutchins5381c052012-07-05 21:16:29 +00002539void Foo::test4() {
2540 ReleasableMutexLock rlock(&mu_);
2541 rlock.Release();
Stephen Hines651f13c2014-04-23 16:59:28 -07002542 rlock.Release(); // expected-warning {{releasing mutex 'mu_' that was not held}}
DeLesley Hutchins5381c052012-07-05 21:16:29 +00002543}
2544
2545void Foo::test5() {
2546 ReleasableMutexLock rlock(&mu_);
2547 if (c) {
2548 rlock.Release();
2549 }
2550 // no warning on join point for managed lock.
Stephen Hines651f13c2014-04-23 16:59:28 -07002551 rlock.Release(); // expected-warning {{releasing mutex 'mu_' that was not held}}
DeLesley Hutchins5381c052012-07-05 21:16:29 +00002552}
2553
2554
DeLesley Hutchinsc99a5d82012-06-28 22:42:48 +00002555} // end namespace ReleasableScopedLock
2556
2557
DeLesley Hutchins76f0a6e2012-07-02 21:59:24 +00002558namespace TrylockFunctionTest {
2559
2560class Foo {
2561public:
2562 Mutex mu1_;
2563 Mutex mu2_;
2564 bool c;
2565
2566 bool lockBoth() EXCLUSIVE_TRYLOCK_FUNCTION(true, mu1_, mu2_);
2567};
2568
2569bool Foo::lockBoth() {
2570 if (!mu1_.TryLock())
2571 return false;
2572
2573 mu2_.Lock();
2574 if (!c) {
2575 mu1_.Unlock();
2576 mu2_.Unlock();
2577 return false;
2578 }
2579
2580 return true;
2581}
2582
2583
2584} // end namespace TrylockFunctionTest
DeLesley Hutchinsc99a5d82012-06-28 22:42:48 +00002585
2586
2587
DeLesley Hutchinsc36eda12012-07-02 22:12:12 +00002588namespace DoubleLockBug {
2589
2590class Foo {
2591public:
2592 Mutex mu_;
2593 int a GUARDED_BY(mu_);
2594
DeLesley Hutchins5381c052012-07-05 21:16:29 +00002595 void foo1() EXCLUSIVE_LOCKS_REQUIRED(mu_);
2596 int foo2() SHARED_LOCKS_REQUIRED(mu_);
DeLesley Hutchinsc36eda12012-07-02 22:12:12 +00002597};
2598
2599
DeLesley Hutchins5381c052012-07-05 21:16:29 +00002600void Foo::foo1() EXCLUSIVE_LOCKS_REQUIRED(mu_) {
DeLesley Hutchinsc36eda12012-07-02 22:12:12 +00002601 a = 0;
2602}
2603
DeLesley Hutchins5381c052012-07-05 21:16:29 +00002604int Foo::foo2() SHARED_LOCKS_REQUIRED(mu_) {
2605 return a;
2606}
2607
2608}
2609
DeLesley Hutchinsc36eda12012-07-02 22:12:12 +00002610
2611
DeLesley Hutchins879a4332012-07-02 22:16:54 +00002612namespace UnlockBug {
DeLesley Hutchinsc36eda12012-07-02 22:12:12 +00002613
DeLesley Hutchins879a4332012-07-02 22:16:54 +00002614class Foo {
2615public:
2616 Mutex mutex_;
2617
2618 void foo1() EXCLUSIVE_LOCKS_REQUIRED(mutex_) { // expected-note {{mutex acquired here}}
2619 mutex_.Unlock();
Stephen Hines651f13c2014-04-23 16:59:28 -07002620 } // expected-warning {{expecting mutex 'mutex_' to be held at the end of function}}
DeLesley Hutchins879a4332012-07-02 22:16:54 +00002621
2622
2623 void foo2() SHARED_LOCKS_REQUIRED(mutex_) { // expected-note {{mutex acquired here}}
2624 mutex_.Unlock();
Stephen Hines651f13c2014-04-23 16:59:28 -07002625 } // expected-warning {{expecting mutex 'mutex_' to be held at the end of function}}
DeLesley Hutchins879a4332012-07-02 22:16:54 +00002626};
2627
2628} // end namespace UnlockBug
DeLesley Hutchinsc36eda12012-07-02 22:12:12 +00002629
DeLesley Hutchinsc99a5d82012-06-28 22:42:48 +00002630
DeLesley Hutchins5381c052012-07-05 21:16:29 +00002631
DeLesley Hutchinsbbe33412012-07-02 22:26:29 +00002632namespace FoolishScopedLockableBug {
2633
2634class SCOPED_LOCKABLE WTF_ScopedLockable {
2635public:
2636 WTF_ScopedLockable(Mutex* mu) EXCLUSIVE_LOCK_FUNCTION(mu);
2637
2638 // have to call release() manually;
2639 ~WTF_ScopedLockable();
2640
2641 void release() UNLOCK_FUNCTION();
2642};
2643
2644
2645class Foo {
2646 Mutex mu_;
2647 int a GUARDED_BY(mu_);
2648 bool c;
2649
2650 void doSomething();
2651
2652 void test1() {
2653 WTF_ScopedLockable wtf(&mu_);
2654 wtf.release();
2655 }
2656
2657 void test2() {
2658 WTF_ScopedLockable wtf(&mu_); // expected-note {{mutex acquired here}}
Stephen Hines651f13c2014-04-23 16:59:28 -07002659 } // expected-warning {{mutex 'mu_' is still held at the end of function}}
DeLesley Hutchinsbbe33412012-07-02 22:26:29 +00002660
2661 void test3() {
2662 if (c) {
2663 WTF_ScopedLockable wtf(&mu_);
2664 wtf.release();
2665 }
2666 }
2667
2668 void test4() {
2669 if (c) {
2670 doSomething();
2671 }
2672 else {
2673 WTF_ScopedLockable wtf(&mu_);
2674 wtf.release();
2675 }
2676 }
2677
2678 void test5() {
2679 if (c) {
2680 WTF_ScopedLockable wtf(&mu_); // expected-note {{mutex acquired here}}
2681 }
Stephen Hines651f13c2014-04-23 16:59:28 -07002682 } // expected-warning {{mutex 'mu_' is not held on every path through here}}
DeLesley Hutchinsbbe33412012-07-02 22:26:29 +00002683
2684 void test6() {
2685 if (c) {
2686 doSomething();
2687 }
2688 else {
2689 WTF_ScopedLockable wtf(&mu_); // expected-note {{mutex acquired here}}
2690 }
Stephen Hines651f13c2014-04-23 16:59:28 -07002691 } // expected-warning {{mutex 'mu_' is not held on every path through here}}
DeLesley Hutchinsbbe33412012-07-02 22:26:29 +00002692};
2693
2694
2695} // end namespace FoolishScopedLockableBug
2696
DeLesley Hutchins9d6e7f32012-07-03 18:25:56 +00002697
DeLesley Hutchins5381c052012-07-05 21:16:29 +00002698
DeLesley Hutchins9d6e7f32012-07-03 18:25:56 +00002699namespace TemporaryCleanupExpr {
2700
2701class Foo {
2702 int a GUARDED_BY(getMutexPtr().get());
2703
2704 SmartPtr<Mutex> getMutexPtr();
2705
2706 void test();
2707};
2708
2709
2710void Foo::test() {
2711 {
2712 ReaderMutexLock lock(getMutexPtr().get());
2713 int b = a;
DeLesley Hutchins96fac6a2012-07-03 19:47:18 +00002714 }
Stephen Hines651f13c2014-04-23 16:59:28 -07002715 int b = a; // expected-warning {{reading variable 'a' requires holding mutex 'getMutexPtr()'}}
DeLesley Hutchins9d6e7f32012-07-03 18:25:56 +00002716}
2717
2718} // end namespace TemporaryCleanupExpr
2719
2720
DeLesley Hutchins96fac6a2012-07-03 19:47:18 +00002721
2722namespace SmartPointerTests {
2723
2724class Foo {
2725public:
2726 SmartPtr<Mutex> mu_;
2727 int a GUARDED_BY(mu_);
2728 int b GUARDED_BY(mu_.get());
2729 int c GUARDED_BY(*mu_);
2730
2731 void Lock() EXCLUSIVE_LOCK_FUNCTION(mu_);
2732 void Unlock() UNLOCK_FUNCTION(mu_);
2733
2734 void test0();
2735 void test1();
2736 void test2();
2737 void test3();
2738 void test4();
2739 void test5();
2740 void test6();
2741 void test7();
2742 void test8();
2743};
2744
2745void Foo::test0() {
Stephen Hines651f13c2014-04-23 16:59:28 -07002746 a = 0; // expected-warning {{writing variable 'a' requires holding mutex 'mu_' exclusively}}
2747 b = 0; // expected-warning {{writing variable 'b' requires holding mutex 'mu_' exclusively}}
2748 c = 0; // expected-warning {{writing variable 'c' requires holding mutex 'mu_' exclusively}}
DeLesley Hutchins96fac6a2012-07-03 19:47:18 +00002749}
2750
2751void Foo::test1() {
2752 mu_->Lock();
2753 a = 0;
2754 b = 0;
2755 c = 0;
2756 mu_->Unlock();
2757}
2758
2759void Foo::test2() {
2760 (*mu_).Lock();
2761 a = 0;
2762 b = 0;
2763 c = 0;
2764 (*mu_).Unlock();
2765}
2766
2767
2768void Foo::test3() {
2769 mu_.get()->Lock();
2770 a = 0;
2771 b = 0;
2772 c = 0;
2773 mu_.get()->Unlock();
2774}
2775
2776
2777void Foo::test4() {
2778 MutexLock lock(mu_.get());
2779 a = 0;
2780 b = 0;
2781 c = 0;
2782}
2783
2784
2785void Foo::test5() {
2786 MutexLock lock(&(*mu_));
2787 a = 0;
2788 b = 0;
2789 c = 0;
2790}
2791
2792
2793void Foo::test6() {
2794 Lock();
2795 a = 0;
2796 b = 0;
2797 c = 0;
2798 Unlock();
2799}
2800
2801
2802void Foo::test7() {
2803 {
2804 Lock();
2805 mu_->Unlock();
2806 }
2807 {
2808 mu_->Lock();
2809 Unlock();
2810 }
2811 {
2812 mu_.get()->Lock();
2813 mu_->Unlock();
2814 }
2815 {
2816 mu_->Lock();
2817 mu_.get()->Unlock();
2818 }
2819 {
2820 mu_.get()->Lock();
2821 (*mu_).Unlock();
2822 }
2823 {
2824 (*mu_).Lock();
2825 mu_->Unlock();
2826 }
2827}
2828
2829
2830void Foo::test8() {
2831 mu_->Lock();
Stephen Hines651f13c2014-04-23 16:59:28 -07002832 mu_.get()->Lock(); // expected-warning {{acquiring mutex 'mu_' that is already held}}
2833 (*mu_).Lock(); // expected-warning {{acquiring mutex 'mu_' that is already held}}
DeLesley Hutchins96fac6a2012-07-03 19:47:18 +00002834 mu_.get()->Unlock();
Stephen Hines651f13c2014-04-23 16:59:28 -07002835 Unlock(); // expected-warning {{releasing mutex 'mu_' that was not held}}
DeLesley Hutchins96fac6a2012-07-03 19:47:18 +00002836}
2837
2838
2839class Bar {
2840 SmartPtr<Foo> foo;
2841
2842 void test0();
2843 void test1();
2844 void test2();
2845 void test3();
2846};
2847
2848
2849void Bar::test0() {
Stephen Hines651f13c2014-04-23 16:59:28 -07002850 foo->a = 0; // expected-warning {{writing variable 'a' requires holding mutex 'foo->mu_' exclusively}}
2851 (*foo).b = 0; // expected-warning {{writing variable 'b' requires holding mutex 'foo->mu_' exclusively}}
2852 foo.get()->c = 0; // expected-warning {{writing variable 'c' requires holding mutex 'foo->mu_' exclusively}}
DeLesley Hutchins96fac6a2012-07-03 19:47:18 +00002853}
2854
2855
2856void Bar::test1() {
2857 foo->mu_->Lock();
2858 foo->a = 0;
2859 (*foo).b = 0;
2860 foo.get()->c = 0;
2861 foo->mu_->Unlock();
2862}
2863
2864
2865void Bar::test2() {
2866 (*foo).mu_->Lock();
2867 foo->a = 0;
2868 (*foo).b = 0;
2869 foo.get()->c = 0;
2870 foo.get()->mu_->Unlock();
2871}
2872
2873
2874void Bar::test3() {
2875 MutexLock lock(foo->mu_.get());
2876 foo->a = 0;
2877 (*foo).b = 0;
2878 foo.get()->c = 0;
2879}
2880
2881} // end namespace SmartPointerTests
2882
2883
2884
DeLesley Hutchins5381c052012-07-05 21:16:29 +00002885namespace DuplicateAttributeTest {
2886
2887class LOCKABLE Foo {
2888public:
2889 Mutex mu1_;
2890 Mutex mu2_;
2891 Mutex mu3_;
2892 int a GUARDED_BY(mu1_);
2893 int b GUARDED_BY(mu2_);
2894 int c GUARDED_BY(mu3_);
2895
2896 void lock() EXCLUSIVE_LOCK_FUNCTION();
2897 void unlock() UNLOCK_FUNCTION();
2898
2899 void lock1() EXCLUSIVE_LOCK_FUNCTION(mu1_);
2900 void slock1() SHARED_LOCK_FUNCTION(mu1_);
2901 void lock3() EXCLUSIVE_LOCK_FUNCTION(mu1_, mu2_, mu3_);
2902 void locklots()
2903 EXCLUSIVE_LOCK_FUNCTION(mu1_)
2904 EXCLUSIVE_LOCK_FUNCTION(mu2_)
2905 EXCLUSIVE_LOCK_FUNCTION(mu1_, mu2_, mu3_);
2906
2907 void unlock1() UNLOCK_FUNCTION(mu1_);
2908 void unlock3() UNLOCK_FUNCTION(mu1_, mu2_, mu3_);
2909 void unlocklots()
2910 UNLOCK_FUNCTION(mu1_)
2911 UNLOCK_FUNCTION(mu2_)
2912 UNLOCK_FUNCTION(mu1_, mu2_, mu3_);
2913};
2914
2915
2916void Foo::lock() EXCLUSIVE_LOCK_FUNCTION() { }
2917void Foo::unlock() UNLOCK_FUNCTION() { }
2918
2919void Foo::lock1() EXCLUSIVE_LOCK_FUNCTION(mu1_) {
2920 mu1_.Lock();
2921}
2922
2923void Foo::slock1() SHARED_LOCK_FUNCTION(mu1_) {
DeLesley Hutchins56968842013-04-08 20:11:11 +00002924 mu1_.ReaderLock();
DeLesley Hutchins5381c052012-07-05 21:16:29 +00002925}
2926
2927void Foo::lock3() EXCLUSIVE_LOCK_FUNCTION(mu1_, mu2_, mu3_) {
2928 mu1_.Lock();
2929 mu2_.Lock();
2930 mu3_.Lock();
2931}
2932
2933void Foo::locklots()
2934 EXCLUSIVE_LOCK_FUNCTION(mu1_, mu2_)
2935 EXCLUSIVE_LOCK_FUNCTION(mu2_, mu3_) {
2936 mu1_.Lock();
2937 mu2_.Lock();
2938 mu3_.Lock();
2939}
2940
2941void Foo::unlock1() UNLOCK_FUNCTION(mu1_) {
2942 mu1_.Unlock();
2943}
2944
2945void Foo::unlock3() UNLOCK_FUNCTION(mu1_, mu2_, mu3_) {
2946 mu1_.Unlock();
2947 mu2_.Unlock();
2948 mu3_.Unlock();
2949}
2950
2951void Foo::unlocklots()
2952 UNLOCK_FUNCTION(mu1_, mu2_)
2953 UNLOCK_FUNCTION(mu2_, mu3_) {
2954 mu1_.Unlock();
2955 mu2_.Unlock();
2956 mu3_.Unlock();
2957}
2958
2959
2960void test0() {
2961 Foo foo;
2962 foo.lock();
2963 foo.unlock();
2964
2965 foo.lock();
Stephen Hines651f13c2014-04-23 16:59:28 -07002966 foo.lock(); // expected-warning {{acquiring mutex 'foo' that is already held}}
DeLesley Hutchins5381c052012-07-05 21:16:29 +00002967 foo.unlock();
Stephen Hines651f13c2014-04-23 16:59:28 -07002968 foo.unlock(); // expected-warning {{releasing mutex 'foo' that was not held}}
DeLesley Hutchins5381c052012-07-05 21:16:29 +00002969}
2970
2971
2972void test1() {
2973 Foo foo;
2974 foo.lock1();
2975 foo.a = 0;
2976 foo.unlock1();
2977
2978 foo.lock1();
Stephen Hines651f13c2014-04-23 16:59:28 -07002979 foo.lock1(); // expected-warning {{acquiring mutex 'foo.mu1_' that is already held}}
DeLesley Hutchins5381c052012-07-05 21:16:29 +00002980 foo.a = 0;
2981 foo.unlock1();
Stephen Hines651f13c2014-04-23 16:59:28 -07002982 foo.unlock1(); // expected-warning {{releasing mutex 'foo.mu1_' that was not held}}
DeLesley Hutchins5381c052012-07-05 21:16:29 +00002983}
2984
2985
2986int test2() {
2987 Foo foo;
2988 foo.slock1();
2989 int d1 = foo.a;
2990 foo.unlock1();
2991
2992 foo.slock1();
Stephen Hines651f13c2014-04-23 16:59:28 -07002993 foo.slock1(); // expected-warning {{acquiring mutex 'foo.mu1_' that is already held}}
DeLesley Hutchins5381c052012-07-05 21:16:29 +00002994 int d2 = foo.a;
2995 foo.unlock1();
Stephen Hines651f13c2014-04-23 16:59:28 -07002996 foo.unlock1(); // expected-warning {{releasing mutex 'foo.mu1_' that was not held}}
DeLesley Hutchins5381c052012-07-05 21:16:29 +00002997 return d1 + d2;
2998}
2999
3000
3001void test3() {
3002 Foo foo;
3003 foo.lock3();
3004 foo.a = 0;
3005 foo.b = 0;
3006 foo.c = 0;
3007 foo.unlock3();
3008
3009 foo.lock3();
3010 foo.lock3(); // \
Stephen Hines651f13c2014-04-23 16:59:28 -07003011 // expected-warning {{acquiring mutex 'foo.mu1_' that is already held}} \
3012 // expected-warning {{acquiring mutex 'foo.mu2_' that is already held}} \
3013 // expected-warning {{acquiring mutex 'foo.mu3_' that is already held}}
DeLesley Hutchins5381c052012-07-05 21:16:29 +00003014 foo.a = 0;
3015 foo.b = 0;
3016 foo.c = 0;
3017 foo.unlock3();
3018 foo.unlock3(); // \
Stephen Hines651f13c2014-04-23 16:59:28 -07003019 // expected-warning {{releasing mutex 'foo.mu1_' that was not held}} \
3020 // expected-warning {{releasing mutex 'foo.mu2_' that was not held}} \
3021 // expected-warning {{releasing mutex 'foo.mu3_' that was not held}}
DeLesley Hutchins5381c052012-07-05 21:16:29 +00003022}
3023
3024
3025void testlots() {
3026 Foo foo;
3027 foo.locklots();
3028 foo.a = 0;
3029 foo.b = 0;
3030 foo.c = 0;
3031 foo.unlocklots();
3032
3033 foo.locklots();
3034 foo.locklots(); // \
Stephen Hines651f13c2014-04-23 16:59:28 -07003035 // expected-warning {{acquiring mutex 'foo.mu1_' that is already held}} \
3036 // expected-warning {{acquiring mutex 'foo.mu2_' that is already held}} \
3037 // expected-warning {{acquiring mutex 'foo.mu3_' that is already held}}
DeLesley Hutchins5381c052012-07-05 21:16:29 +00003038 foo.a = 0;
3039 foo.b = 0;
3040 foo.c = 0;
3041 foo.unlocklots();
3042 foo.unlocklots(); // \
Stephen Hines651f13c2014-04-23 16:59:28 -07003043 // expected-warning {{releasing mutex 'foo.mu1_' that was not held}} \
3044 // expected-warning {{releasing mutex 'foo.mu2_' that was not held}} \
3045 // expected-warning {{releasing mutex 'foo.mu3_' that was not held}}
DeLesley Hutchins5381c052012-07-05 21:16:29 +00003046}
3047
3048} // end namespace DuplicateAttributeTest
3049
3050
3051
DeLesley Hutchins13106112012-07-10 21:47:55 +00003052namespace TryLockEqTest {
3053
3054class Foo {
3055 Mutex mu_;
3056 int a GUARDED_BY(mu_);
3057 bool c;
3058
3059 int tryLockMutexI() EXCLUSIVE_TRYLOCK_FUNCTION(1, mu_);
3060 Mutex* tryLockMutexP() EXCLUSIVE_TRYLOCK_FUNCTION(1, mu_);
3061 void unlock() UNLOCK_FUNCTION(mu_);
3062
3063 void test1();
3064 void test2();
3065};
3066
3067
3068void Foo::test1() {
3069 if (tryLockMutexP() == 0) {
Stephen Hines651f13c2014-04-23 16:59:28 -07003070 a = 0; // expected-warning {{writing variable 'a' requires holding mutex 'mu_' exclusively}}
DeLesley Hutchins13106112012-07-10 21:47:55 +00003071 return;
3072 }
3073 a = 0;
3074 unlock();
3075
3076 if (tryLockMutexP() != 0) {
3077 a = 0;
3078 unlock();
3079 }
3080
3081 if (0 != tryLockMutexP()) {
3082 a = 0;
3083 unlock();
3084 }
3085
3086 if (!(tryLockMutexP() == 0)) {
3087 a = 0;
3088 unlock();
3089 }
3090
3091 if (tryLockMutexI() == 0) {
Stephen Hines651f13c2014-04-23 16:59:28 -07003092 a = 0; // expected-warning {{writing variable 'a' requires holding mutex 'mu_' exclusively}}
DeLesley Hutchins13106112012-07-10 21:47:55 +00003093 return;
3094 }
3095 a = 0;
3096 unlock();
3097
3098 if (0 == tryLockMutexI()) {
Stephen Hines651f13c2014-04-23 16:59:28 -07003099 a = 0; // expected-warning {{writing variable 'a' requires holding mutex 'mu_' exclusively}}
DeLesley Hutchins13106112012-07-10 21:47:55 +00003100 return;
3101 }
3102 a = 0;
3103 unlock();
3104
3105 if (tryLockMutexI() == 1) {
3106 a = 0;
3107 unlock();
3108 }
3109
3110 if (mu_.TryLock() == false) {
Stephen Hines651f13c2014-04-23 16:59:28 -07003111 a = 0; // expected-warning {{writing variable 'a' requires holding mutex 'mu_' exclusively}}
DeLesley Hutchins13106112012-07-10 21:47:55 +00003112 return;
3113 }
3114 a = 0;
3115 unlock();
3116
3117 if (mu_.TryLock() == true) {
3118 a = 0;
3119 unlock();
3120 }
3121 else {
Stephen Hines651f13c2014-04-23 16:59:28 -07003122 a = 0; // expected-warning {{writing variable 'a' requires holding mutex 'mu_' exclusively}}
DeLesley Hutchins13106112012-07-10 21:47:55 +00003123 }
3124
3125#if __has_feature(cxx_nullptr)
3126 if (tryLockMutexP() == nullptr) {
Stephen Hines651f13c2014-04-23 16:59:28 -07003127 a = 0; // expected-warning {{writing variable 'a' requires holding mutex 'mu_' exclusively}}
DeLesley Hutchins13106112012-07-10 21:47:55 +00003128 return;
3129 }
3130 a = 0;
3131 unlock();
3132#endif
3133}
3134
DeLesley Hutchins13106112012-07-10 21:47:55 +00003135} // end namespace TryLockEqTest
DeLesley Hutchins5381c052012-07-05 21:16:29 +00003136
DeLesley Hutchins96fac6a2012-07-03 19:47:18 +00003137
DeLesley Hutchinsee2f0322012-08-10 20:29:46 +00003138namespace ExistentialPatternMatching {
3139
3140class Graph {
3141public:
3142 Mutex mu_;
3143};
3144
3145void LockAllGraphs() EXCLUSIVE_LOCK_FUNCTION(&Graph::mu_);
3146void UnlockAllGraphs() UNLOCK_FUNCTION(&Graph::mu_);
3147
3148class Node {
3149public:
3150 int a GUARDED_BY(&Graph::mu_);
3151
3152 void foo() EXCLUSIVE_LOCKS_REQUIRED(&Graph::mu_) {
3153 a = 0;
3154 }
3155 void foo2() LOCKS_EXCLUDED(&Graph::mu_);
3156};
3157
3158void test() {
3159 Graph g1;
3160 Graph g2;
3161 Node n1;
3162
Stephen Hines651f13c2014-04-23 16:59:28 -07003163 n1.a = 0; // expected-warning {{writing variable 'a' requires holding mutex '&ExistentialPatternMatching::Graph::mu_' exclusively}}
3164 n1.foo(); // expected-warning {{calling function 'foo' requires holding mutex '&ExistentialPatternMatching::Graph::mu_' exclusively}}
DeLesley Hutchinsee2f0322012-08-10 20:29:46 +00003165 n1.foo2();
3166
3167 g1.mu_.Lock();
3168 n1.a = 0;
3169 n1.foo();
Stephen Hines651f13c2014-04-23 16:59:28 -07003170 n1.foo2(); // expected-warning {{cannot call function 'foo2' while mutex '&ExistentialPatternMatching::Graph::mu_' is held}}
DeLesley Hutchinsee2f0322012-08-10 20:29:46 +00003171 g1.mu_.Unlock();
3172
3173 g2.mu_.Lock();
3174 n1.a = 0;
3175 n1.foo();
Stephen Hines651f13c2014-04-23 16:59:28 -07003176 n1.foo2(); // expected-warning {{cannot call function 'foo2' while mutex '&ExistentialPatternMatching::Graph::mu_' is held}}
DeLesley Hutchinsee2f0322012-08-10 20:29:46 +00003177 g2.mu_.Unlock();
3178
3179 LockAllGraphs();
3180 n1.a = 0;
3181 n1.foo();
Stephen Hines651f13c2014-04-23 16:59:28 -07003182 n1.foo2(); // expected-warning {{cannot call function 'foo2' while mutex '&ExistentialPatternMatching::Graph::mu_' is held}}
DeLesley Hutchinsee2f0322012-08-10 20:29:46 +00003183 UnlockAllGraphs();
3184
3185 LockAllGraphs();
3186 g1.mu_.Unlock();
3187
3188 LockAllGraphs();
3189 g2.mu_.Unlock();
3190
3191 LockAllGraphs();
Stephen Hines651f13c2014-04-23 16:59:28 -07003192 g1.mu_.Lock(); // expected-warning {{acquiring mutex 'g1.mu_' that is already held}}
DeLesley Hutchinsee2f0322012-08-10 20:29:46 +00003193 g1.mu_.Unlock();
3194}
3195
3196} // end namespace ExistentialPatternMatching
3197
DeLesley Hutchins4e4c1572012-08-31 21:57:32 +00003198
3199namespace StringIgnoreTest {
3200
3201class Foo {
3202public:
3203 Mutex mu_;
3204 void lock() EXCLUSIVE_LOCK_FUNCTION("");
3205 void unlock() UNLOCK_FUNCTION("");
3206 void goober() EXCLUSIVE_LOCKS_REQUIRED("");
3207 void roober() SHARED_LOCKS_REQUIRED("");
3208};
3209
3210
3211class Bar : public Foo {
3212public:
3213 void bar(Foo* f) {
3214 f->unlock();
3215 f->goober();
3216 f->roober();
3217 f->lock();
3218 };
3219};
3220
3221} // end namespace StringIgnoreTest
3222
3223
DeLesley Hutchins54081532012-08-31 22:09:53 +00003224namespace LockReturnedScopeFix {
3225
3226class Base {
3227protected:
3228 struct Inner;
3229 bool c;
3230
3231 const Mutex& getLock(const Inner* i);
3232
3233 void lockInner (Inner* i) EXCLUSIVE_LOCK_FUNCTION(getLock(i));
3234 void unlockInner(Inner* i) UNLOCK_FUNCTION(getLock(i));
3235 void foo(Inner* i) EXCLUSIVE_LOCKS_REQUIRED(getLock(i));
3236
3237 void bar(Inner* i);
3238};
3239
3240
3241struct Base::Inner {
3242 Mutex lock_;
3243 void doSomething() EXCLUSIVE_LOCKS_REQUIRED(lock_);
3244};
3245
3246
3247const Mutex& Base::getLock(const Inner* i) LOCK_RETURNED(i->lock_) {
3248 return i->lock_;
3249}
3250
3251
3252void Base::foo(Inner* i) {
3253 i->doSomething();
3254}
3255
3256void Base::bar(Inner* i) {
3257 if (c) {
3258 i->lock_.Lock();
3259 unlockInner(i);
3260 }
3261 else {
3262 lockInner(i);
3263 i->lock_.Unlock();
3264 }
3265}
3266
3267} // end namespace LockReturnedScopeFix
3268
DeLesley Hutchinsfd0f11c2012-09-05 20:01:16 +00003269
3270namespace TrylockWithCleanups {
3271
DeLesley Hutchinsfd0f11c2012-09-05 20:01:16 +00003272struct Foo {
3273 Mutex mu_;
3274 int a GUARDED_BY(mu_);
3275};
3276
3277Foo* GetAndLockFoo(const MyString& s)
3278 EXCLUSIVE_TRYLOCK_FUNCTION(true, &Foo::mu_);
3279
3280static void test() {
3281 Foo* lt = GetAndLockFoo("foo");
3282 if (!lt) return;
3283 int a = lt->a;
3284 lt->mu_.Unlock();
3285}
3286
DeLesley Hutchins24a6c942012-09-11 18:27:46 +00003287} // end namespace TrylockWithCleanups
DeLesley Hutchinsfd0f11c2012-09-05 20:01:16 +00003288
3289
DeLesley Hutchins0b4db3e2012-09-07 17:34:53 +00003290namespace UniversalLock {
3291
3292class Foo {
3293 Mutex mu_;
3294 bool c;
3295
3296 int a GUARDED_BY(mu_);
3297 void r_foo() SHARED_LOCKS_REQUIRED(mu_);
3298 void w_foo() EXCLUSIVE_LOCKS_REQUIRED(mu_);
3299
3300 void test1() {
3301 int b;
3302
3303 beginNoWarnOnReads();
3304 b = a;
3305 r_foo();
3306 endNoWarnOnReads();
3307
3308 beginNoWarnOnWrites();
3309 a = 0;
3310 w_foo();
3311 endNoWarnOnWrites();
3312 }
3313
3314 // don't warn on joins with universal lock
3315 void test2() {
3316 if (c) {
3317 beginNoWarnOnWrites();
3318 }
3319 a = 0; // \
Stephen Hines651f13c2014-04-23 16:59:28 -07003320 // expected-warning {{writing variable 'a' requires holding mutex 'mu_' exclusively}}
DeLesley Hutchins0b4db3e2012-09-07 17:34:53 +00003321 endNoWarnOnWrites(); // \
Stephen Hines651f13c2014-04-23 16:59:28 -07003322 // expected-warning {{releasing mutex '*' that was not held}}
DeLesley Hutchins0b4db3e2012-09-07 17:34:53 +00003323 }
3324
3325
3326 // make sure the universal lock joins properly
3327 void test3() {
3328 if (c) {
3329 mu_.Lock();
3330 beginNoWarnOnWrites();
3331 }
3332 else {
3333 beginNoWarnOnWrites();
3334 mu_.Lock();
3335 }
3336 a = 0;
3337 endNoWarnOnWrites();
3338 mu_.Unlock();
3339 }
3340
3341
3342 // combine universal lock with other locks
3343 void test4() {
3344 beginNoWarnOnWrites();
3345 mu_.Lock();
3346 mu_.Unlock();
3347 endNoWarnOnWrites();
3348
3349 mu_.Lock();
3350 beginNoWarnOnWrites();
3351 endNoWarnOnWrites();
3352 mu_.Unlock();
3353
3354 mu_.Lock();
3355 beginNoWarnOnWrites();
3356 mu_.Unlock();
3357 endNoWarnOnWrites();
3358 }
3359};
3360
DeLesley Hutchins24a6c942012-09-11 18:27:46 +00003361} // end namespace UniversalLock
3362
3363
3364namespace TemplateLockReturned {
3365
3366template<class T>
3367class BaseT {
3368public:
3369 virtual void baseMethod() = 0;
3370 Mutex* get_mutex() LOCK_RETURNED(mutex_) { return &mutex_; }
3371
3372 Mutex mutex_;
3373 int a GUARDED_BY(mutex_);
3374};
3375
3376
3377class Derived : public BaseT<int> {
3378public:
3379 void baseMethod() EXCLUSIVE_LOCKS_REQUIRED(get_mutex()) {
3380 a = 0;
3381 }
3382};
3383
3384} // end namespace TemplateLockReturned
3385
3386
DeLesley Hutchinsf9ee0ba2012-09-11 23:04:49 +00003387namespace ExprMatchingBugFix {
3388
3389class Foo {
3390public:
3391 Mutex mu_;
3392};
3393
3394
3395class Bar {
3396public:
3397 bool c;
3398 Foo* foo;
3399 Bar(Foo* f) : foo(f) { }
3400
3401 struct Nested {
3402 Foo* foo;
3403 Nested(Foo* f) : foo(f) { }
3404
3405 void unlockFoo() UNLOCK_FUNCTION(&Foo::mu_);
3406 };
3407
3408 void test();
3409};
3410
3411
3412void Bar::test() {
3413 foo->mu_.Lock();
3414 if (c) {
3415 Nested *n = new Nested(foo);
3416 n->unlockFoo();
3417 }
3418 else {
3419 foo->mu_.Unlock();
3420 }
3421}
3422
3423}; // end namespace ExprMatchingBugfix
3424
3425
DeLesley Hutchins5b280f22012-09-19 19:18:29 +00003426namespace ComplexNameTest {
DeLesley Hutchinsf9ee0ba2012-09-11 23:04:49 +00003427
DeLesley Hutchins5b280f22012-09-19 19:18:29 +00003428class Foo {
3429public:
3430 static Mutex mu_;
3431
3432 Foo() EXCLUSIVE_LOCKS_REQUIRED(mu_) { }
3433 ~Foo() EXCLUSIVE_LOCKS_REQUIRED(mu_) { }
3434
3435 int operator[](int i) EXCLUSIVE_LOCKS_REQUIRED(mu_) { return 0; }
3436};
3437
3438class Bar {
3439public:
3440 static Mutex mu_;
3441
3442 Bar() LOCKS_EXCLUDED(mu_) { }
3443 ~Bar() LOCKS_EXCLUDED(mu_) { }
3444
3445 int operator[](int i) LOCKS_EXCLUDED(mu_) { return 0; }
3446};
3447
3448
3449void test1() {
Stephen Hines651f13c2014-04-23 16:59:28 -07003450 Foo f; // expected-warning {{calling function 'Foo' requires holding mutex 'mu_' exclusively}}
3451 int a = f[0]; // expected-warning {{calling function 'operator[]' requires holding mutex 'mu_' exclusively}}
3452} // expected-warning {{calling function '~Foo' requires holding mutex 'mu_' exclusively}}
DeLesley Hutchins5b280f22012-09-19 19:18:29 +00003453
3454
3455void test2() {
3456 Bar::mu_.Lock();
3457 {
Stephen Hines651f13c2014-04-23 16:59:28 -07003458 Bar b; // expected-warning {{cannot call function 'Bar' while mutex 'mu_' is held}}
3459 int a = b[0]; // expected-warning {{cannot call function 'operator[]' while mutex 'mu_' is held}}
3460 } // expected-warning {{cannot call function '~Bar' while mutex 'mu_' is held}}
DeLesley Hutchins5b280f22012-09-19 19:18:29 +00003461 Bar::mu_.Unlock();
3462}
3463
3464}; // end namespace ComplexNameTest
DeLesley Hutchins2a237e02012-09-19 19:49:40 +00003465
3466
3467namespace UnreachableExitTest {
3468
3469class FemmeFatale {
3470public:
3471 FemmeFatale();
3472 ~FemmeFatale() __attribute__((noreturn));
3473};
3474
3475void exitNow() __attribute__((noreturn));
DeLesley Hutchinsd2f38822012-09-21 17:57:00 +00003476void exitDestruct(const MyString& ms) __attribute__((noreturn));
DeLesley Hutchins2a237e02012-09-19 19:49:40 +00003477
3478Mutex fatalmu_;
3479
3480void test1() EXCLUSIVE_LOCKS_REQUIRED(fatalmu_) {
3481 exitNow();
3482}
3483
3484void test2() EXCLUSIVE_LOCKS_REQUIRED(fatalmu_) {
3485 FemmeFatale femme;
3486}
3487
3488bool c;
3489
3490void test3() EXCLUSIVE_LOCKS_REQUIRED(fatalmu_) {
3491 if (c) {
3492 exitNow();
3493 }
3494 else {
3495 FemmeFatale femme;
3496 }
3497}
3498
DeLesley Hutchinsd2f38822012-09-21 17:57:00 +00003499void test4() EXCLUSIVE_LOCKS_REQUIRED(fatalmu_) {
3500 exitDestruct("foo");
3501}
3502
DeLesley Hutchins2a237e02012-09-19 19:49:40 +00003503} // end namespace UnreachableExitTest
DeLesley Hutchins186af2d2012-09-20 22:18:02 +00003504
3505
3506namespace VirtualMethodCanonicalizationTest {
3507
3508class Base {
3509public:
3510 virtual Mutex* getMutex() = 0;
3511};
3512
3513class Base2 : public Base {
3514public:
3515 Mutex* getMutex();
3516};
3517
3518class Base3 : public Base2 {
3519public:
3520 Mutex* getMutex();
3521};
3522
3523class Derived : public Base3 {
3524public:
3525 Mutex* getMutex(); // overrides Base::getMutex()
3526};
3527
3528void baseFun(Base *b) EXCLUSIVE_LOCKS_REQUIRED(b->getMutex()) { }
3529
3530void derivedFun(Derived *d) EXCLUSIVE_LOCKS_REQUIRED(d->getMutex()) {
3531 baseFun(d);
3532}
3533
3534} // end namespace VirtualMethodCanonicalizationTest
3535
DeLesley Hutchinsd278dbe2012-09-26 17:57:31 +00003536
3537namespace TemplateFunctionParamRemapTest {
3538
3539template <class T>
3540struct Cell {
3541 T dummy_;
3542 Mutex* mu_;
3543};
3544
3545class Foo {
3546public:
3547 template <class T>
3548 void elr(Cell<T>* c) __attribute__((exclusive_locks_required(c->mu_)));
3549
3550 void test();
3551};
3552
3553template<class T>
3554void Foo::elr(Cell<T>* c1) { }
3555
3556void Foo::test() {
3557 Cell<int> cell;
3558 elr(&cell); // \
Stephen Hines651f13c2014-04-23 16:59:28 -07003559 // expected-warning {{calling function 'elr' requires holding mutex 'cell.mu_' exclusively}}
DeLesley Hutchinsd278dbe2012-09-26 17:57:31 +00003560}
3561
3562
3563template<class T>
3564void globalELR(Cell<T>* c) __attribute__((exclusive_locks_required(c->mu_)));
3565
3566template<class T>
3567void globalELR(Cell<T>* c1) { }
3568
3569void globalTest() {
3570 Cell<int> cell;
3571 globalELR(&cell); // \
Stephen Hines651f13c2014-04-23 16:59:28 -07003572 // expected-warning {{calling function 'globalELR' requires holding mutex 'cell.mu_' exclusively}}
DeLesley Hutchinsd278dbe2012-09-26 17:57:31 +00003573}
3574
3575
3576template<class T>
3577void globalELR2(Cell<T>* c) __attribute__((exclusive_locks_required(c->mu_)));
3578
3579// second declaration
3580template<class T>
3581void globalELR2(Cell<T>* c2);
3582
3583template<class T>
3584void globalELR2(Cell<T>* c3) { }
3585
3586// re-declaration after definition
3587template<class T>
3588void globalELR2(Cell<T>* c4);
3589
3590void globalTest2() {
3591 Cell<int> cell;
3592 globalELR2(&cell); // \
Stephen Hines651f13c2014-04-23 16:59:28 -07003593 // expected-warning {{calling function 'globalELR2' requires holding mutex 'cell.mu_' exclusively}}
DeLesley Hutchinsd278dbe2012-09-26 17:57:31 +00003594}
3595
3596
3597template<class T>
3598class FooT {
3599public:
3600 void elr(Cell<T>* c) __attribute__((exclusive_locks_required(c->mu_)));
3601};
3602
3603template<class T>
3604void FooT<T>::elr(Cell<T>* c1) { }
3605
3606void testFooT() {
3607 Cell<int> cell;
3608 FooT<int> foo;
3609 foo.elr(&cell); // \
Stephen Hines651f13c2014-04-23 16:59:28 -07003610 // expected-warning {{calling function 'elr' requires holding mutex 'cell.mu_' exclusively}}
DeLesley Hutchinsd278dbe2012-09-26 17:57:31 +00003611}
3612
3613} // end namespace TemplateFunctionParamRemapTest
3614
DeLesley Hutchinsef2388b2012-10-05 22:38:19 +00003615
3616namespace SelfConstructorTest {
3617
3618class SelfLock {
3619public:
3620 SelfLock() EXCLUSIVE_LOCK_FUNCTION(mu_);
3621 ~SelfLock() UNLOCK_FUNCTION(mu_);
3622
3623 void foo() EXCLUSIVE_LOCKS_REQUIRED(mu_);
3624
3625 Mutex mu_;
3626};
3627
3628class LOCKABLE SelfLock2 {
3629public:
3630 SelfLock2() EXCLUSIVE_LOCK_FUNCTION();
3631 ~SelfLock2() UNLOCK_FUNCTION();
3632
3633 void foo() EXCLUSIVE_LOCKS_REQUIRED(this);
3634};
3635
3636
3637void test() {
3638 SelfLock s;
3639 s.foo();
3640}
3641
3642void test2() {
3643 SelfLock2 s2;
3644 s2.foo();
3645}
3646
3647} // end namespace SelfConstructorTest
3648
DeLesley Hutchins3ce9fae2012-10-12 21:38:12 +00003649
3650namespace MultipleAttributeTest {
3651
3652class Foo {
3653 Mutex mu1_;
3654 Mutex mu2_;
3655 int a GUARDED_BY(mu1_);
3656 int b GUARDED_BY(mu2_);
3657 int c GUARDED_BY(mu1_) GUARDED_BY(mu2_);
3658 int* d PT_GUARDED_BY(mu1_) PT_GUARDED_BY(mu2_);
3659
3660 void foo1() EXCLUSIVE_LOCKS_REQUIRED(mu1_)
3661 EXCLUSIVE_LOCKS_REQUIRED(mu2_);
3662 void foo2() SHARED_LOCKS_REQUIRED(mu1_)
3663 SHARED_LOCKS_REQUIRED(mu2_);
3664 void foo3() LOCKS_EXCLUDED(mu1_)
3665 LOCKS_EXCLUDED(mu2_);
3666 void lock() EXCLUSIVE_LOCK_FUNCTION(mu1_)
3667 EXCLUSIVE_LOCK_FUNCTION(mu2_);
DeLesley Hutchins56968842013-04-08 20:11:11 +00003668 void readerlock() SHARED_LOCK_FUNCTION(mu1_)
3669 SHARED_LOCK_FUNCTION(mu2_);
DeLesley Hutchins3ce9fae2012-10-12 21:38:12 +00003670 void unlock() UNLOCK_FUNCTION(mu1_)
3671 UNLOCK_FUNCTION(mu2_);
3672 bool trylock() EXCLUSIVE_TRYLOCK_FUNCTION(true, mu1_)
3673 EXCLUSIVE_TRYLOCK_FUNCTION(true, mu2_);
3674 bool readertrylock() SHARED_TRYLOCK_FUNCTION(true, mu1_)
3675 SHARED_TRYLOCK_FUNCTION(true, mu2_);
Stephen Hines651f13c2014-04-23 16:59:28 -07003676 void assertBoth() ASSERT_EXCLUSIVE_LOCK(mu1_)
3677 ASSERT_EXCLUSIVE_LOCK(mu2_);
3678 void assertShared() ASSERT_SHARED_LOCK(mu1_)
3679 ASSERT_SHARED_LOCK(mu2_);
DeLesley Hutchins3ce9fae2012-10-12 21:38:12 +00003680
3681 void test();
Stephen Hines651f13c2014-04-23 16:59:28 -07003682 void testAssert();
3683 void testAssertShared();
DeLesley Hutchins3ce9fae2012-10-12 21:38:12 +00003684};
3685
3686
3687void Foo::foo1() {
3688 a = 1;
3689 b = 2;
3690}
3691
3692void Foo::foo2() {
3693 int result = a + b;
3694}
3695
3696void Foo::foo3() { }
DeLesley Hutchins56968842013-04-08 20:11:11 +00003697void Foo::lock() { mu1_.Lock(); mu2_.Lock(); }
3698void Foo::readerlock() { mu1_.ReaderLock(); mu2_.ReaderLock(); }
3699void Foo::unlock() { mu1_.Unlock(); mu2_.Unlock(); }
DeLesley Hutchins3ce9fae2012-10-12 21:38:12 +00003700bool Foo::trylock() { return true; }
3701bool Foo::readertrylock() { return true; }
3702
3703
3704void Foo::test() {
3705 mu1_.Lock();
3706 foo1(); // expected-warning {{}}
3707 c = 0; // expected-warning {{}}
3708 *d = 0; // expected-warning {{}}
3709 mu1_.Unlock();
3710
3711 mu1_.ReaderLock();
3712 foo2(); // expected-warning {{}}
3713 int x = c; // expected-warning {{}}
3714 int y = *d; // expected-warning {{}}
3715 mu1_.Unlock();
3716
3717 mu2_.Lock();
3718 foo3(); // expected-warning {{}}
3719 mu2_.Unlock();
3720
3721 lock();
3722 a = 0;
3723 b = 0;
3724 unlock();
3725
3726 readerlock();
3727 int z = a + b;
3728 unlock();
3729
3730 if (trylock()) {
3731 a = 0;
3732 b = 0;
3733 unlock();
3734 }
3735
3736 if (readertrylock()) {
3737 int zz = a + b;
3738 unlock();
3739 }
3740}
3741
Stephen Hines651f13c2014-04-23 16:59:28 -07003742// Force duplication of attributes
3743void Foo::assertBoth() { }
3744void Foo::assertShared() { }
3745
3746void Foo::testAssert() {
3747 assertBoth();
3748 a = 0;
3749 b = 0;
3750}
3751
3752void Foo::testAssertShared() {
3753 assertShared();
3754 int zz = a + b;
3755}
3756
DeLesley Hutchins3ce9fae2012-10-12 21:38:12 +00003757
3758} // end namespace MultipleAttributeTest
3759
3760
DeLesley Hutchins91e20612012-12-05 01:20:45 +00003761namespace GuardedNonPrimitiveTypeTest {
3762
3763
3764class Data {
3765public:
3766 Data(int i) : dat(i) { }
3767
3768 int getValue() const { return dat; }
3769 void setValue(int i) { dat = i; }
3770
3771 int operator[](int i) const { return dat; }
3772 int& operator[](int i) { return dat; }
3773
3774 void operator()() { }
3775
3776private:
3777 int dat;
3778};
3779
3780
3781class DataCell {
3782public:
3783 DataCell(const Data& d) : dat(d) { }
3784
3785private:
3786 Data dat;
3787};
3788
3789
3790void showDataCell(const DataCell& dc);
3791
3792
3793class Foo {
3794public:
3795 // method call tests
3796 void test() {
3797 data_.setValue(0); // FIXME -- should be writing \
Stephen Hines651f13c2014-04-23 16:59:28 -07003798 // expected-warning {{reading variable 'data_' requires holding mutex 'mu_'}}
DeLesley Hutchins91e20612012-12-05 01:20:45 +00003799 int a = data_.getValue(); // \
Stephen Hines651f13c2014-04-23 16:59:28 -07003800 // expected-warning {{reading variable 'data_' requires holding mutex 'mu_'}}
DeLesley Hutchins91e20612012-12-05 01:20:45 +00003801
3802 datap1_->setValue(0); // FIXME -- should be writing \
Stephen Hines651f13c2014-04-23 16:59:28 -07003803 // expected-warning {{reading variable 'datap1_' requires holding mutex 'mu_'}}
DeLesley Hutchins91e20612012-12-05 01:20:45 +00003804 a = datap1_->getValue(); // \
Stephen Hines651f13c2014-04-23 16:59:28 -07003805 // expected-warning {{reading variable 'datap1_' requires holding mutex 'mu_'}}
DeLesley Hutchins91e20612012-12-05 01:20:45 +00003806
3807 datap2_->setValue(0); // FIXME -- should be writing \
Stephen Hines651f13c2014-04-23 16:59:28 -07003808 // expected-warning {{reading the value pointed to by 'datap2_' requires holding mutex 'mu_'}}
DeLesley Hutchins91e20612012-12-05 01:20:45 +00003809 a = datap2_->getValue(); // \
Stephen Hines651f13c2014-04-23 16:59:28 -07003810 // expected-warning {{reading the value pointed to by 'datap2_' requires holding mutex 'mu_'}}
DeLesley Hutchins91e20612012-12-05 01:20:45 +00003811
3812 (*datap2_).setValue(0); // FIXME -- should be writing \
Stephen Hines651f13c2014-04-23 16:59:28 -07003813 // expected-warning {{reading the value pointed to by 'datap2_' requires holding mutex 'mu_'}}
DeLesley Hutchins91e20612012-12-05 01:20:45 +00003814 a = (*datap2_).getValue(); // \
Stephen Hines651f13c2014-04-23 16:59:28 -07003815 // expected-warning {{reading the value pointed to by 'datap2_' requires holding mutex 'mu_'}}
DeLesley Hutchins91e20612012-12-05 01:20:45 +00003816
3817 mu_.Lock();
3818 data_.setValue(1);
3819 datap1_->setValue(1);
3820 datap2_->setValue(1);
3821 mu_.Unlock();
3822
3823 mu_.ReaderLock();
3824 a = data_.getValue();
3825 datap1_->setValue(0); // reads datap1_, writes *datap1_
3826 a = datap1_->getValue();
3827 a = datap2_->getValue();
3828 mu_.Unlock();
3829 }
3830
3831 // operator tests
3832 void test2() {
Stephen Hines651f13c2014-04-23 16:59:28 -07003833 data_ = Data(1); // expected-warning {{writing variable 'data_' requires holding mutex 'mu_' exclusively}}
3834 *datap1_ = data_; // expected-warning {{reading variable 'datap1_' requires holding mutex 'mu_'}} \
3835 // expected-warning {{reading variable 'data_' requires holding mutex 'mu_'}}
3836 *datap2_ = data_; // expected-warning {{writing the value pointed to by 'datap2_' requires holding mutex 'mu_' exclusively}} \
3837 // expected-warning {{reading variable 'data_' requires holding mutex 'mu_'}}
3838 data_ = *datap1_; // expected-warning {{writing variable 'data_' requires holding mutex 'mu_' exclusively}} \
3839 // expected-warning {{reading variable 'datap1_' requires holding mutex 'mu_'}}
3840 data_ = *datap2_; // expected-warning {{writing variable 'data_' requires holding mutex 'mu_' exclusively}} \
3841 // expected-warning {{reading the value pointed to by 'datap2_' requires holding mutex 'mu_'}}
DeLesley Hutchins91e20612012-12-05 01:20:45 +00003842
Stephen Hines651f13c2014-04-23 16:59:28 -07003843 data_[0] = 0; // expected-warning {{reading variable 'data_' requires holding mutex 'mu_'}}
3844 (*datap2_)[0] = 0; // expected-warning {{reading the value pointed to by 'datap2_' requires holding mutex 'mu_'}}
DeLesley Hutchins91e20612012-12-05 01:20:45 +00003845
Stephen Hines651f13c2014-04-23 16:59:28 -07003846 data_(); // expected-warning {{reading variable 'data_' requires holding mutex 'mu_'}}
DeLesley Hutchins91e20612012-12-05 01:20:45 +00003847 }
3848
3849 // const operator tests
3850 void test3() const {
Stephen Hines651f13c2014-04-23 16:59:28 -07003851 Data mydat(data_); // expected-warning {{reading variable 'data_' requires holding mutex 'mu_'}}
DeLesley Hutchins91e20612012-12-05 01:20:45 +00003852
3853 //FIXME
Stephen Hines651f13c2014-04-23 16:59:28 -07003854 //showDataCell(data_); // xpected-warning {{reading variable 'data_' requires holding mutex 'mu_'}}
3855 //showDataCell(*datap2_); // xpected-warning {{reading the value pointed to by 'datap2_' requires holding mutex 'mu_'}}
DeLesley Hutchins91e20612012-12-05 01:20:45 +00003856
Stephen Hines651f13c2014-04-23 16:59:28 -07003857 int a = data_[0]; // expected-warning {{reading variable 'data_' requires holding mutex 'mu_'}}
DeLesley Hutchins91e20612012-12-05 01:20:45 +00003858 }
3859
3860private:
3861 Mutex mu_;
3862 Data data_ GUARDED_BY(mu_);
3863 Data* datap1_ GUARDED_BY(mu_);
3864 Data* datap2_ PT_GUARDED_BY(mu_);
3865};
3866
DeLesley Hutchins91e20612012-12-05 01:20:45 +00003867} // end namespace GuardedNonPrimitiveTypeTest
3868
DeLesley Hutchins93699d22012-12-08 03:46:30 +00003869
3870namespace GuardedNonPrimitive_MemberAccess {
3871
3872class Cell {
3873public:
3874 Cell(int i);
3875
3876 void cellMethod();
3877
3878 int a;
3879};
3880
3881
3882class Foo {
3883public:
3884 int a;
3885 Cell c GUARDED_BY(cell_mu_);
3886 Cell* cp PT_GUARDED_BY(cell_mu_);
3887
3888 void myMethod();
3889
3890 Mutex cell_mu_;
3891};
3892
3893
3894class Bar {
3895private:
3896 Mutex mu_;
3897 Foo foo GUARDED_BY(mu_);
3898 Foo* foop PT_GUARDED_BY(mu_);
3899
3900 void test() {
Stephen Hines651f13c2014-04-23 16:59:28 -07003901 foo.myMethod(); // expected-warning {{reading variable 'foo' requires holding mutex 'mu_'}}
DeLesley Hutchins93699d22012-12-08 03:46:30 +00003902
Stephen Hines651f13c2014-04-23 16:59:28 -07003903 int fa = foo.a; // expected-warning {{reading variable 'foo' requires holding mutex 'mu_'}}
3904 foo.a = fa; // expected-warning {{writing variable 'foo' requires holding mutex 'mu_' exclusively}}
DeLesley Hutchins93699d22012-12-08 03:46:30 +00003905
Stephen Hines651f13c2014-04-23 16:59:28 -07003906 fa = foop->a; // expected-warning {{reading the value pointed to by 'foop' requires holding mutex 'mu_'}}
3907 foop->a = fa; // expected-warning {{writing the value pointed to by 'foop' requires holding mutex 'mu_' exclusively}}
DeLesley Hutchins93699d22012-12-08 03:46:30 +00003908
Stephen Hines651f13c2014-04-23 16:59:28 -07003909 fa = (*foop).a; // expected-warning {{reading the value pointed to by 'foop' requires holding mutex 'mu_'}}
3910 (*foop).a = fa; // expected-warning {{writing the value pointed to by 'foop' requires holding mutex 'mu_' exclusively}}
DeLesley Hutchins93699d22012-12-08 03:46:30 +00003911
Stephen Hines651f13c2014-04-23 16:59:28 -07003912 foo.c = Cell(0); // expected-warning {{writing variable 'foo' requires holding mutex 'mu_'}} \
3913 // expected-warning {{writing variable 'c' requires holding mutex 'foo.cell_mu_' exclusively}}
3914 foo.c.cellMethod(); // expected-warning {{reading variable 'foo' requires holding mutex 'mu_'}} \
3915 // expected-warning {{reading variable 'c' requires holding mutex 'foo.cell_mu_'}}
DeLesley Hutchins93699d22012-12-08 03:46:30 +00003916
Stephen Hines651f13c2014-04-23 16:59:28 -07003917 foop->c = Cell(0); // expected-warning {{writing the value pointed to by 'foop' requires holding mutex 'mu_'}} \
3918 // expected-warning {{writing variable 'c' requires holding mutex 'foop->cell_mu_' exclusively}}
3919 foop->c.cellMethod(); // expected-warning {{reading the value pointed to by 'foop' requires holding mutex 'mu_'}} \
3920 // expected-warning {{reading variable 'c' requires holding mutex 'foop->cell_mu_'}}
DeLesley Hutchins93699d22012-12-08 03:46:30 +00003921
Stephen Hines651f13c2014-04-23 16:59:28 -07003922 (*foop).c = Cell(0); // expected-warning {{writing the value pointed to by 'foop' requires holding mutex 'mu_'}} \
3923 // expected-warning {{writing variable 'c' requires holding mutex 'foop->cell_mu_' exclusively}}
3924 (*foop).c.cellMethod(); // expected-warning {{reading the value pointed to by 'foop' requires holding mutex 'mu_'}} \
3925 // expected-warning {{reading variable 'c' requires holding mutex 'foop->cell_mu_'}}
DeLesley Hutchins93699d22012-12-08 03:46:30 +00003926 };
3927};
3928
3929} // namespace GuardedNonPrimitive_MemberAccess
3930
DeLesley Hutchins0ecc2e92013-01-18 22:15:45 +00003931
3932namespace TestThrowExpr {
3933
3934class Foo {
3935 Mutex mu_;
3936
3937 bool hasError();
3938
3939 void test() {
3940 mu_.Lock();
3941 if (hasError()) {
3942 throw "ugly";
3943 }
3944 mu_.Unlock();
3945 }
3946};
3947
3948} // end namespace TestThrowExpr
3949
3950
DeLesley Hutchinsed4330b2013-02-07 19:01:07 +00003951namespace UnevaluatedContextTest {
3952
3953// parse attribute expressions in an unevaluated context.
3954
3955static inline Mutex* getMutex1();
3956static inline Mutex* getMutex2();
3957
3958void bar() EXCLUSIVE_LOCKS_REQUIRED(getMutex1());
3959
3960void bar2() EXCLUSIVE_LOCKS_REQUIRED(getMutex1(), getMutex2());
3961
3962} // end namespace UnevaluatedContextTest
3963
DeLesley Hutchins56968842013-04-08 20:11:11 +00003964
3965namespace LockUnlockFunctionTest {
3966
3967// Check built-in lock functions
3968class LOCKABLE MyLockable {
3969public:
3970 void lock() EXCLUSIVE_LOCK_FUNCTION() { mu_.Lock(); }
3971 void readerLock() SHARED_LOCK_FUNCTION() { mu_.ReaderLock(); }
3972 void unlock() UNLOCK_FUNCTION() { mu_.Unlock(); }
3973
3974private:
3975 Mutex mu_;
3976};
3977
3978
3979class Foo {
3980public:
3981 // Correct lock/unlock functions
3982 void lock() EXCLUSIVE_LOCK_FUNCTION(mu_) {
3983 mu_.Lock();
3984 }
3985
3986 void readerLock() SHARED_LOCK_FUNCTION(mu_) {
3987 mu_.ReaderLock();
3988 }
3989
3990 void unlock() UNLOCK_FUNCTION(mu_) {
3991 mu_.Unlock();
3992 }
3993
3994 // Check failure to lock.
3995 void lockBad() EXCLUSIVE_LOCK_FUNCTION(mu_) { // expected-note {{mutex acquired here}}
3996 mu2_.Lock();
3997 mu2_.Unlock();
Stephen Hines651f13c2014-04-23 16:59:28 -07003998 } // expected-warning {{expecting mutex 'mu_' to be held at the end of function}}
DeLesley Hutchins56968842013-04-08 20:11:11 +00003999
4000 void readerLockBad() SHARED_LOCK_FUNCTION(mu_) { // expected-note {{mutex acquired here}}
4001 mu2_.Lock();
4002 mu2_.Unlock();
Stephen Hines651f13c2014-04-23 16:59:28 -07004003 } // expected-warning {{expecting mutex 'mu_' to be held at the end of function}}
DeLesley Hutchins56968842013-04-08 20:11:11 +00004004
4005 void unlockBad() UNLOCK_FUNCTION(mu_) { // expected-note {{mutex acquired here}}
4006 mu2_.Lock();
4007 mu2_.Unlock();
Stephen Hines651f13c2014-04-23 16:59:28 -07004008 } // expected-warning {{mutex 'mu_' is still held at the end of function}}
DeLesley Hutchins56968842013-04-08 20:11:11 +00004009
4010 // Check locking the wrong thing.
4011 void lockBad2() EXCLUSIVE_LOCK_FUNCTION(mu_) { // expected-note {{mutex acquired here}}
4012 mu2_.Lock(); // expected-note {{mutex acquired here}}
Stephen Hines651f13c2014-04-23 16:59:28 -07004013 } // expected-warning {{expecting mutex 'mu_' to be held at the end of function}} \
4014 // expected-warning {{mutex 'mu2_' is still held at the end of function}}
DeLesley Hutchins56968842013-04-08 20:11:11 +00004015
4016
4017 void readerLockBad2() SHARED_LOCK_FUNCTION(mu_) { // expected-note {{mutex acquired here}}
4018 mu2_.ReaderLock(); // expected-note {{mutex acquired here}}
Stephen Hines651f13c2014-04-23 16:59:28 -07004019 } // expected-warning {{expecting mutex 'mu_' to be held at the end of function}} \
4020 // expected-warning {{mutex 'mu2_' is still held at the end of function}}
DeLesley Hutchins56968842013-04-08 20:11:11 +00004021
4022
4023 void unlockBad2() UNLOCK_FUNCTION(mu_) { // expected-note {{mutex acquired here}}
Stephen Hines651f13c2014-04-23 16:59:28 -07004024 mu2_.Unlock(); // expected-warning {{releasing mutex 'mu2_' that was not held}}
4025 } // expected-warning {{mutex 'mu_' is still held at the end of function}}
DeLesley Hutchins56968842013-04-08 20:11:11 +00004026
4027private:
4028 Mutex mu_;
4029 Mutex mu2_;
4030};
4031
4032} // end namespace LockUnlockFunctionTest
4033
DeLesley Hutchins5c6134f2013-05-17 23:02:59 +00004034
4035namespace AssertHeldTest {
4036
4037class Foo {
4038public:
4039 int c;
4040 int a GUARDED_BY(mu_);
4041 Mutex mu_;
4042
4043 void test1() {
4044 mu_.AssertHeld();
4045 int b = a;
4046 a = 0;
4047 }
4048
4049 void test2() {
4050 mu_.AssertReaderHeld();
4051 int b = a;
Stephen Hines651f13c2014-04-23 16:59:28 -07004052 a = 0; // expected-warning {{writing variable 'a' requires holding mutex 'mu_' exclusively}}
DeLesley Hutchins5c6134f2013-05-17 23:02:59 +00004053 }
4054
4055 void test3() {
4056 if (c) {
4057 mu_.AssertHeld();
4058 }
4059 else {
4060 mu_.AssertHeld();
4061 }
4062 int b = a;
4063 a = 0;
4064 }
4065
4066 void test4() EXCLUSIVE_LOCKS_REQUIRED(mu_) {
4067 mu_.AssertHeld();
4068 int b = a;
4069 a = 0;
4070 }
4071
4072 void test5() UNLOCK_FUNCTION(mu_) {
4073 mu_.AssertHeld();
4074 mu_.Unlock();
4075 }
4076
4077 void test6() {
4078 mu_.AssertHeld();
4079 mu_.Unlock();
4080 } // should this be a warning?
4081
4082 void test7() {
4083 if (c) {
4084 mu_.AssertHeld();
4085 }
4086 else {
4087 mu_.Lock();
4088 }
4089 int b = a;
4090 a = 0;
4091 mu_.Unlock();
4092 }
4093
4094 void test8() {
4095 if (c) {
4096 mu_.Lock();
4097 }
4098 else {
4099 mu_.AssertHeld();
4100 }
4101 int b = a;
4102 a = 0;
4103 mu_.Unlock();
4104 }
4105
4106 void test9() {
4107 if (c) {
4108 mu_.AssertHeld();
4109 }
4110 else {
4111 mu_.Lock(); // expected-note {{mutex acquired here}}
4112 }
Stephen Hines651f13c2014-04-23 16:59:28 -07004113 } // expected-warning {{mutex 'mu_' is still held at the end of function}}
DeLesley Hutchins5c6134f2013-05-17 23:02:59 +00004114
4115 void test10() {
4116 if (c) {
4117 mu_.Lock(); // expected-note {{mutex acquired here}}
4118 }
4119 else {
4120 mu_.AssertHeld();
4121 }
Stephen Hines651f13c2014-04-23 16:59:28 -07004122 } // expected-warning {{mutex 'mu_' is still held at the end of function}}
DeLesley Hutchins5c6134f2013-05-17 23:02:59 +00004123
4124 void assertMu() ASSERT_EXCLUSIVE_LOCK(mu_);
4125
4126 void test11() {
4127 assertMu();
4128 int b = a;
4129 a = 0;
4130 }
4131};
4132
4133} // end namespace AssertHeldTest
4134
4135
DeLesley Hutchins7336b9f2013-08-15 23:06:33 +00004136namespace LogicalConditionalTryLock {
4137
4138class Foo {
4139public:
4140 Mutex mu;
4141 int a GUARDED_BY(mu);
4142 bool c;
4143
4144 bool newc();
4145
4146 void test1() {
4147 if (c && mu.TryLock()) {
4148 a = 0;
4149 mu.Unlock();
4150 }
4151 }
4152
4153 void test2() {
4154 bool b = mu.TryLock();
4155 if (c && b) {
4156 a = 0;
4157 mu.Unlock();
4158 }
4159 }
4160
4161 void test3() {
4162 if (c || !mu.TryLock())
4163 return;
4164 a = 0;
4165 mu.Unlock();
4166 }
4167
4168 void test4() {
4169 while (c && mu.TryLock()) {
4170 a = 0;
4171 c = newc();
4172 mu.Unlock();
4173 }
4174 }
4175
4176 void test5() {
4177 while (c) {
4178 if (newc() || !mu.TryLock())
4179 break;
4180 a = 0;
4181 mu.Unlock();
4182 }
4183 }
4184
4185 void test6() {
4186 mu.Lock();
4187 do {
4188 a = 0;
4189 mu.Unlock();
4190 } while (newc() && mu.TryLock());
4191 }
4192
4193 void test7() {
4194 for (bool b = mu.TryLock(); c && b;) {
4195 a = 0;
4196 mu.Unlock();
4197 }
4198 }
4199
4200 void test8() {
4201 if (c && newc() && mu.TryLock()) {
4202 a = 0;
4203 mu.Unlock();
4204 }
4205 }
4206
4207 void test9() {
4208 if (!(c && newc() && mu.TryLock()))
4209 return;
4210 a = 0;
4211 mu.Unlock();
4212 }
DeLesley Hutchins6b725d12013-08-16 18:28:00 +00004213
4214 void test10() {
4215 if (!(c || !mu.TryLock())) {
4216 a = 0;
4217 mu.Unlock();
4218 }
4219 }
DeLesley Hutchins7336b9f2013-08-15 23:06:33 +00004220};
4221
4222} // end namespace LogicalConditionalTryLock
4223
DeLesley Hutchins43399fb2013-11-05 23:09:56 +00004224
4225
4226namespace PtGuardedByTest {
4227
4228void doSomething();
4229
4230class Cell {
4231 public:
4232 int a;
4233};
4234
4235
4236// This mainly duplicates earlier tests, but just to make sure...
4237class PtGuardedBySanityTest {
DeLesley Hutchinsf9495912013-11-08 19:42:01 +00004238 Mutex mu1;
4239 Mutex mu2;
4240 int* a GUARDED_BY(mu1) PT_GUARDED_BY(mu2);
4241 Cell* c GUARDED_BY(mu1) PT_GUARDED_BY(mu2);
4242 int sa[10] GUARDED_BY(mu1);
4243 Cell sc[10] GUARDED_BY(mu1);
DeLesley Hutchins43399fb2013-11-05 23:09:56 +00004244
4245 void test1() {
4246 mu1.Lock();
4247 if (a == 0) doSomething(); // OK, we don't dereference.
4248 a = 0;
4249 c = 0;
DeLesley Hutchinsf9495912013-11-08 19:42:01 +00004250 if (sa[0] == 42) doSomething();
4251 sa[0] = 57;
4252 if (sc[0].a == 42) doSomething();
4253 sc[0].a = 57;
DeLesley Hutchins43399fb2013-11-05 23:09:56 +00004254 mu1.Unlock();
4255 }
4256
4257 void test2() {
4258 mu1.ReaderLock();
Stephen Hines651f13c2014-04-23 16:59:28 -07004259 if (*a == 0) doSomething(); // expected-warning {{reading the value pointed to by 'a' requires holding mutex 'mu2'}}
4260 *a = 0; // expected-warning {{writing the value pointed to by 'a' requires holding mutex 'mu2' exclusively}}
DeLesley Hutchins43399fb2013-11-05 23:09:56 +00004261
Stephen Hines651f13c2014-04-23 16:59:28 -07004262 if (c->a == 0) doSomething(); // expected-warning {{reading the value pointed to by 'c' requires holding mutex 'mu2'}}
4263 c->a = 0; // expected-warning {{writing the value pointed to by 'c' requires holding mutex 'mu2' exclusively}}
DeLesley Hutchins43399fb2013-11-05 23:09:56 +00004264
Stephen Hines651f13c2014-04-23 16:59:28 -07004265 if ((*c).a == 0) doSomething(); // expected-warning {{reading the value pointed to by 'c' requires holding mutex 'mu2'}}
4266 (*c).a = 0; // expected-warning {{writing the value pointed to by 'c' requires holding mutex 'mu2' exclusively}}
DeLesley Hutchinsf9495912013-11-08 19:42:01 +00004267
Stephen Hines651f13c2014-04-23 16:59:28 -07004268 if (a[0] == 42) doSomething(); // expected-warning {{reading the value pointed to by 'a' requires holding mutex 'mu2'}}
4269 a[0] = 57; // expected-warning {{writing the value pointed to by 'a' requires holding mutex 'mu2' exclusively}}
4270 if (c[0].a == 42) doSomething(); // expected-warning {{reading the value pointed to by 'c' requires holding mutex 'mu2'}}
4271 c[0].a = 57; // expected-warning {{writing the value pointed to by 'c' requires holding mutex 'mu2' exclusively}}
DeLesley Hutchins43399fb2013-11-05 23:09:56 +00004272 mu1.Unlock();
4273 }
4274
4275 void test3() {
4276 mu2.Lock();
Stephen Hines651f13c2014-04-23 16:59:28 -07004277 if (*a == 0) doSomething(); // expected-warning {{reading variable 'a' requires holding mutex 'mu1'}}
4278 *a = 0; // expected-warning {{reading variable 'a' requires holding mutex 'mu1'}}
DeLesley Hutchins43399fb2013-11-05 23:09:56 +00004279
Stephen Hines651f13c2014-04-23 16:59:28 -07004280 if (c->a == 0) doSomething(); // expected-warning {{reading variable 'c' requires holding mutex 'mu1'}}
4281 c->a = 0; // expected-warning {{reading variable 'c' requires holding mutex 'mu1'}}
DeLesley Hutchins43399fb2013-11-05 23:09:56 +00004282
Stephen Hines651f13c2014-04-23 16:59:28 -07004283 if ((*c).a == 0) doSomething(); // expected-warning {{reading variable 'c' requires holding mutex 'mu1'}}
4284 (*c).a = 0; // expected-warning {{reading variable 'c' requires holding mutex 'mu1'}}
DeLesley Hutchinsf9495912013-11-08 19:42:01 +00004285
Stephen Hines651f13c2014-04-23 16:59:28 -07004286 if (a[0] == 42) doSomething(); // expected-warning {{reading variable 'a' requires holding mutex 'mu1'}}
4287 a[0] = 57; // expected-warning {{reading variable 'a' requires holding mutex 'mu1'}}
4288 if (c[0].a == 42) doSomething(); // expected-warning {{reading variable 'c' requires holding mutex 'mu1'}}
4289 c[0].a = 57; // expected-warning {{reading variable 'c' requires holding mutex 'mu1'}}
DeLesley Hutchins43399fb2013-11-05 23:09:56 +00004290 mu2.Unlock();
4291 }
4292
DeLesley Hutchinsf9495912013-11-08 19:42:01 +00004293 void test4() { // Literal arrays
Stephen Hines651f13c2014-04-23 16:59:28 -07004294 if (sa[0] == 42) doSomething(); // expected-warning {{reading variable 'sa' requires holding mutex 'mu1'}}
4295 sa[0] = 57; // expected-warning {{writing variable 'sa' requires holding mutex 'mu1' exclusively}}
4296 if (sc[0].a == 42) doSomething(); // expected-warning {{reading variable 'sc' requires holding mutex 'mu1'}}
4297 sc[0].a = 57; // expected-warning {{writing variable 'sc' requires holding mutex 'mu1' exclusively}}
DeLesley Hutchinsf9495912013-11-08 19:42:01 +00004298
Stephen Hines651f13c2014-04-23 16:59:28 -07004299 if (*sa == 42) doSomething(); // expected-warning {{reading variable 'sa' requires holding mutex 'mu1'}}
4300 *sa = 57; // expected-warning {{writing variable 'sa' requires holding mutex 'mu1' exclusively}}
4301 if ((*sc).a == 42) doSomething(); // expected-warning {{reading variable 'sc' requires holding mutex 'mu1'}}
4302 (*sc).a = 57; // expected-warning {{writing variable 'sc' requires holding mutex 'mu1' exclusively}}
4303 if (sc->a == 42) doSomething(); // expected-warning {{reading variable 'sc' requires holding mutex 'mu1'}}
4304 sc->a = 57; // expected-warning {{writing variable 'sc' requires holding mutex 'mu1' exclusively}}
DeLesley Hutchinsf9495912013-11-08 19:42:01 +00004305 }
4306
4307 void test5() {
DeLesley Hutchins43399fb2013-11-05 23:09:56 +00004308 mu1.ReaderLock(); // OK -- correct use.
4309 mu2.Lock();
4310 if (*a == 0) doSomething();
4311 *a = 0;
4312
4313 if (c->a == 0) doSomething();
4314 c->a = 0;
4315
4316 if ((*c).a == 0) doSomething();
4317 (*c).a = 0;
4318 mu2.Unlock();
4319 mu1.Unlock();
4320 }
4321};
4322
4323
4324class SmartPtr_PtGuardedBy_Test {
DeLesley Hutchins9a2f84b2013-11-06 18:40:01 +00004325 Mutex mu1;
DeLesley Hutchins43399fb2013-11-05 23:09:56 +00004326 Mutex mu2;
DeLesley Hutchins9a2f84b2013-11-06 18:40:01 +00004327 SmartPtr<int> sp GUARDED_BY(mu1) PT_GUARDED_BY(mu2);
4328 SmartPtr<Cell> sq GUARDED_BY(mu1) PT_GUARDED_BY(mu2);
DeLesley Hutchins43399fb2013-11-05 23:09:56 +00004329
DeLesley Hutchins9a2f84b2013-11-06 18:40:01 +00004330 void test1() {
4331 mu1.ReaderLock();
4332 mu2.Lock();
4333
4334 sp.get();
4335 if (*sp == 0) doSomething();
4336 *sp = 0;
4337 sq->a = 0;
4338
DeLesley Hutchinsf9495912013-11-08 19:42:01 +00004339 if (sp[0] == 0) doSomething();
4340 sp[0] = 0;
4341
DeLesley Hutchins9a2f84b2013-11-06 18:40:01 +00004342 mu2.Unlock();
4343 mu1.Unlock();
4344 }
4345
4346 void test2() {
4347 mu2.Lock();
4348
Stephen Hines651f13c2014-04-23 16:59:28 -07004349 sp.get(); // expected-warning {{reading variable 'sp' requires holding mutex 'mu1'}}
4350 if (*sp == 0) doSomething(); // expected-warning {{reading variable 'sp' requires holding mutex 'mu1'}}
4351 *sp = 0; // expected-warning {{reading variable 'sp' requires holding mutex 'mu1'}}
4352 sq->a = 0; // expected-warning {{reading variable 'sq' requires holding mutex 'mu1'}}
DeLesley Hutchinsf9495912013-11-08 19:42:01 +00004353
Stephen Hines651f13c2014-04-23 16:59:28 -07004354 if (sp[0] == 0) doSomething(); // expected-warning {{reading variable 'sp' requires holding mutex 'mu1'}}
4355 sp[0] = 0; // expected-warning {{reading variable 'sp' requires holding mutex 'mu1'}}
4356 if (sq[0].a == 0) doSomething(); // expected-warning {{reading variable 'sq' requires holding mutex 'mu1'}}
4357 sq[0].a = 0; // expected-warning {{reading variable 'sq' requires holding mutex 'mu1'}}
DeLesley Hutchins9a2f84b2013-11-06 18:40:01 +00004358
4359 mu2.Unlock();
4360 }
4361
4362 void test3() {
4363 mu1.Lock();
4364
4365 sp.get();
Stephen Hines651f13c2014-04-23 16:59:28 -07004366 if (*sp == 0) doSomething(); // expected-warning {{reading the value pointed to by 'sp' requires holding mutex 'mu2'}}
4367 *sp = 0; // expected-warning {{reading the value pointed to by 'sp' requires holding mutex 'mu2'}}
4368 sq->a = 0; // expected-warning {{reading the value pointed to by 'sq' requires holding mutex 'mu2'}}
DeLesley Hutchinsf9495912013-11-08 19:42:01 +00004369
Stephen Hines651f13c2014-04-23 16:59:28 -07004370 if (sp[0] == 0) doSomething(); // expected-warning {{reading the value pointed to by 'sp' requires holding mutex 'mu2'}}
4371 sp[0] = 0; // expected-warning {{reading the value pointed to by 'sp' requires holding mutex 'mu2'}}
4372 if (sq[0].a == 0) doSomething(); // expected-warning {{reading the value pointed to by 'sq' requires holding mutex 'mu2'}}
4373 sq[0].a = 0; // expected-warning {{reading the value pointed to by 'sq' requires holding mutex 'mu2'}}
DeLesley Hutchins9a2f84b2013-11-06 18:40:01 +00004374
4375 mu1.Unlock();
DeLesley Hutchins43399fb2013-11-05 23:09:56 +00004376 }
4377};
4378
4379} // end namespace PtGuardedByTest
4380
Bill Wendling44444462013-12-01 03:45:49 +00004381
4382namespace NonMemberCalleeICETest {
4383
4384class A {
4385 void Run() {
Stephen Hines651f13c2014-04-23 16:59:28 -07004386 (RunHelper)(); // expected-warning {{calling function 'RunHelper' requires holding mutex 'M' exclusively}}
Bill Wendling44444462013-12-01 03:45:49 +00004387 }
4388
4389 void RunHelper() __attribute__((exclusive_locks_required(M)));
4390 Mutex M;
4391};
4392
4393} // end namespace NonMemberCalleeICETest
4394
Stephen Hines651f13c2014-04-23 16:59:28 -07004395
4396namespace pt_guard_attribute_type {
4397 int i PT_GUARDED_BY(sls_mu); // expected-warning {{'pt_guarded_by' only applies to pointer types; type here is 'int'}}
4398 int j PT_GUARDED_VAR; // expected-warning {{'pt_guarded_var' only applies to pointer types; type here is 'int'}}
4399
4400 void test() {
4401 int i PT_GUARDED_BY(sls_mu); // expected-warning {{'pt_guarded_by' attribute only applies to fields and global variables}}
4402 int j PT_GUARDED_VAR; // expected-warning {{'pt_guarded_var' attribute only applies to fields and global variables}}
4403
4404 typedef int PT_GUARDED_BY(sls_mu) bad1; // expected-warning {{'pt_guarded_by' attribute only applies to fields and global variables}}
4405 typedef int PT_GUARDED_VAR bad2; // expected-warning {{'pt_guarded_var' attribute only applies to fields and global variables}}
4406 }
4407} // end namespace pt_guard_attribute_type
4408
4409
4410namespace ThreadAttributesOnLambdas {
4411
4412class Foo {
4413 Mutex mu_;
4414
4415 void LockedFunction() EXCLUSIVE_LOCKS_REQUIRED(mu_);
4416
4417 void test() {
4418 auto func1 = [this]() EXCLUSIVE_LOCKS_REQUIRED(mu_) {
4419 LockedFunction();
4420 };
4421
4422 auto func2 = [this]() NO_THREAD_SAFETY_ANALYSIS {
4423 LockedFunction();
4424 };
4425
4426 auto func3 = [this]() EXCLUSIVE_LOCK_FUNCTION(mu_) {
4427 mu_.Lock();
4428 };
4429
4430 func1(); // expected-warning {{calling function 'operator()' requires holding mutex 'mu_' exclusively}}
4431 func2();
4432 func3();
4433 mu_.Unlock();
4434 }
4435};
4436
4437} // end namespace ThreadAttributesOnLambdas
Stephen Hines176edba2014-12-01 14:53:08 -08004438
4439
4440
4441namespace AttributeExpressionCornerCases {
4442
4443class Foo {
4444 int a GUARDED_BY(getMu());
4445
4446 Mutex* getMu() LOCK_RETURNED("");
4447 Mutex* getUniv() LOCK_RETURNED("*");
4448
4449 void test1() {
4450 a = 0;
4451 }
4452
4453 void test2() EXCLUSIVE_LOCKS_REQUIRED(getUniv()) {
4454 a = 0;
4455 }
4456
4457 void foo(Mutex* mu) EXCLUSIVE_LOCKS_REQUIRED(mu);
4458
4459 void test3() {
4460 foo(nullptr);
4461 }
4462};
4463
4464
4465class MapTest {
4466 struct MuCell { Mutex* mu; };
4467
4468 MyMap<MyString, Mutex*> map;
4469 MyMap<MyString, MuCell> mapCell;
4470
4471 int a GUARDED_BY(map["foo"]);
4472 int b GUARDED_BY(mapCell["foo"].mu);
4473
4474 void test() {
4475 map["foo"]->Lock();
4476 a = 0;
4477 map["foo"]->Unlock();
4478 }
4479
4480 void test2() {
4481 mapCell["foo"].mu->Lock();
4482 b = 0;
4483 mapCell["foo"].mu->Unlock();
4484 }
4485};
4486
4487
4488class PreciseSmartPtr {
4489 SmartPtr<Mutex> mu;
4490 int val GUARDED_BY(mu);
4491
4492 static bool compare(PreciseSmartPtr& a, PreciseSmartPtr &b) {
4493 a.mu->Lock();
4494 bool result = (a.val == b.val); // expected-warning {{reading variable 'val' requires holding mutex 'b.mu'}} \
4495 // expected-note {{found near match 'a.mu'}}
4496 a.mu->Unlock();
4497 return result;
4498 }
4499};
4500
4501
4502class SmartRedeclare {
4503 SmartPtr<Mutex> mu;
4504 int val GUARDED_BY(mu);
4505
4506 void test() EXCLUSIVE_LOCKS_REQUIRED(mu);
4507 void test2() EXCLUSIVE_LOCKS_REQUIRED(mu.get());
4508 void test3() EXCLUSIVE_LOCKS_REQUIRED(mu.get());
4509};
4510
4511
4512void SmartRedeclare::test() EXCLUSIVE_LOCKS_REQUIRED(mu.get()) {
4513 val = 0;
4514}
4515
4516void SmartRedeclare::test2() EXCLUSIVE_LOCKS_REQUIRED(mu) {
4517 val = 0;
4518}
4519
4520void SmartRedeclare::test3() {
4521 val = 0;
4522}
4523
4524
4525namespace CustomMutex {
4526
4527
4528class LOCKABLE BaseMutex { };
4529class DerivedMutex : public BaseMutex { };
4530
4531void customLock(const BaseMutex *m) EXCLUSIVE_LOCK_FUNCTION(m);
4532void customUnlock(const BaseMutex *m) UNLOCK_FUNCTION(m);
4533
4534static struct DerivedMutex custMu;
4535
4536static void doSomethingRequiringLock() EXCLUSIVE_LOCKS_REQUIRED(custMu) { }
4537
4538void customTest() {
4539 customLock(reinterpret_cast<BaseMutex*>(&custMu)); // ignore casts
4540 doSomethingRequiringLock();
4541 customUnlock(reinterpret_cast<BaseMutex*>(&custMu));
4542}
4543
4544} // end namespace CustomMutex
4545
4546} // end AttributeExpressionCornerCases
4547
4548
4549namespace ScopedLockReturnedInvalid {
4550
4551class Opaque;
4552
4553Mutex* getMutex(Opaque* o) LOCK_RETURNED("");
4554
4555void test(Opaque* o) {
4556 MutexLock lock(getMutex(o));
4557}
4558
4559} // end namespace ScopedLockReturnedInvalid
4560
4561
4562namespace NegativeRequirements {
4563
4564class Bar {
4565 Mutex mu;
4566 int a GUARDED_BY(mu);
4567
4568public:
4569 void baz() EXCLUSIVE_LOCKS_REQUIRED(!mu) {
4570 mu.Lock();
4571 a = 0;
4572 mu.Unlock();
4573 }
4574};
4575
4576
4577class Foo {
4578 Mutex mu;
4579 int a GUARDED_BY(mu);
4580
4581public:
4582 void foo() {
4583 mu.Lock(); // warning? needs !mu?
4584 baz(); // expected-warning {{cannot call function 'baz' while mutex 'mu' is held}}
4585 bar();
4586 mu.Unlock();
4587 }
4588
4589 void bar() {
4590 bar2(); // expected-warning {{calling function 'bar2' requires holding '!mu'}}
4591 }
4592
4593 void bar2() EXCLUSIVE_LOCKS_REQUIRED(!mu) {
4594 baz();
4595 }
4596
4597 void baz() EXCLUSIVE_LOCKS_REQUIRED(!mu) {
4598 mu.Lock();
4599 a = 0;
4600 mu.Unlock();
4601 }
4602
4603 void test() {
4604 Bar b;
4605 b.baz(); // no warning -- in different class.
4606 }
4607};
4608
4609} // end namespace NegativeRequirements
4610
4611
4612namespace NegativeThreadRoles {
4613
4614typedef int __attribute__((capability("role"))) ThreadRole;
4615
4616void acquire(ThreadRole R) __attribute__((exclusive_lock_function(R))) __attribute__((no_thread_safety_analysis)) {}
4617void release(ThreadRole R) __attribute__((unlock_function(R))) __attribute__((no_thread_safety_analysis)) {}
4618
4619ThreadRole FlightControl, Logger;
4620
4621extern void enque_log_msg(const char *msg);
4622void log_msg(const char *msg) {
4623 enque_log_msg(msg);
4624}
4625
4626void dispatch_log(const char *msg) __attribute__((requires_capability(!FlightControl))) {}
4627void dispatch_log2(const char *msg) __attribute__((requires_capability(Logger))) {}
4628
4629void flight_control_entry(void) __attribute__((requires_capability(FlightControl))) {
4630 dispatch_log("wrong"); /* expected-warning {{cannot call function 'dispatch_log' while mutex 'FlightControl' is held}} */
4631 dispatch_log2("also wrong"); /* expected-warning {{calling function 'dispatch_log2' requires holding role 'Logger' exclusively}} */
4632}
4633
4634void spawn_fake_flight_control_thread(void) {
4635 acquire(FlightControl);
4636 flight_control_entry();
4637 release(FlightControl);
4638}
4639
4640extern const char *deque_log_msg(void) __attribute__((requires_capability(Logger)));
4641void logger_entry(void) __attribute__((requires_capability(Logger))) {
4642 const char *msg;
4643
4644 while ((msg = deque_log_msg())) {
4645 dispatch_log(msg);
4646 }
4647}
4648
4649void spawn_fake_logger_thread(void) {
4650 acquire(Logger);
4651 logger_entry();
4652 release(Logger);
4653}
4654
4655int main(void) {
4656 spawn_fake_flight_control_thread();
4657 spawn_fake_logger_thread();
4658
4659 for (;;)
4660 ; /* Pretend to dispatch things. */
4661
4662 return 0;
4663}
4664
4665} // end namespace NegativeThreadRoles
4666
4667
4668namespace AssertSharedExclusive {
4669
4670void doSomething();
4671
4672class Foo {
4673 Mutex mu;
4674 int a GUARDED_BY(mu);
4675
4676 void test() SHARED_LOCKS_REQUIRED(mu) {
4677 mu.AssertHeld();
4678 if (a > 0)
4679 doSomething();
4680 }
4681};
4682
4683} // end namespace AssertSharedExclusive
4684
4685
4686namespace RangeBasedForAndReferences {
4687
4688class Foo {
4689 struct MyStruct {
4690 int a;
4691 };
4692
4693 Mutex mu;
4694 int a GUARDED_BY(mu);
4695 MyContainer<int> cntr GUARDED_BY(mu);
4696 MyStruct s GUARDED_BY(mu);
4697 int arr[10] GUARDED_BY(mu);
4698
4699 void nonref_test() {
4700 int b = a; // expected-warning {{reading variable 'a' requires holding mutex 'mu'}}
4701 b = 0; // no warning
4702 }
4703
4704 void auto_test() {
4705 auto b = a; // expected-warning {{reading variable 'a' requires holding mutex 'mu'}}
4706 b = 0; // no warning
4707 auto &c = a; // no warning
4708 c = 0; // expected-warning {{writing variable 'a' requires holding mutex 'mu' exclusively}}
4709 }
4710
4711 void ref_test() {
4712 int &b = a;
4713 int &c = b;
4714 int &d = c;
4715 b = 0; // expected-warning {{writing variable 'a' requires holding mutex 'mu' exclusively}}
4716 c = 0; // expected-warning {{writing variable 'a' requires holding mutex 'mu' exclusively}}
4717 d = 0; // expected-warning {{writing variable 'a' requires holding mutex 'mu' exclusively}}
4718
4719 MyStruct &rs = s;
4720 rs.a = 0; // expected-warning {{writing variable 's' requires holding mutex 'mu' exclusively}}
4721
4722 int (&rarr)[10] = arr;
4723 rarr[2] = 0; // expected-warning {{writing variable 'arr' requires holding mutex 'mu' exclusively}}
4724 }
4725
4726 void ptr_test() {
4727 int *b = &a;
4728 *b = 0; // no expected warning yet
4729 }
4730
4731 void for_test() {
4732 int total = 0;
4733 for (int i : cntr) { // expected-warning2 {{reading variable 'cntr' requires holding mutex 'mu'}}
4734 total += i;
4735 }
4736 }
4737};
4738
4739
4740} // end namespace RangeBasedForAndReferences
4741
4742
4743
4744namespace PassByRefTest {
4745
4746class Foo {
4747public:
4748 Foo() : a(0), b(0) { }
4749
4750 int a;
4751 int b;
4752
4753 void operator+(const Foo& f);
4754
4755 void operator[](const Foo& g);
4756};
4757
4758template<class T>
4759T&& mymove(T& f);
4760
4761
4762// test top-level functions
4763void copy(Foo f);
4764void write1(Foo& f);
4765void write2(int a, Foo& f);
4766void read1(const Foo& f);
4767void read2(int a, const Foo& f);
4768void destroy(Foo&& f);
4769
4770void operator/(const Foo& f, const Foo& g);
4771void operator*(const Foo& f, const Foo& g);
4772
4773
4774
4775
4776class Bar {
4777public:
4778 Mutex mu;
4779 Foo foo GUARDED_BY(mu);
4780 Foo foo2 GUARDED_BY(mu);
4781 Foo* foop PT_GUARDED_BY(mu);
4782 SmartPtr<Foo> foosp PT_GUARDED_BY(mu);
4783
4784 // test methods.
4785 void mwrite1(Foo& f);
4786 void mwrite2(int a, Foo& f);
4787 void mread1(const Foo& f);
4788 void mread2(int a, const Foo& f);
4789
4790 // static methods
4791 static void smwrite1(Foo& f);
4792 static void smwrite2(int a, Foo& f);
4793 static void smread1(const Foo& f);
4794 static void smread2(int a, const Foo& f);
4795
4796 void operator<<(const Foo& f);
4797
4798 void test1() {
4799 copy(foo); // expected-warning {{reading variable 'foo' requires holding mutex 'mu'}}
4800 write1(foo); // expected-warning {{passing variable 'foo' by reference requires holding mutex 'mu'}}
4801 write2(10, foo); // expected-warning {{passing variable 'foo' by reference requires holding mutex 'mu'}}
4802 read1(foo); // expected-warning {{passing variable 'foo' by reference requires holding mutex 'mu'}}
4803 read2(10, foo); // expected-warning {{passing variable 'foo' by reference requires holding mutex 'mu'}}
4804 destroy(mymove(foo)); // expected-warning {{passing variable 'foo' by reference requires holding mutex 'mu'}}
4805
4806 mwrite1(foo); // expected-warning {{passing variable 'foo' by reference requires holding mutex 'mu'}}
4807 mwrite2(10, foo); // expected-warning {{passing variable 'foo' by reference requires holding mutex 'mu'}}
4808 mread1(foo); // expected-warning {{passing variable 'foo' by reference requires holding mutex 'mu'}}
4809 mread2(10, foo); // expected-warning {{passing variable 'foo' by reference requires holding mutex 'mu'}}
4810
4811 smwrite1(foo); // expected-warning {{passing variable 'foo' by reference requires holding mutex 'mu'}}
4812 smwrite2(10, foo); // expected-warning {{passing variable 'foo' by reference requires holding mutex 'mu'}}
4813 smread1(foo); // expected-warning {{passing variable 'foo' by reference requires holding mutex 'mu'}}
4814 smread2(10, foo); // expected-warning {{passing variable 'foo' by reference requires holding mutex 'mu'}}
4815
4816 foo + foo2; // expected-warning {{reading variable 'foo' requires holding mutex 'mu'}} \
4817 // expected-warning {{passing variable 'foo2' by reference requires holding mutex 'mu'}}
4818 foo / foo2; // expected-warning {{reading variable 'foo' requires holding mutex 'mu'}} \
4819 // expected-warning {{passing variable 'foo2' by reference requires holding mutex 'mu'}}
4820 foo * foo2; // expected-warning {{reading variable 'foo' requires holding mutex 'mu'}} \
4821 // expected-warning {{passing variable 'foo2' by reference requires holding mutex 'mu'}}
4822 foo[foo2]; // expected-warning {{reading variable 'foo' requires holding mutex 'mu'}} \
4823 // expected-warning {{passing variable 'foo2' by reference requires holding mutex 'mu'}}
4824 (*this) << foo; // expected-warning {{passing variable 'foo' by reference requires holding mutex 'mu'}}
4825
4826 copy(*foop); // expected-warning {{reading the value pointed to by 'foop' requires holding mutex 'mu'}}
4827 write1(*foop); // expected-warning {{passing the value that 'foop' points to by reference requires holding mutex 'mu'}}
4828 write2(10, *foop); // expected-warning {{passing the value that 'foop' points to by reference requires holding mutex 'mu'}}
4829 read1(*foop); // expected-warning {{passing the value that 'foop' points to by reference requires holding mutex 'mu'}}
4830 read2(10, *foop); // expected-warning {{passing the value that 'foop' points to by reference requires holding mutex 'mu'}}
4831 destroy(mymove(*foop)); // expected-warning {{passing the value that 'foop' points to by reference requires holding mutex 'mu'}}
4832
4833 copy(*foosp); // expected-warning {{reading the value pointed to by 'foosp' requires holding mutex 'mu'}}
4834 write1(*foosp); // expected-warning {{reading the value pointed to by 'foosp' requires holding mutex 'mu'}}
4835 write2(10, *foosp); // expected-warning {{reading the value pointed to by 'foosp' requires holding mutex 'mu'}}
4836 read1(*foosp); // expected-warning {{reading the value pointed to by 'foosp' requires holding mutex 'mu'}}
4837 read2(10, *foosp); // expected-warning {{reading the value pointed to by 'foosp' requires holding mutex 'mu'}}
4838 destroy(mymove(*foosp)); // expected-warning {{reading the value pointed to by 'foosp' requires holding mutex 'mu'}}
4839
Stephen Hines0e2c34f2015-03-23 12:09:02 -07004840 // TODO -- these require better smart pointer handling.
Stephen Hines176edba2014-12-01 14:53:08 -08004841 copy(*foosp.get());
4842 write1(*foosp.get());
4843 write2(10, *foosp.get());
4844 read1(*foosp.get());
4845 read2(10, *foosp.get());
4846 destroy(mymove(*foosp.get()));
4847 }
4848};
4849
4850
4851} // end namespace PassByRefTest
4852
Stephen Hines0e2c34f2015-03-23 12:09:02 -07004853
4854namespace AcquiredBeforeAfterText {
4855
4856class Foo {
4857 Mutex mu1 ACQUIRED_BEFORE(mu2, mu3);
4858 Mutex mu2;
4859 Mutex mu3;
4860
4861 void test1() {
4862 mu1.Lock();
4863 mu2.Lock();
4864 mu3.Lock();
4865
4866 mu3.Unlock();
4867 mu2.Unlock();
4868 mu1.Unlock();
4869 }
4870
4871 void test2() {
4872 mu2.Lock();
4873 mu1.Lock(); // expected-warning {{mutex 'mu1' must be acquired before 'mu2'}}
4874 mu1.Unlock();
4875 mu2.Unlock();
4876 }
4877
4878 void test3() {
4879 mu3.Lock();
4880 mu1.Lock(); // expected-warning {{mutex 'mu1' must be acquired before 'mu3'}}
4881 mu1.Unlock();
4882 mu3.Unlock();
4883 }
4884
4885 void test4() EXCLUSIVE_LOCKS_REQUIRED(mu1) {
4886 mu2.Lock();
4887 mu2.Unlock();
4888 }
4889
4890 void test5() EXCLUSIVE_LOCKS_REQUIRED(mu2) {
4891 mu1.Lock(); // expected-warning {{mutex 'mu1' must be acquired before 'mu2'}}
4892 mu1.Unlock();
4893 }
4894
4895 void test6() EXCLUSIVE_LOCKS_REQUIRED(mu2) {
4896 mu1.AssertHeld();
4897 }
4898
4899 void test7() EXCLUSIVE_LOCKS_REQUIRED(mu1, mu2, mu3) { }
4900
4901 void test8() EXCLUSIVE_LOCKS_REQUIRED(mu3, mu2, mu1) { }
4902};
4903
4904
4905class Foo2 {
4906 Mutex mu1;
4907 Mutex mu2 ACQUIRED_AFTER(mu1);
4908 Mutex mu3 ACQUIRED_AFTER(mu1);
4909
4910 void test1() {
4911 mu1.Lock();
4912 mu2.Lock();
4913 mu3.Lock();
4914
4915 mu3.Unlock();
4916 mu2.Unlock();
4917 mu1.Unlock();
4918 }
4919
4920 void test2() {
4921 mu2.Lock();
4922 mu1.Lock(); // expected-warning {{mutex 'mu1' must be acquired before 'mu2'}}
4923 mu1.Unlock();
4924 mu2.Unlock();
4925 }
4926
4927 void test3() {
4928 mu3.Lock();
4929 mu1.Lock(); // expected-warning {{mutex 'mu1' must be acquired before 'mu3'}}
4930 mu1.Unlock();
4931 mu3.Unlock();
4932 }
4933};
4934
4935
4936class Foo3 {
4937 Mutex mu1 ACQUIRED_BEFORE(mu2);
4938 Mutex mu2;
4939 Mutex mu3 ACQUIRED_AFTER(mu2) ACQUIRED_BEFORE(mu4);
4940 Mutex mu4;
4941
4942 void test1() {
4943 mu1.Lock();
4944 mu2.Lock();
4945 mu3.Lock();
4946 mu4.Lock();
4947
4948 mu4.Unlock();
4949 mu3.Unlock();
4950 mu2.Unlock();
4951 mu1.Unlock();
4952 }
4953
4954 void test2() {
4955 mu4.Lock();
4956 mu2.Lock(); // expected-warning {{mutex 'mu2' must be acquired before 'mu4'}}
4957
4958 mu2.Unlock();
4959 mu4.Unlock();
4960 }
4961
4962 void test3() {
4963 mu4.Lock();
4964 mu1.Lock(); // expected-warning {{mutex 'mu1' must be acquired before 'mu4'}}
4965
4966 mu1.Unlock();
4967 mu4.Unlock();
4968 }
4969
4970 void test4() {
4971 mu3.Lock();
4972 mu1.Lock(); // expected-warning {{mutex 'mu1' must be acquired before 'mu3'}}
4973
4974 mu1.Unlock();
4975 mu3.Unlock();
4976 }
4977};
4978
4979
4980// Test transitive DAG traversal with AFTER
4981class Foo4 {
4982 Mutex mu1;
4983 Mutex mu2 ACQUIRED_AFTER(mu1);
4984 Mutex mu3 ACQUIRED_AFTER(mu1);
4985 Mutex mu4 ACQUIRED_AFTER(mu2, mu3);
4986 Mutex mu5 ACQUIRED_AFTER(mu4);
4987 Mutex mu6 ACQUIRED_AFTER(mu4);
4988 Mutex mu7 ACQUIRED_AFTER(mu5, mu6);
4989 Mutex mu8 ACQUIRED_AFTER(mu7);
4990
4991 void test() {
4992 mu8.Lock();
4993 mu1.Lock(); // expected-warning {{mutex 'mu1' must be acquired before 'mu8'}}
4994 mu1.Unlock();
4995 mu8.Unlock();
4996 }
4997};
4998
4999
5000// Test transitive DAG traversal with BEFORE
5001class Foo5 {
5002 Mutex mu1 ACQUIRED_BEFORE(mu2, mu3);
5003 Mutex mu2 ACQUIRED_BEFORE(mu4);
5004 Mutex mu3 ACQUIRED_BEFORE(mu4);
5005 Mutex mu4 ACQUIRED_BEFORE(mu5, mu6);
5006 Mutex mu5 ACQUIRED_BEFORE(mu7);
5007 Mutex mu6 ACQUIRED_BEFORE(mu7);
5008 Mutex mu7 ACQUIRED_BEFORE(mu8);
5009 Mutex mu8;
5010
5011 void test() {
5012 mu8.Lock();
5013 mu1.Lock(); // expected-warning {{mutex 'mu1' must be acquired before 'mu8'}}
5014 mu1.Unlock();
5015 mu8.Unlock();
5016 }
5017};
5018
5019
5020class Foo6 {
5021 Mutex mu1 ACQUIRED_AFTER(mu3); // expected-warning {{Cycle in acquired_before/after dependencies, starting with 'mu1'}}
5022 Mutex mu2 ACQUIRED_AFTER(mu1); // expected-warning {{Cycle in acquired_before/after dependencies, starting with 'mu2'}}
5023 Mutex mu3 ACQUIRED_AFTER(mu2); // expected-warning {{Cycle in acquired_before/after dependencies, starting with 'mu3'}}
5024
5025 Mutex mu_b ACQUIRED_BEFORE(mu_b); // expected-warning {{Cycle in acquired_before/after dependencies, starting with 'mu_b'}}
5026 Mutex mu_a ACQUIRED_AFTER(mu_a); // expected-warning {{Cycle in acquired_before/after dependencies, starting with 'mu_a'}}
5027
5028 void test0() {
5029 mu_a.Lock();
5030 mu_b.Lock();
5031 mu_b.Unlock();
5032 mu_a.Unlock();
5033 }
5034
5035 void test1a() {
5036 mu1.Lock();
5037 mu1.Unlock();
5038 }
5039
5040 void test1b() {
5041 mu1.Lock();
5042 mu_a.Lock();
5043 mu_b.Lock();
5044 mu_b.Unlock();
5045 mu_a.Unlock();
5046 mu1.Unlock();
5047 }
5048
5049 void test() {
5050 mu2.Lock();
5051 mu2.Unlock();
5052 }
5053
5054 void test3() {
5055 mu3.Lock();
5056 mu3.Unlock();
5057 }
5058};
5059
5060} // end namespace AcquiredBeforeAfterTest
5061
5062
5063namespace ScopedAdoptTest {
5064
5065class Foo {
5066 Mutex mu;
5067 int a GUARDED_BY(mu);
5068 int b;
5069
5070 void test1() EXCLUSIVE_UNLOCK_FUNCTION(mu) {
5071 MutexLock slock(&mu, true);
5072 a = 0;
5073 }
5074
5075 void test2() SHARED_UNLOCK_FUNCTION(mu) {
5076 ReaderMutexLock slock(&mu, true);
5077 b = a;
5078 }
5079
5080 void test3() EXCLUSIVE_LOCKS_REQUIRED(mu) { // expected-note {{mutex acquired here}}
5081 MutexLock slock(&mu, true);
5082 a = 0;
5083 } // expected-warning {{expecting mutex 'mu' to be held at the end of function}}
5084
5085 void test4() SHARED_LOCKS_REQUIRED(mu) { // expected-note {{mutex acquired here}}
5086 ReaderMutexLock slock(&mu, true);
5087 b = a;
5088 } // expected-warning {{expecting mutex 'mu' to be held at the end of function}}
5089
5090};
5091
5092} // end namespace ScopedAdoptTest
5093