1 // RUN: %clang_cc1 -std=c++1y -verify %s -fcxx-exceptions -triple=x86_64-linux-gnu 2 3 struct S { 4 // dummy ctor to make this a literal type 5 constexpr S(int); 6 7 S(); 8 9 int arr[10]; 10 11 constexpr int &get(int n) { return arr[n]; } 12 constexpr const int &get(int n) const { return arr[n]; } 13 }; 14 15 S s = S(); 16 const S &sr = s; 17 static_assert(&s.get(4) - &sr.get(2) == 2, ""); 18 19 // Compound-statements can be used in constexpr functions. 20 constexpr int e() {{{{}} return 5; }} 21 static_assert(e() == 5, ""); 22 23 // Types can be defined in constexpr functions. 24 constexpr int f() { 25 enum E { e1, e2, e3 }; 26 27 struct S { 28 constexpr S(E e) : e(e) {} 29 constexpr int get() { return e; } 30 E e; 31 }; 32 33 return S(e2).get(); 34 } 35 static_assert(f() == 1, ""); 36 37 // Variables can be declared in constexpr functions. 38 constexpr int g(int k) { 39 const int n = 9; 40 int k2 = k * k; 41 int k3 = k2 * k; 42 return 3 * k3 + 5 * k2 + n * k - 20; 43 } 44 static_assert(g(2) == 42, ""); 45 constexpr int h(int n) { 46 static const int m = n; // expected-error {{static variable not permitted in a constexpr function}} 47 return m; 48 } 49 constexpr int i(int n) { 50 thread_local const int m = n; // expected-error {{thread_local variable not permitted in a constexpr function}} 51 return m; 52 } 53 54 // if-statements can be used in constexpr functions. 55 constexpr int j(int k) { 56 if (k == 5) 57 return 1; 58 if (k == 1) 59 return 5; 60 else { 61 if (int n = 2 * k - 4) { 62 return n + 1; 63 return 2; 64 } 65 } 66 } // expected-note 2{{control reached end of constexpr function}} 67 static_assert(j(0) == -3, ""); 68 static_assert(j(1) == 5, ""); 69 static_assert(j(2), ""); // expected-error {{constant expression}} expected-note {{in call to 'j(2)'}} 70 static_assert(j(3) == 3, ""); 71 static_assert(j(4) == 5, ""); 72 static_assert(j(5) == 1, ""); 73 74 // There can be 0 return-statements. 75 constexpr void k() { 76 } 77 78 // If the return type is not 'void', no return statements => never a constant 79 // expression, so still diagnose that case. 80 [[noreturn]] constexpr int fn() { // expected-error {{no return statement in constexpr function}} 81 fn(); 82 } 83 84 // We evaluate the body of a constexpr constructor, to check for side-effects. 85 struct U { 86 constexpr U(int n) { 87 if (j(n)) {} // expected-note {{in call to 'j(2)'}} 88 } 89 }; 90 constexpr U u1{1}; 91 constexpr U u2{2}; // expected-error {{constant expression}} expected-note {{in call to 'U(2)'}} 92 93 // We allow expression-statements. 94 constexpr int l(bool b) { 95 if (b) 96 throw "invalid value for b!"; // expected-note {{subexpression not valid}} 97 return 5; 98 } 99 static_assert(l(false) == 5, ""); 100 static_assert(l(true), ""); // expected-error {{constant expression}} expected-note {{in call to 'l(true)'}} 101 102 // Potential constant expression checking is still applied where possible. 103 constexpr int htonl(int x) { // expected-error {{never produces a constant expression}} 104 typedef unsigned char uchar; 105 uchar arr[4] = { uchar(x >> 24), uchar(x >> 16), uchar(x >> 8), uchar(x) }; 106 return *reinterpret_cast<int*>(arr); // expected-note {{reinterpret_cast is not allowed in a constant expression}} 107 } 108 109 constexpr int maybe_htonl(bool isBigEndian, int x) { 110 if (isBigEndian) 111 return x; 112 113 typedef unsigned char uchar; 114 uchar arr[4] = { uchar(x >> 24), uchar(x >> 16), uchar(x >> 8), uchar(x) }; 115 return *reinterpret_cast<int*>(arr); // expected-note {{reinterpret_cast is not allowed in a constant expression}} 116 } 117 118 constexpr int swapped = maybe_htonl(false, 123); // expected-error {{constant expression}} expected-note {{in call}} 119 120 namespace NS { 121 constexpr int n = 0; 122 } 123 constexpr int namespace_alias() { 124 namespace N = NS; 125 return N::n; 126 } 127 128 namespace assign { 129 constexpr int a = 0; 130 const int b = 0; 131 int c = 0; // expected-note {{here}} 132 133 constexpr void set(const int &a, int b) { 134 const_cast<int&>(a) = b; // expected-note 3{{constant expression cannot modify an object that is visible outside that expression}} 135 } 136 constexpr int wrap(int a, int b) { 137 set(a, b); 138 return a; 139 } 140 141 static_assert((set(a, 1), a) == 1, ""); // expected-error {{constant expression}} expected-note {{in call to 'set(a, 1)'}} 142 static_assert((set(b, 1), b) == 1, ""); // expected-error {{constant expression}} expected-note {{in call to 'set(b, 1)'}} 143 static_assert((set(c, 1), c) == 1, ""); // expected-error {{constant expression}} expected-note {{in call to 'set(c, 1)'}} 144 145 static_assert(wrap(a, 1) == 1, ""); 146 static_assert(wrap(b, 1) == 1, ""); 147 static_assert(wrap(c, 1) == 1, ""); // expected-error {{constant expression}} expected-note {{read of non-const variable 'c'}} 148 } 149 150 namespace string_assign { 151 template<typename T> 152 constexpr void swap(T &a, T &b) { 153 T tmp = a; 154 a = b; 155 b = tmp; 156 } 157 template<typename Iterator> 158 constexpr void reverse(Iterator begin, Iterator end) { 159 while (begin != end && begin != --end) 160 swap(*begin++, *end); 161 } 162 template<typename Iterator1, typename Iterator2> 163 constexpr bool equal(Iterator1 a, Iterator1 ae, Iterator2 b, Iterator2 be) { 164 while (a != ae && b != be) 165 if (*a++ != *b++) 166 return false; 167 return a == ae && b == be; 168 } 169 constexpr bool test1(int n) { 170 char stuff[100] = "foobarfoo"; 171 const char stuff2[100] = "oofraboof"; 172 reverse(stuff, stuff + n); // expected-note {{cannot refer to element 101 of array of 100 elements}} 173 return equal(stuff, stuff + n, stuff2, stuff2 + n); 174 } 175 static_assert(!test1(1), ""); 176 static_assert(test1(3), ""); 177 static_assert(!test1(6), ""); 178 static_assert(test1(9), ""); 179 static_assert(!test1(100), ""); 180 static_assert(!test1(101), ""); // expected-error {{constant expression}} expected-note {{in call to 'test1(101)'}} 181 182 // FIXME: We should be able to reject this before it's called 183 constexpr void f() { 184 char foo[10] = { "z" }; // expected-note {{here}} 185 foo[10] = 'x'; // expected-warning {{past the end}} expected-note {{assignment to dereferenced one-past-the-end pointer}} 186 } 187 constexpr int k = (f(), 0); // expected-error {{constant expression}} expected-note {{in call}} 188 } 189 190 namespace array_resize { 191 constexpr int do_stuff(int k1, int k2) { 192 int arr[1234] = { 1, 2, 3, 4 }; 193 arr[k1] = 5; // expected-note {{past-the-end}} expected-note {{cannot refer to element 1235}} expected-note {{cannot refer to element -1}} 194 return arr[k2]; 195 } 196 static_assert(do_stuff(1, 2) == 3, ""); 197 static_assert(do_stuff(0, 0) == 5, ""); 198 static_assert(do_stuff(1233, 1233) == 5, ""); 199 static_assert(do_stuff(1233, 0) == 1, ""); 200 static_assert(do_stuff(1234, 0) == 1, ""); // expected-error {{constant expression}} expected-note {{in call}} 201 static_assert(do_stuff(1235, 0) == 1, ""); // expected-error {{constant expression}} expected-note {{in call}} 202 static_assert(do_stuff(-1, 0) == 1, ""); // expected-error {{constant expression}} expected-note {{in call}} 203 } 204 205 namespace potential_const_expr { 206 constexpr void set(int &n) { n = 1; } 207 constexpr int div_zero_1() { int z = 0; set(z); return 100 / z; } // no error 208 constexpr int div_zero_2() { // expected-error {{never produces a constant expression}} 209 int z = 0; 210 return 100 / (set(z), 0); // expected-note {{division by zero}} 211 } 212 int n; // expected-note {{declared here}} 213 constexpr int ref() { // expected-error {{never produces a constant expression}} 214 int &r = n; 215 return r; // expected-note {{read of non-const variable 'n'}} 216 } 217 } 218 219 namespace subobject { 220 union A { constexpr A() : y(5) {} int x, y; }; 221 struct B { A a; }; 222 struct C : B {}; 223 union D { constexpr D() : c() {} constexpr D(int n) : n(n) {} C c; int n; }; 224 constexpr void f(D &d) { 225 d.c.a.y = 3; 226 // expected-note@-1 {{cannot modify an object that is visible outside}} 227 // expected-note@-2 {{assignment to member 'c' of union with active member 'n'}} 228 } 229 constexpr bool check(D &d) { return d.c.a.y == 3; } 230 231 constexpr bool g() { D d; f(d); return d.c.a.y == 3; } 232 static_assert(g(), ""); 233 234 D d; 235 constexpr bool h() { f(d); return check(d); } // expected-note {{in call}} 236 static_assert(h(), ""); // expected-error {{constant expression}} expected-note {{in call}} 237 238 constexpr bool i() { D d(0); f(d); return check(d); } // expected-note {{in call}} 239 static_assert(i(), ""); // expected-error {{constant expression}} expected-note {{in call}} 240 241 constexpr bool j() { D d; d.c.a.x = 3; return check(d); } // expected-note {{assignment to member 'x' of union with active member 'y'}} 242 static_assert(j(), ""); // expected-error {{constant expression}} expected-note {{in call}} 243 } 244 245 namespace lifetime { 246 constexpr int &&id(int &&n) { return static_cast<int&&>(n); } 247 constexpr int &&dead() { return id(0); } // expected-note {{temporary created here}} 248 constexpr int bad() { int &&n = dead(); n = 1; return n; } // expected-note {{assignment to temporary whose lifetime has ended}} 249 static_assert(bad(), ""); // expected-error {{constant expression}} expected-note {{in call}} 250 } 251 252 namespace const_modify { 253 constexpr int modify(int &n) { return n = 1; } // expected-note 2 {{modification of object of const-qualified type 'const int'}} 254 constexpr int test1() { int k = 0; return modify(k); } 255 constexpr int test2() { const int k = 0; return modify(const_cast<int&>(k)); } // expected-note 2 {{in call}} 256 static_assert(test1() == 1, ""); 257 static_assert(test2() == 1, ""); // expected-error {{constant expression}} expected-note {{in call}} 258 constexpr int i = test2(); // expected-error {{constant expression}} expected-note {{in call}} 259 } 260 261 namespace null { 262 constexpr int test(int *p) { 263 return *p = 123; // expected-note {{assignment to dereferenced null pointer}} 264 } 265 static_assert(test(0), ""); // expected-error {{constant expression}} expected-note {{in call}} 266 } 267 268 namespace incdec { 269 template<typename T> constexpr T &ref(T &&r) { return r; } 270 template<typename T> constexpr T postinc(T &&r) { return (r++, r); } 271 template<typename T> constexpr T postdec(T &&r) { return (r--, r); } 272 273 static_assert(++ref(0) == 1, ""); 274 static_assert(ref(0)++ == 0, ""); 275 static_assert(postinc(0) == 1, ""); 276 static_assert(--ref(0) == -1, ""); 277 static_assert(ref(0)-- == 0, ""); 278 static_assert(postdec(0) == -1, ""); 279 280 constexpr int overflow_int_inc_1 = ref(0x7fffffff)++; // expected-error {{constant}} expected-note {{2147483648}} 281 constexpr int overflow_int_inc_1_ok = ref(0x7ffffffe)++; 282 constexpr int overflow_int_inc_2 = ++ref(0x7fffffff); // expected-error {{constant}} expected-note {{2147483648}} 283 constexpr int overflow_int_inc_2_ok = ++ref(0x7ffffffe); 284 285 // inc/dec on short can't overflow because we promote to int first 286 static_assert(++ref<short>(0x7fff) == (int)0xffff8000u, ""); 287 static_assert(--ref<short>(0x8000) == 0x7fff, ""); 288 289 // inc on bool sets to true 290 static_assert(++ref(false), ""); // expected-warning {{deprecated}} 291 static_assert(++ref(true), ""); // expected-warning {{deprecated}} 292 293 int arr[10]; 294 static_assert(++ref(&arr[0]) == &arr[1], ""); 295 static_assert(++ref(&arr[9]) == &arr[10], ""); 296 static_assert(++ref(&arr[10]) == &arr[11], ""); // expected-error {{constant}} expected-note {{cannot refer to element 11}} 297 static_assert(ref(&arr[0])++ == &arr[0], ""); 298 static_assert(ref(&arr[10])++ == &arr[10], ""); // expected-error {{constant}} expected-note {{cannot refer to element 11}} 299 static_assert(postinc(&arr[0]) == &arr[1], ""); 300 static_assert(--ref(&arr[10]) == &arr[9], ""); 301 static_assert(--ref(&arr[1]) == &arr[0], ""); 302 static_assert(--ref(&arr[0]) != &arr[0], ""); // expected-error {{constant}} expected-note {{cannot refer to element -1}} 303 static_assert(ref(&arr[1])-- == &arr[1], ""); 304 static_assert(ref(&arr[0])-- == &arr[0], ""); // expected-error {{constant}} expected-note {{cannot refer to element -1}} 305 static_assert(postdec(&arr[1]) == &arr[0], ""); 306 307 int x; 308 static_assert(++ref(&x) == &x + 1, ""); 309 310 static_assert(++ref(0.0) == 1.0, ""); 311 static_assert(ref(0.0)++ == 0.0, ""); 312 static_assert(postinc(0.0) == 1.0, ""); 313 static_assert(--ref(0.0) == -1.0, ""); 314 static_assert(ref(0.0)-- == 0.0, ""); 315 static_assert(postdec(0.0) == -1.0, ""); 316 317 static_assert(++ref(1e100) == 1e100, ""); 318 static_assert(--ref(1e100) == 1e100, ""); 319 320 union U { 321 int a, b; 322 }; 323 constexpr int f(U u) { 324 return ++u.b; // expected-note {{increment of member 'b' of union with active member 'a'}} 325 } 326 constexpr int wrong_member = f({0}); // expected-error {{constant}} expected-note {{in call to 'f({.a = 0})'}} 327 constexpr int vol = --ref<volatile int>(0); // expected-error {{constant}} expected-note {{decrement of volatile-qualified}} 328 329 constexpr int incr(int k) { 330 int x = k; 331 if (x++ == 100) 332 return x; 333 return incr(x); 334 } 335 static_assert(incr(0) == 101, ""); 336 } 337 338 namespace compound_assign { 339 constexpr bool test_int() { 340 int a = 3; 341 a += 6; 342 if (a != 9) return false; 343 a -= 2; 344 if (a != 7) return false; 345 a *= 3; 346 if (a != 21) return false; 347 if (&(a /= 10) != &a) return false; 348 if (a != 2) return false; 349 a <<= 3; 350 if (a != 16) return false; 351 a %= 6; 352 if (a != 4) return false; 353 a >>= 1; 354 if (a != 2) return false; 355 a ^= 10; 356 if (a != 8) return false; 357 a |= 5; 358 if (a != 13) return false; 359 a &= 14; 360 if (a != 12) return false; 361 return true; 362 } 363 static_assert(test_int(), ""); 364 365 constexpr bool test_float() { 366 float f = 123.; 367 f *= 2; 368 if (f != 246.) return false; 369 if ((f -= 0.5) != 245.5) return false; 370 if (f != 245.5) return false; 371 f /= 0.5; 372 if (f != 491.) return false; 373 f += -40; 374 if (f != 451.) return false; 375 return true; 376 } 377 static_assert(test_float(), ""); 378 379 constexpr bool test_ptr() { 380 int arr[123] = {}; 381 int *p = arr; 382 if ((p += 4) != &arr[4]) return false; 383 if (p != &arr[4]) return false; 384 p += -1; 385 if (p != &arr[3]) return false; 386 if ((p -= -10) != &arr[13]) return false; 387 if (p != &arr[13]) return false; 388 p -= 11; 389 if (p != &arr[2]) return false; 390 return true; 391 } 392 static_assert(test_ptr(), ""); 393 394 template<typename T> 395 constexpr bool test_overflow() { 396 T a = 1; 397 while (a != a / 2) 398 a *= 2; // expected-note {{value 2147483648 is outside the range}} expected-note {{ 9223372036854775808 }} expected-note {{floating point arithmetic produces an infinity}} 399 return true; 400 } 401 402 static_assert(test_overflow<int>(), ""); // expected-error {{constant}} expected-note {{call}} 403 static_assert(test_overflow<unsigned>(), ""); // ok, unsigned overflow is defined 404 static_assert(test_overflow<short>(), ""); // ok, short is promoted to int before multiplication 405 static_assert(test_overflow<unsigned short>(), ""); // ok 406 static_assert(test_overflow<unsigned long long>(), ""); // ok 407 static_assert(test_overflow<long long>(), ""); // expected-error {{constant}} expected-note {{call}} 408 static_assert(test_overflow<float>(), ""); // expected-error {{constant}} expected-note {{call}} 409 410 constexpr short test_promotion(short k) { 411 short s = k; 412 s *= s; 413 return s; 414 } 415 static_assert(test_promotion(100) == 10000, ""); 416 static_assert(test_promotion(200) == -25536, ""); 417 static_assert(test_promotion(256) == 0, ""); 418 419 constexpr const char *test_bounds(const char *p, int o) { 420 return p += o; // expected-note {{element 5 of}} expected-note {{element -1 of}} expected-note {{element 1000 of}} 421 } 422 static_assert(test_bounds("foo", 0)[0] == 'f', ""); 423 static_assert(test_bounds("foo", 3)[0] == 0, ""); 424 static_assert(test_bounds("foo", 4)[-3] == 'o', ""); 425 static_assert(test_bounds("foo" + 4, -4)[0] == 'f', ""); 426 static_assert(test_bounds("foo", 5) != 0, ""); // expected-error {{constant}} expected-note {{call}} 427 static_assert(test_bounds("foo", -1) != 0, ""); // expected-error {{constant}} expected-note {{call}} 428 static_assert(test_bounds("foo", 1000) != 0, ""); // expected-error {{constant}} expected-note {{call}} 429 } 430 431 namespace loops { 432 constexpr int fib_loop(int a) { 433 int f_k = 0, f_k_plus_one = 1; 434 for (int k = 1; k != a; ++k) { 435 int f_k_plus_two = f_k + f_k_plus_one; 436 f_k = f_k_plus_one; 437 f_k_plus_one = f_k_plus_two; 438 } 439 return f_k_plus_one; 440 } 441 static_assert(fib_loop(46) == 1836311903, ""); 442 443 constexpr bool breaks_work() { 444 int a = 0; 445 for (int n = 0; n != 100; ++n) { 446 ++a; 447 if (a == 5) continue; 448 if ((a % 5) == 0) break; 449 } 450 451 int b = 0; 452 while (b != 17) { 453 ++b; 454 if (b == 6) continue; 455 if ((b % 6) == 0) break; 456 } 457 458 int c = 0; 459 do { 460 ++c; 461 if (c == 7) continue; 462 if ((c % 7) == 0) break; 463 } while (c != 21); 464 465 return a == 10 && b == 12 & c == 14; 466 } 467 static_assert(breaks_work(), ""); 468 469 void not_constexpr(); 470 constexpr bool no_cont_after_break() { 471 for (;;) { 472 break; 473 not_constexpr(); 474 } 475 while (true) { 476 break; 477 not_constexpr(); 478 } 479 do { 480 break; 481 not_constexpr(); 482 } while (true); 483 return true; 484 } 485 static_assert(no_cont_after_break(), ""); 486 487 constexpr bool cond() { 488 for (int a = 1; bool b = a != 3; ++a) { 489 if (!b) 490 return false; 491 } 492 while (bool b = true) { 493 b = false; 494 break; 495 } 496 return true; 497 } 498 static_assert(cond(), ""); 499 500 constexpr int range_for() { 501 int arr[] = { 1, 2, 3, 4, 5 }; 502 int sum = 0; 503 for (int x : arr) 504 sum += x; 505 return sum; 506 } 507 static_assert(range_for() == 15, ""); 508 509 template<int...N> struct ints {}; 510 template<typename A, typename B> struct join_ints; 511 template<int...As, int...Bs> struct join_ints<ints<As...>, ints<Bs...>> { 512 using type = ints<As..., sizeof...(As) + Bs...>; 513 }; 514 template<unsigned N> struct make_ints { 515 using type = typename join_ints<typename make_ints<N/2>::type, typename make_ints<(N+1)/2>::type>::type; 516 }; 517 template<> struct make_ints<0> { using type = ints<>; }; 518 template<> struct make_ints<1> { using type = ints<0>; }; 519 520 struct ignore { template<typename ...Ts> constexpr ignore(Ts &&...) {} }; 521 522 template<typename T, unsigned N> struct array { 523 constexpr array() : arr{} {} 524 template<typename ...X> 525 constexpr array(X ...x) : arr{} { 526 init(typename make_ints<sizeof...(X)>::type{}, x...); 527 } 528 template<int ...I, typename ...X> constexpr void init(ints<I...>, X ...x) { 529 ignore{arr[I] = x ...}; 530 } 531 T arr[N]; 532 struct iterator { 533 T *p; 534 constexpr explicit iterator(T *p) : p(p) {} 535 constexpr bool operator!=(iterator o) { return p != o.p; } 536 constexpr iterator &operator++() { ++p; return *this; } 537 constexpr T &operator*() { return *p; } 538 }; 539 constexpr iterator begin() { return iterator(arr); } 540 constexpr iterator end() { return iterator(arr + N); } 541 }; 542 543 constexpr int range_for_2() { 544 array<int, 5> arr { 1, 2, 3, 4, 5 }; 545 int sum = 0; 546 for (int k : arr) { 547 sum += k; 548 if (sum > 8) break; 549 } 550 return sum; 551 } 552 static_assert(range_for_2() == 10, ""); 553 } 554 555 namespace assignment_op { 556 struct A { 557 constexpr A() : n(5) {} 558 int n; 559 struct B { 560 int k = 1; 561 union U { 562 constexpr U() : y(4) {} 563 int x; 564 int y; 565 } u; 566 } b; 567 }; 568 constexpr bool testA() { 569 A a, b; 570 a.n = 7; 571 a.b.u.y = 5; 572 b = a; 573 return b.n == 7 && b.b.u.y == 5 && b.b.k == 1; 574 } 575 static_assert(testA(), ""); 576 577 struct B { 578 bool assigned = false; 579 constexpr B &operator=(const B&) { 580 assigned = true; 581 return *this; 582 } 583 }; 584 struct C : B { 585 B b; 586 int n = 5; 587 }; 588 constexpr bool testC() { 589 C c, d; 590 c.n = 7; 591 d = c; 592 c.n = 3; 593 return d.n == 7 && d.assigned && d.b.assigned; 594 } 595 static_assert(testC(), ""); 596 } 597 598 namespace switch_stmt { 599 constexpr int f(char k) { 600 bool b = false; 601 int z = 6; 602 switch (k) { 603 return -1; 604 case 0: 605 if (false) { 606 case 1: 607 z = 1; 608 for (; b;) { 609 return 5; 610 while (0) 611 case 2: return 2; 612 case 7: z = 7; 613 do case 6: { 614 return z; 615 if (false) 616 case 3: return 3; 617 case 4: z = 4; 618 } while (1); 619 case 5: b = true; 620 case 9: z = 9; 621 } 622 return z; 623 } else if (false) case 8: z = 8; 624 else if (false) { 625 case 10: 626 z = -10; 627 break; 628 } 629 else z = 0; 630 return z; 631 default: 632 return -1; 633 } 634 return -z; 635 } 636 static_assert(f(0) == 0, ""); 637 static_assert(f(1) == 1, ""); 638 static_assert(f(2) == 2, ""); 639 static_assert(f(3) == 3, ""); 640 static_assert(f(4) == 4, ""); 641 static_assert(f(5) == 5, ""); 642 static_assert(f(6) == 6, ""); 643 static_assert(f(7) == 7, ""); 644 static_assert(f(8) == 8, ""); 645 static_assert(f(9) == 9, ""); 646 static_assert(f(10) == 10, ""); 647 648 // Check that we can continue an outer loop from within a switch. 649 constexpr bool contin() { 650 for (int n = 0; n != 10; ++n) { 651 switch (n) { 652 case 0: 653 ++n; 654 continue; 655 case 1: 656 return false; 657 case 2: 658 return true; 659 } 660 } 661 return false; 662 } 663 static_assert(contin(), ""); 664 665 constexpr bool switch_into_for() { 666 int n = 0; 667 switch (n) { 668 for (; n == 1; ++n) { 669 return n == 1; 670 case 0: ; 671 } 672 } 673 return false; 674 } 675 static_assert(switch_into_for(), ""); 676 677 constexpr void duff_copy(char *a, const char *b, int n) { 678 switch ((n - 1) % 8 + 1) { 679 for ( ; n; n = (n - 1) & ~7) { 680 case 8: a[n-8] = b[n-8]; 681 case 7: a[n-7] = b[n-7]; 682 case 6: a[n-6] = b[n-6]; 683 case 5: a[n-5] = b[n-5]; 684 case 4: a[n-4] = b[n-4]; 685 case 3: a[n-3] = b[n-3]; 686 case 2: a[n-2] = b[n-2]; 687 case 1: a[n-1] = b[n-1]; 688 } 689 case 0: ; 690 } 691 } 692 693 constexpr bool test_copy(const char *str, int n) { 694 char buffer[16] = {}; 695 duff_copy(buffer, str, n); 696 for (int i = 0; i != sizeof(buffer); ++i) 697 if (buffer[i] != (i < n ? str[i] : 0)) 698 return false; 699 return true; 700 } 701 static_assert(test_copy("foo", 0), ""); 702 static_assert(test_copy("foo", 1), ""); 703 static_assert(test_copy("foo", 2), ""); 704 static_assert(test_copy("hello world", 0), ""); 705 static_assert(test_copy("hello world", 7), ""); 706 static_assert(test_copy("hello world", 8), ""); 707 static_assert(test_copy("hello world", 9), ""); 708 static_assert(test_copy("hello world", 10), ""); 709 static_assert(test_copy("hello world", 10), ""); 710 } 711 712 namespace deduced_return_type { 713 constexpr auto f() { return 0; } 714 template<typename T> constexpr auto g(T t) { return t; } 715 static_assert(f() == 0, ""); 716 static_assert(g(true), ""); 717 } 718 719 namespace modify_temporary_during_construction { 720 struct A { int &&temporary; int x; int y; }; 721 constexpr int f(int &r) { r *= 9; return r - 12; } 722 // FIXME: The 'uninitialized' warning here is bogus. 723 constexpr A a = { 6, f(a.temporary), a.temporary }; // expected-warning {{uninitialized}} expected-note {{temporary created here}} 724 static_assert(a.x == 42, ""); 725 static_assert(a.y == 54, ""); 726 constexpr int k = a.temporary++; // expected-error {{constant expression}} expected-note {{outside the expression that created the temporary}} 727 } 728 729 namespace std { 730 typedef decltype(sizeof(int)) size_t; 731 732 template <class _E> 733 class initializer_list 734 { 735 const _E* __begin_; 736 size_t __size_; 737 738 constexpr initializer_list(const _E* __b, size_t __s) 739 : __begin_(__b), 740 __size_(__s) 741 {} 742 743 public: 744 typedef _E value_type; 745 typedef const _E& reference; 746 typedef const _E& const_reference; 747 typedef size_t size_type; 748 749 typedef const _E* iterator; 750 typedef const _E* const_iterator; 751 752 constexpr initializer_list() : __begin_(nullptr), __size_(0) {} 753 754 constexpr size_t size() const {return __size_;} 755 constexpr const _E* begin() const {return __begin_;} 756 constexpr const _E* end() const {return __begin_ + __size_;} 757 }; 758 } 759 760 namespace InitializerList { 761 constexpr int sum(std::initializer_list<int> ints) { 762 int total = 0; 763 for (int n : ints) total += n; 764 return total; 765 } 766 static_assert(sum({1, 2, 3, 4, 5}) == 15, ""); 767 } 768 769 namespace StmtExpr { 770 constexpr int f(int k) { 771 switch (k) { 772 case 0: 773 return 0; 774 775 ({ 776 case 1: // expected-note {{not supported}} 777 return 1; 778 }); 779 } 780 } 781 static_assert(f(1) == 1, ""); // expected-error {{constant expression}} expected-note {{in call}} 782 783 constexpr int g() { // expected-error {{never produces a constant}} 784 return ({ int n; n; }); // expected-note {{object of type 'int' is not initialized}} 785 } 786 787 // FIXME: We should handle the void statement expression case. 788 constexpr int h() { // expected-error {{never produces a constant}} 789 ({ if (true) {} }); // expected-note {{not supported}} 790 return 0; 791 } 792 } 793 794 namespace VirtualFromBase { 795 struct S1 { 796 virtual int f() const; 797 }; 798 struct S2 { 799 virtual int f(); 800 }; 801 template <typename T> struct X : T { 802 constexpr X() {} 803 double d = 0.0; 804 constexpr int f() { return sizeof(T); } 805 }; 806 807 // Non-virtual f(), OK. 808 constexpr X<X<S1>> xxs1; 809 constexpr X<S1> *p = const_cast<X<X<S1>>*>(&xxs1); 810 static_assert(p->f() == sizeof(S1), ""); 811 812 // Virtual f(), not OK. 813 constexpr X<X<S2>> xxs2; 814 constexpr X<S2> *q = const_cast<X<X<S2>>*>(&xxs2); 815 static_assert(q->f() == sizeof(X<S2>), ""); // expected-error {{constant expression}} expected-note {{virtual function call}} 816 } 817 818 namespace Lifetime { 819 constexpr int &get(int &&r) { return r; } 820 constexpr int f() { 821 int &r = get(123); 822 return r; // expected-note {{read of object outside its lifetime}} 823 } 824 static_assert(f() == 123, ""); // expected-error {{constant expression}} expected-note {{in call}} 825 826 constexpr int g() { 827 int *p = 0; 828 { 829 int n = 0; 830 p = &n; 831 n = 42; 832 } 833 *p = 123; // expected-note {{assignment to object outside its lifetime}} 834 return *p; 835 } 836 static_assert(g() == 42, ""); // expected-error {{constant expression}} expected-note {{in call}} 837 838 constexpr int h(int n) { 839 int *p[4] = {}; 840 int &&r = 1; 841 p[0] = &r; 842 while (int a = 1) { 843 p[1] = &a; 844 for (int b = 1; int c = 1; ) { 845 p[2] = &b, p[3] = &c; 846 break; 847 } 848 break; 849 } 850 *p[n] = 0; // expected-note 3{{assignment to object outside its lifetime}} 851 return *p[n]; 852 } 853 static_assert(h(0) == 0, ""); // ok, lifetime-extended 854 static_assert(h(1) == 0, ""); // expected-error {{constant expression}} expected-note {{in call}} 855 static_assert(h(2) == 0, ""); // expected-error {{constant expression}} expected-note {{in call}} 856 static_assert(h(3) == 0, ""); // expected-error {{constant expression}} expected-note {{in call}} 857 858 // FIXME: This function should be treated as non-constant. 859 constexpr void lifetime_versus_loops() { 860 int *p = 0; 861 for (int i = 0; i != 2; ++i) { 862 int *q = p; 863 int n = 0; 864 p = &n; 865 if (i) 866 // This modifies the 'n' from the previous iteration of the loop outside 867 // its lifetime. 868 ++*q; 869 } 870 } 871 static_assert((lifetime_versus_loops(), true), ""); 872 } 873 874 namespace Bitfields { 875 struct A { 876 bool b : 3; 877 int n : 4; 878 unsigned u : 5; 879 }; 880 constexpr bool test() { 881 A a {}; 882 a.b += 2; 883 --a.n; 884 --a.u; 885 a.n = -a.n * 3; 886 return a.b == false && a.n == 3 && a.u == 31; 887 } 888 static_assert(test(), ""); 889 } 890 891 namespace PR17615 { 892 struct A { 893 int &&r; 894 constexpr A(int &&r) : r(static_cast<int &&>(r)) {} 895 constexpr A() : A(0) { 896 (void)+r; // expected-note {{outside its lifetime}} 897 } 898 }; 899 constexpr int k = A().r; // expected-error {{constant expression}} expected-note {{in call to}} 900 } 901 902 namespace PR17331 { 903 template<typename T, unsigned int N> 904 constexpr T sum(const T (&arr)[N]) { 905 T result = 0; 906 for (T i : arr) 907 result += i; 908 return result; 909 } 910 911 constexpr int ARR[] = { 1, 2, 3, 4, 5 }; 912 static_assert(sum(ARR) == 15, ""); 913 } 914