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