1 | // RUN: %clang_analyze_cc1 -analyzer-checker=alpha.unix.BlockInCriticalSection -std=c++11 -verify %s |
2 | |
3 | void sleep(int x) {} |
4 | |
5 | namespace std { |
6 | struct mutex { |
7 | void lock() {} |
8 | 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 | |
26 | void getc() {} |
27 | void fgets() {} |
28 | void read() {} |
29 | void recv() {} |
30 | |
31 | void pthread_mutex_lock() {} |
32 | void pthread_mutex_trylock() {} |
33 | void pthread_mutex_unlock() {} |
34 | |
35 | void mtx_lock() {} |
36 | void mtx_timedlock() {} |
37 | void mtx_trylock() {} |
38 | void mtx_unlock() {} |
39 | |
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 | |
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 | |
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 | |
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 | |
109 | void f() { |
110 | sleep(1000); // expected-warning {{Call to blocking function 'sleep' inside of critical section}} |
111 | } |
112 | |
113 | void testBlockInCriticalSectionInterProcedural() { |
114 | std::mutex m; |
115 | m.lock(); |
116 | f(); |
117 | m.unlock(); |
118 | } |
119 | |
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 | |
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 | |
137 | void testBlockInCriticalSectionLockGuardNested() { |
138 | testBlockInCriticalSectionLockGuard(); |
139 | sleep(1); // no-warning |
140 | } |
141 | |
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 | |
151 | void testBlockInCriticalSectionUniqueLockNested() { |
152 | testBlockInCriticalSectionUniqueLock(); |
153 | sleep(1); // no-warning |
154 | } |
155 | |