[docs] Add LICENSE.txt to the root of the mono-repo
[llvm-project.git] / clang / test / SemaCXX / constant-expression-cxx2a.cpp
blob6ebec5dc7e306191e9094a51eb547d5300332fe0
1 // RUN: %clang_cc1 -std=c++2a -verify %s -fcxx-exceptions -triple=x86_64-linux-gnu -Wno-mismatched-new-delete
3 #include "Inputs/std-compare.h"
5 namespace std {
6 struct type_info;
7 struct destroying_delete_t {
8 explicit destroying_delete_t() = default;
9 } inline constexpr destroying_delete{};
10 struct nothrow_t {
11 explicit nothrow_t() = default;
12 } inline constexpr nothrow{};
13 using size_t = decltype(sizeof(0));
14 enum class align_val_t : size_t {};
17 [[nodiscard]] void *operator new(std::size_t, const std::nothrow_t&) noexcept;
18 [[nodiscard]] void *operator new(std::size_t, std::align_val_t, const std::nothrow_t&) noexcept;
19 [[nodiscard]] void *operator new[](std::size_t, const std::nothrow_t&) noexcept;
20 [[nodiscard]] void *operator new[](std::size_t, std::align_val_t, const std::nothrow_t&) noexcept;
21 [[nodiscard]] void *operator new[](std::size_t, std::align_val_t);
22 void operator delete(void*, const std::nothrow_t&) noexcept;
23 void operator delete(void*, std::align_val_t, const std::nothrow_t&) noexcept;
24 void operator delete[](void*, const std::nothrow_t&) noexcept;
25 void operator delete[](void*, std::align_val_t, const std::nothrow_t&) noexcept;
27 // Helper to print out values for debugging.
28 constexpr void not_defined();
29 template<typename T> constexpr void print(T) { not_defined(); }
31 namespace ThreeWayComparison {
32 struct A {
33 int n;
34 constexpr friend int operator<=>(const A &a, const A &b) {
35 return a.n < b.n ? -1 : a.n > b.n ? 1 : 0;
38 static_assert(A{1} <=> A{2} < 0);
39 static_assert(A{2} <=> A{1} > 0);
40 static_assert(A{2} <=> A{2} == 0);
42 static_assert(1 <=> 2 < 0);
43 static_assert(2 <=> 1 > 0);
44 static_assert(1 <=> 1 == 0);
45 constexpr int k = (1 <=> 1, 0);
46 // expected-warning@-1 {{three-way comparison result unused}}
48 static_assert(std::strong_ordering::equal == 0);
50 constexpr void f() {
51 void(1 <=> 1);
54 struct MemPtr {
55 void foo() {}
56 void bar() {}
57 int data;
58 int data2;
59 long data3;
62 struct MemPtr2 {
63 void foo() {}
64 void bar() {}
65 int data;
66 int data2;
67 long data3;
69 using MemPtrT = void (MemPtr::*)();
71 using FnPtrT = void (*)();
73 void FnPtr1() {}
74 void FnPtr2() {}
76 #define CHECK(...) ((__VA_ARGS__) ? void() : throw "error")
77 #define CHECK_TYPE(...) static_assert(__is_same(__VA_ARGS__));
79 constexpr bool test_constexpr_success = [] {
81 auto &EQ = std::strong_ordering::equal;
82 auto &LESS = std::strong_ordering::less;
83 auto &GREATER = std::strong_ordering::greater;
84 using SO = std::strong_ordering;
85 auto eq = (42 <=> 42);
86 CHECK_TYPE(decltype(eq), SO);
87 CHECK(eq.test_eq(EQ));
89 auto less = (-1 <=> 0);
90 CHECK_TYPE(decltype(less), SO);
91 CHECK(less.test_eq(LESS));
93 auto greater = (42l <=> 1u);
94 CHECK_TYPE(decltype(greater), SO);
95 CHECK(greater.test_eq(GREATER));
98 using PO = std::partial_ordering;
99 auto EQUIV = PO::equivalent;
100 auto LESS = PO::less;
101 auto GREATER = PO::greater;
103 auto eq = (42.0 <=> 42.0);
104 CHECK_TYPE(decltype(eq), PO);
105 CHECK(eq.test_eq(EQUIV));
107 auto less = (39.0 <=> 42.0);
108 CHECK_TYPE(decltype(less), PO);
109 CHECK(less.test_eq(LESS));
111 auto greater = (-10.123 <=> -101.1);
112 CHECK_TYPE(decltype(greater), PO);
113 CHECK(greater.test_eq(GREATER));
116 return true;
117 }();
119 int dummy = 42;
120 int dummy2 = 101;
121 constexpr bool tc9 = (&dummy <=> &dummy2) != 0; // expected-error {{constant expression}} expected-note {{unspecified}}
123 template <class T, class R, class I>
124 constexpr T makeComplex(R r, I i) {
125 T res{r, i};
126 return res;
128 } // namespace ThreeWayComparison
130 constexpr bool for_range_init() {
131 int k = 0;
132 for (int arr[3] = {1, 2, 3}; int n : arr) k += n;
133 return k == 6;
135 static_assert(for_range_init());
137 namespace Virtual {
138 struct NonZeroOffset { int padding = 123; };
140 constexpr void assert(bool b) { if (!b) throw 0; }
142 // Ensure that we pick the right final overrider during construction.
143 struct A {
144 virtual constexpr char f() const { return 'A'; }
145 char a = f();
146 constexpr ~A() { assert(f() == 'A'); }
148 struct NoOverrideA : A {};
149 struct B : NonZeroOffset, NoOverrideA {
150 virtual constexpr char f() const { return 'B'; }
151 char b = f();
152 constexpr ~B() { assert(f() == 'B'); }
154 struct NoOverrideB : B {};
155 struct C : NonZeroOffset, A {
156 virtual constexpr char f() const { return 'C'; }
157 A *pba;
158 char c = ((A*)this)->f();
159 char ba = pba->f();
160 constexpr C(A *pba) : pba(pba) {}
161 constexpr ~C() { assert(f() == 'C'); }
163 struct D : NonZeroOffset, NoOverrideB, C { // expected-warning {{inaccessible}}
164 virtual constexpr char f() const { return 'D'; }
165 char d = f();
166 constexpr D() : C((B*)this) {}
167 constexpr ~D() { assert(f() == 'D'); }
169 constexpr int n = (D(), 0);
170 constexpr D d;
171 static_assert(((B&)d).a == 'A');
172 static_assert(((C&)d).a == 'A');
173 static_assert(d.b == 'B');
174 static_assert(d.c == 'C');
175 // During the construction of C, the dynamic type of B's A is B.
176 static_assert(d.ba == 'B');
177 static_assert(d.d == 'D');
178 static_assert(d.f() == 'D');
179 constexpr const A &a = (B&)d;
180 constexpr const B &b = d;
181 static_assert(a.f() == 'D');
182 static_assert(b.f() == 'D');
184 // FIXME: It is unclear whether this should be permitted.
185 D d_not_constexpr;
186 static_assert(d_not_constexpr.f() == 'D'); // expected-error {{constant expression}} expected-note {{virtual function called on object 'd_not_constexpr' whose dynamic type is not constant}}
188 // Check that we apply a proper adjustment for a covariant return type.
189 struct Covariant1 {
190 D d;
191 virtual const A *f() const;
193 template<typename T>
194 struct Covariant2 : Covariant1 {
195 virtual const T *f() const;
197 template<typename T>
198 struct Covariant3 : Covariant2<T> {
199 constexpr virtual const D *f() const { return &this->d; }
202 constexpr Covariant3<B> cb;
203 constexpr Covariant3<C> cc;
205 constexpr const Covariant1 *cb1 = &cb;
206 constexpr const Covariant2<B> *cb2 = &cb;
207 static_assert(cb1->f()->a == 'A');
208 static_assert(cb1->f() == (B*)&cb.d);
209 static_assert(cb1->f()->f() == 'D');
210 static_assert(cb2->f()->b == 'B');
211 static_assert(cb2->f() == &cb.d);
212 static_assert(cb2->f()->f() == 'D');
214 constexpr const Covariant1 *cc1 = &cc;
215 constexpr const Covariant2<C> *cc2 = &cc;
216 static_assert(cc1->f()->a == 'A');
217 static_assert(cc1->f() == (C*)&cc.d);
218 static_assert(cc1->f()->f() == 'D');
219 static_assert(cc2->f()->c == 'C');
220 static_assert(cc2->f() == &cc.d);
221 static_assert(cc2->f()->f() == 'D');
223 static_assert(cb.f()->d == 'D');
224 static_assert(cc.f()->d == 'D');
226 struct Abstract {
227 constexpr virtual void f() = 0; // expected-note {{declared here}}
228 constexpr Abstract() { do_it(); } // expected-note {{in call to}}
229 constexpr void do_it() { f(); } // expected-note {{pure virtual function 'Virtual::Abstract::f' called}}
231 struct PureVirtualCall : Abstract { void f(); }; // expected-note {{in call to 'Abstract}}
232 constexpr PureVirtualCall pure_virtual_call; // expected-error {{constant expression}} expected-note {{in call to 'PureVirtualCall}}
235 namespace DynamicCast {
236 struct A2 { virtual void a2(); };
237 struct A : A2 { virtual void a(); };
238 struct B : A {};
239 struct C2 { virtual void c2(); };
240 struct C : A, C2 { A *c = dynamic_cast<A*>(static_cast<C2*>(this)); };
241 struct D { virtual void d(); };
242 struct E { virtual void e(); };
243 struct F : B, C, D, private E { void *f = dynamic_cast<void*>(static_cast<D*>(this)); };
244 struct Padding { virtual void padding(); };
245 struct G : Padding, F {};
247 constexpr G g;
249 // During construction of C, A is unambiguous subobject of dynamic type C.
250 static_assert(g.c == (C*)&g);
251 // ... but in the complete object, the same is not true, so the runtime fails.
252 static_assert(dynamic_cast<const A*>(static_cast<const C2*>(&g)) == nullptr);
254 // dynamic_cast<void*> produces a pointer to the object of the dynamic type.
255 static_assert(g.f == (void*)(F*)&g);
256 static_assert(dynamic_cast<const void*>(static_cast<const D*>(&g)) == &g);
258 // expected-note@+1 {{reference dynamic_cast failed: 'A' is an ambiguous base class of dynamic type 'DynamicCast::G' of operand}}
259 constexpr int d_a = (dynamic_cast<const A&>(static_cast<const D&>(g)), 0); // expected-error {{}}
261 // Can navigate from A2 to its A...
262 static_assert(&dynamic_cast<A&>((A2&)(B&)g) == &(A&)(B&)g);
263 // ... and from B to its A ...
264 static_assert(&dynamic_cast<A&>((B&)g) == &(A&)(B&)g);
265 // ... but not from D.
266 // expected-note@+1 {{reference dynamic_cast failed: 'A' is an ambiguous base class of dynamic type 'DynamicCast::G' of operand}}
267 static_assert(&dynamic_cast<A&>((D&)g) == &(A&)(B&)g); // expected-error {{}}
269 // Can cast from A2 to sibling class D.
270 static_assert(&dynamic_cast<D&>((A2&)(B&)g) == &(D&)g);
272 // Cannot cast from private base E to derived class F.
273 // expected-note@+1 {{reference dynamic_cast failed: static type 'DynamicCast::E' of operand is a non-public base class of dynamic type 'DynamicCast::G'}}
274 constexpr int e_f = (dynamic_cast<F&>((E&)g), 0); // expected-error {{}}
276 // Cannot cast from B to private sibling E.
277 // expected-note@+1 {{reference dynamic_cast failed: 'E' is a non-public base class of dynamic type 'DynamicCast::G' of operand}}
278 constexpr int b_e = (dynamic_cast<E&>((B&)g), 0); // expected-error {{}}
280 struct Unrelated { virtual void unrelated(); };
281 // expected-note@+1 {{reference dynamic_cast failed: dynamic type 'DynamicCast::G' of operand does not have a base class of type 'Unrelated'}}
282 constexpr int b_unrelated = (dynamic_cast<Unrelated&>((B&)g), 0); // expected-error {{}}
283 // expected-note@+1 {{reference dynamic_cast failed: dynamic type 'DynamicCast::G' of operand does not have a base class of type 'Unrelated'}}
284 constexpr int e_unrelated = (dynamic_cast<Unrelated&>((E&)g), 0); // expected-error {{}}
287 namespace TypeId {
288 struct A {
289 const std::type_info &ti = typeid(*this);
291 struct A2 : A {};
292 static_assert(&A().ti == &typeid(A));
293 static_assert(&typeid((A2())) == &typeid(A2));
294 extern A2 extern_a2;
295 static_assert(&typeid(extern_a2) == &typeid(A2));
297 constexpr A2 a2;
298 constexpr const A &a1 = a2;
299 static_assert(&typeid(a1) == &typeid(A));
301 struct B {
302 virtual void f();
303 const std::type_info &ti1 = typeid(*this);
305 struct B2 : B {
306 const std::type_info &ti2 = typeid(*this);
308 static_assert(&B2().ti1 == &typeid(B));
309 static_assert(&B2().ti2 == &typeid(B2));
310 extern B2 extern_b2;
311 // expected-note@+1 {{typeid applied to object 'extern_b2' whose dynamic type is not constant}}
312 static_assert(&typeid(extern_b2) == &typeid(B2)); // expected-error {{constant expression}}
314 constexpr B2 b2;
315 constexpr const B &b1 = b2;
316 static_assert(&typeid(b1) == &typeid(B2));
318 constexpr bool side_effects() {
319 // Not polymorphic nor a glvalue.
320 bool OK = true;
321 (void)typeid(OK = false, A2()); // expected-warning {{has no effect}}
322 if (!OK) return false;
324 // Not polymorphic.
325 A2 a2;
326 (void)typeid(OK = false, a2); // expected-warning {{has no effect}}
327 if (!OK) return false;
329 // Not a glvalue.
330 (void)typeid(OK = false, B2()); // expected-warning {{has no effect}}
331 if (!OK) return false;
333 // Polymorphic glvalue: operand evaluated.
334 OK = false;
335 B2 b2;
336 (void)typeid(OK = true, b2); // expected-warning {{will be evaluated}}
337 return OK;
339 static_assert(side_effects());
342 namespace Union {
343 struct Base {
344 int y; // expected-note 2{{here}}
346 struct A : Base {
347 int x;
348 int arr[3];
349 union { int p, q; };
351 union B {
352 A a;
353 int b;
355 constexpr int read_wrong_member() { // expected-error {{never produces a constant}}
356 B b = {.b = 1};
357 return b.a.x; // expected-note {{read of member 'a' of union with active member 'b'}}
359 constexpr int change_member() {
360 B b = {.b = 1};
361 b.a.x = 1;
362 return b.a.x;
364 static_assert(change_member() == 1);
365 constexpr int change_member_then_read_wrong_member() { // expected-error {{never produces a constant}}
366 B b = {.b = 1};
367 b.a.x = 1;
368 return b.b; // expected-note {{read of member 'b' of union with active member 'a'}}
370 constexpr int read_wrong_member_indirect() { // expected-error {{never produces a constant}}
371 B b = {.b = 1};
372 int *p = &b.a.y;
373 return *p; // expected-note {{read of member 'a' of union with active member 'b'}}
375 constexpr int read_uninitialized() {
376 B b = {.b = 1};
377 int *p = &b.a.y;
378 b.a.x = 1;
379 return *p; // expected-note {{read of uninitialized object}}
381 static_assert(read_uninitialized() == 0); // expected-error {{constant}} expected-note {{in call}}
382 constexpr void write_wrong_member_indirect() { // expected-error {{never produces a constant}}
383 B b = {.b = 1};
384 int *p = &b.a.y;
385 *p = 1; // expected-note {{assignment to member 'a' of union with active member 'b'}}
387 constexpr int write_uninitialized() {
388 B b = {.b = 1};
389 int *p = &b.a.y;
390 b.a.x = 1;
391 *p = 1;
392 return *p;
394 static_assert(write_uninitialized() == 1);
395 constexpr int change_member_indirectly() {
396 B b = {.b = 1};
397 b.a.arr[1] = 1;
398 int &r = b.a.y;
399 r = 123;
401 b.b = 2;
402 b.a.y = 3;
403 b.a.arr[2] = 4;
404 return b.a.arr[2];
406 static_assert(change_member_indirectly() == 4);
407 constexpr B return_uninit() {
408 B b = {.b = 1};
409 b.a.x = 2;
410 return b;
412 constexpr B uninit = return_uninit(); // expected-error {{constant expression}} expected-note {{subobject of type 'int' is not initialized}}
413 static_assert(return_uninit().a.x == 2);
414 constexpr A return_uninit_struct() {
415 B b = {.b = 1};
416 b.a.x = 2;
417 return b.a; // expected-note {{in call to 'A(b.a)'}} expected-note {{subobject of type 'int' is not initialized}}
419 // Note that this is rejected even though return_uninit() is accepted, and
420 // return_uninit() copies the same stuff wrapped in a union.
422 // Copying a B involves copying the object representation of the union, but
423 // copying an A invokes a copy constructor that copies the object
424 // elementwise, and reading from b.a.y is undefined.
425 static_assert(return_uninit_struct().x == 2); // expected-error {{constant expression}} expected-note {{in call}}
426 constexpr B return_init_all() {
427 B b = {.b = 1};
428 b.a.x = 2;
429 b.a.y = 3;
430 b.a.arr[0] = 4;
431 b.a.arr[1] = 5;
432 b.a.arr[2] = 6;
433 return b;
435 static_assert(return_init_all().a.x == 2);
436 static_assert(return_init_all().a.y == 3);
437 static_assert(return_init_all().a.arr[0] == 4);
438 static_assert(return_init_all().a.arr[1] == 5);
439 static_assert(return_init_all().a.arr[2] == 6);
440 static_assert(return_init_all().a.p == 7); // expected-error {{}} expected-note {{read of member 'p' of union with no active member}}
441 static_assert(return_init_all().a.q == 8); // expected-error {{}} expected-note {{read of member 'q' of union with no active member}}
442 constexpr B init_all = return_init_all();
444 constexpr bool test_no_member_change = []{
445 union U { char dummy = {}; };
446 U u1;
447 U u2;
448 u1 = u2;
449 return true;
450 }();
452 struct S1 {
453 int n;
455 struct S2 : S1 {};
456 struct S3 : S2 {};
457 void f() {
458 S3 s;
459 s.n = 0;
462 union ref_member_1 {
463 int a;
464 int b;
466 struct ref_member_2 {
467 ref_member_1 &&r;
469 union ref_member_3 {
470 ref_member_2 a, b;
472 constexpr int ref_member_test_1() {
473 ref_member_3 r = {.a = {.r = {.a = 1}}};
474 r.a.r.b = 2;
475 return r.a.r.b;
477 static_assert(ref_member_test_1() == 2);
478 constexpr int ref_member_test_2() { // expected-error {{never produces a constant}}
479 ref_member_3 r = {.a = {.r = {.a = 1}}};
480 // FIXME: This note isn't great. The 'read' here is reading the referent of the reference.
481 r.b.r.b = 2; // expected-note {{read of member 'b' of union with active member 'a'}}
482 return r.b.r.b;
485 namespace PR43762 {
486 struct A { int x = 1; constexpr int f() { return 1; } };
487 struct B : A { int y = 1; constexpr int g() { return 2; } };
488 struct C {
489 int x;
490 constexpr virtual int f() = 0;
492 struct D : C {
493 int y;
494 constexpr virtual int f() override { return 3; }
497 union U {
498 int n;
499 B b;
500 D d;
503 constexpr int test(int which) {
504 U u{.n = 5};
505 switch (which) {
506 case 0:
507 u.b.x = 10; // expected-note {{active member 'n'}}
508 return u.b.f();
509 case 1:
510 u.b.y = 10; // expected-note {{active member 'n'}}
511 return u.b.g();
512 case 2:
513 u.d.x = 10; // expected-note {{active member 'n'}}
514 return u.d.f();
515 case 3:
516 u.d.y = 10; // expected-note {{active member 'n'}}
517 return u.d.f();
521 static_assert(test(0)); // expected-error {{}} expected-note {{in call}}
522 static_assert(test(1)); // expected-error {{}} expected-note {{in call}}
523 static_assert(test(2)); // expected-error {{}} expected-note {{in call}}
524 static_assert(test(3)); // expected-error {{}} expected-note {{in call}}
528 namespace TwosComplementShifts {
529 using uint32 = __UINT32_TYPE__;
530 using int32 = __INT32_TYPE__;
531 static_assert(uint32(int32(0x1234) << 16) == 0x12340000);
532 static_assert(uint32(int32(0x1234) << 19) == 0x91a00000);
533 static_assert(uint32(int32(0x1234) << 20) == 0x23400000);
534 static_assert(uint32(int32(0x1234) << 24) == 0x34000000);
535 static_assert(uint32(int32(-1) << 31) == 0x80000000);
537 static_assert(-1 >> 1 == -1);
538 static_assert(-1 >> 31 == -1);
539 static_assert(-2 >> 1 == -1);
540 static_assert(-3 >> 1 == -2);
541 static_assert(-4 >> 1 == -2);
544 namespace Uninit {
545 constexpr int f(bool init) {
546 int a;
547 if (init)
548 a = 1;
549 return a; // expected-note {{read of uninitialized object}}
551 static_assert(f(true) == 1);
552 static_assert(f(false) == 1); // expected-error {{constant expression}} expected-note {{in call}}
554 struct X {
555 int n; // expected-note {{declared here}}
556 constexpr X(bool init) {
557 if (init) n = 123;
560 constinit X x1(true);
561 constinit X x2(false); // expected-error {{constant initializer}} expected-note {{constinit}} expected-note {{subobject of type 'int' is not initialized}}
563 struct Y {
564 struct Z { int n; }; // expected-note {{here}}
565 Z z1;
566 Z z2;
567 Z z3;
568 // OK: the lifetime of z1 (and its members) start before the initializer of
569 // z2 runs.
570 constexpr Y() : z2{ (z1.n = 1, z1.n + 1) } { z3.n = 3; }
571 // Not OK: z3 is not in its lifetime when the initializer of z2 runs.
572 constexpr Y(int) : z2{
573 (z3.n = 1, // expected-note {{assignment to object outside its lifetime}}
574 z3.n + 1) // expected-warning {{uninitialized}}
575 } { z1.n = 3; }
576 constexpr Y(int, int) : z2{} {}
578 // FIXME: This is working around clang not implementing DR2026. With that
579 // fixed, we should be able to test this without the injected copy.
580 constexpr Y copy(Y y) { return y; } // expected-note {{in call to 'Y(y)'}} expected-note {{subobject of type 'int' is not initialized}}
581 constexpr Y y1 = copy(Y());
582 static_assert(y1.z1.n == 1 && y1.z2.n == 2 && y1.z3.n == 3);
584 constexpr Y y2 = copy(Y(0)); // expected-error {{constant expression}} expected-note {{in call}}
586 static_assert(Y(0,0).z2.n == 0);
587 static_assert(Y(0,0).z1.n == 0); // expected-error {{constant expression}} expected-note {{read of uninitialized object}}
588 static_assert(Y(0,0).z3.n == 0); // expected-error {{constant expression}} expected-note {{read of uninitialized object}}
590 static_assert(copy(Y(0,0)).z2.n == 0); // expected-error {{constant expression}} expected-note {{in call}}
592 constexpr unsigned char not_even_unsigned_char() {
593 unsigned char c;
594 return c; // expected-note {{read of uninitialized object}}
596 constexpr unsigned char x = not_even_unsigned_char(); // expected-error {{constant expression}} expected-note {{in call}}
598 constexpr int switch_var(int n) {
599 switch (n) {
600 case 1:
601 int a;
602 a = n;
603 return a;
605 case 2:
606 a = n;
607 return a;
610 constexpr int s1 = switch_var(1);
611 constexpr int s2 = switch_var(2);
612 static_assert(s1 == 1 && s2 == 2);
614 constexpr bool switch_into_init_stmt() {
615 switch (1) {
616 if (int n; false) {
617 for (int m; false;) {
618 case 1:
619 n = m = 1;
620 return n == 1 && m == 1;
625 static_assert(switch_into_init_stmt());
628 namespace dtor {
629 void lifetime_extension() {
630 struct X { constexpr ~X() {} };
631 X &&a = X();
634 template<typename T> constexpr T &&ref(T &&t) { return (T&&)t; }
636 struct Buf {
637 char buf[64];
638 int n = 0;
639 constexpr void operator+=(char c) { buf[n++] = c; }
640 constexpr bool operator==(const char *str) const {
641 return str[n] == 0 && __builtin_memcmp(str, buf, n) == 0;
643 constexpr bool operator!=(const char *str) const { return !operator==(str); }
646 struct A {
647 constexpr A(Buf &buf, char c) : buf(buf), c(c) { buf += c; }
648 constexpr ~A() { buf += c; }
649 constexpr operator bool() const { return true; }
650 Buf &buf;
651 char c;
654 constexpr bool dtor_calls_dtor() {
655 union U {
656 constexpr U(Buf &buf) : u(buf, 'u') { buf += 'U'; }
657 constexpr ~U() { u.buf += 'U'; }
658 A u, v;
661 struct B : A {
662 A c, &&d, e;
663 union {
664 A f;
666 U u;
667 constexpr B(Buf &buf)
668 : A(buf, 'a'), c(buf, 'c'), d(ref(A(buf, 'd'))), e(A(buf, 'e')), f(buf, 'f'), u(buf) {
669 buf += 'b';
671 constexpr ~B() {
672 buf += 'b';
676 Buf buf;
678 B b(buf);
679 if (buf != "acddefuUb")
680 return false;
682 if (buf != "acddefuUbbUeca")
683 return false;
684 return true;
686 static_assert(dtor_calls_dtor());
688 constexpr void abnormal_termination(Buf &buf) {
689 struct Indestructible {
690 constexpr ~Indestructible(); // not defined
693 A a(buf, 'a');
694 A(buf, 'b');
695 int n = 0;
696 for (A &&c = A(buf, 'c'); A d = A(buf, 'd'); A(buf, 'e')) {
697 switch (A f(buf, 'f'); A g = A(buf, 'g')) { // expected-warning {{boolean}}
698 case false: {
699 A x(buf, 'x');
702 case true: {
703 A h(buf, 'h');
704 switch (n++) {
705 case 0:
706 break;
707 case 1:
708 continue;
709 case 2:
710 return;
712 break;
715 default:
716 Indestructible indest;
719 A j = (A(buf, 'i'), A(buf, 'j'));
723 constexpr bool check_abnormal_termination() {
724 Buf buf = {};
725 abnormal_termination(buf);
726 return buf ==
727 "abbc"
728 "dfgh" /*break*/ "hgfijijeed"
729 "dfgh" /*continue*/ "hgfeed"
730 "dfgh" /*return*/ "hgfd"
731 "ca";
733 static_assert(check_abnormal_termination());
735 constexpr bool run_dtors_on_array_filler() {
736 struct S {
737 int times_destroyed = 0;
738 constexpr ~S() { if (++times_destroyed != 1) throw "oops"; }
740 S s[3];
741 return true;
743 static_assert(run_dtors_on_array_filler());
745 // Ensure that we can handle temporary cleanups for array temporaries.
746 struct ArrElem { constexpr ~ArrElem() {} };
747 using Arr = ArrElem[3];
748 static_assert(((void)Arr{}, true));
751 namespace dynamic_alloc {
752 constexpr int *p = // expected-error {{constant}} expected-note {{pointer to heap-allocated object is not a constant expression}}
753 new int; // expected-note {{heap allocation performed here}}
755 constexpr int f(int n) {
756 int *p = new int[n];
757 for (int i = 0; i != n; ++i) {
758 p[i] = i;
760 int k = 0;
761 for (int i = 0; i != n; ++i) {
762 k += p[i];
764 delete[] p;
765 return k;
767 static_assert(f(123) == 123 * 122 / 2);
769 constexpr bool nvdtor() { // expected-error {{never produces a constant expression}}
770 struct S {
771 constexpr ~S() {}
773 struct T : S {};
774 delete (S*)new T; // expected-note {{delete of object with dynamic type 'T' through pointer to base class type 'S' with non-virtual destructor}}
775 return true;
778 constexpr int vdtor_1() {
779 int a;
780 struct S {
781 constexpr S(int *p) : p(p) {}
782 constexpr virtual ~S() { *p = 1; }
783 int *p;
785 struct T : S {
786 // implicit destructor defined eagerly because it is constexpr and virtual
787 using S::S;
789 delete (S*)new T(&a);
790 return a;
792 static_assert(vdtor_1() == 1);
794 constexpr int vdtor_2() {
795 int a = 0;
796 struct S { constexpr virtual ~S() {} };
797 struct T : S {
798 constexpr T(int *p) : p(p) {}
799 constexpr ~T() { ++*p; }
800 int *p;
802 S *p = new T{&a};
803 delete p;
804 return a;
806 static_assert(vdtor_2() == 1);
808 constexpr int vdtor_3(int mode) {
809 int a = 0;
810 struct S { constexpr virtual ~S() {} };
811 struct T : S {
812 constexpr T(int *p) : p(p) {}
813 constexpr ~T() { ++*p; }
814 int *p;
816 S *p = new T[3]{&a, &a, &a}; // expected-note 2{{heap allocation}}
817 switch (mode) {
818 case 0:
819 delete p; // expected-note {{non-array delete used to delete pointer to array object of type 'T[3]'}}
820 break;
821 case 1:
822 // FIXME: This diagnosic isn't great; we should mention the cast to S*
823 // somewhere in here.
824 delete[] p; // expected-note {{delete of pointer to subobject '&{*new T[3]#0}[0]'}}
825 break;
826 case 2:
827 delete (T*)p; // expected-note {{non-array delete used to delete pointer to array object of type 'T[3]'}}
828 break;
829 case 3:
830 delete[] (T*)p;
831 break;
833 return a;
835 static_assert(vdtor_3(0) == 3); // expected-error {{}} expected-note {{in call}}
836 static_assert(vdtor_3(1) == 3); // expected-error {{}} expected-note {{in call}}
837 static_assert(vdtor_3(2) == 3); // expected-error {{}} expected-note {{in call}}
838 static_assert(vdtor_3(3) == 3);
840 constexpr void delete_mismatch() { // expected-error {{never produces a constant expression}}
841 delete[] // expected-note {{array delete used to delete pointer to non-array object of type 'int'}}
842 new int; // expected-note {{allocation}}
845 template<typename T>
846 constexpr T dynarray(int elems, int i) {
847 T *p;
848 if constexpr (sizeof(T) == 1)
849 p = new T[elems]{"fox"}; // expected-note {{evaluated array bound 3 is too small to hold 4 explicitly initialized elements}}
850 else
851 p = new T[elems]{1, 2, 3}; // expected-note {{evaluated array bound 2 is too small to hold 3 explicitly initialized elements}}
852 T n = p[i]; // expected-note 4{{past-the-end}}
853 delete [] p;
854 return n;
856 static_assert(dynarray<int>(4, 0) == 1);
857 static_assert(dynarray<int>(4, 1) == 2);
858 static_assert(dynarray<int>(4, 2) == 3);
859 static_assert(dynarray<int>(4, 3) == 0);
860 static_assert(dynarray<int>(4, 4) == 0); // expected-error {{constant expression}} expected-note {{in call}}
861 static_assert(dynarray<int>(3, 2) == 3);
862 static_assert(dynarray<int>(3, 3) == 0); // expected-error {{constant expression}} expected-note {{in call}}
863 static_assert(dynarray<int>(2, 1) == 0); // expected-error {{constant expression}} expected-note {{in call}}
864 static_assert(dynarray<char>(5, 0) == 'f');
865 static_assert(dynarray<char>(5, 1) == 'o');
866 static_assert(dynarray<char>(5, 2) == 'x');
867 static_assert(dynarray<char>(5, 3) == 0); // (from string)
868 static_assert(dynarray<char>(5, 4) == 0); // (from filler)
869 static_assert(dynarray<char>(5, 5) == 0); // expected-error {{constant expression}} expected-note {{in call}}
870 static_assert(dynarray<char>(4, 0) == 'f');
871 static_assert(dynarray<char>(4, 1) == 'o');
872 static_assert(dynarray<char>(4, 2) == 'x');
873 static_assert(dynarray<char>(4, 3) == 0);
874 static_assert(dynarray<char>(4, 4) == 0); // expected-error {{constant expression}} expected-note {{in call}}
875 static_assert(dynarray<char>(3, 2) == 'x'); // expected-error {{constant expression}} expected-note {{in call}}
877 constexpr bool run_dtors_on_array_filler() {
878 struct S {
879 int times_destroyed = 0;
880 constexpr ~S() { if (++times_destroyed != 1) throw "oops"; }
882 delete[] new S[3];
883 return true;
885 static_assert(run_dtors_on_array_filler());
887 constexpr bool erroneous_array_bound(long long n) {
888 delete[] new int[n]; // expected-note {{array bound -1 is negative}} expected-note {{array bound 4611686018427387904 is too large}}
889 return true;
891 static_assert(erroneous_array_bound(3));
892 static_assert(erroneous_array_bound(0));
893 static_assert(erroneous_array_bound(-1)); // expected-error {{constant expression}} expected-note {{in call}}
894 static_assert(erroneous_array_bound(1LL << 62)); // expected-error {{constant expression}} expected-note {{in call}}
896 constexpr bool erroneous_array_bound_nothrow(long long n) {
897 int *p = new (std::nothrow) int[n];
898 bool result = p != 0;
899 delete[] p;
900 return result;
902 static_assert(erroneous_array_bound_nothrow(3));
903 static_assert(erroneous_array_bound_nothrow(0));
904 static_assert(!erroneous_array_bound_nothrow(-1));
905 static_assert(!erroneous_array_bound_nothrow(1LL << 62));
907 constexpr bool evaluate_nothrow_arg() {
908 bool ok = false;
909 delete new ((ok = true, std::nothrow)) int;
910 return ok;
912 static_assert(evaluate_nothrow_arg());
914 constexpr void double_delete() { // expected-error {{never produces a constant expression}}
915 int *p = new int;
916 delete p;
917 delete p; // expected-note {{delete of pointer that has already been deleted}}
919 constexpr bool super_secret_double_delete() {
920 struct A {
921 constexpr ~A() { delete this; } // expected-note {{destruction of object that is already being destroyed}} expected-note {{in call}}
923 delete new A; // expected-note {{in call}}
924 return true;
926 static_assert(super_secret_double_delete()); // expected-error {{constant expression}} expected-note {{in call}}
928 constexpr void use_after_free() { // expected-error {{never produces a constant expression}}
929 int *p = new int;
930 delete p;
931 *p = 1; // expected-note {{assignment to heap allocated object that has been deleted}}
933 constexpr void use_after_free_2() { // expected-error {{never produces a constant expression}}
934 struct X { constexpr void f() {} };
935 X *p = new X;
936 delete p;
937 p->f(); // expected-note {{member call on heap allocated object that has been deleted}}
940 template<typename T> struct X {
941 std::size_t n;
942 char *p;
943 void dependent();
945 template<typename T> void X<T>::dependent() {
946 char *p;
947 // Ensure that we don't try to evaluate these for overflow and crash. These
948 // are all value-dependent expressions.
949 p = new char[n];
950 p = new ((std::align_val_t)n) char[n];
951 p = new char(n);
954 namespace PR47143 {
955 constexpr char *f(int n) {
956 return new char[n]();
958 const char *p = f(3);
959 constexpr bool test() {
960 char *p = f(3);
961 bool result = !p[0] && !p[1] && !p[2];
962 delete [] p;
963 return result;
965 static_assert(test());
969 struct placement_new_arg {};
970 void *operator new(std::size_t, placement_new_arg);
971 void operator delete(void*, placement_new_arg);
973 namespace placement_new_delete {
974 struct ClassSpecificNew {
975 void *operator new(std::size_t);
977 struct ClassSpecificDelete {
978 void operator delete(void*);
980 struct DestroyingDelete {
981 void operator delete(DestroyingDelete*, std::destroying_delete_t);
983 struct alignas(64) Overaligned {};
985 constexpr bool ok() {
986 delete new Overaligned;
987 delete ::new ClassSpecificNew;
988 ::delete new ClassSpecificDelete;
989 ::delete new DestroyingDelete;
990 return true;
992 static_assert(ok());
994 constexpr bool bad(int which) {
995 switch (which) {
996 case 0:
997 delete new (placement_new_arg{}) int; // expected-note {{call to placement 'operator new'}}
998 break;
1000 case 1:
1001 delete new ClassSpecificNew; // expected-note {{call to class-specific 'operator new'}}
1002 break;
1004 case 2:
1005 delete new ClassSpecificDelete; // expected-note {{call to class-specific 'operator delete'}}
1006 break;
1008 case 3:
1009 delete new DestroyingDelete; // expected-note {{call to class-specific 'operator delete'}}
1010 break;
1012 case 4:
1013 // FIXME: This technically follows the standard's rules, but it seems
1014 // unreasonable to expect implementations to support this.
1015 delete new (std::align_val_t{64}) Overaligned; // expected-note {{placement new expression is not yet supported}}
1016 break;
1019 return true;
1021 static_assert(bad(0)); // expected-error {{constant expression}} expected-note {{in call}}
1022 static_assert(bad(1)); // expected-error {{constant expression}} expected-note {{in call}}
1023 static_assert(bad(2)); // expected-error {{constant expression}} expected-note {{in call}}
1024 static_assert(bad(3)); // expected-error {{constant expression}} expected-note {{in call}}
1025 static_assert(bad(4)); // expected-error {{constant expression}} expected-note {{in call}}
1028 namespace delete_random_things {
1029 static_assert((delete new int, true));
1030 static_assert((delete (int*)0, true));
1031 int n; // expected-note {{declared here}}
1032 static_assert((delete &n, true)); // expected-error {{}} expected-note {{delete of pointer '&n' that does not point to a heap-allocated object}}
1033 struct A { int n; };
1034 static_assert((delete &(new A)->n, true)); // expected-error {{}} expected-note {{delete of pointer to subobject '&{*new A#0}.n'}}
1035 static_assert((delete (new int + 1), true)); // expected-error {{}} expected-note {{delete of pointer '&{*new int#0} + 1' that does not point to complete object}}
1036 static_assert((delete[] (new int[3] + 1), true)); // expected-error {{}} expected-note {{delete of pointer to subobject '&{*new int[3]#0}[1]'}}
1037 static_assert((delete &(int&)(int&&)0, true)); // expected-error {{}} expected-note {{delete of pointer '&0' that does not point to a heap-allocated object}} expected-note {{temporary created here}}
1040 namespace value_dependent_delete {
1041 template<typename T> void f(T *p) {
1042 int arr[(delete p, 0)];
1046 namespace memory_leaks {
1047 static_assert(*new bool(true)); // expected-error {{}} expected-note {{allocation performed here was not deallocated}}
1049 constexpr bool *f() { return new bool(true); } // expected-note {{allocation performed here was not deallocated}}
1050 static_assert(*f()); // expected-error {{}}
1052 struct UP {
1053 bool *p;
1054 constexpr ~UP() { delete p; }
1055 constexpr bool &operator*() { return *p; }
1057 constexpr UP g() { return {new bool(true)}; }
1058 static_assert(*g()); // ok
1060 constexpr bool h(UP p) { return *p; }
1061 static_assert(h({new bool(true)})); // ok
1064 constexpr void *operator new(std::size_t, void *p) { return p; }
1065 namespace std {
1066 template<typename T> constexpr T *construct(T *p) { return new (p) T; }
1067 template<typename T> constexpr void destroy(T *p) { p->~T(); }
1070 namespace dtor_call {
1071 struct A { int n; };
1072 constexpr void f() { // expected-error {{never produces a constant expression}}
1073 A a; // expected-note {{destroying object 'a' whose lifetime has already ended}}
1074 a.~A();
1076 union U { A a; };
1077 constexpr void g() {
1078 U u;
1079 u.a.n = 3;
1080 u.a.~A();
1081 // There's now effectively no active union member, but we model it as if
1082 // 'a' is still the active union member (but its lifetime has ended).
1083 u.a.n = 4; // Start lifetime of 'a' again.
1084 u.a.~A();
1086 static_assert((g(), true));
1088 constexpr bool pseudo(bool read, bool recreate) {
1089 using T = bool;
1090 bool b = false; // expected-note {{lifetime has already ended}}
1091 // This evaluates the store to 'b'...
1092 (b = true).~T();
1093 // ... and ends the lifetime of the object.
1094 return (read
1095 ? b // expected-note {{read of object outside its lifetime}}
1096 : true) +
1097 (recreate
1098 ? (std::construct(&b), true)
1099 : true);
1101 static_assert(pseudo(false, false)); // expected-error {{constant expression}} expected-note {{in call}}
1102 static_assert(pseudo(true, false)); // expected-error {{constant expression}} expected-note {{in call}}
1103 static_assert(pseudo(false, true));
1105 constexpr void use_after_destroy() {
1106 A a;
1107 a.~A();
1108 A b = a; // expected-note {{in call}} expected-note {{read of object outside its lifetime}}
1110 static_assert((use_after_destroy(), true)); // expected-error {{}} expected-note {{in call}}
1112 constexpr void double_destroy() {
1113 A a;
1114 a.~A();
1115 a.~A(); // expected-note {{destruction of object outside its lifetime}}
1117 static_assert((double_destroy(), true)); // expected-error {{}} expected-note {{in call}}
1119 struct X { char *p; constexpr ~X() { *p++ = 'X'; } };
1120 struct Y : X { int y; virtual constexpr ~Y() { *p++ = 'Y'; } };
1121 struct Z : Y { int z; constexpr ~Z() override { *p++ = 'Z'; } };
1122 union VU {
1123 constexpr VU() : z() {}
1124 constexpr ~VU() {}
1125 Z z;
1128 constexpr bool virt_dtor(int mode, const char *expected) {
1129 char buff[4] = {};
1130 VU vu;
1131 vu.z.p = buff;
1132 switch (mode) {
1133 case 0:
1134 vu.z.~Z();
1135 break;
1136 case 1:
1137 ((Y&)vu.z).~Y();
1138 break;
1139 case 2:
1140 ((X&)vu.z).~X();
1141 break;
1142 case 3:
1143 ((Y&)vu.z).Y::~Y();
1144 vu.z.z = 1; // ok, still have a Z (with no Y base class!)
1145 break;
1146 case 4:
1147 ((X&)vu.z).X::~X();
1148 vu.z.y = 1; // ok, still have a Z and a Y (with no X base class!)
1149 break;
1151 return __builtin_strcmp(expected, buff) == 0;
1153 static_assert(virt_dtor(0, "ZYX"));
1154 static_assert(virt_dtor(1, "ZYX"));
1155 static_assert(virt_dtor(2, "X"));
1156 static_assert(virt_dtor(3, "YX"));
1157 static_assert(virt_dtor(4, "X"));
1159 constexpr bool virt_delete(bool global) {
1160 struct A {
1161 virtual constexpr ~A() {}
1163 struct B : A {
1164 void operator delete(void *);
1165 constexpr ~B() {}
1168 A *p = new B;
1169 if (global)
1170 ::delete p;
1171 else
1172 delete p; // expected-note {{call to class-specific 'operator delete'}}
1173 return true;
1175 static_assert(virt_delete(true));
1176 static_assert(virt_delete(false)); // expected-error {{}} expected-note {{in call}}
1178 constexpr void use_after_virt_destroy() {
1179 char buff[4] = {};
1180 VU vu;
1181 vu.z.p = buff;
1182 ((Y&)vu.z).~Y();
1183 ((Z&)vu.z).z = 1; // expected-note {{assignment to object outside its lifetime}}
1185 static_assert((use_after_virt_destroy(), true)); // expected-error {{}} expected-note {{in call}}
1187 constexpr void destroy_after_lifetime() {
1188 A *p;
1190 A a;
1191 p = &a;
1193 p->~A(); // expected-note {{destruction of object outside its lifetime}}
1195 static_assert((destroy_after_lifetime(), true)); // expected-error {{}} expected-note {{in call}}
1197 constexpr void destroy_after_lifetime2() {
1198 A *p = []{ A a; return &a; }(); // expected-warning {{}} expected-note {{declared here}}
1199 p->~A(); // expected-note {{destruction of variable whose lifetime has ended}}
1201 static_assert((destroy_after_lifetime2(), true)); // expected-error {{}} expected-note {{in call}}
1203 constexpr void destroy_after_lifetime3() {
1204 A *p = []{ return &(A&)(A&&)A(); }(); // expected-warning {{}} expected-note {{temporary created here}}
1205 p->~A(); // expected-note {{destruction of temporary whose lifetime has ended}}
1207 static_assert((destroy_after_lifetime3(), true)); // expected-error {{}} expected-note {{in call}}
1209 constexpr void destroy_after_lifetime4() { // expected-error {{never produces a constant expression}}
1210 A *p = new A;
1211 delete p;
1212 p->~A(); // expected-note {{destruction of heap allocated object that has been deleted}}
1215 struct Extern { constexpr ~Extern() {} } extern e;
1216 constexpr void destroy_extern() { // expected-error {{never produces a constant expression}}
1217 e.~Extern(); // expected-note {{cannot modify an object that is visible outside}}
1220 constexpr A &&a_ref = A(); // expected-note {{temporary created here}}
1221 constexpr void destroy_extern_2() { // expected-error {{never produces a constant expression}}
1222 a_ref.~A(); // expected-note {{destruction of temporary is not allowed in a constant expression outside the expression that created the temporary}}
1225 struct S {
1226 constexpr S() { n = 1; }
1227 constexpr ~S() { n = 0; }
1228 int n;
1230 constexpr void destroy_volatile() {
1231 volatile S s;
1233 static_assert((destroy_volatile(), true)); // ok, not volatile during construction and destruction
1235 constexpr void destroy_null() { // expected-error {{never produces a constant expression}}
1236 ((A*)nullptr)->~A(); // expected-note {{destruction of dereferenced null pointer}}
1239 constexpr void destroy_past_end() { // expected-error {{never produces a constant expression}}
1240 A a;
1241 (&a+1)->~A(); // expected-note {{destruction of dereferenced one-past-the-end pointer}}
1244 constexpr void destroy_past_end_array() { // expected-error {{never produces a constant expression}}
1245 A a[2];
1246 a[2].~A(); // expected-note {{destruction of dereferenced one-past-the-end pointer}}
1249 union As {
1250 A a, b;
1253 constexpr void destroy_no_active() { // expected-error {{never produces a constant expression}}
1254 As as;
1255 as.b.~A(); // expected-note {{destruction of member 'b' of union with no active member}}
1258 constexpr void destroy_inactive() { // expected-error {{never produces a constant expression}}
1259 As as;
1260 as.a.n = 1;
1261 as.b.~A(); // expected-note {{destruction of member 'b' of union with active member 'a'}}
1264 constexpr void destroy_no_active_2() { // expected-error {{never produces a constant expression}}
1265 As as;
1266 as.a.n = 1;
1267 as.a.~A();
1268 // FIXME: This diagnostic is wrong; the union has no active member now.
1269 as.b.~A(); // expected-note {{destruction of member 'b' of union with active member 'a'}}
1272 constexpr void destroy_pointer() {
1273 using T = int*;
1274 T p;
1275 // We used to think this was an -> member access because its left-hand side
1276 // is a pointer. Ensure we don't crash.
1277 p.~T();
1278 // Put a T back so we can destroy it again.
1279 std::construct(&p);
1281 static_assert((destroy_pointer(), true));
1284 namespace temp_dtor {
1285 void f();
1286 struct A {
1287 bool b;
1288 constexpr ~A() { if (b) f(); }
1291 // We can't accept either of these unless we start actually registering the
1292 // destructors of the A temporaries to run on shutdown. It's unclear what the
1293 // intended standard behavior is so we reject this for now.
1294 constexpr A &&a = A{false}; // expected-error {{constant}} expected-note {{non-trivial destruction of lifetime-extended temporary}}
1295 void f() { a.b = true; }
1297 constexpr A &&b = A{true}; // expected-error {{constant}} expected-note {{non-trivial destruction of lifetime-extended temporary}}
1299 // FIXME: We could in prinicple accept this.
1300 constexpr const A &c = A{false}; // expected-error {{constant}} expected-note {{non-trivial destruction of lifetime-extended temporary}}
1303 namespace value_dependent_init {
1304 struct A {
1305 constexpr ~A() {}
1307 template<typename T> void f() {
1308 A a = T();
1312 namespace mutable_subobjects {
1313 struct A {
1314 int m;
1315 mutable int n; // expected-note 2{{here}}
1316 constexpr int f() const { return m; }
1317 constexpr int g() const { return n; } // expected-note {{mutable}}
1320 constexpr A a = {1, 2};
1321 static_assert(a.f() == 1); // OK (PR44958)
1322 static_assert(a.g() == 2); // expected-error {{constant}} expected-note {{in call}}
1324 constexpr A b = a; // expected-error {{constant}} expected-note {{read of mutable member 'n'}} expected-note {{in call}}
1326 auto &ti1 = typeid(a);
1327 auto &ti2 = typeid(a.m);
1328 auto &ti3 = typeid(a.n);
1330 constexpr void destroy1() { // expected-error {{constexpr}}
1331 a.~A(); // expected-note {{cannot modify an object that is visible outside}}
1333 using T = int;
1334 constexpr void destroy2() { // expected-error {{constexpr}}
1335 a.m.~T(); // expected-note {{cannot modify an object that is visible outside}}
1337 constexpr void destroy3() { // expected-error {{constexpr}}
1338 a.n.~T(); // expected-note {{cannot modify an object that is visible outside}}
1341 struct X {
1342 mutable int n = 0;
1343 virtual constexpr ~X() {}
1345 struct Y : X {
1347 constexpr Y y;
1348 constexpr const X *p = &y;
1349 constexpr const Y *q = dynamic_cast<const Y*>(p);
1351 // FIXME: It's unclear whether this should be accepted. The dynamic_cast is
1352 // undefined after 'z.y.~Y()`, for example. We essentially assume that all
1353 // objects that the evaluator can reach have unbounded lifetimes. (We make
1354 // the same assumption when evaluating member function calls.)
1355 struct Z {
1356 mutable Y y;
1358 constexpr Z z;
1359 constexpr const X *pz = &z.y;
1360 constexpr const Y *qz = dynamic_cast<const Y*>(pz);
1361 auto &zti = typeid(z.y);
1362 static_assert(&zti == &typeid(Y));
1365 namespace PR45133 {
1366 struct A { long x; };
1368 union U;
1369 constexpr A foo(U *up);
1371 union U {
1372 A a = foo(this); // expected-note {{in call to 'foo(&u)'}}
1373 int y;
1376 constexpr A foo(U *up) {
1377 up->y = 11; // expected-note {{assignment would change active union member during the initialization of a different member}}
1378 return {42};
1381 constinit U u = {}; // expected-error {{constant init}} expected-note {{constinit}}
1383 template<int> struct X {};
1385 union V {
1386 int a, b;
1387 constexpr V(X<0>) : a(a = 1) {} // ok
1388 constexpr V(X<1>) : a(b = 1) {} // expected-note {{assignment would change active union member during the initialization of a different member}}
1389 constexpr V(X<2>) : a() { b = 1; } // ok
1390 // This case (changing the active member then changing it back) is debatable,
1391 // but it seems appropriate to reject.
1392 constexpr V(X<3>) : a((b = 1, a = 1)) {} // expected-note {{assignment would change active union member during the initialization of a different member}}
1394 constinit V v0 = X<0>();
1395 constinit V v1 = X<1>(); // expected-error {{constant init}} expected-note {{constinit}} expected-note {{in call}}
1396 constinit V v2 = X<2>();
1397 constinit V v3 = X<3>(); // expected-error {{constant init}} expected-note {{constinit}} expected-note {{in call}}
1400 namespace PR45350 {
1401 int q;
1402 struct V { int n; int *p = &n; constexpr ~V() { *p = *p * 10 + n; }};
1403 constexpr int f(int n) {
1404 int k = 0;
1405 V *p = new V[n];
1406 for (int i = 0; i != n; ++i) {
1407 if (p[i].p != &p[i].n) return -1;
1408 p[i].n = i;
1409 p[i].p = &k;
1411 delete[] p;
1412 return k;
1414 // [expr.delete]p6:
1415 // In the case of an array, the elements will be destroyed in order of
1416 // decreasing address
1417 static_assert(f(6) == 543210);
1420 namespace PR47805 {
1421 struct A {
1422 bool bad = true;
1423 constexpr ~A() { if (bad) throw; }
1425 constexpr bool f(A a) { a.bad = false; return true; }
1426 constexpr bool b = f(A());
1428 struct B { B *p = this; };
1429 constexpr bool g(B b) { return &b == b.p; }
1430 static_assert(g({}));
1433 constexpr bool destroy_at_test() {
1434 int n = 0;
1435 std::destroy(&n);
1436 std::construct(&n);
1437 return true;
1439 static_assert(destroy_at_test());
1441 namespace PR48582 {
1442 struct S {
1443 void *p = this;
1444 constexpr S() {}
1445 constexpr S(const S&) {}
1447 constexpr bool b = [a = S(), b = S()] { return a.p == b.p; }();
1448 static_assert(!b);
1451 namespace PR45879 {
1452 struct A { int n; };
1453 struct B { A a; };
1454 constexpr A a = (A() = B().a);
1456 union C {
1457 int n;
1458 A a;
1461 constexpr bool f() {
1462 C c = {.n = 1};
1463 c.a = B{2}.a;
1464 return c.a.n == 2;
1466 static_assert(f());
1468 // Only syntactic assignments change the active union member.
1469 constexpr bool g() { // expected-error {{never produces a constant expression}}
1470 C c = {.n = 1};
1471 c.a.operator=(B{2}.a); // expected-note 2{{member call on member 'a' of union with active member 'n' is not allowed in a constant expression}}
1472 return c.a.n == 2;
1474 static_assert(g()); // expected-error {{constant expression}} expected-note {{in call}}