1 // RUN: %clang_analyze_cc1 -Wno-ignored-reference-qualifiers -analyzer-checker=core,debug.ExprInspection -std=c++17 -verify %s 2 3 #include "Inputs/system-header-simulator-cxx.h" 4 5 void clang_analyzer_eval(bool); 6 7 namespace std { 8 template <typename T> 9 struct tuple_size { 10 }; 11 12 template <std::size_t I, typename T> 13 struct tuple_element { 14 }; 15 16 // The std::pair in our system header simulator is not tuple-like, so a tuple-like mock is created here 17 template <typename T1, typename T2> 18 struct mock_pair { 19 T1 first; 20 T2 second; 21 }; 22 template <typename T1, typename T2> 23 struct tuple_size<mock_pair<T1, T2>> { 24 static const std::size_t value = 2; 25 }; 26 27 template <typename T1, typename T2> 28 struct tuple_element<0, mock_pair<T1, T2>> { 29 using type = T1; 30 }; 31 32 template <typename T1, typename T2> 33 struct tuple_element<1, mock_pair<T1, T2>> { 34 using type = T2; 35 }; 36 37 template <std::size_t I, class T> 38 using tuple_element_t = typename tuple_element<I, T>::type; 39 40 template <std::size_t I, class T1, class T2> 41 constexpr std::tuple_element_t<I, std::mock_pair<T1, T2>> & 42 get(std::mock_pair<T1, T2> &p) noexcept { 43 if (I == 0) 44 return p.first; 45 else 46 return p.second; 47 } 48 49 template <std::size_t I, class T1, class T2> 50 constexpr const std::tuple_element_t<I, std::mock_pair<T1, T2>> & 51 get(const std::mock_pair<T1, T2> &p) noexcept { 52 if (I == 0) 53 return p.first; 54 else 55 return p.second; 56 } 57 58 template <std::size_t I, class T1, class T2> 59 constexpr std::tuple_element_t<I, std::mock_pair<T1, T2>> && 60 get(std::mock_pair<T1, T2> &&p) noexcept { 61 62 if (I == 0) 63 return static_cast<std::tuple_element_t<I, std::mock_pair<T1, T2>> &&>(p.first); 64 else 65 return static_cast<std::tuple_element_t<I, std::mock_pair<T1, T2>> &&>(p.second); 66 } 67 68 template <std::size_t I, class T1, class T2> 69 constexpr const std::tuple_element_t<I, std::mock_pair<T1, T2>> && 70 get(const std::mock_pair<T1, T2> &&p) noexcept { 71 if (I == 0) 72 return static_cast<std::tuple_element_t<I, std::mock_pair<T1, T2>> &&>(p.first); 73 else 74 return static_cast<std::tuple_element_t<I, std::mock_pair<T1, T2>> &&>(p.second); 75 } 76 77 } // namespace std 78 // A utility that generates a tuple-like struct with 2 fields 79 // of the same type. The fields are 'first' and 'second' 80 #define GENERATE_TUPLE_LIKE_STRUCT(name, element_type) \ 81 struct name { \ 82 element_type first; \ 83 element_type second; \ 84 }; \ 85 \ 86 namespace std { \ 87 template <> \ 88 struct tuple_size<name> { \ 89 static const std::size_t value = 2; \ 90 }; \ 91 \ 92 template <std::size_t I> \ 93 struct tuple_element<I, name> { \ 94 using type = element_type; \ 95 }; \ 96 } 97 98 void non_user_defined_by_value(void) { 99 std::mock_pair<int, int> p = {1, 2}; 100 101 auto [u, v] = p; 102 103 clang_analyzer_eval(u == 1); // expected-warning{{TRUE}} 104 clang_analyzer_eval(v == 2); // expected-warning{{TRUE}} 105 106 int x = u; 107 u = 10; 108 int y = u; 109 110 clang_analyzer_eval(x == 1); // expected-warning{{TRUE}} 111 clang_analyzer_eval(u == 10); // expected-warning{{TRUE}} 112 113 clang_analyzer_eval(y == 10); // expected-warning{{TRUE}} 114 clang_analyzer_eval(p.first == 1); // expected-warning{{TRUE}} 115 116 p.first = 5; 117 118 clang_analyzer_eval(u == 10); // expected-warning{{TRUE}} 119 } 120 121 void non_user_defined_by_lref(void) { 122 std::mock_pair<int, int> p = {1, 2}; 123 124 auto &[u, v] = p; 125 126 int x = u; 127 u = 10; 128 int y = u; 129 130 clang_analyzer_eval(x == 1); // expected-warning{{TRUE}} 131 clang_analyzer_eval(u == 10); // expected-warning{{TRUE}} 132 133 clang_analyzer_eval(y == 10); // expected-warning{{TRUE}} 134 clang_analyzer_eval(p.first == 10); // expected-warning{{TRUE}} 135 136 clang_analyzer_eval(v == 2); // expected-warning{{TRUE}} 137 clang_analyzer_eval(p.second == 2); // expected-warning{{TRUE}} 138 139 p.first = 5; 140 141 clang_analyzer_eval(u == 5); // expected-warning{{TRUE}} 142 } 143 144 void non_user_defined_by_rref(void) { 145 std::mock_pair<int, int> p = {1, 2}; 146 147 auto &&[u, v] = p; 148 149 int x = u; 150 u = 10; 151 int y = u; 152 153 clang_analyzer_eval(x == 1); // expected-warning{{TRUE}} 154 clang_analyzer_eval(u == 10); // expected-warning{{TRUE}} 155 156 clang_analyzer_eval(y == 10); // expected-warning{{TRUE}} 157 clang_analyzer_eval(p.first == 10); // expected-warning{{TRUE}} 158 159 clang_analyzer_eval(v == 2); // expected-warning{{TRUE}} 160 clang_analyzer_eval(p.second == 2); // expected-warning{{TRUE}} 161 162 p.first = 5; 163 164 clang_analyzer_eval(u == 5); // expected-warning{{TRUE}} 165 } 166 167 GENERATE_TUPLE_LIKE_STRUCT(Test, int); 168 169 template <std::size_t I> 170 int get(Test t) { 171 if (I == 0) { 172 t.second = 10; 173 return t.first; 174 } else { 175 t.first = 20; 176 return t.second; 177 } 178 } 179 180 void user_defined_get_val_by_val(void) { 181 Test p{1, 2}; 182 auto [u, v] = p; 183 184 clang_analyzer_eval(u == 1); // expected-warning{{TRUE}} 185 186 u = 8; 187 188 int x = u; 189 190 clang_analyzer_eval(x == 8); // expected-warning{{TRUE}} 191 192 clang_analyzer_eval(u == 8); // expected-warning{{TRUE}} 193 clang_analyzer_eval(v == 2); // expected-warning{{TRUE}} 194 195 clang_analyzer_eval(p.first == 1); // expected-warning{{TRUE}} 196 clang_analyzer_eval(p.second == 2); // expected-warning{{TRUE}} 197 198 p.first = 5; 199 200 clang_analyzer_eval(u == 8); // expected-warning{{TRUE}} 201 clang_analyzer_eval(p.first == 5); // expected-warning{{TRUE}} 202 } 203 204 GENERATE_TUPLE_LIKE_STRUCT(Test2, int); 205 206 template <std::size_t I> 207 int get(Test2 &t) { 208 if (I == 0) { 209 t.second = 10; 210 return t.first; 211 } else { 212 t.first = 20; 213 return t.second; 214 } 215 } 216 217 void user_defined_get_val_by_lref(void) { 218 Test2 p{1, 2}; 219 220 auto &[u, v] = p; 221 222 clang_analyzer_eval(u == 1); // expected-warning{{TRUE}} 223 clang_analyzer_eval(v == 10); // expected-warning{{TRUE}} 224 225 u = 8; 226 227 int x = u; 228 229 clang_analyzer_eval(x == 8); // expected-warning{{TRUE}} 230 231 clang_analyzer_eval(u == 8); // expected-warning{{TRUE}} 232 clang_analyzer_eval(v == 10); // expected-warning{{TRUE}} 233 234 clang_analyzer_eval(p.first == 20); // expected-warning{{TRUE}} 235 clang_analyzer_eval(p.second == 10); // expected-warning{{TRUE}} 236 237 p.first = 5; 238 239 clang_analyzer_eval(u == 8); // expected-warning{{TRUE}} 240 clang_analyzer_eval(p.first == 5); // expected-warning{{TRUE}} 241 } 242 243 void user_defined_get_val_by_rref(void) { 244 Test2 p{1, 2}; 245 246 auto &&[u, v] = p; 247 248 clang_analyzer_eval(u == 1); // expected-warning{{TRUE}} 249 clang_analyzer_eval(v == 10); // expected-warning{{TRUE}} 250 251 u = 8; 252 253 int x = u; 254 255 clang_analyzer_eval(x == 8); // expected-warning{{TRUE}} 256 257 clang_analyzer_eval(u == 8); // expected-warning{{TRUE}} 258 clang_analyzer_eval(v == 10); // expected-warning{{TRUE}} 259 260 clang_analyzer_eval(p.first == 20); // expected-warning{{TRUE}} 261 clang_analyzer_eval(p.second == 10); // expected-warning{{TRUE}} 262 263 p.first = 5; 264 265 clang_analyzer_eval(u == 8); // expected-warning{{TRUE}} 266 clang_analyzer_eval(p.first == 5); // expected-warning{{TRUE}} 267 } 268 269 struct MixedTest { 270 int x; 271 char &&y; 272 int &z; 273 }; 274 275 namespace std { 276 template <> 277 struct tuple_size<MixedTest> { 278 static const std::size_t value = 3; 279 }; 280 281 template <> 282 struct tuple_element<0, MixedTest> { 283 using type = int; 284 }; 285 286 template <> 287 struct tuple_element<1, MixedTest> { 288 using type = char &&; 289 }; 290 291 template <> 292 struct tuple_element<2, MixedTest> { 293 using type = int &; 294 }; 295 296 template <std::size_t I, typename T> 297 using tuple_element_t = typename tuple_element<I, T>::type; 298 299 } // namespace std 300 301 template <std::size_t I> 302 const std::tuple_element_t<I, MixedTest> &get(const MixedTest &t) {} 303 304 template <> 305 const std::tuple_element_t<0, MixedTest> &get<0>(const MixedTest &t) { 306 return t.x; 307 } 308 309 template <> 310 const std::tuple_element_t<1, MixedTest> &get<1>(const MixedTest &t) { 311 return t.y; 312 } 313 314 template <> 315 const std::tuple_element_t<2, MixedTest> &get<2>(const MixedTest &t) { 316 return t.z; 317 } 318 319 void mixed_type_cref(void) { 320 int x = 1; 321 char y = 2; 322 int z = 3; 323 324 MixedTest m{x, std::move(y), z}; 325 const auto &[a, b, c] = m; 326 327 clang_analyzer_eval(a == 1); // expected-warning{{TRUE}} 328 clang_analyzer_eval(b == 2); // expected-warning{{TRUE}} 329 clang_analyzer_eval(c == 3); // expected-warning{{TRUE}} 330 331 clang_analyzer_eval(a == 1); // expected-warning{{TRUE}} 332 clang_analyzer_eval(b == 2); // expected-warning{{TRUE}} 333 clang_analyzer_eval(c == 3); // expected-warning{{TRUE}} 334 } 335 336 template <std::size_t I> 337 std::tuple_element_t<I, MixedTest> &get(MixedTest &t) {} 338 339 template <> 340 std::tuple_element_t<0, MixedTest> &get<0>(MixedTest &t) { 341 return t.x; 342 } 343 344 template <> 345 std::tuple_element_t<1, MixedTest> &get<1>(MixedTest &t) { 346 return t.y; 347 } 348 349 template <> 350 std::tuple_element_t<2, MixedTest> &get<2>(MixedTest &t) { 351 return t.z; 352 } 353 354 void mixed_type_lref(void) { 355 int x = 1; 356 char y = 2; 357 int z = 3; 358 359 MixedTest m{x, std::move(y), z}; 360 auto &[a, b, c] = m; 361 362 a = 4; 363 b = 5; 364 c = 6; 365 366 clang_analyzer_eval(get<0>(m) == 4); // expected-warning{{TRUE}} 367 clang_analyzer_eval(get<1>(m) == 5); // expected-warning{{TRUE}} 368 clang_analyzer_eval(get<2>(m) == 6); // expected-warning{{TRUE}} 369 370 clang_analyzer_eval(get<0>(m) == 4); // expected-warning{{TRUE}} 371 clang_analyzer_eval(get<1>(m) == 5); // expected-warning{{TRUE}} 372 clang_analyzer_eval(get<2>(m) == 6); // expected-warning{{TRUE}} 373 374 clang_analyzer_eval(z == 6); // expected-warning{{TRUE}} 375 } 376 377 void mixed_type_rref(void) { 378 int x = 1; 379 char y = 2; 380 int z = 3; 381 382 MixedTest m{x, std::move(y), z}; 383 auto &&[a, b, c] = m; 384 385 a = 4; 386 b = 5; 387 c = 6; 388 389 clang_analyzer_eval(get<0>(m) == 4); // expected-warning{{TRUE}} 390 clang_analyzer_eval(get<1>(m) == 5); // expected-warning{{TRUE}} 391 clang_analyzer_eval(get<2>(m) == 6); // expected-warning{{TRUE}} 392 393 clang_analyzer_eval(get<0>(m) == 4); // expected-warning{{TRUE}} 394 clang_analyzer_eval(get<1>(m) == 5); // expected-warning{{TRUE}} 395 clang_analyzer_eval(get<2>(m) == 6); // expected-warning{{TRUE}} 396 397 clang_analyzer_eval(z == 6); // expected-warning{{TRUE}} 398 } 399 400 void ref_val(void) { 401 int i = 1, j = 2; 402 std::mock_pair<int &, int &> p{i, j}; 403 404 auto [a, b] = p; 405 clang_analyzer_eval(a == 1); // expected-warning{{TRUE}} 406 clang_analyzer_eval(b == 2); // expected-warning{{TRUE}} 407 408 a = 3; 409 b = 4; 410 411 clang_analyzer_eval(p.first == 3); // expected-warning{{TRUE}} 412 clang_analyzer_eval(p.second == 4); // expected-warning{{TRUE}} 413 414 clang_analyzer_eval(a == 3); // expected-warning{{TRUE}} 415 clang_analyzer_eval(b == 4); // expected-warning{{TRUE}} 416 } 417 418 struct Small_Non_POD { 419 int i; 420 int j; 421 }; 422 423 void non_user_defined_small_non_pod_by_value(void) { 424 std::mock_pair<Small_Non_POD, Small_Non_POD> p{{1, 2}, {1, 2}}; 425 426 auto [a, b] = p; 427 428 clang_analyzer_eval(a.i == 1); // expected-warning{{TRUE}} 429 clang_analyzer_eval(a.j == 2); // expected-warning{{TRUE}} 430 431 clang_analyzer_eval(b.i == 1); // expected-warning{{TRUE}} 432 clang_analyzer_eval(b.j == 2); // expected-warning{{TRUE}} 433 434 a.i = 3; 435 a.j = 4; 436 437 b.i = 5; 438 b.j = 6; 439 440 clang_analyzer_eval(a.i == 3); // expected-warning{{TRUE}} 441 clang_analyzer_eval(a.j == 4); // expected-warning{{TRUE}} 442 443 clang_analyzer_eval(b.i == 5); // expected-warning{{TRUE}} 444 clang_analyzer_eval(b.j == 6); // expected-warning{{TRUE}} 445 446 clang_analyzer_eval(p.first.i == 1); // expected-warning{{TRUE}} 447 clang_analyzer_eval(p.first.j == 2); // expected-warning{{TRUE}} 448 449 clang_analyzer_eval(p.second.i == 1); // expected-warning{{TRUE}} 450 clang_analyzer_eval(p.second.j == 2); // expected-warning{{TRUE}} 451 } 452 453 void non_user_defined_small_non_pod_by_lref(void) { 454 std::mock_pair<Small_Non_POD, Small_Non_POD> p{{1, 2}, {1, 2}}; 455 456 auto &[a, b] = p; 457 458 clang_analyzer_eval(a.i == 1); // expected-warning{{TRUE}} 459 clang_analyzer_eval(a.j == 2); // expected-warning{{TRUE}} 460 461 clang_analyzer_eval(b.i == 1); // expected-warning{{TRUE}} 462 clang_analyzer_eval(b.j == 2); // expected-warning{{TRUE}} 463 464 a.i = 3; 465 a.j = 4; 466 467 b.i = 5; 468 b.j = 6; 469 470 clang_analyzer_eval(a.i == 3); // expected-warning{{TRUE}} 471 clang_analyzer_eval(a.j == 4); // expected-warning{{TRUE}} 472 473 clang_analyzer_eval(b.i == 5); // expected-warning{{TRUE}} 474 clang_analyzer_eval(b.j == 6); // expected-warning{{TRUE}} 475 476 clang_analyzer_eval(p.first.i == 3); // expected-warning{{TRUE}} 477 clang_analyzer_eval(p.first.j == 4); // expected-warning{{TRUE}} 478 479 clang_analyzer_eval(p.second.i == 5); // expected-warning{{TRUE}} 480 clang_analyzer_eval(p.second.j == 6); // expected-warning{{TRUE}} 481 } 482 483 void non_user_defined_small_non_pod_by_rref(void) { 484 std::mock_pair<Small_Non_POD, Small_Non_POD> p{{1, 2}, {1, 2}}; 485 486 auto &&[a, b] = p; 487 488 clang_analyzer_eval(a.i == 1); // expected-warning{{TRUE}} 489 clang_analyzer_eval(a.j == 2); // expected-warning{{TRUE}} 490 491 clang_analyzer_eval(b.i == 1); // expected-warning{{TRUE}} 492 clang_analyzer_eval(b.j == 2); // expected-warning{{TRUE}} 493 494 a.i = 3; 495 a.j = 4; 496 497 b.i = 5; 498 b.j = 6; 499 500 clang_analyzer_eval(a.i == 3); // expected-warning{{TRUE}} 501 clang_analyzer_eval(a.j == 4); // expected-warning{{TRUE}} 502 503 clang_analyzer_eval(b.i == 5); // expected-warning{{TRUE}} 504 clang_analyzer_eval(b.j == 6); // expected-warning{{TRUE}} 505 506 clang_analyzer_eval(p.first.i == 3); // expected-warning{{TRUE}} 507 clang_analyzer_eval(p.first.j == 4); // expected-warning{{TRUE}} 508 509 clang_analyzer_eval(p.second.i == 5); // expected-warning{{TRUE}} 510 clang_analyzer_eval(p.second.j == 6); // expected-warning{{TRUE}} 511 } 512 513 GENERATE_TUPLE_LIKE_STRUCT(Uninit, int); 514 template <std::size_t I> 515 int &get(Uninit &&t) { 516 if (I == 0) { 517 return t.first; 518 } else { 519 return t.second; 520 } 521 } 522 523 void uninit_a(void) { 524 Uninit u; 525 526 auto [a, b] = u; 527 528 int x = a; // expected-warning{{Assigned value is garbage or undefined}} 529 } 530 531 void uninit_b(void) { 532 Uninit u; 533 534 auto [a, b] = u; 535 536 int x = b; // expected-warning{{Assigned value is garbage or undefined}} 537 } 538 539 GENERATE_TUPLE_LIKE_STRUCT(UninitCall, int); 540 template <std::size_t I> 541 int get(UninitCall t) { 542 if (I == 0) { 543 return t.first; 544 } else { 545 return t.second; 546 } 547 } 548 549 void uninit_call(void) { 550 UninitCall u; 551 552 auto [a, b] = u; 553 554 int x = a; 555 // expected-warning@543{{Undefined or garbage value returned to caller}} 556 } 557 558 void syntax_2() { 559 std::mock_pair<Small_Non_POD, Small_Non_POD> p{{1, 2}, {3, 4}}; 560 561 auto [a, b]{p}; 562 563 clang_analyzer_eval(a.i == 1); // expected-warning{{TRUE}} 564 clang_analyzer_eval(a.j == 2); // expected-warning{{TRUE}} 565 566 clang_analyzer_eval(b.i == 3); // expected-warning{{TRUE}} 567 clang_analyzer_eval(b.j == 4); // expected-warning{{TRUE}} 568 } 569 570 void syntax_3() { 571 std::mock_pair<Small_Non_POD, Small_Non_POD> p{{1, 2}, {3, 4}}; 572 573 auto [a, b](p); 574 575 clang_analyzer_eval(a.i == 1); // expected-warning{{TRUE}} 576 clang_analyzer_eval(a.j == 2); // expected-warning{{TRUE}} 577 578 clang_analyzer_eval(b.i == 3); // expected-warning{{TRUE}} 579 clang_analyzer_eval(b.j == 4); // expected-warning{{TRUE}} 580 } 581