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