[RISCV][FMV] Support target_clones (#85786)
[llvm-project.git] / clang / test / Analysis / uninit-structured-binding-tuple.cpp
blobbc5644474fc9814aa4d2536efb91141d5c63f721
1 // RUN: %clang_analyze_cc1 -Wno-ignored-reference-qualifiers -analyzer-checker=core,debug.ExprInspection -std=c++17 -verify %s
3 #include "Inputs/system-header-simulator-cxx.h"
5 void clang_analyzer_eval(bool);
7 namespace std {
8 template <typename T>
9 struct tuple_size {
12 template <std::size_t I, typename T>
13 struct tuple_element {
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;
22 template <typename T1, typename T2>
23 struct tuple_size<mock_pair<T1, T2>> {
24 static const std::size_t value = 2;
27 template <typename T1, typename T2>
28 struct tuple_element<0, mock_pair<T1, T2>> {
29 using type = T1;
32 template <typename T1, typename T2>
33 struct tuple_element<1, mock_pair<T1, T2>> {
34 using type = T2;
37 template <std::size_t I, class T>
38 using tuple_element_t = typename tuple_element<I, T>::type;
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;
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;
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 {
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);
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);
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 }; \
86 namespace std { \
87 template <> \
88 struct tuple_size<name> { \
89 static const std::size_t value = 2; \
90 }; \
92 template <std::size_t I> \
93 struct tuple_element<I, name> { \
94 using type = element_type; \
95 }; \
98 void non_user_defined_by_value(void) {
99 std::mock_pair<int, int> p = {1, 2};
101 auto [u, v] = p;
103 clang_analyzer_eval(u == 1); // expected-warning{{TRUE}}
104 clang_analyzer_eval(v == 2); // expected-warning{{TRUE}}
106 int x = u;
107 u = 10;
108 int y = u;
110 clang_analyzer_eval(x == 1); // expected-warning{{TRUE}}
111 clang_analyzer_eval(u == 10); // expected-warning{{TRUE}}
113 clang_analyzer_eval(y == 10); // expected-warning{{TRUE}}
114 clang_analyzer_eval(p.first == 1); // expected-warning{{TRUE}}
116 p.first = 5;
118 clang_analyzer_eval(u == 10); // expected-warning{{TRUE}}
121 void non_user_defined_by_lref(void) {
122 std::mock_pair<int, int> p = {1, 2};
124 auto &[u, v] = p;
126 int x = u;
127 u = 10;
128 int y = u;
130 clang_analyzer_eval(x == 1); // expected-warning{{TRUE}}
131 clang_analyzer_eval(u == 10); // expected-warning{{TRUE}}
133 clang_analyzer_eval(y == 10); // expected-warning{{TRUE}}
134 clang_analyzer_eval(p.first == 10); // expected-warning{{TRUE}}
136 clang_analyzer_eval(v == 2); // expected-warning{{TRUE}}
137 clang_analyzer_eval(p.second == 2); // expected-warning{{TRUE}}
139 p.first = 5;
141 clang_analyzer_eval(u == 5); // expected-warning{{TRUE}}
144 void non_user_defined_by_rref(void) {
145 std::mock_pair<int, int> p = {1, 2};
147 auto &&[u, v] = p;
149 int x = u;
150 u = 10;
151 int y = u;
153 clang_analyzer_eval(x == 1); // expected-warning{{TRUE}}
154 clang_analyzer_eval(u == 10); // expected-warning{{TRUE}}
156 clang_analyzer_eval(y == 10); // expected-warning{{TRUE}}
157 clang_analyzer_eval(p.first == 10); // expected-warning{{TRUE}}
159 clang_analyzer_eval(v == 2); // expected-warning{{TRUE}}
160 clang_analyzer_eval(p.second == 2); // expected-warning{{TRUE}}
162 p.first = 5;
164 clang_analyzer_eval(u == 5); // expected-warning{{TRUE}}
167 GENERATE_TUPLE_LIKE_STRUCT(Test, int);
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;
180 void user_defined_get_val_by_val(void) {
181 Test p{1, 2};
182 auto [u, v] = p;
184 clang_analyzer_eval(u == 1); // expected-warning{{TRUE}}
186 u = 8;
188 int x = u;
190 clang_analyzer_eval(x == 8); // expected-warning{{TRUE}}
192 clang_analyzer_eval(u == 8); // expected-warning{{TRUE}}
193 clang_analyzer_eval(v == 2); // expected-warning{{TRUE}}
195 clang_analyzer_eval(p.first == 1); // expected-warning{{TRUE}}
196 clang_analyzer_eval(p.second == 2); // expected-warning{{TRUE}}
198 p.first = 5;
200 clang_analyzer_eval(u == 8); // expected-warning{{TRUE}}
201 clang_analyzer_eval(p.first == 5); // expected-warning{{TRUE}}
204 GENERATE_TUPLE_LIKE_STRUCT(Test2, int);
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;
217 void user_defined_get_val_by_lref(void) {
218 Test2 p{1, 2};
220 auto &[u, v] = p;
222 clang_analyzer_eval(u == 1); // expected-warning{{TRUE}}
223 clang_analyzer_eval(v == 10); // expected-warning{{TRUE}}
225 u = 8;
227 int x = u;
229 clang_analyzer_eval(x == 8); // expected-warning{{TRUE}}
231 clang_analyzer_eval(u == 8); // expected-warning{{TRUE}}
232 clang_analyzer_eval(v == 10); // expected-warning{{TRUE}}
234 clang_analyzer_eval(p.first == 20); // expected-warning{{TRUE}}
235 clang_analyzer_eval(p.second == 10); // expected-warning{{TRUE}}
237 p.first = 5;
239 clang_analyzer_eval(u == 8); // expected-warning{{TRUE}}
240 clang_analyzer_eval(p.first == 5); // expected-warning{{TRUE}}
243 void user_defined_get_val_by_rref(void) {
244 Test2 p{1, 2};
246 auto &&[u, v] = p;
248 clang_analyzer_eval(u == 1); // expected-warning{{TRUE}}
249 clang_analyzer_eval(v == 10); // expected-warning{{TRUE}}
251 u = 8;
253 int x = u;
255 clang_analyzer_eval(x == 8); // expected-warning{{TRUE}}
257 clang_analyzer_eval(u == 8); // expected-warning{{TRUE}}
258 clang_analyzer_eval(v == 10); // expected-warning{{TRUE}}
260 clang_analyzer_eval(p.first == 20); // expected-warning{{TRUE}}
261 clang_analyzer_eval(p.second == 10); // expected-warning{{TRUE}}
263 p.first = 5;
265 clang_analyzer_eval(u == 8); // expected-warning{{TRUE}}
266 clang_analyzer_eval(p.first == 5); // expected-warning{{TRUE}}
269 struct MixedTest {
270 int x;
271 char &&y;
272 int &z;
275 namespace std {
276 template <>
277 struct tuple_size<MixedTest> {
278 static const std::size_t value = 3;
281 template <>
282 struct tuple_element<0, MixedTest> {
283 using type = int;
286 template <>
287 struct tuple_element<1, MixedTest> {
288 using type = char &&;
291 template <>
292 struct tuple_element<2, MixedTest> {
293 using type = int &;
296 template <std::size_t I, typename T>
297 using tuple_element_t = typename tuple_element<I, T>::type;
299 } // namespace std
301 template <std::size_t I>
302 const std::tuple_element_t<I, MixedTest> &get(const MixedTest &t) {}
304 template <>
305 const std::tuple_element_t<0, MixedTest> &get<0>(const MixedTest &t) {
306 return t.x;
309 template <>
310 const std::tuple_element_t<1, MixedTest> &get<1>(const MixedTest &t) {
311 return t.y;
314 template <>
315 const std::tuple_element_t<2, MixedTest> &get<2>(const MixedTest &t) {
316 return t.z;
319 void mixed_type_cref(void) {
320 int x = 1;
321 char y = 2;
322 int z = 3;
324 MixedTest m{x, std::move(y), z};
325 const auto &[a, b, c] = m;
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}}
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}}
336 template <std::size_t I>
337 std::tuple_element_t<I, MixedTest> &get(MixedTest &t) {}
339 template <>
340 std::tuple_element_t<0, MixedTest> &get<0>(MixedTest &t) {
341 return t.x;
344 template <>
345 std::tuple_element_t<1, MixedTest> &get<1>(MixedTest &t) {
346 return t.y;
349 template <>
350 std::tuple_element_t<2, MixedTest> &get<2>(MixedTest &t) {
351 return t.z;
354 void mixed_type_lref(void) {
355 int x = 1;
356 char y = 2;
357 int z = 3;
359 MixedTest m{x, std::move(y), z};
360 auto &[a, b, c] = m;
362 a = 4;
363 b = 5;
364 c = 6;
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}}
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}}
374 clang_analyzer_eval(z == 6); // expected-warning{{TRUE}}
377 void mixed_type_rref(void) {
378 int x = 1;
379 char y = 2;
380 int z = 3;
382 MixedTest m{x, std::move(y), z};
383 auto &&[a, b, c] = m;
385 a = 4;
386 b = 5;
387 c = 6;
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}}
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}}
397 clang_analyzer_eval(z == 6); // expected-warning{{TRUE}}
400 void ref_val(void) {
401 int i = 1, j = 2;
402 std::mock_pair<int &, int &> p{i, j};
404 auto [a, b] = p;
405 clang_analyzer_eval(a == 1); // expected-warning{{TRUE}}
406 clang_analyzer_eval(b == 2); // expected-warning{{TRUE}}
408 a = 3;
409 b = 4;
411 clang_analyzer_eval(p.first == 3); // expected-warning{{TRUE}}
412 clang_analyzer_eval(p.second == 4); // expected-warning{{TRUE}}
414 clang_analyzer_eval(a == 3); // expected-warning{{TRUE}}
415 clang_analyzer_eval(b == 4); // expected-warning{{TRUE}}
418 struct Small_Non_POD {
419 int i;
420 int j;
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}};
426 auto [a, b] = p;
428 clang_analyzer_eval(a.i == 1); // expected-warning{{TRUE}}
429 clang_analyzer_eval(a.j == 2); // expected-warning{{TRUE}}
431 clang_analyzer_eval(b.i == 1); // expected-warning{{TRUE}}
432 clang_analyzer_eval(b.j == 2); // expected-warning{{TRUE}}
434 a.i = 3;
435 a.j = 4;
437 b.i = 5;
438 b.j = 6;
440 clang_analyzer_eval(a.i == 3); // expected-warning{{TRUE}}
441 clang_analyzer_eval(a.j == 4); // expected-warning{{TRUE}}
443 clang_analyzer_eval(b.i == 5); // expected-warning{{TRUE}}
444 clang_analyzer_eval(b.j == 6); // expected-warning{{TRUE}}
446 clang_analyzer_eval(p.first.i == 1); // expected-warning{{TRUE}}
447 clang_analyzer_eval(p.first.j == 2); // expected-warning{{TRUE}}
449 clang_analyzer_eval(p.second.i == 1); // expected-warning{{TRUE}}
450 clang_analyzer_eval(p.second.j == 2); // expected-warning{{TRUE}}
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}};
456 auto &[a, b] = p;
458 clang_analyzer_eval(a.i == 1); // expected-warning{{TRUE}}
459 clang_analyzer_eval(a.j == 2); // expected-warning{{TRUE}}
461 clang_analyzer_eval(b.i == 1); // expected-warning{{TRUE}}
462 clang_analyzer_eval(b.j == 2); // expected-warning{{TRUE}}
464 a.i = 3;
465 a.j = 4;
467 b.i = 5;
468 b.j = 6;
470 clang_analyzer_eval(a.i == 3); // expected-warning{{TRUE}}
471 clang_analyzer_eval(a.j == 4); // expected-warning{{TRUE}}
473 clang_analyzer_eval(b.i == 5); // expected-warning{{TRUE}}
474 clang_analyzer_eval(b.j == 6); // expected-warning{{TRUE}}
476 clang_analyzer_eval(p.first.i == 3); // expected-warning{{TRUE}}
477 clang_analyzer_eval(p.first.j == 4); // expected-warning{{TRUE}}
479 clang_analyzer_eval(p.second.i == 5); // expected-warning{{TRUE}}
480 clang_analyzer_eval(p.second.j == 6); // expected-warning{{TRUE}}
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}};
486 auto &&[a, b] = p;
488 clang_analyzer_eval(a.i == 1); // expected-warning{{TRUE}}
489 clang_analyzer_eval(a.j == 2); // expected-warning{{TRUE}}
491 clang_analyzer_eval(b.i == 1); // expected-warning{{TRUE}}
492 clang_analyzer_eval(b.j == 2); // expected-warning{{TRUE}}
494 a.i = 3;
495 a.j = 4;
497 b.i = 5;
498 b.j = 6;
500 clang_analyzer_eval(a.i == 3); // expected-warning{{TRUE}}
501 clang_analyzer_eval(a.j == 4); // expected-warning{{TRUE}}
503 clang_analyzer_eval(b.i == 5); // expected-warning{{TRUE}}
504 clang_analyzer_eval(b.j == 6); // expected-warning{{TRUE}}
506 clang_analyzer_eval(p.first.i == 3); // expected-warning{{TRUE}}
507 clang_analyzer_eval(p.first.j == 4); // expected-warning{{TRUE}}
509 clang_analyzer_eval(p.second.i == 5); // expected-warning{{TRUE}}
510 clang_analyzer_eval(p.second.j == 6); // expected-warning{{TRUE}}
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;
523 void uninit_a(void) {
524 Uninit u;
526 auto [a, b] = u;
528 int x = a; // expected-warning{{Assigned value is garbage or undefined}}
531 void uninit_b(void) {
532 Uninit u;
534 auto [a, b] = u;
536 int x = b; // expected-warning{{Assigned value is garbage or undefined}}
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;
549 void uninit_call(void) {
550 UninitCall u;
552 auto [a, b] = u;
554 int x = a;
555 // expected-warning@543{{Undefined or garbage value returned to caller}}
558 void syntax_2() {
559 std::mock_pair<Small_Non_POD, Small_Non_POD> p{{1, 2}, {3, 4}};
561 auto [a, b]{p};
563 clang_analyzer_eval(a.i == 1); // expected-warning{{TRUE}}
564 clang_analyzer_eval(a.j == 2); // expected-warning{{TRUE}}
566 clang_analyzer_eval(b.i == 3); // expected-warning{{TRUE}}
567 clang_analyzer_eval(b.j == 4); // expected-warning{{TRUE}}
570 void syntax_3() {
571 std::mock_pair<Small_Non_POD, Small_Non_POD> p{{1, 2}, {3, 4}};
573 auto [a, b](p);
575 clang_analyzer_eval(a.i == 1); // expected-warning{{TRUE}}
576 clang_analyzer_eval(a.j == 2); // expected-warning{{TRUE}}
578 clang_analyzer_eval(b.i == 3); // expected-warning{{TRUE}}
579 clang_analyzer_eval(b.j == 4); // expected-warning{{TRUE}}