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