xref: /minix3/external/bsd/llvm/dist/clang/test/PCH/thread-safety-attrs.cpp (revision 0a6a1f1d05b60e214de2f05a7310ddd1f0e590e7)
1f4a2713aSLionel Sambuc // Test this without pch.
2f4a2713aSLionel Sambuc // RUN: %clang_cc1 -include %s -fsyntax-only -verify -Wthread-safety -std=c++11 %s
3f4a2713aSLionel Sambuc 
4f4a2713aSLionel Sambuc // Test with pch.
5f4a2713aSLionel Sambuc // RUN: %clang_cc1 -emit-pch -o %t %s -std=c++11
6f4a2713aSLionel Sambuc // RUN: %clang_cc1 -include-pch %t -fsyntax-only -verify -Wthread-safety -std=c++11 %s
7f4a2713aSLionel Sambuc 
8f4a2713aSLionel Sambuc #ifndef HEADER
9f4a2713aSLionel Sambuc #define HEADER
10f4a2713aSLionel Sambuc 
11f4a2713aSLionel Sambuc #define LOCKABLE            __attribute__ ((lockable))
12f4a2713aSLionel Sambuc #define SCOPED_LOCKABLE     __attribute__ ((scoped_lockable))
13f4a2713aSLionel Sambuc #define GUARDED_BY(x)       __attribute__ ((guarded_by(x)))
14f4a2713aSLionel Sambuc #define GUARDED_VAR         __attribute__ ((guarded_var))
15f4a2713aSLionel Sambuc #define PT_GUARDED_BY(x)    __attribute__ ((pt_guarded_by(x)))
16f4a2713aSLionel Sambuc #define PT_GUARDED_VAR      __attribute__ ((pt_guarded_var))
17f4a2713aSLionel Sambuc #define ACQUIRED_AFTER(...) __attribute__ ((acquired_after(__VA_ARGS__)))
18f4a2713aSLionel Sambuc #define ACQUIRED_BEFORE(...) __attribute__ ((acquired_before(__VA_ARGS__)))
19f4a2713aSLionel Sambuc #define EXCLUSIVE_LOCK_FUNCTION(...)   __attribute__ ((exclusive_lock_function(__VA_ARGS__)))
20f4a2713aSLionel Sambuc #define SHARED_LOCK_FUNCTION(...)      __attribute__ ((shared_lock_function(__VA_ARGS__)))
21f4a2713aSLionel Sambuc #define EXCLUSIVE_TRYLOCK_FUNCTION(...) __attribute__ ((exclusive_trylock_function(__VA_ARGS__)))
22f4a2713aSLionel Sambuc #define SHARED_TRYLOCK_FUNCTION(...)    __attribute__ ((shared_trylock_function(__VA_ARGS__)))
23f4a2713aSLionel Sambuc #define UNLOCK_FUNCTION(...)            __attribute__ ((unlock_function(__VA_ARGS__)))
24f4a2713aSLionel Sambuc #define LOCK_RETURNED(x)    __attribute__ ((lock_returned(x)))
25f4a2713aSLionel Sambuc #define LOCKS_EXCLUDED(...) __attribute__ ((locks_excluded(__VA_ARGS__)))
26f4a2713aSLionel Sambuc #define EXCLUSIVE_LOCKS_REQUIRED(...) \
27f4a2713aSLionel Sambuc   __attribute__ ((exclusive_locks_required(__VA_ARGS__)))
28f4a2713aSLionel Sambuc #define SHARED_LOCKS_REQUIRED(...) \
29f4a2713aSLionel Sambuc   __attribute__ ((shared_locks_required(__VA_ARGS__)))
30f4a2713aSLionel Sambuc #define NO_THREAD_SAFETY_ANALYSIS  __attribute__ ((no_thread_safety_analysis))
31f4a2713aSLionel Sambuc 
32f4a2713aSLionel Sambuc 
33f4a2713aSLionel Sambuc class  __attribute__((lockable)) Mutex {
34f4a2713aSLionel Sambuc  public:
35f4a2713aSLionel Sambuc   void Lock() __attribute__((exclusive_lock_function));
36f4a2713aSLionel Sambuc   void ReaderLock() __attribute__((shared_lock_function));
37f4a2713aSLionel Sambuc   void Unlock() __attribute__((unlock_function));
38f4a2713aSLionel Sambuc   bool TryLock() __attribute__((exclusive_trylock_function(true)));
39f4a2713aSLionel Sambuc   bool ReaderTryLock() __attribute__((shared_trylock_function(true)));
40f4a2713aSLionel Sambuc   void LockWhen(const int &cond) __attribute__((exclusive_lock_function));
41f4a2713aSLionel Sambuc };
42f4a2713aSLionel Sambuc 
43f4a2713aSLionel Sambuc class __attribute__((scoped_lockable)) MutexLock {
44f4a2713aSLionel Sambuc  public:
45f4a2713aSLionel Sambuc   MutexLock(Mutex *mu) __attribute__((exclusive_lock_function(mu)));
46f4a2713aSLionel Sambuc   ~MutexLock() __attribute__((unlock_function));
47f4a2713aSLionel Sambuc };
48f4a2713aSLionel Sambuc 
49f4a2713aSLionel Sambuc class __attribute__((scoped_lockable)) ReaderMutexLock {
50f4a2713aSLionel Sambuc  public:
51f4a2713aSLionel Sambuc   ReaderMutexLock(Mutex *mu) __attribute__((exclusive_lock_function(mu)));
52f4a2713aSLionel Sambuc   ~ReaderMutexLock() __attribute__((unlock_function));
53f4a2713aSLionel Sambuc };
54f4a2713aSLionel Sambuc 
55f4a2713aSLionel Sambuc class SCOPED_LOCKABLE ReleasableMutexLock {
56f4a2713aSLionel Sambuc  public:
57f4a2713aSLionel Sambuc   ReleasableMutexLock(Mutex *mu) EXCLUSIVE_LOCK_FUNCTION(mu);
58f4a2713aSLionel Sambuc   ~ReleasableMutexLock() UNLOCK_FUNCTION();
59f4a2713aSLionel Sambuc 
60f4a2713aSLionel Sambuc   void Release() UNLOCK_FUNCTION();
61f4a2713aSLionel Sambuc };
62f4a2713aSLionel Sambuc 
63f4a2713aSLionel Sambuc 
64f4a2713aSLionel Sambuc // The universal lock, written "*", allows checking to be selectively turned
65f4a2713aSLionel Sambuc // off for a particular piece of code.
66f4a2713aSLionel Sambuc void beginNoWarnOnReads()  SHARED_LOCK_FUNCTION("*");
67f4a2713aSLionel Sambuc void endNoWarnOnReads()    UNLOCK_FUNCTION("*");
68f4a2713aSLionel Sambuc void beginNoWarnOnWrites() EXCLUSIVE_LOCK_FUNCTION("*");
69f4a2713aSLionel Sambuc void endNoWarnOnWrites()   UNLOCK_FUNCTION("*");
70f4a2713aSLionel Sambuc 
71f4a2713aSLionel Sambuc 
72f4a2713aSLionel Sambuc // For testing handling of smart pointers.
73f4a2713aSLionel Sambuc template<class T>
74f4a2713aSLionel Sambuc class SmartPtr {
75f4a2713aSLionel Sambuc public:
SmartPtr(T * p)76f4a2713aSLionel Sambuc   SmartPtr(T* p) : ptr_(p) { }
SmartPtr(const SmartPtr<T> & p)77f4a2713aSLionel Sambuc   SmartPtr(const SmartPtr<T>& p) : ptr_(p.ptr_) { }
78f4a2713aSLionel Sambuc   ~SmartPtr();
79f4a2713aSLionel Sambuc 
get() const80f4a2713aSLionel Sambuc   T* get()        const { return ptr_; }
operator ->() const81f4a2713aSLionel Sambuc   T* operator->() const { return ptr_; }
operator *() const82f4a2713aSLionel Sambuc   T& operator*()  const { return *ptr_; }
83f4a2713aSLionel Sambuc 
84f4a2713aSLionel Sambuc private:
85f4a2713aSLionel Sambuc   T* ptr_;
86f4a2713aSLionel Sambuc };
87f4a2713aSLionel Sambuc 
88f4a2713aSLionel Sambuc 
89f4a2713aSLionel Sambuc // For testing destructor calls and cleanup.
90f4a2713aSLionel Sambuc class MyString {
91f4a2713aSLionel Sambuc public:
92f4a2713aSLionel Sambuc   MyString(const char* s);
93f4a2713aSLionel Sambuc   ~MyString();
94f4a2713aSLionel Sambuc };
95f4a2713aSLionel Sambuc 
96f4a2713aSLionel Sambuc 
97f4a2713aSLionel Sambuc 
98f4a2713aSLionel Sambuc Mutex sls_mu;
99f4a2713aSLionel Sambuc 
100f4a2713aSLionel Sambuc Mutex sls_mu2 __attribute__((acquired_after(sls_mu)));
101f4a2713aSLionel Sambuc int sls_guard_var __attribute__((guarded_var)) = 0;
102f4a2713aSLionel Sambuc int sls_guardby_var __attribute__((guarded_by(sls_mu))) = 0;
103f4a2713aSLionel Sambuc 
104f4a2713aSLionel Sambuc bool getBool();
105f4a2713aSLionel Sambuc 
106f4a2713aSLionel Sambuc class MutexWrapper {
107f4a2713aSLionel Sambuc public:
108f4a2713aSLionel Sambuc    Mutex mu;
109f4a2713aSLionel Sambuc    int x __attribute__((guarded_by(mu)));
110f4a2713aSLionel Sambuc    void MyLock() __attribute__((exclusive_lock_function(mu)));
111f4a2713aSLionel Sambuc };
112f4a2713aSLionel Sambuc 
113f4a2713aSLionel Sambuc #else
114f4a2713aSLionel Sambuc 
115f4a2713aSLionel Sambuc MutexWrapper sls_mw;
116f4a2713aSLionel Sambuc 
sls_fun_0()117f4a2713aSLionel Sambuc void sls_fun_0() {
118f4a2713aSLionel Sambuc   sls_mw.mu.Lock();
119f4a2713aSLionel Sambuc   sls_mw.x = 5;
120f4a2713aSLionel Sambuc   sls_mw.mu.Unlock();
121f4a2713aSLionel Sambuc }
122f4a2713aSLionel Sambuc 
sls_fun_2()123f4a2713aSLionel Sambuc void sls_fun_2() {
124f4a2713aSLionel Sambuc   sls_mu.Lock();
125f4a2713aSLionel Sambuc   int x = sls_guard_var;
126f4a2713aSLionel Sambuc   sls_mu.Unlock();
127f4a2713aSLionel Sambuc }
128f4a2713aSLionel Sambuc 
sls_fun_3()129f4a2713aSLionel Sambuc void sls_fun_3() {
130f4a2713aSLionel Sambuc   sls_mu.Lock();
131f4a2713aSLionel Sambuc   sls_guard_var = 2;
132f4a2713aSLionel Sambuc   sls_mu.Unlock();
133f4a2713aSLionel Sambuc }
134f4a2713aSLionel Sambuc 
sls_fun_4()135f4a2713aSLionel Sambuc void sls_fun_4() {
136f4a2713aSLionel Sambuc   sls_mu2.Lock();
137f4a2713aSLionel Sambuc   sls_guard_var = 2;
138f4a2713aSLionel Sambuc   sls_mu2.Unlock();
139f4a2713aSLionel Sambuc }
140f4a2713aSLionel Sambuc 
sls_fun_5()141f4a2713aSLionel Sambuc void sls_fun_5() {
142f4a2713aSLionel Sambuc   sls_mu.Lock();
143f4a2713aSLionel Sambuc   int x = sls_guardby_var;
144f4a2713aSLionel Sambuc   sls_mu.Unlock();
145f4a2713aSLionel Sambuc }
146f4a2713aSLionel Sambuc 
sls_fun_6()147f4a2713aSLionel Sambuc void sls_fun_6() {
148f4a2713aSLionel Sambuc   sls_mu.Lock();
149f4a2713aSLionel Sambuc   sls_guardby_var = 2;
150f4a2713aSLionel Sambuc   sls_mu.Unlock();
151f4a2713aSLionel Sambuc }
152f4a2713aSLionel Sambuc 
sls_fun_7()153f4a2713aSLionel Sambuc void sls_fun_7() {
154f4a2713aSLionel Sambuc   sls_mu.Lock();
155f4a2713aSLionel Sambuc   sls_mu2.Lock();
156f4a2713aSLionel Sambuc   sls_mu2.Unlock();
157f4a2713aSLionel Sambuc   sls_mu.Unlock();
158f4a2713aSLionel Sambuc }
159f4a2713aSLionel Sambuc 
sls_fun_8()160f4a2713aSLionel Sambuc void sls_fun_8() {
161f4a2713aSLionel Sambuc   sls_mu.Lock();
162f4a2713aSLionel Sambuc   if (getBool())
163f4a2713aSLionel Sambuc     sls_mu.Unlock();
164f4a2713aSLionel Sambuc   else
165f4a2713aSLionel Sambuc     sls_mu.Unlock();
166f4a2713aSLionel Sambuc }
167f4a2713aSLionel Sambuc 
sls_fun_9()168f4a2713aSLionel Sambuc void sls_fun_9() {
169f4a2713aSLionel Sambuc   if (getBool())
170f4a2713aSLionel Sambuc     sls_mu.Lock();
171f4a2713aSLionel Sambuc   else
172f4a2713aSLionel Sambuc     sls_mu.Lock();
173f4a2713aSLionel Sambuc   sls_mu.Unlock();
174f4a2713aSLionel Sambuc }
175f4a2713aSLionel Sambuc 
sls_fun_good_6()176f4a2713aSLionel Sambuc void sls_fun_good_6() {
177f4a2713aSLionel Sambuc   if (getBool()) {
178f4a2713aSLionel Sambuc     sls_mu.Lock();
179f4a2713aSLionel Sambuc   } else {
180f4a2713aSLionel Sambuc     if (getBool()) {
181f4a2713aSLionel Sambuc       getBool(); // EMPTY
182f4a2713aSLionel Sambuc     } else {
183f4a2713aSLionel Sambuc       getBool(); // EMPTY
184f4a2713aSLionel Sambuc     }
185f4a2713aSLionel Sambuc     sls_mu.Lock();
186f4a2713aSLionel Sambuc   }
187f4a2713aSLionel Sambuc   sls_mu.Unlock();
188f4a2713aSLionel Sambuc }
189f4a2713aSLionel Sambuc 
sls_fun_good_7()190f4a2713aSLionel Sambuc void sls_fun_good_7() {
191f4a2713aSLionel Sambuc   sls_mu.Lock();
192f4a2713aSLionel Sambuc   while (getBool()) {
193f4a2713aSLionel Sambuc     sls_mu.Unlock();
194f4a2713aSLionel Sambuc     if (getBool()) {
195f4a2713aSLionel Sambuc       if (getBool()) {
196f4a2713aSLionel Sambuc         sls_mu.Lock();
197f4a2713aSLionel Sambuc         continue;
198f4a2713aSLionel Sambuc       }
199f4a2713aSLionel Sambuc     }
200f4a2713aSLionel Sambuc     sls_mu.Lock();
201f4a2713aSLionel Sambuc   }
202f4a2713aSLionel Sambuc   sls_mu.Unlock();
203f4a2713aSLionel Sambuc }
204f4a2713aSLionel Sambuc 
sls_fun_good_8()205f4a2713aSLionel Sambuc void sls_fun_good_8() {
206f4a2713aSLionel Sambuc   sls_mw.MyLock();
207f4a2713aSLionel Sambuc   sls_mw.mu.Unlock();
208f4a2713aSLionel Sambuc }
209f4a2713aSLionel Sambuc 
sls_fun_bad_1()210f4a2713aSLionel Sambuc void sls_fun_bad_1() {
211f4a2713aSLionel Sambuc   sls_mu.Unlock(); // \
212*0a6a1f1dSLionel Sambuc     // expected-warning{{releasing mutex 'sls_mu' that was not held}}
213f4a2713aSLionel Sambuc }
214f4a2713aSLionel Sambuc 
sls_fun_bad_2()215f4a2713aSLionel Sambuc void sls_fun_bad_2() {
216f4a2713aSLionel Sambuc   sls_mu.Lock();
217f4a2713aSLionel Sambuc   sls_mu.Lock(); // \
218*0a6a1f1dSLionel Sambuc     // expected-warning{{acquiring mutex 'sls_mu' that is already held}}
219f4a2713aSLionel Sambuc   sls_mu.Unlock();
220f4a2713aSLionel Sambuc }
221f4a2713aSLionel Sambuc 
sls_fun_bad_3()222f4a2713aSLionel Sambuc void sls_fun_bad_3() {
223f4a2713aSLionel Sambuc   sls_mu.Lock(); // expected-note {{mutex acquired here}}
224*0a6a1f1dSLionel Sambuc } // expected-warning{{mutex 'sls_mu' is still held at the end of function}}
225f4a2713aSLionel Sambuc 
sls_fun_bad_4()226f4a2713aSLionel Sambuc void sls_fun_bad_4() {
227f4a2713aSLionel Sambuc   if (getBool())
228f4a2713aSLionel Sambuc     sls_mu.Lock();  // expected-note{{mutex acquired here}}
229f4a2713aSLionel Sambuc   else
230f4a2713aSLionel Sambuc     sls_mu2.Lock(); // expected-note{{mutex acquired here}}
231*0a6a1f1dSLionel Sambuc } // expected-warning{{mutex 'sls_mu' is not held on every path through here}}  \
232*0a6a1f1dSLionel Sambuc   // expected-warning{{mutex 'sls_mu2' is not held on every path through here}}
233f4a2713aSLionel Sambuc 
sls_fun_bad_5()234f4a2713aSLionel Sambuc void sls_fun_bad_5() {
235f4a2713aSLionel Sambuc   sls_mu.Lock(); // expected-note {{mutex acquired here}}
236f4a2713aSLionel Sambuc   if (getBool())
237f4a2713aSLionel Sambuc     sls_mu.Unlock();
238*0a6a1f1dSLionel Sambuc } // expected-warning{{mutex 'sls_mu' is not held on every path through here}}
239f4a2713aSLionel Sambuc 
sls_fun_bad_6()240f4a2713aSLionel Sambuc void sls_fun_bad_6() {
241f4a2713aSLionel Sambuc   if (getBool()) {
242f4a2713aSLionel Sambuc     sls_mu.Lock(); // expected-note {{mutex acquired here}}
243f4a2713aSLionel Sambuc   } else {
244f4a2713aSLionel Sambuc     if (getBool()) {
245f4a2713aSLionel Sambuc       getBool(); // EMPTY
246f4a2713aSLionel Sambuc     } else {
247f4a2713aSLionel Sambuc       getBool(); // EMPTY
248f4a2713aSLionel Sambuc     }
249f4a2713aSLionel Sambuc   }
250f4a2713aSLionel Sambuc   sls_mu.Unlock(); // \
251*0a6a1f1dSLionel Sambuc     expected-warning{{mutex 'sls_mu' is not held on every path through here}}\
252*0a6a1f1dSLionel Sambuc     expected-warning{{releasing mutex 'sls_mu' that was not held}}
253f4a2713aSLionel Sambuc }
254f4a2713aSLionel Sambuc 
sls_fun_bad_7()255f4a2713aSLionel Sambuc void sls_fun_bad_7() {
256f4a2713aSLionel Sambuc   sls_mu.Lock();
257f4a2713aSLionel Sambuc   while (getBool()) {
258f4a2713aSLionel Sambuc     sls_mu.Unlock();
259f4a2713aSLionel Sambuc     if (getBool()) {
260f4a2713aSLionel Sambuc       if (getBool()) {
261f4a2713aSLionel Sambuc         continue; // \
262*0a6a1f1dSLionel Sambuc         expected-warning{{expecting mutex 'sls_mu' to be held at start of each loop}}
263f4a2713aSLionel Sambuc       }
264f4a2713aSLionel Sambuc     }
265f4a2713aSLionel Sambuc     sls_mu.Lock(); // expected-note {{mutex acquired here}}
266f4a2713aSLionel Sambuc   }
267f4a2713aSLionel Sambuc   sls_mu.Unlock();
268f4a2713aSLionel Sambuc }
269f4a2713aSLionel Sambuc 
sls_fun_bad_8()270f4a2713aSLionel Sambuc void sls_fun_bad_8() {
271f4a2713aSLionel Sambuc   sls_mu.Lock(); // expected-note{{mutex acquired here}}
272f4a2713aSLionel Sambuc 
273f4a2713aSLionel Sambuc   do {
274*0a6a1f1dSLionel Sambuc     sls_mu.Unlock(); // expected-warning{{expecting mutex 'sls_mu' to be held at start of each loop}}
275f4a2713aSLionel Sambuc   } while (getBool());
276f4a2713aSLionel Sambuc }
277f4a2713aSLionel Sambuc 
sls_fun_bad_9()278f4a2713aSLionel Sambuc void sls_fun_bad_9() {
279f4a2713aSLionel Sambuc   do {
280f4a2713aSLionel Sambuc     sls_mu.Lock();  // \
281*0a6a1f1dSLionel Sambuc       // expected-warning{{expecting mutex 'sls_mu' to be held at start of each loop}} \
282f4a2713aSLionel Sambuc       // expected-note{{mutex acquired here}}
283f4a2713aSLionel Sambuc   } while (getBool());
284f4a2713aSLionel Sambuc   sls_mu.Unlock();
285f4a2713aSLionel Sambuc }
286f4a2713aSLionel Sambuc 
sls_fun_bad_10()287f4a2713aSLionel Sambuc void sls_fun_bad_10() {
288f4a2713aSLionel Sambuc   sls_mu.Lock();  // expected-note 2{{mutex acquired here}}
289*0a6a1f1dSLionel Sambuc   while(getBool()) {  // expected-warning{{expecting mutex 'sls_mu' to be held at start of each loop}}
290f4a2713aSLionel Sambuc     sls_mu.Unlock();
291f4a2713aSLionel Sambuc   }
292*0a6a1f1dSLionel Sambuc } // expected-warning{{mutex 'sls_mu' is still held at the end of function}}
293f4a2713aSLionel Sambuc 
sls_fun_bad_11()294f4a2713aSLionel Sambuc void sls_fun_bad_11() {
295f4a2713aSLionel Sambuc   while (getBool()) { // \
296*0a6a1f1dSLionel Sambuc       expected-warning{{expecting mutex 'sls_mu' to be held at start of each loop}}
297f4a2713aSLionel Sambuc     sls_mu.Lock(); // expected-note {{mutex acquired here}}
298f4a2713aSLionel Sambuc   }
299f4a2713aSLionel Sambuc   sls_mu.Unlock(); // \
300*0a6a1f1dSLionel Sambuc     // expected-warning{{releasing mutex 'sls_mu' that was not held}}
301f4a2713aSLionel Sambuc }
302f4a2713aSLionel Sambuc 
sls_fun_bad_12()303f4a2713aSLionel Sambuc void sls_fun_bad_12() {
304f4a2713aSLionel Sambuc   sls_mu.Lock(); // expected-note {{mutex acquired here}}
305f4a2713aSLionel Sambuc   while (getBool()) {
306f4a2713aSLionel Sambuc     sls_mu.Unlock();
307f4a2713aSLionel Sambuc     if (getBool()) {
308f4a2713aSLionel Sambuc       if (getBool()) {
309*0a6a1f1dSLionel Sambuc         break; // expected-warning{{mutex 'sls_mu' is not held on every path through here}}
310f4a2713aSLionel Sambuc       }
311f4a2713aSLionel Sambuc     }
312f4a2713aSLionel Sambuc     sls_mu.Lock();
313f4a2713aSLionel Sambuc   }
314f4a2713aSLionel Sambuc   sls_mu.Unlock();
315f4a2713aSLionel Sambuc }
316f4a2713aSLionel Sambuc 
317f4a2713aSLionel Sambuc #endif
318