blob: 445c616b3cbbda4fb46dea7b6b710c5e75f911bd [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
12// Faking std::std::call_once implementation.
13namespace std {
George Karpenkovc928e1f2017-10-11 20:53:01 +000014
15#ifndef EMULATE_LIBSTDCPP
George Karpenkov657a5892017-09-30 00:03:22 +000016typedef struct once_flag_s {
17 unsigned long __state_ = 0;
18} once_flag;
George Karpenkovc928e1f2017-10-11 20:53:01 +000019#else
20typedef struct once_flag_s {
21 int _M_once = 0;
22} once_flag;
23#endif
George Karpenkov657a5892017-09-30 00:03:22 +000024
George Karpenkov03544832017-11-03 00:36:03 +000025#ifndef EMULATE_LIBCXX03
George Karpenkov657a5892017-09-30 00:03:22 +000026template <class Callable, class... Args>
George Karpenkovb2a60c62017-10-17 22:28:18 +000027void call_once(once_flag &o, Callable&& func, Args&&... args) {};
George Karpenkov03544832017-11-03 00:36:03 +000028#else
29template <class Callable, class... Args> // libcxx03 call_once
30void call_once(once_flag &o, Callable func, Args&&... args) {};
31#endif
George Karpenkovc928e1f2017-10-11 20:53:01 +000032
George Karpenkov657a5892017-09-30 00:03:22 +000033} // namespace std
34
35// Check with Lambdas.
36void test_called_warning() {
37 std::once_flag g_initialize;
38 int z;
39
40 std::call_once(g_initialize, [&] {
41 int *x = nullptr;
George Karpenkov03544832017-11-03 00:36:03 +000042#ifndef EMULATE_LIBCXX03
George Karpenkov657a5892017-09-30 00:03:22 +000043 int y = *x; // expected-warning{{Dereference of null pointer (loaded from variable 'x')}}
George Karpenkov03544832017-11-03 00:36:03 +000044#endif
George Karpenkov657a5892017-09-30 00:03:22 +000045 z = 200;
46 });
47}
48
49void test_called_on_path_inside_no_warning() {
50 std::once_flag g_initialize;
51
52 int *x = nullptr;
53 int y = 100;
54 int z;
55
56 std::call_once(g_initialize, [&] {
57 z = 200;
58 x = &z;
59 });
60
George Karpenkov03544832017-11-03 00:36:03 +000061#ifndef EMULATE_LIBCXX03
George Karpenkov657a5892017-09-30 00:03:22 +000062 *x = 100; // no-warning
63 clang_analyzer_eval(z == 100); // expected-warning{{TRUE}}
George Karpenkov03544832017-11-03 00:36:03 +000064#endif
George Karpenkov657a5892017-09-30 00:03:22 +000065}
66
67void test_called_on_path_no_warning() {
68 std::once_flag g_initialize;
69
70 int *x = nullptr;
71 int y = 100;
72
73 std::call_once(g_initialize, [&] {
74 x = &y;
75 });
76
George Karpenkov03544832017-11-03 00:36:03 +000077#ifndef EMULATE_LIBCXX03
George Karpenkov657a5892017-09-30 00:03:22 +000078 *x = 100; // no-warning
George Karpenkov03544832017-11-03 00:36:03 +000079#else
80 *x = 100; // expected-warning{{Dereference of null pointer (loaded from variable 'x')}}
81#endif
George Karpenkov657a5892017-09-30 00:03:22 +000082}
83
84void test_called_on_path_warning() {
85 std::once_flag g_initialize;
86
87 int y = 100;
88 int *x = &y;
89
90 std::call_once(g_initialize, [&] {
91 x = nullptr;
92 });
93
George Karpenkov03544832017-11-03 00:36:03 +000094#ifndef EMULATE_LIBCXX03
George Karpenkov657a5892017-09-30 00:03:22 +000095 *x = 100; // expected-warning{{Dereference of null pointer (loaded from variable 'x')}}
George Karpenkov03544832017-11-03 00:36:03 +000096#endif
George Karpenkov657a5892017-09-30 00:03:22 +000097}
98
99void test_called_once_warning() {
100 std::once_flag g_initialize;
101
102 int *x = nullptr;
103 int y = 100;
104
105 std::call_once(g_initialize, [&] {
106 x = nullptr;
107 });
108
109 std::call_once(g_initialize, [&] {
110 x = &y;
111 });
112
George Karpenkov03544832017-11-03 00:36:03 +0000113#ifndef EMULATE_LIBCXX03
George Karpenkov657a5892017-09-30 00:03:22 +0000114 *x = 100; // expected-warning{{Dereference of null pointer (loaded from variable 'x')}}
George Karpenkov03544832017-11-03 00:36:03 +0000115#endif
George Karpenkov657a5892017-09-30 00:03:22 +0000116}
117
118void test_called_once_no_warning() {
119 std::once_flag g_initialize;
120
121 int *x = nullptr;
122 int y = 100;
123
124 std::call_once(g_initialize, [&] {
125 x = &y;
126 });
127
128 std::call_once(g_initialize, [&] {
129 x = nullptr;
130 });
131
George Karpenkov03544832017-11-03 00:36:03 +0000132#ifndef EMULATE_LIBCXX03
George Karpenkov657a5892017-09-30 00:03:22 +0000133 *x = 100; // no-warning
George Karpenkov03544832017-11-03 00:36:03 +0000134#endif
George Karpenkov657a5892017-09-30 00:03:22 +0000135}
136
137static int global = 0;
138void funcPointer() {
139 global = 1;
140}
141
142void test_func_pointers() {
143 static std::once_flag flag;
144 std::call_once(flag, &funcPointer);
George Karpenkov03544832017-11-03 00:36:03 +0000145#ifndef EMULATE_LIBCXX03
George Karpenkov657a5892017-09-30 00:03:22 +0000146 clang_analyzer_eval(global == 1); // expected-warning{{TRUE}}
George Karpenkov03544832017-11-03 00:36:03 +0000147#endif
George Karpenkov657a5892017-09-30 00:03:22 +0000148}
149
150template <class _Fp>
151class function; // undefined
152template <class _Rp, class... _ArgTypes>
153struct function<_Rp(_ArgTypes...)> {
George Karpenkov305ee8e2017-09-30 01:15:35 +0000154 _Rp operator()(_ArgTypes...) const {};
George Karpenkov657a5892017-09-30 00:03:22 +0000155 template <class _Fp>
George Karpenkov305ee8e2017-09-30 01:15:35 +0000156 function(_Fp) {};
George Karpenkov657a5892017-09-30 00:03:22 +0000157};
158
159// Note: currently we do not support calls to std::function,
160// but the analyzer should not crash either.
161void test_function_objects_warning() {
162 int x = 0;
163 int *y = &x;
164
165 std::once_flag flag;
166
167 function<void()> func = [&]() {
168 y = nullptr;
169 };
170
171 std::call_once(flag, func);
172
173 func();
174 int z = *y;
175}
176
177void test_param_passing_lambda() {
178 std::once_flag flag;
179 int x = 120;
180 int y = 0;
181
182 std::call_once(flag, [&](int p) {
183 y = p;
184 },
185 x);
186
George Karpenkov03544832017-11-03 00:36:03 +0000187#ifndef EMULATE_LIBCXX03
George Karpenkov657a5892017-09-30 00:03:22 +0000188 clang_analyzer_eval(y == 120); // expected-warning{{TRUE}}
George Karpenkov03544832017-11-03 00:36:03 +0000189#endif
George Karpenkov657a5892017-09-30 00:03:22 +0000190}
191
192void test_param_passing_lambda_false() {
193 std::once_flag flag;
194 int x = 120;
195
196 std::call_once(flag, [&](int p) {
197 x = 0;
198 },
199 x);
200
George Karpenkov03544832017-11-03 00:36:03 +0000201#ifndef EMULATE_LIBCXX03
George Karpenkov657a5892017-09-30 00:03:22 +0000202 clang_analyzer_eval(x == 120); // expected-warning{{FALSE}}
George Karpenkov03544832017-11-03 00:36:03 +0000203#endif
George Karpenkov657a5892017-09-30 00:03:22 +0000204}
205
206void test_param_passing_stored_lambda() {
207 std::once_flag flag;
208 int x = 120;
209 int y = 0;
210
211 auto lambda = [&](int p) {
212 y = p;
213 };
214
215 std::call_once(flag, lambda, x);
George Karpenkov03544832017-11-03 00:36:03 +0000216#ifndef EMULATE_LIBCXX03
George Karpenkov657a5892017-09-30 00:03:22 +0000217 clang_analyzer_eval(y == 120); // expected-warning{{TRUE}}
George Karpenkov03544832017-11-03 00:36:03 +0000218#endif
George Karpenkov657a5892017-09-30 00:03:22 +0000219}
220
221void test_multiparam_passing_lambda() {
222 std::once_flag flag;
223 int x = 120;
224
225 std::call_once(flag, [&](int a, int b, int c) {
226 x = a + b + c;
227 },
228 1, 2, 3);
229
George Karpenkov03544832017-11-03 00:36:03 +0000230#ifndef EMULATE_LIBCXX03
George Karpenkov657a5892017-09-30 00:03:22 +0000231 clang_analyzer_eval(x == 120); // expected-warning{{FALSE}}
232 clang_analyzer_eval(x == 6); // expected-warning{{TRUE}}
George Karpenkov03544832017-11-03 00:36:03 +0000233#endif
George Karpenkov657a5892017-09-30 00:03:22 +0000234}
235
236static int global2 = 0;
237void test_param_passing_lambda_global() {
238 std::once_flag flag;
239 global2 = 0;
240 std::call_once(flag, [&](int a, int b, int c) {
241 global2 = a + b + c;
242 },
243 1, 2, 3);
George Karpenkov03544832017-11-03 00:36:03 +0000244#ifndef EMULATE_LIBCXX03
George Karpenkov657a5892017-09-30 00:03:22 +0000245 clang_analyzer_eval(global2 == 6); // expected-warning{{TRUE}}
George Karpenkov03544832017-11-03 00:36:03 +0000246#endif
George Karpenkov657a5892017-09-30 00:03:22 +0000247}
248
249static int global3 = 0;
250void funcptr(int a, int b, int c) {
251 global3 = a + b + c;
252}
253
254void test_param_passing_funcptr() {
255 std::once_flag flag;
256 global3 = 0;
257
258 std::call_once(flag, &funcptr, 1, 2, 3);
259
George Karpenkov03544832017-11-03 00:36:03 +0000260#ifndef EMULATE_LIBCXX03
George Karpenkov657a5892017-09-30 00:03:22 +0000261 clang_analyzer_eval(global3 == 6); // expected-warning{{TRUE}}
George Karpenkov03544832017-11-03 00:36:03 +0000262#endif
George Karpenkov657a5892017-09-30 00:03:22 +0000263}
264
265void test_blocks() {
266 global3 = 0;
267 std::once_flag flag;
268 std::call_once(flag, ^{
269 global3 = 120;
270 });
George Karpenkov03544832017-11-03 00:36:03 +0000271#ifndef EMULATE_LIBCXX03
George Karpenkov657a5892017-09-30 00:03:22 +0000272 clang_analyzer_eval(global3 == 120); // expected-warning{{TRUE}}
George Karpenkov03544832017-11-03 00:36:03 +0000273#endif
George Karpenkov657a5892017-09-30 00:03:22 +0000274}
275
276int call_once() {
277 return 5;
278}
279
280void test_non_std_call_once() {
281 int x = call_once();
George Karpenkov03544832017-11-03 00:36:03 +0000282#ifndef EMULATE_LIBCXX03
George Karpenkov657a5892017-09-30 00:03:22 +0000283 clang_analyzer_eval(x == 5); // expected-warning{{TRUE}}
George Karpenkov03544832017-11-03 00:36:03 +0000284#endif
George Karpenkov657a5892017-09-30 00:03:22 +0000285}
George Karpenkov8b53f7c2017-10-09 23:20:46 +0000286
287namespace std {
288template <typename d, typename e>
289void call_once(d, e);
290}
291void g();
292void test_no_segfault_on_different_impl() {
George Karpenkov03544832017-11-03 00:36:03 +0000293#ifndef EMULATE_LIBCXX03
George Karpenkov8b53f7c2017-10-09 23:20:46 +0000294 std::call_once(g, false); // no-warning
George Karpenkov03544832017-11-03 00:36:03 +0000295#endif
George Karpenkov8b53f7c2017-10-09 23:20:46 +0000296}
George Karpenkovbd4254c2017-10-20 23:29:59 +0000297
298void test_lambda_refcapture() {
299 static std::once_flag flag;
300 int a = 6;
301 std::call_once(flag, [&](int &a) { a = 42; }, a);
George Karpenkov03544832017-11-03 00:36:03 +0000302#ifndef EMULATE_LIBCXX03
George Karpenkovbd4254c2017-10-20 23:29:59 +0000303 clang_analyzer_eval(a == 42); // expected-warning{{TRUE}}
George Karpenkov03544832017-11-03 00:36:03 +0000304#endif
George Karpenkovbd4254c2017-10-20 23:29:59 +0000305}
306
307void test_lambda_refcapture2() {
308 static std::once_flag flag;
309 int a = 6;
310 std::call_once(flag, [=](int &a) { a = 42; }, a);
George Karpenkov03544832017-11-03 00:36:03 +0000311#ifndef EMULATE_LIBCXX03
George Karpenkovbd4254c2017-10-20 23:29:59 +0000312 clang_analyzer_eval(a == 42); // expected-warning{{TRUE}}
George Karpenkov03544832017-11-03 00:36:03 +0000313#endif
George Karpenkovbd4254c2017-10-20 23:29:59 +0000314}
315
316void test_lambda_fail_refcapture() {
317 static std::once_flag flag;
318 int a = 6;
319 std::call_once(flag, [=](int a) { a = 42; }, a);
George Karpenkov03544832017-11-03 00:36:03 +0000320#ifndef EMULATE_LIBCXX03
George Karpenkovbd4254c2017-10-20 23:29:59 +0000321 clang_analyzer_eval(a == 42); // expected-warning{{FALSE}}
George Karpenkov03544832017-11-03 00:36:03 +0000322#endif
George Karpenkovbd4254c2017-10-20 23:29:59 +0000323}
324
325void mutator(int &param) {
326 param = 42;
327}
328void test_reftypes_funcptr() {
329 static std::once_flag flag;
330 int a = 6;
331 std::call_once(flag, &mutator, a);
George Karpenkov03544832017-11-03 00:36:03 +0000332#ifndef EMULATE_LIBCXX03
George Karpenkovbd4254c2017-10-20 23:29:59 +0000333 clang_analyzer_eval(a == 42); // expected-warning{{TRUE}}
George Karpenkov03544832017-11-03 00:36:03 +0000334#endif
George Karpenkovbd4254c2017-10-20 23:29:59 +0000335}
336
337void fail_mutator(int param) {
338 param = 42;
339}
340void test_mutator_noref() {
341 static std::once_flag flag;
342 int a = 6;
343 std::call_once(flag, &fail_mutator, a);
George Karpenkov03544832017-11-03 00:36:03 +0000344#ifndef EMULATE_LIBCXX03
George Karpenkovbd4254c2017-10-20 23:29:59 +0000345 clang_analyzer_eval(a == 42); // expected-warning{{FALSE}}
George Karpenkov03544832017-11-03 00:36:03 +0000346#endif
George Karpenkovbd4254c2017-10-20 23:29:59 +0000347}
George Karpenkov98e81cd2017-10-24 00:13:18 +0000348
349// Function is implicitly treated as a function pointer
350// even when an ampersand is not explicitly set.
351void callbackn(int &param) {
352 param = 42;
George Karpenkovf671bd22017-10-25 00:03:45 +0000353}
George Karpenkov98e81cd2017-10-24 00:13:18 +0000354void test_implicit_funcptr() {
355 int x = 0;
356 static std::once_flag flagn;
357
358 std::call_once(flagn, callbackn, x);
George Karpenkov03544832017-11-03 00:36:03 +0000359#ifndef EMULATE_LIBCXX03
George Karpenkov98e81cd2017-10-24 00:13:18 +0000360 clang_analyzer_eval(x == 42); // expected-warning{{TRUE}}
George Karpenkov03544832017-11-03 00:36:03 +0000361#endif
George Karpenkov98e81cd2017-10-24 00:13:18 +0000362}