xref: /llvm-project/clang/test/Analysis/call_once.cpp (revision faa03f4acaf5a7a2654c440f590c0ba31242b482)
196625fdcSGeorge Karpenkov // RUN: %clang_analyze_cc1 -std=c++11 -fblocks -analyzer-checker=core,debug.ExprInspection -verify %s -o %t.report
296625fdcSGeorge Karpenkov // RUN: %clang_analyze_cc1 -std=c++11 -fblocks -analyzer-checker=core,debug.ExprInspection -DEMULATE_LIBSTDCPP -verify %s -o %t.report
3657a5896SGeorge Karpenkov 
403544830SGeorge Karpenkov // We do NOT model libcxx03 implementation, but the analyzer should still
503544830SGeorge Karpenkov // not crash.
696625fdcSGeorge Karpenkov // RUN: %clang_analyze_cc1 -std=c++11 -fblocks -analyzer-checker=core,debug.ExprInspection -DEMULATE_LIBCXX03 -verify %s -o %t.report
796625fdcSGeorge Karpenkov // RUN: %clang_analyze_cc1 -std=c++11 -fblocks -analyzer-checker=core,debug.ExprInspection -DEMULATE_LIBCXX03 -DEMULATE_LIBSTDCPP -verify %s -o %t.report
896625fdcSGeorge Karpenkov // RUN: rm -rf %t.report
903544830SGeorge Karpenkov 
10657a5896SGeorge Karpenkov void clang_analyzer_eval(bool);
11657a5896SGeorge Karpenkov 
1259202324SGeorge Karpenkov // Faking std::call_once implementation.
13657a5896SGeorge Karpenkov namespace std {
14c928e1f5SGeorge Karpenkov 
1559202324SGeorge Karpenkov // Fake std::function implementation.
1659202324SGeorge Karpenkov template <typename>
1759202324SGeorge Karpenkov class function;
1859202324SGeorge Karpenkov class function_base {
1959202324SGeorge Karpenkov  public:
2059202324SGeorge Karpenkov   long field;
2159202324SGeorge Karpenkov };
2259202324SGeorge Karpenkov template <typename R, typename... P>
2359202324SGeorge Karpenkov class function<R(P...)> : function_base {
2459202324SGeorge Karpenkov  public:
operator ()(P...) const2559202324SGeorge Karpenkov    R operator()(P...) const {
2659202324SGeorge Karpenkov 
2759202324SGeorge Karpenkov      // Read from a super-class necessary to reproduce a crash.
2859202324SGeorge Karpenkov      bool a = field;
2959202324SGeorge Karpenkov    }
3059202324SGeorge Karpenkov };
3159202324SGeorge Karpenkov 
32c928e1f5SGeorge Karpenkov #ifndef EMULATE_LIBSTDCPP
33657a5896SGeorge Karpenkov typedef struct once_flag_s {
34657a5896SGeorge Karpenkov   unsigned long __state_ = 0;
35657a5896SGeorge Karpenkov } once_flag;
36c928e1f5SGeorge Karpenkov #else
37c928e1f5SGeorge Karpenkov typedef struct once_flag_s {
38c928e1f5SGeorge Karpenkov   int _M_once = 0;
39c928e1f5SGeorge Karpenkov } once_flag;
40c928e1f5SGeorge Karpenkov #endif
41657a5896SGeorge Karpenkov 
4203544830SGeorge Karpenkov #ifndef EMULATE_LIBCXX03
43657a5896SGeorge Karpenkov template <class Callable, class... Args>
call_once(once_flag & o,Callable && func,Args &&...args)44b2a60c6aSGeorge Karpenkov void call_once(once_flag &o, Callable&& func, Args&&... args) {};
4503544830SGeorge Karpenkov #else
4603544830SGeorge Karpenkov template <class Callable, class... Args> // libcxx03 call_once
call_once(once_flag & o,Callable func,Args &&...args)4703544830SGeorge Karpenkov void call_once(once_flag &o, Callable func, Args&&... args) {};
4803544830SGeorge Karpenkov #endif
49c928e1f5SGeorge Karpenkov 
50657a5896SGeorge Karpenkov } // namespace std
51657a5896SGeorge Karpenkov 
52657a5896SGeorge Karpenkov // Check with Lambdas.
test_called_warning()53657a5896SGeorge Karpenkov void test_called_warning() {
54657a5896SGeorge Karpenkov   std::once_flag g_initialize;
55657a5896SGeorge Karpenkov   int z;
56657a5896SGeorge Karpenkov 
57657a5896SGeorge Karpenkov   std::call_once(g_initialize, [&] {
58657a5896SGeorge Karpenkov     int *x = nullptr;
5903544830SGeorge Karpenkov #ifndef EMULATE_LIBCXX03
60657a5896SGeorge Karpenkov     int y = *x; // expected-warning{{Dereference of null pointer (loaded from variable 'x')}}
6103544830SGeorge Karpenkov #endif
62657a5896SGeorge Karpenkov     z = 200;
63657a5896SGeorge Karpenkov   });
64657a5896SGeorge Karpenkov }
65657a5896SGeorge Karpenkov 
test_called_on_path_inside_no_warning()66657a5896SGeorge Karpenkov void test_called_on_path_inside_no_warning() {
67657a5896SGeorge Karpenkov   std::once_flag g_initialize;
68657a5896SGeorge Karpenkov 
69657a5896SGeorge Karpenkov   int *x = nullptr;
70657a5896SGeorge Karpenkov   int y = 100;
71657a5896SGeorge Karpenkov   int z;
72657a5896SGeorge Karpenkov 
73657a5896SGeorge Karpenkov   std::call_once(g_initialize, [&] {
74657a5896SGeorge Karpenkov     z = 200;
75657a5896SGeorge Karpenkov     x = &z;
76657a5896SGeorge Karpenkov   });
77657a5896SGeorge Karpenkov 
7803544830SGeorge Karpenkov #ifndef EMULATE_LIBCXX03
79657a5896SGeorge Karpenkov   *x = 100; // no-warning
80657a5896SGeorge Karpenkov   clang_analyzer_eval(z == 100); // expected-warning{{TRUE}}
8103544830SGeorge Karpenkov #endif
82657a5896SGeorge Karpenkov }
83657a5896SGeorge Karpenkov 
test_called_on_path_no_warning()84657a5896SGeorge Karpenkov void test_called_on_path_no_warning() {
85657a5896SGeorge Karpenkov   std::once_flag g_initialize;
86657a5896SGeorge Karpenkov 
87657a5896SGeorge Karpenkov   int *x = nullptr;
88657a5896SGeorge Karpenkov   int y = 100;
89657a5896SGeorge Karpenkov 
90657a5896SGeorge Karpenkov   std::call_once(g_initialize, [&] {
91657a5896SGeorge Karpenkov     x = &y;
92657a5896SGeorge Karpenkov   });
93657a5896SGeorge Karpenkov 
9403544830SGeorge Karpenkov #ifndef EMULATE_LIBCXX03
95657a5896SGeorge Karpenkov   *x = 100; // no-warning
9603544830SGeorge Karpenkov #else
9703544830SGeorge Karpenkov   *x = 100; // expected-warning{{Dereference of null pointer (loaded from variable 'x')}}
9803544830SGeorge Karpenkov #endif
99657a5896SGeorge Karpenkov }
100657a5896SGeorge Karpenkov 
test_called_on_path_warning()101657a5896SGeorge Karpenkov void test_called_on_path_warning() {
102657a5896SGeorge Karpenkov   std::once_flag g_initialize;
103657a5896SGeorge Karpenkov 
104657a5896SGeorge Karpenkov   int y = 100;
105657a5896SGeorge Karpenkov   int *x = &y;
106657a5896SGeorge Karpenkov 
107657a5896SGeorge Karpenkov   std::call_once(g_initialize, [&] {
108657a5896SGeorge Karpenkov     x = nullptr;
109657a5896SGeorge Karpenkov   });
110657a5896SGeorge Karpenkov 
11103544830SGeorge Karpenkov #ifndef EMULATE_LIBCXX03
112657a5896SGeorge Karpenkov   *x = 100; // expected-warning{{Dereference of null pointer (loaded from variable 'x')}}
11303544830SGeorge Karpenkov #endif
114657a5896SGeorge Karpenkov }
115657a5896SGeorge Karpenkov 
test_called_once_warning()116657a5896SGeorge Karpenkov void test_called_once_warning() {
117657a5896SGeorge Karpenkov   std::once_flag g_initialize;
118657a5896SGeorge Karpenkov 
119657a5896SGeorge Karpenkov   int *x = nullptr;
120657a5896SGeorge Karpenkov   int y = 100;
121657a5896SGeorge Karpenkov 
122657a5896SGeorge Karpenkov   std::call_once(g_initialize, [&] {
123657a5896SGeorge Karpenkov     x = nullptr;
124657a5896SGeorge Karpenkov   });
125657a5896SGeorge Karpenkov 
126657a5896SGeorge Karpenkov   std::call_once(g_initialize, [&] {
127657a5896SGeorge Karpenkov     x = &y;
128657a5896SGeorge Karpenkov   });
129657a5896SGeorge Karpenkov 
13003544830SGeorge Karpenkov #ifndef EMULATE_LIBCXX03
131657a5896SGeorge Karpenkov   *x = 100; // expected-warning{{Dereference of null pointer (loaded from variable 'x')}}
13203544830SGeorge Karpenkov #endif
133657a5896SGeorge Karpenkov }
134657a5896SGeorge Karpenkov 
test_called_once_no_warning()135657a5896SGeorge Karpenkov void test_called_once_no_warning() {
136657a5896SGeorge Karpenkov   std::once_flag g_initialize;
137657a5896SGeorge Karpenkov 
138657a5896SGeorge Karpenkov   int *x = nullptr;
139657a5896SGeorge Karpenkov   int y = 100;
140657a5896SGeorge Karpenkov 
141657a5896SGeorge Karpenkov   std::call_once(g_initialize, [&] {
142657a5896SGeorge Karpenkov     x = &y;
143657a5896SGeorge Karpenkov   });
144657a5896SGeorge Karpenkov 
145657a5896SGeorge Karpenkov   std::call_once(g_initialize, [&] {
146657a5896SGeorge Karpenkov     x = nullptr;
147657a5896SGeorge Karpenkov   });
148657a5896SGeorge Karpenkov 
14903544830SGeorge Karpenkov #ifndef EMULATE_LIBCXX03
150657a5896SGeorge Karpenkov   *x = 100; // no-warning
15103544830SGeorge Karpenkov #endif
152657a5896SGeorge Karpenkov }
153657a5896SGeorge Karpenkov 
154657a5896SGeorge Karpenkov static int global = 0;
funcPointer()155657a5896SGeorge Karpenkov void funcPointer() {
156657a5896SGeorge Karpenkov   global = 1;
157657a5896SGeorge Karpenkov }
158657a5896SGeorge Karpenkov 
test_func_pointers()159657a5896SGeorge Karpenkov void test_func_pointers() {
160657a5896SGeorge Karpenkov   static std::once_flag flag;
161657a5896SGeorge Karpenkov   std::call_once(flag, &funcPointer);
16203544830SGeorge Karpenkov #ifndef EMULATE_LIBCXX03
163657a5896SGeorge Karpenkov   clang_analyzer_eval(global == 1); // expected-warning{{TRUE}}
16403544830SGeorge Karpenkov #endif
165657a5896SGeorge Karpenkov }
166657a5896SGeorge Karpenkov 
167657a5896SGeorge Karpenkov template <class _Fp>
168657a5896SGeorge Karpenkov class function; // undefined
169657a5896SGeorge Karpenkov template <class _Rp, class... _ArgTypes>
170657a5896SGeorge Karpenkov struct function<_Rp(_ArgTypes...)> {
operator ()function171305ee8e5SGeorge Karpenkov   _Rp operator()(_ArgTypes...) const {};
172657a5896SGeorge Karpenkov   template <class _Fp>
functionfunction173305ee8e5SGeorge Karpenkov   function(_Fp) {};
174657a5896SGeorge Karpenkov };
175657a5896SGeorge Karpenkov 
176657a5896SGeorge Karpenkov // Note: currently we do not support calls to std::function,
177657a5896SGeorge Karpenkov // but the analyzer should not crash either.
test_function_objects_warning()178657a5896SGeorge Karpenkov void test_function_objects_warning() {
179657a5896SGeorge Karpenkov   int x = 0;
180657a5896SGeorge Karpenkov   int *y = &x;
181657a5896SGeorge Karpenkov 
182657a5896SGeorge Karpenkov   std::once_flag flag;
183657a5896SGeorge Karpenkov 
184657a5896SGeorge Karpenkov   function<void()> func = [&]() {
185657a5896SGeorge Karpenkov     y = nullptr;
186657a5896SGeorge Karpenkov   };
187657a5896SGeorge Karpenkov 
188657a5896SGeorge Karpenkov   std::call_once(flag, func);
189657a5896SGeorge Karpenkov 
190657a5896SGeorge Karpenkov   func();
191657a5896SGeorge Karpenkov   int z = *y;
192657a5896SGeorge Karpenkov }
193657a5896SGeorge Karpenkov 
test_param_passing_lambda()194657a5896SGeorge Karpenkov void test_param_passing_lambda() {
195657a5896SGeorge Karpenkov   std::once_flag flag;
196657a5896SGeorge Karpenkov   int x = 120;
197657a5896SGeorge Karpenkov   int y = 0;
198657a5896SGeorge Karpenkov 
199657a5896SGeorge Karpenkov   std::call_once(flag, [&](int p) {
200657a5896SGeorge Karpenkov     y = p;
201657a5896SGeorge Karpenkov   },
202657a5896SGeorge Karpenkov                  x);
203657a5896SGeorge Karpenkov 
20403544830SGeorge Karpenkov #ifndef EMULATE_LIBCXX03
205657a5896SGeorge Karpenkov   clang_analyzer_eval(y == 120); // expected-warning{{TRUE}}
20603544830SGeorge Karpenkov #endif
207657a5896SGeorge Karpenkov }
208657a5896SGeorge Karpenkov 
test_param_passing_lambda_false()209657a5896SGeorge Karpenkov void test_param_passing_lambda_false() {
210657a5896SGeorge Karpenkov   std::once_flag flag;
211657a5896SGeorge Karpenkov   int x = 120;
212657a5896SGeorge Karpenkov 
213657a5896SGeorge Karpenkov   std::call_once(flag, [&](int p) {
214657a5896SGeorge Karpenkov     x = 0;
215657a5896SGeorge Karpenkov   },
216657a5896SGeorge Karpenkov                  x);
217657a5896SGeorge Karpenkov 
21803544830SGeorge Karpenkov #ifndef EMULATE_LIBCXX03
219657a5896SGeorge Karpenkov   clang_analyzer_eval(x == 120); // expected-warning{{FALSE}}
22003544830SGeorge Karpenkov #endif
221657a5896SGeorge Karpenkov }
222657a5896SGeorge Karpenkov 
test_param_passing_stored_lambda()223657a5896SGeorge Karpenkov void test_param_passing_stored_lambda() {
224657a5896SGeorge Karpenkov   std::once_flag flag;
225657a5896SGeorge Karpenkov   int x = 120;
226657a5896SGeorge Karpenkov   int y = 0;
227657a5896SGeorge Karpenkov 
228657a5896SGeorge Karpenkov   auto lambda = [&](int p) {
229657a5896SGeorge Karpenkov     y = p;
230657a5896SGeorge Karpenkov   };
231657a5896SGeorge Karpenkov 
232657a5896SGeorge Karpenkov   std::call_once(flag, lambda, x);
23303544830SGeorge Karpenkov #ifndef EMULATE_LIBCXX03
234657a5896SGeorge Karpenkov   clang_analyzer_eval(y == 120); // expected-warning{{TRUE}}
23503544830SGeorge Karpenkov #endif
236657a5896SGeorge Karpenkov }
237657a5896SGeorge Karpenkov 
test_multiparam_passing_lambda()238657a5896SGeorge Karpenkov void test_multiparam_passing_lambda() {
239657a5896SGeorge Karpenkov   std::once_flag flag;
240657a5896SGeorge Karpenkov   int x = 120;
241657a5896SGeorge Karpenkov 
242657a5896SGeorge Karpenkov   std::call_once(flag, [&](int a, int b, int c) {
243657a5896SGeorge Karpenkov     x = a + b + c;
244657a5896SGeorge Karpenkov   },
245657a5896SGeorge Karpenkov                  1, 2, 3);
246657a5896SGeorge Karpenkov 
24703544830SGeorge Karpenkov #ifndef EMULATE_LIBCXX03
248657a5896SGeorge Karpenkov   clang_analyzer_eval(x == 120); // expected-warning{{FALSE}}
249657a5896SGeorge Karpenkov   clang_analyzer_eval(x == 6); // expected-warning{{TRUE}}
25003544830SGeorge Karpenkov #endif
251657a5896SGeorge Karpenkov }
252657a5896SGeorge Karpenkov 
253657a5896SGeorge Karpenkov static int global2 = 0;
test_param_passing_lambda_global()254657a5896SGeorge Karpenkov void test_param_passing_lambda_global() {
255657a5896SGeorge Karpenkov   std::once_flag flag;
256657a5896SGeorge Karpenkov   global2 = 0;
257657a5896SGeorge Karpenkov   std::call_once(flag, [&](int a, int b, int c) {
258657a5896SGeorge Karpenkov     global2 = a + b + c;
259657a5896SGeorge Karpenkov   },
260657a5896SGeorge Karpenkov                  1, 2, 3);
26103544830SGeorge Karpenkov #ifndef EMULATE_LIBCXX03
262657a5896SGeorge Karpenkov   clang_analyzer_eval(global2 == 6); // expected-warning{{TRUE}}
26303544830SGeorge Karpenkov #endif
264657a5896SGeorge Karpenkov }
265657a5896SGeorge Karpenkov 
266657a5896SGeorge Karpenkov static int global3 = 0;
funcptr(int a,int b,int c)267657a5896SGeorge Karpenkov void funcptr(int a, int b, int c) {
268657a5896SGeorge Karpenkov   global3 = a + b + c;
269657a5896SGeorge Karpenkov }
270657a5896SGeorge Karpenkov 
test_param_passing_funcptr()271657a5896SGeorge Karpenkov void test_param_passing_funcptr() {
272657a5896SGeorge Karpenkov   std::once_flag flag;
273657a5896SGeorge Karpenkov   global3 = 0;
274657a5896SGeorge Karpenkov 
275657a5896SGeorge Karpenkov   std::call_once(flag, &funcptr, 1, 2, 3);
276657a5896SGeorge Karpenkov 
27703544830SGeorge Karpenkov #ifndef EMULATE_LIBCXX03
278657a5896SGeorge Karpenkov   clang_analyzer_eval(global3 == 6); // expected-warning{{TRUE}}
27903544830SGeorge Karpenkov #endif
280657a5896SGeorge Karpenkov }
281657a5896SGeorge Karpenkov 
test_blocks()282657a5896SGeorge Karpenkov void test_blocks() {
283657a5896SGeorge Karpenkov   global3 = 0;
284657a5896SGeorge Karpenkov   std::once_flag flag;
285657a5896SGeorge Karpenkov   std::call_once(flag, ^{
286657a5896SGeorge Karpenkov     global3 = 120;
287657a5896SGeorge Karpenkov   });
28803544830SGeorge Karpenkov #ifndef EMULATE_LIBCXX03
289657a5896SGeorge Karpenkov   clang_analyzer_eval(global3 == 120); // expected-warning{{TRUE}}
29003544830SGeorge Karpenkov #endif
291657a5896SGeorge Karpenkov }
292657a5896SGeorge Karpenkov 
call_once()293657a5896SGeorge Karpenkov int call_once() {
294657a5896SGeorge Karpenkov   return 5;
295657a5896SGeorge Karpenkov }
296657a5896SGeorge Karpenkov 
test_non_std_call_once()297657a5896SGeorge Karpenkov void test_non_std_call_once() {
298657a5896SGeorge Karpenkov   int x = call_once();
29903544830SGeorge Karpenkov #ifndef EMULATE_LIBCXX03
300657a5896SGeorge Karpenkov   clang_analyzer_eval(x == 5); // expected-warning{{TRUE}}
30103544830SGeorge Karpenkov #endif
302657a5896SGeorge Karpenkov }
3038b53f7caSGeorge Karpenkov 
3048b53f7caSGeorge Karpenkov namespace std {
3058b53f7caSGeorge Karpenkov template <typename d, typename e>
3068b53f7caSGeorge Karpenkov void call_once(d, e);
3078b53f7caSGeorge Karpenkov }
3088b53f7caSGeorge Karpenkov void g();
test_no_segfault_on_different_impl()3098b53f7caSGeorge Karpenkov void test_no_segfault_on_different_impl() {
31003544830SGeorge Karpenkov #ifndef EMULATE_LIBCXX03
3118b53f7caSGeorge Karpenkov   std::call_once(g, false); // no-warning
31203544830SGeorge Karpenkov #endif
3138b53f7caSGeorge Karpenkov }
314bd4254c6SGeorge Karpenkov 
test_lambda_refcapture()315bd4254c6SGeorge Karpenkov void test_lambda_refcapture() {
316bd4254c6SGeorge Karpenkov   static std::once_flag flag;
317bd4254c6SGeorge Karpenkov   int a = 6;
318bd4254c6SGeorge Karpenkov   std::call_once(flag, [&](int &a) { a = 42; }, a);
31903544830SGeorge Karpenkov #ifndef EMULATE_LIBCXX03
320bd4254c6SGeorge Karpenkov   clang_analyzer_eval(a == 42); // expected-warning{{TRUE}}
32103544830SGeorge Karpenkov #endif
322bd4254c6SGeorge Karpenkov }
323bd4254c6SGeorge Karpenkov 
test_lambda_refcapture2()324bd4254c6SGeorge Karpenkov void test_lambda_refcapture2() {
325bd4254c6SGeorge Karpenkov   static std::once_flag flag;
326bd4254c6SGeorge Karpenkov   int a = 6;
327bd4254c6SGeorge Karpenkov   std::call_once(flag, [=](int &a) { a = 42; }, a);
32803544830SGeorge Karpenkov #ifndef EMULATE_LIBCXX03
329bd4254c6SGeorge Karpenkov   clang_analyzer_eval(a == 42); // expected-warning{{TRUE}}
33003544830SGeorge Karpenkov #endif
331bd4254c6SGeorge Karpenkov }
332bd4254c6SGeorge Karpenkov 
test_lambda_fail_refcapture()333bd4254c6SGeorge Karpenkov void test_lambda_fail_refcapture() {
334bd4254c6SGeorge Karpenkov   static std::once_flag flag;
335bd4254c6SGeorge Karpenkov   int a = 6;
336bd4254c6SGeorge Karpenkov   std::call_once(flag, [=](int a) { a = 42; }, a);
33703544830SGeorge Karpenkov #ifndef EMULATE_LIBCXX03
338bd4254c6SGeorge Karpenkov   clang_analyzer_eval(a == 42); // expected-warning{{FALSE}}
33903544830SGeorge Karpenkov #endif
340bd4254c6SGeorge Karpenkov }
341bd4254c6SGeorge Karpenkov 
mutator(int & param)342bd4254c6SGeorge Karpenkov void mutator(int &param) {
343bd4254c6SGeorge Karpenkov   param = 42;
344bd4254c6SGeorge Karpenkov }
test_reftypes_funcptr()345bd4254c6SGeorge Karpenkov void test_reftypes_funcptr() {
346bd4254c6SGeorge Karpenkov   static std::once_flag flag;
347bd4254c6SGeorge Karpenkov   int a = 6;
348bd4254c6SGeorge Karpenkov   std::call_once(flag, &mutator, a);
34903544830SGeorge Karpenkov #ifndef EMULATE_LIBCXX03
350bd4254c6SGeorge Karpenkov   clang_analyzer_eval(a == 42); // expected-warning{{TRUE}}
35103544830SGeorge Karpenkov #endif
352bd4254c6SGeorge Karpenkov }
353bd4254c6SGeorge Karpenkov 
fail_mutator(int param)354bd4254c6SGeorge Karpenkov void fail_mutator(int param) {
355bd4254c6SGeorge Karpenkov   param = 42;
356bd4254c6SGeorge Karpenkov }
test_mutator_noref()357bd4254c6SGeorge Karpenkov void test_mutator_noref() {
358bd4254c6SGeorge Karpenkov   static std::once_flag flag;
359bd4254c6SGeorge Karpenkov   int a = 6;
360bd4254c6SGeorge Karpenkov   std::call_once(flag, &fail_mutator, a);
36103544830SGeorge Karpenkov #ifndef EMULATE_LIBCXX03
362bd4254c6SGeorge Karpenkov   clang_analyzer_eval(a == 42); // expected-warning{{FALSE}}
36303544830SGeorge Karpenkov #endif
364bd4254c6SGeorge Karpenkov }
36598e81cd3SGeorge Karpenkov 
36698e81cd3SGeorge Karpenkov // Function is implicitly treated as a function pointer
36798e81cd3SGeorge Karpenkov // even when an ampersand is not explicitly set.
callbackn(int & param)36898e81cd3SGeorge Karpenkov void callbackn(int &param) {
36998e81cd3SGeorge Karpenkov   param = 42;
370f671bd26SGeorge Karpenkov }
test_implicit_funcptr()37198e81cd3SGeorge Karpenkov void test_implicit_funcptr() {
37298e81cd3SGeorge Karpenkov   int x = 0;
37398e81cd3SGeorge Karpenkov   static std::once_flag flagn;
37498e81cd3SGeorge Karpenkov 
37598e81cd3SGeorge Karpenkov   std::call_once(flagn, callbackn, x);
37603544830SGeorge Karpenkov #ifndef EMULATE_LIBCXX03
37798e81cd3SGeorge Karpenkov   clang_analyzer_eval(x == 42); // expected-warning{{TRUE}}
37803544830SGeorge Karpenkov #endif
37998e81cd3SGeorge Karpenkov }
38059202324SGeorge Karpenkov 
param_passed(int * x)38159202324SGeorge Karpenkov int param_passed(int *x) {
38259202324SGeorge Karpenkov   return *x; // no-warning, as std::function is not working yet.
38359202324SGeorge Karpenkov }
38459202324SGeorge Karpenkov 
callback_taking_func_ok(std::function<void (int *)> & innerCallback)38559202324SGeorge Karpenkov void callback_taking_func_ok(std::function<void(int*)> &innerCallback) {
38659202324SGeorge Karpenkov   innerCallback(nullptr);
38759202324SGeorge Karpenkov }
38859202324SGeorge Karpenkov 
38959202324SGeorge Karpenkov // The provided callback expects an std::function, but instead a pointer
39059202324SGeorge Karpenkov // to a C++ function is provided.
callback_with_implicit_cast_ok()39159202324SGeorge Karpenkov void callback_with_implicit_cast_ok() {
39259202324SGeorge Karpenkov   std::once_flag flag;
39359202324SGeorge Karpenkov   call_once(flag, callback_taking_func_ok, &param_passed);
39459202324SGeorge Karpenkov }
39559202324SGeorge Karpenkov 
callback_taking_func(std::function<void ()> & innerCallback)39659202324SGeorge Karpenkov void callback_taking_func(std::function<void()> &innerCallback) {
39759202324SGeorge Karpenkov   innerCallback();
39859202324SGeorge Karpenkov }
39959202324SGeorge Karpenkov 
40059202324SGeorge Karpenkov // The provided callback expects an std::function, but instead a C function
40159202324SGeorge Karpenkov // name is provided, and C++ implicitly auto-constructs a pointer from it.
callback_with_implicit_cast()40259202324SGeorge Karpenkov void callback_with_implicit_cast() {
40359202324SGeorge Karpenkov   std::once_flag flag;
40459202324SGeorge Karpenkov   call_once(flag, callback_taking_func, callback_with_implicit_cast);
40559202324SGeorge Karpenkov }
406*faa03f4aSGeorge Karpenkov 
407*faa03f4aSGeorge Karpenkov std::once_flag another_once_flag;
408*faa03f4aSGeorge Karpenkov typedef void (*my_callback_t)(int *);
409*faa03f4aSGeorge Karpenkov my_callback_t callback;
410*faa03f4aSGeorge Karpenkov int global_int;
411*faa03f4aSGeorge Karpenkov 
rdar40270582()412*faa03f4aSGeorge Karpenkov void rdar40270582() {
413*faa03f4aSGeorge Karpenkov   call_once(another_once_flag, callback, &global_int);
414*faa03f4aSGeorge Karpenkov }
415