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