1*67e74705SXin Li // RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 -Wthread-safety -Wthread-safety-beta -Wno-thread-safety-negative -fcxx-exceptions %s
2*67e74705SXin Li
3*67e74705SXin Li // FIXME: should also run %clang_cc1 -fsyntax-only -verify -Wthread-safety -std=c++11 -Wc++98-compat %s
4*67e74705SXin Li // FIXME: should also run %clang_cc1 -fsyntax-only -verify -Wthread-safety %s
5*67e74705SXin Li
6*67e74705SXin Li #define LOCKABLE __attribute__((lockable))
7*67e74705SXin Li #define SCOPED_LOCKABLE __attribute__((scoped_lockable))
8*67e74705SXin Li #define GUARDED_BY(x) __attribute__((guarded_by(x)))
9*67e74705SXin Li #define GUARDED_VAR __attribute__((guarded_var))
10*67e74705SXin Li #define PT_GUARDED_BY(x) __attribute__((pt_guarded_by(x)))
11*67e74705SXin Li #define PT_GUARDED_VAR __attribute__((pt_guarded_var))
12*67e74705SXin Li #define ACQUIRED_AFTER(...) __attribute__((acquired_after(__VA_ARGS__)))
13*67e74705SXin Li #define ACQUIRED_BEFORE(...) __attribute__((acquired_before(__VA_ARGS__)))
14*67e74705SXin Li #define EXCLUSIVE_LOCK_FUNCTION(...) __attribute__((exclusive_lock_function(__VA_ARGS__)))
15*67e74705SXin Li #define SHARED_LOCK_FUNCTION(...) __attribute__((shared_lock_function(__VA_ARGS__)))
16*67e74705SXin Li #define ASSERT_EXCLUSIVE_LOCK(...) __attribute__((assert_exclusive_lock(__VA_ARGS__)))
17*67e74705SXin Li #define ASSERT_SHARED_LOCK(...) __attribute__((assert_shared_lock(__VA_ARGS__)))
18*67e74705SXin Li #define EXCLUSIVE_TRYLOCK_FUNCTION(...) __attribute__((exclusive_trylock_function(__VA_ARGS__)))
19*67e74705SXin Li #define SHARED_TRYLOCK_FUNCTION(...) __attribute__((shared_trylock_function(__VA_ARGS__)))
20*67e74705SXin Li #define UNLOCK_FUNCTION(...) __attribute__((unlock_function(__VA_ARGS__)))
21*67e74705SXin Li #define EXCLUSIVE_UNLOCK_FUNCTION(...) __attribute__((release_capability(__VA_ARGS__)))
22*67e74705SXin Li #define SHARED_UNLOCK_FUNCTION(...) __attribute__((release_shared_capability(__VA_ARGS__)))
23*67e74705SXin Li #define LOCK_RETURNED(x) __attribute__((lock_returned(x)))
24*67e74705SXin Li #define LOCKS_EXCLUDED(...) __attribute__((locks_excluded(__VA_ARGS__)))
25*67e74705SXin Li #define EXCLUSIVE_LOCKS_REQUIRED(...) __attribute__((exclusive_locks_required(__VA_ARGS__)))
26*67e74705SXin Li #define SHARED_LOCKS_REQUIRED(...) __attribute__((shared_locks_required(__VA_ARGS__)))
27*67e74705SXin Li #define NO_THREAD_SAFETY_ANALYSIS __attribute__((no_thread_safety_analysis))
28*67e74705SXin Li
29*67e74705SXin Li
30*67e74705SXin Li class LOCKABLE Mutex {
31*67e74705SXin Li public:
32*67e74705SXin Li void Lock() __attribute__((exclusive_lock_function));
33*67e74705SXin Li void ReaderLock() __attribute__((shared_lock_function));
34*67e74705SXin Li void Unlock() __attribute__((unlock_function));
35*67e74705SXin Li bool TryLock() __attribute__((exclusive_trylock_function(true)));
36*67e74705SXin Li bool ReaderTryLock() __attribute__((shared_trylock_function(true)));
37*67e74705SXin Li void LockWhen(const int &cond) __attribute__((exclusive_lock_function));
38*67e74705SXin Li
39*67e74705SXin Li // for negative capabilities
operator !() const40*67e74705SXin Li const Mutex& operator!() const { return *this; }
41*67e74705SXin Li
42*67e74705SXin Li void AssertHeld() ASSERT_EXCLUSIVE_LOCK();
43*67e74705SXin Li void AssertReaderHeld() ASSERT_SHARED_LOCK();
44*67e74705SXin Li };
45*67e74705SXin Li
46*67e74705SXin Li class SCOPED_LOCKABLE MutexLock {
47*67e74705SXin Li public:
48*67e74705SXin Li MutexLock(Mutex *mu) EXCLUSIVE_LOCK_FUNCTION(mu);
49*67e74705SXin Li MutexLock(Mutex *mu, bool adopt) EXCLUSIVE_LOCKS_REQUIRED(mu);
50*67e74705SXin Li ~MutexLock() UNLOCK_FUNCTION();
51*67e74705SXin Li };
52*67e74705SXin Li
53*67e74705SXin Li class SCOPED_LOCKABLE ReaderMutexLock {
54*67e74705SXin Li public:
55*67e74705SXin Li ReaderMutexLock(Mutex *mu) SHARED_LOCK_FUNCTION(mu);
56*67e74705SXin Li ReaderMutexLock(Mutex *mu, bool adopt) SHARED_LOCKS_REQUIRED(mu);
57*67e74705SXin Li ~ReaderMutexLock() UNLOCK_FUNCTION();
58*67e74705SXin Li };
59*67e74705SXin Li
60*67e74705SXin Li class SCOPED_LOCKABLE ReleasableMutexLock {
61*67e74705SXin Li public:
62*67e74705SXin Li ReleasableMutexLock(Mutex *mu) EXCLUSIVE_LOCK_FUNCTION(mu);
63*67e74705SXin Li ~ReleasableMutexLock() UNLOCK_FUNCTION();
64*67e74705SXin Li
65*67e74705SXin Li void Release() UNLOCK_FUNCTION();
66*67e74705SXin Li };
67*67e74705SXin Li
68*67e74705SXin Li class __attribute__((scoped_lockable)) DoubleMutexLock {
69*67e74705SXin Li public:
70*67e74705SXin Li DoubleMutexLock(Mutex *mu1, Mutex *mu2)
71*67e74705SXin Li __attribute__((exclusive_lock_function(mu1, mu2)));
72*67e74705SXin Li ~DoubleMutexLock() __attribute__((unlock_function));
73*67e74705SXin Li };
74*67e74705SXin Li
75*67e74705SXin Li // The universal lock, written "*", allows checking to be selectively turned
76*67e74705SXin Li // off for a particular piece of code.
77*67e74705SXin Li void beginNoWarnOnReads() SHARED_LOCK_FUNCTION("*");
78*67e74705SXin Li void endNoWarnOnReads() UNLOCK_FUNCTION("*");
79*67e74705SXin Li void beginNoWarnOnWrites() EXCLUSIVE_LOCK_FUNCTION("*");
80*67e74705SXin Li void endNoWarnOnWrites() UNLOCK_FUNCTION("*");
81*67e74705SXin Li
82*67e74705SXin Li
83*67e74705SXin Li // For testing handling of smart pointers.
84*67e74705SXin Li template<class T>
85*67e74705SXin Li class SmartPtr {
86*67e74705SXin Li public:
SmartPtr(T * p)87*67e74705SXin Li SmartPtr(T* p) : ptr_(p) { }
SmartPtr(const SmartPtr<T> & p)88*67e74705SXin Li SmartPtr(const SmartPtr<T>& p) : ptr_(p.ptr_) { }
89*67e74705SXin Li ~SmartPtr();
90*67e74705SXin Li
get() const91*67e74705SXin Li T* get() const { return ptr_; }
operator ->() const92*67e74705SXin Li T* operator->() const { return ptr_; }
operator *() const93*67e74705SXin Li T& operator*() const { return *ptr_; }
operator [](int i) const94*67e74705SXin Li T& operator[](int i) const { return ptr_[i]; }
95*67e74705SXin Li
96*67e74705SXin Li private:
97*67e74705SXin Li T* ptr_;
98*67e74705SXin Li };
99*67e74705SXin Li
100*67e74705SXin Li
101*67e74705SXin Li // For testing destructor calls and cleanup.
102*67e74705SXin Li class MyString {
103*67e74705SXin Li public:
104*67e74705SXin Li MyString(const char* s);
105*67e74705SXin Li ~MyString();
106*67e74705SXin Li };
107*67e74705SXin Li
108*67e74705SXin Li
109*67e74705SXin Li // For testing operator overloading
110*67e74705SXin Li template <class K, class T>
111*67e74705SXin Li class MyMap {
112*67e74705SXin Li public:
113*67e74705SXin Li T& operator[](const K& k);
114*67e74705SXin Li };
115*67e74705SXin Li
116*67e74705SXin Li
117*67e74705SXin Li // For testing handling of containers.
118*67e74705SXin Li template <class T>
119*67e74705SXin Li class MyContainer {
120*67e74705SXin Li public:
121*67e74705SXin Li MyContainer();
122*67e74705SXin Li
123*67e74705SXin Li typedef T* iterator;
124*67e74705SXin Li typedef const T* const_iterator;
125*67e74705SXin Li
126*67e74705SXin Li T* begin();
127*67e74705SXin Li T* end();
128*67e74705SXin Li
129*67e74705SXin Li const T* cbegin();
130*67e74705SXin Li const T* cend();
131*67e74705SXin Li
132*67e74705SXin Li T& operator[](int i);
133*67e74705SXin Li const T& operator[](int i) const;
134*67e74705SXin Li
135*67e74705SXin Li private:
136*67e74705SXin Li T* ptr_;
137*67e74705SXin Li };
138*67e74705SXin Li
139*67e74705SXin Li
140*67e74705SXin Li
141*67e74705SXin Li Mutex sls_mu;
142*67e74705SXin Li
143*67e74705SXin Li Mutex sls_mu2 __attribute__((acquired_after(sls_mu)));
144*67e74705SXin Li int sls_guard_var __attribute__((guarded_var)) = 0;
145*67e74705SXin Li int sls_guardby_var __attribute__((guarded_by(sls_mu))) = 0;
146*67e74705SXin Li
147*67e74705SXin Li bool getBool();
148*67e74705SXin Li
149*67e74705SXin Li class MutexWrapper {
150*67e74705SXin Li public:
151*67e74705SXin Li Mutex mu;
152*67e74705SXin Li int x __attribute__((guarded_by(mu)));
153*67e74705SXin Li void MyLock() __attribute__((exclusive_lock_function(mu)));
154*67e74705SXin Li };
155*67e74705SXin Li
156*67e74705SXin Li MutexWrapper sls_mw;
157*67e74705SXin Li
sls_fun_0()158*67e74705SXin Li void sls_fun_0() {
159*67e74705SXin Li sls_mw.mu.Lock();
160*67e74705SXin Li sls_mw.x = 5;
161*67e74705SXin Li sls_mw.mu.Unlock();
162*67e74705SXin Li }
163*67e74705SXin Li
sls_fun_2()164*67e74705SXin Li void sls_fun_2() {
165*67e74705SXin Li sls_mu.Lock();
166*67e74705SXin Li int x = sls_guard_var;
167*67e74705SXin Li sls_mu.Unlock();
168*67e74705SXin Li }
169*67e74705SXin Li
sls_fun_3()170*67e74705SXin Li void sls_fun_3() {
171*67e74705SXin Li sls_mu.Lock();
172*67e74705SXin Li sls_guard_var = 2;
173*67e74705SXin Li sls_mu.Unlock();
174*67e74705SXin Li }
175*67e74705SXin Li
sls_fun_4()176*67e74705SXin Li void sls_fun_4() {
177*67e74705SXin Li sls_mu2.Lock();
178*67e74705SXin Li sls_guard_var = 2;
179*67e74705SXin Li sls_mu2.Unlock();
180*67e74705SXin Li }
181*67e74705SXin Li
sls_fun_5()182*67e74705SXin Li void sls_fun_5() {
183*67e74705SXin Li sls_mu.Lock();
184*67e74705SXin Li int x = sls_guardby_var;
185*67e74705SXin Li sls_mu.Unlock();
186*67e74705SXin Li }
187*67e74705SXin Li
sls_fun_6()188*67e74705SXin Li void sls_fun_6() {
189*67e74705SXin Li sls_mu.Lock();
190*67e74705SXin Li sls_guardby_var = 2;
191*67e74705SXin Li sls_mu.Unlock();
192*67e74705SXin Li }
193*67e74705SXin Li
sls_fun_7()194*67e74705SXin Li void sls_fun_7() {
195*67e74705SXin Li sls_mu.Lock();
196*67e74705SXin Li sls_mu2.Lock();
197*67e74705SXin Li sls_mu2.Unlock();
198*67e74705SXin Li sls_mu.Unlock();
199*67e74705SXin Li }
200*67e74705SXin Li
sls_fun_8()201*67e74705SXin Li void sls_fun_8() {
202*67e74705SXin Li sls_mu.Lock();
203*67e74705SXin Li if (getBool())
204*67e74705SXin Li sls_mu.Unlock();
205*67e74705SXin Li else
206*67e74705SXin Li sls_mu.Unlock();
207*67e74705SXin Li }
208*67e74705SXin Li
sls_fun_9()209*67e74705SXin Li void sls_fun_9() {
210*67e74705SXin Li if (getBool())
211*67e74705SXin Li sls_mu.Lock();
212*67e74705SXin Li else
213*67e74705SXin Li sls_mu.Lock();
214*67e74705SXin Li sls_mu.Unlock();
215*67e74705SXin Li }
216*67e74705SXin Li
sls_fun_good_6()217*67e74705SXin Li void sls_fun_good_6() {
218*67e74705SXin Li if (getBool()) {
219*67e74705SXin Li sls_mu.Lock();
220*67e74705SXin Li } else {
221*67e74705SXin Li if (getBool()) {
222*67e74705SXin Li getBool(); // EMPTY
223*67e74705SXin Li } else {
224*67e74705SXin Li getBool(); // EMPTY
225*67e74705SXin Li }
226*67e74705SXin Li sls_mu.Lock();
227*67e74705SXin Li }
228*67e74705SXin Li sls_mu.Unlock();
229*67e74705SXin Li }
230*67e74705SXin Li
sls_fun_good_7()231*67e74705SXin Li void sls_fun_good_7() {
232*67e74705SXin Li sls_mu.Lock();
233*67e74705SXin Li while (getBool()) {
234*67e74705SXin Li sls_mu.Unlock();
235*67e74705SXin Li if (getBool()) {
236*67e74705SXin Li if (getBool()) {
237*67e74705SXin Li sls_mu.Lock();
238*67e74705SXin Li continue;
239*67e74705SXin Li }
240*67e74705SXin Li }
241*67e74705SXin Li sls_mu.Lock();
242*67e74705SXin Li }
243*67e74705SXin Li sls_mu.Unlock();
244*67e74705SXin Li }
245*67e74705SXin Li
sls_fun_good_8()246*67e74705SXin Li void sls_fun_good_8() {
247*67e74705SXin Li sls_mw.MyLock();
248*67e74705SXin Li sls_mw.mu.Unlock();
249*67e74705SXin Li }
250*67e74705SXin Li
sls_fun_bad_1()251*67e74705SXin Li void sls_fun_bad_1() {
252*67e74705SXin Li sls_mu.Unlock(); // \
253*67e74705SXin Li // expected-warning{{releasing mutex 'sls_mu' that was not held}}
254*67e74705SXin Li }
255*67e74705SXin Li
sls_fun_bad_2()256*67e74705SXin Li void sls_fun_bad_2() {
257*67e74705SXin Li sls_mu.Lock();
258*67e74705SXin Li sls_mu.Lock(); // \
259*67e74705SXin Li // expected-warning{{acquiring mutex 'sls_mu' that is already held}}
260*67e74705SXin Li sls_mu.Unlock();
261*67e74705SXin Li }
262*67e74705SXin Li
sls_fun_bad_3()263*67e74705SXin Li void sls_fun_bad_3() {
264*67e74705SXin Li sls_mu.Lock(); // expected-note {{mutex acquired here}}
265*67e74705SXin Li } // expected-warning{{mutex 'sls_mu' is still held at the end of function}}
266*67e74705SXin Li
sls_fun_bad_4()267*67e74705SXin Li void sls_fun_bad_4() {
268*67e74705SXin Li if (getBool())
269*67e74705SXin Li sls_mu.Lock(); // expected-note{{mutex acquired here}}
270*67e74705SXin Li else
271*67e74705SXin Li sls_mu2.Lock(); // expected-note{{mutex acquired here}}
272*67e74705SXin Li } // expected-warning{{mutex 'sls_mu' is not held on every path through here}} \
273*67e74705SXin Li // expected-warning{{mutex 'sls_mu2' is not held on every path through here}}
274*67e74705SXin Li
sls_fun_bad_5()275*67e74705SXin Li void sls_fun_bad_5() {
276*67e74705SXin Li sls_mu.Lock(); // expected-note {{mutex acquired here}}
277*67e74705SXin Li if (getBool())
278*67e74705SXin Li sls_mu.Unlock();
279*67e74705SXin Li } // expected-warning{{mutex 'sls_mu' is not held on every path through here}}
280*67e74705SXin Li
sls_fun_bad_6()281*67e74705SXin Li void sls_fun_bad_6() {
282*67e74705SXin Li if (getBool()) {
283*67e74705SXin Li sls_mu.Lock(); // expected-note {{mutex acquired here}}
284*67e74705SXin Li } else {
285*67e74705SXin Li if (getBool()) {
286*67e74705SXin Li getBool(); // EMPTY
287*67e74705SXin Li } else {
288*67e74705SXin Li getBool(); // EMPTY
289*67e74705SXin Li }
290*67e74705SXin Li }
291*67e74705SXin Li sls_mu.Unlock(); // \
292*67e74705SXin Li expected-warning{{mutex 'sls_mu' is not held on every path through here}}\
293*67e74705SXin Li expected-warning{{releasing mutex 'sls_mu' that was not held}}
294*67e74705SXin Li }
295*67e74705SXin Li
sls_fun_bad_7()296*67e74705SXin Li void sls_fun_bad_7() {
297*67e74705SXin Li sls_mu.Lock();
298*67e74705SXin Li while (getBool()) {
299*67e74705SXin Li sls_mu.Unlock();
300*67e74705SXin Li if (getBool()) {
301*67e74705SXin Li if (getBool()) {
302*67e74705SXin Li continue; // \
303*67e74705SXin Li expected-warning{{expecting mutex 'sls_mu' to be held at start of each loop}}
304*67e74705SXin Li }
305*67e74705SXin Li }
306*67e74705SXin Li sls_mu.Lock(); // expected-note {{mutex acquired here}}
307*67e74705SXin Li }
308*67e74705SXin Li sls_mu.Unlock();
309*67e74705SXin Li }
310*67e74705SXin Li
sls_fun_bad_8()311*67e74705SXin Li void sls_fun_bad_8() {
312*67e74705SXin Li sls_mu.Lock(); // expected-note{{mutex acquired here}}
313*67e74705SXin Li
314*67e74705SXin Li do {
315*67e74705SXin Li sls_mu.Unlock(); // expected-warning{{expecting mutex 'sls_mu' to be held at start of each loop}}
316*67e74705SXin Li } while (getBool());
317*67e74705SXin Li }
318*67e74705SXin Li
sls_fun_bad_9()319*67e74705SXin Li void sls_fun_bad_9() {
320*67e74705SXin Li do {
321*67e74705SXin Li sls_mu.Lock(); // \
322*67e74705SXin Li // expected-warning{{expecting mutex 'sls_mu' to be held at start of each loop}} \
323*67e74705SXin Li // expected-note{{mutex acquired here}}
324*67e74705SXin Li } while (getBool());
325*67e74705SXin Li sls_mu.Unlock();
326*67e74705SXin Li }
327*67e74705SXin Li
sls_fun_bad_10()328*67e74705SXin Li void sls_fun_bad_10() {
329*67e74705SXin Li sls_mu.Lock(); // expected-note 2{{mutex acquired here}}
330*67e74705SXin Li while(getBool()) { // expected-warning{{expecting mutex 'sls_mu' to be held at start of each loop}}
331*67e74705SXin Li sls_mu.Unlock();
332*67e74705SXin Li }
333*67e74705SXin Li } // expected-warning{{mutex 'sls_mu' is still held at the end of function}}
334*67e74705SXin Li
sls_fun_bad_11()335*67e74705SXin Li void sls_fun_bad_11() {
336*67e74705SXin Li while (getBool()) { // \
337*67e74705SXin Li expected-warning{{expecting mutex 'sls_mu' to be held at start of each loop}}
338*67e74705SXin Li sls_mu.Lock(); // expected-note {{mutex acquired here}}
339*67e74705SXin Li }
340*67e74705SXin Li sls_mu.Unlock(); // \
341*67e74705SXin Li // expected-warning{{releasing mutex 'sls_mu' that was not held}}
342*67e74705SXin Li }
343*67e74705SXin Li
sls_fun_bad_12()344*67e74705SXin Li void sls_fun_bad_12() {
345*67e74705SXin Li sls_mu.Lock(); // expected-note {{mutex acquired here}}
346*67e74705SXin Li while (getBool()) {
347*67e74705SXin Li sls_mu.Unlock();
348*67e74705SXin Li if (getBool()) {
349*67e74705SXin Li if (getBool()) {
350*67e74705SXin Li break; // expected-warning{{mutex 'sls_mu' is not held on every path through here}}
351*67e74705SXin Li }
352*67e74705SXin Li }
353*67e74705SXin Li sls_mu.Lock();
354*67e74705SXin Li }
355*67e74705SXin Li sls_mu.Unlock();
356*67e74705SXin Li }
357*67e74705SXin Li
358*67e74705SXin Li //-----------------------------------------//
359*67e74705SXin Li // Handling lock expressions in attribute args
360*67e74705SXin Li // -------------------------------------------//
361*67e74705SXin Li
362*67e74705SXin Li Mutex aa_mu;
363*67e74705SXin Li
364*67e74705SXin Li class GlobalLocker {
365*67e74705SXin Li public:
366*67e74705SXin Li void globalLock() __attribute__((exclusive_lock_function(aa_mu)));
367*67e74705SXin Li void globalUnlock() __attribute__((unlock_function(aa_mu)));
368*67e74705SXin Li };
369*67e74705SXin Li
370*67e74705SXin Li GlobalLocker glock;
371*67e74705SXin Li
aa_fun_1()372*67e74705SXin Li void aa_fun_1() {
373*67e74705SXin Li glock.globalLock();
374*67e74705SXin Li glock.globalUnlock();
375*67e74705SXin Li }
376*67e74705SXin Li
aa_fun_bad_1()377*67e74705SXin Li void aa_fun_bad_1() {
378*67e74705SXin Li glock.globalUnlock(); // \
379*67e74705SXin Li // expected-warning{{releasing mutex 'aa_mu' that was not held}}
380*67e74705SXin Li }
381*67e74705SXin Li
aa_fun_bad_2()382*67e74705SXin Li void aa_fun_bad_2() {
383*67e74705SXin Li glock.globalLock();
384*67e74705SXin Li glock.globalLock(); // \
385*67e74705SXin Li // expected-warning{{acquiring mutex 'aa_mu' that is already held}}
386*67e74705SXin Li glock.globalUnlock();
387*67e74705SXin Li }
388*67e74705SXin Li
aa_fun_bad_3()389*67e74705SXin Li void aa_fun_bad_3() {
390*67e74705SXin Li glock.globalLock(); // expected-note{{mutex acquired here}}
391*67e74705SXin Li } // expected-warning{{mutex 'aa_mu' is still held at the end of function}}
392*67e74705SXin Li
393*67e74705SXin Li //--------------------------------------------------//
394*67e74705SXin Li // Regression tests for unusual method names
395*67e74705SXin Li //--------------------------------------------------//
396*67e74705SXin Li
397*67e74705SXin Li Mutex wmu;
398*67e74705SXin Li
399*67e74705SXin Li // Test diagnostics for other method names.
400*67e74705SXin Li class WeirdMethods {
401*67e74705SXin Li // FIXME: can't currently check inside constructors and destructors.
WeirdMethods()402*67e74705SXin Li WeirdMethods() {
403*67e74705SXin Li wmu.Lock(); // EXPECTED-NOTE {{mutex acquired here}}
404*67e74705SXin Li } // EXPECTED-WARNING {{mutex 'wmu' is still held at the end of function}}
~WeirdMethods()405*67e74705SXin Li ~WeirdMethods() {
406*67e74705SXin Li wmu.Lock(); // EXPECTED-NOTE {{mutex acquired here}}
407*67e74705SXin Li } // EXPECTED-WARNING {{mutex 'wmu' is still held at the end of function}}
operator ++()408*67e74705SXin Li void operator++() {
409*67e74705SXin Li wmu.Lock(); // expected-note {{mutex acquired here}}
410*67e74705SXin Li } // expected-warning {{mutex 'wmu' is still held at the end of function}}
operator int*()411*67e74705SXin Li operator int*() {
412*67e74705SXin Li wmu.Lock(); // expected-note {{mutex acquired here}}
413*67e74705SXin Li return 0;
414*67e74705SXin Li } // expected-warning {{mutex 'wmu' is still held at the end of function}}
415*67e74705SXin Li };
416*67e74705SXin Li
417*67e74705SXin Li //-----------------------------------------------//
418*67e74705SXin Li // Errors for guarded by or guarded var variables
419*67e74705SXin Li // ----------------------------------------------//
420*67e74705SXin Li
421*67e74705SXin Li int *pgb_gvar __attribute__((pt_guarded_var));
422*67e74705SXin Li int *pgb_var __attribute__((pt_guarded_by(sls_mu)));
423*67e74705SXin Li
424*67e74705SXin Li class PGBFoo {
425*67e74705SXin Li public:
426*67e74705SXin Li int x;
427*67e74705SXin Li int *pgb_field __attribute__((guarded_by(sls_mu2)))
428*67e74705SXin Li __attribute__((pt_guarded_by(sls_mu)));
testFoo()429*67e74705SXin Li void testFoo() {
430*67e74705SXin Li pgb_field = &x; // \
431*67e74705SXin Li // expected-warning {{writing variable 'pgb_field' requires holding mutex 'sls_mu2' exclusively}}
432*67e74705SXin Li *pgb_field = x; // expected-warning {{reading variable 'pgb_field' requires holding mutex 'sls_mu2'}} \
433*67e74705SXin Li // expected-warning {{writing the value pointed to by 'pgb_field' requires holding mutex 'sls_mu' exclusively}}
434*67e74705SXin Li x = *pgb_field; // expected-warning {{reading variable 'pgb_field' requires holding mutex 'sls_mu2'}} \
435*67e74705SXin Li // expected-warning {{reading the value pointed to by 'pgb_field' requires holding mutex 'sls_mu'}}
436*67e74705SXin Li (*pgb_field)++; // expected-warning {{reading variable 'pgb_field' requires holding mutex 'sls_mu2'}} \
437*67e74705SXin Li // expected-warning {{writing the value pointed to by 'pgb_field' requires holding mutex 'sls_mu' exclusively}}
438*67e74705SXin Li }
439*67e74705SXin Li };
440*67e74705SXin Li
441*67e74705SXin Li class GBFoo {
442*67e74705SXin Li public:
443*67e74705SXin Li int gb_field __attribute__((guarded_by(sls_mu)));
444*67e74705SXin Li
testFoo()445*67e74705SXin Li void testFoo() {
446*67e74705SXin Li gb_field = 0; // \
447*67e74705SXin Li // expected-warning {{writing variable 'gb_field' requires holding mutex 'sls_mu' exclusively}}
448*67e74705SXin Li }
449*67e74705SXin Li
testNoAnal()450*67e74705SXin Li void testNoAnal() __attribute__((no_thread_safety_analysis)) {
451*67e74705SXin Li gb_field = 0;
452*67e74705SXin Li }
453*67e74705SXin Li };
454*67e74705SXin Li
455*67e74705SXin Li GBFoo GlobalGBFoo __attribute__((guarded_by(sls_mu)));
456*67e74705SXin Li
gb_fun_0()457*67e74705SXin Li void gb_fun_0() {
458*67e74705SXin Li sls_mu.Lock();
459*67e74705SXin Li int x = *pgb_var;
460*67e74705SXin Li sls_mu.Unlock();
461*67e74705SXin Li }
462*67e74705SXin Li
gb_fun_1()463*67e74705SXin Li void gb_fun_1() {
464*67e74705SXin Li sls_mu.Lock();
465*67e74705SXin Li *pgb_var = 2;
466*67e74705SXin Li sls_mu.Unlock();
467*67e74705SXin Li }
468*67e74705SXin Li
gb_fun_2()469*67e74705SXin Li void gb_fun_2() {
470*67e74705SXin Li int x;
471*67e74705SXin Li pgb_var = &x;
472*67e74705SXin Li }
473*67e74705SXin Li
gb_fun_3()474*67e74705SXin Li void gb_fun_3() {
475*67e74705SXin Li int *x = pgb_var;
476*67e74705SXin Li }
477*67e74705SXin Li
gb_bad_0()478*67e74705SXin Li void gb_bad_0() {
479*67e74705SXin Li sls_guard_var = 1; // \
480*67e74705SXin Li // expected-warning{{writing variable 'sls_guard_var' requires holding any mutex exclusively}}
481*67e74705SXin Li }
482*67e74705SXin Li
gb_bad_1()483*67e74705SXin Li void gb_bad_1() {
484*67e74705SXin Li int x = sls_guard_var; // \
485*67e74705SXin Li // expected-warning{{reading variable 'sls_guard_var' requires holding any mutex}}
486*67e74705SXin Li }
487*67e74705SXin Li
gb_bad_2()488*67e74705SXin Li void gb_bad_2() {
489*67e74705SXin Li sls_guardby_var = 1; // \
490*67e74705SXin Li // expected-warning {{writing variable 'sls_guardby_var' requires holding mutex 'sls_mu' exclusively}}
491*67e74705SXin Li }
492*67e74705SXin Li
gb_bad_3()493*67e74705SXin Li void gb_bad_3() {
494*67e74705SXin Li int x = sls_guardby_var; // \
495*67e74705SXin Li // expected-warning {{reading variable 'sls_guardby_var' requires holding mutex 'sls_mu'}}
496*67e74705SXin Li }
497*67e74705SXin Li
gb_bad_4()498*67e74705SXin Li void gb_bad_4() {
499*67e74705SXin Li *pgb_gvar = 1; // \
500*67e74705SXin Li // expected-warning {{writing the value pointed to by 'pgb_gvar' requires holding any mutex exclusively}}
501*67e74705SXin Li }
502*67e74705SXin Li
gb_bad_5()503*67e74705SXin Li void gb_bad_5() {
504*67e74705SXin Li int x = *pgb_gvar; // \
505*67e74705SXin Li // expected-warning {{reading the value pointed to by 'pgb_gvar' requires holding any mutex}}
506*67e74705SXin Li }
507*67e74705SXin Li
gb_bad_6()508*67e74705SXin Li void gb_bad_6() {
509*67e74705SXin Li *pgb_var = 1; // \
510*67e74705SXin Li // expected-warning {{writing the value pointed to by 'pgb_var' requires holding mutex 'sls_mu' exclusively}}
511*67e74705SXin Li }
512*67e74705SXin Li
gb_bad_7()513*67e74705SXin Li void gb_bad_7() {
514*67e74705SXin Li int x = *pgb_var; // \
515*67e74705SXin Li // expected-warning {{reading the value pointed to by 'pgb_var' requires holding mutex 'sls_mu'}}
516*67e74705SXin Li }
517*67e74705SXin Li
gb_bad_8()518*67e74705SXin Li void gb_bad_8() {
519*67e74705SXin Li GBFoo G;
520*67e74705SXin Li G.gb_field = 0; // \
521*67e74705SXin Li // expected-warning {{writing variable 'gb_field' requires holding mutex 'sls_mu'}}
522*67e74705SXin Li }
523*67e74705SXin Li
gb_bad_9()524*67e74705SXin Li void gb_bad_9() {
525*67e74705SXin Li sls_guard_var++; // \
526*67e74705SXin Li // expected-warning{{writing variable 'sls_guard_var' requires holding any mutex exclusively}}
527*67e74705SXin Li sls_guard_var--; // \
528*67e74705SXin Li // expected-warning{{writing variable 'sls_guard_var' requires holding any mutex exclusively}}
529*67e74705SXin Li ++sls_guard_var; // \
530*67e74705SXin Li // expected-warning{{writing variable 'sls_guard_var' requires holding any mutex exclusively}}
531*67e74705SXin Li --sls_guard_var;// \
532*67e74705SXin Li // expected-warning{{writing variable 'sls_guard_var' requires holding any mutex exclusively}}
533*67e74705SXin Li }
534*67e74705SXin Li
535*67e74705SXin Li //-----------------------------------------------//
536*67e74705SXin Li // Warnings on variables with late parsed attributes
537*67e74705SXin Li // ----------------------------------------------//
538*67e74705SXin Li
539*67e74705SXin Li class LateFoo {
540*67e74705SXin Li public:
541*67e74705SXin Li int a __attribute__((guarded_by(mu)));
542*67e74705SXin Li int b;
543*67e74705SXin Li
foo()544*67e74705SXin Li void foo() __attribute__((exclusive_locks_required(mu))) { }
545*67e74705SXin Li
test()546*67e74705SXin Li void test() {
547*67e74705SXin Li a = 0; // \
548*67e74705SXin Li // expected-warning{{writing variable 'a' requires holding mutex 'mu' exclusively}}
549*67e74705SXin Li b = a; // \
550*67e74705SXin Li // expected-warning {{reading variable 'a' requires holding mutex 'mu'}}
551*67e74705SXin Li c = 0; // \
552*67e74705SXin Li // expected-warning {{writing variable 'c' requires holding mutex 'mu' exclusively}}
553*67e74705SXin Li }
554*67e74705SXin Li
555*67e74705SXin Li int c __attribute__((guarded_by(mu)));
556*67e74705SXin Li
557*67e74705SXin Li Mutex mu;
558*67e74705SXin Li };
559*67e74705SXin Li
560*67e74705SXin Li class LateBar {
561*67e74705SXin Li public:
562*67e74705SXin Li int a_ __attribute__((guarded_by(mu1_)));
563*67e74705SXin Li int b_;
564*67e74705SXin Li int *q __attribute__((pt_guarded_by(mu)));
565*67e74705SXin Li Mutex mu1_;
566*67e74705SXin Li Mutex mu;
567*67e74705SXin Li LateFoo Foo;
568*67e74705SXin Li LateFoo Foo2;
569*67e74705SXin Li LateFoo *FooPointer;
570*67e74705SXin Li };
571*67e74705SXin Li
572*67e74705SXin Li LateBar b1, *b3;
573*67e74705SXin Li
late_0()574*67e74705SXin Li void late_0() {
575*67e74705SXin Li LateFoo FooA;
576*67e74705SXin Li LateFoo FooB;
577*67e74705SXin Li FooA.mu.Lock();
578*67e74705SXin Li FooA.a = 5;
579*67e74705SXin Li FooA.mu.Unlock();
580*67e74705SXin Li }
581*67e74705SXin Li
late_1()582*67e74705SXin Li void late_1() {
583*67e74705SXin Li LateBar BarA;
584*67e74705SXin Li BarA.FooPointer->mu.Lock();
585*67e74705SXin Li BarA.FooPointer->a = 2;
586*67e74705SXin Li BarA.FooPointer->mu.Unlock();
587*67e74705SXin Li }
588*67e74705SXin Li
late_bad_0()589*67e74705SXin Li void late_bad_0() {
590*67e74705SXin Li LateFoo fooA;
591*67e74705SXin Li LateFoo fooB;
592*67e74705SXin Li fooA.mu.Lock();
593*67e74705SXin Li fooB.a = 5; // \
594*67e74705SXin Li // expected-warning{{writing variable 'a' requires holding mutex 'fooB.mu' exclusively}} \
595*67e74705SXin Li // expected-note{{found near match 'fooA.mu'}}
596*67e74705SXin Li fooA.mu.Unlock();
597*67e74705SXin Li }
598*67e74705SXin Li
late_bad_1()599*67e74705SXin Li void late_bad_1() {
600*67e74705SXin Li Mutex mu;
601*67e74705SXin Li mu.Lock();
602*67e74705SXin Li b1.mu1_.Lock();
603*67e74705SXin Li int res = b1.a_ + b3->b_;
604*67e74705SXin Li b3->b_ = *b1.q; // \
605*67e74705SXin Li // expected-warning{{reading the value pointed to by 'q' requires holding mutex 'b1.mu'}}
606*67e74705SXin Li b1.mu1_.Unlock();
607*67e74705SXin Li b1.b_ = res;
608*67e74705SXin Li mu.Unlock();
609*67e74705SXin Li }
610*67e74705SXin Li
late_bad_2()611*67e74705SXin Li void late_bad_2() {
612*67e74705SXin Li LateBar BarA;
613*67e74705SXin Li BarA.FooPointer->mu.Lock();
614*67e74705SXin Li BarA.Foo.a = 2; // \
615*67e74705SXin Li // expected-warning{{writing variable 'a' requires holding mutex 'BarA.Foo.mu' exclusively}} \
616*67e74705SXin Li // expected-note{{found near match 'BarA.FooPointer->mu'}}
617*67e74705SXin Li BarA.FooPointer->mu.Unlock();
618*67e74705SXin Li }
619*67e74705SXin Li
late_bad_3()620*67e74705SXin Li void late_bad_3() {
621*67e74705SXin Li LateBar BarA;
622*67e74705SXin Li BarA.Foo.mu.Lock();
623*67e74705SXin Li BarA.FooPointer->a = 2; // \
624*67e74705SXin Li // expected-warning{{writing variable 'a' requires holding mutex 'BarA.FooPointer->mu' exclusively}} \
625*67e74705SXin Li // expected-note{{found near match 'BarA.Foo.mu'}}
626*67e74705SXin Li BarA.Foo.mu.Unlock();
627*67e74705SXin Li }
628*67e74705SXin Li
late_bad_4()629*67e74705SXin Li void late_bad_4() {
630*67e74705SXin Li LateBar BarA;
631*67e74705SXin Li BarA.Foo.mu.Lock();
632*67e74705SXin Li BarA.Foo2.a = 2; // \
633*67e74705SXin Li // expected-warning{{writing variable 'a' requires holding mutex 'BarA.Foo2.mu' exclusively}} \
634*67e74705SXin Li // expected-note{{found near match 'BarA.Foo.mu'}}
635*67e74705SXin Li BarA.Foo.mu.Unlock();
636*67e74705SXin Li }
637*67e74705SXin Li
638*67e74705SXin Li //-----------------------------------------------//
639*67e74705SXin Li // Extra warnings for shared vs. exclusive locks
640*67e74705SXin Li // ----------------------------------------------//
641*67e74705SXin Li
shared_fun_0()642*67e74705SXin Li void shared_fun_0() {
643*67e74705SXin Li sls_mu.Lock();
644*67e74705SXin Li do {
645*67e74705SXin Li sls_mu.Unlock();
646*67e74705SXin Li sls_mu.Lock();
647*67e74705SXin Li } while (getBool());
648*67e74705SXin Li sls_mu.Unlock();
649*67e74705SXin Li }
650*67e74705SXin Li
shared_fun_1()651*67e74705SXin Li void shared_fun_1() {
652*67e74705SXin Li sls_mu.ReaderLock(); // \
653*67e74705SXin Li // expected-warning {{mutex 'sls_mu' is acquired exclusively and shared in the same scope}}
654*67e74705SXin Li do {
655*67e74705SXin Li sls_mu.Unlock();
656*67e74705SXin Li sls_mu.Lock(); // \
657*67e74705SXin Li // expected-note {{the other acquisition of mutex 'sls_mu' is here}}
658*67e74705SXin Li } while (getBool());
659*67e74705SXin Li sls_mu.Unlock();
660*67e74705SXin Li }
661*67e74705SXin Li
shared_fun_3()662*67e74705SXin Li void shared_fun_3() {
663*67e74705SXin Li if (getBool())
664*67e74705SXin Li sls_mu.Lock();
665*67e74705SXin Li else
666*67e74705SXin Li sls_mu.Lock();
667*67e74705SXin Li *pgb_var = 1;
668*67e74705SXin Li sls_mu.Unlock();
669*67e74705SXin Li }
670*67e74705SXin Li
shared_fun_4()671*67e74705SXin Li void shared_fun_4() {
672*67e74705SXin Li if (getBool())
673*67e74705SXin Li sls_mu.ReaderLock();
674*67e74705SXin Li else
675*67e74705SXin Li sls_mu.ReaderLock();
676*67e74705SXin Li int x = sls_guardby_var;
677*67e74705SXin Li sls_mu.Unlock();
678*67e74705SXin Li }
679*67e74705SXin Li
shared_fun_8()680*67e74705SXin Li void shared_fun_8() {
681*67e74705SXin Li if (getBool())
682*67e74705SXin Li sls_mu.Lock(); // \
683*67e74705SXin Li // expected-warning {{mutex 'sls_mu' is acquired exclusively and shared in the same scope}}
684*67e74705SXin Li else
685*67e74705SXin Li sls_mu.ReaderLock(); // \
686*67e74705SXin Li // expected-note {{the other acquisition of mutex 'sls_mu' is here}}
687*67e74705SXin Li sls_mu.Unlock();
688*67e74705SXin Li }
689*67e74705SXin Li
shared_bad_0()690*67e74705SXin Li void shared_bad_0() {
691*67e74705SXin Li sls_mu.Lock(); // \
692*67e74705SXin Li // expected-warning {{mutex 'sls_mu' is acquired exclusively and shared in the same scope}}
693*67e74705SXin Li do {
694*67e74705SXin Li sls_mu.Unlock();
695*67e74705SXin Li sls_mu.ReaderLock(); // \
696*67e74705SXin Li // expected-note {{the other acquisition of mutex 'sls_mu' is here}}
697*67e74705SXin Li } while (getBool());
698*67e74705SXin Li sls_mu.Unlock();
699*67e74705SXin Li }
700*67e74705SXin Li
shared_bad_1()701*67e74705SXin Li void shared_bad_1() {
702*67e74705SXin Li if (getBool())
703*67e74705SXin Li sls_mu.Lock(); // \
704*67e74705SXin Li // expected-warning {{mutex 'sls_mu' is acquired exclusively and shared in the same scope}}
705*67e74705SXin Li else
706*67e74705SXin Li sls_mu.ReaderLock(); // \
707*67e74705SXin Li // expected-note {{the other acquisition of mutex 'sls_mu' is here}}
708*67e74705SXin Li *pgb_var = 1;
709*67e74705SXin Li sls_mu.Unlock();
710*67e74705SXin Li }
711*67e74705SXin Li
shared_bad_2()712*67e74705SXin Li void shared_bad_2() {
713*67e74705SXin Li if (getBool())
714*67e74705SXin Li sls_mu.ReaderLock(); // \
715*67e74705SXin Li // expected-warning {{mutex 'sls_mu' is acquired exclusively and shared in the same scope}}
716*67e74705SXin Li else
717*67e74705SXin Li sls_mu.Lock(); // \
718*67e74705SXin Li // expected-note {{the other acquisition of mutex 'sls_mu' is here}}
719*67e74705SXin Li *pgb_var = 1;
720*67e74705SXin Li sls_mu.Unlock();
721*67e74705SXin Li }
722*67e74705SXin Li
723*67e74705SXin Li // FIXME: Add support for functions (not only methods)
724*67e74705SXin Li class LRBar {
725*67e74705SXin Li public:
726*67e74705SXin Li void aa_elr_fun() __attribute__((exclusive_locks_required(aa_mu)));
727*67e74705SXin Li void aa_elr_fun_s() __attribute__((shared_locks_required(aa_mu)));
728*67e74705SXin Li void le_fun() __attribute__((locks_excluded(sls_mu)));
729*67e74705SXin Li };
730*67e74705SXin Li
731*67e74705SXin Li class LRFoo {
732*67e74705SXin Li public:
733*67e74705SXin Li void test() __attribute__((exclusive_locks_required(sls_mu)));
734*67e74705SXin Li void testShared() __attribute__((shared_locks_required(sls_mu2)));
735*67e74705SXin Li };
736*67e74705SXin Li
737*67e74705SXin Li void elr_fun() __attribute__((exclusive_locks_required(sls_mu)));
elr_fun()738*67e74705SXin Li void elr_fun() {}
739*67e74705SXin Li
740*67e74705SXin Li LRFoo MyLRFoo;
741*67e74705SXin Li LRBar Bar;
742*67e74705SXin Li
es_fun_0()743*67e74705SXin Li void es_fun_0() {
744*67e74705SXin Li aa_mu.Lock();
745*67e74705SXin Li Bar.aa_elr_fun();
746*67e74705SXin Li aa_mu.Unlock();
747*67e74705SXin Li }
748*67e74705SXin Li
es_fun_1()749*67e74705SXin Li void es_fun_1() {
750*67e74705SXin Li aa_mu.Lock();
751*67e74705SXin Li Bar.aa_elr_fun_s();
752*67e74705SXin Li aa_mu.Unlock();
753*67e74705SXin Li }
754*67e74705SXin Li
es_fun_2()755*67e74705SXin Li void es_fun_2() {
756*67e74705SXin Li aa_mu.ReaderLock();
757*67e74705SXin Li Bar.aa_elr_fun_s();
758*67e74705SXin Li aa_mu.Unlock();
759*67e74705SXin Li }
760*67e74705SXin Li
es_fun_3()761*67e74705SXin Li void es_fun_3() {
762*67e74705SXin Li sls_mu.Lock();
763*67e74705SXin Li MyLRFoo.test();
764*67e74705SXin Li sls_mu.Unlock();
765*67e74705SXin Li }
766*67e74705SXin Li
es_fun_4()767*67e74705SXin Li void es_fun_4() {
768*67e74705SXin Li sls_mu2.Lock();
769*67e74705SXin Li MyLRFoo.testShared();
770*67e74705SXin Li sls_mu2.Unlock();
771*67e74705SXin Li }
772*67e74705SXin Li
es_fun_5()773*67e74705SXin Li void es_fun_5() {
774*67e74705SXin Li sls_mu2.ReaderLock();
775*67e74705SXin Li MyLRFoo.testShared();
776*67e74705SXin Li sls_mu2.Unlock();
777*67e74705SXin Li }
778*67e74705SXin Li
es_fun_6()779*67e74705SXin Li void es_fun_6() {
780*67e74705SXin Li Bar.le_fun();
781*67e74705SXin Li }
782*67e74705SXin Li
es_fun_7()783*67e74705SXin Li void es_fun_7() {
784*67e74705SXin Li sls_mu.Lock();
785*67e74705SXin Li elr_fun();
786*67e74705SXin Li sls_mu.Unlock();
787*67e74705SXin Li }
788*67e74705SXin Li
789*67e74705SXin Li void es_fun_8() __attribute__((no_thread_safety_analysis));
790*67e74705SXin Li
es_fun_8()791*67e74705SXin Li void es_fun_8() {
792*67e74705SXin Li Bar.aa_elr_fun_s();
793*67e74705SXin Li }
794*67e74705SXin Li
795*67e74705SXin Li void es_fun_9() __attribute__((shared_locks_required(aa_mu)));
es_fun_9()796*67e74705SXin Li void es_fun_9() {
797*67e74705SXin Li Bar.aa_elr_fun_s();
798*67e74705SXin Li }
799*67e74705SXin Li
800*67e74705SXin Li void es_fun_10() __attribute__((exclusive_locks_required(aa_mu)));
es_fun_10()801*67e74705SXin Li void es_fun_10() {
802*67e74705SXin Li Bar.aa_elr_fun_s();
803*67e74705SXin Li }
804*67e74705SXin Li
es_bad_0()805*67e74705SXin Li void es_bad_0() {
806*67e74705SXin Li Bar.aa_elr_fun(); // \
807*67e74705SXin Li // expected-warning {{calling function 'aa_elr_fun' requires holding mutex 'aa_mu' exclusively}}
808*67e74705SXin Li }
809*67e74705SXin Li
es_bad_1()810*67e74705SXin Li void es_bad_1() {
811*67e74705SXin Li aa_mu.ReaderLock();
812*67e74705SXin Li Bar.aa_elr_fun(); // \
813*67e74705SXin Li // expected-warning {{calling function 'aa_elr_fun' requires holding mutex 'aa_mu' exclusively}}
814*67e74705SXin Li aa_mu.Unlock();
815*67e74705SXin Li }
816*67e74705SXin Li
es_bad_2()817*67e74705SXin Li void es_bad_2() {
818*67e74705SXin Li Bar.aa_elr_fun_s(); // \
819*67e74705SXin Li // expected-warning {{calling function 'aa_elr_fun_s' requires holding mutex 'aa_mu'}}
820*67e74705SXin Li }
821*67e74705SXin Li
es_bad_3()822*67e74705SXin Li void es_bad_3() {
823*67e74705SXin Li MyLRFoo.test(); // \
824*67e74705SXin Li // expected-warning {{calling function 'test' requires holding mutex 'sls_mu' exclusively}}
825*67e74705SXin Li }
826*67e74705SXin Li
es_bad_4()827*67e74705SXin Li void es_bad_4() {
828*67e74705SXin Li MyLRFoo.testShared(); // \
829*67e74705SXin Li // expected-warning {{calling function 'testShared' requires holding mutex 'sls_mu2'}}
830*67e74705SXin Li }
831*67e74705SXin Li
es_bad_5()832*67e74705SXin Li void es_bad_5() {
833*67e74705SXin Li sls_mu.ReaderLock();
834*67e74705SXin Li MyLRFoo.test(); // \
835*67e74705SXin Li // expected-warning {{calling function 'test' requires holding mutex 'sls_mu' exclusively}}
836*67e74705SXin Li sls_mu.Unlock();
837*67e74705SXin Li }
838*67e74705SXin Li
es_bad_6()839*67e74705SXin Li void es_bad_6() {
840*67e74705SXin Li sls_mu.Lock();
841*67e74705SXin Li Bar.le_fun(); // \
842*67e74705SXin Li // expected-warning {{cannot call function 'le_fun' while mutex 'sls_mu' is held}}
843*67e74705SXin Li sls_mu.Unlock();
844*67e74705SXin Li }
845*67e74705SXin Li
es_bad_7()846*67e74705SXin Li void es_bad_7() {
847*67e74705SXin Li sls_mu.ReaderLock();
848*67e74705SXin Li Bar.le_fun(); // \
849*67e74705SXin Li // expected-warning {{cannot call function 'le_fun' while mutex 'sls_mu' is held}}
850*67e74705SXin Li sls_mu.Unlock();
851*67e74705SXin Li }
852*67e74705SXin Li
853*67e74705SXin Li
854*67e74705SXin Li //-----------------------------------------------//
855*67e74705SXin Li // Unparseable lock expressions
856*67e74705SXin Li // ----------------------------------------------//
857*67e74705SXin Li
858*67e74705SXin Li // FIXME -- derive new tests for unhandled expressions
859*67e74705SXin Li
860*67e74705SXin Li
861*67e74705SXin Li //----------------------------------------------------------------------------//
862*67e74705SXin Li // The following test cases are ported from the gcc thread safety implementation
863*67e74705SXin Li // They are each wrapped inside a namespace with the test number of the gcc test
864*67e74705SXin Li //
865*67e74705SXin Li // FIXME: add all the gcc tests, once this analysis passes them.
866*67e74705SXin Li //----------------------------------------------------------------------------//
867*67e74705SXin Li
868*67e74705SXin Li //-----------------------------------------//
869*67e74705SXin Li // Good testcases (no errors)
870*67e74705SXin Li //-----------------------------------------//
871*67e74705SXin Li
872*67e74705SXin Li namespace thread_annot_lock_20 {
873*67e74705SXin Li class Bar {
874*67e74705SXin Li public:
875*67e74705SXin Li static int func1() EXCLUSIVE_LOCKS_REQUIRED(mu1_);
876*67e74705SXin Li static int b_ GUARDED_BY(mu1_);
877*67e74705SXin Li static Mutex mu1_;
878*67e74705SXin Li static int a_ GUARDED_BY(mu1_);
879*67e74705SXin Li };
880*67e74705SXin Li
881*67e74705SXin Li Bar b1;
882*67e74705SXin Li
func1()883*67e74705SXin Li int Bar::func1()
884*67e74705SXin Li {
885*67e74705SXin Li int res = 5;
886*67e74705SXin Li
887*67e74705SXin Li if (a_ == 4)
888*67e74705SXin Li res = b_;
889*67e74705SXin Li return res;
890*67e74705SXin Li }
891*67e74705SXin Li } // end namespace thread_annot_lock_20
892*67e74705SXin Li
893*67e74705SXin Li namespace thread_annot_lock_22 {
894*67e74705SXin Li // Test various usage of GUARDED_BY and PT_GUARDED_BY annotations, especially
895*67e74705SXin Li // uses in class definitions.
896*67e74705SXin Li Mutex mu;
897*67e74705SXin Li
898*67e74705SXin Li class Bar {
899*67e74705SXin Li public:
900*67e74705SXin Li int a_ GUARDED_BY(mu1_);
901*67e74705SXin Li int b_;
902*67e74705SXin Li int *q PT_GUARDED_BY(mu);
903*67e74705SXin Li Mutex mu1_ ACQUIRED_AFTER(mu);
904*67e74705SXin Li };
905*67e74705SXin Li
906*67e74705SXin Li Bar b1, *b3;
907*67e74705SXin Li int *p GUARDED_BY(mu) PT_GUARDED_BY(mu);
908*67e74705SXin Li int res GUARDED_BY(mu) = 5;
909*67e74705SXin Li
func(int i)910*67e74705SXin Li int func(int i)
911*67e74705SXin Li {
912*67e74705SXin Li int x;
913*67e74705SXin Li mu.Lock();
914*67e74705SXin Li b1.mu1_.Lock();
915*67e74705SXin Li res = b1.a_ + b3->b_;
916*67e74705SXin Li *p = i;
917*67e74705SXin Li b1.a_ = res + b3->b_;
918*67e74705SXin Li b3->b_ = *b1.q;
919*67e74705SXin Li b1.mu1_.Unlock();
920*67e74705SXin Li b1.b_ = res;
921*67e74705SXin Li x = res;
922*67e74705SXin Li mu.Unlock();
923*67e74705SXin Li return x;
924*67e74705SXin Li }
925*67e74705SXin Li } // end namespace thread_annot_lock_22
926*67e74705SXin Li
927*67e74705SXin Li namespace thread_annot_lock_27_modified {
928*67e74705SXin Li // test lock annotations applied to function definitions
929*67e74705SXin Li // Modified: applied annotations only to function declarations
930*67e74705SXin Li Mutex mu1;
931*67e74705SXin Li Mutex mu2 ACQUIRED_AFTER(mu1);
932*67e74705SXin Li
933*67e74705SXin Li class Foo {
934*67e74705SXin Li public:
935*67e74705SXin Li int method1(int i) SHARED_LOCKS_REQUIRED(mu2) EXCLUSIVE_LOCKS_REQUIRED(mu1);
936*67e74705SXin Li };
937*67e74705SXin Li
method1(int i)938*67e74705SXin Li int Foo::method1(int i) {
939*67e74705SXin Li return i;
940*67e74705SXin Li }
941*67e74705SXin Li
942*67e74705SXin Li
943*67e74705SXin Li int foo(int i) EXCLUSIVE_LOCKS_REQUIRED(mu2) SHARED_LOCKS_REQUIRED(mu1);
foo(int i)944*67e74705SXin Li int foo(int i) {
945*67e74705SXin Li return i;
946*67e74705SXin Li }
947*67e74705SXin Li
948*67e74705SXin Li static int bar(int i) EXCLUSIVE_LOCKS_REQUIRED(mu1);
bar(int i)949*67e74705SXin Li static int bar(int i) {
950*67e74705SXin Li return i;
951*67e74705SXin Li }
952*67e74705SXin Li
main()953*67e74705SXin Li void main() {
954*67e74705SXin Li Foo a;
955*67e74705SXin Li
956*67e74705SXin Li mu1.Lock();
957*67e74705SXin Li mu2.Lock();
958*67e74705SXin Li a.method1(1);
959*67e74705SXin Li foo(2);
960*67e74705SXin Li mu2.Unlock();
961*67e74705SXin Li bar(3);
962*67e74705SXin Li mu1.Unlock();
963*67e74705SXin Li }
964*67e74705SXin Li } // end namespace thread_annot_lock_27_modified
965*67e74705SXin Li
966*67e74705SXin Li
967*67e74705SXin Li namespace thread_annot_lock_38 {
968*67e74705SXin Li // Test the case where a template member function is annotated with lock
969*67e74705SXin Li // attributes in a non-template class.
970*67e74705SXin Li class Foo {
971*67e74705SXin Li public:
972*67e74705SXin Li void func1(int y) LOCKS_EXCLUDED(mu_);
973*67e74705SXin Li template <typename T> void func2(T x) LOCKS_EXCLUDED(mu_);
974*67e74705SXin Li private:
975*67e74705SXin Li Mutex mu_;
976*67e74705SXin Li };
977*67e74705SXin Li
978*67e74705SXin Li Foo *foo;
979*67e74705SXin Li
main()980*67e74705SXin Li void main()
981*67e74705SXin Li {
982*67e74705SXin Li foo->func1(5);
983*67e74705SXin Li foo->func2(5);
984*67e74705SXin Li }
985*67e74705SXin Li } // end namespace thread_annot_lock_38
986*67e74705SXin Li
987*67e74705SXin Li namespace thread_annot_lock_43 {
988*67e74705SXin Li // Tests lock canonicalization
989*67e74705SXin Li class Foo {
990*67e74705SXin Li public:
991*67e74705SXin Li Mutex *mu_;
992*67e74705SXin Li };
993*67e74705SXin Li
994*67e74705SXin Li class FooBar {
995*67e74705SXin Li public:
996*67e74705SXin Li Foo *foo_;
GetA()997*67e74705SXin Li int GetA() EXCLUSIVE_LOCKS_REQUIRED(foo_->mu_) { return a_; }
998*67e74705SXin Li int a_ GUARDED_BY(foo_->mu_);
999*67e74705SXin Li };
1000*67e74705SXin Li
1001*67e74705SXin Li FooBar *fb;
1002*67e74705SXin Li
main()1003*67e74705SXin Li void main()
1004*67e74705SXin Li {
1005*67e74705SXin Li int x;
1006*67e74705SXin Li fb->foo_->mu_->Lock();
1007*67e74705SXin Li x = fb->GetA();
1008*67e74705SXin Li fb->foo_->mu_->Unlock();
1009*67e74705SXin Li }
1010*67e74705SXin Li } // end namespace thread_annot_lock_43
1011*67e74705SXin Li
1012*67e74705SXin Li namespace thread_annot_lock_49 {
1013*67e74705SXin Li // Test the support for use of lock expression in the annotations
1014*67e74705SXin Li class Foo {
1015*67e74705SXin Li public:
1016*67e74705SXin Li Mutex foo_mu_;
1017*67e74705SXin Li };
1018*67e74705SXin Li
1019*67e74705SXin Li class Bar {
1020*67e74705SXin Li private:
1021*67e74705SXin Li Foo *foo;
1022*67e74705SXin Li Mutex bar_mu_ ACQUIRED_AFTER(foo->foo_mu_);
1023*67e74705SXin Li
1024*67e74705SXin Li public:
Test1()1025*67e74705SXin Li void Test1() {
1026*67e74705SXin Li foo->foo_mu_.Lock();
1027*67e74705SXin Li bar_mu_.Lock();
1028*67e74705SXin Li bar_mu_.Unlock();
1029*67e74705SXin Li foo->foo_mu_.Unlock();
1030*67e74705SXin Li }
1031*67e74705SXin Li };
1032*67e74705SXin Li
main()1033*67e74705SXin Li void main() {
1034*67e74705SXin Li Bar bar;
1035*67e74705SXin Li bar.Test1();
1036*67e74705SXin Li }
1037*67e74705SXin Li } // end namespace thread_annot_lock_49
1038*67e74705SXin Li
1039*67e74705SXin Li namespace thread_annot_lock_61_modified {
1040*67e74705SXin Li // Modified to fix the compiler errors
1041*67e74705SXin Li // Test the fix for a bug introduced by the support of pass-by-reference
1042*67e74705SXin Li // paramters.
operator <<thread_annot_lock_61_modified::Foo1043*67e74705SXin Li struct Foo { Foo &operator<< (bool) {return *this;} };
1044*67e74705SXin Li Foo &getFoo();
functhread_annot_lock_61_modified::Bar1045*67e74705SXin Li struct Bar { Foo &func () {return getFoo();} };
operator &thread_annot_lock_61_modified::Bas1046*67e74705SXin Li struct Bas { void operator& (Foo &) {} };
mumble()1047*67e74705SXin Li void mumble()
1048*67e74705SXin Li {
1049*67e74705SXin Li Bas() & Bar().func() << "" << "";
1050*67e74705SXin Li Bas() & Bar().func() << "";
1051*67e74705SXin Li }
1052*67e74705SXin Li } // end namespace thread_annot_lock_61_modified
1053*67e74705SXin Li
1054*67e74705SXin Li
1055*67e74705SXin Li namespace thread_annot_lock_65 {
1056*67e74705SXin Li // Test the fix for a bug in the support of allowing reader locks for
1057*67e74705SXin Li // non-const, non-modifying overload functions. (We didn't handle the builtin
1058*67e74705SXin Li // properly.)
1059*67e74705SXin Li enum MyFlags {
1060*67e74705SXin Li Zero,
1061*67e74705SXin Li One,
1062*67e74705SXin Li Two,
1063*67e74705SXin Li Three,
1064*67e74705SXin Li Four,
1065*67e74705SXin Li Five,
1066*67e74705SXin Li Six,
1067*67e74705SXin Li Seven,
1068*67e74705SXin Li Eight,
1069*67e74705SXin Li Nine
1070*67e74705SXin Li };
1071*67e74705SXin Li
1072*67e74705SXin Li inline MyFlags
operator |(MyFlags a,MyFlags b)1073*67e74705SXin Li operator|(MyFlags a, MyFlags b)
1074*67e74705SXin Li {
1075*67e74705SXin Li return MyFlags(static_cast<int>(a) | static_cast<int>(b));
1076*67e74705SXin Li }
1077*67e74705SXin Li
1078*67e74705SXin Li inline MyFlags&
operator |=(MyFlags & a,MyFlags b)1079*67e74705SXin Li operator|=(MyFlags& a, MyFlags b)
1080*67e74705SXin Li {
1081*67e74705SXin Li return a = a | b;
1082*67e74705SXin Li }
1083*67e74705SXin Li } // end namespace thread_annot_lock_65
1084*67e74705SXin Li
1085*67e74705SXin Li namespace thread_annot_lock_66_modified {
1086*67e74705SXin Li // Modified: Moved annotation to function defn
1087*67e74705SXin Li // Test annotations on out-of-line definitions of member functions where the
1088*67e74705SXin Li // annotations refer to locks that are also data members in the class.
1089*67e74705SXin Li Mutex mu;
1090*67e74705SXin Li
1091*67e74705SXin Li class Foo {
1092*67e74705SXin Li public:
1093*67e74705SXin Li int method1(int i) SHARED_LOCKS_REQUIRED(mu1, mu, mu2);
1094*67e74705SXin Li int data GUARDED_BY(mu1);
1095*67e74705SXin Li Mutex *mu1;
1096*67e74705SXin Li Mutex *mu2;
1097*67e74705SXin Li };
1098*67e74705SXin Li
method1(int i)1099*67e74705SXin Li int Foo::method1(int i)
1100*67e74705SXin Li {
1101*67e74705SXin Li return data + i;
1102*67e74705SXin Li }
1103*67e74705SXin Li
main()1104*67e74705SXin Li void main()
1105*67e74705SXin Li {
1106*67e74705SXin Li Foo a;
1107*67e74705SXin Li
1108*67e74705SXin Li a.mu2->Lock();
1109*67e74705SXin Li a.mu1->Lock();
1110*67e74705SXin Li mu.Lock();
1111*67e74705SXin Li a.method1(1);
1112*67e74705SXin Li mu.Unlock();
1113*67e74705SXin Li a.mu1->Unlock();
1114*67e74705SXin Li a.mu2->Unlock();
1115*67e74705SXin Li }
1116*67e74705SXin Li } // end namespace thread_annot_lock_66_modified
1117*67e74705SXin Li
1118*67e74705SXin Li namespace thread_annot_lock_68_modified {
1119*67e74705SXin Li // Test a fix to a bug in the delayed name binding with nested template
1120*67e74705SXin Li // instantiation. We use a stack to make sure a name is not resolved to an
1121*67e74705SXin Li // inner context.
1122*67e74705SXin Li template <typename T>
1123*67e74705SXin Li class Bar {
1124*67e74705SXin Li Mutex mu_;
1125*67e74705SXin Li };
1126*67e74705SXin Li
1127*67e74705SXin Li template <typename T>
1128*67e74705SXin Li class Foo {
1129*67e74705SXin Li public:
func(T x)1130*67e74705SXin Li void func(T x) {
1131*67e74705SXin Li mu_.Lock();
1132*67e74705SXin Li count_ = x;
1133*67e74705SXin Li mu_.Unlock();
1134*67e74705SXin Li }
1135*67e74705SXin Li
1136*67e74705SXin Li private:
1137*67e74705SXin Li T count_ GUARDED_BY(mu_);
1138*67e74705SXin Li Bar<T> bar_;
1139*67e74705SXin Li Mutex mu_;
1140*67e74705SXin Li };
1141*67e74705SXin Li
main()1142*67e74705SXin Li void main()
1143*67e74705SXin Li {
1144*67e74705SXin Li Foo<int> *foo;
1145*67e74705SXin Li foo->func(5);
1146*67e74705SXin Li }
1147*67e74705SXin Li } // end namespace thread_annot_lock_68_modified
1148*67e74705SXin Li
1149*67e74705SXin Li namespace thread_annot_lock_30_modified {
1150*67e74705SXin Li // Test delay parsing of lock attribute arguments with nested classes.
1151*67e74705SXin Li // Modified: trylocks replaced with exclusive_lock_fun
1152*67e74705SXin Li int a = 0;
1153*67e74705SXin Li
1154*67e74705SXin Li class Bar {
1155*67e74705SXin Li struct Foo;
1156*67e74705SXin Li
1157*67e74705SXin Li public:
1158*67e74705SXin Li void MyLock() EXCLUSIVE_LOCK_FUNCTION(mu);
1159*67e74705SXin Li
func()1160*67e74705SXin Li int func() {
1161*67e74705SXin Li MyLock();
1162*67e74705SXin Li // if (foo == 0) {
1163*67e74705SXin Li // return 0;
1164*67e74705SXin Li // }
1165*67e74705SXin Li a = 5;
1166*67e74705SXin Li mu.Unlock();
1167*67e74705SXin Li return 1;
1168*67e74705SXin Li }
1169*67e74705SXin Li
1170*67e74705SXin Li class FooBar {
1171*67e74705SXin Li int x;
1172*67e74705SXin Li int y;
1173*67e74705SXin Li };
1174*67e74705SXin Li
1175*67e74705SXin Li private:
1176*67e74705SXin Li Mutex mu;
1177*67e74705SXin Li };
1178*67e74705SXin Li
1179*67e74705SXin Li Bar *bar;
1180*67e74705SXin Li
main()1181*67e74705SXin Li void main()
1182*67e74705SXin Li {
1183*67e74705SXin Li bar->func();
1184*67e74705SXin Li }
1185*67e74705SXin Li } // end namespace thread_annot_lock_30_modified
1186*67e74705SXin Li
1187*67e74705SXin Li namespace thread_annot_lock_47 {
1188*67e74705SXin Li // Test the support for annotations on virtual functions.
1189*67e74705SXin Li // This is a good test case. (i.e. There should be no warning emitted by the
1190*67e74705SXin Li // compiler.)
1191*67e74705SXin Li class Base {
1192*67e74705SXin Li public:
1193*67e74705SXin Li virtual void func1() EXCLUSIVE_LOCKS_REQUIRED(mu_);
1194*67e74705SXin Li virtual void func2() LOCKS_EXCLUDED(mu_);
1195*67e74705SXin Li Mutex mu_;
1196*67e74705SXin Li };
1197*67e74705SXin Li
1198*67e74705SXin Li class Child : public Base {
1199*67e74705SXin Li public:
1200*67e74705SXin Li virtual void func1() EXCLUSIVE_LOCKS_REQUIRED(mu_);
1201*67e74705SXin Li virtual void func2() LOCKS_EXCLUDED(mu_);
1202*67e74705SXin Li };
1203*67e74705SXin Li
main()1204*67e74705SXin Li void main() {
1205*67e74705SXin Li Child *c;
1206*67e74705SXin Li Base *b = c;
1207*67e74705SXin Li
1208*67e74705SXin Li b->mu_.Lock();
1209*67e74705SXin Li b->func1();
1210*67e74705SXin Li b->mu_.Unlock();
1211*67e74705SXin Li b->func2();
1212*67e74705SXin Li
1213*67e74705SXin Li c->mu_.Lock();
1214*67e74705SXin Li c->func1();
1215*67e74705SXin Li c->mu_.Unlock();
1216*67e74705SXin Li c->func2();
1217*67e74705SXin Li }
1218*67e74705SXin Li } // end namespace thread_annot_lock_47
1219*67e74705SXin Li
1220*67e74705SXin Li //-----------------------------------------//
1221*67e74705SXin Li // Tests which produce errors
1222*67e74705SXin Li //-----------------------------------------//
1223*67e74705SXin Li
1224*67e74705SXin Li namespace thread_annot_lock_13 {
1225*67e74705SXin Li Mutex mu1;
1226*67e74705SXin Li Mutex mu2;
1227*67e74705SXin Li
1228*67e74705SXin Li int g GUARDED_BY(mu1);
1229*67e74705SXin Li int w GUARDED_BY(mu2);
1230*67e74705SXin Li
1231*67e74705SXin Li class Foo {
1232*67e74705SXin Li public:
1233*67e74705SXin Li void bar() LOCKS_EXCLUDED(mu_, mu1);
1234*67e74705SXin Li int foo() SHARED_LOCKS_REQUIRED(mu_) EXCLUSIVE_LOCKS_REQUIRED(mu2);
1235*67e74705SXin Li
1236*67e74705SXin Li private:
1237*67e74705SXin Li int a_ GUARDED_BY(mu_);
1238*67e74705SXin Li public:
1239*67e74705SXin Li Mutex mu_ ACQUIRED_AFTER(mu1);
1240*67e74705SXin Li };
1241*67e74705SXin Li
foo()1242*67e74705SXin Li int Foo::foo()
1243*67e74705SXin Li {
1244*67e74705SXin Li int res;
1245*67e74705SXin Li w = 5;
1246*67e74705SXin Li res = a_ + 5;
1247*67e74705SXin Li return res;
1248*67e74705SXin Li }
1249*67e74705SXin Li
bar()1250*67e74705SXin Li void Foo::bar()
1251*67e74705SXin Li {
1252*67e74705SXin Li int x;
1253*67e74705SXin Li mu_.Lock();
1254*67e74705SXin Li x = foo(); // expected-warning {{calling function 'foo' requires holding mutex 'mu2' exclusively}}
1255*67e74705SXin Li a_ = x + 1;
1256*67e74705SXin Li mu_.Unlock();
1257*67e74705SXin Li if (x > 5) {
1258*67e74705SXin Li mu1.Lock();
1259*67e74705SXin Li g = 2;
1260*67e74705SXin Li mu1.Unlock();
1261*67e74705SXin Li }
1262*67e74705SXin Li }
1263*67e74705SXin Li
main()1264*67e74705SXin Li void main()
1265*67e74705SXin Li {
1266*67e74705SXin Li Foo f1, *f2;
1267*67e74705SXin Li f1.mu_.Lock();
1268*67e74705SXin Li f1.bar(); // expected-warning {{cannot call function 'bar' while mutex 'f1.mu_' is held}}
1269*67e74705SXin Li mu2.Lock();
1270*67e74705SXin Li f1.foo();
1271*67e74705SXin Li mu2.Unlock();
1272*67e74705SXin Li f1.mu_.Unlock();
1273*67e74705SXin Li f2->mu_.Lock();
1274*67e74705SXin Li f2->bar(); // expected-warning {{cannot call function 'bar' while mutex 'f2->mu_' is held}}
1275*67e74705SXin Li f2->mu_.Unlock();
1276*67e74705SXin Li mu2.Lock();
1277*67e74705SXin Li w = 2;
1278*67e74705SXin Li mu2.Unlock();
1279*67e74705SXin Li }
1280*67e74705SXin Li } // end namespace thread_annot_lock_13
1281*67e74705SXin Li
1282*67e74705SXin Li namespace thread_annot_lock_18_modified {
1283*67e74705SXin Li // Modified: Trylocks removed
1284*67e74705SXin Li // Test the ability to distnguish between the same lock field of
1285*67e74705SXin Li // different objects of a class.
1286*67e74705SXin Li class Bar {
1287*67e74705SXin Li public:
1288*67e74705SXin Li bool MyLock() EXCLUSIVE_LOCK_FUNCTION(mu1_);
1289*67e74705SXin Li void MyUnlock() UNLOCK_FUNCTION(mu1_);
1290*67e74705SXin Li int a_ GUARDED_BY(mu1_);
1291*67e74705SXin Li
1292*67e74705SXin Li private:
1293*67e74705SXin Li Mutex mu1_;
1294*67e74705SXin Li };
1295*67e74705SXin Li
1296*67e74705SXin Li Bar *b1, *b2;
1297*67e74705SXin Li
func()1298*67e74705SXin Li void func()
1299*67e74705SXin Li {
1300*67e74705SXin Li b1->MyLock();
1301*67e74705SXin Li b1->a_ = 5;
1302*67e74705SXin Li b2->a_ = 3; // \
1303*67e74705SXin Li // expected-warning {{writing variable 'a_' requires holding mutex 'b2->mu1_' exclusively}} \
1304*67e74705SXin Li // expected-note {{found near match 'b1->mu1_'}}
1305*67e74705SXin Li b2->MyLock();
1306*67e74705SXin Li b2->MyUnlock();
1307*67e74705SXin Li b1->MyUnlock();
1308*67e74705SXin Li }
1309*67e74705SXin Li } // end namespace thread_annot_lock_18_modified
1310*67e74705SXin Li
1311*67e74705SXin Li namespace thread_annot_lock_21 {
1312*67e74705SXin Li // Test various usage of GUARDED_BY and PT_GUARDED_BY annotations, especially
1313*67e74705SXin Li // uses in class definitions.
1314*67e74705SXin Li Mutex mu;
1315*67e74705SXin Li
1316*67e74705SXin Li class Bar {
1317*67e74705SXin Li public:
1318*67e74705SXin Li int a_ GUARDED_BY(mu1_);
1319*67e74705SXin Li int b_;
1320*67e74705SXin Li int *q PT_GUARDED_BY(mu);
1321*67e74705SXin Li Mutex mu1_ ACQUIRED_AFTER(mu);
1322*67e74705SXin Li };
1323*67e74705SXin Li
1324*67e74705SXin Li Bar b1, *b3;
1325*67e74705SXin Li int *p GUARDED_BY(mu) PT_GUARDED_BY(mu);
1326*67e74705SXin Li
1327*67e74705SXin Li int res GUARDED_BY(mu) = 5;
1328*67e74705SXin Li
func(int i)1329*67e74705SXin Li int func(int i)
1330*67e74705SXin Li {
1331*67e74705SXin Li int x;
1332*67e74705SXin Li b3->mu1_.Lock();
1333*67e74705SXin Li res = b1.a_ + b3->b_; // expected-warning {{reading variable 'a_' requires holding mutex 'b1.mu1_'}} \
1334*67e74705SXin Li // expected-warning {{writing variable 'res' requires holding mutex 'mu' exclusively}} \
1335*67e74705SXin Li // expected-note {{found near match 'b3->mu1_'}}
1336*67e74705SXin Li *p = i; // expected-warning {{reading variable 'p' requires holding mutex 'mu'}} \
1337*67e74705SXin Li // expected-warning {{writing the value pointed to by 'p' requires holding mutex 'mu' exclusively}}
1338*67e74705SXin Li b1.a_ = res + b3->b_; // expected-warning {{reading variable 'res' requires holding mutex 'mu'}} \
1339*67e74705SXin Li // expected-warning {{writing variable 'a_' requires holding mutex 'b1.mu1_' exclusively}} \
1340*67e74705SXin Li // expected-note {{found near match 'b3->mu1_'}}
1341*67e74705SXin Li b3->b_ = *b1.q; // expected-warning {{reading the value pointed to by 'q' requires holding mutex 'mu'}}
1342*67e74705SXin Li b3->mu1_.Unlock();
1343*67e74705SXin Li b1.b_ = res; // expected-warning {{reading variable 'res' requires holding mutex 'mu'}}
1344*67e74705SXin Li x = res; // expected-warning {{reading variable 'res' requires holding mutex 'mu'}}
1345*67e74705SXin Li return x;
1346*67e74705SXin Li }
1347*67e74705SXin Li } // end namespace thread_annot_lock_21
1348*67e74705SXin Li
1349*67e74705SXin Li namespace thread_annot_lock_35_modified {
1350*67e74705SXin Li // Test the analyzer's ability to distinguish the lock field of different
1351*67e74705SXin Li // objects.
1352*67e74705SXin Li class Foo {
1353*67e74705SXin Li private:
1354*67e74705SXin Li Mutex lock_;
1355*67e74705SXin Li int a_ GUARDED_BY(lock_);
1356*67e74705SXin Li
1357*67e74705SXin Li public:
Func(Foo * child)1358*67e74705SXin Li void Func(Foo* child) LOCKS_EXCLUDED(lock_) {
1359*67e74705SXin Li Foo *new_foo = new Foo;
1360*67e74705SXin Li
1361*67e74705SXin Li lock_.Lock();
1362*67e74705SXin Li
1363*67e74705SXin Li child->Func(new_foo); // There shouldn't be any warning here as the
1364*67e74705SXin Li // acquired lock is not in child.
1365*67e74705SXin Li child->bar(7); // \
1366*67e74705SXin Li // expected-warning {{calling function 'bar' requires holding mutex 'child->lock_' exclusively}} \
1367*67e74705SXin Li // expected-note {{found near match 'lock_'}}
1368*67e74705SXin Li child->a_ = 5; // \
1369*67e74705SXin Li // expected-warning {{writing variable 'a_' requires holding mutex 'child->lock_' exclusively}} \
1370*67e74705SXin Li // expected-note {{found near match 'lock_'}}
1371*67e74705SXin Li lock_.Unlock();
1372*67e74705SXin Li }
1373*67e74705SXin Li
bar(int y)1374*67e74705SXin Li void bar(int y) EXCLUSIVE_LOCKS_REQUIRED(lock_) {
1375*67e74705SXin Li a_ = y;
1376*67e74705SXin Li }
1377*67e74705SXin Li };
1378*67e74705SXin Li
1379*67e74705SXin Li Foo *x;
1380*67e74705SXin Li
main()1381*67e74705SXin Li void main() {
1382*67e74705SXin Li Foo *child = new Foo;
1383*67e74705SXin Li x->Func(child);
1384*67e74705SXin Li }
1385*67e74705SXin Li } // end namespace thread_annot_lock_35_modified
1386*67e74705SXin Li
1387*67e74705SXin Li namespace thread_annot_lock_36_modified {
1388*67e74705SXin Li // Modified to move the annotations to function defns.
1389*67e74705SXin Li // Test the analyzer's ability to distinguish the lock field of different
1390*67e74705SXin Li // objects
1391*67e74705SXin Li class Foo {
1392*67e74705SXin Li private:
1393*67e74705SXin Li Mutex lock_;
1394*67e74705SXin Li int a_ GUARDED_BY(lock_);
1395*67e74705SXin Li
1396*67e74705SXin Li public:
1397*67e74705SXin Li void Func(Foo* child) LOCKS_EXCLUDED(lock_);
1398*67e74705SXin Li void bar(int y) EXCLUSIVE_LOCKS_REQUIRED(lock_);
1399*67e74705SXin Li };
1400*67e74705SXin Li
Func(Foo * child)1401*67e74705SXin Li void Foo::Func(Foo* child) {
1402*67e74705SXin Li Foo *new_foo = new Foo;
1403*67e74705SXin Li
1404*67e74705SXin Li lock_.Lock();
1405*67e74705SXin Li
1406*67e74705SXin Li child->lock_.Lock();
1407*67e74705SXin Li child->Func(new_foo); // expected-warning {{cannot call function 'Func' while mutex 'child->lock_' is held}}
1408*67e74705SXin Li child->bar(7);
1409*67e74705SXin Li child->a_ = 5;
1410*67e74705SXin Li child->lock_.Unlock();
1411*67e74705SXin Li
1412*67e74705SXin Li lock_.Unlock();
1413*67e74705SXin Li }
1414*67e74705SXin Li
bar(int y)1415*67e74705SXin Li void Foo::bar(int y) {
1416*67e74705SXin Li a_ = y;
1417*67e74705SXin Li }
1418*67e74705SXin Li
1419*67e74705SXin Li
1420*67e74705SXin Li Foo *x;
1421*67e74705SXin Li
main()1422*67e74705SXin Li void main() {
1423*67e74705SXin Li Foo *child = new Foo;
1424*67e74705SXin Li x->Func(child);
1425*67e74705SXin Li }
1426*67e74705SXin Li } // end namespace thread_annot_lock_36_modified
1427*67e74705SXin Li
1428*67e74705SXin Li
1429*67e74705SXin Li namespace thread_annot_lock_42 {
1430*67e74705SXin Li // Test support of multiple lock attributes of the same kind on a decl.
1431*67e74705SXin Li class Foo {
1432*67e74705SXin Li private:
1433*67e74705SXin Li Mutex mu1, mu2, mu3;
1434*67e74705SXin Li int x GUARDED_BY(mu1) GUARDED_BY(mu2);
1435*67e74705SXin Li int y GUARDED_BY(mu2);
1436*67e74705SXin Li
f2()1437*67e74705SXin Li void f2() LOCKS_EXCLUDED(mu1) LOCKS_EXCLUDED(mu2) LOCKS_EXCLUDED(mu3) {
1438*67e74705SXin Li mu2.Lock();
1439*67e74705SXin Li y = 2;
1440*67e74705SXin Li mu2.Unlock();
1441*67e74705SXin Li }
1442*67e74705SXin Li
1443*67e74705SXin Li public:
f1()1444*67e74705SXin Li void f1() EXCLUSIVE_LOCKS_REQUIRED(mu2) EXCLUSIVE_LOCKS_REQUIRED(mu1) {
1445*67e74705SXin Li x = 5;
1446*67e74705SXin Li f2(); // expected-warning {{cannot call function 'f2' while mutex 'mu1' is held}} \
1447*67e74705SXin Li // expected-warning {{cannot call function 'f2' while mutex 'mu2' is held}}
1448*67e74705SXin Li }
1449*67e74705SXin Li };
1450*67e74705SXin Li
1451*67e74705SXin Li Foo *foo;
1452*67e74705SXin Li
func()1453*67e74705SXin Li void func()
1454*67e74705SXin Li {
1455*67e74705SXin Li foo->f1(); // expected-warning {{calling function 'f1' requires holding mutex 'foo->mu2' exclusively}} \
1456*67e74705SXin Li // expected-warning {{calling function 'f1' requires holding mutex 'foo->mu1' exclusively}}
1457*67e74705SXin Li }
1458*67e74705SXin Li } // end namespace thread_annot_lock_42
1459*67e74705SXin Li
1460*67e74705SXin Li namespace thread_annot_lock_46 {
1461*67e74705SXin Li // Test the support for annotations on virtual functions.
1462*67e74705SXin Li class Base {
1463*67e74705SXin Li public:
1464*67e74705SXin Li virtual void func1() EXCLUSIVE_LOCKS_REQUIRED(mu_);
1465*67e74705SXin Li virtual void func2() LOCKS_EXCLUDED(mu_);
1466*67e74705SXin Li Mutex mu_;
1467*67e74705SXin Li };
1468*67e74705SXin Li
1469*67e74705SXin Li class Child : public Base {
1470*67e74705SXin Li public:
1471*67e74705SXin Li virtual void func1() EXCLUSIVE_LOCKS_REQUIRED(mu_);
1472*67e74705SXin Li virtual void func2() LOCKS_EXCLUDED(mu_);
1473*67e74705SXin Li };
1474*67e74705SXin Li
main()1475*67e74705SXin Li void main() {
1476*67e74705SXin Li Child *c;
1477*67e74705SXin Li Base *b = c;
1478*67e74705SXin Li
1479*67e74705SXin Li b->func1(); // expected-warning {{calling function 'func1' requires holding mutex 'b->mu_' exclusively}}
1480*67e74705SXin Li b->mu_.Lock();
1481*67e74705SXin Li b->func2(); // expected-warning {{cannot call function 'func2' while mutex 'b->mu_' is held}}
1482*67e74705SXin Li b->mu_.Unlock();
1483*67e74705SXin Li
1484*67e74705SXin Li c->func1(); // expected-warning {{calling function 'func1' requires holding mutex 'c->mu_' exclusively}}
1485*67e74705SXin Li c->mu_.Lock();
1486*67e74705SXin Li c->func2(); // expected-warning {{cannot call function 'func2' while mutex 'c->mu_' is held}}
1487*67e74705SXin Li c->mu_.Unlock();
1488*67e74705SXin Li }
1489*67e74705SXin Li } // end namespace thread_annot_lock_46
1490*67e74705SXin Li
1491*67e74705SXin Li namespace thread_annot_lock_67_modified {
1492*67e74705SXin Li // Modified: attributes on definitions moved to declarations
1493*67e74705SXin Li // Test annotations on out-of-line definitions of member functions where the
1494*67e74705SXin Li // annotations refer to locks that are also data members in the class.
1495*67e74705SXin Li Mutex mu;
1496*67e74705SXin Li Mutex mu3;
1497*67e74705SXin Li
1498*67e74705SXin Li class Foo {
1499*67e74705SXin Li public:
1500*67e74705SXin Li int method1(int i) SHARED_LOCKS_REQUIRED(mu1, mu, mu2, mu3);
1501*67e74705SXin Li int data GUARDED_BY(mu1);
1502*67e74705SXin Li Mutex *mu1;
1503*67e74705SXin Li Mutex *mu2;
1504*67e74705SXin Li };
1505*67e74705SXin Li
method1(int i)1506*67e74705SXin Li int Foo::method1(int i) {
1507*67e74705SXin Li return data + i;
1508*67e74705SXin Li }
1509*67e74705SXin Li
main()1510*67e74705SXin Li void main()
1511*67e74705SXin Li {
1512*67e74705SXin Li Foo a;
1513*67e74705SXin Li a.method1(1); // expected-warning {{calling function 'method1' requires holding mutex 'a.mu1'}} \
1514*67e74705SXin Li // expected-warning {{calling function 'method1' requires holding mutex 'mu'}} \
1515*67e74705SXin Li // expected-warning {{calling function 'method1' requires holding mutex 'a.mu2'}} \
1516*67e74705SXin Li // expected-warning {{calling function 'method1' requires holding mutex 'mu3'}}
1517*67e74705SXin Li }
1518*67e74705SXin Li } // end namespace thread_annot_lock_67_modified
1519*67e74705SXin Li
1520*67e74705SXin Li
1521*67e74705SXin Li namespace substitution_test {
1522*67e74705SXin Li class MyData {
1523*67e74705SXin Li public:
1524*67e74705SXin Li Mutex mu;
1525*67e74705SXin Li
1526*67e74705SXin Li void lockData() __attribute__((exclusive_lock_function(mu)));
1527*67e74705SXin Li void unlockData() __attribute__((unlock_function(mu)));
1528*67e74705SXin Li
doSomething()1529*67e74705SXin Li void doSomething() __attribute__((exclusive_locks_required(mu))) { }
1530*67e74705SXin Li };
1531*67e74705SXin Li
1532*67e74705SXin Li
1533*67e74705SXin Li class DataLocker {
1534*67e74705SXin Li public:
1535*67e74705SXin Li void lockData (MyData *d) __attribute__((exclusive_lock_function(d->mu)));
1536*67e74705SXin Li void unlockData(MyData *d) __attribute__((unlock_function(d->mu)));
1537*67e74705SXin Li };
1538*67e74705SXin Li
1539*67e74705SXin Li
1540*67e74705SXin Li class Foo {
1541*67e74705SXin Li public:
foo(MyData * d)1542*67e74705SXin Li void foo(MyData* d) __attribute__((exclusive_locks_required(d->mu))) { }
1543*67e74705SXin Li
bar1(MyData * d)1544*67e74705SXin Li void bar1(MyData* d) {
1545*67e74705SXin Li d->lockData();
1546*67e74705SXin Li foo(d);
1547*67e74705SXin Li d->unlockData();
1548*67e74705SXin Li }
1549*67e74705SXin Li
bar2(MyData * d)1550*67e74705SXin Li void bar2(MyData* d) {
1551*67e74705SXin Li DataLocker dlr;
1552*67e74705SXin Li dlr.lockData(d);
1553*67e74705SXin Li foo(d);
1554*67e74705SXin Li dlr.unlockData(d);
1555*67e74705SXin Li }
1556*67e74705SXin Li
bar3(MyData * d1,MyData * d2)1557*67e74705SXin Li void bar3(MyData* d1, MyData* d2) {
1558*67e74705SXin Li DataLocker dlr;
1559*67e74705SXin Li dlr.lockData(d1); // expected-note {{mutex acquired here}}
1560*67e74705SXin Li dlr.unlockData(d2); // \
1561*67e74705SXin Li // expected-warning {{releasing mutex 'd2->mu' that was not held}}
1562*67e74705SXin Li } // expected-warning {{mutex 'd1->mu' is still held at the end of function}}
1563*67e74705SXin Li
bar4(MyData * d1,MyData * d2)1564*67e74705SXin Li void bar4(MyData* d1, MyData* d2) {
1565*67e74705SXin Li DataLocker dlr;
1566*67e74705SXin Li dlr.lockData(d1);
1567*67e74705SXin Li foo(d2); // \
1568*67e74705SXin Li // expected-warning {{calling function 'foo' requires holding mutex 'd2->mu' exclusively}} \
1569*67e74705SXin Li // expected-note {{found near match 'd1->mu'}}
1570*67e74705SXin Li dlr.unlockData(d1);
1571*67e74705SXin Li }
1572*67e74705SXin Li };
1573*67e74705SXin Li } // end namespace substituation_test
1574*67e74705SXin Li
1575*67e74705SXin Li
1576*67e74705SXin Li
1577*67e74705SXin Li namespace constructor_destructor_tests {
1578*67e74705SXin Li Mutex fooMu;
1579*67e74705SXin Li int myVar GUARDED_BY(fooMu);
1580*67e74705SXin Li
1581*67e74705SXin Li class Foo {
1582*67e74705SXin Li public:
Foo()1583*67e74705SXin Li Foo() __attribute__((exclusive_lock_function(fooMu))) { }
~Foo()1584*67e74705SXin Li ~Foo() __attribute__((unlock_function(fooMu))) { }
1585*67e74705SXin Li };
1586*67e74705SXin Li
fooTest()1587*67e74705SXin Li void fooTest() {
1588*67e74705SXin Li Foo foo;
1589*67e74705SXin Li myVar = 0;
1590*67e74705SXin Li }
1591*67e74705SXin Li }
1592*67e74705SXin Li
1593*67e74705SXin Li
1594*67e74705SXin Li namespace template_member_test {
1595*67e74705SXin Li
1596*67e74705SXin Li struct S { int n; };
1597*67e74705SXin Li struct T {
1598*67e74705SXin Li Mutex m;
1599*67e74705SXin Li S *s GUARDED_BY(this->m);
1600*67e74705SXin Li };
1601*67e74705SXin Li Mutex m;
1602*67e74705SXin Li struct U {
1603*67e74705SXin Li union {
1604*67e74705SXin Li int n;
1605*67e74705SXin Li };
1606*67e74705SXin Li } *u GUARDED_BY(m);
1607*67e74705SXin Li
1608*67e74705SXin Li template<typename U>
1609*67e74705SXin Li struct IndirectLock {
DoNaughtyThingstemplate_member_test::IndirectLock1610*67e74705SXin Li int DoNaughtyThings(T *t) {
1611*67e74705SXin Li u->n = 0; // expected-warning {{reading variable 'u' requires holding mutex 'm'}}
1612*67e74705SXin Li return t->s->n; // expected-warning {{reading variable 's' requires holding mutex 't->m'}}
1613*67e74705SXin Li }
1614*67e74705SXin Li };
1615*67e74705SXin Li
1616*67e74705SXin Li template struct IndirectLock<int>; // expected-note {{here}}
1617*67e74705SXin Li
1618*67e74705SXin Li struct V {
1619*67e74705SXin Li void f(int);
1620*67e74705SXin Li void f(double);
1621*67e74705SXin Li
1622*67e74705SXin Li Mutex m;
1623*67e74705SXin Li V *p GUARDED_BY(this->m);
1624*67e74705SXin Li };
1625*67e74705SXin Li template<typename U> struct W {
1626*67e74705SXin Li V v;
ftemplate_member_test::W1627*67e74705SXin Li void f(U u) {
1628*67e74705SXin Li v.p->f(u); // expected-warning {{reading variable 'p' requires holding mutex 'v.m'}}
1629*67e74705SXin Li }
1630*67e74705SXin Li };
1631*67e74705SXin Li template struct W<int>; // expected-note {{here}}
1632*67e74705SXin Li
1633*67e74705SXin Li }
1634*67e74705SXin Li
1635*67e74705SXin Li namespace test_scoped_lockable {
1636*67e74705SXin Li
1637*67e74705SXin Li struct TestScopedLockable {
1638*67e74705SXin Li Mutex mu1;
1639*67e74705SXin Li Mutex mu2;
1640*67e74705SXin Li int a __attribute__((guarded_by(mu1)));
1641*67e74705SXin Li int b __attribute__((guarded_by(mu2)));
1642*67e74705SXin Li
1643*67e74705SXin Li bool getBool();
1644*67e74705SXin Li
foo1test_scoped_lockable::TestScopedLockable1645*67e74705SXin Li void foo1() {
1646*67e74705SXin Li MutexLock mulock(&mu1);
1647*67e74705SXin Li a = 5;
1648*67e74705SXin Li }
1649*67e74705SXin Li
foo2test_scoped_lockable::TestScopedLockable1650*67e74705SXin Li void foo2() {
1651*67e74705SXin Li ReaderMutexLock mulock1(&mu1);
1652*67e74705SXin Li if (getBool()) {
1653*67e74705SXin Li MutexLock mulock2a(&mu2);
1654*67e74705SXin Li b = a + 1;
1655*67e74705SXin Li }
1656*67e74705SXin Li else {
1657*67e74705SXin Li MutexLock mulock2b(&mu2);
1658*67e74705SXin Li b = a + 2;
1659*67e74705SXin Li }
1660*67e74705SXin Li }
1661*67e74705SXin Li
foo3test_scoped_lockable::TestScopedLockable1662*67e74705SXin Li void foo3() {
1663*67e74705SXin Li MutexLock mulock_a(&mu1);
1664*67e74705SXin Li MutexLock mulock_b(&mu1); // \
1665*67e74705SXin Li // expected-warning {{acquiring mutex 'mu1' that is already held}}
1666*67e74705SXin Li }
1667*67e74705SXin Li
foo4test_scoped_lockable::TestScopedLockable1668*67e74705SXin Li void foo4() {
1669*67e74705SXin Li MutexLock mulock1(&mu1), mulock2(&mu2);
1670*67e74705SXin Li a = b+1;
1671*67e74705SXin Li b = a+1;
1672*67e74705SXin Li }
1673*67e74705SXin Li
foo5test_scoped_lockable::TestScopedLockable1674*67e74705SXin Li void foo5() {
1675*67e74705SXin Li DoubleMutexLock mulock(&mu1, &mu2);
1676*67e74705SXin Li a = b + 1;
1677*67e74705SXin Li b = a + 1;
1678*67e74705SXin Li }
1679*67e74705SXin Li };
1680*67e74705SXin Li
1681*67e74705SXin Li } // end namespace test_scoped_lockable
1682*67e74705SXin Li
1683*67e74705SXin Li
1684*67e74705SXin Li namespace FunctionAttrTest {
1685*67e74705SXin Li
1686*67e74705SXin Li class Foo {
1687*67e74705SXin Li public:
1688*67e74705SXin Li Mutex mu_;
1689*67e74705SXin Li int a GUARDED_BY(mu_);
1690*67e74705SXin Li };
1691*67e74705SXin Li
1692*67e74705SXin Li Foo fooObj;
1693*67e74705SXin Li
1694*67e74705SXin Li void foo() EXCLUSIVE_LOCKS_REQUIRED(fooObj.mu_);
1695*67e74705SXin Li
bar()1696*67e74705SXin Li void bar() {
1697*67e74705SXin Li foo(); // expected-warning {{calling function 'foo' requires holding mutex 'fooObj.mu_' exclusively}}
1698*67e74705SXin Li fooObj.mu_.Lock();
1699*67e74705SXin Li foo();
1700*67e74705SXin Li fooObj.mu_.Unlock();
1701*67e74705SXin Li }
1702*67e74705SXin Li
1703*67e74705SXin Li }; // end namespace FunctionAttrTest
1704*67e74705SXin Li
1705*67e74705SXin Li
1706*67e74705SXin Li namespace TryLockTest {
1707*67e74705SXin Li
1708*67e74705SXin Li struct TestTryLock {
1709*67e74705SXin Li Mutex mu;
1710*67e74705SXin Li int a GUARDED_BY(mu);
1711*67e74705SXin Li bool cond;
1712*67e74705SXin Li
foo1TryLockTest::TestTryLock1713*67e74705SXin Li void foo1() {
1714*67e74705SXin Li if (mu.TryLock()) {
1715*67e74705SXin Li a = 1;
1716*67e74705SXin Li mu.Unlock();
1717*67e74705SXin Li }
1718*67e74705SXin Li }
1719*67e74705SXin Li
foo2TryLockTest::TestTryLock1720*67e74705SXin Li void foo2() {
1721*67e74705SXin Li if (!mu.TryLock()) return;
1722*67e74705SXin Li a = 2;
1723*67e74705SXin Li mu.Unlock();
1724*67e74705SXin Li }
1725*67e74705SXin Li
foo3TryLockTest::TestTryLock1726*67e74705SXin Li void foo3() {
1727*67e74705SXin Li bool b = mu.TryLock();
1728*67e74705SXin Li if (b) {
1729*67e74705SXin Li a = 3;
1730*67e74705SXin Li mu.Unlock();
1731*67e74705SXin Li }
1732*67e74705SXin Li }
1733*67e74705SXin Li
foo4TryLockTest::TestTryLock1734*67e74705SXin Li void foo4() {
1735*67e74705SXin Li bool b = mu.TryLock();
1736*67e74705SXin Li if (!b) return;
1737*67e74705SXin Li a = 4;
1738*67e74705SXin Li mu.Unlock();
1739*67e74705SXin Li }
1740*67e74705SXin Li
foo5TryLockTest::TestTryLock1741*67e74705SXin Li void foo5() {
1742*67e74705SXin Li while (mu.TryLock()) {
1743*67e74705SXin Li a = a + 1;
1744*67e74705SXin Li mu.Unlock();
1745*67e74705SXin Li }
1746*67e74705SXin Li }
1747*67e74705SXin Li
foo6TryLockTest::TestTryLock1748*67e74705SXin Li void foo6() {
1749*67e74705SXin Li bool b = mu.TryLock();
1750*67e74705SXin Li b = !b;
1751*67e74705SXin Li if (b) return;
1752*67e74705SXin Li a = 6;
1753*67e74705SXin Li mu.Unlock();
1754*67e74705SXin Li }
1755*67e74705SXin Li
foo7TryLockTest::TestTryLock1756*67e74705SXin Li void foo7() {
1757*67e74705SXin Li bool b1 = mu.TryLock();
1758*67e74705SXin Li bool b2 = !b1;
1759*67e74705SXin Li bool b3 = !b2;
1760*67e74705SXin Li if (b3) {
1761*67e74705SXin Li a = 7;
1762*67e74705SXin Li mu.Unlock();
1763*67e74705SXin Li }
1764*67e74705SXin Li }
1765*67e74705SXin Li
1766*67e74705SXin Li // Test use-def chains: join points
foo8TryLockTest::TestTryLock1767*67e74705SXin Li void foo8() {
1768*67e74705SXin Li bool b = mu.TryLock();
1769*67e74705SXin Li bool b2 = b;
1770*67e74705SXin Li if (cond)
1771*67e74705SXin Li b = true;
1772*67e74705SXin Li if (b) { // b should be unknown at this point, because of the join point
1773*67e74705SXin Li a = 8; // expected-warning {{writing variable 'a' requires holding mutex 'mu' exclusively}}
1774*67e74705SXin Li }
1775*67e74705SXin Li if (b2) { // b2 should be known at this point.
1776*67e74705SXin Li a = 8;
1777*67e74705SXin Li mu.Unlock();
1778*67e74705SXin Li }
1779*67e74705SXin Li }
1780*67e74705SXin Li
1781*67e74705SXin Li // Test use-def-chains: back edges
foo9TryLockTest::TestTryLock1782*67e74705SXin Li void foo9() {
1783*67e74705SXin Li bool b = mu.TryLock();
1784*67e74705SXin Li
1785*67e74705SXin Li for (int i = 0; i < 10; ++i);
1786*67e74705SXin Li
1787*67e74705SXin Li if (b) { // b is still known, because the loop doesn't alter it
1788*67e74705SXin Li a = 9;
1789*67e74705SXin Li mu.Unlock();
1790*67e74705SXin Li }
1791*67e74705SXin Li }
1792*67e74705SXin Li
1793*67e74705SXin Li // Test use-def chains: back edges
foo10TryLockTest::TestTryLock1794*67e74705SXin Li void foo10() {
1795*67e74705SXin Li bool b = mu.TryLock();
1796*67e74705SXin Li
1797*67e74705SXin Li while (cond) {
1798*67e74705SXin Li if (b) { // b should be uknown at this point b/c of the loop
1799*67e74705SXin Li a = 10; // expected-warning {{writing variable 'a' requires holding mutex 'mu' exclusively}}
1800*67e74705SXin Li }
1801*67e74705SXin Li b = !b;
1802*67e74705SXin Li }
1803*67e74705SXin Li }
1804*67e74705SXin Li
1805*67e74705SXin Li // Test merge of exclusive trylock
foo11TryLockTest::TestTryLock1806*67e74705SXin Li void foo11() {
1807*67e74705SXin Li if (cond) {
1808*67e74705SXin Li if (!mu.TryLock())
1809*67e74705SXin Li return;
1810*67e74705SXin Li }
1811*67e74705SXin Li else {
1812*67e74705SXin Li mu.Lock();
1813*67e74705SXin Li }
1814*67e74705SXin Li a = 10;
1815*67e74705SXin Li mu.Unlock();
1816*67e74705SXin Li }
1817*67e74705SXin Li
1818*67e74705SXin Li // Test merge of shared trylock
foo12TryLockTest::TestTryLock1819*67e74705SXin Li void foo12() {
1820*67e74705SXin Li if (cond) {
1821*67e74705SXin Li if (!mu.ReaderTryLock())
1822*67e74705SXin Li return;
1823*67e74705SXin Li }
1824*67e74705SXin Li else {
1825*67e74705SXin Li mu.ReaderLock();
1826*67e74705SXin Li }
1827*67e74705SXin Li int i = a;
1828*67e74705SXin Li mu.Unlock();
1829*67e74705SXin Li }
1830*67e74705SXin Li }; // end TestTrylock
1831*67e74705SXin Li
1832*67e74705SXin Li } // end namespace TrylockTest
1833*67e74705SXin Li
1834*67e74705SXin Li
1835*67e74705SXin Li namespace TestTemplateAttributeInstantiation {
1836*67e74705SXin Li
1837*67e74705SXin Li class Foo1 {
1838*67e74705SXin Li public:
1839*67e74705SXin Li Mutex mu_;
1840*67e74705SXin Li int a GUARDED_BY(mu_);
1841*67e74705SXin Li };
1842*67e74705SXin Li
1843*67e74705SXin Li class Foo2 {
1844*67e74705SXin Li public:
1845*67e74705SXin Li int a GUARDED_BY(mu_);
1846*67e74705SXin Li Mutex mu_;
1847*67e74705SXin Li };
1848*67e74705SXin Li
1849*67e74705SXin Li
1850*67e74705SXin Li class Bar {
1851*67e74705SXin Li public:
1852*67e74705SXin Li // Test non-dependent expressions in attributes on template functions
1853*67e74705SXin Li template <class T>
barND(Foo1 * foo,T * fooT)1854*67e74705SXin Li void barND(Foo1 *foo, T *fooT) EXCLUSIVE_LOCKS_REQUIRED(foo->mu_) {
1855*67e74705SXin Li foo->a = 0;
1856*67e74705SXin Li }
1857*67e74705SXin Li
1858*67e74705SXin Li // Test dependent expressions in attributes on template functions
1859*67e74705SXin Li template <class T>
barD(Foo1 * foo,T * fooT)1860*67e74705SXin Li void barD(Foo1 *foo, T *fooT) EXCLUSIVE_LOCKS_REQUIRED(fooT->mu_) {
1861*67e74705SXin Li fooT->a = 0;
1862*67e74705SXin Li }
1863*67e74705SXin Li };
1864*67e74705SXin Li
1865*67e74705SXin Li
1866*67e74705SXin Li template <class T>
1867*67e74705SXin Li class BarT {
1868*67e74705SXin Li public:
1869*67e74705SXin Li Foo1 fooBase;
1870*67e74705SXin Li T fooBaseT;
1871*67e74705SXin Li
1872*67e74705SXin Li // Test non-dependent expression in ordinary method on template class
barND()1873*67e74705SXin Li void barND() EXCLUSIVE_LOCKS_REQUIRED(fooBase.mu_) {
1874*67e74705SXin Li fooBase.a = 0;
1875*67e74705SXin Li }
1876*67e74705SXin Li
1877*67e74705SXin Li // Test dependent expressions in ordinary methods on template class
barD()1878*67e74705SXin Li void barD() EXCLUSIVE_LOCKS_REQUIRED(fooBaseT.mu_) {
1879*67e74705SXin Li fooBaseT.a = 0;
1880*67e74705SXin Li }
1881*67e74705SXin Li
1882*67e74705SXin Li // Test dependent expressions in template method in template class
1883*67e74705SXin Li template <class T2>
barTD(T2 * fooT)1884*67e74705SXin Li void barTD(T2 *fooT) EXCLUSIVE_LOCKS_REQUIRED(fooBaseT.mu_, fooT->mu_) {
1885*67e74705SXin Li fooBaseT.a = 0;
1886*67e74705SXin Li fooT->a = 0;
1887*67e74705SXin Li }
1888*67e74705SXin Li };
1889*67e74705SXin Li
1890*67e74705SXin Li template <class T>
1891*67e74705SXin Li class Cell {
1892*67e74705SXin Li public:
1893*67e74705SXin Li Mutex mu_;
1894*67e74705SXin Li // Test dependent guarded_by
1895*67e74705SXin Li T data GUARDED_BY(mu_);
1896*67e74705SXin Li
fooEx()1897*67e74705SXin Li void fooEx() EXCLUSIVE_LOCKS_REQUIRED(mu_) {
1898*67e74705SXin Li data = 0;
1899*67e74705SXin Li }
1900*67e74705SXin Li
foo()1901*67e74705SXin Li void foo() {
1902*67e74705SXin Li mu_.Lock();
1903*67e74705SXin Li data = 0;
1904*67e74705SXin Li mu_.Unlock();
1905*67e74705SXin Li }
1906*67e74705SXin Li };
1907*67e74705SXin Li
test()1908*67e74705SXin Li void test() {
1909*67e74705SXin Li Bar b;
1910*67e74705SXin Li BarT<Foo2> bt;
1911*67e74705SXin Li Foo1 f1;
1912*67e74705SXin Li Foo2 f2;
1913*67e74705SXin Li
1914*67e74705SXin Li f1.mu_.Lock();
1915*67e74705SXin Li f2.mu_.Lock();
1916*67e74705SXin Li bt.fooBase.mu_.Lock();
1917*67e74705SXin Li bt.fooBaseT.mu_.Lock();
1918*67e74705SXin Li
1919*67e74705SXin Li b.barND(&f1, &f2);
1920*67e74705SXin Li b.barD(&f1, &f2);
1921*67e74705SXin Li bt.barND();
1922*67e74705SXin Li bt.barD();
1923*67e74705SXin Li bt.barTD(&f2);
1924*67e74705SXin Li
1925*67e74705SXin Li f1.mu_.Unlock();
1926*67e74705SXin Li bt.barTD(&f1); // \
1927*67e74705SXin Li // expected-warning {{calling function 'barTD' requires holding mutex 'f1.mu_' exclusively}} \
1928*67e74705SXin Li // expected-note {{found near match 'bt.fooBase.mu_'}}
1929*67e74705SXin Li
1930*67e74705SXin Li bt.fooBase.mu_.Unlock();
1931*67e74705SXin Li bt.fooBaseT.mu_.Unlock();
1932*67e74705SXin Li f2.mu_.Unlock();
1933*67e74705SXin Li
1934*67e74705SXin Li Cell<int> cell;
1935*67e74705SXin Li cell.data = 0; // \
1936*67e74705SXin Li // expected-warning {{writing variable 'data' requires holding mutex 'cell.mu_' exclusively}}
1937*67e74705SXin Li cell.foo();
1938*67e74705SXin Li cell.mu_.Lock();
1939*67e74705SXin Li cell.fooEx();
1940*67e74705SXin Li cell.mu_.Unlock();
1941*67e74705SXin Li }
1942*67e74705SXin Li
1943*67e74705SXin Li
1944*67e74705SXin Li template <class T>
1945*67e74705SXin Li class CellDelayed {
1946*67e74705SXin Li public:
1947*67e74705SXin Li // Test dependent guarded_by
1948*67e74705SXin Li T data GUARDED_BY(mu_);
1949*67e74705SXin Li static T static_data GUARDED_BY(static_mu_);
1950*67e74705SXin Li
fooEx(CellDelayed<T> * other)1951*67e74705SXin Li void fooEx(CellDelayed<T> *other) EXCLUSIVE_LOCKS_REQUIRED(mu_, other->mu_) {
1952*67e74705SXin Li this->data = other->data;
1953*67e74705SXin Li }
1954*67e74705SXin Li
1955*67e74705SXin Li template <class T2>
fooExT(CellDelayed<T2> * otherT)1956*67e74705SXin Li void fooExT(CellDelayed<T2> *otherT) EXCLUSIVE_LOCKS_REQUIRED(mu_, otherT->mu_) {
1957*67e74705SXin Li this->data = otherT->data;
1958*67e74705SXin Li }
1959*67e74705SXin Li
foo()1960*67e74705SXin Li void foo() {
1961*67e74705SXin Li mu_.Lock();
1962*67e74705SXin Li data = 0;
1963*67e74705SXin Li mu_.Unlock();
1964*67e74705SXin Li }
1965*67e74705SXin Li
1966*67e74705SXin Li Mutex mu_;
1967*67e74705SXin Li static Mutex static_mu_;
1968*67e74705SXin Li };
1969*67e74705SXin Li
testDelayed()1970*67e74705SXin Li void testDelayed() {
1971*67e74705SXin Li CellDelayed<int> celld;
1972*67e74705SXin Li CellDelayed<int> celld2;
1973*67e74705SXin Li celld.foo();
1974*67e74705SXin Li celld.mu_.Lock();
1975*67e74705SXin Li celld2.mu_.Lock();
1976*67e74705SXin Li
1977*67e74705SXin Li celld.fooEx(&celld2);
1978*67e74705SXin Li celld.fooExT(&celld2);
1979*67e74705SXin Li
1980*67e74705SXin Li celld2.mu_.Unlock();
1981*67e74705SXin Li celld.mu_.Unlock();
1982*67e74705SXin Li }
1983*67e74705SXin Li
1984*67e74705SXin Li }; // end namespace TestTemplateAttributeInstantiation
1985*67e74705SXin Li
1986*67e74705SXin Li
1987*67e74705SXin Li namespace FunctionDeclDefTest {
1988*67e74705SXin Li
1989*67e74705SXin Li class Foo {
1990*67e74705SXin Li public:
1991*67e74705SXin Li Mutex mu_;
1992*67e74705SXin Li int a GUARDED_BY(mu_);
1993*67e74705SXin Li
1994*67e74705SXin Li virtual void foo1(Foo *f_declared) EXCLUSIVE_LOCKS_REQUIRED(f_declared->mu_);
1995*67e74705SXin Li };
1996*67e74705SXin Li
1997*67e74705SXin Li // EXCLUSIVE_LOCKS_REQUIRED should be applied, and rewritten to f_defined->mu_
foo1(Foo * f_defined)1998*67e74705SXin Li void Foo::foo1(Foo *f_defined) {
1999*67e74705SXin Li f_defined->a = 0;
2000*67e74705SXin Li };
2001*67e74705SXin Li
test()2002*67e74705SXin Li void test() {
2003*67e74705SXin Li Foo myfoo;
2004*67e74705SXin Li myfoo.foo1(&myfoo); // \
2005*67e74705SXin Li // expected-warning {{calling function 'foo1' requires holding mutex 'myfoo.mu_' exclusively}}
2006*67e74705SXin Li myfoo.mu_.Lock();
2007*67e74705SXin Li myfoo.foo1(&myfoo);
2008*67e74705SXin Li myfoo.mu_.Unlock();
2009*67e74705SXin Li }
2010*67e74705SXin Li
2011*67e74705SXin Li };
2012*67e74705SXin Li
2013*67e74705SXin Li namespace GoingNative {
2014*67e74705SXin Li
2015*67e74705SXin Li struct __attribute__((lockable)) mutex {
2016*67e74705SXin Li void lock() __attribute__((exclusive_lock_function));
2017*67e74705SXin Li void unlock() __attribute__((unlock_function));
2018*67e74705SXin Li // ...
2019*67e74705SXin Li };
2020*67e74705SXin Li bool foo();
2021*67e74705SXin Li bool bar();
2022*67e74705SXin Li mutex m;
test()2023*67e74705SXin Li void test() {
2024*67e74705SXin Li m.lock();
2025*67e74705SXin Li while (foo()) {
2026*67e74705SXin Li m.unlock();
2027*67e74705SXin Li // ...
2028*67e74705SXin Li if (bar()) {
2029*67e74705SXin Li // ...
2030*67e74705SXin Li if (foo())
2031*67e74705SXin Li continue; // expected-warning {{expecting mutex 'm' to be held at start of each loop}}
2032*67e74705SXin Li //...
2033*67e74705SXin Li }
2034*67e74705SXin Li // ...
2035*67e74705SXin Li m.lock(); // expected-note {{mutex acquired here}}
2036*67e74705SXin Li }
2037*67e74705SXin Li m.unlock();
2038*67e74705SXin Li }
2039*67e74705SXin Li
2040*67e74705SXin Li }
2041*67e74705SXin Li
2042*67e74705SXin Li
2043*67e74705SXin Li
2044*67e74705SXin Li namespace FunctionDefinitionTest {
2045*67e74705SXin Li
2046*67e74705SXin Li class Foo {
2047*67e74705SXin Li public:
2048*67e74705SXin Li void foo1();
2049*67e74705SXin Li void foo2();
2050*67e74705SXin Li void foo3(Foo *other);
2051*67e74705SXin Li
2052*67e74705SXin Li template<class T>
2053*67e74705SXin Li void fooT1(const T& dummy1);
2054*67e74705SXin Li
2055*67e74705SXin Li template<class T>
2056*67e74705SXin Li void fooT2(const T& dummy2) EXCLUSIVE_LOCKS_REQUIRED(mu_);
2057*67e74705SXin Li
2058*67e74705SXin Li Mutex mu_;
2059*67e74705SXin Li int a GUARDED_BY(mu_);
2060*67e74705SXin Li };
2061*67e74705SXin Li
2062*67e74705SXin Li template<class T>
2063*67e74705SXin Li class FooT {
2064*67e74705SXin Li public:
2065*67e74705SXin Li void foo();
2066*67e74705SXin Li
2067*67e74705SXin Li Mutex mu_;
2068*67e74705SXin Li T a GUARDED_BY(mu_);
2069*67e74705SXin Li };
2070*67e74705SXin Li
2071*67e74705SXin Li
foo1()2072*67e74705SXin Li void Foo::foo1() NO_THREAD_SAFETY_ANALYSIS {
2073*67e74705SXin Li a = 1;
2074*67e74705SXin Li }
2075*67e74705SXin Li
foo2()2076*67e74705SXin Li void Foo::foo2() EXCLUSIVE_LOCKS_REQUIRED(mu_) {
2077*67e74705SXin Li a = 2;
2078*67e74705SXin Li }
2079*67e74705SXin Li
foo3(Foo * other)2080*67e74705SXin Li void Foo::foo3(Foo *other) EXCLUSIVE_LOCKS_REQUIRED(other->mu_) {
2081*67e74705SXin Li other->a = 3;
2082*67e74705SXin Li }
2083*67e74705SXin Li
2084*67e74705SXin Li template<class T>
fooT1(const T & dummy1)2085*67e74705SXin Li void Foo::fooT1(const T& dummy1) EXCLUSIVE_LOCKS_REQUIRED(mu_) {
2086*67e74705SXin Li a = dummy1;
2087*67e74705SXin Li }
2088*67e74705SXin Li
2089*67e74705SXin Li /* TODO -- uncomment with template instantiation of attributes.
2090*67e74705SXin Li template<class T>
2091*67e74705SXin Li void Foo::fooT2(const T& dummy2) {
2092*67e74705SXin Li a = dummy2;
2093*67e74705SXin Li }
2094*67e74705SXin Li */
2095*67e74705SXin Li
fooF1(Foo * f)2096*67e74705SXin Li void fooF1(Foo *f) EXCLUSIVE_LOCKS_REQUIRED(f->mu_) {
2097*67e74705SXin Li f->a = 1;
2098*67e74705SXin Li }
2099*67e74705SXin Li
2100*67e74705SXin Li void fooF2(Foo *f);
fooF2(Foo * f)2101*67e74705SXin Li void fooF2(Foo *f) EXCLUSIVE_LOCKS_REQUIRED(f->mu_) {
2102*67e74705SXin Li f->a = 2;
2103*67e74705SXin Li }
2104*67e74705SXin Li
2105*67e74705SXin Li void fooF3(Foo *f) EXCLUSIVE_LOCKS_REQUIRED(f->mu_);
fooF3(Foo * f)2106*67e74705SXin Li void fooF3(Foo *f) {
2107*67e74705SXin Li f->a = 3;
2108*67e74705SXin Li }
2109*67e74705SXin Li
2110*67e74705SXin Li template<class T>
foo()2111*67e74705SXin Li void FooT<T>::foo() EXCLUSIVE_LOCKS_REQUIRED(mu_) {
2112*67e74705SXin Li a = 0;
2113*67e74705SXin Li }
2114*67e74705SXin Li
test()2115*67e74705SXin Li void test() {
2116*67e74705SXin Li int dummy = 0;
2117*67e74705SXin Li Foo myFoo;
2118*67e74705SXin Li
2119*67e74705SXin Li myFoo.foo2(); // \
2120*67e74705SXin Li // expected-warning {{calling function 'foo2' requires holding mutex 'myFoo.mu_' exclusively}}
2121*67e74705SXin Li myFoo.foo3(&myFoo); // \
2122*67e74705SXin Li // expected-warning {{calling function 'foo3' requires holding mutex 'myFoo.mu_' exclusively}}
2123*67e74705SXin Li myFoo.fooT1(dummy); // \
2124*67e74705SXin Li // expected-warning {{calling function 'fooT1' requires holding mutex 'myFoo.mu_' exclusively}}
2125*67e74705SXin Li
2126*67e74705SXin Li myFoo.fooT2(dummy); // \
2127*67e74705SXin Li // expected-warning {{calling function 'fooT2' requires holding mutex 'myFoo.mu_' exclusively}}
2128*67e74705SXin Li
2129*67e74705SXin Li fooF1(&myFoo); // \
2130*67e74705SXin Li // expected-warning {{calling function 'fooF1' requires holding mutex 'myFoo.mu_' exclusively}}
2131*67e74705SXin Li fooF2(&myFoo); // \
2132*67e74705SXin Li // expected-warning {{calling function 'fooF2' requires holding mutex 'myFoo.mu_' exclusively}}
2133*67e74705SXin Li fooF3(&myFoo); // \
2134*67e74705SXin Li // expected-warning {{calling function 'fooF3' requires holding mutex 'myFoo.mu_' exclusively}}
2135*67e74705SXin Li
2136*67e74705SXin Li myFoo.mu_.Lock();
2137*67e74705SXin Li myFoo.foo2();
2138*67e74705SXin Li myFoo.foo3(&myFoo);
2139*67e74705SXin Li myFoo.fooT1(dummy);
2140*67e74705SXin Li
2141*67e74705SXin Li myFoo.fooT2(dummy);
2142*67e74705SXin Li
2143*67e74705SXin Li fooF1(&myFoo);
2144*67e74705SXin Li fooF2(&myFoo);
2145*67e74705SXin Li fooF3(&myFoo);
2146*67e74705SXin Li myFoo.mu_.Unlock();
2147*67e74705SXin Li
2148*67e74705SXin Li FooT<int> myFooT;
2149*67e74705SXin Li myFooT.foo(); // \
2150*67e74705SXin Li // expected-warning {{calling function 'foo' requires holding mutex 'myFooT.mu_' exclusively}}
2151*67e74705SXin Li }
2152*67e74705SXin Li
2153*67e74705SXin Li } // end namespace FunctionDefinitionTest
2154*67e74705SXin Li
2155*67e74705SXin Li
2156*67e74705SXin Li namespace SelfLockingTest {
2157*67e74705SXin Li
2158*67e74705SXin Li class LOCKABLE MyLock {
2159*67e74705SXin Li public:
2160*67e74705SXin Li int foo GUARDED_BY(this);
2161*67e74705SXin Li
2162*67e74705SXin Li void lock() EXCLUSIVE_LOCK_FUNCTION();
2163*67e74705SXin Li void unlock() UNLOCK_FUNCTION();
2164*67e74705SXin Li
doSomething()2165*67e74705SXin Li void doSomething() {
2166*67e74705SXin Li this->lock(); // allow 'this' as a lock expression
2167*67e74705SXin Li foo = 0;
2168*67e74705SXin Li doSomethingElse();
2169*67e74705SXin Li this->unlock();
2170*67e74705SXin Li }
2171*67e74705SXin Li
doSomethingElse()2172*67e74705SXin Li void doSomethingElse() EXCLUSIVE_LOCKS_REQUIRED(this) {
2173*67e74705SXin Li foo = 1;
2174*67e74705SXin Li };
2175*67e74705SXin Li
test()2176*67e74705SXin Li void test() {
2177*67e74705SXin Li foo = 2; // \
2178*67e74705SXin Li // expected-warning {{writing variable 'foo' requires holding mutex 'this' exclusively}}
2179*67e74705SXin Li }
2180*67e74705SXin Li };
2181*67e74705SXin Li
2182*67e74705SXin Li
2183*67e74705SXin Li class LOCKABLE MyLock2 {
2184*67e74705SXin Li public:
2185*67e74705SXin Li Mutex mu_;
2186*67e74705SXin Li int foo GUARDED_BY(this);
2187*67e74705SXin Li
2188*67e74705SXin Li // don't check inside lock and unlock functions
lock()2189*67e74705SXin Li void lock() EXCLUSIVE_LOCK_FUNCTION() { mu_.Lock(); }
unlock()2190*67e74705SXin Li void unlock() UNLOCK_FUNCTION() { mu_.Unlock(); }
2191*67e74705SXin Li
2192*67e74705SXin Li // don't check inside constructors and destructors
MyLock2()2193*67e74705SXin Li MyLock2() { foo = 1; }
~MyLock2()2194*67e74705SXin Li ~MyLock2() { foo = 0; }
2195*67e74705SXin Li };
2196*67e74705SXin Li
2197*67e74705SXin Li
2198*67e74705SXin Li } // end namespace SelfLockingTest
2199*67e74705SXin Li
2200*67e74705SXin Li
2201*67e74705SXin Li namespace InvalidNonstatic {
2202*67e74705SXin Li
2203*67e74705SXin Li // Forward decl here causes bogus "invalid use of non-static data member"
2204*67e74705SXin Li // on reference to mutex_ in guarded_by attribute.
2205*67e74705SXin Li class Foo;
2206*67e74705SXin Li
2207*67e74705SXin Li class Foo {
2208*67e74705SXin Li Mutex* mutex_;
2209*67e74705SXin Li
2210*67e74705SXin Li int foo __attribute__((guarded_by(mutex_)));
2211*67e74705SXin Li };
2212*67e74705SXin Li
2213*67e74705SXin Li } // end namespace InvalidNonStatic
2214*67e74705SXin Li
2215*67e74705SXin Li
2216*67e74705SXin Li namespace NoReturnTest {
2217*67e74705SXin Li
2218*67e74705SXin Li bool condition();
2219*67e74705SXin Li void fatal() __attribute__((noreturn));
2220*67e74705SXin Li
2221*67e74705SXin Li Mutex mu_;
2222*67e74705SXin Li
test1()2223*67e74705SXin Li void test1() {
2224*67e74705SXin Li MutexLock lock(&mu_);
2225*67e74705SXin Li if (condition()) {
2226*67e74705SXin Li fatal();
2227*67e74705SXin Li return;
2228*67e74705SXin Li }
2229*67e74705SXin Li }
2230*67e74705SXin Li
2231*67e74705SXin Li } // end namespace NoReturnTest
2232*67e74705SXin Li
2233*67e74705SXin Li
2234*67e74705SXin Li namespace TestMultiDecl {
2235*67e74705SXin Li
2236*67e74705SXin Li class Foo {
2237*67e74705SXin Li public:
2238*67e74705SXin Li int GUARDED_BY(mu_) a;
2239*67e74705SXin Li int GUARDED_BY(mu_) b, c;
2240*67e74705SXin Li
foo()2241*67e74705SXin Li void foo() {
2242*67e74705SXin Li a = 0; // \
2243*67e74705SXin Li // expected-warning {{writing variable 'a' requires holding mutex 'mu_' exclusively}}
2244*67e74705SXin Li b = 0; // \
2245*67e74705SXin Li // expected-warning {{writing variable 'b' requires holding mutex 'mu_' exclusively}}
2246*67e74705SXin Li c = 0; // \
2247*67e74705SXin Li // expected-warning {{writing variable 'c' requires holding mutex 'mu_' exclusively}}
2248*67e74705SXin Li }
2249*67e74705SXin Li
2250*67e74705SXin Li private:
2251*67e74705SXin Li Mutex mu_;
2252*67e74705SXin Li };
2253*67e74705SXin Li
2254*67e74705SXin Li } // end namespace TestMultiDecl
2255*67e74705SXin Li
2256*67e74705SXin Li
2257*67e74705SXin Li namespace WarnNoDecl {
2258*67e74705SXin Li
2259*67e74705SXin Li class Foo {
2260*67e74705SXin Li void foo(int a); __attribute__(( // \
2261*67e74705SXin Li // expected-warning {{declaration does not declare anything}}
2262*67e74705SXin Li exclusive_locks_required(a))); // \
2263*67e74705SXin Li // expected-warning {{attribute exclusive_locks_required ignored}}
2264*67e74705SXin Li };
2265*67e74705SXin Li
2266*67e74705SXin Li } // end namespace WarnNoDecl
2267*67e74705SXin Li
2268*67e74705SXin Li
2269*67e74705SXin Li
2270*67e74705SXin Li namespace MoreLockExpressions {
2271*67e74705SXin Li
2272*67e74705SXin Li class Foo {
2273*67e74705SXin Li public:
2274*67e74705SXin Li Mutex mu_;
2275*67e74705SXin Li int a GUARDED_BY(mu_);
2276*67e74705SXin Li };
2277*67e74705SXin Li
2278*67e74705SXin Li class Bar {
2279*67e74705SXin Li public:
2280*67e74705SXin Li int b;
2281*67e74705SXin Li Foo* f;
2282*67e74705SXin Li
getFoo()2283*67e74705SXin Li Foo& getFoo() { return *f; }
getFoo2(int c)2284*67e74705SXin Li Foo& getFoo2(int c) { return *f; }
getFoo3(int c,int d)2285*67e74705SXin Li Foo& getFoo3(int c, int d) { return *f; }
2286*67e74705SXin Li
getFooey()2287*67e74705SXin Li Foo& getFooey() { return *f; }
2288*67e74705SXin Li };
2289*67e74705SXin Li
getBarFoo(Bar & bar,int c)2290*67e74705SXin Li Foo& getBarFoo(Bar &bar, int c) { return bar.getFoo2(c); }
2291*67e74705SXin Li
test()2292*67e74705SXin Li void test() {
2293*67e74705SXin Li Foo foo;
2294*67e74705SXin Li Foo *fooArray;
2295*67e74705SXin Li Bar bar;
2296*67e74705SXin Li int a;
2297*67e74705SXin Li int b;
2298*67e74705SXin Li int c;
2299*67e74705SXin Li
2300*67e74705SXin Li bar.getFoo().mu_.Lock();
2301*67e74705SXin Li bar.getFoo().a = 0;
2302*67e74705SXin Li bar.getFoo().mu_.Unlock();
2303*67e74705SXin Li
2304*67e74705SXin Li (bar.getFoo().mu_).Lock(); // test parenthesis
2305*67e74705SXin Li bar.getFoo().a = 0;
2306*67e74705SXin Li (bar.getFoo().mu_).Unlock();
2307*67e74705SXin Li
2308*67e74705SXin Li bar.getFoo2(a).mu_.Lock();
2309*67e74705SXin Li bar.getFoo2(a).a = 0;
2310*67e74705SXin Li bar.getFoo2(a).mu_.Unlock();
2311*67e74705SXin Li
2312*67e74705SXin Li bar.getFoo3(a, b).mu_.Lock();
2313*67e74705SXin Li bar.getFoo3(a, b).a = 0;
2314*67e74705SXin Li bar.getFoo3(a, b).mu_.Unlock();
2315*67e74705SXin Li
2316*67e74705SXin Li getBarFoo(bar, a).mu_.Lock();
2317*67e74705SXin Li getBarFoo(bar, a).a = 0;
2318*67e74705SXin Li getBarFoo(bar, a).mu_.Unlock();
2319*67e74705SXin Li
2320*67e74705SXin Li bar.getFoo2(10).mu_.Lock();
2321*67e74705SXin Li bar.getFoo2(10).a = 0;
2322*67e74705SXin Li bar.getFoo2(10).mu_.Unlock();
2323*67e74705SXin Li
2324*67e74705SXin Li bar.getFoo2(a + 1).mu_.Lock();
2325*67e74705SXin Li bar.getFoo2(a + 1).a = 0;
2326*67e74705SXin Li bar.getFoo2(a + 1).mu_.Unlock();
2327*67e74705SXin Li
2328*67e74705SXin Li (a > 0 ? fooArray[1] : fooArray[b]).mu_.Lock();
2329*67e74705SXin Li (a > 0 ? fooArray[1] : fooArray[b]).a = 0;
2330*67e74705SXin Li (a > 0 ? fooArray[1] : fooArray[b]).mu_.Unlock();
2331*67e74705SXin Li }
2332*67e74705SXin Li
2333*67e74705SXin Li
test2()2334*67e74705SXin Li void test2() {
2335*67e74705SXin Li Foo *fooArray;
2336*67e74705SXin Li Bar bar;
2337*67e74705SXin Li int a;
2338*67e74705SXin Li int b;
2339*67e74705SXin Li int c;
2340*67e74705SXin Li
2341*67e74705SXin Li bar.getFoo().mu_.Lock();
2342*67e74705SXin Li bar.getFooey().a = 0; // \
2343*67e74705SXin Li // expected-warning {{writing variable 'a' requires holding mutex 'bar.getFooey().mu_' exclusively}} \
2344*67e74705SXin Li // expected-note {{found near match 'bar.getFoo().mu_'}}
2345*67e74705SXin Li bar.getFoo().mu_.Unlock();
2346*67e74705SXin Li
2347*67e74705SXin Li bar.getFoo2(a).mu_.Lock();
2348*67e74705SXin Li bar.getFoo2(b).a = 0; // \
2349*67e74705SXin Li // expected-warning {{writing variable 'a' requires holding mutex 'bar.getFoo2(b).mu_' exclusively}} \
2350*67e74705SXin Li // expected-note {{found near match 'bar.getFoo2(a).mu_'}}
2351*67e74705SXin Li bar.getFoo2(a).mu_.Unlock();
2352*67e74705SXin Li
2353*67e74705SXin Li bar.getFoo3(a, b).mu_.Lock();
2354*67e74705SXin Li bar.getFoo3(a, c).a = 0; // \
2355*67e74705SXin Li // expected-warning {{writing variable 'a' requires holding mutex 'bar.getFoo3(a, c).mu_' exclusively}} \
2356*67e74705SXin Li // expected-note {{found near match 'bar.getFoo3(a, b).mu_'}}
2357*67e74705SXin Li bar.getFoo3(a, b).mu_.Unlock();
2358*67e74705SXin Li
2359*67e74705SXin Li getBarFoo(bar, a).mu_.Lock();
2360*67e74705SXin Li getBarFoo(bar, b).a = 0; // \
2361*67e74705SXin Li // expected-warning {{writing variable 'a' requires holding mutex 'getBarFoo(bar, b).mu_' exclusively}} \
2362*67e74705SXin Li // expected-note {{found near match 'getBarFoo(bar, a).mu_'}}
2363*67e74705SXin Li getBarFoo(bar, a).mu_.Unlock();
2364*67e74705SXin Li
2365*67e74705SXin Li (a > 0 ? fooArray[1] : fooArray[b]).mu_.Lock();
2366*67e74705SXin Li (a > 0 ? fooArray[b] : fooArray[c]).a = 0; // \
2367*67e74705SXin Li // expected-warning {{writing variable 'a' requires holding mutex '((0 < a) ? fooArray[b] : fooArray[c]).mu_' exclusively}} \
2368*67e74705SXin Li // expected-note {{found near match '((0 < a) ? fooArray[1] : fooArray[b]).mu_'}}
2369*67e74705SXin Li (a > 0 ? fooArray[1] : fooArray[b]).mu_.Unlock();
2370*67e74705SXin Li }
2371*67e74705SXin Li
2372*67e74705SXin Li
2373*67e74705SXin Li } // end namespace MoreLockExpressions
2374*67e74705SXin Li
2375*67e74705SXin Li
2376*67e74705SXin Li namespace TrylockJoinPoint {
2377*67e74705SXin Li
2378*67e74705SXin Li class Foo {
2379*67e74705SXin Li Mutex mu;
2380*67e74705SXin Li bool c;
2381*67e74705SXin Li
foo()2382*67e74705SXin Li void foo() {
2383*67e74705SXin Li if (c) {
2384*67e74705SXin Li if (!mu.TryLock())
2385*67e74705SXin Li return;
2386*67e74705SXin Li } else {
2387*67e74705SXin Li mu.Lock();
2388*67e74705SXin Li }
2389*67e74705SXin Li mu.Unlock();
2390*67e74705SXin Li }
2391*67e74705SXin Li };
2392*67e74705SXin Li
2393*67e74705SXin Li } // end namespace TrylockJoinPoint
2394*67e74705SXin Li
2395*67e74705SXin Li
2396*67e74705SXin Li namespace LockReturned {
2397*67e74705SXin Li
2398*67e74705SXin Li class Foo {
2399*67e74705SXin Li public:
2400*67e74705SXin Li int a GUARDED_BY(mu_);
2401*67e74705SXin Li void foo() EXCLUSIVE_LOCKS_REQUIRED(mu_);
2402*67e74705SXin Li void foo2(Foo* f) EXCLUSIVE_LOCKS_REQUIRED(mu_, f->mu_);
2403*67e74705SXin Li
2404*67e74705SXin Li static void sfoo(Foo* f) EXCLUSIVE_LOCKS_REQUIRED(f->mu_);
2405*67e74705SXin Li
2406*67e74705SXin Li Mutex* getMu() LOCK_RETURNED(mu_);
2407*67e74705SXin Li
2408*67e74705SXin Li Mutex mu_;
2409*67e74705SXin Li
2410*67e74705SXin Li static Mutex* getMu(Foo* f) LOCK_RETURNED(f->mu_);
2411*67e74705SXin Li };
2412*67e74705SXin Li
2413*67e74705SXin Li
2414*67e74705SXin Li // Calls getMu() directly to lock and unlock
test1(Foo * f1,Foo * f2)2415*67e74705SXin Li void test1(Foo* f1, Foo* f2) {
2416*67e74705SXin Li f1->a = 0; // expected-warning {{writing variable 'a' requires holding mutex 'f1->mu_' exclusively}}
2417*67e74705SXin Li f1->foo(); // expected-warning {{calling function 'foo' requires holding mutex 'f1->mu_' exclusively}}
2418*67e74705SXin Li
2419*67e74705SXin Li f1->foo2(f2); // expected-warning {{calling function 'foo2' requires holding mutex 'f1->mu_' exclusively}} \
2420*67e74705SXin Li // expected-warning {{calling function 'foo2' requires holding mutex 'f2->mu_' exclusively}}
2421*67e74705SXin Li Foo::sfoo(f1); // expected-warning {{calling function 'sfoo' requires holding mutex 'f1->mu_' exclusively}}
2422*67e74705SXin Li
2423*67e74705SXin Li f1->getMu()->Lock();
2424*67e74705SXin Li
2425*67e74705SXin Li f1->a = 0;
2426*67e74705SXin Li f1->foo();
2427*67e74705SXin Li f1->foo2(f2); // \
2428*67e74705SXin Li // expected-warning {{calling function 'foo2' requires holding mutex 'f2->mu_' exclusively}} \
2429*67e74705SXin Li // expected-note {{found near match 'f1->mu_'}}
2430*67e74705SXin Li
2431*67e74705SXin Li Foo::getMu(f2)->Lock();
2432*67e74705SXin Li f1->foo2(f2);
2433*67e74705SXin Li Foo::getMu(f2)->Unlock();
2434*67e74705SXin Li
2435*67e74705SXin Li Foo::sfoo(f1);
2436*67e74705SXin Li
2437*67e74705SXin Li f1->getMu()->Unlock();
2438*67e74705SXin Li }
2439*67e74705SXin Li
2440*67e74705SXin Li
2441*67e74705SXin Li Mutex* getFooMu(Foo* f) LOCK_RETURNED(Foo::getMu(f));
2442*67e74705SXin Li
2443*67e74705SXin Li class Bar : public Foo {
2444*67e74705SXin Li public:
2445*67e74705SXin Li int b GUARDED_BY(getMu());
2446*67e74705SXin Li void bar() EXCLUSIVE_LOCKS_REQUIRED(getMu());
2447*67e74705SXin Li void bar2(Bar* g) EXCLUSIVE_LOCKS_REQUIRED(getMu(this), g->getMu());
2448*67e74705SXin Li
2449*67e74705SXin Li static void sbar(Bar* g) EXCLUSIVE_LOCKS_REQUIRED(g->getMu());
2450*67e74705SXin Li static void sbar2(Bar* g) EXCLUSIVE_LOCKS_REQUIRED(getFooMu(g));
2451*67e74705SXin Li };
2452*67e74705SXin Li
2453*67e74705SXin Li
2454*67e74705SXin Li
2455*67e74705SXin Li // Use getMu() within other attributes.
2456*67e74705SXin Li // This requires at lest levels of substitution, more in the case of
test2(Bar * b1,Bar * b2)2457*67e74705SXin Li void test2(Bar* b1, Bar* b2) {
2458*67e74705SXin Li b1->b = 0; // expected-warning {{writing variable 'b' requires holding mutex 'b1->mu_' exclusively}}
2459*67e74705SXin Li b1->bar(); // expected-warning {{calling function 'bar' requires holding mutex 'b1->mu_' exclusively}}
2460*67e74705SXin Li b1->bar2(b2); // expected-warning {{calling function 'bar2' requires holding mutex 'b1->mu_' exclusively}} \
2461*67e74705SXin Li // expected-warning {{calling function 'bar2' requires holding mutex 'b2->mu_' exclusively}}
2462*67e74705SXin Li Bar::sbar(b1); // expected-warning {{calling function 'sbar' requires holding mutex 'b1->mu_' exclusively}}
2463*67e74705SXin Li Bar::sbar2(b1); // expected-warning {{calling function 'sbar2' requires holding mutex 'b1->mu_' exclusively}}
2464*67e74705SXin Li
2465*67e74705SXin Li b1->getMu()->Lock();
2466*67e74705SXin Li
2467*67e74705SXin Li b1->b = 0;
2468*67e74705SXin Li b1->bar();
2469*67e74705SXin Li b1->bar2(b2); // \
2470*67e74705SXin Li // expected-warning {{calling function 'bar2' requires holding mutex 'b2->mu_' exclusively}} \
2471*67e74705SXin Li // // expected-note {{found near match 'b1->mu_'}}
2472*67e74705SXin Li
2473*67e74705SXin Li b2->getMu()->Lock();
2474*67e74705SXin Li b1->bar2(b2);
2475*67e74705SXin Li
2476*67e74705SXin Li b2->getMu()->Unlock();
2477*67e74705SXin Li
2478*67e74705SXin Li Bar::sbar(b1);
2479*67e74705SXin Li Bar::sbar2(b1);
2480*67e74705SXin Li
2481*67e74705SXin Li b1->getMu()->Unlock();
2482*67e74705SXin Li }
2483*67e74705SXin Li
2484*67e74705SXin Li
2485*67e74705SXin Li // Sanity check -- lock the mutex directly, but use attributes that call getMu()
2486*67e74705SXin Li // Also lock the mutex using getFooMu, which calls a lock_returned function.
test3(Bar * b1,Bar * b2)2487*67e74705SXin Li void test3(Bar* b1, Bar* b2) {
2488*67e74705SXin Li b1->mu_.Lock();
2489*67e74705SXin Li b1->b = 0;
2490*67e74705SXin Li b1->bar();
2491*67e74705SXin Li
2492*67e74705SXin Li getFooMu(b2)->Lock();
2493*67e74705SXin Li b1->bar2(b2);
2494*67e74705SXin Li getFooMu(b2)->Unlock();
2495*67e74705SXin Li
2496*67e74705SXin Li Bar::sbar(b1);
2497*67e74705SXin Li Bar::sbar2(b1);
2498*67e74705SXin Li
2499*67e74705SXin Li b1->mu_.Unlock();
2500*67e74705SXin Li }
2501*67e74705SXin Li
2502*67e74705SXin Li } // end namespace LockReturned
2503*67e74705SXin Li
2504*67e74705SXin Li
2505*67e74705SXin Li namespace ReleasableScopedLock {
2506*67e74705SXin Li
2507*67e74705SXin Li class Foo {
2508*67e74705SXin Li Mutex mu_;
2509*67e74705SXin Li bool c;
2510*67e74705SXin Li int a GUARDED_BY(mu_);
2511*67e74705SXin Li
2512*67e74705SXin Li void test1();
2513*67e74705SXin Li void test2();
2514*67e74705SXin Li void test3();
2515*67e74705SXin Li void test4();
2516*67e74705SXin Li void test5();
2517*67e74705SXin Li };
2518*67e74705SXin Li
2519*67e74705SXin Li
test1()2520*67e74705SXin Li void Foo::test1() {
2521*67e74705SXin Li ReleasableMutexLock rlock(&mu_);
2522*67e74705SXin Li rlock.Release();
2523*67e74705SXin Li }
2524*67e74705SXin Li
test2()2525*67e74705SXin Li void Foo::test2() {
2526*67e74705SXin Li ReleasableMutexLock rlock(&mu_);
2527*67e74705SXin Li if (c) { // test join point -- held/not held during release
2528*67e74705SXin Li rlock.Release();
2529*67e74705SXin Li }
2530*67e74705SXin Li }
2531*67e74705SXin Li
test3()2532*67e74705SXin Li void Foo::test3() {
2533*67e74705SXin Li ReleasableMutexLock rlock(&mu_);
2534*67e74705SXin Li a = 0;
2535*67e74705SXin Li rlock.Release();
2536*67e74705SXin Li a = 1; // expected-warning {{writing variable 'a' requires holding mutex 'mu_' exclusively}}
2537*67e74705SXin Li }
2538*67e74705SXin Li
test4()2539*67e74705SXin Li void Foo::test4() {
2540*67e74705SXin Li ReleasableMutexLock rlock(&mu_);
2541*67e74705SXin Li rlock.Release();
2542*67e74705SXin Li rlock.Release(); // expected-warning {{releasing mutex 'mu_' that was not held}}
2543*67e74705SXin Li }
2544*67e74705SXin Li
test5()2545*67e74705SXin Li void Foo::test5() {
2546*67e74705SXin Li ReleasableMutexLock rlock(&mu_);
2547*67e74705SXin Li if (c) {
2548*67e74705SXin Li rlock.Release();
2549*67e74705SXin Li }
2550*67e74705SXin Li // no warning on join point for managed lock.
2551*67e74705SXin Li rlock.Release(); // expected-warning {{releasing mutex 'mu_' that was not held}}
2552*67e74705SXin Li }
2553*67e74705SXin Li
2554*67e74705SXin Li
2555*67e74705SXin Li } // end namespace ReleasableScopedLock
2556*67e74705SXin Li
2557*67e74705SXin Li
2558*67e74705SXin Li namespace TrylockFunctionTest {
2559*67e74705SXin Li
2560*67e74705SXin Li class Foo {
2561*67e74705SXin Li public:
2562*67e74705SXin Li Mutex mu1_;
2563*67e74705SXin Li Mutex mu2_;
2564*67e74705SXin Li bool c;
2565*67e74705SXin Li
2566*67e74705SXin Li bool lockBoth() EXCLUSIVE_TRYLOCK_FUNCTION(true, mu1_, mu2_);
2567*67e74705SXin Li };
2568*67e74705SXin Li
lockBoth()2569*67e74705SXin Li bool Foo::lockBoth() {
2570*67e74705SXin Li if (!mu1_.TryLock())
2571*67e74705SXin Li return false;
2572*67e74705SXin Li
2573*67e74705SXin Li mu2_.Lock();
2574*67e74705SXin Li if (!c) {
2575*67e74705SXin Li mu1_.Unlock();
2576*67e74705SXin Li mu2_.Unlock();
2577*67e74705SXin Li return false;
2578*67e74705SXin Li }
2579*67e74705SXin Li
2580*67e74705SXin Li return true;
2581*67e74705SXin Li }
2582*67e74705SXin Li
2583*67e74705SXin Li
2584*67e74705SXin Li } // end namespace TrylockFunctionTest
2585*67e74705SXin Li
2586*67e74705SXin Li
2587*67e74705SXin Li
2588*67e74705SXin Li namespace DoubleLockBug {
2589*67e74705SXin Li
2590*67e74705SXin Li class Foo {
2591*67e74705SXin Li public:
2592*67e74705SXin Li Mutex mu_;
2593*67e74705SXin Li int a GUARDED_BY(mu_);
2594*67e74705SXin Li
2595*67e74705SXin Li void foo1() EXCLUSIVE_LOCKS_REQUIRED(mu_);
2596*67e74705SXin Li int foo2() SHARED_LOCKS_REQUIRED(mu_);
2597*67e74705SXin Li };
2598*67e74705SXin Li
2599*67e74705SXin Li
foo1()2600*67e74705SXin Li void Foo::foo1() EXCLUSIVE_LOCKS_REQUIRED(mu_) {
2601*67e74705SXin Li a = 0;
2602*67e74705SXin Li }
2603*67e74705SXin Li
foo2()2604*67e74705SXin Li int Foo::foo2() SHARED_LOCKS_REQUIRED(mu_) {
2605*67e74705SXin Li return a;
2606*67e74705SXin Li }
2607*67e74705SXin Li
2608*67e74705SXin Li }
2609*67e74705SXin Li
2610*67e74705SXin Li
2611*67e74705SXin Li
2612*67e74705SXin Li namespace UnlockBug {
2613*67e74705SXin Li
2614*67e74705SXin Li class Foo {
2615*67e74705SXin Li public:
2616*67e74705SXin Li Mutex mutex_;
2617*67e74705SXin Li
foo1()2618*67e74705SXin Li void foo1() EXCLUSIVE_LOCKS_REQUIRED(mutex_) { // expected-note {{mutex acquired here}}
2619*67e74705SXin Li mutex_.Unlock();
2620*67e74705SXin Li } // expected-warning {{expecting mutex 'mutex_' to be held at the end of function}}
2621*67e74705SXin Li
2622*67e74705SXin Li
foo2()2623*67e74705SXin Li void foo2() SHARED_LOCKS_REQUIRED(mutex_) { // expected-note {{mutex acquired here}}
2624*67e74705SXin Li mutex_.Unlock();
2625*67e74705SXin Li } // expected-warning {{expecting mutex 'mutex_' to be held at the end of function}}
2626*67e74705SXin Li };
2627*67e74705SXin Li
2628*67e74705SXin Li } // end namespace UnlockBug
2629*67e74705SXin Li
2630*67e74705SXin Li
2631*67e74705SXin Li
2632*67e74705SXin Li namespace FoolishScopedLockableBug {
2633*67e74705SXin Li
2634*67e74705SXin Li class SCOPED_LOCKABLE WTF_ScopedLockable {
2635*67e74705SXin Li public:
2636*67e74705SXin Li WTF_ScopedLockable(Mutex* mu) EXCLUSIVE_LOCK_FUNCTION(mu);
2637*67e74705SXin Li
2638*67e74705SXin Li // have to call release() manually;
2639*67e74705SXin Li ~WTF_ScopedLockable();
2640*67e74705SXin Li
2641*67e74705SXin Li void release() UNLOCK_FUNCTION();
2642*67e74705SXin Li };
2643*67e74705SXin Li
2644*67e74705SXin Li
2645*67e74705SXin Li class Foo {
2646*67e74705SXin Li Mutex mu_;
2647*67e74705SXin Li int a GUARDED_BY(mu_);
2648*67e74705SXin Li bool c;
2649*67e74705SXin Li
2650*67e74705SXin Li void doSomething();
2651*67e74705SXin Li
test1()2652*67e74705SXin Li void test1() {
2653*67e74705SXin Li WTF_ScopedLockable wtf(&mu_);
2654*67e74705SXin Li wtf.release();
2655*67e74705SXin Li }
2656*67e74705SXin Li
test2()2657*67e74705SXin Li void test2() {
2658*67e74705SXin Li WTF_ScopedLockable wtf(&mu_); // expected-note {{mutex acquired here}}
2659*67e74705SXin Li } // expected-warning {{mutex 'mu_' is still held at the end of function}}
2660*67e74705SXin Li
test3()2661*67e74705SXin Li void test3() {
2662*67e74705SXin Li if (c) {
2663*67e74705SXin Li WTF_ScopedLockable wtf(&mu_);
2664*67e74705SXin Li wtf.release();
2665*67e74705SXin Li }
2666*67e74705SXin Li }
2667*67e74705SXin Li
test4()2668*67e74705SXin Li void test4() {
2669*67e74705SXin Li if (c) {
2670*67e74705SXin Li doSomething();
2671*67e74705SXin Li }
2672*67e74705SXin Li else {
2673*67e74705SXin Li WTF_ScopedLockable wtf(&mu_);
2674*67e74705SXin Li wtf.release();
2675*67e74705SXin Li }
2676*67e74705SXin Li }
2677*67e74705SXin Li
test5()2678*67e74705SXin Li void test5() {
2679*67e74705SXin Li if (c) {
2680*67e74705SXin Li WTF_ScopedLockable wtf(&mu_); // expected-note {{mutex acquired here}}
2681*67e74705SXin Li }
2682*67e74705SXin Li } // expected-warning {{mutex 'mu_' is not held on every path through here}}
2683*67e74705SXin Li
test6()2684*67e74705SXin Li void test6() {
2685*67e74705SXin Li if (c) {
2686*67e74705SXin Li doSomething();
2687*67e74705SXin Li }
2688*67e74705SXin Li else {
2689*67e74705SXin Li WTF_ScopedLockable wtf(&mu_); // expected-note {{mutex acquired here}}
2690*67e74705SXin Li }
2691*67e74705SXin Li } // expected-warning {{mutex 'mu_' is not held on every path through here}}
2692*67e74705SXin Li };
2693*67e74705SXin Li
2694*67e74705SXin Li
2695*67e74705SXin Li } // end namespace FoolishScopedLockableBug
2696*67e74705SXin Li
2697*67e74705SXin Li
2698*67e74705SXin Li
2699*67e74705SXin Li namespace TemporaryCleanupExpr {
2700*67e74705SXin Li
2701*67e74705SXin Li class Foo {
2702*67e74705SXin Li int a GUARDED_BY(getMutexPtr().get());
2703*67e74705SXin Li
2704*67e74705SXin Li SmartPtr<Mutex> getMutexPtr();
2705*67e74705SXin Li
2706*67e74705SXin Li void test();
2707*67e74705SXin Li };
2708*67e74705SXin Li
2709*67e74705SXin Li
test()2710*67e74705SXin Li void Foo::test() {
2711*67e74705SXin Li {
2712*67e74705SXin Li ReaderMutexLock lock(getMutexPtr().get());
2713*67e74705SXin Li int b = a;
2714*67e74705SXin Li }
2715*67e74705SXin Li int b = a; // expected-warning {{reading variable 'a' requires holding mutex 'getMutexPtr()'}}
2716*67e74705SXin Li }
2717*67e74705SXin Li
2718*67e74705SXin Li } // end namespace TemporaryCleanupExpr
2719*67e74705SXin Li
2720*67e74705SXin Li
2721*67e74705SXin Li
2722*67e74705SXin Li namespace SmartPointerTests {
2723*67e74705SXin Li
2724*67e74705SXin Li class Foo {
2725*67e74705SXin Li public:
2726*67e74705SXin Li SmartPtr<Mutex> mu_;
2727*67e74705SXin Li int a GUARDED_BY(mu_);
2728*67e74705SXin Li int b GUARDED_BY(mu_.get());
2729*67e74705SXin Li int c GUARDED_BY(*mu_);
2730*67e74705SXin Li
2731*67e74705SXin Li void Lock() EXCLUSIVE_LOCK_FUNCTION(mu_);
2732*67e74705SXin Li void Unlock() UNLOCK_FUNCTION(mu_);
2733*67e74705SXin Li
2734*67e74705SXin Li void test0();
2735*67e74705SXin Li void test1();
2736*67e74705SXin Li void test2();
2737*67e74705SXin Li void test3();
2738*67e74705SXin Li void test4();
2739*67e74705SXin Li void test5();
2740*67e74705SXin Li void test6();
2741*67e74705SXin Li void test7();
2742*67e74705SXin Li void test8();
2743*67e74705SXin Li };
2744*67e74705SXin Li
test0()2745*67e74705SXin Li void Foo::test0() {
2746*67e74705SXin Li a = 0; // expected-warning {{writing variable 'a' requires holding mutex 'mu_' exclusively}}
2747*67e74705SXin Li b = 0; // expected-warning {{writing variable 'b' requires holding mutex 'mu_' exclusively}}
2748*67e74705SXin Li c = 0; // expected-warning {{writing variable 'c' requires holding mutex 'mu_' exclusively}}
2749*67e74705SXin Li }
2750*67e74705SXin Li
test1()2751*67e74705SXin Li void Foo::test1() {
2752*67e74705SXin Li mu_->Lock();
2753*67e74705SXin Li a = 0;
2754*67e74705SXin Li b = 0;
2755*67e74705SXin Li c = 0;
2756*67e74705SXin Li mu_->Unlock();
2757*67e74705SXin Li }
2758*67e74705SXin Li
test2()2759*67e74705SXin Li void Foo::test2() {
2760*67e74705SXin Li (*mu_).Lock();
2761*67e74705SXin Li a = 0;
2762*67e74705SXin Li b = 0;
2763*67e74705SXin Li c = 0;
2764*67e74705SXin Li (*mu_).Unlock();
2765*67e74705SXin Li }
2766*67e74705SXin Li
2767*67e74705SXin Li
test3()2768*67e74705SXin Li void Foo::test3() {
2769*67e74705SXin Li mu_.get()->Lock();
2770*67e74705SXin Li a = 0;
2771*67e74705SXin Li b = 0;
2772*67e74705SXin Li c = 0;
2773*67e74705SXin Li mu_.get()->Unlock();
2774*67e74705SXin Li }
2775*67e74705SXin Li
2776*67e74705SXin Li
test4()2777*67e74705SXin Li void Foo::test4() {
2778*67e74705SXin Li MutexLock lock(mu_.get());
2779*67e74705SXin Li a = 0;
2780*67e74705SXin Li b = 0;
2781*67e74705SXin Li c = 0;
2782*67e74705SXin Li }
2783*67e74705SXin Li
2784*67e74705SXin Li
test5()2785*67e74705SXin Li void Foo::test5() {
2786*67e74705SXin Li MutexLock lock(&(*mu_));
2787*67e74705SXin Li a = 0;
2788*67e74705SXin Li b = 0;
2789*67e74705SXin Li c = 0;
2790*67e74705SXin Li }
2791*67e74705SXin Li
2792*67e74705SXin Li
test6()2793*67e74705SXin Li void Foo::test6() {
2794*67e74705SXin Li Lock();
2795*67e74705SXin Li a = 0;
2796*67e74705SXin Li b = 0;
2797*67e74705SXin Li c = 0;
2798*67e74705SXin Li Unlock();
2799*67e74705SXin Li }
2800*67e74705SXin Li
2801*67e74705SXin Li
test7()2802*67e74705SXin Li void Foo::test7() {
2803*67e74705SXin Li {
2804*67e74705SXin Li Lock();
2805*67e74705SXin Li mu_->Unlock();
2806*67e74705SXin Li }
2807*67e74705SXin Li {
2808*67e74705SXin Li mu_->Lock();
2809*67e74705SXin Li Unlock();
2810*67e74705SXin Li }
2811*67e74705SXin Li {
2812*67e74705SXin Li mu_.get()->Lock();
2813*67e74705SXin Li mu_->Unlock();
2814*67e74705SXin Li }
2815*67e74705SXin Li {
2816*67e74705SXin Li mu_->Lock();
2817*67e74705SXin Li mu_.get()->Unlock();
2818*67e74705SXin Li }
2819*67e74705SXin Li {
2820*67e74705SXin Li mu_.get()->Lock();
2821*67e74705SXin Li (*mu_).Unlock();
2822*67e74705SXin Li }
2823*67e74705SXin Li {
2824*67e74705SXin Li (*mu_).Lock();
2825*67e74705SXin Li mu_->Unlock();
2826*67e74705SXin Li }
2827*67e74705SXin Li }
2828*67e74705SXin Li
2829*67e74705SXin Li
test8()2830*67e74705SXin Li void Foo::test8() {
2831*67e74705SXin Li mu_->Lock();
2832*67e74705SXin Li mu_.get()->Lock(); // expected-warning {{acquiring mutex 'mu_' that is already held}}
2833*67e74705SXin Li (*mu_).Lock(); // expected-warning {{acquiring mutex 'mu_' that is already held}}
2834*67e74705SXin Li mu_.get()->Unlock();
2835*67e74705SXin Li Unlock(); // expected-warning {{releasing mutex 'mu_' that was not held}}
2836*67e74705SXin Li }
2837*67e74705SXin Li
2838*67e74705SXin Li
2839*67e74705SXin Li class Bar {
2840*67e74705SXin Li SmartPtr<Foo> foo;
2841*67e74705SXin Li
2842*67e74705SXin Li void test0();
2843*67e74705SXin Li void test1();
2844*67e74705SXin Li void test2();
2845*67e74705SXin Li void test3();
2846*67e74705SXin Li };
2847*67e74705SXin Li
2848*67e74705SXin Li
test0()2849*67e74705SXin Li void Bar::test0() {
2850*67e74705SXin Li foo->a = 0; // expected-warning {{writing variable 'a' requires holding mutex 'foo->mu_' exclusively}}
2851*67e74705SXin Li (*foo).b = 0; // expected-warning {{writing variable 'b' requires holding mutex 'foo->mu_' exclusively}}
2852*67e74705SXin Li foo.get()->c = 0; // expected-warning {{writing variable 'c' requires holding mutex 'foo->mu_' exclusively}}
2853*67e74705SXin Li }
2854*67e74705SXin Li
2855*67e74705SXin Li
test1()2856*67e74705SXin Li void Bar::test1() {
2857*67e74705SXin Li foo->mu_->Lock();
2858*67e74705SXin Li foo->a = 0;
2859*67e74705SXin Li (*foo).b = 0;
2860*67e74705SXin Li foo.get()->c = 0;
2861*67e74705SXin Li foo->mu_->Unlock();
2862*67e74705SXin Li }
2863*67e74705SXin Li
2864*67e74705SXin Li
test2()2865*67e74705SXin Li void Bar::test2() {
2866*67e74705SXin Li (*foo).mu_->Lock();
2867*67e74705SXin Li foo->a = 0;
2868*67e74705SXin Li (*foo).b = 0;
2869*67e74705SXin Li foo.get()->c = 0;
2870*67e74705SXin Li foo.get()->mu_->Unlock();
2871*67e74705SXin Li }
2872*67e74705SXin Li
2873*67e74705SXin Li
test3()2874*67e74705SXin Li void Bar::test3() {
2875*67e74705SXin Li MutexLock lock(foo->mu_.get());
2876*67e74705SXin Li foo->a = 0;
2877*67e74705SXin Li (*foo).b = 0;
2878*67e74705SXin Li foo.get()->c = 0;
2879*67e74705SXin Li }
2880*67e74705SXin Li
2881*67e74705SXin Li } // end namespace SmartPointerTests
2882*67e74705SXin Li
2883*67e74705SXin Li
2884*67e74705SXin Li
2885*67e74705SXin Li namespace DuplicateAttributeTest {
2886*67e74705SXin Li
2887*67e74705SXin Li class LOCKABLE Foo {
2888*67e74705SXin Li public:
2889*67e74705SXin Li Mutex mu1_;
2890*67e74705SXin Li Mutex mu2_;
2891*67e74705SXin Li Mutex mu3_;
2892*67e74705SXin Li int a GUARDED_BY(mu1_);
2893*67e74705SXin Li int b GUARDED_BY(mu2_);
2894*67e74705SXin Li int c GUARDED_BY(mu3_);
2895*67e74705SXin Li
2896*67e74705SXin Li void lock() EXCLUSIVE_LOCK_FUNCTION();
2897*67e74705SXin Li void unlock() UNLOCK_FUNCTION();
2898*67e74705SXin Li
2899*67e74705SXin Li void lock1() EXCLUSIVE_LOCK_FUNCTION(mu1_);
2900*67e74705SXin Li void slock1() SHARED_LOCK_FUNCTION(mu1_);
2901*67e74705SXin Li void lock3() EXCLUSIVE_LOCK_FUNCTION(mu1_, mu2_, mu3_);
2902*67e74705SXin Li void locklots()
2903*67e74705SXin Li EXCLUSIVE_LOCK_FUNCTION(mu1_)
2904*67e74705SXin Li EXCLUSIVE_LOCK_FUNCTION(mu2_)
2905*67e74705SXin Li EXCLUSIVE_LOCK_FUNCTION(mu1_, mu2_, mu3_);
2906*67e74705SXin Li
2907*67e74705SXin Li void unlock1() UNLOCK_FUNCTION(mu1_);
2908*67e74705SXin Li void unlock3() UNLOCK_FUNCTION(mu1_, mu2_, mu3_);
2909*67e74705SXin Li void unlocklots()
2910*67e74705SXin Li UNLOCK_FUNCTION(mu1_)
2911*67e74705SXin Li UNLOCK_FUNCTION(mu2_)
2912*67e74705SXin Li UNLOCK_FUNCTION(mu1_, mu2_, mu3_);
2913*67e74705SXin Li };
2914*67e74705SXin Li
2915*67e74705SXin Li
lock()2916*67e74705SXin Li void Foo::lock() EXCLUSIVE_LOCK_FUNCTION() { }
unlock()2917*67e74705SXin Li void Foo::unlock() UNLOCK_FUNCTION() { }
2918*67e74705SXin Li
lock1()2919*67e74705SXin Li void Foo::lock1() EXCLUSIVE_LOCK_FUNCTION(mu1_) {
2920*67e74705SXin Li mu1_.Lock();
2921*67e74705SXin Li }
2922*67e74705SXin Li
slock1()2923*67e74705SXin Li void Foo::slock1() SHARED_LOCK_FUNCTION(mu1_) {
2924*67e74705SXin Li mu1_.ReaderLock();
2925*67e74705SXin Li }
2926*67e74705SXin Li
lock3()2927*67e74705SXin Li void Foo::lock3() EXCLUSIVE_LOCK_FUNCTION(mu1_, mu2_, mu3_) {
2928*67e74705SXin Li mu1_.Lock();
2929*67e74705SXin Li mu2_.Lock();
2930*67e74705SXin Li mu3_.Lock();
2931*67e74705SXin Li }
2932*67e74705SXin Li
locklots()2933*67e74705SXin Li void Foo::locklots()
2934*67e74705SXin Li EXCLUSIVE_LOCK_FUNCTION(mu1_, mu2_)
2935*67e74705SXin Li EXCLUSIVE_LOCK_FUNCTION(mu2_, mu3_) {
2936*67e74705SXin Li mu1_.Lock();
2937*67e74705SXin Li mu2_.Lock();
2938*67e74705SXin Li mu3_.Lock();
2939*67e74705SXin Li }
2940*67e74705SXin Li
unlock1()2941*67e74705SXin Li void Foo::unlock1() UNLOCK_FUNCTION(mu1_) {
2942*67e74705SXin Li mu1_.Unlock();
2943*67e74705SXin Li }
2944*67e74705SXin Li
unlock3()2945*67e74705SXin Li void Foo::unlock3() UNLOCK_FUNCTION(mu1_, mu2_, mu3_) {
2946*67e74705SXin Li mu1_.Unlock();
2947*67e74705SXin Li mu2_.Unlock();
2948*67e74705SXin Li mu3_.Unlock();
2949*67e74705SXin Li }
2950*67e74705SXin Li
unlocklots()2951*67e74705SXin Li void Foo::unlocklots()
2952*67e74705SXin Li UNLOCK_FUNCTION(mu1_, mu2_)
2953*67e74705SXin Li UNLOCK_FUNCTION(mu2_, mu3_) {
2954*67e74705SXin Li mu1_.Unlock();
2955*67e74705SXin Li mu2_.Unlock();
2956*67e74705SXin Li mu3_.Unlock();
2957*67e74705SXin Li }
2958*67e74705SXin Li
2959*67e74705SXin Li
test0()2960*67e74705SXin Li void test0() {
2961*67e74705SXin Li Foo foo;
2962*67e74705SXin Li foo.lock();
2963*67e74705SXin Li foo.unlock();
2964*67e74705SXin Li
2965*67e74705SXin Li foo.lock();
2966*67e74705SXin Li foo.lock(); // expected-warning {{acquiring mutex 'foo' that is already held}}
2967*67e74705SXin Li foo.unlock();
2968*67e74705SXin Li foo.unlock(); // expected-warning {{releasing mutex 'foo' that was not held}}
2969*67e74705SXin Li }
2970*67e74705SXin Li
2971*67e74705SXin Li
test1()2972*67e74705SXin Li void test1() {
2973*67e74705SXin Li Foo foo;
2974*67e74705SXin Li foo.lock1();
2975*67e74705SXin Li foo.a = 0;
2976*67e74705SXin Li foo.unlock1();
2977*67e74705SXin Li
2978*67e74705SXin Li foo.lock1();
2979*67e74705SXin Li foo.lock1(); // expected-warning {{acquiring mutex 'foo.mu1_' that is already held}}
2980*67e74705SXin Li foo.a = 0;
2981*67e74705SXin Li foo.unlock1();
2982*67e74705SXin Li foo.unlock1(); // expected-warning {{releasing mutex 'foo.mu1_' that was not held}}
2983*67e74705SXin Li }
2984*67e74705SXin Li
2985*67e74705SXin Li
test2()2986*67e74705SXin Li int test2() {
2987*67e74705SXin Li Foo foo;
2988*67e74705SXin Li foo.slock1();
2989*67e74705SXin Li int d1 = foo.a;
2990*67e74705SXin Li foo.unlock1();
2991*67e74705SXin Li
2992*67e74705SXin Li foo.slock1();
2993*67e74705SXin Li foo.slock1(); // expected-warning {{acquiring mutex 'foo.mu1_' that is already held}}
2994*67e74705SXin Li int d2 = foo.a;
2995*67e74705SXin Li foo.unlock1();
2996*67e74705SXin Li foo.unlock1(); // expected-warning {{releasing mutex 'foo.mu1_' that was not held}}
2997*67e74705SXin Li return d1 + d2;
2998*67e74705SXin Li }
2999*67e74705SXin Li
3000*67e74705SXin Li
test3()3001*67e74705SXin Li void test3() {
3002*67e74705SXin Li Foo foo;
3003*67e74705SXin Li foo.lock3();
3004*67e74705SXin Li foo.a = 0;
3005*67e74705SXin Li foo.b = 0;
3006*67e74705SXin Li foo.c = 0;
3007*67e74705SXin Li foo.unlock3();
3008*67e74705SXin Li
3009*67e74705SXin Li foo.lock3();
3010*67e74705SXin Li foo.lock3(); // \
3011*67e74705SXin Li // expected-warning {{acquiring mutex 'foo.mu1_' that is already held}} \
3012*67e74705SXin Li // expected-warning {{acquiring mutex 'foo.mu2_' that is already held}} \
3013*67e74705SXin Li // expected-warning {{acquiring mutex 'foo.mu3_' that is already held}}
3014*67e74705SXin Li foo.a = 0;
3015*67e74705SXin Li foo.b = 0;
3016*67e74705SXin Li foo.c = 0;
3017*67e74705SXin Li foo.unlock3();
3018*67e74705SXin Li foo.unlock3(); // \
3019*67e74705SXin Li // expected-warning {{releasing mutex 'foo.mu1_' that was not held}} \
3020*67e74705SXin Li // expected-warning {{releasing mutex 'foo.mu2_' that was not held}} \
3021*67e74705SXin Li // expected-warning {{releasing mutex 'foo.mu3_' that was not held}}
3022*67e74705SXin Li }
3023*67e74705SXin Li
3024*67e74705SXin Li
testlots()3025*67e74705SXin Li void testlots() {
3026*67e74705SXin Li Foo foo;
3027*67e74705SXin Li foo.locklots();
3028*67e74705SXin Li foo.a = 0;
3029*67e74705SXin Li foo.b = 0;
3030*67e74705SXin Li foo.c = 0;
3031*67e74705SXin Li foo.unlocklots();
3032*67e74705SXin Li
3033*67e74705SXin Li foo.locklots();
3034*67e74705SXin Li foo.locklots(); // \
3035*67e74705SXin Li // expected-warning {{acquiring mutex 'foo.mu1_' that is already held}} \
3036*67e74705SXin Li // expected-warning {{acquiring mutex 'foo.mu2_' that is already held}} \
3037*67e74705SXin Li // expected-warning {{acquiring mutex 'foo.mu3_' that is already held}}
3038*67e74705SXin Li foo.a = 0;
3039*67e74705SXin Li foo.b = 0;
3040*67e74705SXin Li foo.c = 0;
3041*67e74705SXin Li foo.unlocklots();
3042*67e74705SXin Li foo.unlocklots(); // \
3043*67e74705SXin Li // expected-warning {{releasing mutex 'foo.mu1_' that was not held}} \
3044*67e74705SXin Li // expected-warning {{releasing mutex 'foo.mu2_' that was not held}} \
3045*67e74705SXin Li // expected-warning {{releasing mutex 'foo.mu3_' that was not held}}
3046*67e74705SXin Li }
3047*67e74705SXin Li
3048*67e74705SXin Li } // end namespace DuplicateAttributeTest
3049*67e74705SXin Li
3050*67e74705SXin Li
3051*67e74705SXin Li
3052*67e74705SXin Li namespace TryLockEqTest {
3053*67e74705SXin Li
3054*67e74705SXin Li class Foo {
3055*67e74705SXin Li Mutex mu_;
3056*67e74705SXin Li int a GUARDED_BY(mu_);
3057*67e74705SXin Li bool c;
3058*67e74705SXin Li
3059*67e74705SXin Li int tryLockMutexI() EXCLUSIVE_TRYLOCK_FUNCTION(1, mu_);
3060*67e74705SXin Li Mutex* tryLockMutexP() EXCLUSIVE_TRYLOCK_FUNCTION(1, mu_);
3061*67e74705SXin Li void unlock() UNLOCK_FUNCTION(mu_);
3062*67e74705SXin Li
3063*67e74705SXin Li void test1();
3064*67e74705SXin Li void test2();
3065*67e74705SXin Li };
3066*67e74705SXin Li
3067*67e74705SXin Li
test1()3068*67e74705SXin Li void Foo::test1() {
3069*67e74705SXin Li if (tryLockMutexP() == 0) {
3070*67e74705SXin Li a = 0; // expected-warning {{writing variable 'a' requires holding mutex 'mu_' exclusively}}
3071*67e74705SXin Li return;
3072*67e74705SXin Li }
3073*67e74705SXin Li a = 0;
3074*67e74705SXin Li unlock();
3075*67e74705SXin Li
3076*67e74705SXin Li if (tryLockMutexP() != 0) {
3077*67e74705SXin Li a = 0;
3078*67e74705SXin Li unlock();
3079*67e74705SXin Li }
3080*67e74705SXin Li
3081*67e74705SXin Li if (0 != tryLockMutexP()) {
3082*67e74705SXin Li a = 0;
3083*67e74705SXin Li unlock();
3084*67e74705SXin Li }
3085*67e74705SXin Li
3086*67e74705SXin Li if (!(tryLockMutexP() == 0)) {
3087*67e74705SXin Li a = 0;
3088*67e74705SXin Li unlock();
3089*67e74705SXin Li }
3090*67e74705SXin Li
3091*67e74705SXin Li if (tryLockMutexI() == 0) {
3092*67e74705SXin Li a = 0; // expected-warning {{writing variable 'a' requires holding mutex 'mu_' exclusively}}
3093*67e74705SXin Li return;
3094*67e74705SXin Li }
3095*67e74705SXin Li a = 0;
3096*67e74705SXin Li unlock();
3097*67e74705SXin Li
3098*67e74705SXin Li if (0 == tryLockMutexI()) {
3099*67e74705SXin Li a = 0; // expected-warning {{writing variable 'a' requires holding mutex 'mu_' exclusively}}
3100*67e74705SXin Li return;
3101*67e74705SXin Li }
3102*67e74705SXin Li a = 0;
3103*67e74705SXin Li unlock();
3104*67e74705SXin Li
3105*67e74705SXin Li if (tryLockMutexI() == 1) {
3106*67e74705SXin Li a = 0;
3107*67e74705SXin Li unlock();
3108*67e74705SXin Li }
3109*67e74705SXin Li
3110*67e74705SXin Li if (mu_.TryLock() == false) {
3111*67e74705SXin Li a = 0; // expected-warning {{writing variable 'a' requires holding mutex 'mu_' exclusively}}
3112*67e74705SXin Li return;
3113*67e74705SXin Li }
3114*67e74705SXin Li a = 0;
3115*67e74705SXin Li unlock();
3116*67e74705SXin Li
3117*67e74705SXin Li if (mu_.TryLock() == true) {
3118*67e74705SXin Li a = 0;
3119*67e74705SXin Li unlock();
3120*67e74705SXin Li }
3121*67e74705SXin Li else {
3122*67e74705SXin Li a = 0; // expected-warning {{writing variable 'a' requires holding mutex 'mu_' exclusively}}
3123*67e74705SXin Li }
3124*67e74705SXin Li
3125*67e74705SXin Li #if __has_feature(cxx_nullptr)
3126*67e74705SXin Li if (tryLockMutexP() == nullptr) {
3127*67e74705SXin Li a = 0; // expected-warning {{writing variable 'a' requires holding mutex 'mu_' exclusively}}
3128*67e74705SXin Li return;
3129*67e74705SXin Li }
3130*67e74705SXin Li a = 0;
3131*67e74705SXin Li unlock();
3132*67e74705SXin Li #endif
3133*67e74705SXin Li }
3134*67e74705SXin Li
3135*67e74705SXin Li } // end namespace TryLockEqTest
3136*67e74705SXin Li
3137*67e74705SXin Li
3138*67e74705SXin Li namespace ExistentialPatternMatching {
3139*67e74705SXin Li
3140*67e74705SXin Li class Graph {
3141*67e74705SXin Li public:
3142*67e74705SXin Li Mutex mu_;
3143*67e74705SXin Li };
3144*67e74705SXin Li
3145*67e74705SXin Li void LockAllGraphs() EXCLUSIVE_LOCK_FUNCTION(&Graph::mu_);
3146*67e74705SXin Li void UnlockAllGraphs() UNLOCK_FUNCTION(&Graph::mu_);
3147*67e74705SXin Li
3148*67e74705SXin Li class Node {
3149*67e74705SXin Li public:
3150*67e74705SXin Li int a GUARDED_BY(&Graph::mu_);
3151*67e74705SXin Li
foo()3152*67e74705SXin Li void foo() EXCLUSIVE_LOCKS_REQUIRED(&Graph::mu_) {
3153*67e74705SXin Li a = 0;
3154*67e74705SXin Li }
3155*67e74705SXin Li void foo2() LOCKS_EXCLUDED(&Graph::mu_);
3156*67e74705SXin Li };
3157*67e74705SXin Li
test()3158*67e74705SXin Li void test() {
3159*67e74705SXin Li Graph g1;
3160*67e74705SXin Li Graph g2;
3161*67e74705SXin Li Node n1;
3162*67e74705SXin Li
3163*67e74705SXin Li n1.a = 0; // expected-warning {{writing variable 'a' requires holding mutex '&ExistentialPatternMatching::Graph::mu_' exclusively}}
3164*67e74705SXin Li n1.foo(); // expected-warning {{calling function 'foo' requires holding mutex '&ExistentialPatternMatching::Graph::mu_' exclusively}}
3165*67e74705SXin Li n1.foo2();
3166*67e74705SXin Li
3167*67e74705SXin Li g1.mu_.Lock();
3168*67e74705SXin Li n1.a = 0;
3169*67e74705SXin Li n1.foo();
3170*67e74705SXin Li n1.foo2(); // expected-warning {{cannot call function 'foo2' while mutex '&ExistentialPatternMatching::Graph::mu_' is held}}
3171*67e74705SXin Li g1.mu_.Unlock();
3172*67e74705SXin Li
3173*67e74705SXin Li g2.mu_.Lock();
3174*67e74705SXin Li n1.a = 0;
3175*67e74705SXin Li n1.foo();
3176*67e74705SXin Li n1.foo2(); // expected-warning {{cannot call function 'foo2' while mutex '&ExistentialPatternMatching::Graph::mu_' is held}}
3177*67e74705SXin Li g2.mu_.Unlock();
3178*67e74705SXin Li
3179*67e74705SXin Li LockAllGraphs();
3180*67e74705SXin Li n1.a = 0;
3181*67e74705SXin Li n1.foo();
3182*67e74705SXin Li n1.foo2(); // expected-warning {{cannot call function 'foo2' while mutex '&ExistentialPatternMatching::Graph::mu_' is held}}
3183*67e74705SXin Li UnlockAllGraphs();
3184*67e74705SXin Li
3185*67e74705SXin Li LockAllGraphs();
3186*67e74705SXin Li g1.mu_.Unlock();
3187*67e74705SXin Li
3188*67e74705SXin Li LockAllGraphs();
3189*67e74705SXin Li g2.mu_.Unlock();
3190*67e74705SXin Li
3191*67e74705SXin Li LockAllGraphs();
3192*67e74705SXin Li g1.mu_.Lock(); // expected-warning {{acquiring mutex 'g1.mu_' that is already held}}
3193*67e74705SXin Li g1.mu_.Unlock();
3194*67e74705SXin Li }
3195*67e74705SXin Li
3196*67e74705SXin Li } // end namespace ExistentialPatternMatching
3197*67e74705SXin Li
3198*67e74705SXin Li
3199*67e74705SXin Li namespace StringIgnoreTest {
3200*67e74705SXin Li
3201*67e74705SXin Li class Foo {
3202*67e74705SXin Li public:
3203*67e74705SXin Li Mutex mu_;
3204*67e74705SXin Li void lock() EXCLUSIVE_LOCK_FUNCTION("");
3205*67e74705SXin Li void unlock() UNLOCK_FUNCTION("");
3206*67e74705SXin Li void goober() EXCLUSIVE_LOCKS_REQUIRED("");
3207*67e74705SXin Li void roober() SHARED_LOCKS_REQUIRED("");
3208*67e74705SXin Li };
3209*67e74705SXin Li
3210*67e74705SXin Li
3211*67e74705SXin Li class Bar : public Foo {
3212*67e74705SXin Li public:
bar(Foo * f)3213*67e74705SXin Li void bar(Foo* f) {
3214*67e74705SXin Li f->unlock();
3215*67e74705SXin Li f->goober();
3216*67e74705SXin Li f->roober();
3217*67e74705SXin Li f->lock();
3218*67e74705SXin Li };
3219*67e74705SXin Li };
3220*67e74705SXin Li
3221*67e74705SXin Li } // end namespace StringIgnoreTest
3222*67e74705SXin Li
3223*67e74705SXin Li
3224*67e74705SXin Li namespace LockReturnedScopeFix {
3225*67e74705SXin Li
3226*67e74705SXin Li class Base {
3227*67e74705SXin Li protected:
3228*67e74705SXin Li struct Inner;
3229*67e74705SXin Li bool c;
3230*67e74705SXin Li
3231*67e74705SXin Li const Mutex& getLock(const Inner* i);
3232*67e74705SXin Li
3233*67e74705SXin Li void lockInner (Inner* i) EXCLUSIVE_LOCK_FUNCTION(getLock(i));
3234*67e74705SXin Li void unlockInner(Inner* i) UNLOCK_FUNCTION(getLock(i));
3235*67e74705SXin Li void foo(Inner* i) EXCLUSIVE_LOCKS_REQUIRED(getLock(i));
3236*67e74705SXin Li
3237*67e74705SXin Li void bar(Inner* i);
3238*67e74705SXin Li };
3239*67e74705SXin Li
3240*67e74705SXin Li
3241*67e74705SXin Li struct Base::Inner {
3242*67e74705SXin Li Mutex lock_;
3243*67e74705SXin Li void doSomething() EXCLUSIVE_LOCKS_REQUIRED(lock_);
3244*67e74705SXin Li };
3245*67e74705SXin Li
3246*67e74705SXin Li
getLock(const Inner * i)3247*67e74705SXin Li const Mutex& Base::getLock(const Inner* i) LOCK_RETURNED(i->lock_) {
3248*67e74705SXin Li return i->lock_;
3249*67e74705SXin Li }
3250*67e74705SXin Li
3251*67e74705SXin Li
foo(Inner * i)3252*67e74705SXin Li void Base::foo(Inner* i) {
3253*67e74705SXin Li i->doSomething();
3254*67e74705SXin Li }
3255*67e74705SXin Li
bar(Inner * i)3256*67e74705SXin Li void Base::bar(Inner* i) {
3257*67e74705SXin Li if (c) {
3258*67e74705SXin Li i->lock_.Lock();
3259*67e74705SXin Li unlockInner(i);
3260*67e74705SXin Li }
3261*67e74705SXin Li else {
3262*67e74705SXin Li lockInner(i);
3263*67e74705SXin Li i->lock_.Unlock();
3264*67e74705SXin Li }
3265*67e74705SXin Li }
3266*67e74705SXin Li
3267*67e74705SXin Li } // end namespace LockReturnedScopeFix
3268*67e74705SXin Li
3269*67e74705SXin Li
3270*67e74705SXin Li namespace TrylockWithCleanups {
3271*67e74705SXin Li
3272*67e74705SXin Li struct Foo {
3273*67e74705SXin Li Mutex mu_;
3274*67e74705SXin Li int a GUARDED_BY(mu_);
3275*67e74705SXin Li };
3276*67e74705SXin Li
3277*67e74705SXin Li Foo* GetAndLockFoo(const MyString& s)
3278*67e74705SXin Li EXCLUSIVE_TRYLOCK_FUNCTION(true, &Foo::mu_);
3279*67e74705SXin Li
test()3280*67e74705SXin Li static void test() {
3281*67e74705SXin Li Foo* lt = GetAndLockFoo("foo");
3282*67e74705SXin Li if (!lt) return;
3283*67e74705SXin Li int a = lt->a;
3284*67e74705SXin Li lt->mu_.Unlock();
3285*67e74705SXin Li }
3286*67e74705SXin Li
3287*67e74705SXin Li } // end namespace TrylockWithCleanups
3288*67e74705SXin Li
3289*67e74705SXin Li
3290*67e74705SXin Li namespace UniversalLock {
3291*67e74705SXin Li
3292*67e74705SXin Li class Foo {
3293*67e74705SXin Li Mutex mu_;
3294*67e74705SXin Li bool c;
3295*67e74705SXin Li
3296*67e74705SXin Li int a GUARDED_BY(mu_);
3297*67e74705SXin Li void r_foo() SHARED_LOCKS_REQUIRED(mu_);
3298*67e74705SXin Li void w_foo() EXCLUSIVE_LOCKS_REQUIRED(mu_);
3299*67e74705SXin Li
test1()3300*67e74705SXin Li void test1() {
3301*67e74705SXin Li int b;
3302*67e74705SXin Li
3303*67e74705SXin Li beginNoWarnOnReads();
3304*67e74705SXin Li b = a;
3305*67e74705SXin Li r_foo();
3306*67e74705SXin Li endNoWarnOnReads();
3307*67e74705SXin Li
3308*67e74705SXin Li beginNoWarnOnWrites();
3309*67e74705SXin Li a = 0;
3310*67e74705SXin Li w_foo();
3311*67e74705SXin Li endNoWarnOnWrites();
3312*67e74705SXin Li }
3313*67e74705SXin Li
3314*67e74705SXin Li // don't warn on joins with universal lock
test2()3315*67e74705SXin Li void test2() {
3316*67e74705SXin Li if (c) {
3317*67e74705SXin Li beginNoWarnOnWrites();
3318*67e74705SXin Li }
3319*67e74705SXin Li a = 0; // \
3320*67e74705SXin Li // expected-warning {{writing variable 'a' requires holding mutex 'mu_' exclusively}}
3321*67e74705SXin Li endNoWarnOnWrites(); // \
3322*67e74705SXin Li // expected-warning {{releasing mutex '*' that was not held}}
3323*67e74705SXin Li }
3324*67e74705SXin Li
3325*67e74705SXin Li
3326*67e74705SXin Li // make sure the universal lock joins properly
test3()3327*67e74705SXin Li void test3() {
3328*67e74705SXin Li if (c) {
3329*67e74705SXin Li mu_.Lock();
3330*67e74705SXin Li beginNoWarnOnWrites();
3331*67e74705SXin Li }
3332*67e74705SXin Li else {
3333*67e74705SXin Li beginNoWarnOnWrites();
3334*67e74705SXin Li mu_.Lock();
3335*67e74705SXin Li }
3336*67e74705SXin Li a = 0;
3337*67e74705SXin Li endNoWarnOnWrites();
3338*67e74705SXin Li mu_.Unlock();
3339*67e74705SXin Li }
3340*67e74705SXin Li
3341*67e74705SXin Li
3342*67e74705SXin Li // combine universal lock with other locks
test4()3343*67e74705SXin Li void test4() {
3344*67e74705SXin Li beginNoWarnOnWrites();
3345*67e74705SXin Li mu_.Lock();
3346*67e74705SXin Li mu_.Unlock();
3347*67e74705SXin Li endNoWarnOnWrites();
3348*67e74705SXin Li
3349*67e74705SXin Li mu_.Lock();
3350*67e74705SXin Li beginNoWarnOnWrites();
3351*67e74705SXin Li endNoWarnOnWrites();
3352*67e74705SXin Li mu_.Unlock();
3353*67e74705SXin Li
3354*67e74705SXin Li mu_.Lock();
3355*67e74705SXin Li beginNoWarnOnWrites();
3356*67e74705SXin Li mu_.Unlock();
3357*67e74705SXin Li endNoWarnOnWrites();
3358*67e74705SXin Li }
3359*67e74705SXin Li };
3360*67e74705SXin Li
3361*67e74705SXin Li } // end namespace UniversalLock
3362*67e74705SXin Li
3363*67e74705SXin Li
3364*67e74705SXin Li namespace TemplateLockReturned {
3365*67e74705SXin Li
3366*67e74705SXin Li template<class T>
3367*67e74705SXin Li class BaseT {
3368*67e74705SXin Li public:
3369*67e74705SXin Li virtual void baseMethod() = 0;
get_mutex()3370*67e74705SXin Li Mutex* get_mutex() LOCK_RETURNED(mutex_) { return &mutex_; }
3371*67e74705SXin Li
3372*67e74705SXin Li Mutex mutex_;
3373*67e74705SXin Li int a GUARDED_BY(mutex_);
3374*67e74705SXin Li };
3375*67e74705SXin Li
3376*67e74705SXin Li
3377*67e74705SXin Li class Derived : public BaseT<int> {
3378*67e74705SXin Li public:
baseMethod()3379*67e74705SXin Li void baseMethod() EXCLUSIVE_LOCKS_REQUIRED(get_mutex()) {
3380*67e74705SXin Li a = 0;
3381*67e74705SXin Li }
3382*67e74705SXin Li };
3383*67e74705SXin Li
3384*67e74705SXin Li } // end namespace TemplateLockReturned
3385*67e74705SXin Li
3386*67e74705SXin Li
3387*67e74705SXin Li namespace ExprMatchingBugFix {
3388*67e74705SXin Li
3389*67e74705SXin Li class Foo {
3390*67e74705SXin Li public:
3391*67e74705SXin Li Mutex mu_;
3392*67e74705SXin Li };
3393*67e74705SXin Li
3394*67e74705SXin Li
3395*67e74705SXin Li class Bar {
3396*67e74705SXin Li public:
3397*67e74705SXin Li bool c;
3398*67e74705SXin Li Foo* foo;
Bar(Foo * f)3399*67e74705SXin Li Bar(Foo* f) : foo(f) { }
3400*67e74705SXin Li
3401*67e74705SXin Li struct Nested {
3402*67e74705SXin Li Foo* foo;
NestedExprMatchingBugFix::Bar::Nested3403*67e74705SXin Li Nested(Foo* f) : foo(f) { }
3404*67e74705SXin Li
3405*67e74705SXin Li void unlockFoo() UNLOCK_FUNCTION(&Foo::mu_);
3406*67e74705SXin Li };
3407*67e74705SXin Li
3408*67e74705SXin Li void test();
3409*67e74705SXin Li };
3410*67e74705SXin Li
3411*67e74705SXin Li
test()3412*67e74705SXin Li void Bar::test() {
3413*67e74705SXin Li foo->mu_.Lock();
3414*67e74705SXin Li if (c) {
3415*67e74705SXin Li Nested *n = new Nested(foo);
3416*67e74705SXin Li n->unlockFoo();
3417*67e74705SXin Li }
3418*67e74705SXin Li else {
3419*67e74705SXin Li foo->mu_.Unlock();
3420*67e74705SXin Li }
3421*67e74705SXin Li }
3422*67e74705SXin Li
3423*67e74705SXin Li }; // end namespace ExprMatchingBugfix
3424*67e74705SXin Li
3425*67e74705SXin Li
3426*67e74705SXin Li namespace ComplexNameTest {
3427*67e74705SXin Li
3428*67e74705SXin Li class Foo {
3429*67e74705SXin Li public:
3430*67e74705SXin Li static Mutex mu_;
3431*67e74705SXin Li
EXCLUSIVE_LOCKS_REQUIRED(mu_)3432*67e74705SXin Li Foo() EXCLUSIVE_LOCKS_REQUIRED(mu_) { }
EXCLUSIVE_LOCKS_REQUIRED(mu_)3433*67e74705SXin Li ~Foo() EXCLUSIVE_LOCKS_REQUIRED(mu_) { }
3434*67e74705SXin Li
operator [](int i)3435*67e74705SXin Li int operator[](int i) EXCLUSIVE_LOCKS_REQUIRED(mu_) { return 0; }
3436*67e74705SXin Li };
3437*67e74705SXin Li
3438*67e74705SXin Li class Bar {
3439*67e74705SXin Li public:
3440*67e74705SXin Li static Mutex mu_;
3441*67e74705SXin Li
LOCKS_EXCLUDED(mu_)3442*67e74705SXin Li Bar() LOCKS_EXCLUDED(mu_) { }
LOCKS_EXCLUDED(mu_)3443*67e74705SXin Li ~Bar() LOCKS_EXCLUDED(mu_) { }
3444*67e74705SXin Li
operator [](int i)3445*67e74705SXin Li int operator[](int i) LOCKS_EXCLUDED(mu_) { return 0; }
3446*67e74705SXin Li };
3447*67e74705SXin Li
3448*67e74705SXin Li
test1()3449*67e74705SXin Li void test1() {
3450*67e74705SXin Li Foo f; // expected-warning {{calling function 'Foo' requires holding mutex 'mu_' exclusively}}
3451*67e74705SXin Li int a = f[0]; // expected-warning {{calling function 'operator[]' requires holding mutex 'mu_' exclusively}}
3452*67e74705SXin Li } // expected-warning {{calling function '~Foo' requires holding mutex 'mu_' exclusively}}
3453*67e74705SXin Li
3454*67e74705SXin Li
test2()3455*67e74705SXin Li void test2() {
3456*67e74705SXin Li Bar::mu_.Lock();
3457*67e74705SXin Li {
3458*67e74705SXin Li Bar b; // expected-warning {{cannot call function 'Bar' while mutex 'mu_' is held}}
3459*67e74705SXin Li int a = b[0]; // expected-warning {{cannot call function 'operator[]' while mutex 'mu_' is held}}
3460*67e74705SXin Li } // expected-warning {{cannot call function '~Bar' while mutex 'mu_' is held}}
3461*67e74705SXin Li Bar::mu_.Unlock();
3462*67e74705SXin Li }
3463*67e74705SXin Li
3464*67e74705SXin Li }; // end namespace ComplexNameTest
3465*67e74705SXin Li
3466*67e74705SXin Li
3467*67e74705SXin Li namespace UnreachableExitTest {
3468*67e74705SXin Li
3469*67e74705SXin Li class FemmeFatale {
3470*67e74705SXin Li public:
3471*67e74705SXin Li FemmeFatale();
3472*67e74705SXin Li ~FemmeFatale() __attribute__((noreturn));
3473*67e74705SXin Li };
3474*67e74705SXin Li
3475*67e74705SXin Li void exitNow() __attribute__((noreturn));
3476*67e74705SXin Li void exitDestruct(const MyString& ms) __attribute__((noreturn));
3477*67e74705SXin Li
3478*67e74705SXin Li Mutex fatalmu_;
3479*67e74705SXin Li
test1()3480*67e74705SXin Li void test1() EXCLUSIVE_LOCKS_REQUIRED(fatalmu_) {
3481*67e74705SXin Li exitNow();
3482*67e74705SXin Li }
3483*67e74705SXin Li
test2()3484*67e74705SXin Li void test2() EXCLUSIVE_LOCKS_REQUIRED(fatalmu_) {
3485*67e74705SXin Li FemmeFatale femme;
3486*67e74705SXin Li }
3487*67e74705SXin Li
3488*67e74705SXin Li bool c;
3489*67e74705SXin Li
test3()3490*67e74705SXin Li void test3() EXCLUSIVE_LOCKS_REQUIRED(fatalmu_) {
3491*67e74705SXin Li if (c) {
3492*67e74705SXin Li exitNow();
3493*67e74705SXin Li }
3494*67e74705SXin Li else {
3495*67e74705SXin Li FemmeFatale femme;
3496*67e74705SXin Li }
3497*67e74705SXin Li }
3498*67e74705SXin Li
test4()3499*67e74705SXin Li void test4() EXCLUSIVE_LOCKS_REQUIRED(fatalmu_) {
3500*67e74705SXin Li exitDestruct("foo");
3501*67e74705SXin Li }
3502*67e74705SXin Li
3503*67e74705SXin Li } // end namespace UnreachableExitTest
3504*67e74705SXin Li
3505*67e74705SXin Li
3506*67e74705SXin Li namespace VirtualMethodCanonicalizationTest {
3507*67e74705SXin Li
3508*67e74705SXin Li class Base {
3509*67e74705SXin Li public:
3510*67e74705SXin Li virtual Mutex* getMutex() = 0;
3511*67e74705SXin Li };
3512*67e74705SXin Li
3513*67e74705SXin Li class Base2 : public Base {
3514*67e74705SXin Li public:
3515*67e74705SXin Li Mutex* getMutex();
3516*67e74705SXin Li };
3517*67e74705SXin Li
3518*67e74705SXin Li class Base3 : public Base2 {
3519*67e74705SXin Li public:
3520*67e74705SXin Li Mutex* getMutex();
3521*67e74705SXin Li };
3522*67e74705SXin Li
3523*67e74705SXin Li class Derived : public Base3 {
3524*67e74705SXin Li public:
3525*67e74705SXin Li Mutex* getMutex(); // overrides Base::getMutex()
3526*67e74705SXin Li };
3527*67e74705SXin Li
baseFun(Base * b)3528*67e74705SXin Li void baseFun(Base *b) EXCLUSIVE_LOCKS_REQUIRED(b->getMutex()) { }
3529*67e74705SXin Li
derivedFun(Derived * d)3530*67e74705SXin Li void derivedFun(Derived *d) EXCLUSIVE_LOCKS_REQUIRED(d->getMutex()) {
3531*67e74705SXin Li baseFun(d);
3532*67e74705SXin Li }
3533*67e74705SXin Li
3534*67e74705SXin Li } // end namespace VirtualMethodCanonicalizationTest
3535*67e74705SXin Li
3536*67e74705SXin Li
3537*67e74705SXin Li namespace TemplateFunctionParamRemapTest {
3538*67e74705SXin Li
3539*67e74705SXin Li template <class T>
3540*67e74705SXin Li struct Cell {
3541*67e74705SXin Li T dummy_;
3542*67e74705SXin Li Mutex* mu_;
3543*67e74705SXin Li };
3544*67e74705SXin Li
3545*67e74705SXin Li class Foo {
3546*67e74705SXin Li public:
3547*67e74705SXin Li template <class T>
3548*67e74705SXin Li void elr(Cell<T>* c) __attribute__((exclusive_locks_required(c->mu_)));
3549*67e74705SXin Li
3550*67e74705SXin Li void test();
3551*67e74705SXin Li };
3552*67e74705SXin Li
3553*67e74705SXin Li template<class T>
elr(Cell<T> * c1)3554*67e74705SXin Li void Foo::elr(Cell<T>* c1) { }
3555*67e74705SXin Li
test()3556*67e74705SXin Li void Foo::test() {
3557*67e74705SXin Li Cell<int> cell;
3558*67e74705SXin Li elr(&cell); // \
3559*67e74705SXin Li // expected-warning {{calling function 'elr' requires holding mutex 'cell.mu_' exclusively}}
3560*67e74705SXin Li }
3561*67e74705SXin Li
3562*67e74705SXin Li
3563*67e74705SXin Li template<class T>
3564*67e74705SXin Li void globalELR(Cell<T>* c) __attribute__((exclusive_locks_required(c->mu_)));
3565*67e74705SXin Li
3566*67e74705SXin Li template<class T>
globalELR(Cell<T> * c1)3567*67e74705SXin Li void globalELR(Cell<T>* c1) { }
3568*67e74705SXin Li
globalTest()3569*67e74705SXin Li void globalTest() {
3570*67e74705SXin Li Cell<int> cell;
3571*67e74705SXin Li globalELR(&cell); // \
3572*67e74705SXin Li // expected-warning {{calling function 'globalELR' requires holding mutex 'cell.mu_' exclusively}}
3573*67e74705SXin Li }
3574*67e74705SXin Li
3575*67e74705SXin Li
3576*67e74705SXin Li template<class T>
3577*67e74705SXin Li void globalELR2(Cell<T>* c) __attribute__((exclusive_locks_required(c->mu_)));
3578*67e74705SXin Li
3579*67e74705SXin Li // second declaration
3580*67e74705SXin Li template<class T>
3581*67e74705SXin Li void globalELR2(Cell<T>* c2);
3582*67e74705SXin Li
3583*67e74705SXin Li template<class T>
globalELR2(Cell<T> * c3)3584*67e74705SXin Li void globalELR2(Cell<T>* c3) { }
3585*67e74705SXin Li
3586*67e74705SXin Li // re-declaration after definition
3587*67e74705SXin Li template<class T>
3588*67e74705SXin Li void globalELR2(Cell<T>* c4);
3589*67e74705SXin Li
globalTest2()3590*67e74705SXin Li void globalTest2() {
3591*67e74705SXin Li Cell<int> cell;
3592*67e74705SXin Li globalELR2(&cell); // \
3593*67e74705SXin Li // expected-warning {{calling function 'globalELR2' requires holding mutex 'cell.mu_' exclusively}}
3594*67e74705SXin Li }
3595*67e74705SXin Li
3596*67e74705SXin Li
3597*67e74705SXin Li template<class T>
3598*67e74705SXin Li class FooT {
3599*67e74705SXin Li public:
3600*67e74705SXin Li void elr(Cell<T>* c) __attribute__((exclusive_locks_required(c->mu_)));
3601*67e74705SXin Li };
3602*67e74705SXin Li
3603*67e74705SXin Li template<class T>
elr(Cell<T> * c1)3604*67e74705SXin Li void FooT<T>::elr(Cell<T>* c1) { }
3605*67e74705SXin Li
testFooT()3606*67e74705SXin Li void testFooT() {
3607*67e74705SXin Li Cell<int> cell;
3608*67e74705SXin Li FooT<int> foo;
3609*67e74705SXin Li foo.elr(&cell); // \
3610*67e74705SXin Li // expected-warning {{calling function 'elr' requires holding mutex 'cell.mu_' exclusively}}
3611*67e74705SXin Li }
3612*67e74705SXin Li
3613*67e74705SXin Li } // end namespace TemplateFunctionParamRemapTest
3614*67e74705SXin Li
3615*67e74705SXin Li
3616*67e74705SXin Li namespace SelfConstructorTest {
3617*67e74705SXin Li
3618*67e74705SXin Li class SelfLock {
3619*67e74705SXin Li public:
3620*67e74705SXin Li SelfLock() EXCLUSIVE_LOCK_FUNCTION(mu_);
3621*67e74705SXin Li ~SelfLock() UNLOCK_FUNCTION(mu_);
3622*67e74705SXin Li
3623*67e74705SXin Li void foo() EXCLUSIVE_LOCKS_REQUIRED(mu_);
3624*67e74705SXin Li
3625*67e74705SXin Li Mutex mu_;
3626*67e74705SXin Li };
3627*67e74705SXin Li
3628*67e74705SXin Li class LOCKABLE SelfLock2 {
3629*67e74705SXin Li public:
3630*67e74705SXin Li SelfLock2() EXCLUSIVE_LOCK_FUNCTION();
3631*67e74705SXin Li ~SelfLock2() UNLOCK_FUNCTION();
3632*67e74705SXin Li
3633*67e74705SXin Li void foo() EXCLUSIVE_LOCKS_REQUIRED(this);
3634*67e74705SXin Li };
3635*67e74705SXin Li
3636*67e74705SXin Li
test()3637*67e74705SXin Li void test() {
3638*67e74705SXin Li SelfLock s;
3639*67e74705SXin Li s.foo();
3640*67e74705SXin Li }
3641*67e74705SXin Li
test2()3642*67e74705SXin Li void test2() {
3643*67e74705SXin Li SelfLock2 s2;
3644*67e74705SXin Li s2.foo();
3645*67e74705SXin Li }
3646*67e74705SXin Li
3647*67e74705SXin Li } // end namespace SelfConstructorTest
3648*67e74705SXin Li
3649*67e74705SXin Li
3650*67e74705SXin Li namespace MultipleAttributeTest {
3651*67e74705SXin Li
3652*67e74705SXin Li class Foo {
3653*67e74705SXin Li Mutex mu1_;
3654*67e74705SXin Li Mutex mu2_;
3655*67e74705SXin Li int a GUARDED_BY(mu1_);
3656*67e74705SXin Li int b GUARDED_BY(mu2_);
3657*67e74705SXin Li int c GUARDED_BY(mu1_) GUARDED_BY(mu2_);
3658*67e74705SXin Li int* d PT_GUARDED_BY(mu1_) PT_GUARDED_BY(mu2_);
3659*67e74705SXin Li
3660*67e74705SXin Li void foo1() EXCLUSIVE_LOCKS_REQUIRED(mu1_)
3661*67e74705SXin Li EXCLUSIVE_LOCKS_REQUIRED(mu2_);
3662*67e74705SXin Li void foo2() SHARED_LOCKS_REQUIRED(mu1_)
3663*67e74705SXin Li SHARED_LOCKS_REQUIRED(mu2_);
3664*67e74705SXin Li void foo3() LOCKS_EXCLUDED(mu1_)
3665*67e74705SXin Li LOCKS_EXCLUDED(mu2_);
3666*67e74705SXin Li void lock() EXCLUSIVE_LOCK_FUNCTION(mu1_)
3667*67e74705SXin Li EXCLUSIVE_LOCK_FUNCTION(mu2_);
3668*67e74705SXin Li void readerlock() SHARED_LOCK_FUNCTION(mu1_)
3669*67e74705SXin Li SHARED_LOCK_FUNCTION(mu2_);
3670*67e74705SXin Li void unlock() UNLOCK_FUNCTION(mu1_)
3671*67e74705SXin Li UNLOCK_FUNCTION(mu2_);
3672*67e74705SXin Li bool trylock() EXCLUSIVE_TRYLOCK_FUNCTION(true, mu1_)
3673*67e74705SXin Li EXCLUSIVE_TRYLOCK_FUNCTION(true, mu2_);
3674*67e74705SXin Li bool readertrylock() SHARED_TRYLOCK_FUNCTION(true, mu1_)
3675*67e74705SXin Li SHARED_TRYLOCK_FUNCTION(true, mu2_);
3676*67e74705SXin Li void assertBoth() ASSERT_EXCLUSIVE_LOCK(mu1_)
3677*67e74705SXin Li ASSERT_EXCLUSIVE_LOCK(mu2_);
3678*67e74705SXin Li void assertShared() ASSERT_SHARED_LOCK(mu1_)
3679*67e74705SXin Li ASSERT_SHARED_LOCK(mu2_);
3680*67e74705SXin Li
3681*67e74705SXin Li void test();
3682*67e74705SXin Li void testAssert();
3683*67e74705SXin Li void testAssertShared();
3684*67e74705SXin Li };
3685*67e74705SXin Li
3686*67e74705SXin Li
foo1()3687*67e74705SXin Li void Foo::foo1() {
3688*67e74705SXin Li a = 1;
3689*67e74705SXin Li b = 2;
3690*67e74705SXin Li }
3691*67e74705SXin Li
foo2()3692*67e74705SXin Li void Foo::foo2() {
3693*67e74705SXin Li int result = a + b;
3694*67e74705SXin Li }
3695*67e74705SXin Li
foo3()3696*67e74705SXin Li void Foo::foo3() { }
lock()3697*67e74705SXin Li void Foo::lock() { mu1_.Lock(); mu2_.Lock(); }
readerlock()3698*67e74705SXin Li void Foo::readerlock() { mu1_.ReaderLock(); mu2_.ReaderLock(); }
unlock()3699*67e74705SXin Li void Foo::unlock() { mu1_.Unlock(); mu2_.Unlock(); }
trylock()3700*67e74705SXin Li bool Foo::trylock() { return true; }
readertrylock()3701*67e74705SXin Li bool Foo::readertrylock() { return true; }
3702*67e74705SXin Li
3703*67e74705SXin Li
test()3704*67e74705SXin Li void Foo::test() {
3705*67e74705SXin Li mu1_.Lock();
3706*67e74705SXin Li foo1(); // expected-warning {{}}
3707*67e74705SXin Li c = 0; // expected-warning {{}}
3708*67e74705SXin Li *d = 0; // expected-warning {{}}
3709*67e74705SXin Li mu1_.Unlock();
3710*67e74705SXin Li
3711*67e74705SXin Li mu1_.ReaderLock();
3712*67e74705SXin Li foo2(); // expected-warning {{}}
3713*67e74705SXin Li int x = c; // expected-warning {{}}
3714*67e74705SXin Li int y = *d; // expected-warning {{}}
3715*67e74705SXin Li mu1_.Unlock();
3716*67e74705SXin Li
3717*67e74705SXin Li mu2_.Lock();
3718*67e74705SXin Li foo3(); // expected-warning {{}}
3719*67e74705SXin Li mu2_.Unlock();
3720*67e74705SXin Li
3721*67e74705SXin Li lock();
3722*67e74705SXin Li a = 0;
3723*67e74705SXin Li b = 0;
3724*67e74705SXin Li unlock();
3725*67e74705SXin Li
3726*67e74705SXin Li readerlock();
3727*67e74705SXin Li int z = a + b;
3728*67e74705SXin Li unlock();
3729*67e74705SXin Li
3730*67e74705SXin Li if (trylock()) {
3731*67e74705SXin Li a = 0;
3732*67e74705SXin Li b = 0;
3733*67e74705SXin Li unlock();
3734*67e74705SXin Li }
3735*67e74705SXin Li
3736*67e74705SXin Li if (readertrylock()) {
3737*67e74705SXin Li int zz = a + b;
3738*67e74705SXin Li unlock();
3739*67e74705SXin Li }
3740*67e74705SXin Li }
3741*67e74705SXin Li
3742*67e74705SXin Li // Force duplication of attributes
assertBoth()3743*67e74705SXin Li void Foo::assertBoth() { }
assertShared()3744*67e74705SXin Li void Foo::assertShared() { }
3745*67e74705SXin Li
testAssert()3746*67e74705SXin Li void Foo::testAssert() {
3747*67e74705SXin Li assertBoth();
3748*67e74705SXin Li a = 0;
3749*67e74705SXin Li b = 0;
3750*67e74705SXin Li }
3751*67e74705SXin Li
testAssertShared()3752*67e74705SXin Li void Foo::testAssertShared() {
3753*67e74705SXin Li assertShared();
3754*67e74705SXin Li int zz = a + b;
3755*67e74705SXin Li }
3756*67e74705SXin Li
3757*67e74705SXin Li
3758*67e74705SXin Li } // end namespace MultipleAttributeTest
3759*67e74705SXin Li
3760*67e74705SXin Li
3761*67e74705SXin Li namespace GuardedNonPrimitiveTypeTest {
3762*67e74705SXin Li
3763*67e74705SXin Li
3764*67e74705SXin Li class Data {
3765*67e74705SXin Li public:
Data(int i)3766*67e74705SXin Li Data(int i) : dat(i) { }
3767*67e74705SXin Li
getValue() const3768*67e74705SXin Li int getValue() const { return dat; }
setValue(int i)3769*67e74705SXin Li void setValue(int i) { dat = i; }
3770*67e74705SXin Li
operator [](int i) const3771*67e74705SXin Li int operator[](int i) const { return dat; }
operator [](int i)3772*67e74705SXin Li int& operator[](int i) { return dat; }
3773*67e74705SXin Li
operator ()()3774*67e74705SXin Li void operator()() { }
3775*67e74705SXin Li
3776*67e74705SXin Li private:
3777*67e74705SXin Li int dat;
3778*67e74705SXin Li };
3779*67e74705SXin Li
3780*67e74705SXin Li
3781*67e74705SXin Li class DataCell {
3782*67e74705SXin Li public:
DataCell(const Data & d)3783*67e74705SXin Li DataCell(const Data& d) : dat(d) { }
3784*67e74705SXin Li
3785*67e74705SXin Li private:
3786*67e74705SXin Li Data dat;
3787*67e74705SXin Li };
3788*67e74705SXin Li
3789*67e74705SXin Li
3790*67e74705SXin Li void showDataCell(const DataCell& dc);
3791*67e74705SXin Li
3792*67e74705SXin Li
3793*67e74705SXin Li class Foo {
3794*67e74705SXin Li public:
3795*67e74705SXin Li // method call tests
test()3796*67e74705SXin Li void test() {
3797*67e74705SXin Li data_.setValue(0); // FIXME -- should be writing \
3798*67e74705SXin Li // expected-warning {{reading variable 'data_' requires holding mutex 'mu_'}}
3799*67e74705SXin Li int a = data_.getValue(); // \
3800*67e74705SXin Li // expected-warning {{reading variable 'data_' requires holding mutex 'mu_'}}
3801*67e74705SXin Li
3802*67e74705SXin Li datap1_->setValue(0); // FIXME -- should be writing \
3803*67e74705SXin Li // expected-warning {{reading variable 'datap1_' requires holding mutex 'mu_'}}
3804*67e74705SXin Li a = datap1_->getValue(); // \
3805*67e74705SXin Li // expected-warning {{reading variable 'datap1_' requires holding mutex 'mu_'}}
3806*67e74705SXin Li
3807*67e74705SXin Li datap2_->setValue(0); // FIXME -- should be writing \
3808*67e74705SXin Li // expected-warning {{reading the value pointed to by 'datap2_' requires holding mutex 'mu_'}}
3809*67e74705SXin Li a = datap2_->getValue(); // \
3810*67e74705SXin Li // expected-warning {{reading the value pointed to by 'datap2_' requires holding mutex 'mu_'}}
3811*67e74705SXin Li
3812*67e74705SXin Li (*datap2_).setValue(0); // FIXME -- should be writing \
3813*67e74705SXin Li // expected-warning {{reading the value pointed to by 'datap2_' requires holding mutex 'mu_'}}
3814*67e74705SXin Li a = (*datap2_).getValue(); // \
3815*67e74705SXin Li // expected-warning {{reading the value pointed to by 'datap2_' requires holding mutex 'mu_'}}
3816*67e74705SXin Li
3817*67e74705SXin Li mu_.Lock();
3818*67e74705SXin Li data_.setValue(1);
3819*67e74705SXin Li datap1_->setValue(1);
3820*67e74705SXin Li datap2_->setValue(1);
3821*67e74705SXin Li mu_.Unlock();
3822*67e74705SXin Li
3823*67e74705SXin Li mu_.ReaderLock();
3824*67e74705SXin Li a = data_.getValue();
3825*67e74705SXin Li datap1_->setValue(0); // reads datap1_, writes *datap1_
3826*67e74705SXin Li a = datap1_->getValue();
3827*67e74705SXin Li a = datap2_->getValue();
3828*67e74705SXin Li mu_.Unlock();
3829*67e74705SXin Li }
3830*67e74705SXin Li
3831*67e74705SXin Li // operator tests
test2()3832*67e74705SXin Li void test2() {
3833*67e74705SXin Li data_ = Data(1); // expected-warning {{writing variable 'data_' requires holding mutex 'mu_' exclusively}}
3834*67e74705SXin Li *datap1_ = data_; // expected-warning {{reading variable 'datap1_' requires holding mutex 'mu_'}} \
3835*67e74705SXin Li // expected-warning {{reading variable 'data_' requires holding mutex 'mu_'}}
3836*67e74705SXin Li *datap2_ = data_; // expected-warning {{writing the value pointed to by 'datap2_' requires holding mutex 'mu_' exclusively}} \
3837*67e74705SXin Li // expected-warning {{reading variable 'data_' requires holding mutex 'mu_'}}
3838*67e74705SXin Li data_ = *datap1_; // expected-warning {{writing variable 'data_' requires holding mutex 'mu_' exclusively}} \
3839*67e74705SXin Li // expected-warning {{reading variable 'datap1_' requires holding mutex 'mu_'}}
3840*67e74705SXin Li data_ = *datap2_; // expected-warning {{writing variable 'data_' requires holding mutex 'mu_' exclusively}} \
3841*67e74705SXin Li // expected-warning {{reading the value pointed to by 'datap2_' requires holding mutex 'mu_'}}
3842*67e74705SXin Li
3843*67e74705SXin Li data_[0] = 0; // expected-warning {{reading variable 'data_' requires holding mutex 'mu_'}}
3844*67e74705SXin Li (*datap2_)[0] = 0; // expected-warning {{reading the value pointed to by 'datap2_' requires holding mutex 'mu_'}}
3845*67e74705SXin Li
3846*67e74705SXin Li data_(); // expected-warning {{reading variable 'data_' requires holding mutex 'mu_'}}
3847*67e74705SXin Li }
3848*67e74705SXin Li
3849*67e74705SXin Li // const operator tests
test3() const3850*67e74705SXin Li void test3() const {
3851*67e74705SXin Li Data mydat(data_); // expected-warning {{reading variable 'data_' requires holding mutex 'mu_'}}
3852*67e74705SXin Li
3853*67e74705SXin Li //FIXME
3854*67e74705SXin Li //showDataCell(data_); // xpected-warning {{reading variable 'data_' requires holding mutex 'mu_'}}
3855*67e74705SXin Li //showDataCell(*datap2_); // xpected-warning {{reading the value pointed to by 'datap2_' requires holding mutex 'mu_'}}
3856*67e74705SXin Li
3857*67e74705SXin Li int a = data_[0]; // expected-warning {{reading variable 'data_' requires holding mutex 'mu_'}}
3858*67e74705SXin Li }
3859*67e74705SXin Li
3860*67e74705SXin Li private:
3861*67e74705SXin Li Mutex mu_;
3862*67e74705SXin Li Data data_ GUARDED_BY(mu_);
3863*67e74705SXin Li Data* datap1_ GUARDED_BY(mu_);
3864*67e74705SXin Li Data* datap2_ PT_GUARDED_BY(mu_);
3865*67e74705SXin Li };
3866*67e74705SXin Li
3867*67e74705SXin Li } // end namespace GuardedNonPrimitiveTypeTest
3868*67e74705SXin Li
3869*67e74705SXin Li
3870*67e74705SXin Li namespace GuardedNonPrimitive_MemberAccess {
3871*67e74705SXin Li
3872*67e74705SXin Li class Cell {
3873*67e74705SXin Li public:
3874*67e74705SXin Li Cell(int i);
3875*67e74705SXin Li
3876*67e74705SXin Li void cellMethod();
3877*67e74705SXin Li
3878*67e74705SXin Li int a;
3879*67e74705SXin Li };
3880*67e74705SXin Li
3881*67e74705SXin Li
3882*67e74705SXin Li class Foo {
3883*67e74705SXin Li public:
3884*67e74705SXin Li int a;
3885*67e74705SXin Li Cell c GUARDED_BY(cell_mu_);
3886*67e74705SXin Li Cell* cp PT_GUARDED_BY(cell_mu_);
3887*67e74705SXin Li
3888*67e74705SXin Li void myMethod();
3889*67e74705SXin Li
3890*67e74705SXin Li Mutex cell_mu_;
3891*67e74705SXin Li };
3892*67e74705SXin Li
3893*67e74705SXin Li
3894*67e74705SXin Li class Bar {
3895*67e74705SXin Li private:
3896*67e74705SXin Li Mutex mu_;
3897*67e74705SXin Li Foo foo GUARDED_BY(mu_);
3898*67e74705SXin Li Foo* foop PT_GUARDED_BY(mu_);
3899*67e74705SXin Li
test()3900*67e74705SXin Li void test() {
3901*67e74705SXin Li foo.myMethod(); // expected-warning {{reading variable 'foo' requires holding mutex 'mu_'}}
3902*67e74705SXin Li
3903*67e74705SXin Li int fa = foo.a; // expected-warning {{reading variable 'foo' requires holding mutex 'mu_'}}
3904*67e74705SXin Li foo.a = fa; // expected-warning {{writing variable 'foo' requires holding mutex 'mu_' exclusively}}
3905*67e74705SXin Li
3906*67e74705SXin Li fa = foop->a; // expected-warning {{reading the value pointed to by 'foop' requires holding mutex 'mu_'}}
3907*67e74705SXin Li foop->a = fa; // expected-warning {{writing the value pointed to by 'foop' requires holding mutex 'mu_' exclusively}}
3908*67e74705SXin Li
3909*67e74705SXin Li fa = (*foop).a; // expected-warning {{reading the value pointed to by 'foop' requires holding mutex 'mu_'}}
3910*67e74705SXin Li (*foop).a = fa; // expected-warning {{writing the value pointed to by 'foop' requires holding mutex 'mu_' exclusively}}
3911*67e74705SXin Li
3912*67e74705SXin Li foo.c = Cell(0); // expected-warning {{writing variable 'foo' requires holding mutex 'mu_'}} \
3913*67e74705SXin Li // expected-warning {{writing variable 'c' requires holding mutex 'foo.cell_mu_' exclusively}}
3914*67e74705SXin Li foo.c.cellMethod(); // expected-warning {{reading variable 'foo' requires holding mutex 'mu_'}} \
3915*67e74705SXin Li // expected-warning {{reading variable 'c' requires holding mutex 'foo.cell_mu_'}}
3916*67e74705SXin Li
3917*67e74705SXin Li foop->c = Cell(0); // expected-warning {{writing the value pointed to by 'foop' requires holding mutex 'mu_'}} \
3918*67e74705SXin Li // expected-warning {{writing variable 'c' requires holding mutex 'foop->cell_mu_' exclusively}}
3919*67e74705SXin Li foop->c.cellMethod(); // expected-warning {{reading the value pointed to by 'foop' requires holding mutex 'mu_'}} \
3920*67e74705SXin Li // expected-warning {{reading variable 'c' requires holding mutex 'foop->cell_mu_'}}
3921*67e74705SXin Li
3922*67e74705SXin Li (*foop).c = Cell(0); // expected-warning {{writing the value pointed to by 'foop' requires holding mutex 'mu_'}} \
3923*67e74705SXin Li // expected-warning {{writing variable 'c' requires holding mutex 'foop->cell_mu_' exclusively}}
3924*67e74705SXin Li (*foop).c.cellMethod(); // expected-warning {{reading the value pointed to by 'foop' requires holding mutex 'mu_'}} \
3925*67e74705SXin Li // expected-warning {{reading variable 'c' requires holding mutex 'foop->cell_mu_'}}
3926*67e74705SXin Li };
3927*67e74705SXin Li };
3928*67e74705SXin Li
3929*67e74705SXin Li } // namespace GuardedNonPrimitive_MemberAccess
3930*67e74705SXin Li
3931*67e74705SXin Li
3932*67e74705SXin Li namespace TestThrowExpr {
3933*67e74705SXin Li
3934*67e74705SXin Li class Foo {
3935*67e74705SXin Li Mutex mu_;
3936*67e74705SXin Li
3937*67e74705SXin Li bool hasError();
3938*67e74705SXin Li
test()3939*67e74705SXin Li void test() {
3940*67e74705SXin Li mu_.Lock();
3941*67e74705SXin Li if (hasError()) {
3942*67e74705SXin Li throw "ugly";
3943*67e74705SXin Li }
3944*67e74705SXin Li mu_.Unlock();
3945*67e74705SXin Li }
3946*67e74705SXin Li };
3947*67e74705SXin Li
3948*67e74705SXin Li } // end namespace TestThrowExpr
3949*67e74705SXin Li
3950*67e74705SXin Li
3951*67e74705SXin Li namespace UnevaluatedContextTest {
3952*67e74705SXin Li
3953*67e74705SXin Li // parse attribute expressions in an unevaluated context.
3954*67e74705SXin Li
3955*67e74705SXin Li static inline Mutex* getMutex1();
3956*67e74705SXin Li static inline Mutex* getMutex2();
3957*67e74705SXin Li
3958*67e74705SXin Li void bar() EXCLUSIVE_LOCKS_REQUIRED(getMutex1());
3959*67e74705SXin Li
3960*67e74705SXin Li void bar2() EXCLUSIVE_LOCKS_REQUIRED(getMutex1(), getMutex2());
3961*67e74705SXin Li
3962*67e74705SXin Li } // end namespace UnevaluatedContextTest
3963*67e74705SXin Li
3964*67e74705SXin Li
3965*67e74705SXin Li namespace LockUnlockFunctionTest {
3966*67e74705SXin Li
3967*67e74705SXin Li // Check built-in lock functions
3968*67e74705SXin Li class LOCKABLE MyLockable {
3969*67e74705SXin Li public:
lock()3970*67e74705SXin Li void lock() EXCLUSIVE_LOCK_FUNCTION() { mu_.Lock(); }
readerLock()3971*67e74705SXin Li void readerLock() SHARED_LOCK_FUNCTION() { mu_.ReaderLock(); }
unlock()3972*67e74705SXin Li void unlock() UNLOCK_FUNCTION() { mu_.Unlock(); }
3973*67e74705SXin Li
3974*67e74705SXin Li private:
3975*67e74705SXin Li Mutex mu_;
3976*67e74705SXin Li };
3977*67e74705SXin Li
3978*67e74705SXin Li
3979*67e74705SXin Li class Foo {
3980*67e74705SXin Li public:
3981*67e74705SXin Li // Correct lock/unlock functions
lock()3982*67e74705SXin Li void lock() EXCLUSIVE_LOCK_FUNCTION(mu_) {
3983*67e74705SXin Li mu_.Lock();
3984*67e74705SXin Li }
3985*67e74705SXin Li
readerLock()3986*67e74705SXin Li void readerLock() SHARED_LOCK_FUNCTION(mu_) {
3987*67e74705SXin Li mu_.ReaderLock();
3988*67e74705SXin Li }
3989*67e74705SXin Li
unlock()3990*67e74705SXin Li void unlock() UNLOCK_FUNCTION(mu_) {
3991*67e74705SXin Li mu_.Unlock();
3992*67e74705SXin Li }
3993*67e74705SXin Li
3994*67e74705SXin Li // Check failure to lock.
lockBad()3995*67e74705SXin Li void lockBad() EXCLUSIVE_LOCK_FUNCTION(mu_) { // expected-note {{mutex acquired here}}
3996*67e74705SXin Li mu2_.Lock();
3997*67e74705SXin Li mu2_.Unlock();
3998*67e74705SXin Li } // expected-warning {{expecting mutex 'mu_' to be held at the end of function}}
3999*67e74705SXin Li
readerLockBad()4000*67e74705SXin Li void readerLockBad() SHARED_LOCK_FUNCTION(mu_) { // expected-note {{mutex acquired here}}
4001*67e74705SXin Li mu2_.Lock();
4002*67e74705SXin Li mu2_.Unlock();
4003*67e74705SXin Li } // expected-warning {{expecting mutex 'mu_' to be held at the end of function}}
4004*67e74705SXin Li
unlockBad()4005*67e74705SXin Li void unlockBad() UNLOCK_FUNCTION(mu_) { // expected-note {{mutex acquired here}}
4006*67e74705SXin Li mu2_.Lock();
4007*67e74705SXin Li mu2_.Unlock();
4008*67e74705SXin Li } // expected-warning {{mutex 'mu_' is still held at the end of function}}
4009*67e74705SXin Li
4010*67e74705SXin Li // Check locking the wrong thing.
lockBad2()4011*67e74705SXin Li void lockBad2() EXCLUSIVE_LOCK_FUNCTION(mu_) { // expected-note {{mutex acquired here}}
4012*67e74705SXin Li mu2_.Lock(); // expected-note {{mutex acquired here}}
4013*67e74705SXin Li } // expected-warning {{expecting mutex 'mu_' to be held at the end of function}} \
4014*67e74705SXin Li // expected-warning {{mutex 'mu2_' is still held at the end of function}}
4015*67e74705SXin Li
4016*67e74705SXin Li
readerLockBad2()4017*67e74705SXin Li void readerLockBad2() SHARED_LOCK_FUNCTION(mu_) { // expected-note {{mutex acquired here}}
4018*67e74705SXin Li mu2_.ReaderLock(); // expected-note {{mutex acquired here}}
4019*67e74705SXin Li } // expected-warning {{expecting mutex 'mu_' to be held at the end of function}} \
4020*67e74705SXin Li // expected-warning {{mutex 'mu2_' is still held at the end of function}}
4021*67e74705SXin Li
4022*67e74705SXin Li
unlockBad2()4023*67e74705SXin Li void unlockBad2() UNLOCK_FUNCTION(mu_) { // expected-note {{mutex acquired here}}
4024*67e74705SXin Li mu2_.Unlock(); // expected-warning {{releasing mutex 'mu2_' that was not held}}
4025*67e74705SXin Li } // expected-warning {{mutex 'mu_' is still held at the end of function}}
4026*67e74705SXin Li
4027*67e74705SXin Li private:
4028*67e74705SXin Li Mutex mu_;
4029*67e74705SXin Li Mutex mu2_;
4030*67e74705SXin Li };
4031*67e74705SXin Li
4032*67e74705SXin Li } // end namespace LockUnlockFunctionTest
4033*67e74705SXin Li
4034*67e74705SXin Li
4035*67e74705SXin Li namespace AssertHeldTest {
4036*67e74705SXin Li
4037*67e74705SXin Li class Foo {
4038*67e74705SXin Li public:
4039*67e74705SXin Li int c;
4040*67e74705SXin Li int a GUARDED_BY(mu_);
4041*67e74705SXin Li Mutex mu_;
4042*67e74705SXin Li
test1()4043*67e74705SXin Li void test1() {
4044*67e74705SXin Li mu_.AssertHeld();
4045*67e74705SXin Li int b = a;
4046*67e74705SXin Li a = 0;
4047*67e74705SXin Li }
4048*67e74705SXin Li
test2()4049*67e74705SXin Li void test2() {
4050*67e74705SXin Li mu_.AssertReaderHeld();
4051*67e74705SXin Li int b = a;
4052*67e74705SXin Li a = 0; // expected-warning {{writing variable 'a' requires holding mutex 'mu_' exclusively}}
4053*67e74705SXin Li }
4054*67e74705SXin Li
test3()4055*67e74705SXin Li void test3() {
4056*67e74705SXin Li if (c) {
4057*67e74705SXin Li mu_.AssertHeld();
4058*67e74705SXin Li }
4059*67e74705SXin Li else {
4060*67e74705SXin Li mu_.AssertHeld();
4061*67e74705SXin Li }
4062*67e74705SXin Li int b = a;
4063*67e74705SXin Li a = 0;
4064*67e74705SXin Li }
4065*67e74705SXin Li
test4()4066*67e74705SXin Li void test4() EXCLUSIVE_LOCKS_REQUIRED(mu_) {
4067*67e74705SXin Li mu_.AssertHeld();
4068*67e74705SXin Li int b = a;
4069*67e74705SXin Li a = 0;
4070*67e74705SXin Li }
4071*67e74705SXin Li
test5()4072*67e74705SXin Li void test5() UNLOCK_FUNCTION(mu_) {
4073*67e74705SXin Li mu_.AssertHeld();
4074*67e74705SXin Li mu_.Unlock();
4075*67e74705SXin Li }
4076*67e74705SXin Li
test6()4077*67e74705SXin Li void test6() {
4078*67e74705SXin Li mu_.AssertHeld();
4079*67e74705SXin Li mu_.Unlock();
4080*67e74705SXin Li } // should this be a warning?
4081*67e74705SXin Li
test7()4082*67e74705SXin Li void test7() {
4083*67e74705SXin Li if (c) {
4084*67e74705SXin Li mu_.AssertHeld();
4085*67e74705SXin Li }
4086*67e74705SXin Li else {
4087*67e74705SXin Li mu_.Lock();
4088*67e74705SXin Li }
4089*67e74705SXin Li int b = a;
4090*67e74705SXin Li a = 0;
4091*67e74705SXin Li mu_.Unlock();
4092*67e74705SXin Li }
4093*67e74705SXin Li
test8()4094*67e74705SXin Li void test8() {
4095*67e74705SXin Li if (c) {
4096*67e74705SXin Li mu_.Lock();
4097*67e74705SXin Li }
4098*67e74705SXin Li else {
4099*67e74705SXin Li mu_.AssertHeld();
4100*67e74705SXin Li }
4101*67e74705SXin Li int b = a;
4102*67e74705SXin Li a = 0;
4103*67e74705SXin Li mu_.Unlock();
4104*67e74705SXin Li }
4105*67e74705SXin Li
test9()4106*67e74705SXin Li void test9() {
4107*67e74705SXin Li if (c) {
4108*67e74705SXin Li mu_.AssertHeld();
4109*67e74705SXin Li }
4110*67e74705SXin Li else {
4111*67e74705SXin Li mu_.Lock(); // expected-note {{mutex acquired here}}
4112*67e74705SXin Li }
4113*67e74705SXin Li } // expected-warning {{mutex 'mu_' is still held at the end of function}}
4114*67e74705SXin Li
test10()4115*67e74705SXin Li void test10() {
4116*67e74705SXin Li if (c) {
4117*67e74705SXin Li mu_.Lock(); // expected-note {{mutex acquired here}}
4118*67e74705SXin Li }
4119*67e74705SXin Li else {
4120*67e74705SXin Li mu_.AssertHeld();
4121*67e74705SXin Li }
4122*67e74705SXin Li } // expected-warning {{mutex 'mu_' is still held at the end of function}}
4123*67e74705SXin Li
4124*67e74705SXin Li void assertMu() ASSERT_EXCLUSIVE_LOCK(mu_);
4125*67e74705SXin Li
test11()4126*67e74705SXin Li void test11() {
4127*67e74705SXin Li assertMu();
4128*67e74705SXin Li int b = a;
4129*67e74705SXin Li a = 0;
4130*67e74705SXin Li }
4131*67e74705SXin Li };
4132*67e74705SXin Li
4133*67e74705SXin Li } // end namespace AssertHeldTest
4134*67e74705SXin Li
4135*67e74705SXin Li
4136*67e74705SXin Li namespace LogicalConditionalTryLock {
4137*67e74705SXin Li
4138*67e74705SXin Li class Foo {
4139*67e74705SXin Li public:
4140*67e74705SXin Li Mutex mu;
4141*67e74705SXin Li int a GUARDED_BY(mu);
4142*67e74705SXin Li bool c;
4143*67e74705SXin Li
4144*67e74705SXin Li bool newc();
4145*67e74705SXin Li
test1()4146*67e74705SXin Li void test1() {
4147*67e74705SXin Li if (c && mu.TryLock()) {
4148*67e74705SXin Li a = 0;
4149*67e74705SXin Li mu.Unlock();
4150*67e74705SXin Li }
4151*67e74705SXin Li }
4152*67e74705SXin Li
test2()4153*67e74705SXin Li void test2() {
4154*67e74705SXin Li bool b = mu.TryLock();
4155*67e74705SXin Li if (c && b) {
4156*67e74705SXin Li a = 0;
4157*67e74705SXin Li mu.Unlock();
4158*67e74705SXin Li }
4159*67e74705SXin Li }
4160*67e74705SXin Li
test3()4161*67e74705SXin Li void test3() {
4162*67e74705SXin Li if (c || !mu.TryLock())
4163*67e74705SXin Li return;
4164*67e74705SXin Li a = 0;
4165*67e74705SXin Li mu.Unlock();
4166*67e74705SXin Li }
4167*67e74705SXin Li
test4()4168*67e74705SXin Li void test4() {
4169*67e74705SXin Li while (c && mu.TryLock()) {
4170*67e74705SXin Li a = 0;
4171*67e74705SXin Li c = newc();
4172*67e74705SXin Li mu.Unlock();
4173*67e74705SXin Li }
4174*67e74705SXin Li }
4175*67e74705SXin Li
test5()4176*67e74705SXin Li void test5() {
4177*67e74705SXin Li while (c) {
4178*67e74705SXin Li if (newc() || !mu.TryLock())
4179*67e74705SXin Li break;
4180*67e74705SXin Li a = 0;
4181*67e74705SXin Li mu.Unlock();
4182*67e74705SXin Li }
4183*67e74705SXin Li }
4184*67e74705SXin Li
test6()4185*67e74705SXin Li void test6() {
4186*67e74705SXin Li mu.Lock();
4187*67e74705SXin Li do {
4188*67e74705SXin Li a = 0;
4189*67e74705SXin Li mu.Unlock();
4190*67e74705SXin Li } while (newc() && mu.TryLock());
4191*67e74705SXin Li }
4192*67e74705SXin Li
test7()4193*67e74705SXin Li void test7() {
4194*67e74705SXin Li for (bool b = mu.TryLock(); c && b;) {
4195*67e74705SXin Li a = 0;
4196*67e74705SXin Li mu.Unlock();
4197*67e74705SXin Li }
4198*67e74705SXin Li }
4199*67e74705SXin Li
test8()4200*67e74705SXin Li void test8() {
4201*67e74705SXin Li if (c && newc() && mu.TryLock()) {
4202*67e74705SXin Li a = 0;
4203*67e74705SXin Li mu.Unlock();
4204*67e74705SXin Li }
4205*67e74705SXin Li }
4206*67e74705SXin Li
test9()4207*67e74705SXin Li void test9() {
4208*67e74705SXin Li if (!(c && newc() && mu.TryLock()))
4209*67e74705SXin Li return;
4210*67e74705SXin Li a = 0;
4211*67e74705SXin Li mu.Unlock();
4212*67e74705SXin Li }
4213*67e74705SXin Li
test10()4214*67e74705SXin Li void test10() {
4215*67e74705SXin Li if (!(c || !mu.TryLock())) {
4216*67e74705SXin Li a = 0;
4217*67e74705SXin Li mu.Unlock();
4218*67e74705SXin Li }
4219*67e74705SXin Li }
4220*67e74705SXin Li };
4221*67e74705SXin Li
4222*67e74705SXin Li } // end namespace LogicalConditionalTryLock
4223*67e74705SXin Li
4224*67e74705SXin Li
4225*67e74705SXin Li
4226*67e74705SXin Li namespace PtGuardedByTest {
4227*67e74705SXin Li
4228*67e74705SXin Li void doSomething();
4229*67e74705SXin Li
4230*67e74705SXin Li class Cell {
4231*67e74705SXin Li public:
4232*67e74705SXin Li int a;
4233*67e74705SXin Li };
4234*67e74705SXin Li
4235*67e74705SXin Li
4236*67e74705SXin Li // This mainly duplicates earlier tests, but just to make sure...
4237*67e74705SXin Li class PtGuardedBySanityTest {
4238*67e74705SXin Li Mutex mu1;
4239*67e74705SXin Li Mutex mu2;
4240*67e74705SXin Li int* a GUARDED_BY(mu1) PT_GUARDED_BY(mu2);
4241*67e74705SXin Li Cell* c GUARDED_BY(mu1) PT_GUARDED_BY(mu2);
4242*67e74705SXin Li int sa[10] GUARDED_BY(mu1);
4243*67e74705SXin Li Cell sc[10] GUARDED_BY(mu1);
4244*67e74705SXin Li
test1()4245*67e74705SXin Li void test1() {
4246*67e74705SXin Li mu1.Lock();
4247*67e74705SXin Li if (a == 0) doSomething(); // OK, we don't dereference.
4248*67e74705SXin Li a = 0;
4249*67e74705SXin Li c = 0;
4250*67e74705SXin Li if (sa[0] == 42) doSomething();
4251*67e74705SXin Li sa[0] = 57;
4252*67e74705SXin Li if (sc[0].a == 42) doSomething();
4253*67e74705SXin Li sc[0].a = 57;
4254*67e74705SXin Li mu1.Unlock();
4255*67e74705SXin Li }
4256*67e74705SXin Li
test2()4257*67e74705SXin Li void test2() {
4258*67e74705SXin Li mu1.ReaderLock();
4259*67e74705SXin Li if (*a == 0) doSomething(); // expected-warning {{reading the value pointed to by 'a' requires holding mutex 'mu2'}}
4260*67e74705SXin Li *a = 0; // expected-warning {{writing the value pointed to by 'a' requires holding mutex 'mu2' exclusively}}
4261*67e74705SXin Li
4262*67e74705SXin Li if (c->a == 0) doSomething(); // expected-warning {{reading the value pointed to by 'c' requires holding mutex 'mu2'}}
4263*67e74705SXin Li c->a = 0; // expected-warning {{writing the value pointed to by 'c' requires holding mutex 'mu2' exclusively}}
4264*67e74705SXin Li
4265*67e74705SXin Li if ((*c).a == 0) doSomething(); // expected-warning {{reading the value pointed to by 'c' requires holding mutex 'mu2'}}
4266*67e74705SXin Li (*c).a = 0; // expected-warning {{writing the value pointed to by 'c' requires holding mutex 'mu2' exclusively}}
4267*67e74705SXin Li
4268*67e74705SXin Li if (a[0] == 42) doSomething(); // expected-warning {{reading the value pointed to by 'a' requires holding mutex 'mu2'}}
4269*67e74705SXin Li a[0] = 57; // expected-warning {{writing the value pointed to by 'a' requires holding mutex 'mu2' exclusively}}
4270*67e74705SXin Li if (c[0].a == 42) doSomething(); // expected-warning {{reading the value pointed to by 'c' requires holding mutex 'mu2'}}
4271*67e74705SXin Li c[0].a = 57; // expected-warning {{writing the value pointed to by 'c' requires holding mutex 'mu2' exclusively}}
4272*67e74705SXin Li mu1.Unlock();
4273*67e74705SXin Li }
4274*67e74705SXin Li
test3()4275*67e74705SXin Li void test3() {
4276*67e74705SXin Li mu2.Lock();
4277*67e74705SXin Li if (*a == 0) doSomething(); // expected-warning {{reading variable 'a' requires holding mutex 'mu1'}}
4278*67e74705SXin Li *a = 0; // expected-warning {{reading variable 'a' requires holding mutex 'mu1'}}
4279*67e74705SXin Li
4280*67e74705SXin Li if (c->a == 0) doSomething(); // expected-warning {{reading variable 'c' requires holding mutex 'mu1'}}
4281*67e74705SXin Li c->a = 0; // expected-warning {{reading variable 'c' requires holding mutex 'mu1'}}
4282*67e74705SXin Li
4283*67e74705SXin Li if ((*c).a == 0) doSomething(); // expected-warning {{reading variable 'c' requires holding mutex 'mu1'}}
4284*67e74705SXin Li (*c).a = 0; // expected-warning {{reading variable 'c' requires holding mutex 'mu1'}}
4285*67e74705SXin Li
4286*67e74705SXin Li if (a[0] == 42) doSomething(); // expected-warning {{reading variable 'a' requires holding mutex 'mu1'}}
4287*67e74705SXin Li a[0] = 57; // expected-warning {{reading variable 'a' requires holding mutex 'mu1'}}
4288*67e74705SXin Li if (c[0].a == 42) doSomething(); // expected-warning {{reading variable 'c' requires holding mutex 'mu1'}}
4289*67e74705SXin Li c[0].a = 57; // expected-warning {{reading variable 'c' requires holding mutex 'mu1'}}
4290*67e74705SXin Li mu2.Unlock();
4291*67e74705SXin Li }
4292*67e74705SXin Li
test4()4293*67e74705SXin Li void test4() { // Literal arrays
4294*67e74705SXin Li if (sa[0] == 42) doSomething(); // expected-warning {{reading variable 'sa' requires holding mutex 'mu1'}}
4295*67e74705SXin Li sa[0] = 57; // expected-warning {{writing variable 'sa' requires holding mutex 'mu1' exclusively}}
4296*67e74705SXin Li if (sc[0].a == 42) doSomething(); // expected-warning {{reading variable 'sc' requires holding mutex 'mu1'}}
4297*67e74705SXin Li sc[0].a = 57; // expected-warning {{writing variable 'sc' requires holding mutex 'mu1' exclusively}}
4298*67e74705SXin Li
4299*67e74705SXin Li if (*sa == 42) doSomething(); // expected-warning {{reading variable 'sa' requires holding mutex 'mu1'}}
4300*67e74705SXin Li *sa = 57; // expected-warning {{writing variable 'sa' requires holding mutex 'mu1' exclusively}}
4301*67e74705SXin Li if ((*sc).a == 42) doSomething(); // expected-warning {{reading variable 'sc' requires holding mutex 'mu1'}}
4302*67e74705SXin Li (*sc).a = 57; // expected-warning {{writing variable 'sc' requires holding mutex 'mu1' exclusively}}
4303*67e74705SXin Li if (sc->a == 42) doSomething(); // expected-warning {{reading variable 'sc' requires holding mutex 'mu1'}}
4304*67e74705SXin Li sc->a = 57; // expected-warning {{writing variable 'sc' requires holding mutex 'mu1' exclusively}}
4305*67e74705SXin Li }
4306*67e74705SXin Li
test5()4307*67e74705SXin Li void test5() {
4308*67e74705SXin Li mu1.ReaderLock(); // OK -- correct use.
4309*67e74705SXin Li mu2.Lock();
4310*67e74705SXin Li if (*a == 0) doSomething();
4311*67e74705SXin Li *a = 0;
4312*67e74705SXin Li
4313*67e74705SXin Li if (c->a == 0) doSomething();
4314*67e74705SXin Li c->a = 0;
4315*67e74705SXin Li
4316*67e74705SXin Li if ((*c).a == 0) doSomething();
4317*67e74705SXin Li (*c).a = 0;
4318*67e74705SXin Li mu2.Unlock();
4319*67e74705SXin Li mu1.Unlock();
4320*67e74705SXin Li }
4321*67e74705SXin Li };
4322*67e74705SXin Li
4323*67e74705SXin Li
4324*67e74705SXin Li class SmartPtr_PtGuardedBy_Test {
4325*67e74705SXin Li Mutex mu1;
4326*67e74705SXin Li Mutex mu2;
4327*67e74705SXin Li SmartPtr<int> sp GUARDED_BY(mu1) PT_GUARDED_BY(mu2);
4328*67e74705SXin Li SmartPtr<Cell> sq GUARDED_BY(mu1) PT_GUARDED_BY(mu2);
4329*67e74705SXin Li
test1()4330*67e74705SXin Li void test1() {
4331*67e74705SXin Li mu1.ReaderLock();
4332*67e74705SXin Li mu2.Lock();
4333*67e74705SXin Li
4334*67e74705SXin Li sp.get();
4335*67e74705SXin Li if (*sp == 0) doSomething();
4336*67e74705SXin Li *sp = 0;
4337*67e74705SXin Li sq->a = 0;
4338*67e74705SXin Li
4339*67e74705SXin Li if (sp[0] == 0) doSomething();
4340*67e74705SXin Li sp[0] = 0;
4341*67e74705SXin Li
4342*67e74705SXin Li mu2.Unlock();
4343*67e74705SXin Li mu1.Unlock();
4344*67e74705SXin Li }
4345*67e74705SXin Li
test2()4346*67e74705SXin Li void test2() {
4347*67e74705SXin Li mu2.Lock();
4348*67e74705SXin Li
4349*67e74705SXin Li sp.get(); // expected-warning {{reading variable 'sp' requires holding mutex 'mu1'}}
4350*67e74705SXin Li if (*sp == 0) doSomething(); // expected-warning {{reading variable 'sp' requires holding mutex 'mu1'}}
4351*67e74705SXin Li *sp = 0; // expected-warning {{reading variable 'sp' requires holding mutex 'mu1'}}
4352*67e74705SXin Li sq->a = 0; // expected-warning {{reading variable 'sq' requires holding mutex 'mu1'}}
4353*67e74705SXin Li
4354*67e74705SXin Li if (sp[0] == 0) doSomething(); // expected-warning {{reading variable 'sp' requires holding mutex 'mu1'}}
4355*67e74705SXin Li sp[0] = 0; // expected-warning {{reading variable 'sp' requires holding mutex 'mu1'}}
4356*67e74705SXin Li if (sq[0].a == 0) doSomething(); // expected-warning {{reading variable 'sq' requires holding mutex 'mu1'}}
4357*67e74705SXin Li sq[0].a = 0; // expected-warning {{reading variable 'sq' requires holding mutex 'mu1'}}
4358*67e74705SXin Li
4359*67e74705SXin Li mu2.Unlock();
4360*67e74705SXin Li }
4361*67e74705SXin Li
test3()4362*67e74705SXin Li void test3() {
4363*67e74705SXin Li mu1.Lock();
4364*67e74705SXin Li
4365*67e74705SXin Li sp.get();
4366*67e74705SXin Li if (*sp == 0) doSomething(); // expected-warning {{reading the value pointed to by 'sp' requires holding mutex 'mu2'}}
4367*67e74705SXin Li *sp = 0; // expected-warning {{reading the value pointed to by 'sp' requires holding mutex 'mu2'}}
4368*67e74705SXin Li sq->a = 0; // expected-warning {{reading the value pointed to by 'sq' requires holding mutex 'mu2'}}
4369*67e74705SXin Li
4370*67e74705SXin Li if (sp[0] == 0) doSomething(); // expected-warning {{reading the value pointed to by 'sp' requires holding mutex 'mu2'}}
4371*67e74705SXin Li sp[0] = 0; // expected-warning {{reading the value pointed to by 'sp' requires holding mutex 'mu2'}}
4372*67e74705SXin Li if (sq[0].a == 0) doSomething(); // expected-warning {{reading the value pointed to by 'sq' requires holding mutex 'mu2'}}
4373*67e74705SXin Li sq[0].a = 0; // expected-warning {{reading the value pointed to by 'sq' requires holding mutex 'mu2'}}
4374*67e74705SXin Li
4375*67e74705SXin Li mu1.Unlock();
4376*67e74705SXin Li }
4377*67e74705SXin Li };
4378*67e74705SXin Li
4379*67e74705SXin Li } // end namespace PtGuardedByTest
4380*67e74705SXin Li
4381*67e74705SXin Li
4382*67e74705SXin Li namespace NonMemberCalleeICETest {
4383*67e74705SXin Li
4384*67e74705SXin Li class A {
Run()4385*67e74705SXin Li void Run() {
4386*67e74705SXin Li (RunHelper)(); // expected-warning {{calling function 'RunHelper' requires holding mutex 'M' exclusively}}
4387*67e74705SXin Li }
4388*67e74705SXin Li
4389*67e74705SXin Li void RunHelper() __attribute__((exclusive_locks_required(M)));
4390*67e74705SXin Li Mutex M;
4391*67e74705SXin Li };
4392*67e74705SXin Li
4393*67e74705SXin Li } // end namespace NonMemberCalleeICETest
4394*67e74705SXin Li
4395*67e74705SXin Li
4396*67e74705SXin Li namespace pt_guard_attribute_type {
4397*67e74705SXin Li int i PT_GUARDED_BY(sls_mu); // expected-warning {{'pt_guarded_by' only applies to pointer types; type here is 'int'}}
4398*67e74705SXin Li int j PT_GUARDED_VAR; // expected-warning {{'pt_guarded_var' only applies to pointer types; type here is 'int'}}
4399*67e74705SXin Li
test()4400*67e74705SXin Li void test() {
4401*67e74705SXin Li int i PT_GUARDED_BY(sls_mu); // expected-warning {{'pt_guarded_by' attribute only applies to fields and global variables}}
4402*67e74705SXin Li int j PT_GUARDED_VAR; // expected-warning {{'pt_guarded_var' attribute only applies to fields and global variables}}
4403*67e74705SXin Li
4404*67e74705SXin Li typedef int PT_GUARDED_BY(sls_mu) bad1; // expected-warning {{'pt_guarded_by' attribute only applies to fields and global variables}}
4405*67e74705SXin Li typedef int PT_GUARDED_VAR bad2; // expected-warning {{'pt_guarded_var' attribute only applies to fields and global variables}}
4406*67e74705SXin Li }
4407*67e74705SXin Li } // end namespace pt_guard_attribute_type
4408*67e74705SXin Li
4409*67e74705SXin Li
4410*67e74705SXin Li namespace ThreadAttributesOnLambdas {
4411*67e74705SXin Li
4412*67e74705SXin Li class Foo {
4413*67e74705SXin Li Mutex mu_;
4414*67e74705SXin Li
4415*67e74705SXin Li void LockedFunction() EXCLUSIVE_LOCKS_REQUIRED(mu_);
4416*67e74705SXin Li
test()4417*67e74705SXin Li void test() {
4418*67e74705SXin Li auto func1 = [this]() EXCLUSIVE_LOCKS_REQUIRED(mu_) {
4419*67e74705SXin Li LockedFunction();
4420*67e74705SXin Li };
4421*67e74705SXin Li
4422*67e74705SXin Li auto func2 = [this]() NO_THREAD_SAFETY_ANALYSIS {
4423*67e74705SXin Li LockedFunction();
4424*67e74705SXin Li };
4425*67e74705SXin Li
4426*67e74705SXin Li auto func3 = [this]() EXCLUSIVE_LOCK_FUNCTION(mu_) {
4427*67e74705SXin Li mu_.Lock();
4428*67e74705SXin Li };
4429*67e74705SXin Li
4430*67e74705SXin Li func1(); // expected-warning {{calling function 'operator()' requires holding mutex 'mu_' exclusively}}
4431*67e74705SXin Li func2();
4432*67e74705SXin Li func3();
4433*67e74705SXin Li mu_.Unlock();
4434*67e74705SXin Li }
4435*67e74705SXin Li };
4436*67e74705SXin Li
4437*67e74705SXin Li } // end namespace ThreadAttributesOnLambdas
4438*67e74705SXin Li
4439*67e74705SXin Li
4440*67e74705SXin Li
4441*67e74705SXin Li namespace AttributeExpressionCornerCases {
4442*67e74705SXin Li
4443*67e74705SXin Li class Foo {
4444*67e74705SXin Li int a GUARDED_BY(getMu());
4445*67e74705SXin Li
4446*67e74705SXin Li Mutex* getMu() LOCK_RETURNED("");
4447*67e74705SXin Li Mutex* getUniv() LOCK_RETURNED("*");
4448*67e74705SXin Li
test1()4449*67e74705SXin Li void test1() {
4450*67e74705SXin Li a = 0;
4451*67e74705SXin Li }
4452*67e74705SXin Li
test2()4453*67e74705SXin Li void test2() EXCLUSIVE_LOCKS_REQUIRED(getUniv()) {
4454*67e74705SXin Li a = 0;
4455*67e74705SXin Li }
4456*67e74705SXin Li
4457*67e74705SXin Li void foo(Mutex* mu) EXCLUSIVE_LOCKS_REQUIRED(mu);
4458*67e74705SXin Li
test3()4459*67e74705SXin Li void test3() {
4460*67e74705SXin Li foo(nullptr);
4461*67e74705SXin Li }
4462*67e74705SXin Li };
4463*67e74705SXin Li
4464*67e74705SXin Li
4465*67e74705SXin Li class MapTest {
4466*67e74705SXin Li struct MuCell { Mutex* mu; };
4467*67e74705SXin Li
4468*67e74705SXin Li MyMap<MyString, Mutex*> map;
4469*67e74705SXin Li MyMap<MyString, MuCell> mapCell;
4470*67e74705SXin Li
4471*67e74705SXin Li int a GUARDED_BY(map["foo"]);
4472*67e74705SXin Li int b GUARDED_BY(mapCell["foo"].mu);
4473*67e74705SXin Li
test()4474*67e74705SXin Li void test() {
4475*67e74705SXin Li map["foo"]->Lock();
4476*67e74705SXin Li a = 0;
4477*67e74705SXin Li map["foo"]->Unlock();
4478*67e74705SXin Li }
4479*67e74705SXin Li
test2()4480*67e74705SXin Li void test2() {
4481*67e74705SXin Li mapCell["foo"].mu->Lock();
4482*67e74705SXin Li b = 0;
4483*67e74705SXin Li mapCell["foo"].mu->Unlock();
4484*67e74705SXin Li }
4485*67e74705SXin Li };
4486*67e74705SXin Li
4487*67e74705SXin Li
4488*67e74705SXin Li class PreciseSmartPtr {
4489*67e74705SXin Li SmartPtr<Mutex> mu;
4490*67e74705SXin Li int val GUARDED_BY(mu);
4491*67e74705SXin Li
compare(PreciseSmartPtr & a,PreciseSmartPtr & b)4492*67e74705SXin Li static bool compare(PreciseSmartPtr& a, PreciseSmartPtr &b) {
4493*67e74705SXin Li a.mu->Lock();
4494*67e74705SXin Li bool result = (a.val == b.val); // expected-warning {{reading variable 'val' requires holding mutex 'b.mu'}} \
4495*67e74705SXin Li // expected-note {{found near match 'a.mu'}}
4496*67e74705SXin Li a.mu->Unlock();
4497*67e74705SXin Li return result;
4498*67e74705SXin Li }
4499*67e74705SXin Li };
4500*67e74705SXin Li
4501*67e74705SXin Li
4502*67e74705SXin Li class SmartRedeclare {
4503*67e74705SXin Li SmartPtr<Mutex> mu;
4504*67e74705SXin Li int val GUARDED_BY(mu);
4505*67e74705SXin Li
4506*67e74705SXin Li void test() EXCLUSIVE_LOCKS_REQUIRED(mu);
4507*67e74705SXin Li void test2() EXCLUSIVE_LOCKS_REQUIRED(mu.get());
4508*67e74705SXin Li void test3() EXCLUSIVE_LOCKS_REQUIRED(mu.get());
4509*67e74705SXin Li };
4510*67e74705SXin Li
4511*67e74705SXin Li
test()4512*67e74705SXin Li void SmartRedeclare::test() EXCLUSIVE_LOCKS_REQUIRED(mu.get()) {
4513*67e74705SXin Li val = 0;
4514*67e74705SXin Li }
4515*67e74705SXin Li
test2()4516*67e74705SXin Li void SmartRedeclare::test2() EXCLUSIVE_LOCKS_REQUIRED(mu) {
4517*67e74705SXin Li val = 0;
4518*67e74705SXin Li }
4519*67e74705SXin Li
test3()4520*67e74705SXin Li void SmartRedeclare::test3() {
4521*67e74705SXin Li val = 0;
4522*67e74705SXin Li }
4523*67e74705SXin Li
4524*67e74705SXin Li
4525*67e74705SXin Li namespace CustomMutex {
4526*67e74705SXin Li
4527*67e74705SXin Li
4528*67e74705SXin Li class LOCKABLE BaseMutex { };
4529*67e74705SXin Li class DerivedMutex : public BaseMutex { };
4530*67e74705SXin Li
4531*67e74705SXin Li void customLock(const BaseMutex *m) EXCLUSIVE_LOCK_FUNCTION(m);
4532*67e74705SXin Li void customUnlock(const BaseMutex *m) UNLOCK_FUNCTION(m);
4533*67e74705SXin Li
4534*67e74705SXin Li static struct DerivedMutex custMu;
4535*67e74705SXin Li
doSomethingRequiringLock()4536*67e74705SXin Li static void doSomethingRequiringLock() EXCLUSIVE_LOCKS_REQUIRED(custMu) { }
4537*67e74705SXin Li
customTest()4538*67e74705SXin Li void customTest() {
4539*67e74705SXin Li customLock(reinterpret_cast<BaseMutex*>(&custMu)); // ignore casts
4540*67e74705SXin Li doSomethingRequiringLock();
4541*67e74705SXin Li customUnlock(reinterpret_cast<BaseMutex*>(&custMu));
4542*67e74705SXin Li }
4543*67e74705SXin Li
4544*67e74705SXin Li } // end namespace CustomMutex
4545*67e74705SXin Li
4546*67e74705SXin Li } // end AttributeExpressionCornerCases
4547*67e74705SXin Li
4548*67e74705SXin Li
4549*67e74705SXin Li namespace ScopedLockReturnedInvalid {
4550*67e74705SXin Li
4551*67e74705SXin Li class Opaque;
4552*67e74705SXin Li
4553*67e74705SXin Li Mutex* getMutex(Opaque* o) LOCK_RETURNED("");
4554*67e74705SXin Li
test(Opaque * o)4555*67e74705SXin Li void test(Opaque* o) {
4556*67e74705SXin Li MutexLock lock(getMutex(o));
4557*67e74705SXin Li }
4558*67e74705SXin Li
4559*67e74705SXin Li } // end namespace ScopedLockReturnedInvalid
4560*67e74705SXin Li
4561*67e74705SXin Li
4562*67e74705SXin Li namespace NegativeRequirements {
4563*67e74705SXin Li
4564*67e74705SXin Li class Bar {
4565*67e74705SXin Li Mutex mu;
4566*67e74705SXin Li int a GUARDED_BY(mu);
4567*67e74705SXin Li
4568*67e74705SXin Li public:
baz()4569*67e74705SXin Li void baz() EXCLUSIVE_LOCKS_REQUIRED(!mu) {
4570*67e74705SXin Li mu.Lock();
4571*67e74705SXin Li a = 0;
4572*67e74705SXin Li mu.Unlock();
4573*67e74705SXin Li }
4574*67e74705SXin Li };
4575*67e74705SXin Li
4576*67e74705SXin Li
4577*67e74705SXin Li class Foo {
4578*67e74705SXin Li Mutex mu;
4579*67e74705SXin Li int a GUARDED_BY(mu);
4580*67e74705SXin Li
4581*67e74705SXin Li public:
foo()4582*67e74705SXin Li void foo() {
4583*67e74705SXin Li mu.Lock(); // warning? needs !mu?
4584*67e74705SXin Li baz(); // expected-warning {{cannot call function 'baz' while mutex 'mu' is held}}
4585*67e74705SXin Li bar();
4586*67e74705SXin Li mu.Unlock();
4587*67e74705SXin Li }
4588*67e74705SXin Li
bar()4589*67e74705SXin Li void bar() {
4590*67e74705SXin Li bar2(); // expected-warning {{calling function 'bar2' requires holding '!mu'}}
4591*67e74705SXin Li }
4592*67e74705SXin Li
bar2()4593*67e74705SXin Li void bar2() EXCLUSIVE_LOCKS_REQUIRED(!mu) {
4594*67e74705SXin Li baz();
4595*67e74705SXin Li }
4596*67e74705SXin Li
baz()4597*67e74705SXin Li void baz() EXCLUSIVE_LOCKS_REQUIRED(!mu) {
4598*67e74705SXin Li mu.Lock();
4599*67e74705SXin Li a = 0;
4600*67e74705SXin Li mu.Unlock();
4601*67e74705SXin Li }
4602*67e74705SXin Li
test()4603*67e74705SXin Li void test() {
4604*67e74705SXin Li Bar b;
4605*67e74705SXin Li b.baz(); // no warning -- in different class.
4606*67e74705SXin Li }
4607*67e74705SXin Li };
4608*67e74705SXin Li
4609*67e74705SXin Li } // end namespace NegativeRequirements
4610*67e74705SXin Li
4611*67e74705SXin Li
4612*67e74705SXin Li namespace NegativeThreadRoles {
4613*67e74705SXin Li
4614*67e74705SXin Li typedef int __attribute__((capability("role"))) ThreadRole;
4615*67e74705SXin Li
acquire(ThreadRole R)4616*67e74705SXin Li void acquire(ThreadRole R) __attribute__((exclusive_lock_function(R))) __attribute__((no_thread_safety_analysis)) {}
release(ThreadRole R)4617*67e74705SXin Li void release(ThreadRole R) __attribute__((unlock_function(R))) __attribute__((no_thread_safety_analysis)) {}
4618*67e74705SXin Li
4619*67e74705SXin Li ThreadRole FlightControl, Logger;
4620*67e74705SXin Li
4621*67e74705SXin Li extern void enque_log_msg(const char *msg);
log_msg(const char * msg)4622*67e74705SXin Li void log_msg(const char *msg) {
4623*67e74705SXin Li enque_log_msg(msg);
4624*67e74705SXin Li }
4625*67e74705SXin Li
dispatch_log(const char * msg)4626*67e74705SXin Li void dispatch_log(const char *msg) __attribute__((requires_capability(!FlightControl))) {}
dispatch_log2(const char * msg)4627*67e74705SXin Li void dispatch_log2(const char *msg) __attribute__((requires_capability(Logger))) {}
4628*67e74705SXin Li
flight_control_entry(void)4629*67e74705SXin Li void flight_control_entry(void) __attribute__((requires_capability(FlightControl))) {
4630*67e74705SXin Li dispatch_log("wrong"); /* expected-warning {{cannot call function 'dispatch_log' while mutex 'FlightControl' is held}} */
4631*67e74705SXin Li dispatch_log2("also wrong"); /* expected-warning {{calling function 'dispatch_log2' requires holding role 'Logger' exclusively}} */
4632*67e74705SXin Li }
4633*67e74705SXin Li
spawn_fake_flight_control_thread(void)4634*67e74705SXin Li void spawn_fake_flight_control_thread(void) {
4635*67e74705SXin Li acquire(FlightControl);
4636*67e74705SXin Li flight_control_entry();
4637*67e74705SXin Li release(FlightControl);
4638*67e74705SXin Li }
4639*67e74705SXin Li
4640*67e74705SXin Li extern const char *deque_log_msg(void) __attribute__((requires_capability(Logger)));
logger_entry(void)4641*67e74705SXin Li void logger_entry(void) __attribute__((requires_capability(Logger))) {
4642*67e74705SXin Li const char *msg;
4643*67e74705SXin Li
4644*67e74705SXin Li while ((msg = deque_log_msg())) {
4645*67e74705SXin Li dispatch_log(msg);
4646*67e74705SXin Li }
4647*67e74705SXin Li }
4648*67e74705SXin Li
spawn_fake_logger_thread(void)4649*67e74705SXin Li void spawn_fake_logger_thread(void) {
4650*67e74705SXin Li acquire(Logger);
4651*67e74705SXin Li logger_entry();
4652*67e74705SXin Li release(Logger);
4653*67e74705SXin Li }
4654*67e74705SXin Li
main(void)4655*67e74705SXin Li int main(void) {
4656*67e74705SXin Li spawn_fake_flight_control_thread();
4657*67e74705SXin Li spawn_fake_logger_thread();
4658*67e74705SXin Li
4659*67e74705SXin Li for (;;)
4660*67e74705SXin Li ; /* Pretend to dispatch things. */
4661*67e74705SXin Li
4662*67e74705SXin Li return 0;
4663*67e74705SXin Li }
4664*67e74705SXin Li
4665*67e74705SXin Li } // end namespace NegativeThreadRoles
4666*67e74705SXin Li
4667*67e74705SXin Li
4668*67e74705SXin Li namespace AssertSharedExclusive {
4669*67e74705SXin Li
4670*67e74705SXin Li void doSomething();
4671*67e74705SXin Li
4672*67e74705SXin Li class Foo {
4673*67e74705SXin Li Mutex mu;
4674*67e74705SXin Li int a GUARDED_BY(mu);
4675*67e74705SXin Li
test()4676*67e74705SXin Li void test() SHARED_LOCKS_REQUIRED(mu) {
4677*67e74705SXin Li mu.AssertHeld();
4678*67e74705SXin Li if (a > 0)
4679*67e74705SXin Li doSomething();
4680*67e74705SXin Li }
4681*67e74705SXin Li };
4682*67e74705SXin Li
4683*67e74705SXin Li } // end namespace AssertSharedExclusive
4684*67e74705SXin Li
4685*67e74705SXin Li
4686*67e74705SXin Li namespace RangeBasedForAndReferences {
4687*67e74705SXin Li
4688*67e74705SXin Li class Foo {
4689*67e74705SXin Li struct MyStruct {
4690*67e74705SXin Li int a;
4691*67e74705SXin Li };
4692*67e74705SXin Li
4693*67e74705SXin Li Mutex mu;
4694*67e74705SXin Li int a GUARDED_BY(mu);
4695*67e74705SXin Li MyContainer<int> cntr GUARDED_BY(mu);
4696*67e74705SXin Li MyStruct s GUARDED_BY(mu);
4697*67e74705SXin Li int arr[10] GUARDED_BY(mu);
4698*67e74705SXin Li
nonref_test()4699*67e74705SXin Li void nonref_test() {
4700*67e74705SXin Li int b = a; // expected-warning {{reading variable 'a' requires holding mutex 'mu'}}
4701*67e74705SXin Li b = 0; // no warning
4702*67e74705SXin Li }
4703*67e74705SXin Li
auto_test()4704*67e74705SXin Li void auto_test() {
4705*67e74705SXin Li auto b = a; // expected-warning {{reading variable 'a' requires holding mutex 'mu'}}
4706*67e74705SXin Li b = 0; // no warning
4707*67e74705SXin Li auto &c = a; // no warning
4708*67e74705SXin Li c = 0; // expected-warning {{writing variable 'a' requires holding mutex 'mu' exclusively}}
4709*67e74705SXin Li }
4710*67e74705SXin Li
ref_test()4711*67e74705SXin Li void ref_test() {
4712*67e74705SXin Li int &b = a;
4713*67e74705SXin Li int &c = b;
4714*67e74705SXin Li int &d = c;
4715*67e74705SXin Li b = 0; // expected-warning {{writing variable 'a' requires holding mutex 'mu' exclusively}}
4716*67e74705SXin Li c = 0; // expected-warning {{writing variable 'a' requires holding mutex 'mu' exclusively}}
4717*67e74705SXin Li d = 0; // expected-warning {{writing variable 'a' requires holding mutex 'mu' exclusively}}
4718*67e74705SXin Li
4719*67e74705SXin Li MyStruct &rs = s;
4720*67e74705SXin Li rs.a = 0; // expected-warning {{writing variable 's' requires holding mutex 'mu' exclusively}}
4721*67e74705SXin Li
4722*67e74705SXin Li int (&rarr)[10] = arr;
4723*67e74705SXin Li rarr[2] = 0; // expected-warning {{writing variable 'arr' requires holding mutex 'mu' exclusively}}
4724*67e74705SXin Li }
4725*67e74705SXin Li
ptr_test()4726*67e74705SXin Li void ptr_test() {
4727*67e74705SXin Li int *b = &a;
4728*67e74705SXin Li *b = 0; // no expected warning yet
4729*67e74705SXin Li }
4730*67e74705SXin Li
for_test()4731*67e74705SXin Li void for_test() {
4732*67e74705SXin Li int total = 0;
4733*67e74705SXin Li for (int i : cntr) { // expected-warning2 {{reading variable 'cntr' requires holding mutex 'mu'}}
4734*67e74705SXin Li total += i;
4735*67e74705SXin Li }
4736*67e74705SXin Li }
4737*67e74705SXin Li };
4738*67e74705SXin Li
4739*67e74705SXin Li
4740*67e74705SXin Li } // end namespace RangeBasedForAndReferences
4741*67e74705SXin Li
4742*67e74705SXin Li
4743*67e74705SXin Li
4744*67e74705SXin Li namespace PassByRefTest {
4745*67e74705SXin Li
4746*67e74705SXin Li class Foo {
4747*67e74705SXin Li public:
Foo()4748*67e74705SXin Li Foo() : a(0), b(0) { }
4749*67e74705SXin Li
4750*67e74705SXin Li int a;
4751*67e74705SXin Li int b;
4752*67e74705SXin Li
4753*67e74705SXin Li void operator+(const Foo& f);
4754*67e74705SXin Li
4755*67e74705SXin Li void operator[](const Foo& g);
4756*67e74705SXin Li };
4757*67e74705SXin Li
4758*67e74705SXin Li template<class T>
4759*67e74705SXin Li T&& mymove(T& f);
4760*67e74705SXin Li
4761*67e74705SXin Li
4762*67e74705SXin Li // test top-level functions
4763*67e74705SXin Li void copy(Foo f);
4764*67e74705SXin Li void write1(Foo& f);
4765*67e74705SXin Li void write2(int a, Foo& f);
4766*67e74705SXin Li void read1(const Foo& f);
4767*67e74705SXin Li void read2(int a, const Foo& f);
4768*67e74705SXin Li void destroy(Foo&& f);
4769*67e74705SXin Li
4770*67e74705SXin Li void operator/(const Foo& f, const Foo& g);
4771*67e74705SXin Li void operator*(const Foo& f, const Foo& g);
4772*67e74705SXin Li
4773*67e74705SXin Li
4774*67e74705SXin Li
4775*67e74705SXin Li
4776*67e74705SXin Li class Bar {
4777*67e74705SXin Li public:
4778*67e74705SXin Li Mutex mu;
4779*67e74705SXin Li Foo foo GUARDED_BY(mu);
4780*67e74705SXin Li Foo foo2 GUARDED_BY(mu);
4781*67e74705SXin Li Foo* foop PT_GUARDED_BY(mu);
4782*67e74705SXin Li SmartPtr<Foo> foosp PT_GUARDED_BY(mu);
4783*67e74705SXin Li
4784*67e74705SXin Li // test methods.
4785*67e74705SXin Li void mwrite1(Foo& f);
4786*67e74705SXin Li void mwrite2(int a, Foo& f);
4787*67e74705SXin Li void mread1(const Foo& f);
4788*67e74705SXin Li void mread2(int a, const Foo& f);
4789*67e74705SXin Li
4790*67e74705SXin Li // static methods
4791*67e74705SXin Li static void smwrite1(Foo& f);
4792*67e74705SXin Li static void smwrite2(int a, Foo& f);
4793*67e74705SXin Li static void smread1(const Foo& f);
4794*67e74705SXin Li static void smread2(int a, const Foo& f);
4795*67e74705SXin Li
4796*67e74705SXin Li void operator<<(const Foo& f);
4797*67e74705SXin Li
test1()4798*67e74705SXin Li void test1() {
4799*67e74705SXin Li copy(foo); // expected-warning {{reading variable 'foo' requires holding mutex 'mu'}}
4800*67e74705SXin Li write1(foo); // expected-warning {{passing variable 'foo' by reference requires holding mutex 'mu'}}
4801*67e74705SXin Li write2(10, foo); // expected-warning {{passing variable 'foo' by reference requires holding mutex 'mu'}}
4802*67e74705SXin Li read1(foo); // expected-warning {{passing variable 'foo' by reference requires holding mutex 'mu'}}
4803*67e74705SXin Li read2(10, foo); // expected-warning {{passing variable 'foo' by reference requires holding mutex 'mu'}}
4804*67e74705SXin Li destroy(mymove(foo)); // expected-warning {{passing variable 'foo' by reference requires holding mutex 'mu'}}
4805*67e74705SXin Li
4806*67e74705SXin Li mwrite1(foo); // expected-warning {{passing variable 'foo' by reference requires holding mutex 'mu'}}
4807*67e74705SXin Li mwrite2(10, foo); // expected-warning {{passing variable 'foo' by reference requires holding mutex 'mu'}}
4808*67e74705SXin Li mread1(foo); // expected-warning {{passing variable 'foo' by reference requires holding mutex 'mu'}}
4809*67e74705SXin Li mread2(10, foo); // expected-warning {{passing variable 'foo' by reference requires holding mutex 'mu'}}
4810*67e74705SXin Li
4811*67e74705SXin Li smwrite1(foo); // expected-warning {{passing variable 'foo' by reference requires holding mutex 'mu'}}
4812*67e74705SXin Li smwrite2(10, foo); // expected-warning {{passing variable 'foo' by reference requires holding mutex 'mu'}}
4813*67e74705SXin Li smread1(foo); // expected-warning {{passing variable 'foo' by reference requires holding mutex 'mu'}}
4814*67e74705SXin Li smread2(10, foo); // expected-warning {{passing variable 'foo' by reference requires holding mutex 'mu'}}
4815*67e74705SXin Li
4816*67e74705SXin Li foo + foo2; // expected-warning {{reading variable 'foo' requires holding mutex 'mu'}} \
4817*67e74705SXin Li // expected-warning {{passing variable 'foo2' by reference requires holding mutex 'mu'}}
4818*67e74705SXin Li foo / foo2; // expected-warning {{reading variable 'foo' requires holding mutex 'mu'}} \
4819*67e74705SXin Li // expected-warning {{passing variable 'foo2' by reference requires holding mutex 'mu'}}
4820*67e74705SXin Li foo * foo2; // expected-warning {{reading variable 'foo' requires holding mutex 'mu'}} \
4821*67e74705SXin Li // expected-warning {{passing variable 'foo2' by reference requires holding mutex 'mu'}}
4822*67e74705SXin Li foo[foo2]; // expected-warning {{reading variable 'foo' requires holding mutex 'mu'}} \
4823*67e74705SXin Li // expected-warning {{passing variable 'foo2' by reference requires holding mutex 'mu'}}
4824*67e74705SXin Li (*this) << foo; // expected-warning {{passing variable 'foo' by reference requires holding mutex 'mu'}}
4825*67e74705SXin Li
4826*67e74705SXin Li copy(*foop); // expected-warning {{reading the value pointed to by 'foop' requires holding mutex 'mu'}}
4827*67e74705SXin Li write1(*foop); // expected-warning {{passing the value that 'foop' points to by reference requires holding mutex 'mu'}}
4828*67e74705SXin Li write2(10, *foop); // expected-warning {{passing the value that 'foop' points to by reference requires holding mutex 'mu'}}
4829*67e74705SXin Li read1(*foop); // expected-warning {{passing the value that 'foop' points to by reference requires holding mutex 'mu'}}
4830*67e74705SXin Li read2(10, *foop); // expected-warning {{passing the value that 'foop' points to by reference requires holding mutex 'mu'}}
4831*67e74705SXin Li destroy(mymove(*foop)); // expected-warning {{passing the value that 'foop' points to by reference requires holding mutex 'mu'}}
4832*67e74705SXin Li
4833*67e74705SXin Li copy(*foosp); // expected-warning {{reading the value pointed to by 'foosp' requires holding mutex 'mu'}}
4834*67e74705SXin Li write1(*foosp); // expected-warning {{reading the value pointed to by 'foosp' requires holding mutex 'mu'}}
4835*67e74705SXin Li write2(10, *foosp); // expected-warning {{reading the value pointed to by 'foosp' requires holding mutex 'mu'}}
4836*67e74705SXin Li read1(*foosp); // expected-warning {{reading the value pointed to by 'foosp' requires holding mutex 'mu'}}
4837*67e74705SXin Li read2(10, *foosp); // expected-warning {{reading the value pointed to by 'foosp' requires holding mutex 'mu'}}
4838*67e74705SXin Li destroy(mymove(*foosp)); // expected-warning {{reading the value pointed to by 'foosp' requires holding mutex 'mu'}}
4839*67e74705SXin Li
4840*67e74705SXin Li // TODO -- these require better smart pointer handling.
4841*67e74705SXin Li copy(*foosp.get());
4842*67e74705SXin Li write1(*foosp.get());
4843*67e74705SXin Li write2(10, *foosp.get());
4844*67e74705SXin Li read1(*foosp.get());
4845*67e74705SXin Li read2(10, *foosp.get());
4846*67e74705SXin Li destroy(mymove(*foosp.get()));
4847*67e74705SXin Li }
4848*67e74705SXin Li };
4849*67e74705SXin Li
4850*67e74705SXin Li
4851*67e74705SXin Li } // end namespace PassByRefTest
4852*67e74705SXin Li
4853*67e74705SXin Li
4854*67e74705SXin Li namespace AcquiredBeforeAfterText {
4855*67e74705SXin Li
4856*67e74705SXin Li class Foo {
4857*67e74705SXin Li Mutex mu1 ACQUIRED_BEFORE(mu2, mu3);
4858*67e74705SXin Li Mutex mu2;
4859*67e74705SXin Li Mutex mu3;
4860*67e74705SXin Li
test1()4861*67e74705SXin Li void test1() {
4862*67e74705SXin Li mu1.Lock();
4863*67e74705SXin Li mu2.Lock();
4864*67e74705SXin Li mu3.Lock();
4865*67e74705SXin Li
4866*67e74705SXin Li mu3.Unlock();
4867*67e74705SXin Li mu2.Unlock();
4868*67e74705SXin Li mu1.Unlock();
4869*67e74705SXin Li }
4870*67e74705SXin Li
test2()4871*67e74705SXin Li void test2() {
4872*67e74705SXin Li mu2.Lock();
4873*67e74705SXin Li mu1.Lock(); // expected-warning {{mutex 'mu1' must be acquired before 'mu2'}}
4874*67e74705SXin Li mu1.Unlock();
4875*67e74705SXin Li mu2.Unlock();
4876*67e74705SXin Li }
4877*67e74705SXin Li
test3()4878*67e74705SXin Li void test3() {
4879*67e74705SXin Li mu3.Lock();
4880*67e74705SXin Li mu1.Lock(); // expected-warning {{mutex 'mu1' must be acquired before 'mu3'}}
4881*67e74705SXin Li mu1.Unlock();
4882*67e74705SXin Li mu3.Unlock();
4883*67e74705SXin Li }
4884*67e74705SXin Li
test4()4885*67e74705SXin Li void test4() EXCLUSIVE_LOCKS_REQUIRED(mu1) {
4886*67e74705SXin Li mu2.Lock();
4887*67e74705SXin Li mu2.Unlock();
4888*67e74705SXin Li }
4889*67e74705SXin Li
test5()4890*67e74705SXin Li void test5() EXCLUSIVE_LOCKS_REQUIRED(mu2) {
4891*67e74705SXin Li mu1.Lock(); // expected-warning {{mutex 'mu1' must be acquired before 'mu2'}}
4892*67e74705SXin Li mu1.Unlock();
4893*67e74705SXin Li }
4894*67e74705SXin Li
test6()4895*67e74705SXin Li void test6() EXCLUSIVE_LOCKS_REQUIRED(mu2) {
4896*67e74705SXin Li mu1.AssertHeld();
4897*67e74705SXin Li }
4898*67e74705SXin Li
test7()4899*67e74705SXin Li void test7() EXCLUSIVE_LOCKS_REQUIRED(mu1, mu2, mu3) { }
4900*67e74705SXin Li
test8()4901*67e74705SXin Li void test8() EXCLUSIVE_LOCKS_REQUIRED(mu3, mu2, mu1) { }
4902*67e74705SXin Li };
4903*67e74705SXin Li
4904*67e74705SXin Li
4905*67e74705SXin Li class Foo2 {
4906*67e74705SXin Li Mutex mu1;
4907*67e74705SXin Li Mutex mu2 ACQUIRED_AFTER(mu1);
4908*67e74705SXin Li Mutex mu3 ACQUIRED_AFTER(mu1);
4909*67e74705SXin Li
test1()4910*67e74705SXin Li void test1() {
4911*67e74705SXin Li mu1.Lock();
4912*67e74705SXin Li mu2.Lock();
4913*67e74705SXin Li mu3.Lock();
4914*67e74705SXin Li
4915*67e74705SXin Li mu3.Unlock();
4916*67e74705SXin Li mu2.Unlock();
4917*67e74705SXin Li mu1.Unlock();
4918*67e74705SXin Li }
4919*67e74705SXin Li
test2()4920*67e74705SXin Li void test2() {
4921*67e74705SXin Li mu2.Lock();
4922*67e74705SXin Li mu1.Lock(); // expected-warning {{mutex 'mu1' must be acquired before 'mu2'}}
4923*67e74705SXin Li mu1.Unlock();
4924*67e74705SXin Li mu2.Unlock();
4925*67e74705SXin Li }
4926*67e74705SXin Li
test3()4927*67e74705SXin Li void test3() {
4928*67e74705SXin Li mu3.Lock();
4929*67e74705SXin Li mu1.Lock(); // expected-warning {{mutex 'mu1' must be acquired before 'mu3'}}
4930*67e74705SXin Li mu1.Unlock();
4931*67e74705SXin Li mu3.Unlock();
4932*67e74705SXin Li }
4933*67e74705SXin Li };
4934*67e74705SXin Li
4935*67e74705SXin Li
4936*67e74705SXin Li class Foo3 {
4937*67e74705SXin Li Mutex mu1 ACQUIRED_BEFORE(mu2);
4938*67e74705SXin Li Mutex mu2;
4939*67e74705SXin Li Mutex mu3 ACQUIRED_AFTER(mu2) ACQUIRED_BEFORE(mu4);
4940*67e74705SXin Li Mutex mu4;
4941*67e74705SXin Li
test1()4942*67e74705SXin Li void test1() {
4943*67e74705SXin Li mu1.Lock();
4944*67e74705SXin Li mu2.Lock();
4945*67e74705SXin Li mu3.Lock();
4946*67e74705SXin Li mu4.Lock();
4947*67e74705SXin Li
4948*67e74705SXin Li mu4.Unlock();
4949*67e74705SXin Li mu3.Unlock();
4950*67e74705SXin Li mu2.Unlock();
4951*67e74705SXin Li mu1.Unlock();
4952*67e74705SXin Li }
4953*67e74705SXin Li
test2()4954*67e74705SXin Li void test2() {
4955*67e74705SXin Li mu4.Lock();
4956*67e74705SXin Li mu2.Lock(); // expected-warning {{mutex 'mu2' must be acquired before 'mu4'}}
4957*67e74705SXin Li
4958*67e74705SXin Li mu2.Unlock();
4959*67e74705SXin Li mu4.Unlock();
4960*67e74705SXin Li }
4961*67e74705SXin Li
test3()4962*67e74705SXin Li void test3() {
4963*67e74705SXin Li mu4.Lock();
4964*67e74705SXin Li mu1.Lock(); // expected-warning {{mutex 'mu1' must be acquired before 'mu4'}}
4965*67e74705SXin Li
4966*67e74705SXin Li mu1.Unlock();
4967*67e74705SXin Li mu4.Unlock();
4968*67e74705SXin Li }
4969*67e74705SXin Li
test4()4970*67e74705SXin Li void test4() {
4971*67e74705SXin Li mu3.Lock();
4972*67e74705SXin Li mu1.Lock(); // expected-warning {{mutex 'mu1' must be acquired before 'mu3'}}
4973*67e74705SXin Li
4974*67e74705SXin Li mu1.Unlock();
4975*67e74705SXin Li mu3.Unlock();
4976*67e74705SXin Li }
4977*67e74705SXin Li };
4978*67e74705SXin Li
4979*67e74705SXin Li
4980*67e74705SXin Li // Test transitive DAG traversal with AFTER
4981*67e74705SXin Li class Foo4 {
4982*67e74705SXin Li Mutex mu1;
4983*67e74705SXin Li Mutex mu2 ACQUIRED_AFTER(mu1);
4984*67e74705SXin Li Mutex mu3 ACQUIRED_AFTER(mu1);
4985*67e74705SXin Li Mutex mu4 ACQUIRED_AFTER(mu2, mu3);
4986*67e74705SXin Li Mutex mu5 ACQUIRED_AFTER(mu4);
4987*67e74705SXin Li Mutex mu6 ACQUIRED_AFTER(mu4);
4988*67e74705SXin Li Mutex mu7 ACQUIRED_AFTER(mu5, mu6);
4989*67e74705SXin Li Mutex mu8 ACQUIRED_AFTER(mu7);
4990*67e74705SXin Li
test()4991*67e74705SXin Li void test() {
4992*67e74705SXin Li mu8.Lock();
4993*67e74705SXin Li mu1.Lock(); // expected-warning {{mutex 'mu1' must be acquired before 'mu8'}}
4994*67e74705SXin Li mu1.Unlock();
4995*67e74705SXin Li mu8.Unlock();
4996*67e74705SXin Li }
4997*67e74705SXin Li };
4998*67e74705SXin Li
4999*67e74705SXin Li
5000*67e74705SXin Li // Test transitive DAG traversal with BEFORE
5001*67e74705SXin Li class Foo5 {
5002*67e74705SXin Li Mutex mu1 ACQUIRED_BEFORE(mu2, mu3);
5003*67e74705SXin Li Mutex mu2 ACQUIRED_BEFORE(mu4);
5004*67e74705SXin Li Mutex mu3 ACQUIRED_BEFORE(mu4);
5005*67e74705SXin Li Mutex mu4 ACQUIRED_BEFORE(mu5, mu6);
5006*67e74705SXin Li Mutex mu5 ACQUIRED_BEFORE(mu7);
5007*67e74705SXin Li Mutex mu6 ACQUIRED_BEFORE(mu7);
5008*67e74705SXin Li Mutex mu7 ACQUIRED_BEFORE(mu8);
5009*67e74705SXin Li Mutex mu8;
5010*67e74705SXin Li
test()5011*67e74705SXin Li void test() {
5012*67e74705SXin Li mu8.Lock();
5013*67e74705SXin Li mu1.Lock(); // expected-warning {{mutex 'mu1' must be acquired before 'mu8'}}
5014*67e74705SXin Li mu1.Unlock();
5015*67e74705SXin Li mu8.Unlock();
5016*67e74705SXin Li }
5017*67e74705SXin Li };
5018*67e74705SXin Li
5019*67e74705SXin Li
5020*67e74705SXin Li class Foo6 {
5021*67e74705SXin Li Mutex mu1 ACQUIRED_AFTER(mu3); // expected-warning {{Cycle in acquired_before/after dependencies, starting with 'mu1'}}
5022*67e74705SXin Li Mutex mu2 ACQUIRED_AFTER(mu1); // expected-warning {{Cycle in acquired_before/after dependencies, starting with 'mu2'}}
5023*67e74705SXin Li Mutex mu3 ACQUIRED_AFTER(mu2); // expected-warning {{Cycle in acquired_before/after dependencies, starting with 'mu3'}}
5024*67e74705SXin Li
5025*67e74705SXin Li Mutex mu_b ACQUIRED_BEFORE(mu_b); // expected-warning {{Cycle in acquired_before/after dependencies, starting with 'mu_b'}}
5026*67e74705SXin Li Mutex mu_a ACQUIRED_AFTER(mu_a); // expected-warning {{Cycle in acquired_before/after dependencies, starting with 'mu_a'}}
5027*67e74705SXin Li
test0()5028*67e74705SXin Li void test0() {
5029*67e74705SXin Li mu_a.Lock();
5030*67e74705SXin Li mu_b.Lock();
5031*67e74705SXin Li mu_b.Unlock();
5032*67e74705SXin Li mu_a.Unlock();
5033*67e74705SXin Li }
5034*67e74705SXin Li
test1a()5035*67e74705SXin Li void test1a() {
5036*67e74705SXin Li mu1.Lock();
5037*67e74705SXin Li mu1.Unlock();
5038*67e74705SXin Li }
5039*67e74705SXin Li
test1b()5040*67e74705SXin Li void test1b() {
5041*67e74705SXin Li mu1.Lock();
5042*67e74705SXin Li mu_a.Lock();
5043*67e74705SXin Li mu_b.Lock();
5044*67e74705SXin Li mu_b.Unlock();
5045*67e74705SXin Li mu_a.Unlock();
5046*67e74705SXin Li mu1.Unlock();
5047*67e74705SXin Li }
5048*67e74705SXin Li
test()5049*67e74705SXin Li void test() {
5050*67e74705SXin Li mu2.Lock();
5051*67e74705SXin Li mu2.Unlock();
5052*67e74705SXin Li }
5053*67e74705SXin Li
test3()5054*67e74705SXin Li void test3() {
5055*67e74705SXin Li mu3.Lock();
5056*67e74705SXin Li mu3.Unlock();
5057*67e74705SXin Li }
5058*67e74705SXin Li };
5059*67e74705SXin Li
5060*67e74705SXin Li } // end namespace AcquiredBeforeAfterTest
5061*67e74705SXin Li
5062*67e74705SXin Li
5063*67e74705SXin Li namespace ScopedAdoptTest {
5064*67e74705SXin Li
5065*67e74705SXin Li class Foo {
5066*67e74705SXin Li Mutex mu;
5067*67e74705SXin Li int a GUARDED_BY(mu);
5068*67e74705SXin Li int b;
5069*67e74705SXin Li
test1()5070*67e74705SXin Li void test1() EXCLUSIVE_UNLOCK_FUNCTION(mu) {
5071*67e74705SXin Li MutexLock slock(&mu, true);
5072*67e74705SXin Li a = 0;
5073*67e74705SXin Li }
5074*67e74705SXin Li
test2()5075*67e74705SXin Li void test2() SHARED_UNLOCK_FUNCTION(mu) {
5076*67e74705SXin Li ReaderMutexLock slock(&mu, true);
5077*67e74705SXin Li b = a;
5078*67e74705SXin Li }
5079*67e74705SXin Li
test3()5080*67e74705SXin Li void test3() EXCLUSIVE_LOCKS_REQUIRED(mu) { // expected-note {{mutex acquired here}}
5081*67e74705SXin Li MutexLock slock(&mu, true);
5082*67e74705SXin Li a = 0;
5083*67e74705SXin Li } // expected-warning {{expecting mutex 'mu' to be held at the end of function}}
5084*67e74705SXin Li
test4()5085*67e74705SXin Li void test4() SHARED_LOCKS_REQUIRED(mu) { // expected-note {{mutex acquired here}}
5086*67e74705SXin Li ReaderMutexLock slock(&mu, true);
5087*67e74705SXin Li b = a;
5088*67e74705SXin Li } // expected-warning {{expecting mutex 'mu' to be held at the end of function}}
5089*67e74705SXin Li
5090*67e74705SXin Li };
5091*67e74705SXin Li
5092*67e74705SXin Li } // end namespace ScopedAdoptTest
5093*67e74705SXin Li
5094*67e74705SXin Li
5095*67e74705SXin Li namespace TestReferenceNoThreadSafetyAnalysis {
5096*67e74705SXin Li
5097*67e74705SXin Li #define TS_UNCHECKED_READ(x) ts_unchecked_read(x)
5098*67e74705SXin Li
5099*67e74705SXin Li // Takes a reference to a guarded data member, and returns an unguarded
5100*67e74705SXin Li // reference.
5101*67e74705SXin Li template <class T>
ts_unchecked_read(const T & v)5102*67e74705SXin Li inline const T& ts_unchecked_read(const T& v) NO_THREAD_SAFETY_ANALYSIS {
5103*67e74705SXin Li return v;
5104*67e74705SXin Li }
5105*67e74705SXin Li
5106*67e74705SXin Li template <class T>
ts_unchecked_read(T & v)5107*67e74705SXin Li inline T& ts_unchecked_read(T& v) NO_THREAD_SAFETY_ANALYSIS {
5108*67e74705SXin Li return v;
5109*67e74705SXin Li }
5110*67e74705SXin Li
5111*67e74705SXin Li
5112*67e74705SXin Li class Foo {
5113*67e74705SXin Li public:
Foo()5114*67e74705SXin Li Foo(): a(0) { }
5115*67e74705SXin Li
5116*67e74705SXin Li int a;
5117*67e74705SXin Li };
5118*67e74705SXin Li
5119*67e74705SXin Li
5120*67e74705SXin Li class Bar {
5121*67e74705SXin Li public:
Bar()5122*67e74705SXin Li Bar() : a(0) { }
5123*67e74705SXin Li
5124*67e74705SXin Li Mutex mu;
5125*67e74705SXin Li int a GUARDED_BY(mu);
5126*67e74705SXin Li Foo foo GUARDED_BY(mu);
5127*67e74705SXin Li };
5128*67e74705SXin Li
5129*67e74705SXin Li
test()5130*67e74705SXin Li void test() {
5131*67e74705SXin Li Bar bar;
5132*67e74705SXin Li const Bar cbar;
5133*67e74705SXin Li
5134*67e74705SXin Li int a = TS_UNCHECKED_READ(bar.a); // nowarn
5135*67e74705SXin Li TS_UNCHECKED_READ(bar.a) = 1; // nowarn
5136*67e74705SXin Li
5137*67e74705SXin Li int b = TS_UNCHECKED_READ(bar.foo).a; // nowarn
5138*67e74705SXin Li TS_UNCHECKED_READ(bar.foo).a = 1; // nowarn
5139*67e74705SXin Li
5140*67e74705SXin Li int c = TS_UNCHECKED_READ(cbar.a); // nowarn
5141*67e74705SXin Li }
5142*67e74705SXin Li
5143*67e74705SXin Li #undef TS_UNCHECKED_READ
5144*67e74705SXin Li
5145*67e74705SXin Li } // end namespace TestReferenceNoThreadSafetyAnalysis
5146*67e74705SXin Li
5147*67e74705SXin Li
5148*67e74705SXin Li namespace GlobalAcquiredBeforeAfterTest {
5149*67e74705SXin Li
5150*67e74705SXin Li Mutex mu1;
5151*67e74705SXin Li Mutex mu2 ACQUIRED_AFTER(mu1);
5152*67e74705SXin Li
test3()5153*67e74705SXin Li void test3() {
5154*67e74705SXin Li mu2.Lock();
5155*67e74705SXin Li mu1.Lock(); // expected-warning {{mutex 'mu1' must be acquired before 'mu2'}}
5156*67e74705SXin Li mu1.Unlock();
5157*67e74705SXin Li mu2.Unlock();
5158*67e74705SXin Li }
5159*67e74705SXin Li
5160*67e74705SXin Li } // end namespace GlobalAcquiredBeforeAfterTest
5161*67e74705SXin Li
5162*67e74705SXin Li
5163*67e74705SXin Li namespace LockableUnions {
5164*67e74705SXin Li
5165*67e74705SXin Li union LOCKABLE MutexUnion {
5166*67e74705SXin Li int a;
5167*67e74705SXin Li char* b;
5168*67e74705SXin Li
5169*67e74705SXin Li void Lock() EXCLUSIVE_LOCK_FUNCTION();
5170*67e74705SXin Li void Unlock() UNLOCK_FUNCTION();
5171*67e74705SXin Li };
5172*67e74705SXin Li
5173*67e74705SXin Li MutexUnion muun2;
5174*67e74705SXin Li MutexUnion muun1 ACQUIRED_BEFORE(muun2);
5175*67e74705SXin Li
test()5176*67e74705SXin Li void test() {
5177*67e74705SXin Li muun2.Lock();
5178*67e74705SXin Li muun1.Lock(); // expected-warning {{mutex 'muun1' must be acquired before 'muun2'}}
5179*67e74705SXin Li muun1.Unlock();
5180*67e74705SXin Li muun2.Unlock();
5181*67e74705SXin Li }
5182*67e74705SXin Li
5183*67e74705SXin Li } // end namespace LockableUnions
5184*67e74705SXin Li
5185*67e74705SXin Li // This used to crash.
5186*67e74705SXin Li class acquired_before_empty_str {
WaitUntilSpaceAvailable()5187*67e74705SXin Li void WaitUntilSpaceAvailable() {
5188*67e74705SXin Li lock_.ReaderLock(); // expected-note {{acquired here}}
5189*67e74705SXin Li } // expected-warning {{mutex 'lock_' is still held at the end of function}}
5190*67e74705SXin Li Mutex lock_ ACQUIRED_BEFORE("");
5191*67e74705SXin Li };
5192