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