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
33class  __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
43class __attribute__((scoped_lockable)) MutexLock {
44 public:
45  MutexLock(Mutex *mu) __attribute__((exclusive_lock_function(mu)));
46  ~MutexLock() __attribute__((unlock_function));
47};
48
49class __attribute__((scoped_lockable)) ReaderMutexLock {
50 public:
51  ReaderMutexLock(Mutex *mu) __attribute__((exclusive_lock_function(mu)));
52  ~ReaderMutexLock() __attribute__((unlock_function));
53};
54
55class 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.
66void beginNoWarnOnReads()  SHARED_LOCK_FUNCTION("*");
67void endNoWarnOnReads()    UNLOCK_FUNCTION("*");
68void beginNoWarnOnWrites() EXCLUSIVE_LOCK_FUNCTION("*");
69void endNoWarnOnWrites()   UNLOCK_FUNCTION("*");
70
71
72// For testing handling of smart pointers.
73template<class T>
74class SmartPtr {
75public:
76  SmartPtr(T* p) : ptr_(p) { }
77  SmartPtr(const SmartPtr<T>& p) : ptr_(p.ptr_) { }
78  ~SmartPtr();
79
80  T* get()        const { return ptr_; }
81  T* operator->() const { return ptr_; }
82  T& operator*()  const { return *ptr_; }
83
84private:
85  T* ptr_;
86};
87
88
89// For testing destructor calls and cleanup.
90class MyString {
91public:
92  MyString(const char* s);
93  ~MyString();
94};
95
96
97
98Mutex sls_mu;
99
100Mutex sls_mu2 __attribute__((acquired_after(sls_mu)));
101int sls_guard_var __attribute__((guarded_var)) = 0;
102int sls_guardby_var __attribute__((guarded_by(sls_mu))) = 0;
103
104bool getBool();
105
106class MutexWrapper {
107public:
108   Mutex mu;
109   int x __attribute__((guarded_by(mu)));
110   void MyLock() __attribute__((exclusive_lock_function(mu)));
111};
112
113#else
114
115MutexWrapper sls_mw;
116
117void sls_fun_0() {
118  sls_mw.mu.Lock();
119  sls_mw.x = 5;
120  sls_mw.mu.Unlock();
121}
122
123void sls_fun_2() {
124  sls_mu.Lock();
125  int x = sls_guard_var;
126  sls_mu.Unlock();
127}
128
129void sls_fun_3() {
130  sls_mu.Lock();
131  sls_guard_var = 2;
132  sls_mu.Unlock();
133}
134
135void sls_fun_4() {
136  sls_mu2.Lock();
137  sls_guard_var = 2;
138  sls_mu2.Unlock();
139}
140
141void sls_fun_5() {
142  sls_mu.Lock();
143  int x = sls_guardby_var;
144  sls_mu.Unlock();
145}
146
147void sls_fun_6() {
148  sls_mu.Lock();
149  sls_guardby_var = 2;
150  sls_mu.Unlock();
151}
152
153void sls_fun_7() {
154  sls_mu.Lock();
155  sls_mu2.Lock();
156  sls_mu2.Unlock();
157  sls_mu.Unlock();
158}
159
160void sls_fun_8() {
161  sls_mu.Lock();
162  if (getBool())
163    sls_mu.Unlock();
164  else
165    sls_mu.Unlock();
166}
167
168void sls_fun_9() {
169  if (getBool())
170    sls_mu.Lock();
171  else
172    sls_mu.Lock();
173  sls_mu.Unlock();
174}
175
176void 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
190void 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
205void sls_fun_good_8() {
206  sls_mw.MyLock();
207  sls_mw.mu.Unlock();
208}
209
210void sls_fun_bad_1() {
211  sls_mu.Unlock(); // \
212    // expected-warning{{releasing mutex 'sls_mu' that was not held}}
213}
214
215void sls_fun_bad_2() {
216  sls_mu.Lock();
217  sls_mu.Lock(); // \
218    // expected-warning{{acquiring mutex 'sls_mu' that is already held}}
219  sls_mu.Unlock();
220}
221
222void 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
226void 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
234void 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
240void 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
255void 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
270void 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
278void 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
287void 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
294void 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
303void 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