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
4 // We do NOT model libcxx03 implementation, but the analyzer should still
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
10 void clang_analyzer_eval(bool);
12 // Faking std::call_once implementation.
15 // Fake std::function implementation.
22 template <typename R
, typename
... P
>
23 class function
<R(P
...)> : function_base
{
25 R
operator()(P
...) const {
27 // Read from a super-class necessary to reproduce a crash.
32 #ifndef EMULATE_LIBSTDCPP
33 typedef struct once_flag_s
{
34 unsigned long __state_
= 0;
37 typedef struct once_flag_s
{
42 #ifndef EMULATE_LIBCXX03
43 template <class Callable
, class... Args
>
44 void call_once(once_flag
&o
, Callable
&& func
, Args
&&... args
) {};
46 template <class Callable
, class... Args
> // libcxx03 call_once
47 void call_once(once_flag
&o
, Callable func
, Args
&&... args
) {};
52 // Check with Lambdas.
53 void test_called_warning() {
54 std::once_flag g_initialize
;
57 std::call_once(g_initialize
, [&] {
59 #ifndef EMULATE_LIBCXX03
60 int y
= *x
; // expected-warning{{Dereference of null pointer (loaded from variable 'x')}}
66 void test_called_on_path_inside_no_warning() {
67 std::once_flag g_initialize
;
73 std::call_once(g_initialize
, [&] {
78 #ifndef EMULATE_LIBCXX03
79 *x
= 100; // no-warning
80 clang_analyzer_eval(z
== 100); // expected-warning{{TRUE}}
84 void test_called_on_path_no_warning() {
85 std::once_flag g_initialize
;
90 std::call_once(g_initialize
, [&] {
94 #ifndef EMULATE_LIBCXX03
95 *x
= 100; // no-warning
97 *x
= 100; // expected-warning{{Dereference of null pointer (loaded from variable 'x')}}
101 void test_called_on_path_warning() {
102 std::once_flag g_initialize
;
107 std::call_once(g_initialize
, [&] {
111 #ifndef EMULATE_LIBCXX03
112 *x
= 100; // expected-warning{{Dereference of null pointer (loaded from variable 'x')}}
116 void test_called_once_warning() {
117 std::once_flag g_initialize
;
122 std::call_once(g_initialize
, [&] {
126 std::call_once(g_initialize
, [&] {
130 #ifndef EMULATE_LIBCXX03
131 *x
= 100; // expected-warning{{Dereference of null pointer (loaded from variable 'x')}}
135 void test_called_once_no_warning() {
136 std::once_flag g_initialize
;
141 std::call_once(g_initialize
, [&] {
145 std::call_once(g_initialize
, [&] {
149 #ifndef EMULATE_LIBCXX03
150 *x
= 100; // no-warning
154 static int global
= 0;
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}}
168 class function
; // undefined
169 template <class _Rp
, class... _ArgTypes
>
170 struct function
<_Rp(_ArgTypes
...)> {
171 _Rp
operator()(_ArgTypes
...) const {};
176 // Note: currently we do not support calls to std::function,
177 // but the analyzer should not crash either.
178 void test_function_objects_warning() {
184 function
<void()> func
= [&]() {
188 std::call_once(flag
, func
);
194 void test_param_passing_lambda() {
199 std::call_once(flag
, [&](int p
) {
204 #ifndef EMULATE_LIBCXX03
205 clang_analyzer_eval(y
== 120); // expected-warning{{TRUE}}
209 void test_param_passing_lambda_false() {
213 std::call_once(flag
, [&](int p
) {
218 #ifndef EMULATE_LIBCXX03
219 clang_analyzer_eval(x
== 120); // expected-warning{{FALSE}}
223 void test_param_passing_stored_lambda() {
228 auto lambda
= [&](int p
) {
232 std::call_once(flag
, lambda
, x
);
233 #ifndef EMULATE_LIBCXX03
234 clang_analyzer_eval(y
== 120); // expected-warning{{TRUE}}
238 void test_multiparam_passing_lambda() {
242 std::call_once(flag
, [&](int a
, int b
, int c
) {
247 #ifndef EMULATE_LIBCXX03
248 clang_analyzer_eval(x
== 120); // expected-warning{{FALSE}}
249 clang_analyzer_eval(x
== 6); // expected-warning{{TRUE}}
253 static int global2
= 0;
254 void test_param_passing_lambda_global() {
257 std::call_once(flag
, [&](int a
, int b
, int c
) {
261 #ifndef EMULATE_LIBCXX03
262 clang_analyzer_eval(global2
== 6); // expected-warning{{TRUE}}
266 static int global3
= 0;
267 void funcptr(int a
, int b
, int c
) {
271 void test_param_passing_funcptr() {
275 std::call_once(flag
, &funcptr
, 1, 2, 3);
277 #ifndef EMULATE_LIBCXX03
278 clang_analyzer_eval(global3
== 6); // expected-warning{{TRUE}}
285 std::call_once(flag
, ^{
288 #ifndef EMULATE_LIBCXX03
289 clang_analyzer_eval(global3
== 120); // expected-warning{{TRUE}}
297 void test_non_std_call_once() {
299 #ifndef EMULATE_LIBCXX03
300 clang_analyzer_eval(x
== 5); // expected-warning{{TRUE}}
305 template <typename d
, typename e
>
306 void call_once(d
, e
);
309 void test_no_segfault_on_different_impl() {
310 #ifndef EMULATE_LIBCXX03
311 std::call_once(g
, false); // no-warning
315 void test_lambda_refcapture() {
316 static std::once_flag flag
;
318 std::call_once(flag
, [&](int &a
) { a
= 42; }, a
);
319 #ifndef EMULATE_LIBCXX03
320 clang_analyzer_eval(a
== 42); // expected-warning{{TRUE}}
324 void test_lambda_refcapture2() {
325 static std::once_flag flag
;
327 std::call_once(flag
, [=](int &a
) { a
= 42; }, a
);
328 #ifndef EMULATE_LIBCXX03
329 clang_analyzer_eval(a
== 42); // expected-warning{{TRUE}}
333 void test_lambda_fail_refcapture() {
334 static std::once_flag flag
;
336 std::call_once(flag
, [=](int a
) { a
= 42; }, a
);
337 #ifndef EMULATE_LIBCXX03
338 clang_analyzer_eval(a
== 42); // expected-warning{{FALSE}}
342 void mutator(int ¶m
) {
345 void test_reftypes_funcptr() {
346 static std::once_flag flag
;
348 std::call_once(flag
, &mutator
, a
);
349 #ifndef EMULATE_LIBCXX03
350 clang_analyzer_eval(a
== 42); // expected-warning{{TRUE}}
354 void fail_mutator(int param
) {
357 void test_mutator_noref() {
358 static std::once_flag flag
;
360 std::call_once(flag
, &fail_mutator
, a
);
361 #ifndef EMULATE_LIBCXX03
362 clang_analyzer_eval(a
== 42); // expected-warning{{FALSE}}
366 // Function is implicitly treated as a function pointer
367 // even when an ampersand is not explicitly set.
368 void callbackn(int ¶m
) {
371 void test_implicit_funcptr() {
373 static std::once_flag flagn
;
375 std::call_once(flagn
, callbackn
, x
);
376 #ifndef EMULATE_LIBCXX03
377 clang_analyzer_eval(x
== 42); // expected-warning{{TRUE}}
381 int param_passed(int *x
) {
382 return *x
; // no-warning, as std::function is not working yet.
385 void callback_taking_func_ok(std::function
<void(int*)> &innerCallback
) {
386 innerCallback(nullptr);
389 // The provided callback expects an std::function, but instead a pointer
390 // to a C++ function is provided.
391 void callback_with_implicit_cast_ok() {
393 call_once(flag
, callback_taking_func_ok
, ¶m_passed
);
396 void callback_taking_func(std::function
<void()> &innerCallback
) {
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.
402 void callback_with_implicit_cast() {
404 call_once(flag
, callback_taking_func
, callback_with_implicit_cast
);
407 std::once_flag another_once_flag
;
408 typedef void (*my_callback_t
)(int *);
409 my_callback_t callback
;
412 void rdar40270582() {
413 call_once(another_once_flag
, callback
, &global_int
);