George Karpenkov | 96625fd | 2018-01-02 23:05:47 +0000 | [diff] [blame] | 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 |
George Karpenkov | 657a589 | 2017-09-30 00:03:22 +0000 | [diff] [blame] | 3 | |
George Karpenkov | 0354483 | 2017-11-03 00:36:03 +0000 | [diff] [blame] | 4 | // We do NOT model libcxx03 implementation, but the analyzer should still |
| 5 | // not crash. |
George Karpenkov | 96625fd | 2018-01-02 23:05:47 +0000 | [diff] [blame] | 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 |
George Karpenkov | 0354483 | 2017-11-03 00:36:03 +0000 | [diff] [blame] | 9 | |
George Karpenkov | 657a589 | 2017-09-30 00:03:22 +0000 | [diff] [blame] | 10 | void clang_analyzer_eval(bool); |
| 11 | |
George Karpenkov | 5920232 | 2018-02-02 01:44:07 +0000 | [diff] [blame] | 12 | // Faking std::call_once implementation. |
George Karpenkov | 657a589 | 2017-09-30 00:03:22 +0000 | [diff] [blame] | 13 | namespace std { |
George Karpenkov | c928e1f | 2017-10-11 20:53:01 +0000 | [diff] [blame] | 14 | |
George Karpenkov | 5920232 | 2018-02-02 01:44:07 +0000 | [diff] [blame] | 15 | // Fake std::function implementation. |
| 16 | template <typename> |
| 17 | class function; |
| 18 | class function_base { |
| 19 | public: |
| 20 | long field; |
| 21 | }; |
| 22 | template <typename R, typename... P> |
| 23 | class 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 Karpenkov | c928e1f | 2017-10-11 20:53:01 +0000 | [diff] [blame] | 32 | #ifndef EMULATE_LIBSTDCPP |
George Karpenkov | 657a589 | 2017-09-30 00:03:22 +0000 | [diff] [blame] | 33 | typedef struct once_flag_s { |
| 34 | unsigned long __state_ = 0; |
| 35 | } once_flag; |
George Karpenkov | c928e1f | 2017-10-11 20:53:01 +0000 | [diff] [blame] | 36 | #else |
| 37 | typedef struct once_flag_s { |
| 38 | int _M_once = 0; |
| 39 | } once_flag; |
| 40 | #endif |
George Karpenkov | 657a589 | 2017-09-30 00:03:22 +0000 | [diff] [blame] | 41 | |
George Karpenkov | 0354483 | 2017-11-03 00:36:03 +0000 | [diff] [blame] | 42 | #ifndef EMULATE_LIBCXX03 |
George Karpenkov | 657a589 | 2017-09-30 00:03:22 +0000 | [diff] [blame] | 43 | template <class Callable, class... Args> |
George Karpenkov | b2a60c6 | 2017-10-17 22:28:18 +0000 | [diff] [blame] | 44 | void call_once(once_flag &o, Callable&& func, Args&&... args) {}; |
George Karpenkov | 0354483 | 2017-11-03 00:36:03 +0000 | [diff] [blame] | 45 | #else |
| 46 | template <class Callable, class... Args> // libcxx03 call_once |
| 47 | void call_once(once_flag &o, Callable func, Args&&... args) {}; |
| 48 | #endif |
George Karpenkov | c928e1f | 2017-10-11 20:53:01 +0000 | [diff] [blame] | 49 | |
George Karpenkov | 657a589 | 2017-09-30 00:03:22 +0000 | [diff] [blame] | 50 | } // namespace std |
| 51 | |
| 52 | // Check with Lambdas. |
| 53 | void test_called_warning() { |
| 54 | std::once_flag g_initialize; |
| 55 | int z; |
| 56 | |
| 57 | std::call_once(g_initialize, [&] { |
| 58 | int *x = nullptr; |
George Karpenkov | 0354483 | 2017-11-03 00:36:03 +0000 | [diff] [blame] | 59 | #ifndef EMULATE_LIBCXX03 |
George Karpenkov | 657a589 | 2017-09-30 00:03:22 +0000 | [diff] [blame] | 60 | int y = *x; // expected-warning{{Dereference of null pointer (loaded from variable 'x')}} |
George Karpenkov | 0354483 | 2017-11-03 00:36:03 +0000 | [diff] [blame] | 61 | #endif |
George Karpenkov | 657a589 | 2017-09-30 00:03:22 +0000 | [diff] [blame] | 62 | z = 200; |
| 63 | }); |
| 64 | } |
| 65 | |
| 66 | void 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 Karpenkov | 0354483 | 2017-11-03 00:36:03 +0000 | [diff] [blame] | 78 | #ifndef EMULATE_LIBCXX03 |
George Karpenkov | 657a589 | 2017-09-30 00:03:22 +0000 | [diff] [blame] | 79 | *x = 100; // no-warning |
| 80 | clang_analyzer_eval(z == 100); // expected-warning{{TRUE}} |
George Karpenkov | 0354483 | 2017-11-03 00:36:03 +0000 | [diff] [blame] | 81 | #endif |
George Karpenkov | 657a589 | 2017-09-30 00:03:22 +0000 | [diff] [blame] | 82 | } |
| 83 | |
| 84 | void 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 Karpenkov | 0354483 | 2017-11-03 00:36:03 +0000 | [diff] [blame] | 94 | #ifndef EMULATE_LIBCXX03 |
George Karpenkov | 657a589 | 2017-09-30 00:03:22 +0000 | [diff] [blame] | 95 | *x = 100; // no-warning |
George Karpenkov | 0354483 | 2017-11-03 00:36:03 +0000 | [diff] [blame] | 96 | #else |
| 97 | *x = 100; // expected-warning{{Dereference of null pointer (loaded from variable 'x')}} |
| 98 | #endif |
George Karpenkov | 657a589 | 2017-09-30 00:03:22 +0000 | [diff] [blame] | 99 | } |
| 100 | |
| 101 | void 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 Karpenkov | 0354483 | 2017-11-03 00:36:03 +0000 | [diff] [blame] | 111 | #ifndef EMULATE_LIBCXX03 |
George Karpenkov | 657a589 | 2017-09-30 00:03:22 +0000 | [diff] [blame] | 112 | *x = 100; // expected-warning{{Dereference of null pointer (loaded from variable 'x')}} |
George Karpenkov | 0354483 | 2017-11-03 00:36:03 +0000 | [diff] [blame] | 113 | #endif |
George Karpenkov | 657a589 | 2017-09-30 00:03:22 +0000 | [diff] [blame] | 114 | } |
| 115 | |
| 116 | void 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 Karpenkov | 0354483 | 2017-11-03 00:36:03 +0000 | [diff] [blame] | 130 | #ifndef EMULATE_LIBCXX03 |
George Karpenkov | 657a589 | 2017-09-30 00:03:22 +0000 | [diff] [blame] | 131 | *x = 100; // expected-warning{{Dereference of null pointer (loaded from variable 'x')}} |
George Karpenkov | 0354483 | 2017-11-03 00:36:03 +0000 | [diff] [blame] | 132 | #endif |
George Karpenkov | 657a589 | 2017-09-30 00:03:22 +0000 | [diff] [blame] | 133 | } |
| 134 | |
| 135 | void 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 Karpenkov | 0354483 | 2017-11-03 00:36:03 +0000 | [diff] [blame] | 149 | #ifndef EMULATE_LIBCXX03 |
George Karpenkov | 657a589 | 2017-09-30 00:03:22 +0000 | [diff] [blame] | 150 | *x = 100; // no-warning |
George Karpenkov | 0354483 | 2017-11-03 00:36:03 +0000 | [diff] [blame] | 151 | #endif |
George Karpenkov | 657a589 | 2017-09-30 00:03:22 +0000 | [diff] [blame] | 152 | } |
| 153 | |
| 154 | static int global = 0; |
| 155 | void funcPointer() { |
| 156 | global = 1; |
| 157 | } |
| 158 | |
| 159 | void test_func_pointers() { |
| 160 | static std::once_flag flag; |
| 161 | std::call_once(flag, &funcPointer); |
George Karpenkov | 0354483 | 2017-11-03 00:36:03 +0000 | [diff] [blame] | 162 | #ifndef EMULATE_LIBCXX03 |
George Karpenkov | 657a589 | 2017-09-30 00:03:22 +0000 | [diff] [blame] | 163 | clang_analyzer_eval(global == 1); // expected-warning{{TRUE}} |
George Karpenkov | 0354483 | 2017-11-03 00:36:03 +0000 | [diff] [blame] | 164 | #endif |
George Karpenkov | 657a589 | 2017-09-30 00:03:22 +0000 | [diff] [blame] | 165 | } |
| 166 | |
| 167 | template <class _Fp> |
| 168 | class function; // undefined |
| 169 | template <class _Rp, class... _ArgTypes> |
| 170 | struct function<_Rp(_ArgTypes...)> { |
George Karpenkov | 305ee8e | 2017-09-30 01:15:35 +0000 | [diff] [blame] | 171 | _Rp operator()(_ArgTypes...) const {}; |
George Karpenkov | 657a589 | 2017-09-30 00:03:22 +0000 | [diff] [blame] | 172 | template <class _Fp> |
George Karpenkov | 305ee8e | 2017-09-30 01:15:35 +0000 | [diff] [blame] | 173 | function(_Fp) {}; |
George Karpenkov | 657a589 | 2017-09-30 00:03:22 +0000 | [diff] [blame] | 174 | }; |
| 175 | |
| 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() { |
| 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 | |
| 194 | void 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 Karpenkov | 0354483 | 2017-11-03 00:36:03 +0000 | [diff] [blame] | 204 | #ifndef EMULATE_LIBCXX03 |
George Karpenkov | 657a589 | 2017-09-30 00:03:22 +0000 | [diff] [blame] | 205 | clang_analyzer_eval(y == 120); // expected-warning{{TRUE}} |
George Karpenkov | 0354483 | 2017-11-03 00:36:03 +0000 | [diff] [blame] | 206 | #endif |
George Karpenkov | 657a589 | 2017-09-30 00:03:22 +0000 | [diff] [blame] | 207 | } |
| 208 | |
| 209 | void 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 Karpenkov | 0354483 | 2017-11-03 00:36:03 +0000 | [diff] [blame] | 218 | #ifndef EMULATE_LIBCXX03 |
George Karpenkov | 657a589 | 2017-09-30 00:03:22 +0000 | [diff] [blame] | 219 | clang_analyzer_eval(x == 120); // expected-warning{{FALSE}} |
George Karpenkov | 0354483 | 2017-11-03 00:36:03 +0000 | [diff] [blame] | 220 | #endif |
George Karpenkov | 657a589 | 2017-09-30 00:03:22 +0000 | [diff] [blame] | 221 | } |
| 222 | |
| 223 | void 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 Karpenkov | 0354483 | 2017-11-03 00:36:03 +0000 | [diff] [blame] | 233 | #ifndef EMULATE_LIBCXX03 |
George Karpenkov | 657a589 | 2017-09-30 00:03:22 +0000 | [diff] [blame] | 234 | clang_analyzer_eval(y == 120); // expected-warning{{TRUE}} |
George Karpenkov | 0354483 | 2017-11-03 00:36:03 +0000 | [diff] [blame] | 235 | #endif |
George Karpenkov | 657a589 | 2017-09-30 00:03:22 +0000 | [diff] [blame] | 236 | } |
| 237 | |
| 238 | void 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 Karpenkov | 0354483 | 2017-11-03 00:36:03 +0000 | [diff] [blame] | 247 | #ifndef EMULATE_LIBCXX03 |
George Karpenkov | 657a589 | 2017-09-30 00:03:22 +0000 | [diff] [blame] | 248 | clang_analyzer_eval(x == 120); // expected-warning{{FALSE}} |
| 249 | clang_analyzer_eval(x == 6); // expected-warning{{TRUE}} |
George Karpenkov | 0354483 | 2017-11-03 00:36:03 +0000 | [diff] [blame] | 250 | #endif |
George Karpenkov | 657a589 | 2017-09-30 00:03:22 +0000 | [diff] [blame] | 251 | } |
| 252 | |
| 253 | static int global2 = 0; |
| 254 | void 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 Karpenkov | 0354483 | 2017-11-03 00:36:03 +0000 | [diff] [blame] | 261 | #ifndef EMULATE_LIBCXX03 |
George Karpenkov | 657a589 | 2017-09-30 00:03:22 +0000 | [diff] [blame] | 262 | clang_analyzer_eval(global2 == 6); // expected-warning{{TRUE}} |
George Karpenkov | 0354483 | 2017-11-03 00:36:03 +0000 | [diff] [blame] | 263 | #endif |
George Karpenkov | 657a589 | 2017-09-30 00:03:22 +0000 | [diff] [blame] | 264 | } |
| 265 | |
| 266 | static int global3 = 0; |
| 267 | void funcptr(int a, int b, int c) { |
| 268 | global3 = a + b + c; |
| 269 | } |
| 270 | |
| 271 | void test_param_passing_funcptr() { |
| 272 | std::once_flag flag; |
| 273 | global3 = 0; |
| 274 | |
| 275 | std::call_once(flag, &funcptr, 1, 2, 3); |
| 276 | |
George Karpenkov | 0354483 | 2017-11-03 00:36:03 +0000 | [diff] [blame] | 277 | #ifndef EMULATE_LIBCXX03 |
George Karpenkov | 657a589 | 2017-09-30 00:03:22 +0000 | [diff] [blame] | 278 | clang_analyzer_eval(global3 == 6); // expected-warning{{TRUE}} |
George Karpenkov | 0354483 | 2017-11-03 00:36:03 +0000 | [diff] [blame] | 279 | #endif |
George Karpenkov | 657a589 | 2017-09-30 00:03:22 +0000 | [diff] [blame] | 280 | } |
| 281 | |
| 282 | void test_blocks() { |
| 283 | global3 = 0; |
| 284 | std::once_flag flag; |
| 285 | std::call_once(flag, ^{ |
| 286 | global3 = 120; |
| 287 | }); |
George Karpenkov | 0354483 | 2017-11-03 00:36:03 +0000 | [diff] [blame] | 288 | #ifndef EMULATE_LIBCXX03 |
George Karpenkov | 657a589 | 2017-09-30 00:03:22 +0000 | [diff] [blame] | 289 | clang_analyzer_eval(global3 == 120); // expected-warning{{TRUE}} |
George Karpenkov | 0354483 | 2017-11-03 00:36:03 +0000 | [diff] [blame] | 290 | #endif |
George Karpenkov | 657a589 | 2017-09-30 00:03:22 +0000 | [diff] [blame] | 291 | } |
| 292 | |
| 293 | int call_once() { |
| 294 | return 5; |
| 295 | } |
| 296 | |
| 297 | void test_non_std_call_once() { |
| 298 | int x = call_once(); |
George Karpenkov | 0354483 | 2017-11-03 00:36:03 +0000 | [diff] [blame] | 299 | #ifndef EMULATE_LIBCXX03 |
George Karpenkov | 657a589 | 2017-09-30 00:03:22 +0000 | [diff] [blame] | 300 | clang_analyzer_eval(x == 5); // expected-warning{{TRUE}} |
George Karpenkov | 0354483 | 2017-11-03 00:36:03 +0000 | [diff] [blame] | 301 | #endif |
George Karpenkov | 657a589 | 2017-09-30 00:03:22 +0000 | [diff] [blame] | 302 | } |
George Karpenkov | 8b53f7c | 2017-10-09 23:20:46 +0000 | [diff] [blame] | 303 | |
| 304 | namespace std { |
| 305 | template <typename d, typename e> |
| 306 | void call_once(d, e); |
| 307 | } |
| 308 | void g(); |
| 309 | void test_no_segfault_on_different_impl() { |
George Karpenkov | 0354483 | 2017-11-03 00:36:03 +0000 | [diff] [blame] | 310 | #ifndef EMULATE_LIBCXX03 |
George Karpenkov | 8b53f7c | 2017-10-09 23:20:46 +0000 | [diff] [blame] | 311 | std::call_once(g, false); // no-warning |
George Karpenkov | 0354483 | 2017-11-03 00:36:03 +0000 | [diff] [blame] | 312 | #endif |
George Karpenkov | 8b53f7c | 2017-10-09 23:20:46 +0000 | [diff] [blame] | 313 | } |
George Karpenkov | bd4254c | 2017-10-20 23:29:59 +0000 | [diff] [blame] | 314 | |
| 315 | void test_lambda_refcapture() { |
| 316 | static std::once_flag flag; |
| 317 | int a = 6; |
| 318 | std::call_once(flag, [&](int &a) { a = 42; }, a); |
George Karpenkov | 0354483 | 2017-11-03 00:36:03 +0000 | [diff] [blame] | 319 | #ifndef EMULATE_LIBCXX03 |
George Karpenkov | bd4254c | 2017-10-20 23:29:59 +0000 | [diff] [blame] | 320 | clang_analyzer_eval(a == 42); // expected-warning{{TRUE}} |
George Karpenkov | 0354483 | 2017-11-03 00:36:03 +0000 | [diff] [blame] | 321 | #endif |
George Karpenkov | bd4254c | 2017-10-20 23:29:59 +0000 | [diff] [blame] | 322 | } |
| 323 | |
| 324 | void test_lambda_refcapture2() { |
| 325 | static std::once_flag flag; |
| 326 | int a = 6; |
| 327 | std::call_once(flag, [=](int &a) { a = 42; }, a); |
George Karpenkov | 0354483 | 2017-11-03 00:36:03 +0000 | [diff] [blame] | 328 | #ifndef EMULATE_LIBCXX03 |
George Karpenkov | bd4254c | 2017-10-20 23:29:59 +0000 | [diff] [blame] | 329 | clang_analyzer_eval(a == 42); // expected-warning{{TRUE}} |
George Karpenkov | 0354483 | 2017-11-03 00:36:03 +0000 | [diff] [blame] | 330 | #endif |
George Karpenkov | bd4254c | 2017-10-20 23:29:59 +0000 | [diff] [blame] | 331 | } |
| 332 | |
| 333 | void 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 Karpenkov | 0354483 | 2017-11-03 00:36:03 +0000 | [diff] [blame] | 337 | #ifndef EMULATE_LIBCXX03 |
George Karpenkov | bd4254c | 2017-10-20 23:29:59 +0000 | [diff] [blame] | 338 | clang_analyzer_eval(a == 42); // expected-warning{{FALSE}} |
George Karpenkov | 0354483 | 2017-11-03 00:36:03 +0000 | [diff] [blame] | 339 | #endif |
George Karpenkov | bd4254c | 2017-10-20 23:29:59 +0000 | [diff] [blame] | 340 | } |
| 341 | |
| 342 | void mutator(int ¶m) { |
| 343 | param = 42; |
| 344 | } |
| 345 | void test_reftypes_funcptr() { |
| 346 | static std::once_flag flag; |
| 347 | int a = 6; |
| 348 | std::call_once(flag, &mutator, a); |
George Karpenkov | 0354483 | 2017-11-03 00:36:03 +0000 | [diff] [blame] | 349 | #ifndef EMULATE_LIBCXX03 |
George Karpenkov | bd4254c | 2017-10-20 23:29:59 +0000 | [diff] [blame] | 350 | clang_analyzer_eval(a == 42); // expected-warning{{TRUE}} |
George Karpenkov | 0354483 | 2017-11-03 00:36:03 +0000 | [diff] [blame] | 351 | #endif |
George Karpenkov | bd4254c | 2017-10-20 23:29:59 +0000 | [diff] [blame] | 352 | } |
| 353 | |
| 354 | void fail_mutator(int param) { |
| 355 | param = 42; |
| 356 | } |
| 357 | void test_mutator_noref() { |
| 358 | static std::once_flag flag; |
| 359 | int a = 6; |
| 360 | std::call_once(flag, &fail_mutator, a); |
George Karpenkov | 0354483 | 2017-11-03 00:36:03 +0000 | [diff] [blame] | 361 | #ifndef EMULATE_LIBCXX03 |
George Karpenkov | bd4254c | 2017-10-20 23:29:59 +0000 | [diff] [blame] | 362 | clang_analyzer_eval(a == 42); // expected-warning{{FALSE}} |
George Karpenkov | 0354483 | 2017-11-03 00:36:03 +0000 | [diff] [blame] | 363 | #endif |
George Karpenkov | bd4254c | 2017-10-20 23:29:59 +0000 | [diff] [blame] | 364 | } |
George Karpenkov | 98e81cd | 2017-10-24 00:13:18 +0000 | [diff] [blame] | 365 | |
| 366 | // Function is implicitly treated as a function pointer |
| 367 | // even when an ampersand is not explicitly set. |
| 368 | void callbackn(int ¶m) { |
| 369 | param = 42; |
George Karpenkov | f671bd2 | 2017-10-25 00:03:45 +0000 | [diff] [blame] | 370 | } |
George Karpenkov | 98e81cd | 2017-10-24 00:13:18 +0000 | [diff] [blame] | 371 | void test_implicit_funcptr() { |
| 372 | int x = 0; |
| 373 | static std::once_flag flagn; |
| 374 | |
| 375 | std::call_once(flagn, callbackn, x); |
George Karpenkov | 0354483 | 2017-11-03 00:36:03 +0000 | [diff] [blame] | 376 | #ifndef EMULATE_LIBCXX03 |
George Karpenkov | 98e81cd | 2017-10-24 00:13:18 +0000 | [diff] [blame] | 377 | clang_analyzer_eval(x == 42); // expected-warning{{TRUE}} |
George Karpenkov | 0354483 | 2017-11-03 00:36:03 +0000 | [diff] [blame] | 378 | #endif |
George Karpenkov | 98e81cd | 2017-10-24 00:13:18 +0000 | [diff] [blame] | 379 | } |
George Karpenkov | 5920232 | 2018-02-02 01:44:07 +0000 | [diff] [blame] | 380 | |
| 381 | int param_passed(int *x) { |
| 382 | return *x; // no-warning, as std::function is not working yet. |
| 383 | } |
| 384 | |
| 385 | void 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. |
| 391 | void callback_with_implicit_cast_ok() { |
| 392 | std::once_flag flag; |
| 393 | call_once(flag, callback_taking_func_ok, ¶m_passed); |
| 394 | } |
| 395 | |
| 396 | void 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. |
| 402 | void callback_with_implicit_cast() { |
| 403 | std::once_flag flag; |
| 404 | call_once(flag, callback_taking_func, callback_with_implicit_cast); |
| 405 | } |
George Karpenkov | faa03f4 | 2018-05-16 00:29:13 +0000 | [diff] [blame] | 406 | |
| 407 | std::once_flag another_once_flag; |
| 408 | typedef void (*my_callback_t)(int *); |
| 409 | my_callback_t callback; |
| 410 | int global_int; |
| 411 | |
| 412 | void rdar40270582() { |
| 413 | call_once(another_once_flag, callback, &global_int); |
| 414 | } |