581 lines · cpp
1// RUN: %clang_analyze_cc1 -Wno-ignored-reference-qualifiers -analyzer-checker=core,debug.ExprInspection -std=c++17 -verify %s2 3#include "Inputs/system-header-simulator-cxx.h"4 5void clang_analyzer_eval(bool);6 7namespace std {8template <typename T>9struct tuple_size {10};11 12template <std::size_t I, typename T>13struct tuple_element {14};15 16// The std::pair in our system header simulator is not tuple-like, so a tuple-like mock is created here17template <typename T1, typename T2>18struct mock_pair {19 T1 first;20 T2 second;21};22template <typename T1, typename T2>23struct tuple_size<mock_pair<T1, T2>> {24 static const std::size_t value = 2;25};26 27template <typename T1, typename T2>28struct tuple_element<0, mock_pair<T1, T2>> {29 using type = T1;30};31 32template <typename T1, typename T2>33struct tuple_element<1, mock_pair<T1, T2>> {34 using type = T2;35};36 37template <std::size_t I, class T>38using tuple_element_t = typename tuple_element<I, T>::type;39 40template <std::size_t I, class T1, class T2>41constexpr std::tuple_element_t<I, std::mock_pair<T1, T2>> &42get(std::mock_pair<T1, T2> &p) noexcept {43 if (I == 0)44 return p.first;45 else46 return p.second;47}48 49template <std::size_t I, class T1, class T2>50constexpr const std::tuple_element_t<I, std::mock_pair<T1, T2>> &51get(const std::mock_pair<T1, T2> &p) noexcept {52 if (I == 0)53 return p.first;54 else55 return p.second;56}57 58template <std::size_t I, class T1, class T2>59constexpr std::tuple_element_t<I, std::mock_pair<T1, T2>> &&60get(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 else65 return static_cast<std::tuple_element_t<I, std::mock_pair<T1, T2>> &&>(p.second);66}67 68template <std::size_t I, class T1, class T2>69constexpr const std::tuple_element_t<I, std::mock_pair<T1, T2>> &&70get(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 else74 return static_cast<std::tuple_element_t<I, std::mock_pair<T1, T2>> &&>(p.second);75}76 77} // namespace std78// A utility that generates a tuple-like struct with 2 fields79// 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 98void 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 121void 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 144void 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 167GENERATE_TUPLE_LIKE_STRUCT(Test, int);168 169template <std::size_t I>170int 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 180void 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 204GENERATE_TUPLE_LIKE_STRUCT(Test2, int);205 206template <std::size_t I>207int 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 217void 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 243void 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 269struct MixedTest {270 int x;271 char &&y;272 int &z;273};274 275namespace std {276template <>277struct tuple_size<MixedTest> {278 static const std::size_t value = 3;279};280 281template <>282struct tuple_element<0, MixedTest> {283 using type = int;284};285 286template <>287struct tuple_element<1, MixedTest> {288 using type = char &&;289};290 291template <>292struct tuple_element<2, MixedTest> {293 using type = int &;294};295 296template <std::size_t I, typename T>297using tuple_element_t = typename tuple_element<I, T>::type;298 299} // namespace std300 301template <std::size_t I>302const std::tuple_element_t<I, MixedTest> &get(const MixedTest &t) {}303 304template <>305const std::tuple_element_t<0, MixedTest> &get<0>(const MixedTest &t) {306 return t.x;307}308 309template <>310const std::tuple_element_t<1, MixedTest> &get<1>(const MixedTest &t) {311 return t.y;312}313 314template <>315const std::tuple_element_t<2, MixedTest> &get<2>(const MixedTest &t) {316 return t.z;317}318 319void 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 336template <std::size_t I>337std::tuple_element_t<I, MixedTest> &get(MixedTest &t) {}338 339template <>340std::tuple_element_t<0, MixedTest> &get<0>(MixedTest &t) {341 return t.x;342}343 344template <>345std::tuple_element_t<1, MixedTest> &get<1>(MixedTest &t) {346 return t.y;347}348 349template <>350std::tuple_element_t<2, MixedTest> &get<2>(MixedTest &t) {351 return t.z;352}353 354void 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 377void 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 400void 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 418struct Small_Non_POD {419 int i;420 int j;421};422 423void 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 453void 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 483void 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 513GENERATE_TUPLE_LIKE_STRUCT(Uninit, int);514template <std::size_t I>515int &get(Uninit &&t) {516 if (I == 0) {517 return t.first;518 } else {519 return t.second;520 }521}522 523void uninit_a(void) {524 Uninit u;525 526 auto [a, b] = u;527 528 int x = a; // expected-warning{{Assigned value is uninitialized}}529}530 531void uninit_b(void) {532 Uninit u;533 534 auto [a, b] = u;535 536 int x = b; // expected-warning{{Assigned value is uninitialized}}537}538 539GENERATE_TUPLE_LIKE_STRUCT(UninitCall, int);540template <std::size_t I>541int get(UninitCall t) {542 if (I == 0) {543 return t.first;544 } else {545 return t.second;546 }547}548 549void 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 558void 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 570void 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