xref: /llvm-project/clang/test/SemaCXX/warn-unsequenced.cpp (revision 8a571538dff6dbc1b7f4fed6aed8be7ec1a00a8d)
1 // RUN: %clang_cc1 -fsyntax-only -verify=cxx11 -std=c++11 -Wno-unused -Wno-uninitialized \
2 // RUN:            -Wunsequenced -Wno-c++17-extensions -Wno-c++14-extensions %s
3 // RUN: %clang_cc1 -fsyntax-only -verify=cxx17 -std=c++17 -Wno-unused -Wno-uninitialized \
4 // RUN:            -Wunsequenced -Wno-c++17-extensions -Wno-c++14-extensions %s
5 
6 int f(int, int = 0);
7 int g1();
8 int g2(int);
9 
10 struct A {
11   int x, y;
12 };
13 struct S {
14   S(int, int);
15   int n;
16 };
17 
18 // TODO: Implement the C++17 sequencing rules.
19 void test() {
20   int a;
21   int xs[10];
22   ++a = 0; // ok
23   a + ++a; // cxx11-warning {{unsequenced modification and access to 'a'}}
24            // cxx17-warning@-1 {{unsequenced modification and access to 'a'}}
25   a = ++a; // ok
26   a + a++; // cxx11-warning {{unsequenced modification and access to 'a'}}
27            // cxx17-warning@-1 {{unsequenced modification and access to 'a'}}
28   a = a++; // cxx11-warning {{multiple unsequenced modifications to 'a'}}
29            // TODO cxx17-warning@-1 {{multiple unsequenced modifications to 'a'}}
30   ++ ++a; // ok
31   (a++, a++); // ok
32   ++a + ++a; // cxx11-warning {{multiple unsequenced modifications to 'a'}}
33              // cxx17-warning@-1 {{multiple unsequenced modifications to 'a'}}
34   a++ + a++; // cxx11-warning {{multiple unsequenced modifications to 'a'}}
35              // cxx17-warning@-1 {{multiple unsequenced modifications to 'a'}}
36   (a++, a) = 0; // ok, increment is sequenced before value computation of LHS
37   a = xs[++a]; // ok
38   a = xs[a++]; // cxx11-warning {{multiple unsequenced modifications to 'a'}}
39                // TODO cxx17-warning@-1 {{multiple unsequenced modifications to 'a'}}
40   (a ? xs[0] : xs[1]) = ++a; // cxx11-warning {{unsequenced modification and access to 'a'}}
41                              // TODO cxx17-warning@-1 {{unsequenced modification and access to 'a'}}
42   a = (++a, ++a); // ok
43   a = (a++, ++a); // ok
44   a = (a++, a++); // cxx11-warning {{multiple unsequenced modifications to 'a'}}
45                   // TODO cxx17-warning@-1 {{multiple unsequenced modifications to 'a'}}
46   f(a, a); // ok
47   f(a = 0, a); // cxx11-warning {{unsequenced modification and access to 'a'}}
48                // cxx17-warning@-1 {{unsequenced modification and access to 'a'}}
49   f(a, a += 0); // cxx11-warning {{unsequenced modification and access to 'a'}}
50                 // cxx17-warning@-1 {{unsequenced modification and access to 'a'}}
51   f(a = 0, a = 0); // cxx11-warning {{multiple unsequenced modifications to 'a'}}
52                    // cxx17-warning@-1 {{multiple unsequenced modifications to 'a'}}
53   a = f(++a); // ok
54   a = f(a++); // ok
55   a = f(++a, a++); // cxx11-warning {{multiple unsequenced modifications to 'a'}}
56                    // cxx17-warning@-1 {{multiple unsequenced modifications to 'a'}}
57 
58   // Compound assignment "A OP= B" is equivalent to "A = A OP B" except that A
59   // is evaluated only once.
60   (++a, a) = 1; // ok
61   (++a, a) += 1; // ok
62   a = ++a; // ok
63   a += ++a; // cxx11-warning {{unsequenced modification and access to 'a'}}
64             // TODO cxx17-warning@-1 {{unsequenced modification and access to 'a'}}
65 
66   A agg1 = { a++, a++ }; // ok
67   A agg2 = { a++ + a, a++ }; // cxx11-warning {{unsequenced modification and access to 'a'}}
68                              // cxx17-warning@-1 {{unsequenced modification and access to 'a'}}
69 
70   S str1(a++, a++); // cxx11-warning {{multiple unsequenced modifications to 'a'}}
71                     // cxx17-warning@-1 {{multiple unsequenced modifications to 'a'}}
72   S str2 = { a++, a++ }; // ok
73   S str3 = { a++ + a, a++ }; // cxx11-warning {{unsequenced modification and access to 'a'}}
74                              // cxx17-warning@-1 {{unsequenced modification and access to 'a'}}
75 
76   struct Z { A a; S s; } z = { { ++a, ++a }, { ++a, ++a } }; // ok
77   a = S { ++a, a++ }.n; // ok
78   A { ++a, a++ }.x; // ok
79   a = A { ++a, a++ }.x; // cxx11-warning {{multiple unsequenced modifications to 'a'}}
80                         // TODO cxx17-warning@-1 {{multiple unsequenced modifications to 'a'}}
81   A { ++a, a++ }.x + A { ++a, a++ }.y; // cxx11-warning {{multiple unsequenced modifications to 'a'}}
82                                        // cxx17-warning@-1 {{multiple unsequenced modifications to 'a'}}
83 
84   (xs[2] && (a = 0)) + a; // cxx11-warning {{unsequenced modification and access to 'a'}}
85                           // cxx17-warning@-1 {{unsequenced modification and access to 'a'}}
86   (0 && (a = 0)) + a; // ok
87   (1 && (a = 0)) + a; // cxx11-warning {{unsequenced modification and access to 'a'}}
88                       // cxx17-warning@-1 {{unsequenced modification and access to 'a'}}
89 
90   (xs[3] || (a = 0)) + a; // cxx11-warning {{unsequenced modification and access to 'a'}}
91                           // cxx17-warning@-1 {{unsequenced modification and access to 'a'}}
92   (0 || (a = 0)) + a; // cxx11-warning {{unsequenced modification and access to 'a'}}
93                       // cxx17-warning@-1 {{unsequenced modification and access to 'a'}}
94   (1 || (a = 0)) + a; // ok
95 
96   (xs[4] ? a : ++a) + a; // cxx11-warning {{unsequenced modification and access to 'a'}}
97                          // cxx17-warning@-1 {{unsequenced modification and access to 'a'}}
98   (0 ? a : ++a) + a; // cxx11-warning {{unsequenced modification and access to 'a'}}
99                      // cxx17-warning@-1 {{unsequenced modification and access to 'a'}}
100   (1 ? a : ++a) + a; // ok
101   (0 ? a : a++) + a; // cxx11-warning {{unsequenced modification and access to 'a'}}
102                      // cxx17-warning@-1 {{unsequenced modification and access to 'a'}}
103   (1 ? a : a++) + a; // ok
104   (xs[5] ? ++a : ++a) + a; // cxx11-warning {{unsequenced modification and access to 'a'}}
105                            // cxx17-warning@-1 {{unsequenced modification and access to 'a'}}
106 
107   (++a, xs[6] ? ++a : 0) + a; // cxx11-warning {{unsequenced modification and access to 'a'}}
108                               // cxx17-warning@-1 {{unsequenced modification and access to 'a'}}
109 
110   // Here, the read of the fourth 'a' might happen before or after the write to
111   // the second 'a'.
112   a += (a++, a) + a; // cxx11-warning {{unsequenced modification and access to 'a'}}
113                      // cxx17-warning@-1 {{unsequenced modification and access to 'a'}}
114 
115   int *p = xs;
116   a = *(a++, p); // ok
117   a = a++ && a; // ok
118   p[(long long unsigned)(p = 0)]; // cxx11-warning {{unsequenced modification and access to 'p'}}
119 
120   A *q = &agg1;
121   (q = &agg2)->y = q->x; // cxx11-warning {{unsequenced modification and access to 'q'}}
122                          // TODO cxx17-warning@-1 {{unsequenced modification and access to 'q'}}
123 
124   // This has undefined behavior if a == 0; otherwise, the side-effect of the
125   // increment is sequenced before the value computation of 'f(a, a)', which is
126   // sequenced before the value computation of the '&&', which is sequenced
127   // before the assignment. We treat the sequencing in '&&' as being
128   // unconditional.
129   a = a++ && f(a, a);
130 
131   // This has undefined behavior if a != 0.
132   (a && a++) + a; // cxx11-warning {{unsequenced modification and access to 'a'}}
133                   // cxx17-warning@-1 {{unsequenced modification and access to 'a'}}
134 
135   // FIXME: Don't warn here.
136   (xs[7] && ++a) * (!xs[7] && ++a); // cxx11-warning {{multiple unsequenced modifications to 'a'}}
137                                     // cxx17-warning@-1 {{multiple unsequenced modifications to 'a'}}
138 
139   xs[0] = (a = 1, a); // ok
140   (a -= 128) &= 128; // ok
141   ++a += 1; // ok
142 
143   xs[8] ? ++a + a++ : 0; // cxx11-warning {{multiple unsequenced modifications to 'a'}}
144                          // cxx17-warning@-1 {{multiple unsequenced modifications to 'a'}}
145   xs[8] ? 0 : ++a + a++; // cxx11-warning {{multiple unsequenced modifications to 'a'}}
146                          // cxx17-warning@-1 {{multiple unsequenced modifications to 'a'}}
147   xs[8] ? ++a : a++; // no-warning
148   xs[8] ? a+=1 : a+= 2; // no-warning
149   (xs[8] ? a+=1 : a+= 2) = a; // cxx11-warning {{unsequenced modification and access to 'a'}}
150                               // TODO cxx17-warning@-1 {{unsequenced modification and access to 'a'}}
151   (xs[8] ? a+=1 : a) = a; // cxx11-warning {{unsequenced modification and access to 'a'}}
152                           // TODO cxx17-warning@-1 {{unsequenced modification and access to 'a'}}
153   (xs[8] ? a : a+= 2) = a; // cxx11-warning {{unsequenced modification and access to 'a'}}
154                            // TODO cxx17-warning@-1 {{unsequenced modification and access to 'a'}}
155   a = (xs[8] ? a+=1 : a+= 2); // no-warning
156   a += (xs[8] ? a+=1 : a+= 2); // cxx11-warning {{unsequenced modification and access to 'a'}}
157                                // TODO cxx17-warning@-1 {{unsequenced modification and access to 'a'}}
158 
159   (false ? a+=1 : a) = a; // no-warning
160   (true ? a+=1 : a) = a; // cxx11-warning {{unsequenced modification and access to 'a'}}
161                          // TODO cxx17-warning@-1 {{unsequenced modification and access to 'a'}}
162   (false ? a : a+=2) = a; // cxx11-warning {{unsequenced modification and access to 'a'}}
163                           // TODO cxx17-warning@-1 {{unsequenced modification and access to 'a'}}
164   (true ? a : a+=2) = a; // no-warning
165 
166   xs[8] && (++a + a++); // cxx11-warning {{multiple unsequenced modifications to 'a'}}
167                         // cxx17-warning@-1 {{multiple unsequenced modifications to 'a'}}
168   xs[8] || (++a + a++); // cxx11-warning {{multiple unsequenced modifications to 'a'}}
169                         // cxx17-warning@-1 {{multiple unsequenced modifications to 'a'}}
170 
171   ((a++, false) || (a++, false)); // no-warning PR39779
172   ((a++, true) && (a++, true)); // no-warning PR39779
173 
174   int i,j;
175   (i = g1(), false) || (j = g2(i)); // no-warning PR22197
176   (i = g1(), true) && (j = g2(i)); // no-warning PR22197
177 
178   (a++, false) || (a++, false) || (a++, false) || (a++, false); // no-warning
179   (a++, true) || (a++, true) || (a++, true) || (a++, true); // no-warning
180   a = ((a++, false) || (a++, false) || (a++, false) || (a++, false)); // no-warning
181   a = ((a++, true) && (a++, true) && (a++, true) && (a++, true)); // no-warning
182   a = ((a++, false) || (a++, false) || (a++, false) || a++); // cxx11-warning {{multiple unsequenced modifications to 'a'}}
183                                                              // TODO cxx17-warning@-1 {{multiple unsequenced modifications to 'a'}}
184   a = ((a++, true) && (a++, true) && (a++, true) && a++); // cxx11-warning {{multiple unsequenced modifications to 'a'}}
185                                                           // TODO cxx17-warning@-1 {{multiple unsequenced modifications to 'a'}}
186   a = ((a++, false) || (a++, false) || (a++, false) || (a + a, false)); // no-warning
187   a = ((a++, true) && (a++, true) && (a++, true) && (a + a, true)); // no-warning
188 
189   a = (false && a++); // no-warning
190   a = (true && a++); // cxx11-warning {{multiple unsequenced modifications to 'a'}}
191                      // TODO cxx17-warning@-1 {{multiple unsequenced modifications to 'a'}}
192   a = (true && ++a); // no-warning
193   a = (true || a++); // no-warning
194   a = (false || a++); // cxx11-warning {{multiple unsequenced modifications to 'a'}}
195                       // TODO cxx17-warning@-1 {{multiple unsequenced modifications to 'a'}}
196   a = (false || ++a); // no-warning
197 
198   (a++) | (a++); // cxx11-warning {{multiple unsequenced modifications to 'a'}}
199                  // cxx17-warning@-1 {{multiple unsequenced modifications to 'a'}}
200   (a++) & (a++); // cxx11-warning {{multiple unsequenced modifications to 'a'}}
201                  // cxx17-warning@-1 {{multiple unsequenced modifications to 'a'}}
202   (a++) ^ (a++); // cxx11-warning {{multiple unsequenced modifications to 'a'}}
203                  // cxx17-warning@-1 {{multiple unsequenced modifications to 'a'}}
204 
205   (__builtin_classify_type(++a) ? 1 : 0) + ++a; // ok
206   (__builtin_constant_p(++a) ? 1 : 0) + ++a; // ok
207   (__builtin_object_size(&(++a, a), 0) ? 1 : 0) + ++a; // ok
208   (__builtin_expect(++a, 0) ? 1 : 0) + ++a; // cxx11-warning {{multiple unsequenced modifications to 'a'}}
209                                             // cxx17-warning@-1 {{multiple unsequenced modifications to 'a'}}
210 }
211 
212 namespace members {
213 
214 struct S1 {
215   unsigned bf1 : 2;
216   unsigned bf2 : 2;
217   unsigned a;
218   unsigned b;
219   static unsigned x;
220   void member_f(S1 &s);
221 };
222 
223 void S1::member_f(S1 &s) {
224   ++a + ++a; // cxx11-warning {{multiple unsequenced modifications to 'a'}}
225              // cxx17-warning@-1 {{multiple unsequenced modifications to 'a'}}
226   a + ++a; // cxx11-warning {{unsequenced modification and access to 'a'}}
227            // cxx17-warning@-1 {{unsequenced modification and access to 'a'}}
228   ++a + ++b; // no-warning
229   a + ++b; // no-warning
230 
231   // TODO: Warn here.
232   ++s.a + ++s.a; // no-warning TODO {{multiple unsequenced modifications to}}
233   s.a + ++s.a; // no-warning TODO {{unsequenced modification and access to}}
234   ++s.a + ++s.b; // no-warning
235   s.a + ++s.b; // no-warning
236 
237   ++a + ++s.a; // no-warning
238   a + ++s.a; // no-warning
239   ++a + ++s.b; // no-warning
240   a + ++s.b; // no-warning
241 
242   // TODO Warn here for bit-fields in the same memory location.
243   ++bf1 + ++bf1; // cxx11-warning {{multiple unsequenced modifications to 'bf1'}}
244                  // cxx17-warning@-1 {{multiple unsequenced modifications to 'bf1'}}
245   bf1 + ++bf1; // cxx11-warning {{unsequenced modification and access to 'bf1'}}
246                // cxx17-warning@-1 {{unsequenced modification and access to 'bf1'}}
247   ++bf1 + ++bf2; // no-warning TODO {{multiple unsequenced modifications to}}
248   bf1 + ++bf2; // no-warning TODO {{unsequenced modification and access to}}
249 
250   // TODO Warn here for bit-fields in the same memory location.
251   ++s.bf1 + ++s.bf1; // no-warning TODO {{multiple unsequenced modifications to}}
252   s.bf1 + ++s.bf1; // no-warning TODO {{unsequenced modification and access to}}
253   ++s.bf1 + ++s.bf2; // no-warning TODO {{multiple unsequenced modifications to}}
254   s.bf1 + ++s.bf2; // no-warning TODO {{unsequenced modification and access to}}
255 
256   ++bf1 + ++s.bf1; // no-warning
257   bf1 + ++s.bf1; // no-warning
258   ++bf1 + ++s.bf2; // no-warning
259   bf1 + ++s.bf2; // no-warning
260 
261   struct Der : S1 {};
262   Der d;
263   Der &d_ref = d;
264   S1 &s1_ref = d_ref;
265 
266   ++s1_ref.a + ++d_ref.a; // no-warning TODO {{multiple unsequenced modifications to member 'a' of 'd'}}
267   ++s1_ref.a + d_ref.a; // no-warning TODO {{unsequenced modification and access to member 'a' of 'd'}}
268   ++s1_ref.a + ++d_ref.b; // no-warning
269   ++s1_ref.a + d_ref.b; // no-warning
270 
271   ++x + ++x; // cxx11-warning {{multiple unsequenced modifications to 'x'}}
272              // cxx17-warning@-1 {{multiple unsequenced modifications to 'x'}}
273   ++x + x; // cxx11-warning {{unsequenced modification and access to 'x'}}
274            // cxx17-warning@-1 {{unsequenced modification and access to 'x'}}
275   ++s.x + x; // no-warning TODO {{unsequenced modification and access to static member 'x' of 'S1'}}
276   ++this->x + x; // cxx11-warning {{unsequenced modification and access to 'x'}}
277                  // cxx17-warning@-1 {{unsequenced modification and access to 'x'}}
278   ++d_ref.x + ++S1::x; // no-warning TODO {{unsequenced modification and access to static member 'x' of 'S1'}}
279 }
280 
281 struct S2 {
282   union { unsigned x, y; };
283   void f2();
284 };
285 
286 void S2::f2() {
287   ++x + ++x; // no-warning TODO {{multiple unsequenced modifications to}}
288   x + ++x; // no-warning TODO {{unsequenced modification and access to}}
289   ++x + ++y; // no-warning
290   x + ++y; // no-warning
291 }
292 
293 void f2(S2 &s) {
294   ++s.x + ++s.x; // no-warning TODO {{multiple unsequenced modifications to}}
295   s.x + ++s.x; // no-warning TODO {{unsequenced modification and access to}}
296   ++s.x + ++s.y; // no-warning
297   s.x + ++s.y; // no-warning
298 }
299 
300 struct S3 {
301   union {
302     union {
303       unsigned x;
304     };
305   };
306   unsigned y;
307   void f3();
308 };
309 
310 void S3::f3() {
311   ++x + ++x; // no-warning TODO {{multiple unsequenced modifications to}}
312   x + ++x; // no-warning TODO {{unsequenced modification and access to}}
313   ++x + ++y; // no-warning
314   x + ++y; // no-warning
315 }
316 
317 void f3(S3 &s) {
318   ++s.x + ++s.x; // no-warning TODO {{multiple unsequenced modifications to}}
319   s.x + ++s.x; // no-warning TODO {{unsequenced modification and access to}}
320   ++s.x + ++s.y; // no-warning
321   s.x + ++s.y; // no-warning
322 }
323 
324 struct S4 : S3 {
325   unsigned y;
326   void f4();
327 };
328 
329 void S4::f4() {
330   ++x + ++x; // no-warning TODO {{multiple unsequenced modifications to}}
331   x + ++x; // no-warning TODO {{unsequenced modification and access to}}
332   ++x + ++y; // no-warning
333   x + ++y; // no-warning
334   ++S3::y + ++y; // no-warning
335   S3::y + ++y; // no-warning
336 }
337 
338 void f4(S4 &s) {
339   ++s.x + ++s.x; // no-warning TODO {{multiple unsequenced modifications to}}
340   s.x + ++s.x; // no-warning TODO {{unsequenced modification and access to}}
341   ++s.x + ++s.y; // no-warning
342   s.x + ++s.y; // no-warning
343   ++s.S3::y + ++s.y; // no-warning
344   s.S3::y + ++s.y; // no-warning
345 }
346 
347 static union {
348   unsigned Ux;
349   unsigned Uy;
350 };
351 
352 void f5() {
353   ++Ux + ++Ux; // no-warning TODO {{multiple unsequenced modifications to}}
354   Ux + ++Ux; // no-warning TODO {{unsequenced modification and access to}}
355   ++Ux + ++Uy; // no-warning
356   Ux + ++Uy; // no-warning
357 }
358 
359 void f6() {
360   struct S { unsigned x, y; } s;
361   ++s.x + ++s.x; // no-warning TODO {{multiple unsequenced modifications to}}
362   s.x + ++s.x; // no-warning TODO {{unsequenced modification and access to}}
363   ++s.x + ++s.y; // no-warning
364   s.x + ++s.y; // no-warning
365 
366   struct { unsigned x, y; } t;
367   ++t.x + ++t.x; // no-warning TODO {{multiple unsequenced modifications to}}
368   t.x + ++t.x; // no-warning TODO {{unsequenced modification and access to}}
369   ++t.x + ++t.y; // no-warning
370   t.x + ++t.y; // no-warning
371 }
372 
373 } // namespace members
374 
375 namespace references {
376 void reference_f() {
377   // TODO: Check that we can see through references.
378   // For now this is completely unhandled.
379   int a;
380   int xs[10];
381   int &b = a;
382   int &c = b;
383   int &ra1 = c;
384   int &ra2 = b;
385   int other;
386 
387   ++ra1 + ++ra2; // no-warning TODO {{multiple unsequenced modifications to}}
388   ra1 + ++ra2; // no-warning TODO {{unsequenced modification and access to}}
389   ++ra1 + ++other; // no-warning
390   ra1 + ++other; // no-warning
391 
392   // Make sure we handle reference cycles.
393   int &ref_cycle = ref_cycle;
394   ++ref_cycle + ++ref_cycle; // cxx11-warning {{multiple unsequenced modifications to 'ref_cycle'}}
395                              // cxx17-warning@-1 {{multiple unsequenced modifications to 'ref_cycle'}}
396   ref_cycle + ++ref_cycle; // cxx11-warning {{unsequenced modification and access to 'ref_cycle'}}
397                            // cxx17-warning@-1 {{unsequenced modification and access to 'ref_cycle'}}
398 }
399 } // namespace references
400 
401 namespace std {
402   using size_t = decltype(sizeof(0));
403   template<typename> struct tuple_size;
404   template<size_t, typename> struct tuple_element { using type = int; };
405 }
406 namespace bindings {
407 
408   struct A { int x, y; };
409   typedef int B[2];
410   struct C { template<int> int get(); };
411   struct D : A {};
412 
413 } // namespace bindings
414 template<> struct std::tuple_size<bindings::C> { enum { value = 2 }; };
415 namespace bindings {
416 void testa() {
417   A a;
418   {
419     auto [x, y] = a;
420     ++x + ++x; // cxx11-warning {{multiple unsequenced modifications to 'x'}}
421                // cxx17-warning@-1 {{multiple unsequenced modifications to 'x'}}
422     ++x + x; // cxx11-warning {{unsequenced modification and access to 'x'}}
423              // cxx17-warning@-1 {{unsequenced modification and access to 'x'}}
424     ++x + ++y; // no-warning
425     ++x + y; // no-warning
426     ++x + ++a.x; // no-warning
427     ++x + a.x; // no-warning
428   }
429   {
430     auto &[x, y] = a;
431     ++x + ++x; // cxx11-warning {{multiple unsequenced modifications to 'x'}}
432                // cxx17-warning@-1 {{multiple unsequenced modifications to 'x'}}
433     ++x + x; // cxx11-warning {{unsequenced modification and access to 'x'}}
434              // cxx17-warning@-1 {{unsequenced modification and access to 'x'}}
435     ++x + ++y; // no-warning
436     ++x + y; // no-warning
437     ++x + ++a.x; // no-warning TODO
438     ++x + a.x; // no-warning TODO
439   }
440 }
441 void testb() {
442   B b;
443   {
444     auto [x, y] = b;
445     ++x + ++x; // cxx11-warning {{multiple unsequenced modifications to 'x'}}
446                // cxx17-warning@-1 {{multiple unsequenced modifications to 'x'}}
447     ++x + x; // cxx11-warning {{unsequenced modification and access to 'x'}}
448              // cxx17-warning@-1 {{unsequenced modification and access to 'x'}}
449     ++x + ++y; // no-warning
450     ++x + y; // no-warning
451     ++x + ++b[0]; // no-warning
452     ++x + b[0]; // no-warning
453   }
454   {
455     auto &[x, y] = b;
456     ++x + ++x; // cxx11-warning {{multiple unsequenced modifications to 'x'}}
457                // cxx17-warning@-1 {{multiple unsequenced modifications to 'x'}}
458     ++x + x; // cxx11-warning {{unsequenced modification and access to 'x'}}
459              // cxx17-warning@-1 {{unsequenced modification and access to 'x'}}
460     ++x + ++y; // no-warning
461     ++x + y; // no-warning
462     ++x + ++b[0]; // no-warning TODO
463     ++x + b[0]; // no-warning TODO
464   }
465 }
466 void testc() {
467   C c;
468   {
469     auto [x, y] = c;
470     ++x + ++x; // cxx11-warning {{multiple unsequenced modifications to 'x'}}
471                // cxx17-warning@-1 {{multiple unsequenced modifications to 'x'}}
472     ++x + x; // cxx11-warning {{unsequenced modification and access to 'x'}}
473              // cxx17-warning@-1 {{unsequenced modification and access to 'x'}}
474     ++x + ++y; // no-warning
475     ++x + y; // no-warning
476   }
477   {
478     auto &[x, y] = c;
479     ++x + ++x; // cxx11-warning {{multiple unsequenced modifications to 'x'}}
480                // cxx17-warning@-1 {{multiple unsequenced modifications to 'x'}}
481     ++x + x; // cxx11-warning {{unsequenced modification and access to 'x'}}
482              // cxx17-warning@-1 {{unsequenced modification and access to 'x'}}
483     ++x + ++y; // no-warning
484     ++x + y; // no-warning
485   }
486 }
487 void testd() {
488   D d;
489   {
490     auto [x, y] = d;
491     ++x + ++x; // cxx11-warning {{multiple unsequenced modifications to 'x'}}
492                // cxx17-warning@-1 {{multiple unsequenced modifications to 'x'}}
493     ++x + x; // cxx11-warning {{unsequenced modification and access to 'x'}}
494              // cxx17-warning@-1 {{unsequenced modification and access to 'x'}}
495     ++x + ++y; // no-warning
496     ++x + y; // no-warning
497     ++x + ++d.x; // no-warning
498     ++x + d.x; // no-warning
499   }
500   {
501     auto &[x, y] = d;
502     ++x + ++x; // cxx11-warning {{multiple unsequenced modifications to 'x'}}
503                // cxx17-warning@-1 {{multiple unsequenced modifications to 'x'}}
504     ++x + x; // cxx11-warning {{unsequenced modification and access to 'x'}}
505              // cxx17-warning@-1 {{unsequenced modification and access to 'x'}}
506     ++x + ++y; // no-warning
507     ++x + y; // no-warning
508     ++x + ++d.x; // no-warning TODO
509     ++x + d.x; // no-warning TODO
510   }
511 }
512 } // namespace bindings
513 
514 namespace templates {
515 
516 template <typename T>
517 struct Bar {
518   T get() { return 0; }
519 };
520 
521 template <typename X>
522 struct Foo {
523   int Run();
524   Bar<int> bar;
525 };
526 
527 enum E {e1, e2};
528 bool operator&&(E, E);
529 
530 void foo(int, int);
531 
532 template <typename X>
533 int Foo<X>::Run() {
534   char num = 0;
535 
536   // Before instantiation, Clang may consider the builtin operator here as
537   // unresolved function calls, and treat the arguments as unordered when
538   // the builtin operator evaluatation is well-ordered.  Waiting until
539   // instantiation to check these expressions will prevent false positives.
540   if ((num = bar.get()) < 5 && num < 10) { }
541   if ((num = bar.get()) < 5 || num < 10) { }
542   if (static_cast<E>((num = bar.get()) < 5) || static_cast<E>(num < 10)) { }
543 
544   if (static_cast<E>((num = bar.get()) < 5) && static_cast<E>(num < 10)) { }
545   // cxx11-warning@-1 {{unsequenced modification and access to 'num'}}
546   // cxx17-warning@-2 {{unsequenced modification and access to 'num'}}
547 
548   foo(num++, num++);
549   // cxx11-warning@-1 {{multiple unsequenced modifications to 'num'}}
550   // cxx17-warning@-2 {{multiple unsequenced modifications to 'num'}}
551   return 1;
552 }
553 
554 int x = Foo<int>().Run();
555 // cxx11-note@-1 {{in instantiation of member function 'templates::Foo<int>::Run'}}
556 // cxx17-note@-2 {{in instantiation of member function 'templates::Foo<int>::Run'}}
557 
558 
559 template <typename T>
560 int Run2() {
561   T t = static_cast<T>(0);
562   return (t = static_cast<T>(1)) && t;
563   // cxx11-warning@-1 {{unsequenced modification and access to 't'}}
564   // cxx17-warning@-2 {{unsequenced modification and access to 't'}}
565 }
566 
567 int y = Run2<bool>();
568 int z = Run2<E>();
569 // cxx11-note@-1{{in instantiation of function template specialization 'templates::Run2<templates::E>' requested here}}
570 // cxx17-note@-2{{in instantiation of function template specialization 'templates::Run2<templates::E>' requested here}}
571 
572 template <typename T> int var = sizeof(T);
573 void test_var() {
574   var<int>++ + var<int>++; // cxx11-warning {{multiple unsequenced modifications to 'var<int>'}}
575                            // cxx17-warning@-1 {{multiple unsequenced modifications to 'var<int>'}}
576   var<int>++ + var<int>; // cxx11-warning {{unsequenced modification and access to 'var<int>'}}
577                          // cxx17-warning@-1 {{unsequenced modification and access to 'var<int>'}}
578   int &r = var<int>;
579   r++ + var<int>++; // no-warning TODO {{multiple unsequenced modifications to 'var<int>'}}
580   r++ + var<long>++; // no-warning
581 }
582 
583 } // namespace templates
584