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::call_once implementation. 13 namespace std { 14 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 32 #ifndef EMULATE_LIBSTDCPP 33 typedef struct once_flag_s { 34 unsigned long __state_ = 0; 35 } once_flag; 36 #else 37 typedef struct once_flag_s { 38 int _M_once = 0; 39 } once_flag; 40 #endif 41 42 #ifndef EMULATE_LIBCXX03 43 template <class Callable, class... Args> 44 void call_once(once_flag &o, Callable&& func, Args&&... args) {}; 45 #else 46 template <class Callable, class... Args> // libcxx03 call_once 47 void call_once(once_flag &o, Callable func, Args&&... args) {}; 48 #endif 49 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; 59 #ifndef EMULATE_LIBCXX03 60 int y = *x; // expected-warning{{Dereference of null pointer (loaded from variable 'x')}} 61 #endif 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 78 #ifndef EMULATE_LIBCXX03 79 *x = 100; // no-warning 80 clang_analyzer_eval(z == 100); // expected-warning{{TRUE}} 81 #endif 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 94 #ifndef EMULATE_LIBCXX03 95 *x = 100; // no-warning 96 #else 97 *x = 100; // expected-warning{{Dereference of null pointer (loaded from variable 'x')}} 98 #endif 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 111 #ifndef EMULATE_LIBCXX03 112 *x = 100; // expected-warning{{Dereference of null pointer (loaded from variable 'x')}} 113 #endif 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 130 #ifndef EMULATE_LIBCXX03 131 *x = 100; // expected-warning{{Dereference of null pointer (loaded from variable 'x')}} 132 #endif 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 149 #ifndef EMULATE_LIBCXX03 150 *x = 100; // no-warning 151 #endif 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); 162 #ifndef EMULATE_LIBCXX03 163 clang_analyzer_eval(global == 1); // expected-warning{{TRUE}} 164 #endif 165 } 166 167 template <class _Fp> 168 class function; // undefined 169 template <class _Rp, class... _ArgTypes> 170 struct function<_Rp(_ArgTypes...)> { 171 _Rp operator()(_ArgTypes...) const {}; 172 template <class _Fp> 173 function(_Fp) {}; 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 204 #ifndef EMULATE_LIBCXX03 205 clang_analyzer_eval(y == 120); // expected-warning{{TRUE}} 206 #endif 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 218 #ifndef EMULATE_LIBCXX03 219 clang_analyzer_eval(x == 120); // expected-warning{{FALSE}} 220 #endif 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); 233 #ifndef EMULATE_LIBCXX03 234 clang_analyzer_eval(y == 120); // expected-warning{{TRUE}} 235 #endif 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 247 #ifndef EMULATE_LIBCXX03 248 clang_analyzer_eval(x == 120); // expected-warning{{FALSE}} 249 clang_analyzer_eval(x == 6); // expected-warning{{TRUE}} 250 #endif 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); 261 #ifndef EMULATE_LIBCXX03 262 clang_analyzer_eval(global2 == 6); // expected-warning{{TRUE}} 263 #endif 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 277 #ifndef EMULATE_LIBCXX03 278 clang_analyzer_eval(global3 == 6); // expected-warning{{TRUE}} 279 #endif 280 } 281 282 void test_blocks() { 283 global3 = 0; 284 std::once_flag flag; 285 std::call_once(flag, ^{ 286 global3 = 120; 287 }); 288 #ifndef EMULATE_LIBCXX03 289 clang_analyzer_eval(global3 == 120); // expected-warning{{TRUE}} 290 #endif 291 } 292 293 int call_once() { 294 return 5; 295 } 296 297 void test_non_std_call_once() { 298 int x = call_once(); 299 #ifndef EMULATE_LIBCXX03 300 clang_analyzer_eval(x == 5); // expected-warning{{TRUE}} 301 #endif 302 } 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() { 310 #ifndef EMULATE_LIBCXX03 311 std::call_once(g, false); // no-warning 312 #endif 313 } 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); 319 #ifndef EMULATE_LIBCXX03 320 clang_analyzer_eval(a == 42); // expected-warning{{TRUE}} 321 #endif 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); 328 #ifndef EMULATE_LIBCXX03 329 clang_analyzer_eval(a == 42); // expected-warning{{TRUE}} 330 #endif 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); 337 #ifndef EMULATE_LIBCXX03 338 clang_analyzer_eval(a == 42); // expected-warning{{FALSE}} 339 #endif 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); 349 #ifndef EMULATE_LIBCXX03 350 clang_analyzer_eval(a == 42); // expected-warning{{TRUE}} 351 #endif 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); 361 #ifndef EMULATE_LIBCXX03 362 clang_analyzer_eval(a == 42); // expected-warning{{FALSE}} 363 #endif 364 } 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; 370 } 371 void test_implicit_funcptr() { 372 int x = 0; 373 static std::once_flag flagn; 374 375 std::call_once(flagn, callbackn, x); 376 #ifndef EMULATE_LIBCXX03 377 clang_analyzer_eval(x == 42); // expected-warning{{TRUE}} 378 #endif 379 } 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 } 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 } 415