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