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