blob: 344de809078755de2ba6f7d20974a7f4e3a12a67 [file] [log] [blame]
George Karpenkov96625fd2018-01-02 23:05:47 +00001// 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
George Karpenkov657a5892017-09-30 00:03:22 +00003
George Karpenkov03544832017-11-03 00:36:03 +00004// We do NOT model libcxx03 implementation, but the analyzer should still
5// not crash.
George Karpenkov96625fd2018-01-02 23:05:47 +00006// 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
George Karpenkov03544832017-11-03 00:36:03 +00009
George Karpenkov657a5892017-09-30 00:03:22 +000010void clang_analyzer_eval(bool);
11
George Karpenkov59202322018-02-02 01:44:07 +000012// Faking std::call_once implementation.
George Karpenkov657a5892017-09-30 00:03:22 +000013namespace std {
George Karpenkovc928e1f2017-10-11 20:53:01 +000014
George Karpenkov59202322018-02-02 01:44:07 +000015// Fake std::function implementation.
16template <typename>
17class function;
18class function_base {
19 public:
20 long field;
21};
22template <typename R, typename... P>
23class function<R(P...)> : function_base {
24 public:
25 R operator()(P...) const {
26
27 // Read from a super-class necessary to reproduce a crash.
28 bool a = field;
29 }
30};
31
George Karpenkovc928e1f2017-10-11 20:53:01 +000032#ifndef EMULATE_LIBSTDCPP
George Karpenkov657a5892017-09-30 00:03:22 +000033typedef struct once_flag_s {
34 unsigned long __state_ = 0;
35} once_flag;
George Karpenkovc928e1f2017-10-11 20:53:01 +000036#else
37typedef struct once_flag_s {
38 int _M_once = 0;
39} once_flag;
40#endif
George Karpenkov657a5892017-09-30 00:03:22 +000041
George Karpenkov03544832017-11-03 00:36:03 +000042#ifndef EMULATE_LIBCXX03
George Karpenkov657a5892017-09-30 00:03:22 +000043template <class Callable, class... Args>
George Karpenkovb2a60c62017-10-17 22:28:18 +000044void call_once(once_flag &o, Callable&& func, Args&&... args) {};
George Karpenkov03544832017-11-03 00:36:03 +000045#else
46template <class Callable, class... Args> // libcxx03 call_once
47void call_once(once_flag &o, Callable func, Args&&... args) {};
48#endif
George Karpenkovc928e1f2017-10-11 20:53:01 +000049
George Karpenkov657a5892017-09-30 00:03:22 +000050} // namespace std
51
52// Check with Lambdas.
53void test_called_warning() {
54 std::once_flag g_initialize;
55 int z;
56
57 std::call_once(g_initialize, [&] {
58 int *x = nullptr;
George Karpenkov03544832017-11-03 00:36:03 +000059#ifndef EMULATE_LIBCXX03
George Karpenkov657a5892017-09-30 00:03:22 +000060 int y = *x; // expected-warning{{Dereference of null pointer (loaded from variable 'x')}}
George Karpenkov03544832017-11-03 00:36:03 +000061#endif
George Karpenkov657a5892017-09-30 00:03:22 +000062 z = 200;
63 });
64}
65
66void 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
George Karpenkov03544832017-11-03 00:36:03 +000078#ifndef EMULATE_LIBCXX03
George Karpenkov657a5892017-09-30 00:03:22 +000079 *x = 100; // no-warning
80 clang_analyzer_eval(z == 100); // expected-warning{{TRUE}}
George Karpenkov03544832017-11-03 00:36:03 +000081#endif
George Karpenkov657a5892017-09-30 00:03:22 +000082}
83
84void 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
George Karpenkov03544832017-11-03 00:36:03 +000094#ifndef EMULATE_LIBCXX03
George Karpenkov657a5892017-09-30 00:03:22 +000095 *x = 100; // no-warning
George Karpenkov03544832017-11-03 00:36:03 +000096#else
97 *x = 100; // expected-warning{{Dereference of null pointer (loaded from variable 'x')}}
98#endif
George Karpenkov657a5892017-09-30 00:03:22 +000099}
100
101void 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
George Karpenkov03544832017-11-03 00:36:03 +0000111#ifndef EMULATE_LIBCXX03
George Karpenkov657a5892017-09-30 00:03:22 +0000112 *x = 100; // expected-warning{{Dereference of null pointer (loaded from variable 'x')}}
George Karpenkov03544832017-11-03 00:36:03 +0000113#endif
George Karpenkov657a5892017-09-30 00:03:22 +0000114}
115
116void 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
George Karpenkov03544832017-11-03 00:36:03 +0000130#ifndef EMULATE_LIBCXX03
George Karpenkov657a5892017-09-30 00:03:22 +0000131 *x = 100; // expected-warning{{Dereference of null pointer (loaded from variable 'x')}}
George Karpenkov03544832017-11-03 00:36:03 +0000132#endif
George Karpenkov657a5892017-09-30 00:03:22 +0000133}
134
135void 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
George Karpenkov03544832017-11-03 00:36:03 +0000149#ifndef EMULATE_LIBCXX03
George Karpenkov657a5892017-09-30 00:03:22 +0000150 *x = 100; // no-warning
George Karpenkov03544832017-11-03 00:36:03 +0000151#endif
George Karpenkov657a5892017-09-30 00:03:22 +0000152}
153
154static int global = 0;
155void funcPointer() {
156 global = 1;
157}
158
159void test_func_pointers() {
160 static std::once_flag flag;
161 std::call_once(flag, &funcPointer);
George Karpenkov03544832017-11-03 00:36:03 +0000162#ifndef EMULATE_LIBCXX03
George Karpenkov657a5892017-09-30 00:03:22 +0000163 clang_analyzer_eval(global == 1); // expected-warning{{TRUE}}
George Karpenkov03544832017-11-03 00:36:03 +0000164#endif
George Karpenkov657a5892017-09-30 00:03:22 +0000165}
166
167template <class _Fp>
168class function; // undefined
169template <class _Rp, class... _ArgTypes>
170struct function<_Rp(_ArgTypes...)> {
George Karpenkov305ee8e2017-09-30 01:15:35 +0000171 _Rp operator()(_ArgTypes...) const {};
George Karpenkov657a5892017-09-30 00:03:22 +0000172 template <class _Fp>
George Karpenkov305ee8e2017-09-30 01:15:35 +0000173 function(_Fp) {};
George Karpenkov657a5892017-09-30 00:03:22 +0000174};
175
176// Note: currently we do not support calls to std::function,
177// but the analyzer should not crash either.
178void 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
194void 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
George Karpenkov03544832017-11-03 00:36:03 +0000204#ifndef EMULATE_LIBCXX03
George Karpenkov657a5892017-09-30 00:03:22 +0000205 clang_analyzer_eval(y == 120); // expected-warning{{TRUE}}
George Karpenkov03544832017-11-03 00:36:03 +0000206#endif
George Karpenkov657a5892017-09-30 00:03:22 +0000207}
208
209void 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
George Karpenkov03544832017-11-03 00:36:03 +0000218#ifndef EMULATE_LIBCXX03
George Karpenkov657a5892017-09-30 00:03:22 +0000219 clang_analyzer_eval(x == 120); // expected-warning{{FALSE}}
George Karpenkov03544832017-11-03 00:36:03 +0000220#endif
George Karpenkov657a5892017-09-30 00:03:22 +0000221}
222
223void 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);
George Karpenkov03544832017-11-03 00:36:03 +0000233#ifndef EMULATE_LIBCXX03
George Karpenkov657a5892017-09-30 00:03:22 +0000234 clang_analyzer_eval(y == 120); // expected-warning{{TRUE}}
George Karpenkov03544832017-11-03 00:36:03 +0000235#endif
George Karpenkov657a5892017-09-30 00:03:22 +0000236}
237
238void 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
George Karpenkov03544832017-11-03 00:36:03 +0000247#ifndef EMULATE_LIBCXX03
George Karpenkov657a5892017-09-30 00:03:22 +0000248 clang_analyzer_eval(x == 120); // expected-warning{{FALSE}}
249 clang_analyzer_eval(x == 6); // expected-warning{{TRUE}}
George Karpenkov03544832017-11-03 00:36:03 +0000250#endif
George Karpenkov657a5892017-09-30 00:03:22 +0000251}
252
253static int global2 = 0;
254void 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);
George Karpenkov03544832017-11-03 00:36:03 +0000261#ifndef EMULATE_LIBCXX03
George Karpenkov657a5892017-09-30 00:03:22 +0000262 clang_analyzer_eval(global2 == 6); // expected-warning{{TRUE}}
George Karpenkov03544832017-11-03 00:36:03 +0000263#endif
George Karpenkov657a5892017-09-30 00:03:22 +0000264}
265
266static int global3 = 0;
267void funcptr(int a, int b, int c) {
268 global3 = a + b + c;
269}
270
271void test_param_passing_funcptr() {
272 std::once_flag flag;
273 global3 = 0;
274
275 std::call_once(flag, &funcptr, 1, 2, 3);
276
George Karpenkov03544832017-11-03 00:36:03 +0000277#ifndef EMULATE_LIBCXX03
George Karpenkov657a5892017-09-30 00:03:22 +0000278 clang_analyzer_eval(global3 == 6); // expected-warning{{TRUE}}
George Karpenkov03544832017-11-03 00:36:03 +0000279#endif
George Karpenkov657a5892017-09-30 00:03:22 +0000280}
281
282void test_blocks() {
283 global3 = 0;
284 std::once_flag flag;
285 std::call_once(flag, ^{
286 global3 = 120;
287 });
George Karpenkov03544832017-11-03 00:36:03 +0000288#ifndef EMULATE_LIBCXX03
George Karpenkov657a5892017-09-30 00:03:22 +0000289 clang_analyzer_eval(global3 == 120); // expected-warning{{TRUE}}
George Karpenkov03544832017-11-03 00:36:03 +0000290#endif
George Karpenkov657a5892017-09-30 00:03:22 +0000291}
292
293int call_once() {
294 return 5;
295}
296
297void test_non_std_call_once() {
298 int x = call_once();
George Karpenkov03544832017-11-03 00:36:03 +0000299#ifndef EMULATE_LIBCXX03
George Karpenkov657a5892017-09-30 00:03:22 +0000300 clang_analyzer_eval(x == 5); // expected-warning{{TRUE}}
George Karpenkov03544832017-11-03 00:36:03 +0000301#endif
George Karpenkov657a5892017-09-30 00:03:22 +0000302}
George Karpenkov8b53f7c2017-10-09 23:20:46 +0000303
304namespace std {
305template <typename d, typename e>
306void call_once(d, e);
307}
308void g();
309void test_no_segfault_on_different_impl() {
George Karpenkov03544832017-11-03 00:36:03 +0000310#ifndef EMULATE_LIBCXX03
George Karpenkov8b53f7c2017-10-09 23:20:46 +0000311 std::call_once(g, false); // no-warning
George Karpenkov03544832017-11-03 00:36:03 +0000312#endif
George Karpenkov8b53f7c2017-10-09 23:20:46 +0000313}
George Karpenkovbd4254c2017-10-20 23:29:59 +0000314
315void test_lambda_refcapture() {
316 static std::once_flag flag;
317 int a = 6;
318 std::call_once(flag, [&](int &a) { a = 42; }, a);
George Karpenkov03544832017-11-03 00:36:03 +0000319#ifndef EMULATE_LIBCXX03
George Karpenkovbd4254c2017-10-20 23:29:59 +0000320 clang_analyzer_eval(a == 42); // expected-warning{{TRUE}}
George Karpenkov03544832017-11-03 00:36:03 +0000321#endif
George Karpenkovbd4254c2017-10-20 23:29:59 +0000322}
323
324void test_lambda_refcapture2() {
325 static std::once_flag flag;
326 int a = 6;
327 std::call_once(flag, [=](int &a) { a = 42; }, a);
George Karpenkov03544832017-11-03 00:36:03 +0000328#ifndef EMULATE_LIBCXX03
George Karpenkovbd4254c2017-10-20 23:29:59 +0000329 clang_analyzer_eval(a == 42); // expected-warning{{TRUE}}
George Karpenkov03544832017-11-03 00:36:03 +0000330#endif
George Karpenkovbd4254c2017-10-20 23:29:59 +0000331}
332
333void test_lambda_fail_refcapture() {
334 static std::once_flag flag;
335 int a = 6;
336 std::call_once(flag, [=](int a) { a = 42; }, a);
George Karpenkov03544832017-11-03 00:36:03 +0000337#ifndef EMULATE_LIBCXX03
George Karpenkovbd4254c2017-10-20 23:29:59 +0000338 clang_analyzer_eval(a == 42); // expected-warning{{FALSE}}
George Karpenkov03544832017-11-03 00:36:03 +0000339#endif
George Karpenkovbd4254c2017-10-20 23:29:59 +0000340}
341
342void mutator(int &param) {
343 param = 42;
344}
345void test_reftypes_funcptr() {
346 static std::once_flag flag;
347 int a = 6;
348 std::call_once(flag, &mutator, a);
George Karpenkov03544832017-11-03 00:36:03 +0000349#ifndef EMULATE_LIBCXX03
George Karpenkovbd4254c2017-10-20 23:29:59 +0000350 clang_analyzer_eval(a == 42); // expected-warning{{TRUE}}
George Karpenkov03544832017-11-03 00:36:03 +0000351#endif
George Karpenkovbd4254c2017-10-20 23:29:59 +0000352}
353
354void fail_mutator(int param) {
355 param = 42;
356}
357void test_mutator_noref() {
358 static std::once_flag flag;
359 int a = 6;
360 std::call_once(flag, &fail_mutator, a);
George Karpenkov03544832017-11-03 00:36:03 +0000361#ifndef EMULATE_LIBCXX03
George Karpenkovbd4254c2017-10-20 23:29:59 +0000362 clang_analyzer_eval(a == 42); // expected-warning{{FALSE}}
George Karpenkov03544832017-11-03 00:36:03 +0000363#endif
George Karpenkovbd4254c2017-10-20 23:29:59 +0000364}
George Karpenkov98e81cd2017-10-24 00:13:18 +0000365
366// Function is implicitly treated as a function pointer
367// even when an ampersand is not explicitly set.
368void callbackn(int &param) {
369 param = 42;
George Karpenkovf671bd22017-10-25 00:03:45 +0000370}
George Karpenkov98e81cd2017-10-24 00:13:18 +0000371void test_implicit_funcptr() {
372 int x = 0;
373 static std::once_flag flagn;
374
375 std::call_once(flagn, callbackn, x);
George Karpenkov03544832017-11-03 00:36:03 +0000376#ifndef EMULATE_LIBCXX03
George Karpenkov98e81cd2017-10-24 00:13:18 +0000377 clang_analyzer_eval(x == 42); // expected-warning{{TRUE}}
George Karpenkov03544832017-11-03 00:36:03 +0000378#endif
George Karpenkov98e81cd2017-10-24 00:13:18 +0000379}
George Karpenkov59202322018-02-02 01:44:07 +0000380
381int param_passed(int *x) {
382 return *x; // no-warning, as std::function is not working yet.
383}
384
385void 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.
391void callback_with_implicit_cast_ok() {
392 std::once_flag flag;
393 call_once(flag, callback_taking_func_ok, &param_passed);
394}
395
396void 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.
402void callback_with_implicit_cast() {
403 std::once_flag flag;
404 call_once(flag, callback_taking_func, callback_with_implicit_cast);
405}
George Karpenkovfaa03f42018-05-16 00:29:13 +0000406
407std::once_flag another_once_flag;
408typedef void (*my_callback_t)(int *);
409my_callback_t callback;
410int global_int;
411
412void rdar40270582() {
413 call_once(another_once_flag, callback, &global_int);
414}