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::std::call_once implementation.
13 namespace std {
14 
15 #ifndef EMULATE_LIBSTDCPP
16 typedef struct once_flag_s {
17   unsigned long __state_ = 0;
18 } once_flag;
19 #else
20 typedef struct once_flag_s {
21   int _M_once = 0;
22 } once_flag;
23 #endif
24 
25 #ifndef EMULATE_LIBCXX03
26 template <class Callable, class... Args>
27 void call_once(once_flag &o, Callable&& func, Args&&... args) {};
28 #else
29 template <class Callable, class... Args> // libcxx03 call_once
30 void call_once(once_flag &o, Callable func, Args&&... args) {};
31 #endif
32 
33 } // namespace std
34 
35 // Check with Lambdas.
36 void test_called_warning() {
37   std::once_flag g_initialize;
38   int z;
39 
40   std::call_once(g_initialize, [&] {
41     int *x = nullptr;
42 #ifndef EMULATE_LIBCXX03
43     int y = *x; // expected-warning{{Dereference of null pointer (loaded from variable 'x')}}
44 #endif
45     z = 200;
46   });
47 }
48 
49 void 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 
61 #ifndef EMULATE_LIBCXX03
62   *x = 100; // no-warning
63   clang_analyzer_eval(z == 100); // expected-warning{{TRUE}}
64 #endif
65 }
66 
67 void 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 
77 #ifndef EMULATE_LIBCXX03
78   *x = 100; // no-warning
79 #else
80   *x = 100; // expected-warning{{Dereference of null pointer (loaded from variable 'x')}}
81 #endif
82 }
83 
84 void 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 
94 #ifndef EMULATE_LIBCXX03
95   *x = 100; // expected-warning{{Dereference of null pointer (loaded from variable 'x')}}
96 #endif
97 }
98 
99 void 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 
113 #ifndef EMULATE_LIBCXX03
114   *x = 100; // expected-warning{{Dereference of null pointer (loaded from variable 'x')}}
115 #endif
116 }
117 
118 void 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 
132 #ifndef EMULATE_LIBCXX03
133   *x = 100; // no-warning
134 #endif
135 }
136 
137 static int global = 0;
138 void funcPointer() {
139   global = 1;
140 }
141 
142 void test_func_pointers() {
143   static std::once_flag flag;
144   std::call_once(flag, &funcPointer);
145 #ifndef EMULATE_LIBCXX03
146   clang_analyzer_eval(global == 1); // expected-warning{{TRUE}}
147 #endif
148 }
149 
150 template <class _Fp>
151 class function; // undefined
152 template <class _Rp, class... _ArgTypes>
153 struct function<_Rp(_ArgTypes...)> {
154   _Rp operator()(_ArgTypes...) const {};
155   template <class _Fp>
156   function(_Fp) {};
157 };
158 
159 // Note: currently we do not support calls to std::function,
160 // but the analyzer should not crash either.
161 void 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 
177 void 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 
187 #ifndef EMULATE_LIBCXX03
188   clang_analyzer_eval(y == 120); // expected-warning{{TRUE}}
189 #endif
190 }
191 
192 void 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 
201 #ifndef EMULATE_LIBCXX03
202   clang_analyzer_eval(x == 120); // expected-warning{{FALSE}}
203 #endif
204 }
205 
206 void 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);
216 #ifndef EMULATE_LIBCXX03
217   clang_analyzer_eval(y == 120); // expected-warning{{TRUE}}
218 #endif
219 }
220 
221 void 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 
230 #ifndef EMULATE_LIBCXX03
231   clang_analyzer_eval(x == 120); // expected-warning{{FALSE}}
232   clang_analyzer_eval(x == 6); // expected-warning{{TRUE}}
233 #endif
234 }
235 
236 static int global2 = 0;
237 void 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);
244 #ifndef EMULATE_LIBCXX03
245   clang_analyzer_eval(global2 == 6); // expected-warning{{TRUE}}
246 #endif
247 }
248 
249 static int global3 = 0;
250 void funcptr(int a, int b, int c) {
251   global3 = a + b + c;
252 }
253 
254 void test_param_passing_funcptr() {
255   std::once_flag flag;
256   global3 = 0;
257 
258   std::call_once(flag, &funcptr, 1, 2, 3);
259 
260 #ifndef EMULATE_LIBCXX03
261   clang_analyzer_eval(global3 == 6); // expected-warning{{TRUE}}
262 #endif
263 }
264 
265 void test_blocks() {
266   global3 = 0;
267   std::once_flag flag;
268   std::call_once(flag, ^{
269     global3 = 120;
270   });
271 #ifndef EMULATE_LIBCXX03
272   clang_analyzer_eval(global3 == 120); // expected-warning{{TRUE}}
273 #endif
274 }
275 
276 int call_once() {
277   return 5;
278 }
279 
280 void test_non_std_call_once() {
281   int x = call_once();
282 #ifndef EMULATE_LIBCXX03
283   clang_analyzer_eval(x == 5); // expected-warning{{TRUE}}
284 #endif
285 }
286 
287 namespace std {
288 template <typename d, typename e>
289 void call_once(d, e);
290 }
291 void g();
292 void test_no_segfault_on_different_impl() {
293 #ifndef EMULATE_LIBCXX03
294   std::call_once(g, false); // no-warning
295 #endif
296 }
297 
298 void test_lambda_refcapture() {
299   static std::once_flag flag;
300   int a = 6;
301   std::call_once(flag, [&](int &a) { a = 42; }, a);
302 #ifndef EMULATE_LIBCXX03
303   clang_analyzer_eval(a == 42); // expected-warning{{TRUE}}
304 #endif
305 }
306 
307 void test_lambda_refcapture2() {
308   static std::once_flag flag;
309   int a = 6;
310   std::call_once(flag, [=](int &a) { a = 42; }, a);
311 #ifndef EMULATE_LIBCXX03
312   clang_analyzer_eval(a == 42); // expected-warning{{TRUE}}
313 #endif
314 }
315 
316 void test_lambda_fail_refcapture() {
317   static std::once_flag flag;
318   int a = 6;
319   std::call_once(flag, [=](int a) { a = 42; }, a);
320 #ifndef EMULATE_LIBCXX03
321   clang_analyzer_eval(a == 42); // expected-warning{{FALSE}}
322 #endif
323 }
324 
325 void mutator(int &param) {
326   param = 42;
327 }
328 void test_reftypes_funcptr() {
329   static std::once_flag flag;
330   int a = 6;
331   std::call_once(flag, &mutator, a);
332 #ifndef EMULATE_LIBCXX03
333   clang_analyzer_eval(a == 42); // expected-warning{{TRUE}}
334 #endif
335 }
336 
337 void fail_mutator(int param) {
338   param = 42;
339 }
340 void test_mutator_noref() {
341   static std::once_flag flag;
342   int a = 6;
343   std::call_once(flag, &fail_mutator, a);
344 #ifndef EMULATE_LIBCXX03
345   clang_analyzer_eval(a == 42); // expected-warning{{FALSE}}
346 #endif
347 }
348 
349 // Function is implicitly treated as a function pointer
350 // even when an ampersand is not explicitly set.
351 void callbackn(int &param) {
352   param = 42;
353 }
354 void test_implicit_funcptr() {
355   int x = 0;
356   static std::once_flag flagn;
357 
358   std::call_once(flagn, callbackn, x);
359 #ifndef EMULATE_LIBCXX03
360   clang_analyzer_eval(x == 42); // expected-warning{{TRUE}}
361 #endif
362 }
363