838 lines · cpp
1// RUN: %clang_cc1 -fexperimental-new-constant-interpreter -verify=expected,both %s2// RUN: %clang_cc1 -fexperimental-new-constant-interpreter -verify=expected,both -std=c++20 %s3// RUN: %clang_cc1 -verify=ref,both %s4// RUN: %clang_cc1 -verify=ref,both -std=c++20 %s5 6constexpr int m = 3;7constexpr const int *foo[][5] = {8 {nullptr, &m, nullptr, nullptr, nullptr},9 {nullptr, nullptr, &m, nullptr, nullptr},10 {nullptr, nullptr, nullptr, &m, nullptr},11};12 13static_assert(foo[0][0] == nullptr, "");14static_assert(foo[0][1] == &m, "");15static_assert(foo[0][2] == nullptr, "");16static_assert(foo[0][3] == nullptr, "");17static_assert(foo[0][4] == nullptr, "");18static_assert(foo[1][0] == nullptr, "");19static_assert(foo[1][1] == nullptr, "");20static_assert(foo[1][2] == &m, "");21static_assert(foo[1][3] == nullptr, "");22static_assert(foo[1][4] == nullptr, "");23static_assert(foo[2][0] == nullptr, "");24static_assert(foo[2][1] == nullptr, "");25static_assert(foo[2][2] == nullptr, "");26static_assert(foo[2][3] == &m, "");27static_assert(foo[2][4] == nullptr, "");28 29constexpr int afterEnd[] = {1,2,3};30static_assert(&afterEnd[3] == afterEnd + 3, "");31 32constexpr int ZeroSizeArray[] = {};33 34constexpr int SomeInt[] = {1};35constexpr int getSomeInt() { return *SomeInt; }36static_assert(getSomeInt() == 1, "");37 38/// A init list for a primitive value.39constexpr int f{5};40static_assert(f == 5, "");41 42 43constexpr int getElement(int i) {44 int values[] = {1, 4, 9, 16, 25, 36};45 return values[i];46}47static_assert(getElement(1) == 4, "");48static_assert(getElement(5) == 36, "");49 50constexpr int data[] = {5, 4, 3, 2, 1};51constexpr int getElement(const int *Arr, int index) {52 return *(Arr + index);53}54 55constexpr int derefPtr(const int *d) {56 return *d;57}58static_assert(derefPtr(data) == 5, "");59 60/// Make sure we can refer to the one-past-the-end element61/// and then return back to the end of the array.62static_assert((&data[5])[-1] == 1, "");63 64constexpr int storePtr() {65 int b[] = {1,2,3,4};66 int *c = b;67 68 *c = 4;69 return *c;70}71static_assert(storePtr() == 4, "");72 73 74static_assert(getElement(data, 1) == 4, "");75static_assert(getElement(data, 4) == 1, "");76 77constexpr int getElementFromEnd(const int *Arr, int size, int index) {78 return *(Arr + size - index - 1);79}80static_assert(getElementFromEnd(data, 5, 0) == 1, "");81static_assert(getElementFromEnd(data, 5, 4) == 5, "");82 83constexpr int getFirstElem(const int *a) {84 return a[0]; // both-note {{read of dereferenced null pointer}}85}86static_assert(getFirstElem(nullptr) == 1, ""); // both-error {{not an integral constant expression}} \87 // both-note {{in call to}}88 89constexpr static int arr[2] = {1,2};90constexpr static int arr2[2] = {3,4};91constexpr int *p1 = nullptr;92constexpr int *p2 = p1 + 1; // both-error {{must be initialized by a constant expression}} \93 // both-note {{cannot perform pointer arithmetic on null pointer}}94constexpr int *p3 = p1 + 0;95constexpr int *p4 = p1 - 0;96constexpr int *p5 = 0 + p1;97constexpr int *p6 = 0 - p1; // both-error {{invalid operands to binary expression}}98 99constexpr int const * ap1 = &arr[0];100constexpr int const * ap2 = ap1 + 3; // both-error {{must be initialized by a constant expression}} \101 // both-note {{cannot refer to element 3 of array of 2}}102 103constexpr auto ap3 = arr - 1; // both-error {{must be initialized by a constant expression}} \104 // both-note {{cannot refer to element -1}}105constexpr int k1 = &arr[1] - &arr[0];106static_assert(k1 == 1, "");107static_assert((&arr[0] - &arr[1]) == -1, "");108 109constexpr int k2 = &arr2[1] - &arr[0]; // both-error {{must be initialized by a constant expression}} \110 // both-note {{arithmetic involving unrelated objects}}111 112static_assert((arr + 0) == arr, "");113static_assert(&arr[0] == arr, "");114static_assert(*(&arr[0]) == 1, "");115static_assert(*(&arr[1]) == 2, "");116 117constexpr const int *OOB = (arr + 3) - 3; // both-error {{must be initialized by a constant expression}} \118 // both-note {{cannot refer to element 3 of array of 2 elements}}119 120template<typename T>121constexpr T getElementOf(T* array, int i) {122 return array[i];123}124static_assert(getElementOf(foo[0], 1) == &m, "");125 126 127template <typename T, int N>128constexpr T& getElementOfArray(T (&array)[N], int I) {129 return array[I];130}131static_assert(getElementOfArray(foo[2], 3) == &m, "");132 133 134static_assert(data[0] == 4, ""); // both-error{{failed}} \135 // both-note{{5 == 4}}136 137constexpr int dynamic[] = {138 f, 3, 2 + 5, data[3], *getElementOf(foo[2], 3)139};140static_assert(dynamic[0] == f, "");141static_assert(dynamic[3] == 2, "");142 143 144constexpr int dependent[4] = {145 0, 1, dependent[0], dependent[1]146};147static_assert(dependent[2] == dependent[0], "");148static_assert(dependent[3] == dependent[1], "");149 150union { char x[]; } r = {0};151 152#pragma clang diagnostic push153#pragma clang diagnostic ignored "-Wc99-extensions"154#pragma clang diagnostic ignored "-Winitializer-overrides"155constexpr int DI[] = {156 [0] = 10,157 [1] = 20,158 30,159 40,160 [1] = 50161};162static_assert(DI[0] == 10, "");163static_assert(DI[1] == 50, "");164static_assert(DI[2] == 30, "");165static_assert(DI[3] == 40, "");166 167constexpr int addThreeElements(const int v[3]) {168 return v[0] + v[1] + v[2];169}170constexpr int is[] = {10, 20, 30 };171static_assert(addThreeElements(is) == 60, "");172 173struct fred {174 char s [6];175 int n;176};177 178struct fred y [] = { [0] = { .s[0] = 'q' } };179#pragma clang diagnostic pop180 181namespace indices {182 constexpr int first[] = {1};183 constexpr int firstValue = first[2]; // both-error {{must be initialized by a constant expression}} \184 // both-note {{cannot refer to element 2 of array of 1}}185 186 constexpr int second[10] = {17};187 constexpr int secondValue = second[10];// both-error {{must be initialized by a constant expression}} \188 // both-note {{read of dereferenced one-past-the-end pointer}} \189 190 constexpr int negative = second[-2]; // both-error {{must be initialized by a constant expression}} \191 // both-note {{cannot refer to element -2 of array of 10}}192};193 194namespace DefaultInit {195 template <typename T, unsigned N>196 struct B {197 T a[N];198 };199 200 int f() {201 constexpr B<int,10> arr = {};202 constexpr int x = arr.a[0];203 }204};205 206class A {207public:208 int a;209 constexpr A(int m = 2) : a(10 + m) {}210};211class AU {212public:213 int a;214 constexpr AU() : a(5 / 0) {} // both-warning {{division by zero is undefined}} \215 // both-note 2{{division by zero}} \216 // both-error {{never produces a constant expression}}217};218class B {219public:220 A a[2];221 constexpr B() {}222};223constexpr B b;224static_assert(b.a[0].a == 12, "");225static_assert(b.a[1].a == 12, "");226 227class BU {228public:229 AU a[2];230 constexpr BU() {} // both-note {{in call to 'AU()'}}231};232constexpr BU bu; // both-error {{must be initialized by a constant expression}} \233 // both-note {{in call to 'BU()'}}234 235namespace IncDec {236 constexpr int getNextElem(const int *A, int I) {237 const int *B = (A + I);238 ++B;239 return *B;240 }241 constexpr int E[] = {1,2,3,4};242 243 static_assert(getNextElem(E, 1) == 3, "");244 245 constexpr int getFirst() {246 const int *e = E;247 return *(e++);248 }249 static_assert(getFirst() == 1, "");250 251 constexpr int getFirst2() {252 const int *e = E;253 e++;254 return *e;255 }256 static_assert(getFirst2() == 2, "");257 258 constexpr int getSecond() {259 const int *e = E;260 return *(++e);261 }262 static_assert(getSecond() == 2, "");263 264 constexpr int getSecond2() {265 const int *e = E;266 ++e;267 return *e;268 }269 static_assert(getSecond2() == 2, "");270 271 constexpr int getLast() {272 const int *e = E + 3;273 return *(e--);274 }275 static_assert(getLast() == 4, "");276 277 constexpr int getLast2() {278 const int *e = E + 3;279 e--;280 return *e;281 }282 static_assert(getLast2() == 3, "");283 284 constexpr int getSecondToLast() {285 const int *e = E + 3;286 return *(--e);287 }288 static_assert(getSecondToLast() == 3, "");289 290 constexpr int getSecondToLast2() {291 const int *e = E + 3;292 --e;293 return *e;294 }295 static_assert(getSecondToLast2() == 3, "");296 297 constexpr int bad1() { // both-error {{never produces a constant expression}}298 const int *e = E + 3;299 e++; // This is fine because it's a one-past-the-end pointer300 return *e; // both-note 2{{read of dereferenced one-past-the-end pointer}}301 }302 static_assert(bad1() == 0, ""); // both-error {{not an integral constant expression}} \303 // both-note {{in call to}}304 305 constexpr int bad2() { // both-error {{never produces a constant expression}}306 const int *e = E + 4;307 e++; // both-note 2{{cannot refer to element 5 of array of 4 elements}}308 return *e; // This is UB as well309 }310 static_assert(bad2() == 0, ""); // both-error {{not an integral constant expression}} \311 // both-note {{in call to}}312 313 constexpr int bad3() { // both-error {{never produces a constant expression}}314 const int *e = E;315 e--; // both-note 2{{cannot refer to element -1 of array of 4 elements}}316 return *e; // This is UB as well317 }318 static_assert(bad3() == 0, ""); // both-error {{not an integral constant expression}} \319 // both-note {{in call to}}320 321 constexpr int nullptr1(bool Pre) {322 int *a = nullptr;323 if (Pre)324 ++a; // both-note {{arithmetic on null pointer}}325 else326 a++; // both-note {{arithmetic on null pointer}}327 return 1;328 }329 static_assert(nullptr1(true) == 1, ""); // both-error {{not an integral constant expression}} \330 // both-note {{in call to}}331 332 static_assert(nullptr1(false) == 1, ""); // both-error {{not an integral constant expression}} \333 // both-note {{in call to}}334};335 336namespace ZeroInit {337 struct A {338 int *p[2];339 };340 constexpr A a = {};341 static_assert(a.p[0] == nullptr, "");342 static_assert(a.p[1] == nullptr, "");343 344 struct B {345 double f[2];346 };347 constexpr B b = {};348 static_assert(b.f[0] == 0.0, "");349 static_assert(b.f[1] == 0.0, "");350}351 352namespace ArrayInitLoop {353 struct X {354 int arr[3];355 };356 constexpr X f(int &r) {357 return {++r, ++r, ++r};358 }359 constexpr int g() {360 int n = 0;361 auto [a, b, c] = f(n).arr;362 return a + b + c;363 }364 static_assert(g() == 6, "");365}366 367namespace StringZeroFill {368 struct A {369 char c[6];370 };371 constexpr A a = { "abc" };372 static_assert(a.c[0] == 'a', "");373 static_assert(a.c[1] == 'b', "");374 static_assert(a.c[2] == 'c', "");375 static_assert(a.c[3] == '\0', "");376 static_assert(a.c[4] == '\0', "");377 static_assert(a.c[5] == '\0', "");378 379 constexpr char b[6] = "foo";380 static_assert(b[0] == 'f', "");381 static_assert(b[1] == 'o', "");382 static_assert(b[2] == 'o', "");383 static_assert(b[3] == '\0', "");384 static_assert(b[4] == '\0', "");385 static_assert(b[5] == '\0', "");386}387 388namespace NoInitMapLeak {389#pragma clang diagnostic push390#pragma clang diagnostic ignored "-Wdivision-by-zero"391#pragma clang diagnostic ignored "-Wc++20-extensions"392 constexpr int testLeak() { // both-error {{never produces a constant expression}}393 int a[2];394 a[0] = 1;395 // interrupts interpretation.396 (void)(1 / 0); // both-note 2{{division by zero}}397 398 return 1;399 }400#pragma clang diagnostic pop401 static_assert(testLeak() == 1, ""); // both-error {{not an integral constant expression}} \402 // both-note {{in call to 'testLeak()'}}403 404 constexpr int a[] = {1,2,3,4/0,5}; // both-error {{must be initialized by a constant expression}} \405 // both-note {{division by zero}} \406 // ref-note {{declared here}}407 408 /// FIXME: This should fail in the new interpreter as well.409 constexpr int b = a[0]; // ref-error {{must be initialized by a constant expression}} \410 // ref-note {{is not a constant expression}} \411 // ref-note {{declared here}}412 static_assert(b == 1, ""); // ref-error {{not an integral constant expression}} \413 // ref-note {{not a constant expression}}414 415 constexpr int f() { // both-error {{never produces a constant expression}}416 int a[] = {19,2,3/0,4}; // both-note 2{{division by zero}} \417 // both-warning {{is undefined}}418 return 1;419 }420 static_assert(f() == 1, ""); // both-error {{not an integral constant expression}} \421 // both-note {{in call to}}422}423 424namespace Incomplete {425 struct Foo {426 char c;427 int a[];428 };429 430 constexpr Foo F{};431 constexpr const int *A = F.a; // both-error {{must be initialized by a constant expression}} \432 // both-note {{array-to-pointer decay of array member without known bound}}433 434 constexpr const int *B = F.a + 1; // both-error {{must be initialized by a constant expression}} \435 // both-note {{array-to-pointer decay of array member without known bound}}436 437 constexpr int C = *F.a; // both-error {{must be initialized by a constant expression}} \438 // both-note {{array-to-pointer decay of array member without known bound}}439 440 struct X {441 int a;442 int b[];443 };444 extern X x;445 constexpr int *xb = x.b; // both-error {{must be initialized by a constant expression}} \446 // both-note {{array-to-pointer decay of array member without known bound}}447 448 449 /// These are from test/SemaCXX/constant-expression-cxx11.cpp450 extern int arr[];451 constexpr int *c = &arr[1]; // both-error {{must be initialized by a constant expression}} \452 // both-note {{indexing of array without known bound}}453 constexpr int *d = &arr[1]; // both-error {{must be initialized by a constant expression}} \454 // both-note {{indexing of array without known bound}}455 constexpr int *e = arr + 1; // both-error {{must be initialized by a constant expression}} \456 // both-note {{indexing of array without known bound}}457}458 459namespace GH69115 {460 /// This used to crash because we were trying to emit destructors for the461 /// array.462 constexpr int foo() {463 int arr[2][2] = {1, 2, 3, 4};464 return 0;465 }466 static_assert(foo() == 0, "");467 468 /// Test that we still emit the destructors for multi-dimensional469 /// composite arrays.470#if __cplusplus >= 202002L471 constexpr void assert(bool C) {472 if (C)473 return;474 // Invalid in constexpr.475 (void)(1 / 0); // both-warning {{undefined}}476 }477 478 class F {479 public:480 int a;481 int *dtor;482 int &idx;483 constexpr F(int a, int *dtor, int &idx) : a(a), dtor(dtor), idx(idx) {}484 constexpr ~F() noexcept(false){485 dtor[idx] = a;486 ++idx;487 }488 };489 constexpr int foo2() {490 int dtorIndices[] = {0, 0, 0, 0};491 int idx = 0;492 493 {494 F arr[2][2] = {F(1, dtorIndices, idx),495 F(2, dtorIndices, idx),496 F(3, dtorIndices, idx),497 F(4, dtorIndices, idx)};498 }499 500 /// Reverse-reverse order.501 assert(idx == 4);502 assert(dtorIndices[0] == 4);503 assert(dtorIndices[1] == 3);504 assert(dtorIndices[2] == 2);505 assert(dtorIndices[3] == 1);506 507 return 0;508 }509 static_assert(foo2() == 0, "");510#endif511}512 513namespace NonConstReads {514#if __cplusplus >= 202002L515 void *p = nullptr; // both-note {{declared here}}516 517 int arr[!p]; // both-error {{not allowed at file scope}} \518 // both-warning {{variable length arrays}} \519 // both-note {{read of non-constexpr variable 'p'}}520 int z; // both-note {{declared here}}521 int a[z]; // both-error {{not allowed at file scope}} \522 // both-warning {{variable length arrays}} \523 // both-note {{read of non-const variable 'z'}}524#else525 void *p = nullptr;526 int arr[!p]; // both-error {{not allowed at file scope}}527 int z;528 int a[z]; // both-error {{not allowed at file scope}}529#endif530 531 const int y = 0;532 int yy[y];533}534 535namespace SelfComparison {536 struct S {537 int field;538 static int static_field;539 int array[4];540 };541 542 struct T {543 int field;544 static int static_field;545 int array[4];546 S s;547 };548 549 int struct_test(S s1, S s2, S *s3, T t) {550 return s3->array[t.field] == s3->array[t.field]; // both-warning {{self-comparison always evaluates to true}}551 };552}553 554namespace LocalIndex {555 void test() {556 const int const_subscript = 3;557 int array[2]; // both-note {{declared here}}558 array[const_subscript] = 0; // both-warning {{array index 3 is past the end of the array (that has type 'int[2]')}}559 }560}561 562namespace LocalVLA {563 struct Foo {564 int x;565 Foo(int x) : x(x) {}566 };567 struct Elidable {568 Elidable();569 };570 571 void foo(int size) {572 Elidable elidableDynArray[size];573#if __cplusplus >= 202002L574 // both-note@-3 {{declared here}}575 // both-warning@-3 {{variable length array}}576 // both-note@-4 {{function parameter 'size' with unknown value}}577#endif578 }579 580 void f (unsigned int m) {581 int e[2][m];582#if __cplusplus >= 202002L583 // both-note@-3 {{declared here}}584 // both-warning@-3 2{{variable length array}}585 // both-note@-4 {{function parameter 'm' with unknown value}}586#endif587 e[0][0] = 0;588 }589}590 591char melchizedek[2];592typedef decltype(melchizedek[1] - melchizedek[0]) ptrdiff_t;593constexpr ptrdiff_t d1 = &melchizedek[1] - &melchizedek[0]; // ok594constexpr ptrdiff_t d3 = &melchizedek[0] - &melchizedek[1]; // ok595 596/// GH#88018597const int SZA[] = {};598void testZeroSizedArrayAccess() { unsigned c = SZA[4]; }599 600#if __cplusplus >= 202002L601constexpr int test_multiarray2() { // both-error {{never produces a constant expression}}602 int multi2[2][1]; // both-note {{declared here}}603 return multi2[2][0]; // both-note {{cannot access array element of pointer past the end of object}} \604 // both-warning {{array index 2 is past the end of the array (that has type 'int[2][1]')}}605}606 607/// Same but with a dummy pointer.608int multi22[2][2]; // both-note {{declared here}}609int test_multiarray22() {610 return multi22[2][0]; // both-warning {{array index 2 is past the end of the array (that has type 'int[2][2]')}}611}612 613#endif614 615namespace ArrayMemberAccess {616 struct A {617 int x;618 };619 void f(const A (&a)[]) {620 bool cond = a->x;621 }622}623 624namespace OnePastEndSub {625 struct A {};626 constexpr A a[3][3];627 constexpr int diff2 = &a[1][3] - &a[1][0]; /// Used to crash.628}629 630static int same_entity_2[3];631constexpr int *get2() {632 // This is a redeclaration of the same entity, even though it doesn't633 // inherit the type of the prior declaration.634 extern int same_entity_2[];635 return same_entity_2;636}637static_assert(get2() == same_entity_2, "failed to find previous decl");638 639constexpr int zs[2][2][2][2] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 };640constexpr int fail(const int &p) {641 return (&p)[64]; // both-note 2{{cannot refer to element 64 of array of 2 elements}} \642 // both-note {{cannot refer to element 65 of array of 2 elements}} \643 // both-note {{cannot refer to element 66 of array of 2 elements}}644}645static_assert(fail(*(&(&(*(*&(&zs[2] - 1)[0] + 2 - 2))[2])[-1][2] - 2)) == 11, ""); // both-error {{not an integral constant expression}} \646 // both-note {{in call to}}647 648 649static_assert(fail( // both-error {{not an integral constant expression}} \650 // both-note {{in call to 'fail(zs[1][1][0][0])'}}651 *(*(*((*652 (zs + 1)) /// int[2][2][2]653 + 1) /// int[2][2]654 + 2 - 2) /// int[2]655 + 2 - 2) /// int656 ));657 658static_assert(fail( // both-error {{not an integral constant expression}} \659 // both-note {{in call to 'fail(zs[1][0][0][1])'}}660 *(*(*((*661 (zs + 1)) /// int[2][2][2]662 + 0) /// int[2][2]663 + 2 - 2) /// int[2]664 + 1) /// int665 ));666 667static_assert(fail( // both-error {{not an integral constant expression}} \668 // both-note {{in call to 'fail(zs[1][0][0][2])'}}669 *(*(*((*670 (zs + 1)) /// int[2][2][2]671 + 0) /// int[2][2]672 + 2 - 2) /// int[2]673 + 2) /// int674 ));675 676namespace ZeroIndex {677 constexpr char foo(const char *a) {678 return a[0];679 }680 constexpr const char *f = "abc";681 static_assert(foo(f + 1) == 'b', "");682}683 684namespace MultiDimArrayOffset {685#define assert(x) (x ? void(0) : __builtin_abort())686 struct R {687 int a;688 };689 690 template<typename T>691 class view {692 public:693 T* V;694 T* current;695 696 constexpr view(T*V) : V(V), current(V) {}697 698 constexpr void operator+=(unsigned N) {699 current += N;700 }701 702 constexpr auto operator*() {703 return *current;704 }705 706 };707 708 constexpr int foo() {709 R buffer[2][4] = {{1, 2, 3, 4}, {5, 6, 7, 8}};710 711 auto A = buffer;712 A += 1;713 assert((**A).a == 5);714 assert(buffer == buffer + 1 - 1);715 716 assert(--A+0 == buffer+0);717 718 view V(buffer);719 assert(*V == &buffer[0][0]);720 V += 1;721 assert(*V == &buffer[1][0]);722 assert(*(V.current) == &buffer[1][0]);723 return 1;724 }725 static_assert(foo() == 1, "");726}727 728namespace ZeroSizeTypes {729 constexpr int (*p1)[0] = 0, (*p2)[0] = 0;730 constexpr int k = p2 - p1; // both-error {{constexpr variable 'k' must be initialized by a constant expression}} \731 // both-note {{subtraction of pointers to type 'int[0]' of zero size}} \732 // both-warning {{subtraction of pointers to type 'int[0]' of zero size has undefined behavior}}733 734 constexpr int k2 = p1 - p1; // both-error {{constexpr variable 'k2' must be initialized by a constant expression}} \735 // both-note {{subtraction of pointers to type 'int[0]' of zero size}} \736 // both-warning {{subtraction of pointers to type 'int[0]' of zero size has undefined behavior}}737 738 int arr[5][0];739 constexpr int f() { // both-error {{never produces a constant expression}}740 return &arr[3] - &arr[0]; // both-note {{subtraction of pointers to type 'int[0]' of zero size}} \741 // both-warning {{subtraction of pointers to type 'int[0]' of zero size has undefined behavior}}742 }743 744 constexpr int z[0]{};745 static_assert((z - z) == 0);746}747 748namespace InvalidIndex {749 constexpr int foo(int i) { // both-error {{no return statement in constexpr function}}750 int a[] = {1,2,3};751 return a[_z]; // both-error {{use of undeclared identifier}}752 }753 static_assert(foo(0) == 1, "");754}755 756namespace PointerSubscript {757 template<typename T>758 constexpr T foo() {759 T ss[] = {{}, {}, {}};760 T *s = &ss[0];761 762 return s[2];763 }764 static_assert(foo<int>() == 0);765 struct S{};766 static_assert((foo<S>(), true));767}768 769namespace OnePastEndDiag {770 771 constexpr int a(const int *b) {772 return *b; // both-note {{read of dereferenced one-past-the-end pointer}}773 }774 constexpr int foo[] = {1,2};775 constexpr int k = a(foo + 2); // both-error {{must be initialized by a constant expression}} \776 // both-note {{in call to 'a(&foo[2])'}}777}778 779namespace DiscardedSubScriptExpr {780 constexpr bool foo() { // both-error {{never produces a constant expression}}781 int a[2] = {};782 (void)a[3]; // both-note {{cannot refer to element 3 of array of 2 elements in a constant expression}}783 return true;784 }785}786 787namespace ZeroSizeArrayRead {788 constexpr char str[0] = {};789 constexpr unsigned checksum(const char *s) {790 unsigned result = 0;791 for (const char *p = s; *p != '\0'; ++p) { // both-note {{read of dereferenced one-past-the-end pointer}}792 result += *p;793 }794 return result;795 }796 constexpr unsigned C = checksum(str); // both-error {{must be initialized by a constant expression}} \797 // both-note {{in call to}}798 799 constexpr const char *p1 = &str[0];800 constexpr const char *p2 = &str[1]; // both-error {{must be initialized by a constant expression}} \801 // both-note {{cannot refer to element 1 of array of 0 elements in a constant expression}}802 803 constexpr char s[] = {};804 static_assert(s[0] == '0', ""); // both-error {{not an integral constant expression}} \805 // both-note {{read of dereferenced one-past-the-end pointer}}806}807 808namespace FAM {809 char *strchr(const char *, int);810 811 struct A {812 char n, a[2];813 };814 struct B {815 int n;816 struct A a[]; // both-note {{here}}817 };818 819 const struct B b = {0, {{1, {2, 3}}, {4, {5, 6}}}};820 void foo(void) { int sch = 0 != strchr(b.a[1].a, '\0'); }821 822 int foo2() {823 struct B b = {0, {{1, {2, 3}}, {4, {5, 6}}}}; // both-error {{initialization of flexible array member is not allowed}}824 return 1;825 }826}827 828namespace MultiDimConstructExpr {829 struct a {830 a *p = this;831 };832 struct b {833 a m[3][3];834 };835 constexpr b d;836 static_assert(d.m[2][1].p == &d.m[2][1]);837}838