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