[clang] Implement lifetime analysis for lifetime_capture_by(X) (#115921)
[llvm-project.git] / clang / test / AST / ByteCode / new-delete.cpp
blob8466e9b88782f2026321ae6e05ca39b2b01a082b
1 // RUN: %clang_cc1 -fexperimental-new-constant-interpreter -verify=expected,both %s
2 // RUN: %clang_cc1 -std=c++20 -fexperimental-new-constant-interpreter -verify=expected,both %s
3 // RUN: %clang_cc1 -triple=i686-linux-gnu -std=c++20 -fexperimental-new-constant-interpreter -verify=expected,both %s
4 // RUN: %clang_cc1 -verify=ref,both %s
5 // RUN: %clang_cc1 -std=c++20 -verify=ref,both %s
6 // RUN: %clang_cc1 -triple=i686-linux-gnu -std=c++20 -verify=ref,both %s
8 #if __cplusplus >= 202002L
10 constexpr int *Global = new int(12); // both-error {{must be initialized by a constant expression}} \
11 // both-note {{pointer to heap-allocated object}} \
12 // both-note {{heap allocation performed here}}
14 static_assert(*(new int(12)) == 12); // both-error {{not an integral constant expression}} \
15 // both-note {{allocation performed here was not deallocated}}
18 constexpr int a() {
19 new int(12); // both-note {{allocation performed here was not deallocated}}
20 return 1;
22 static_assert(a() == 1, ""); // both-error {{not an integral constant expression}}
24 constexpr int b() {
25 int *i = new int(12);
26 int m = *i;
27 delete(i);
28 return m;
30 static_assert(b() == 12, "");
33 struct S {
34 int a;
35 int b;
37 static constexpr S *create(int a, int b) {
38 return new S(a, b);
42 constexpr int c() {
43 S *s = new S(12, 13);
45 int i = s->a;
46 delete s;
48 return i;
50 static_assert(c() == 12, "");
52 /// Dynamic allocation in function ::create(), freed in function d().
53 constexpr int d() {
54 S* s = S::create(12, 14);
56 int sum = s->a + s->b;
57 delete s;
58 return sum;
60 static_assert(d() == 26);
63 /// Test we emit the right diagnostic for several allocations done on
64 /// the same site.
65 constexpr int loop() {
66 for (int i = 0; i < 10; ++i) {
67 int *a = new int[10]; // both-note {{not deallocated (along with 9 other memory leaks)}}
70 return 1;
72 static_assert(loop() == 1, ""); // both-error {{not an integral constant expression}}
74 /// No initializer.
75 constexpr int noInit() {
76 int *i = new int;
77 delete i;
78 return 0;
80 static_assert(noInit() == 0, "");
82 /// Try to delete a pointer that hasn't been heap allocated.
83 constexpr int notHeapAllocated() { // both-error {{never produces a constant expression}}
84 int A = 0; // both-note 2{{declared here}}
85 delete &A; // ref-note 2{{delete of pointer '&A' that does not point to a heap-allocated object}} \
86 // expected-note 2{{delete of pointer '&A' that does not point to a heap-allocated object}}
88 return 1;
90 static_assert(notHeapAllocated() == 1, ""); // both-error {{not an integral constant expression}} \
91 // both-note {{in call to 'notHeapAllocated()'}}
93 consteval int deleteNull() {
94 int *A = nullptr;
95 delete A;
96 return 1;
98 static_assert(deleteNull() == 1, "");
100 consteval int doubleDelete() { // both-error {{never produces a constant expression}}
101 int *A = new int;
102 delete A;
103 delete A; // both-note 2{{delete of pointer that has already been deleted}}
104 return 1;
106 static_assert(doubleDelete() == 1); // both-error {{not an integral constant expression}} \
107 // both-note {{in call to 'doubleDelete()'}}
109 constexpr int AutoArray() {
110 auto array = new int[]{0, 1, 2, 3};
111 int ret = array[3];
112 delete [] array;
113 return ret;
116 static_assert(AutoArray() == 3);
118 #if 0
119 consteval int largeArray1(bool b) {
120 if (b) {
121 int *a = new int[1ull<<32]; // both-note {{cannot allocate array; evaluated array bound 4294967296 is too large}}
122 delete[] a;
124 return 1;
126 static_assert(largeArray1(false) == 1, "");
127 static_assert(largeArray1(true) == 1, ""); // both-error {{not an integral constant expression}} \
128 // both-note {{in call to 'largeArray1(true)'}}
130 consteval int largeArray2(bool b) {
131 if (b) {
132 S *a = new S[1ull<<32]; // both-note {{cannot allocate array; evaluated array bound 4294967296 is too large}}
133 delete[] a;
135 return 1;
137 static_assert(largeArray2(false) == 1, "");
138 static_assert(largeArray2(true) == 1, ""); // both-error {{not an integral constant expression}} \
139 // both-note {{in call to 'largeArray2(true)'}}
140 #endif
141 namespace Arrays {
142 constexpr int d() {
143 int *Arr = new int[12];
145 Arr[0] = 1;
146 Arr[1] = 5;
148 int sum = Arr[0] + Arr[1];
149 delete[] Arr;
150 return sum;
152 static_assert(d() == 6);
155 constexpr int mismatch1() { // both-error {{never produces a constant expression}}
156 int *i = new int(12); // both-note {{allocated with 'new' here}} \
157 // both-note 2{{heap allocation performed here}}
158 delete[] i; // both-warning {{'delete[]' applied to a pointer that was allocated with 'new'}} \
159 // both-note 2{{array delete used to delete pointer to non-array object of type 'int'}}
160 return 6;
162 static_assert(mismatch1() == 6); // both-error {{not an integral constant expression}} \
163 // both-note {{in call to 'mismatch1()'}}
165 constexpr int mismatch2() { // both-error {{never produces a constant expression}}
166 int *i = new int[12]; // both-note {{allocated with 'new[]' here}} \
167 // both-note 2{{heap allocation performed here}}
168 delete i; // both-warning {{'delete' applied to a pointer that was allocated with 'new[]'}} \
169 // both-note 2{{non-array delete used to delete pointer to array object of type 'int[12]'}}
170 return 6;
172 static_assert(mismatch2() == 6); // both-error {{not an integral constant expression}} \
173 // both-note {{in call to 'mismatch2()'}}
174 /// Array of composite elements.
175 constexpr int foo() {
176 S *ss = new S[12];
178 ss[0].a = 12;
180 int m = ss[0].a;
182 delete[] ss;
183 return m;
185 static_assert(foo() == 12);
189 constexpr int ArrayInit() {
190 auto array = new int[4]{0, 1, 2, 3};
191 int ret = array[0];
192 delete [] array;
193 return ret;
195 static_assert(ArrayInit() == 0, "");
197 struct S {
198 float F;
200 constexpr float ArrayInit2() {
201 auto array = new S[4]{};
202 float ret = array[0].F;
203 delete [] array;
204 return ret;
206 static_assert(ArrayInit2() == 0.0f, "");
209 namespace std {
210 struct type_info;
211 struct destroying_delete_t {
212 explicit destroying_delete_t() = default;
213 } inline constexpr destroying_delete{};
214 struct nothrow_t {
215 explicit nothrow_t() = default;
216 } inline constexpr nothrow{};
217 using size_t = decltype(sizeof(0));
218 enum class align_val_t : size_t {};
221 [[nodiscard]] void *operator new(std::size_t, const std::nothrow_t&) noexcept;
222 [[nodiscard]] void *operator new(std::size_t, std::align_val_t, const std::nothrow_t&) noexcept;
223 [[nodiscard]] void *operator new[](std::size_t, const std::nothrow_t&) noexcept;
224 [[nodiscard]] void *operator new[](std::size_t, std::align_val_t, const std::nothrow_t&) noexcept;
225 [[nodiscard]] void *operator new[](std::size_t, std::align_val_t);
226 void operator delete(void*, const std::nothrow_t&) noexcept;
227 void operator delete(void*, std::align_val_t, const std::nothrow_t&) noexcept;
228 void operator delete[](void*, const std::nothrow_t&) noexcept;
229 void operator delete[](void*, std::align_val_t, const std::nothrow_t&) noexcept;
231 struct placement_new_arg {};
232 void *operator new(std::size_t, placement_new_arg);
233 void operator delete(void*, placement_new_arg);
236 constexpr void *operator new(std::size_t, void *p) { return p; }
237 namespace std {
238 template<typename T> constexpr T *construct(T *p) { return new (p) T; }
239 template<typename T> constexpr void destroy(T *p) { p->~T(); }
244 namespace PlacementNew {
245 constexpr int foo() { // both-error {{never produces a constant expression}}
246 char c[sizeof(int)];
247 new (c) int{12}; // both-note {{this placement new expression is not supported in constant expressions before C++2c}}
248 return 0;
252 namespace NowThrowNew {
253 constexpr bool erroneous_array_bound_nothrow(long long n) {
254 int *p = new (std::nothrow) int[n];
255 bool result = p != nullptr;
256 delete[] p;
257 return result;
259 static_assert(erroneous_array_bound_nothrow(3));
260 static_assert(erroneous_array_bound_nothrow(0));
261 static_assert(erroneous_array_bound_nothrow(-1) == 0);
262 static_assert(!erroneous_array_bound_nothrow(1LL << 62));
264 struct S { int a; };
265 constexpr bool erroneous_array_bound_nothrow2(long long n) {
266 S *p = new (std::nothrow) S[n];
267 bool result = p != nullptr;
268 delete[] p;
269 return result;
271 /// This needs support for CXXConstrucExprs with non-constant array sizes.
272 static_assert(erroneous_array_bound_nothrow2(3)); // expected-error {{not an integral constant expression}}
273 static_assert(erroneous_array_bound_nothrow2(0));// expected-error {{not an integral constant expression}}
274 static_assert(erroneous_array_bound_nothrow2(-1) == 0);// expected-error {{not an integral constant expression}}
275 static_assert(!erroneous_array_bound_nothrow2(1LL << 62));// expected-error {{not an integral constant expression}}
277 constexpr bool erroneous_array_bound(long long n) {
278 delete[] new int[n]; // both-note {{array bound -1 is negative}} both-note {{array bound 4611686018427387904 is too large}}
279 return true;
281 static_assert(erroneous_array_bound(3));
282 static_assert(erroneous_array_bound(0));
283 static_assert(erroneous_array_bound(-1)); // both-error {{constant expression}} both-note {{in call}}
284 static_assert(erroneous_array_bound(1LL << 62)); // both-error {{constant expression}} both-note {{in call}}
286 constexpr bool evaluate_nothrow_arg() {
287 bool ok = false;
288 delete new ((ok = true, std::nothrow)) int;
289 return ok;
291 static_assert(evaluate_nothrow_arg());
294 namespace placement_new_delete {
295 struct ClassSpecificNew {
296 void *operator new(std::size_t);
298 struct ClassSpecificDelete {
299 void operator delete(void*);
301 struct DestroyingDelete {
302 void operator delete(DestroyingDelete*, std::destroying_delete_t);
304 struct alignas(64) Overaligned {};
306 constexpr bool ok() {
307 delete new Overaligned;
308 delete ::new ClassSpecificNew;
309 ::delete new ClassSpecificDelete;
310 ::delete new DestroyingDelete;
311 return true;
313 static_assert(ok());
315 constexpr bool bad(int which) {
316 switch (which) {
317 case 0:
318 delete new (placement_new_arg{}) int; // both-note {{this placement new expression is not supported in constant expressions}}
319 break;
321 case 1:
322 delete new ClassSpecificNew; // both-note {{call to class-specific 'operator new'}}
323 break;
325 case 2:
326 delete new ClassSpecificDelete; // both-note {{call to class-specific 'operator delete'}}
327 break;
329 case 3:
330 delete new DestroyingDelete; // both-note {{call to class-specific 'operator delete'}}
331 break;
333 case 4:
334 // FIXME: This technically follows the standard's rules, but it seems
335 // unreasonable to expect implementations to support this.
336 delete new (std::align_val_t{64}) Overaligned; // both-note {{this placement new expression is not supported in constant expressions}}
337 break;
340 return true;
342 static_assert(bad(0)); // both-error {{constant expression}} \
343 // both-note {{in call}}
344 static_assert(bad(1)); // both-error {{constant expression}} both-note {{in call}}
345 static_assert(bad(2)); // both-error {{constant expression}} both-note {{in call}}
346 static_assert(bad(3)); // both-error {{constant expression}} both-note {{in call}}
347 static_assert(bad(4)); // both-error {{constant expression}} \
348 // both-note {{in call}}
354 namespace delete_random_things {
355 static_assert((delete new int, true));
356 static_assert((delete (int*)0, true));
357 int n; // both-note {{declared here}}
358 static_assert((delete &n, true)); // both-error {{}} \
359 // both-note {{delete of pointer '&n' that does not point to a heap-allocated object}}
360 struct A { int n; };
361 static_assert((delete &(new A)->n, true)); // both-error {{}} \
362 // both-note {{delete of pointer to subobject }}
363 static_assert((delete (new int + 1), true)); // both-error {{}} \
364 // ref-note {{delete of pointer '&{*new int#0} + 1' that does not point to complete object}} \
365 // expected-note {{delete of pointer '&{*new int#1} + 1' that does not point to complete object}}
366 static_assert((delete[] (new int[3] + 1), true)); // both-error {{}} \
367 // both-note {{delete of pointer to subobject}}
368 static_assert((delete &(int&)(int&&)0, true)); // both-error {{}} \
369 // both-note {{delete of pointer '&0' that does not point to a heap-allocated object}} \
370 // both-note {{temporary created here}}
373 namespace value_dependent_delete {
374 template<typename T> void f(T *p) {
375 int arr[(delete p, 0)];
379 namespace memory_leaks {
380 static_assert(*new bool(true)); // both-error {{}} both-note {{allocation performed here was not deallocated}}
382 constexpr bool *f() { return new bool(true); } // both-note {{allocation performed here was not deallocated}}
383 static_assert(*f()); // both-error {{}}
385 struct UP {
386 bool *p;
387 constexpr ~UP() { delete p; }
388 constexpr bool &operator*() { return *p; }
390 constexpr UP g() { return {new bool(true)}; }
391 static_assert(*g()); // ok
393 constexpr bool h(UP p) { return *p; }
394 static_assert(h({new bool(true)})); // ok
397 /// From test/SemaCXX/cxx2a-consteval.cpp
399 namespace std {
400 template <typename T> struct remove_reference { using type = T; };
401 template <typename T> struct remove_reference<T &> { using type = T; };
402 template <typename T> struct remove_reference<T &&> { using type = T; };
403 template <typename T>
404 constexpr typename std::remove_reference<T>::type&& move(T &&t) noexcept {
405 return static_cast<typename std::remove_reference<T>::type &&>(t);
409 namespace cxx2a {
410 struct A {
411 int* p = new int(42); // both-note 3{{heap allocation performed here}}
412 consteval int ret_i() const { return p ? *p : 0; }
413 consteval A ret_a() const { return A{}; }
414 constexpr ~A() { delete p; }
417 consteval int by_value_a(A a) { return a.ret_i(); }
419 consteval int const_a_ref(const A &a) {
420 return a.ret_i();
423 consteval int rvalue_ref(const A &&a) {
424 return a.ret_i();
427 consteval const A &to_lvalue_ref(const A &&a) {
428 return a;
431 void test() {
432 constexpr A a{ nullptr };
433 { int k = A().ret_i(); }
435 { A k = A().ret_a(); } // both-error {{'cxx2a::A::ret_a' is not a constant expression}} \
436 // both-note {{heap-allocated object is not a constant expression}}
437 { A k = to_lvalue_ref(A()); } // both-error {{'cxx2a::to_lvalue_ref' is not a constant expression}} \
438 // both-note {{reference to temporary is not a constant expression}} \
439 // both-note {{temporary created here}}
440 { A k = to_lvalue_ref(A().ret_a()); } // both-error {{'cxx2a::to_lvalue_ref' is not a constant expression}} \
441 // both-note {{reference to temporary is not a constant expression}} \
442 // both-note {{temporary created here}}
443 { int k = A().ret_a().ret_i(); } // both-error {{'cxx2a::A::ret_a' is not a constant expression}} \
444 // both-note {{heap-allocated object is not a constant expression}}
445 { int k = by_value_a(A()); }
446 { int k = const_a_ref(A()); }
447 { int k = const_a_ref(a); }
448 { int k = rvalue_ref(A()); }
449 { int k = rvalue_ref(std::move(a)); }
450 { int k = const_a_ref(A().ret_a()); }
451 { int k = const_a_ref(to_lvalue_ref(A().ret_a())); }
452 { int k = const_a_ref(to_lvalue_ref(std::move(a))); }
453 { int k = by_value_a(A().ret_a()); }
454 { int k = by_value_a(to_lvalue_ref(static_cast<const A&&>(a))); }
455 { int k = (A().ret_a(), A().ret_i()); } // both-error {{'cxx2a::A::ret_a' is not a constant expression}} \
456 // both-note {{is not a constant expression}} \
457 // both-warning {{left operand of comma operator has no effect}}
458 { int k = (const_a_ref(A().ret_a()), A().ret_i()); } // both-warning {{left operand of comma operator has no effect}}
462 constexpr int *const &p = new int; // both-error {{must be initialized by a constant expression}} \
463 // both-note {{pointer to heap-allocated object}} \
464 // both-note {{allocation performed here}}
466 constexpr const int *A[] = {nullptr, nullptr, new int{12}}; // both-error {{must be initialized by a constant expression}} \
467 // both-note {{pointer to heap-allocated object}} \
468 // both-note {{allocation performed here}}
470 struct Sp {
471 const int *p;
473 constexpr Sp ss[] = {Sp{new int{154}}}; // both-error {{must be initialized by a constant expression}} \
474 // both-note {{pointer to heap-allocated object}} \
475 // both-note {{allocation performed here}}
477 namespace DeleteRunsDtors {
478 struct InnerFoo {
479 int *mem;
480 constexpr ~InnerFoo() {
481 delete mem;
485 struct Foo {
486 int *a;
487 InnerFoo IF;
489 constexpr Foo() {
490 a = new int(13);
491 IF.mem = new int(100);
493 constexpr ~Foo() { delete a; }
496 constexpr int abc() {
497 Foo *F = new Foo();
498 int n = *F->a;
499 delete F;
501 return n;
503 static_assert(abc() == 13);
505 constexpr int abc2() {
506 Foo *f = new Foo[3];
508 delete[] f;
510 return 1;
512 static_assert(abc2() == 1);
515 /// FIXME: There is a slight difference in diagnostics here.
516 namespace FaultyDtorCalledByDelete {
517 struct InnerFoo {
518 int *mem;
519 constexpr ~InnerFoo() {
520 if (mem) {
521 (void)(1/0); // both-warning {{division by zero is undefined}} \
522 // both-note {{division by zero}}
524 delete mem;
528 struct Foo {
529 int *a;
530 InnerFoo IF;
532 constexpr Foo() {
533 a = new int(13);
534 IF.mem = new int(100);
536 constexpr ~Foo() { delete a; } // expected-note {{in call to}}
539 constexpr int abc() {
540 Foo *F = new Foo();
541 int n = *F->a;
542 delete F; // both-note {{in call to}} \
543 // ref-note {{in call to}}
545 return n;
547 static_assert(abc() == 13); // both-error {{not an integral constant expression}} \
548 // both-note {{in call to 'abc()'}}
551 namespace DeleteThis {
552 constexpr bool super_secret_double_delete() {
553 struct A {
554 constexpr ~A() { delete this; } // both-note {{destruction of object that is already being destroyed}} \
555 // ref-note {{in call to}}
557 delete new A; // both-note {{in call to}}
558 return true;
560 static_assert(super_secret_double_delete()); // both-error {{not an integral constant expression}} \
561 // both-note {{in call to 'super_secret_double_delete()'}}
564 namespace CastedDelete {
565 struct S {
566 constexpr S(int *p) : p(p) {}
567 constexpr virtual ~S() { *p = 1; }
568 int *p;
570 struct T: S {
571 // implicit destructor defined eagerly because it is constexpr and virtual
572 using S::S;
575 constexpr int vdtor_1() {
576 int a;
577 delete (S*)new T(&a);
578 return a;
580 static_assert(vdtor_1() == 1);
582 constexpr int foo() { // both-error {{never produces a constant expression}}
583 struct S {};
584 struct T : S {};
585 S *p = new T();
586 delete p; // both-note 2{{delete of object with dynamic type 'T' through pointer to base class type 'S' with non-virtual destructor}}
587 return 1;
589 static_assert(foo() == 1); // both-error {{not an integral constant expression}} \
590 // both-note {{in call to}}
593 constexpr void use_after_free_2() { // both-error {{never produces a constant expression}}
594 struct X { constexpr void f() {} };
595 X *p = new X;
596 delete p;
597 p->f(); // both-note {{member call on heap allocated object that has been deleted}}
600 /// std::allocator definition
601 namespace std {
602 using size_t = decltype(sizeof(0));
603 template<typename T> struct allocator {
604 constexpr T *allocate(size_t N) {
605 return (T*)__builtin_operator_new(sizeof(T) * N); // both-note 2{{allocation performed here}} \
606 // #alloc
608 constexpr void deallocate(void *p) {
609 __builtin_operator_delete(p); // both-note 2{{std::allocator<...>::deallocate' used to delete pointer to object allocated with 'new'}} \
610 // both-note {{used to delete a null pointer}}
613 template<typename T, typename ...Args>
614 constexpr void construct_at(void *p, Args &&...args) { // #construct
615 new (p) T((Args&&)args...);
619 /// Specialization for float, using operator new/delete.
620 namespace std {
621 using size_t = decltype(sizeof(0));
622 template<> struct allocator<float> {
623 constexpr float *allocate(size_t N) {
624 return (float*)operator new (sizeof(float) * N);
626 constexpr void deallocate(void *p) {
627 operator delete(p);
632 namespace OperatorNewDelete {
634 constexpr bool mismatched(int alloc_kind, int dealloc_kind) {
635 int *p;
636 switch (alloc_kind) {
637 case 0:
638 p = new int; // both-note {{heap allocation performed here}}
639 break;
640 case 1:
641 p = new int[1]; // both-note {{heap allocation performed here}}
642 break;
643 case 2:
644 p = std::allocator<int>().allocate(1);
645 break;
647 switch (dealloc_kind) {
648 case 0:
649 delete p; // both-note {{'delete' used to delete pointer to object allocated with 'std::allocator<...>::allocate'}}
650 break;
651 case 1:
652 delete[] p; // both-note {{'delete' used to delete pointer to object allocated with 'std::allocator<...>::allocate'}}
653 break;
654 case 2:
655 std::allocator<int>().deallocate(p); // both-note 2{{in call}}
656 break;
658 return true;
660 static_assert(mismatched(0, 2)); // both-error {{constant expression}} \
661 // both-note {{in call to}}
662 static_assert(mismatched(1, 2)); // both-error {{constant expression}} \
663 // both-note {{in call to}}
664 static_assert(mismatched(2, 0)); // both-error {{constant expression}} \
665 // both-note {{in call}}
666 static_assert(mismatched(2, 1)); // both-error {{constant expression}} \
667 // both-note {{in call}}
668 static_assert(mismatched(2, 2));
670 constexpr bool zeroAlloc() {
671 int *F = std::allocator<int>().allocate(0);
672 std::allocator<int>().deallocate(F);
673 return true;
675 static_assert(zeroAlloc());
677 /// FIXME: This is broken in the current interpreter.
678 constexpr int arrayAlloc() {
679 int *F = std::allocator<int>().allocate(2);
680 F[0] = 10; // ref-note {{assignment to object outside its lifetime is not allowed in a constant expression}}
681 F[1] = 13;
682 int Res = F[1] + F[0];
683 std::allocator<int>().deallocate(F);
684 return Res;
686 static_assert(arrayAlloc() == 23); // ref-error {{not an integral constant expression}} \
687 // ref-note {{in call to}}
689 struct S {
690 int i;
691 constexpr S(int i) : i(i) {}
692 constexpr ~S() { }
695 /// FIXME: This is broken in the current interpreter.
696 constexpr bool structAlloc() {
697 S *s = std::allocator<S>().allocate(1);
699 s->i = 12; // ref-note {{assignment to object outside its lifetime is not allowed in a constant expression}}
701 bool Res = (s->i == 12);
702 std::allocator<S>().deallocate(s);
704 return Res;
706 static_assert(structAlloc()); // ref-error {{not an integral constant expression}} \
707 // ref-note {{in call to}}
709 constexpr bool structAllocArray() {
710 S *s = std::allocator<S>().allocate(9);
712 s[2].i = 12; // ref-note {{assignment to object outside its lifetime is not allowed in a constant expression}}
713 bool Res = (s[2].i == 12);
714 std::allocator<S>().deallocate(s);
716 return Res;
718 static_assert(structAllocArray()); // ref-error {{not an integral constant expression}} \
719 // ref-note {{in call to}}
721 constexpr bool alloc_from_user_code() {
722 void *p = __builtin_operator_new(sizeof(int)); // both-note {{cannot allocate untyped memory in a constant expression; use 'std::allocator<T>::allocate'}}
723 __builtin_operator_delete(p);
724 return true;
726 static_assert(alloc_from_user_code()); // both-error {{constant expression}} \
727 // both-note {{in call to}}
730 constexpr int no_deallocate_nullptr = (std::allocator<int>().deallocate(nullptr), 1); // both-error {{constant expression}} \
731 // both-note {{in call}}
733 static_assert((std::allocator<float>().deallocate(std::allocator<float>().allocate(10)), 1) == 1);
736 namespace Limits {
737 template<typename T>
738 constexpr T dynarray(int elems, int i) {
739 T *p;
740 if constexpr (sizeof(T) == 1)
741 p = new T[elems]{"fox"};
742 else
743 p = new T[elems]{1, 2, 3};
744 T n = p[i];
745 delete [] p;
746 return n;
748 static_assert(dynarray<char>(5, 0) == 'f');
751 #if __LP64__
752 template <typename T>
753 struct S {
754 constexpr S(unsigned long long N)
755 : data(nullptr){
756 data = alloc.allocate(N); // both-note {{in call to 'this->alloc.allocate(18446744073709551615)}}
758 constexpr T operator[](std::size_t i) const {
759 return data[i];
762 constexpr ~S() {
763 alloc.deallocate(data);
765 std::allocator<T> alloc;
766 T* data;
769 constexpr std::size_t s = S<std::size_t>(~0UL)[42]; // both-error {{constexpr variable 's' must be initialized by a constant expression}} \
770 // both-note@#alloc {{cannot allocate array; evaluated array bound 2305843009213693951 is too large}} \
771 // both-note {{in call to}}
772 #endif
775 /// Just test that we reject placement-new expressions before C++2c.
776 /// Tests for successful expressions are in placement-new.cpp
777 namespace Placement {
778 consteval auto ok1() { // both-error {{never produces a constant expression}}
779 bool b;
780 new (&b) bool(true); // both-note 2{{this placement new expression is not supported in constant expressions before C++2c}}
781 return b;
783 static_assert(ok1()); // both-error {{not an integral constant expression}} \
784 // both-note {{in call to}}
786 /// placement-new should be supported before C++26 in std functions.
787 constexpr int ok2() {
788 int *I = new int;
789 std::construct_at<int>(I);
790 int r = *I;
791 delete I;
792 return r;
794 static_assert(ok2()== 0);
797 constexpr bool virt_delete(bool global) {
798 struct A {
799 virtual constexpr ~A() {}
801 struct B : A {
802 void operator delete(void *);
803 constexpr ~B() {}
806 A *p = new B;
807 if (global)
808 ::delete p;
809 else
810 delete p; // both-note {{call to class-specific 'operator delete'}}
811 return true;
813 static_assert(virt_delete(true));
814 static_assert(virt_delete(false)); // both-error {{not an integral constant expression}} \
815 // both-note {{in call to}}
818 namespace ToplevelScopeInTemplateArg {
819 class string {
820 public:
821 char *mem;
822 constexpr string() {
823 this->mem = new char(1);
825 constexpr ~string() {
826 delete this->mem;
828 constexpr unsigned size() const { return 4; }
832 template <unsigned N>
833 void test() {};
835 void f() {
836 test<string().size()>();
837 static_assert(string().size() == 4);
841 #else
842 /// Make sure we reject this prior to C++20
843 constexpr int a() { // both-error {{never produces a constant expression}}
844 delete new int(12); // both-note 2{{dynamic memory allocation is not permitted in constant expressions until C++20}}
845 return 1;
847 static_assert(a() == 1, ""); // both-error {{not an integral constant expression}} \
848 // both-note {{in call to 'a()'}}
851 static_assert(true ? *new int : 4, ""); // both-error {{expression is not an integral constant expression}} \
852 // both-note {{read of uninitialized object is not allowed in a constant expression}}
854 #endif