xref: /llvm-project/clang/test/AST/ByteCode/arrays.cpp (revision a0bd40e5a3df94229ec06243f2958289071ca75c)
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