1 // RUN: %clang_analyze_cc1 -std=c++11 -fblocks -analyzer-checker=core,debug.ExprInspection -verify %s
2 // RUN: %clang_analyze_cc1 -std=c++11 -fblocks -analyzer-checker=core,debug.ExprInspection -DEMULATE_LIBSTDCPP -verify %s
3 
4 void clang_analyzer_eval(bool);
5 
6 // Faking std::std::call_once implementation.
7 namespace std {
8 
9 #ifndef EMULATE_LIBSTDCPP
10 typedef struct once_flag_s {
11   unsigned long __state_ = 0;
12 } once_flag;
13 #else
14 typedef struct once_flag_s {
15   int _M_once = 0;
16 } once_flag;
17 #endif
18 
19 template <class Callable, class... Args>
20 void call_once(once_flag &o, Callable&& func, Args&&... args) {};
21 
22 } // namespace std
23 
24 // Check with Lambdas.
25 void test_called_warning() {
26   std::once_flag g_initialize;
27   int z;
28 
29   std::call_once(g_initialize, [&] {
30     int *x = nullptr;
31     int y = *x; // expected-warning{{Dereference of null pointer (loaded from variable 'x')}}
32     z = 200;
33   });
34 }
35 
36 void test_called_on_path_inside_no_warning() {
37   std::once_flag g_initialize;
38 
39   int *x = nullptr;
40   int y = 100;
41   int z;
42 
43   std::call_once(g_initialize, [&] {
44     z = 200;
45     x = &z;
46   });
47 
48   *x = 100; // no-warning
49   clang_analyzer_eval(z == 100); // expected-warning{{TRUE}}
50 }
51 
52 void test_called_on_path_no_warning() {
53   std::once_flag g_initialize;
54 
55   int *x = nullptr;
56   int y = 100;
57 
58   std::call_once(g_initialize, [&] {
59     x = &y;
60   });
61 
62   *x = 100; // no-warning
63 }
64 
65 void test_called_on_path_warning() {
66   std::once_flag g_initialize;
67 
68   int y = 100;
69   int *x = &y;
70 
71   std::call_once(g_initialize, [&] {
72     x = nullptr;
73   });
74 
75   *x = 100; // expected-warning{{Dereference of null pointer (loaded from variable 'x')}}
76 }
77 
78 void test_called_once_warning() {
79   std::once_flag g_initialize;
80 
81   int *x = nullptr;
82   int y = 100;
83 
84   std::call_once(g_initialize, [&] {
85     x = nullptr;
86   });
87 
88   std::call_once(g_initialize, [&] {
89     x = &y;
90   });
91 
92   *x = 100; // expected-warning{{Dereference of null pointer (loaded from variable 'x')}}
93 }
94 
95 void test_called_once_no_warning() {
96   std::once_flag g_initialize;
97 
98   int *x = nullptr;
99   int y = 100;
100 
101   std::call_once(g_initialize, [&] {
102     x = &y;
103   });
104 
105   std::call_once(g_initialize, [&] {
106     x = nullptr;
107   });
108 
109   *x = 100; // no-warning
110 }
111 
112 static int global = 0;
113 void funcPointer() {
114   global = 1;
115 }
116 
117 void test_func_pointers() {
118   static std::once_flag flag;
119   std::call_once(flag, &funcPointer);
120   clang_analyzer_eval(global == 1); // expected-warning{{TRUE}}
121 }
122 
123 template <class _Fp>
124 class function; // undefined
125 template <class _Rp, class... _ArgTypes>
126 struct function<_Rp(_ArgTypes...)> {
127   _Rp operator()(_ArgTypes...) const {};
128   template <class _Fp>
129   function(_Fp) {};
130 };
131 
132 // Note: currently we do not support calls to std::function,
133 // but the analyzer should not crash either.
134 void test_function_objects_warning() {
135   int x = 0;
136   int *y = &x;
137 
138   std::once_flag flag;
139 
140   function<void()> func = [&]() {
141     y = nullptr;
142   };
143 
144   std::call_once(flag, func);
145 
146   func();
147   int z = *y;
148 }
149 
150 void test_param_passing_lambda() {
151   std::once_flag flag;
152   int x = 120;
153   int y = 0;
154 
155   std::call_once(flag, [&](int p) {
156     y = p;
157   },
158                  x);
159 
160   clang_analyzer_eval(y == 120); // expected-warning{{TRUE}}
161 }
162 
163 void test_param_passing_lambda_false() {
164   std::once_flag flag;
165   int x = 120;
166 
167   std::call_once(flag, [&](int p) {
168     x = 0;
169   },
170                  x);
171 
172   clang_analyzer_eval(x == 120); // expected-warning{{FALSE}}
173 }
174 
175 void test_param_passing_stored_lambda() {
176   std::once_flag flag;
177   int x = 120;
178   int y = 0;
179 
180   auto lambda = [&](int p) {
181     y = p;
182   };
183 
184   std::call_once(flag, lambda, x);
185   clang_analyzer_eval(y == 120); // expected-warning{{TRUE}}
186 }
187 
188 void test_multiparam_passing_lambda() {
189   std::once_flag flag;
190   int x = 120;
191 
192   std::call_once(flag, [&](int a, int b, int c) {
193     x = a + b + c;
194   },
195                  1, 2, 3);
196 
197   clang_analyzer_eval(x == 120); // expected-warning{{FALSE}}
198   clang_analyzer_eval(x == 6); // expected-warning{{TRUE}}
199 }
200 
201 static int global2 = 0;
202 void test_param_passing_lambda_global() {
203   std::once_flag flag;
204   global2 = 0;
205   std::call_once(flag, [&](int a, int b, int c) {
206     global2 = a + b + c;
207   },
208                  1, 2, 3);
209   clang_analyzer_eval(global2 == 6); // expected-warning{{TRUE}}
210 }
211 
212 static int global3 = 0;
213 void funcptr(int a, int b, int c) {
214   global3 = a + b + c;
215 }
216 
217 void test_param_passing_funcptr() {
218   std::once_flag flag;
219   global3 = 0;
220 
221   std::call_once(flag, &funcptr, 1, 2, 3);
222 
223   clang_analyzer_eval(global3 == 6); // expected-warning{{TRUE}}
224 }
225 
226 void test_blocks() {
227   global3 = 0;
228   std::once_flag flag;
229   std::call_once(flag, ^{
230     global3 = 120;
231   });
232   clang_analyzer_eval(global3 == 120); // expected-warning{{TRUE}}
233 }
234 
235 int call_once() {
236   return 5;
237 }
238 
239 void test_non_std_call_once() {
240   int x = call_once();
241   clang_analyzer_eval(x == 5); // expected-warning{{TRUE}}
242 }
243 
244 namespace std {
245 template <typename d, typename e>
246 void call_once(d, e);
247 }
248 void g();
249 void test_no_segfault_on_different_impl() {
250   std::call_once(g, false); // no-warning
251 }
252 
253 void test_lambda_refcapture() {
254   static std::once_flag flag;
255   int a = 6;
256   std::call_once(flag, [&](int &a) { a = 42; }, a);
257   clang_analyzer_eval(a == 42); // expected-warning{{TRUE}}
258 }
259 
260 void test_lambda_refcapture2() {
261   static std::once_flag flag;
262   int a = 6;
263   std::call_once(flag, [=](int &a) { a = 42; }, a);
264   clang_analyzer_eval(a == 42); // expected-warning{{TRUE}}
265 }
266 
267 void test_lambda_fail_refcapture() {
268   static std::once_flag flag;
269   int a = 6;
270   std::call_once(flag, [=](int a) { a = 42; }, a);
271   clang_analyzer_eval(a == 42); // expected-warning{{FALSE}}
272 }
273 
274 void mutator(int &param) {
275   param = 42;
276 }
277 void test_reftypes_funcptr() {
278   static std::once_flag flag;
279   int a = 6;
280   std::call_once(flag, &mutator, a);
281   clang_analyzer_eval(a == 42); // expected-warning{{TRUE}}
282 }
283 
284 void fail_mutator(int param) {
285   param = 42;
286 }
287 void test_mutator_noref() {
288   static std::once_flag flag;
289   int a = 6;
290   std::call_once(flag, &fail_mutator, a);
291   clang_analyzer_eval(a == 42); // expected-warning{{FALSE}}
292 }
293 
294 // Function is implicitly treated as a function pointer
295 // even when an ampersand is not explicitly set.
296 void callbackn(int &param) {
297   param = 42;
298 };
299 void test_implicit_funcptr() {
300   int x = 0;
301   static std::once_flag flagn;
302 
303   std::call_once(flagn, callbackn, x);
304   clang_analyzer_eval(x == 42); // expected-warning{{TRUE}}
305 }
306