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