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