brintos

brintos / llvm-project-archived public Read only

0
0
Text · 24.7 KiB · d83ae97 Raw
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