1a07aba5dSTimm Baeder // RUN: %clang_cc1 -fexperimental-new-constant-interpreter -verify=expected,both %s 2a07aba5dSTimm Baeder // RUN: %clang_cc1 -fexperimental-new-constant-interpreter -std=c++20 -verify=expected,both %s 3a07aba5dSTimm Baeder // RUN: %clang_cc1 -verify=ref,both %s 4a07aba5dSTimm Baeder // RUN: %clang_cc1 -verify=ref,both -std=c++20 %s 5a07aba5dSTimm Baeder 6a07aba5dSTimm Baeder constexpr int m = 3; 7a07aba5dSTimm Baeder constexpr const int *foo[][5] = { 8a07aba5dSTimm Baeder {nullptr, &m, nullptr, nullptr, nullptr}, 9a07aba5dSTimm Baeder {nullptr, nullptr, &m, nullptr, nullptr}, 10a07aba5dSTimm Baeder {nullptr, nullptr, nullptr, &m, nullptr}, 11a07aba5dSTimm Baeder }; 12a07aba5dSTimm Baeder 13a07aba5dSTimm Baeder static_assert(foo[0][0] == nullptr, ""); 14a07aba5dSTimm Baeder static_assert(foo[0][1] == &m, ""); 15a07aba5dSTimm Baeder static_assert(foo[0][2] == nullptr, ""); 16a07aba5dSTimm Baeder static_assert(foo[0][3] == nullptr, ""); 17a07aba5dSTimm Baeder static_assert(foo[0][4] == nullptr, ""); 18a07aba5dSTimm Baeder static_assert(foo[1][0] == nullptr, ""); 19a07aba5dSTimm Baeder static_assert(foo[1][1] == nullptr, ""); 20a07aba5dSTimm Baeder static_assert(foo[1][2] == &m, ""); 21a07aba5dSTimm Baeder static_assert(foo[1][3] == nullptr, ""); 22a07aba5dSTimm Baeder static_assert(foo[1][4] == nullptr, ""); 23a07aba5dSTimm Baeder static_assert(foo[2][0] == nullptr, ""); 24a07aba5dSTimm Baeder static_assert(foo[2][1] == nullptr, ""); 25a07aba5dSTimm Baeder static_assert(foo[2][2] == nullptr, ""); 26a07aba5dSTimm Baeder static_assert(foo[2][3] == &m, ""); 27a07aba5dSTimm Baeder static_assert(foo[2][4] == nullptr, ""); 28a07aba5dSTimm Baeder 29a07aba5dSTimm Baeder constexpr int afterEnd[] = {1,2,3}; 30a07aba5dSTimm Baeder static_assert(&afterEnd[3] == afterEnd + 3, ""); 31a07aba5dSTimm Baeder 32a07aba5dSTimm Baeder constexpr int ZeroSizeArray[] = {}; 33a07aba5dSTimm Baeder 34a07aba5dSTimm Baeder constexpr int SomeInt[] = {1}; 35a07aba5dSTimm Baeder constexpr int getSomeInt() { return *SomeInt; } 36a07aba5dSTimm Baeder static_assert(getSomeInt() == 1, ""); 37a07aba5dSTimm Baeder 38a07aba5dSTimm Baeder /// A init list for a primitive value. 39a07aba5dSTimm Baeder constexpr int f{5}; 40a07aba5dSTimm Baeder static_assert(f == 5, ""); 41a07aba5dSTimm Baeder 42a07aba5dSTimm Baeder 43a07aba5dSTimm Baeder constexpr int getElement(int i) { 44a07aba5dSTimm Baeder int values[] = {1, 4, 9, 16, 25, 36}; 45a07aba5dSTimm Baeder return values[i]; 46a07aba5dSTimm Baeder } 47a07aba5dSTimm Baeder static_assert(getElement(1) == 4, ""); 48a07aba5dSTimm Baeder static_assert(getElement(5) == 36, ""); 49a07aba5dSTimm Baeder 50a07aba5dSTimm Baeder constexpr int data[] = {5, 4, 3, 2, 1}; 51a07aba5dSTimm Baeder constexpr int getElement(const int *Arr, int index) { 52a07aba5dSTimm Baeder return *(Arr + index); 53a07aba5dSTimm Baeder } 54a07aba5dSTimm Baeder 55a07aba5dSTimm Baeder constexpr int derefPtr(const int *d) { 56a07aba5dSTimm Baeder return *d; 57a07aba5dSTimm Baeder } 58a07aba5dSTimm Baeder static_assert(derefPtr(data) == 5, ""); 59a07aba5dSTimm Baeder 60a07aba5dSTimm Baeder /// Make sure we can refer to the one-past-the-end element 61a07aba5dSTimm Baeder /// and then return back to the end of the array. 62a07aba5dSTimm Baeder static_assert((&data[5])[-1] == 1, ""); 63a07aba5dSTimm Baeder 64a07aba5dSTimm Baeder constexpr int storePtr() { 65a07aba5dSTimm Baeder int b[] = {1,2,3,4}; 66a07aba5dSTimm Baeder int *c = b; 67a07aba5dSTimm Baeder 68a07aba5dSTimm Baeder *c = 4; 69a07aba5dSTimm Baeder return *c; 70a07aba5dSTimm Baeder } 71a07aba5dSTimm Baeder static_assert(storePtr() == 4, ""); 72a07aba5dSTimm Baeder 73a07aba5dSTimm Baeder 74a07aba5dSTimm Baeder static_assert(getElement(data, 1) == 4, ""); 75a07aba5dSTimm Baeder static_assert(getElement(data, 4) == 1, ""); 76a07aba5dSTimm Baeder 77a07aba5dSTimm Baeder constexpr int getElementFromEnd(const int *Arr, int size, int index) { 78a07aba5dSTimm Baeder return *(Arr + size - index - 1); 79a07aba5dSTimm Baeder } 80a07aba5dSTimm Baeder static_assert(getElementFromEnd(data, 5, 0) == 1, ""); 81a07aba5dSTimm Baeder static_assert(getElementFromEnd(data, 5, 4) == 5, ""); 82a07aba5dSTimm Baeder 83a07aba5dSTimm Baeder constexpr int getFirstElem(const int *a) { 84a07aba5dSTimm Baeder return a[0]; // both-note {{read of dereferenced null pointer}} 85a07aba5dSTimm Baeder } 86a07aba5dSTimm Baeder static_assert(getFirstElem(nullptr) == 1, ""); // both-error {{not an integral constant expression}} \ 87a07aba5dSTimm Baeder // both-note {{in call to}} 88a07aba5dSTimm Baeder 89a07aba5dSTimm Baeder constexpr static int arr[2] = {1,2}; 90a07aba5dSTimm Baeder constexpr static int arr2[2] = {3,4}; 91a07aba5dSTimm Baeder constexpr int *p1 = nullptr; 92a07aba5dSTimm Baeder constexpr int *p2 = p1 + 1; // both-error {{must be initialized by a constant expression}} \ 93a07aba5dSTimm Baeder // both-note {{cannot perform pointer arithmetic on null pointer}} 94a07aba5dSTimm Baeder constexpr int *p3 = p1 + 0; 95a07aba5dSTimm Baeder constexpr int *p4 = p1 - 0; 96a07aba5dSTimm Baeder constexpr int *p5 = 0 + p1; 97a07aba5dSTimm Baeder constexpr int *p6 = 0 - p1; // both-error {{invalid operands to binary expression}} 98a07aba5dSTimm Baeder 99a07aba5dSTimm Baeder constexpr int const * ap1 = &arr[0]; 100a07aba5dSTimm Baeder constexpr int const * ap2 = ap1 + 3; // both-error {{must be initialized by a constant expression}} \ 101a07aba5dSTimm Baeder // both-note {{cannot refer to element 3 of array of 2}} 102a07aba5dSTimm Baeder 103a07aba5dSTimm Baeder constexpr auto ap3 = arr - 1; // both-error {{must be initialized by a constant expression}} \ 104a07aba5dSTimm Baeder // both-note {{cannot refer to element -1}} 105a07aba5dSTimm Baeder constexpr int k1 = &arr[1] - &arr[0]; 106a07aba5dSTimm Baeder static_assert(k1 == 1, ""); 107a07aba5dSTimm Baeder static_assert((&arr[0] - &arr[1]) == -1, ""); 108a07aba5dSTimm Baeder 109a07aba5dSTimm Baeder constexpr int k2 = &arr2[1] - &arr[0]; // both-error {{must be initialized by a constant expression}} 110a07aba5dSTimm Baeder 111a07aba5dSTimm Baeder static_assert((arr + 0) == arr, ""); 112a07aba5dSTimm Baeder static_assert(&arr[0] == arr, ""); 113a07aba5dSTimm Baeder static_assert(*(&arr[0]) == 1, ""); 114a07aba5dSTimm Baeder static_assert(*(&arr[1]) == 2, ""); 115a07aba5dSTimm Baeder 116a07aba5dSTimm Baeder constexpr const int *OOB = (arr + 3) - 3; // both-error {{must be initialized by a constant expression}} \ 117a07aba5dSTimm Baeder // both-note {{cannot refer to element 3 of array of 2 elements}} 118a07aba5dSTimm Baeder 119a07aba5dSTimm Baeder template<typename T> 120a07aba5dSTimm Baeder constexpr T getElementOf(T* array, int i) { 121a07aba5dSTimm Baeder return array[i]; 122a07aba5dSTimm Baeder } 123a07aba5dSTimm Baeder static_assert(getElementOf(foo[0], 1) == &m, ""); 124a07aba5dSTimm Baeder 125a07aba5dSTimm Baeder 126a07aba5dSTimm Baeder template <typename T, int N> 127a07aba5dSTimm Baeder constexpr T& getElementOfArray(T (&array)[N], int I) { 128a07aba5dSTimm Baeder return array[I]; 129a07aba5dSTimm Baeder } 130a07aba5dSTimm Baeder static_assert(getElementOfArray(foo[2], 3) == &m, ""); 131a07aba5dSTimm Baeder 132a07aba5dSTimm Baeder 133a07aba5dSTimm Baeder static_assert(data[0] == 4, ""); // both-error{{failed}} \ 134a07aba5dSTimm Baeder // both-note{{5 == 4}} 135a07aba5dSTimm Baeder 136a07aba5dSTimm Baeder constexpr int dynamic[] = { 137a07aba5dSTimm Baeder f, 3, 2 + 5, data[3], *getElementOf(foo[2], 3) 138a07aba5dSTimm Baeder }; 139a07aba5dSTimm Baeder static_assert(dynamic[0] == f, ""); 140a07aba5dSTimm Baeder static_assert(dynamic[3] == 2, ""); 141a07aba5dSTimm Baeder 142a07aba5dSTimm Baeder 143a07aba5dSTimm Baeder constexpr int dependent[4] = { 144a07aba5dSTimm Baeder 0, 1, dependent[0], dependent[1] 145a07aba5dSTimm Baeder }; 146a07aba5dSTimm Baeder static_assert(dependent[2] == dependent[0], ""); 147a07aba5dSTimm Baeder static_assert(dependent[3] == dependent[1], ""); 148a07aba5dSTimm Baeder 149a07aba5dSTimm Baeder union { char x[]; } r = {0}; 150a07aba5dSTimm Baeder 151a07aba5dSTimm Baeder #pragma clang diagnostic push 152a07aba5dSTimm Baeder #pragma clang diagnostic ignored "-Wc99-extensions" 153a07aba5dSTimm Baeder #pragma clang diagnostic ignored "-Winitializer-overrides" 154a07aba5dSTimm Baeder constexpr int DI[] = { 155a07aba5dSTimm Baeder [0] = 10, 156a07aba5dSTimm Baeder [1] = 20, 157a07aba5dSTimm Baeder 30, 158a07aba5dSTimm Baeder 40, 159a07aba5dSTimm Baeder [1] = 50 160a07aba5dSTimm Baeder }; 161a07aba5dSTimm Baeder static_assert(DI[0] == 10, ""); 162a07aba5dSTimm Baeder static_assert(DI[1] == 50, ""); 163a07aba5dSTimm Baeder static_assert(DI[2] == 30, ""); 164a07aba5dSTimm Baeder static_assert(DI[3] == 40, ""); 165a07aba5dSTimm Baeder 166a07aba5dSTimm Baeder constexpr int addThreeElements(const int v[3]) { 167a07aba5dSTimm Baeder return v[0] + v[1] + v[2]; 168a07aba5dSTimm Baeder } 169a07aba5dSTimm Baeder constexpr int is[] = {10, 20, 30 }; 170a07aba5dSTimm Baeder static_assert(addThreeElements(is) == 60, ""); 171a07aba5dSTimm Baeder 172a07aba5dSTimm Baeder struct fred { 173a07aba5dSTimm Baeder char s [6]; 174a07aba5dSTimm Baeder int n; 175a07aba5dSTimm Baeder }; 176a07aba5dSTimm Baeder 177a07aba5dSTimm Baeder struct fred y [] = { [0] = { .s[0] = 'q' } }; 178a07aba5dSTimm Baeder #pragma clang diagnostic pop 179a07aba5dSTimm Baeder 180a07aba5dSTimm Baeder namespace indices { 181a07aba5dSTimm Baeder constexpr int first[] = {1}; 182a07aba5dSTimm Baeder constexpr int firstValue = first[2]; // both-error {{must be initialized by a constant expression}} \ 183a07aba5dSTimm Baeder // both-note {{cannot refer to element 2 of array of 1}} 184a07aba5dSTimm Baeder 185a07aba5dSTimm Baeder constexpr int second[10] = {17}; 186a07aba5dSTimm Baeder constexpr int secondValue = second[10];// both-error {{must be initialized by a constant expression}} \ 187a07aba5dSTimm Baeder // both-note {{read of dereferenced one-past-the-end pointer}} \ 188a07aba5dSTimm Baeder 189a07aba5dSTimm Baeder constexpr int negative = second[-2]; // both-error {{must be initialized by a constant expression}} \ 190a07aba5dSTimm Baeder // both-note {{cannot refer to element -2 of array of 10}} 191a07aba5dSTimm Baeder }; 192a07aba5dSTimm Baeder 193a07aba5dSTimm Baeder namespace DefaultInit { 194a07aba5dSTimm Baeder template <typename T, unsigned N> 195a07aba5dSTimm Baeder struct B { 196a07aba5dSTimm Baeder T a[N]; 197a07aba5dSTimm Baeder }; 198a07aba5dSTimm Baeder 199a07aba5dSTimm Baeder int f() { 200a07aba5dSTimm Baeder constexpr B<int,10> arr = {}; 201a07aba5dSTimm Baeder constexpr int x = arr.a[0]; 202a07aba5dSTimm Baeder } 203a07aba5dSTimm Baeder }; 204a07aba5dSTimm Baeder 205a07aba5dSTimm Baeder class A { 206a07aba5dSTimm Baeder public: 207a07aba5dSTimm Baeder int a; 208a07aba5dSTimm Baeder constexpr A(int m = 2) : a(10 + m) {} 209a07aba5dSTimm Baeder }; 210a07aba5dSTimm Baeder class AU { 211a07aba5dSTimm Baeder public: 212a07aba5dSTimm Baeder int a; 213a07aba5dSTimm Baeder constexpr AU() : a(5 / 0) {} // both-warning {{division by zero is undefined}} \ 214a07aba5dSTimm Baeder // both-note 2{{division by zero}} \ 215a07aba5dSTimm Baeder // both-error {{never produces a constant expression}} 216a07aba5dSTimm Baeder }; 217a07aba5dSTimm Baeder class B { 218a07aba5dSTimm Baeder public: 219a07aba5dSTimm Baeder A a[2]; 220a07aba5dSTimm Baeder constexpr B() {} 221a07aba5dSTimm Baeder }; 222a07aba5dSTimm Baeder constexpr B b; 223a07aba5dSTimm Baeder static_assert(b.a[0].a == 12, ""); 224a07aba5dSTimm Baeder static_assert(b.a[1].a == 12, ""); 225a07aba5dSTimm Baeder 226a07aba5dSTimm Baeder class BU { 227a07aba5dSTimm Baeder public: 228a07aba5dSTimm Baeder AU a[2]; 229a07aba5dSTimm Baeder constexpr BU() {} // both-note {{in call to 'AU()'}} 230a07aba5dSTimm Baeder }; 231a07aba5dSTimm Baeder constexpr BU bu; // both-error {{must be initialized by a constant expression}} \ 232a07aba5dSTimm Baeder // both-note {{in call to 'BU()'}} 233a07aba5dSTimm Baeder 234a07aba5dSTimm Baeder namespace IncDec { 235a07aba5dSTimm Baeder constexpr int getNextElem(const int *A, int I) { 236a07aba5dSTimm Baeder const int *B = (A + I); 237a07aba5dSTimm Baeder ++B; 238a07aba5dSTimm Baeder return *B; 239a07aba5dSTimm Baeder } 240a07aba5dSTimm Baeder constexpr int E[] = {1,2,3,4}; 241a07aba5dSTimm Baeder 242a07aba5dSTimm Baeder static_assert(getNextElem(E, 1) == 3, ""); 243a07aba5dSTimm Baeder 244a07aba5dSTimm Baeder constexpr int getFirst() { 245a07aba5dSTimm Baeder const int *e = E; 246a07aba5dSTimm Baeder return *(e++); 247a07aba5dSTimm Baeder } 248a07aba5dSTimm Baeder static_assert(getFirst() == 1, ""); 249a07aba5dSTimm Baeder 250a07aba5dSTimm Baeder constexpr int getFirst2() { 251a07aba5dSTimm Baeder const int *e = E; 252a07aba5dSTimm Baeder e++; 253a07aba5dSTimm Baeder return *e; 254a07aba5dSTimm Baeder } 255a07aba5dSTimm Baeder static_assert(getFirst2() == 2, ""); 256a07aba5dSTimm Baeder 257a07aba5dSTimm Baeder constexpr int getSecond() { 258a07aba5dSTimm Baeder const int *e = E; 259a07aba5dSTimm Baeder return *(++e); 260a07aba5dSTimm Baeder } 261a07aba5dSTimm Baeder static_assert(getSecond() == 2, ""); 262a07aba5dSTimm Baeder 263a07aba5dSTimm Baeder constexpr int getSecond2() { 264a07aba5dSTimm Baeder const int *e = E; 265a07aba5dSTimm Baeder ++e; 266a07aba5dSTimm Baeder return *e; 267a07aba5dSTimm Baeder } 268a07aba5dSTimm Baeder static_assert(getSecond2() == 2, ""); 269a07aba5dSTimm Baeder 270a07aba5dSTimm Baeder constexpr int getLast() { 271a07aba5dSTimm Baeder const int *e = E + 3; 272a07aba5dSTimm Baeder return *(e--); 273a07aba5dSTimm Baeder } 274a07aba5dSTimm Baeder static_assert(getLast() == 4, ""); 275a07aba5dSTimm Baeder 276a07aba5dSTimm Baeder constexpr int getLast2() { 277a07aba5dSTimm Baeder const int *e = E + 3; 278a07aba5dSTimm Baeder e--; 279a07aba5dSTimm Baeder return *e; 280a07aba5dSTimm Baeder } 281a07aba5dSTimm Baeder static_assert(getLast2() == 3, ""); 282a07aba5dSTimm Baeder 283a07aba5dSTimm Baeder constexpr int getSecondToLast() { 284a07aba5dSTimm Baeder const int *e = E + 3; 285a07aba5dSTimm Baeder return *(--e); 286a07aba5dSTimm Baeder } 287a07aba5dSTimm Baeder static_assert(getSecondToLast() == 3, ""); 288a07aba5dSTimm Baeder 289a07aba5dSTimm Baeder constexpr int getSecondToLast2() { 290a07aba5dSTimm Baeder const int *e = E + 3; 291a07aba5dSTimm Baeder --e; 292a07aba5dSTimm Baeder return *e; 293a07aba5dSTimm Baeder } 294a07aba5dSTimm Baeder static_assert(getSecondToLast2() == 3, ""); 295a07aba5dSTimm Baeder 296a07aba5dSTimm Baeder constexpr int bad1() { // both-error {{never produces a constant expression}} 297a07aba5dSTimm Baeder const int *e = E + 3; 298a07aba5dSTimm Baeder e++; // This is fine because it's a one-past-the-end pointer 299a07aba5dSTimm Baeder return *e; // both-note 2{{read of dereferenced one-past-the-end pointer}} 300a07aba5dSTimm Baeder } 301a07aba5dSTimm Baeder static_assert(bad1() == 0, ""); // both-error {{not an integral constant expression}} \ 302a07aba5dSTimm Baeder // both-note {{in call to}} 303a07aba5dSTimm Baeder 304a07aba5dSTimm Baeder constexpr int bad2() { // both-error {{never produces a constant expression}} 305a07aba5dSTimm Baeder const int *e = E + 4; 306a07aba5dSTimm Baeder e++; // both-note 2{{cannot refer to element 5 of array of 4 elements}} 307a07aba5dSTimm Baeder return *e; // This is UB as well 308a07aba5dSTimm Baeder } 309a07aba5dSTimm Baeder static_assert(bad2() == 0, ""); // both-error {{not an integral constant expression}} \ 310a07aba5dSTimm Baeder // both-note {{in call to}} 311a07aba5dSTimm Baeder 312a07aba5dSTimm Baeder constexpr int bad3() { // both-error {{never produces a constant expression}} 313a07aba5dSTimm Baeder const int *e = E; 314a07aba5dSTimm Baeder e--; // both-note 2{{cannot refer to element -1 of array of 4 elements}} 315a07aba5dSTimm Baeder return *e; // This is UB as well 316a07aba5dSTimm Baeder } 317a07aba5dSTimm Baeder static_assert(bad3() == 0, ""); // both-error {{not an integral constant expression}} \ 318a07aba5dSTimm Baeder // both-note {{in call to}} 319a07aba5dSTimm Baeder 320a07aba5dSTimm Baeder constexpr int nullptr1(bool Pre) { 321a07aba5dSTimm Baeder int *a = nullptr; 322a07aba5dSTimm Baeder if (Pre) 323a07aba5dSTimm Baeder ++a; // both-note {{arithmetic on null pointer}} 324a07aba5dSTimm Baeder else 325a07aba5dSTimm Baeder a++; // both-note {{arithmetic on null pointer}} 326a07aba5dSTimm Baeder return 1; 327a07aba5dSTimm Baeder } 328a07aba5dSTimm Baeder static_assert(nullptr1(true) == 1, ""); // both-error {{not an integral constant expression}} \ 329a07aba5dSTimm Baeder // both-note {{in call to}} 330a07aba5dSTimm Baeder 331a07aba5dSTimm Baeder static_assert(nullptr1(false) == 1, ""); // both-error {{not an integral constant expression}} \ 332a07aba5dSTimm Baeder // both-note {{in call to}} 333a07aba5dSTimm Baeder }; 334a07aba5dSTimm Baeder 335a07aba5dSTimm Baeder namespace ZeroInit { 336a07aba5dSTimm Baeder struct A { 337a07aba5dSTimm Baeder int *p[2]; 338a07aba5dSTimm Baeder }; 339a07aba5dSTimm Baeder constexpr A a = {}; 340a07aba5dSTimm Baeder static_assert(a.p[0] == nullptr, ""); 341a07aba5dSTimm Baeder static_assert(a.p[1] == nullptr, ""); 342a07aba5dSTimm Baeder 343a07aba5dSTimm Baeder struct B { 344a07aba5dSTimm Baeder double f[2]; 345a07aba5dSTimm Baeder }; 346a07aba5dSTimm Baeder constexpr B b = {}; 347a07aba5dSTimm Baeder static_assert(b.f[0] == 0.0, ""); 348a07aba5dSTimm Baeder static_assert(b.f[1] == 0.0, ""); 349a07aba5dSTimm Baeder } 350a07aba5dSTimm Baeder 351a07aba5dSTimm Baeder namespace ArrayInitLoop { 352a07aba5dSTimm Baeder struct X { 353a07aba5dSTimm Baeder int arr[3]; 354a07aba5dSTimm Baeder }; 355a07aba5dSTimm Baeder constexpr X f(int &r) { 356a07aba5dSTimm Baeder return {++r, ++r, ++r}; 357a07aba5dSTimm Baeder } 358a07aba5dSTimm Baeder constexpr int g() { 359a07aba5dSTimm Baeder int n = 0; 360a07aba5dSTimm Baeder auto [a, b, c] = f(n).arr; 361a07aba5dSTimm Baeder return a + b + c; 362a07aba5dSTimm Baeder } 363a07aba5dSTimm Baeder static_assert(g() == 6, ""); 364a07aba5dSTimm Baeder } 365a07aba5dSTimm Baeder 366a07aba5dSTimm Baeder namespace StringZeroFill { 367a07aba5dSTimm Baeder struct A { 368a07aba5dSTimm Baeder char c[6]; 369a07aba5dSTimm Baeder }; 370a07aba5dSTimm Baeder constexpr A a = { "abc" }; 371a07aba5dSTimm Baeder static_assert(a.c[0] == 'a', ""); 372a07aba5dSTimm Baeder static_assert(a.c[1] == 'b', ""); 373a07aba5dSTimm Baeder static_assert(a.c[2] == 'c', ""); 374a07aba5dSTimm Baeder static_assert(a.c[3] == '\0', ""); 375a07aba5dSTimm Baeder static_assert(a.c[4] == '\0', ""); 376a07aba5dSTimm Baeder static_assert(a.c[5] == '\0', ""); 377a07aba5dSTimm Baeder 378a07aba5dSTimm Baeder constexpr char b[6] = "foo"; 379a07aba5dSTimm Baeder static_assert(b[0] == 'f', ""); 380a07aba5dSTimm Baeder static_assert(b[1] == 'o', ""); 381a07aba5dSTimm Baeder static_assert(b[2] == 'o', ""); 382a07aba5dSTimm Baeder static_assert(b[3] == '\0', ""); 383a07aba5dSTimm Baeder static_assert(b[4] == '\0', ""); 384a07aba5dSTimm Baeder static_assert(b[5] == '\0', ""); 385a07aba5dSTimm Baeder } 386a07aba5dSTimm Baeder 387a07aba5dSTimm Baeder namespace NoInitMapLeak { 388a07aba5dSTimm Baeder #pragma clang diagnostic push 389a07aba5dSTimm Baeder #pragma clang diagnostic ignored "-Wdivision-by-zero" 390a07aba5dSTimm Baeder #pragma clang diagnostic ignored "-Wc++20-extensions" 391a07aba5dSTimm Baeder constexpr int testLeak() { // both-error {{never produces a constant expression}} 392a07aba5dSTimm Baeder int a[2]; 393a07aba5dSTimm Baeder a[0] = 1; 394a07aba5dSTimm Baeder // interrupts interpretation. 395a07aba5dSTimm Baeder (void)(1 / 0); // both-note 2{{division by zero}} 396a07aba5dSTimm Baeder 397a07aba5dSTimm Baeder return 1; 398a07aba5dSTimm Baeder } 399a07aba5dSTimm Baeder #pragma clang diagnostic pop 400a07aba5dSTimm Baeder static_assert(testLeak() == 1, ""); // both-error {{not an integral constant expression}} \ 401a07aba5dSTimm Baeder // both-note {{in call to 'testLeak()'}} 402a07aba5dSTimm Baeder 403a07aba5dSTimm Baeder constexpr int a[] = {1,2,3,4/0,5}; // both-error {{must be initialized by a constant expression}} \ 404a07aba5dSTimm Baeder // both-note {{division by zero}} \ 405*a0bd40e5STimm Bäder // ref-note {{declared here}} 406a07aba5dSTimm Baeder 407*a0bd40e5STimm Bäder /// FIXME: This should fail in the new interpreter as well. 408*a0bd40e5STimm Bäder constexpr int b = a[0]; // ref-error {{must be initialized by a constant expression}} \ 409*a0bd40e5STimm Bäder // ref-note {{is not a constant expression}} \ 410*a0bd40e5STimm Bäder // ref-note {{declared here}} 411*a0bd40e5STimm Bäder static_assert(b == 1, ""); // ref-error {{not an integral constant expression}} \ 412*a0bd40e5STimm Bäder // ref-note {{not a constant expression}} 413a07aba5dSTimm Baeder 414a07aba5dSTimm Baeder constexpr int f() { // both-error {{never produces a constant expression}} 415a07aba5dSTimm Baeder int a[] = {19,2,3/0,4}; // both-note 2{{division by zero}} \ 416a07aba5dSTimm Baeder // both-warning {{is undefined}} 417a07aba5dSTimm Baeder return 1; 418a07aba5dSTimm Baeder } 419a07aba5dSTimm Baeder static_assert(f() == 1, ""); // both-error {{not an integral constant expression}} \ 420a07aba5dSTimm Baeder // both-note {{in call to}} 421a07aba5dSTimm Baeder } 422a07aba5dSTimm Baeder 423a07aba5dSTimm Baeder namespace Incomplete { 424a07aba5dSTimm Baeder struct Foo { 425a07aba5dSTimm Baeder char c; 426a07aba5dSTimm Baeder int a[]; 427a07aba5dSTimm Baeder }; 428a07aba5dSTimm Baeder 429a07aba5dSTimm Baeder constexpr Foo F{}; 430a07aba5dSTimm Baeder constexpr const int *A = F.a; // both-error {{must be initialized by a constant expression}} \ 431a07aba5dSTimm Baeder // both-note {{array-to-pointer decay of array member without known bound}} 432a07aba5dSTimm Baeder 433a07aba5dSTimm Baeder constexpr const int *B = F.a + 1; // both-error {{must be initialized by a constant expression}} \ 434a07aba5dSTimm Baeder // both-note {{array-to-pointer decay of array member without known bound}} 435a07aba5dSTimm Baeder 436a07aba5dSTimm Baeder constexpr int C = *F.a; // both-error {{must be initialized by a constant expression}} \ 437a07aba5dSTimm Baeder // both-note {{array-to-pointer decay of array member without known bound}} 438a07aba5dSTimm Baeder 439f7a74eceSTimm Baeder struct X { 440f7a74eceSTimm Baeder int a; 441f7a74eceSTimm Baeder int b[]; 442f7a74eceSTimm Baeder }; 443f7a74eceSTimm Baeder extern X x; 444f7a74eceSTimm Baeder constexpr int *xb = x.b; // both-error {{must be initialized by a constant expression}} \ 445f7a74eceSTimm Baeder // both-note {{array-to-pointer decay of array member without known bound}} 446f7a74eceSTimm Baeder 447f7a74eceSTimm Baeder 448a07aba5dSTimm Baeder /// These are from test/SemaCXX/constant-expression-cxx11.cpp 449a07aba5dSTimm Baeder extern int arr[]; 450a07aba5dSTimm Baeder constexpr int *c = &arr[1]; // both-error {{must be initialized by a constant expression}} \ 451a07aba5dSTimm Baeder // both-note {{indexing of array without known bound}} 452a07aba5dSTimm Baeder constexpr int *d = &arr[1]; // both-error {{must be initialized by a constant expression}} \ 453a07aba5dSTimm Baeder // both-note {{indexing of array without known bound}} 454a07aba5dSTimm Baeder constexpr int *e = arr + 1; // both-error {{must be initialized by a constant expression}} \ 455a07aba5dSTimm Baeder // both-note {{indexing of array without known bound}} 456a07aba5dSTimm Baeder } 457a07aba5dSTimm Baeder 458a07aba5dSTimm Baeder namespace GH69115 { 459a07aba5dSTimm Baeder /// This used to crash because we were trying to emit destructors for the 460a07aba5dSTimm Baeder /// array. 461a07aba5dSTimm Baeder constexpr int foo() { 462a07aba5dSTimm Baeder int arr[2][2] = {1, 2, 3, 4}; 463a07aba5dSTimm Baeder return 0; 464a07aba5dSTimm Baeder } 465a07aba5dSTimm Baeder static_assert(foo() == 0, ""); 466a07aba5dSTimm Baeder 467a07aba5dSTimm Baeder /// Test that we still emit the destructors for multi-dimensional 468a07aba5dSTimm Baeder /// composite arrays. 469a07aba5dSTimm Baeder #if __cplusplus >= 202002L 470a07aba5dSTimm Baeder constexpr void assert(bool C) { 471a07aba5dSTimm Baeder if (C) 472a07aba5dSTimm Baeder return; 473a07aba5dSTimm Baeder // Invalid in constexpr. 474a07aba5dSTimm Baeder (void)(1 / 0); // both-warning {{undefined}} 475a07aba5dSTimm Baeder } 476a07aba5dSTimm Baeder 477a07aba5dSTimm Baeder class F { 478a07aba5dSTimm Baeder public: 479a07aba5dSTimm Baeder int a; 480a07aba5dSTimm Baeder int *dtor; 481a07aba5dSTimm Baeder int &idx; 482a07aba5dSTimm Baeder constexpr F(int a, int *dtor, int &idx) : a(a), dtor(dtor), idx(idx) {} 483a07aba5dSTimm Baeder constexpr ~F() noexcept(false){ 484a07aba5dSTimm Baeder dtor[idx] = a; 485a07aba5dSTimm Baeder ++idx; 486a07aba5dSTimm Baeder } 487a07aba5dSTimm Baeder }; 488a07aba5dSTimm Baeder constexpr int foo2() { 489a07aba5dSTimm Baeder int dtorIndices[] = {0, 0, 0, 0}; 490a07aba5dSTimm Baeder int idx = 0; 491a07aba5dSTimm Baeder 492a07aba5dSTimm Baeder { 493a07aba5dSTimm Baeder F arr[2][2] = {F(1, dtorIndices, idx), 494a07aba5dSTimm Baeder F(2, dtorIndices, idx), 495a07aba5dSTimm Baeder F(3, dtorIndices, idx), 496a07aba5dSTimm Baeder F(4, dtorIndices, idx)}; 497a07aba5dSTimm Baeder } 498a07aba5dSTimm Baeder 499a07aba5dSTimm Baeder /// Reverse-reverse order. 500a07aba5dSTimm Baeder assert(idx == 4); 501a07aba5dSTimm Baeder assert(dtorIndices[0] == 4); 502a07aba5dSTimm Baeder assert(dtorIndices[1] == 3); 503a07aba5dSTimm Baeder assert(dtorIndices[2] == 2); 504a07aba5dSTimm Baeder assert(dtorIndices[3] == 1); 505a07aba5dSTimm Baeder 506a07aba5dSTimm Baeder return 0; 507a07aba5dSTimm Baeder } 508a07aba5dSTimm Baeder static_assert(foo2() == 0, ""); 509a07aba5dSTimm Baeder #endif 510a07aba5dSTimm Baeder } 511a07aba5dSTimm Baeder 512a07aba5dSTimm Baeder namespace NonConstReads { 513a07aba5dSTimm Baeder #if __cplusplus >= 202002L 514a07aba5dSTimm Baeder void *p = nullptr; // both-note {{declared here}} 515a07aba5dSTimm Baeder 516a07aba5dSTimm Baeder int arr[!p]; // both-error {{not allowed at file scope}} \ 517a07aba5dSTimm Baeder // both-warning {{variable length arrays}} \ 518a07aba5dSTimm Baeder // both-note {{read of non-constexpr variable 'p'}} 519a07aba5dSTimm Baeder int z; // both-note {{declared here}} 520a07aba5dSTimm Baeder int a[z]; // both-error {{not allowed at file scope}} \ 521a07aba5dSTimm Baeder // both-warning {{variable length arrays}} \ 522a07aba5dSTimm Baeder // both-note {{read of non-const variable 'z'}} 523a07aba5dSTimm Baeder #else 524a07aba5dSTimm Baeder void *p = nullptr; 525a07aba5dSTimm Baeder int arr[!p]; // both-error {{not allowed at file scope}} 526a07aba5dSTimm Baeder int z; 527a07aba5dSTimm Baeder int a[z]; // both-error {{not allowed at file scope}} 528a07aba5dSTimm Baeder #endif 529a07aba5dSTimm Baeder 530a07aba5dSTimm Baeder const int y = 0; 531a07aba5dSTimm Baeder int yy[y]; 532a07aba5dSTimm Baeder } 533a07aba5dSTimm Baeder 534a07aba5dSTimm Baeder namespace SelfComparison { 535a07aba5dSTimm Baeder struct S { 536a07aba5dSTimm Baeder int field; 537a07aba5dSTimm Baeder static int static_field; 538a07aba5dSTimm Baeder int array[4]; 539a07aba5dSTimm Baeder }; 540a07aba5dSTimm Baeder 541a07aba5dSTimm Baeder struct T { 542a07aba5dSTimm Baeder int field; 543a07aba5dSTimm Baeder static int static_field; 544a07aba5dSTimm Baeder int array[4]; 545a07aba5dSTimm Baeder S s; 546a07aba5dSTimm Baeder }; 547a07aba5dSTimm Baeder 548a07aba5dSTimm Baeder int struct_test(S s1, S s2, S *s3, T t) { 549a07aba5dSTimm Baeder return s3->array[t.field] == s3->array[t.field]; // both-warning {{self-comparison always evaluates to true}} 550a07aba5dSTimm Baeder }; 551a07aba5dSTimm Baeder } 552a07aba5dSTimm Baeder 553a07aba5dSTimm Baeder namespace LocalIndex { 554a07aba5dSTimm Baeder void test() { 555a07aba5dSTimm Baeder const int const_subscript = 3; 556a07aba5dSTimm Baeder int array[2]; // both-note {{declared here}} 557a07aba5dSTimm Baeder array[const_subscript] = 0; // both-warning {{array index 3 is past the end of the array (that has type 'int[2]')}} 558a07aba5dSTimm Baeder } 559a07aba5dSTimm Baeder } 560a07aba5dSTimm Baeder 561a07aba5dSTimm Baeder namespace LocalVLA { 562a07aba5dSTimm Baeder struct Foo { 563a07aba5dSTimm Baeder int x; 564a07aba5dSTimm Baeder Foo(int x) : x(x) {} 565a07aba5dSTimm Baeder }; 566a07aba5dSTimm Baeder struct Elidable { 567a07aba5dSTimm Baeder Elidable(); 568a07aba5dSTimm Baeder }; 569a07aba5dSTimm Baeder 570a07aba5dSTimm Baeder void foo(int size) { 571a07aba5dSTimm Baeder Elidable elidableDynArray[size]; 572a07aba5dSTimm Baeder #if __cplusplus >= 202002L 573a07aba5dSTimm Baeder // both-note@-3 {{declared here}} 574a07aba5dSTimm Baeder // both-warning@-3 {{variable length array}} 575a07aba5dSTimm Baeder // both-note@-4 {{function parameter 'size' with unknown value}} 576a07aba5dSTimm Baeder #endif 577a07aba5dSTimm Baeder } 578a07aba5dSTimm Baeder 579a07aba5dSTimm Baeder void f (unsigned int m) { 580a07aba5dSTimm Baeder int e[2][m]; 581a07aba5dSTimm Baeder #if __cplusplus >= 202002L 582a07aba5dSTimm Baeder // both-note@-3 {{declared here}} 583a07aba5dSTimm Baeder // both-warning@-3 2{{variable length array}} 584a07aba5dSTimm Baeder // both-note@-4 {{function parameter 'm' with unknown value}} 585a07aba5dSTimm Baeder #endif 586a07aba5dSTimm Baeder e[0][0] = 0; 587a07aba5dSTimm Baeder } 588a07aba5dSTimm Baeder } 589a07aba5dSTimm Baeder 590a07aba5dSTimm Baeder char melchizedek[2]; 591a07aba5dSTimm Baeder typedef decltype(melchizedek[1] - melchizedek[0]) ptrdiff_t; 592a07aba5dSTimm Baeder constexpr ptrdiff_t d1 = &melchizedek[1] - &melchizedek[0]; // ok 593a07aba5dSTimm Baeder constexpr ptrdiff_t d3 = &melchizedek[0] - &melchizedek[1]; // ok 594a07aba5dSTimm Baeder 595a07aba5dSTimm Baeder /// GH#88018 596a07aba5dSTimm Baeder const int SZA[] = {}; 597a07aba5dSTimm Baeder void testZeroSizedArrayAccess() { unsigned c = SZA[4]; } 598a07aba5dSTimm Baeder 599a07aba5dSTimm Baeder #if __cplusplus >= 202002L 600a07aba5dSTimm Baeder constexpr int test_multiarray2() { // both-error {{never produces a constant expression}} 601a07aba5dSTimm Baeder int multi2[2][1]; // both-note {{declared here}} 602a07aba5dSTimm Baeder return multi2[2][0]; // both-note {{cannot access array element of pointer past the end of object}} \ 603a07aba5dSTimm Baeder // both-warning {{array index 2 is past the end of the array (that has type 'int[2][1]')}} 604a07aba5dSTimm Baeder } 605a07aba5dSTimm Baeder 606a07aba5dSTimm Baeder /// Same but with a dummy pointer. 607a07aba5dSTimm Baeder int multi22[2][2]; // both-note {{declared here}} 608a07aba5dSTimm Baeder int test_multiarray22() { 609a07aba5dSTimm Baeder return multi22[2][0]; // both-warning {{array index 2 is past the end of the array (that has type 'int[2][2]')}} 610a07aba5dSTimm Baeder } 611a07aba5dSTimm Baeder 612a07aba5dSTimm Baeder #endif 613a07aba5dSTimm Baeder 614a07aba5dSTimm Baeder namespace ArrayMemberAccess { 615a07aba5dSTimm Baeder struct A { 616a07aba5dSTimm Baeder int x; 617a07aba5dSTimm Baeder }; 618a07aba5dSTimm Baeder void f(const A (&a)[]) { 619a07aba5dSTimm Baeder bool cond = a->x; 620a07aba5dSTimm Baeder } 621a07aba5dSTimm Baeder } 622a07aba5dSTimm Baeder 623a07aba5dSTimm Baeder namespace OnePastEndSub { 624a07aba5dSTimm Baeder struct A {}; 625a07aba5dSTimm Baeder constexpr A a[3][3]; 626a07aba5dSTimm Baeder constexpr int diff2 = &a[1][3] - &a[1][0]; /// Used to crash. 627a07aba5dSTimm Baeder } 628a07aba5dSTimm Baeder 629a07aba5dSTimm Baeder static int same_entity_2[3]; 630a07aba5dSTimm Baeder constexpr int *get2() { 631a07aba5dSTimm Baeder // This is a redeclaration of the same entity, even though it doesn't 632a07aba5dSTimm Baeder // inherit the type of the prior declaration. 633a07aba5dSTimm Baeder extern int same_entity_2[]; 634a07aba5dSTimm Baeder return same_entity_2; 635a07aba5dSTimm Baeder } 636a07aba5dSTimm Baeder static_assert(get2() == same_entity_2, "failed to find previous decl"); 637a07aba5dSTimm Baeder 638a07aba5dSTimm Baeder constexpr int zs[2][2][2][2] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 }; 639a07aba5dSTimm Baeder constexpr int fail(const int &p) { 640a07aba5dSTimm Baeder return (&p)[64]; // both-note {{cannot refer to element 64 of array of 2 elements}} 641a07aba5dSTimm Baeder } 642a07aba5dSTimm Baeder static_assert(fail(*(&(&(*(*&(&zs[2] - 1)[0] + 2 - 2))[2])[-1][2] - 2)) == 11, ""); // both-error {{not an integral constant expression}} \ 643a07aba5dSTimm Baeder // both-note {{in call to}} 644a07aba5dSTimm Baeder 645a07aba5dSTimm Baeder namespace ZeroSizeTypes { 646a07aba5dSTimm Baeder constexpr int (*p1)[0] = 0, (*p2)[0] = 0; 647a07aba5dSTimm Baeder constexpr int k = p2 - p1; // both-error {{constexpr variable 'k' must be initialized by a constant expression}} \ 648a07aba5dSTimm Baeder // both-note {{subtraction of pointers to type 'int[0]' of zero size}} \ 649a07aba5dSTimm Baeder // both-warning {{subtraction of pointers to type 'int[0]' of zero size has undefined behavior}} 650a07aba5dSTimm Baeder 651a07aba5dSTimm Baeder int arr[5][0]; 652a07aba5dSTimm Baeder constexpr int f() { // both-error {{never produces a constant expression}} 653a07aba5dSTimm Baeder return &arr[3] - &arr[0]; // both-note {{subtraction of pointers to type 'int[0]' of zero size}} \ 654a07aba5dSTimm Baeder // both-warning {{subtraction of pointers to type 'int[0]' of zero size has undefined behavior}} 655a07aba5dSTimm Baeder } 656a07aba5dSTimm Baeder } 657