1 // RUN: %clang_analyze_cc1 -analyzer-checker=alpha.unix.BlockInCriticalSection -std=c++11 -verify %s
2 
sleep(int x)3 void sleep(int x) {}
4 
5 namespace std {
6 struct mutex {
lockstd::mutex7   void lock() {}
unlockstd::mutex8   void unlock() {}
9 };
10 template<typename T>
11 struct lock_guard {
12   lock_guard<T>(std::mutex) {}
13   ~lock_guard<T>() {}
14 };
15 template<typename T>
16 struct unique_lock {
17   unique_lock<T>(std::mutex) {}
18   ~unique_lock<T>() {}
19 };
20 template<typename T>
21 struct not_real_lock {
22   not_real_lock<T>(std::mutex) {}
23 };
24 }
25 
getc()26 void getc() {}
fgets()27 void fgets() {}
read()28 void read() {}
recv()29 void recv() {}
30 
pthread_mutex_lock()31 void pthread_mutex_lock() {}
pthread_mutex_trylock()32 void pthread_mutex_trylock() {}
pthread_mutex_unlock()33 void pthread_mutex_unlock() {}
34 
mtx_lock()35 void mtx_lock() {}
mtx_timedlock()36 void mtx_timedlock() {}
mtx_trylock()37 void mtx_trylock() {}
mtx_unlock()38 void mtx_unlock() {}
39 
testBlockInCriticalSectionWithStdMutex()40 void testBlockInCriticalSectionWithStdMutex() {
41   std::mutex m;
42   m.lock();
43   sleep(3); // expected-warning {{Call to blocking function 'sleep' inside of critical section}}
44   getc(); // expected-warning {{Call to blocking function 'getc' inside of critical section}}
45   fgets(); // expected-warning {{Call to blocking function 'fgets' inside of critical section}}
46   read(); // expected-warning {{Call to blocking function 'read' inside of critical section}}
47   recv(); // expected-warning {{Call to blocking function 'recv' inside of critical section}}
48   m.unlock();
49 }
50 
testBlockInCriticalSectionWithPthreadMutex()51 void testBlockInCriticalSectionWithPthreadMutex() {
52   pthread_mutex_lock();
53   sleep(3); // expected-warning {{Call to blocking function 'sleep' inside of critical section}}
54   getc(); // expected-warning {{Call to blocking function 'getc' inside of critical section}}
55   fgets(); // expected-warning {{Call to blocking function 'fgets' inside of critical section}}
56   read(); // expected-warning {{Call to blocking function 'read' inside of critical section}}
57   recv(); // expected-warning {{Call to blocking function 'recv' inside of critical section}}
58   pthread_mutex_unlock();
59 
60   pthread_mutex_trylock();
61   sleep(3); // expected-warning {{Call to blocking function 'sleep' inside of critical section}}
62   getc(); // expected-warning {{Call to blocking function 'getc' inside of critical section}}
63   fgets(); // expected-warning {{Call to blocking function 'fgets' inside of critical section}}
64   read(); // expected-warning {{Call to blocking function 'read' inside of critical section}}
65   recv(); // expected-warning {{Call to blocking function 'recv' inside of critical section}}
66   pthread_mutex_unlock();
67 }
68 
testBlockInCriticalSectionC11Locks()69 void testBlockInCriticalSectionC11Locks() {
70   mtx_lock();
71   sleep(3); // expected-warning {{Call to blocking function 'sleep' inside of critical section}}
72   getc(); // expected-warning {{Call to blocking function 'getc' inside of critical section}}
73   fgets(); // expected-warning {{Call to blocking function 'fgets' inside of critical section}}
74   read(); // expected-warning {{Call to blocking function 'read' inside of critical section}}
75   recv(); // expected-warning {{Call to blocking function 'recv' inside of critical section}}
76   mtx_unlock();
77 
78   mtx_timedlock();
79   sleep(3); // expected-warning {{Call to blocking function 'sleep' inside of critical section}}
80   getc(); // expected-warning {{Call to blocking function 'getc' inside of critical section}}
81   fgets(); // expected-warning {{Call to blocking function 'fgets' inside of critical section}}
82   read(); // expected-warning {{Call to blocking function 'read' inside of critical section}}
83   recv(); // expected-warning {{Call to blocking function 'recv' inside of critical section}}
84   mtx_unlock();
85 
86   mtx_trylock();
87   sleep(3); // expected-warning {{Call to blocking function 'sleep' inside of critical section}}
88   getc(); // expected-warning {{Call to blocking function 'getc' inside of critical section}}
89   fgets(); // expected-warning {{Call to blocking function 'fgets' inside of critical section}}
90   read(); // expected-warning {{Call to blocking function 'read' inside of critical section}}
91   recv(); // expected-warning {{Call to blocking function 'recv' inside of critical section}}
92   mtx_unlock();
93 }
94 
testBlockInCriticalSectionWithNestedMutexes()95 void testBlockInCriticalSectionWithNestedMutexes() {
96   std::mutex m, n, k;
97   m.lock();
98   n.lock();
99   k.lock();
100   sleep(3); // expected-warning {{Call to blocking function 'sleep' inside of critical section}}
101   k.unlock();
102   sleep(5); // expected-warning {{Call to blocking function 'sleep' inside of critical section}}
103   n.unlock();
104   sleep(3); // expected-warning {{Call to blocking function 'sleep' inside of critical section}}
105   m.unlock();
106   sleep(3); // no-warning
107 }
108 
f()109 void f() {
110   sleep(1000); // expected-warning {{Call to blocking function 'sleep' inside of critical section}}
111 }
112 
testBlockInCriticalSectionInterProcedural()113 void testBlockInCriticalSectionInterProcedural() {
114   std::mutex m;
115   m.lock();
116   f();
117   m.unlock();
118 }
119 
testBlockInCriticalSectionUnexpectedUnlock()120 void testBlockInCriticalSectionUnexpectedUnlock() {
121   std::mutex m;
122   m.unlock();
123   sleep(1); // no-warning
124   m.lock();
125   sleep(1); // expected-warning {{Call to blocking function 'sleep' inside of critical section}}
126 }
127 
testBlockInCriticalSectionLockGuard()128 void testBlockInCriticalSectionLockGuard() {
129   std::mutex g_mutex;
130   std::not_real_lock<std::mutex> not_real_lock(g_mutex);
131   sleep(1); // no-warning
132 
133   std::lock_guard<std::mutex> lock(g_mutex);
134   sleep(1); // expected-warning {{Call to blocking function 'sleep' inside of critical section}}
135 }
136 
testBlockInCriticalSectionLockGuardNested()137 void testBlockInCriticalSectionLockGuardNested() {
138   testBlockInCriticalSectionLockGuard();
139   sleep(1); // no-warning
140 }
141 
testBlockInCriticalSectionUniqueLock()142 void testBlockInCriticalSectionUniqueLock() {
143   std::mutex g_mutex;
144   std::not_real_lock<std::mutex> not_real_lock(g_mutex);
145   sleep(1); // no-warning
146 
147   std::unique_lock<std::mutex> lock(g_mutex);
148   sleep(1); // expected-warning {{Call to blocking function 'sleep' inside of critical section}}
149 }
150 
testBlockInCriticalSectionUniqueLockNested()151 void testBlockInCriticalSectionUniqueLockNested() {
152   testBlockInCriticalSectionUniqueLock();
153   sleep(1); // no-warning
154 }
155