1513 lines · cpp
1// RUN: %clang_cc1 -std=c++2a -verify %s -fcxx-exceptions -triple=x86_64-linux-gnu -Wno-mismatched-new-delete2 3#include "Inputs/std-compare.h"4 5namespace 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 {};15};16 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);22void operator delete(void*, const std::nothrow_t&) noexcept;23void operator delete(void*, std::align_val_t, const std::nothrow_t&) noexcept;24void operator delete[](void*, const std::nothrow_t&) noexcept;25void operator delete[](void*, std::align_val_t, const std::nothrow_t&) noexcept;26 27// Helper to print out values for debugging.28constexpr void not_defined();29template<typename T> constexpr void print(T) { not_defined(); }30 31namespace 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;36 }37 };38 static_assert(A{1} <=> A{2} < 0);39 static_assert(A{2} <=> A{1} > 0);40 static_assert(A{2} <=> A{2} == 0);41 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}}47 48 static_assert(std::strong_ordering::equal == 0);49 50 constexpr void f() {51 void(1 <=> 1);52 }53 54 struct MemPtr {55 void foo() {}56 void bar() {}57 int data;58 int data2;59 long data3;60 };61 62 struct MemPtr2 {63 void foo() {}64 void bar() {}65 int data;66 int data2;67 long data3;68 };69 using MemPtrT = void (MemPtr::*)();70 71 using FnPtrT = void (*)();72 73 void FnPtr1() {}74 void FnPtr2() {}75 76#define CHECK(...) ((__VA_ARGS__) ? void() : throw "error")77#define CHECK_TYPE(...) static_assert(__is_same(__VA_ARGS__));78 79constexpr bool test_constexpr_success = [] {80 {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));88 89 auto less = (-1 <=> 0);90 CHECK_TYPE(decltype(less), SO);91 CHECK(less.test_eq(LESS));92 93 auto greater = (42l <=> 1u);94 CHECK_TYPE(decltype(greater), SO);95 CHECK(greater.test_eq(GREATER));96 }97 {98 using PO = std::partial_ordering;99 auto EQUIV = PO::equivalent;100 auto LESS = PO::less;101 auto GREATER = PO::greater;102 103 auto eq = (42.0 <=> 42.0);104 CHECK_TYPE(decltype(eq), PO);105 CHECK(eq.test_eq(EQUIV));106 107 auto less = (39.0 <=> 42.0);108 CHECK_TYPE(decltype(less), PO);109 CHECK(less.test_eq(LESS));110 111 auto greater = (-10.123 <=> -101.1);112 CHECK_TYPE(decltype(greater), PO);113 CHECK(greater.test_eq(GREATER));114 }115 116 return true;117}();118 119int dummy = 42;120int dummy2 = 101;121constexpr bool tc9 = (&dummy <=> &dummy2) != 0; // expected-error {{constant expression}} expected-note {{unspecified}}122 123template <class T, class R, class I>124constexpr T makeComplex(R r, I i) {125 T res{r, i};126 return res;127};128} // namespace ThreeWayComparison129 130constexpr 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;134}135static_assert(for_range_init());136 137namespace Virtual {138 struct NonZeroOffset { int padding = 123; };139 140 constexpr void assert(bool b) { if (!b) throw 0; }141 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'); }147 };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'); }153 };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'); }162 };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'); }168 };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');183 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}}187 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;192 };193 template<typename T>194 struct Covariant2 : Covariant1 {195 virtual const T *f() const;196 };197 template<typename T>198 struct Covariant3 : Covariant2<T> {199 constexpr virtual const D *f() const { return &this->d; }200 };201 202 constexpr Covariant3<B> cb;203 constexpr Covariant3<C> cc;204 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');213 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');222 223 static_assert(cb.f()->d == 'D');224 static_assert(cc.f()->d == 'D');225 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}}230 };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}}233}234 235namespace 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 {};246 247 constexpr G g;248 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);253 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);257 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 {{}}260 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 {{}}268 269 // Can cast from A2 to sibling class D.270 static_assert(&dynamic_cast<D&>((A2&)(B&)g) == &(D&)g);271 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 {{}}275 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 {{}}279 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 {{}}285}286 287namespace TypeId {288 struct A {289 const std::type_info &ti = typeid(*this);290 };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));296 297 constexpr A2 a2;298 constexpr const A &a1 = a2;299 static_assert(&typeid(a1) == &typeid(A));300 301 struct B {302 virtual void f();303 const std::type_info &ti1 = typeid(*this);304 };305 struct B2 : B {306 const std::type_info &ti2 = typeid(*this);307 };308 static_assert(&B2().ti1 == &typeid(B));309 static_assert(&B2().ti2 == &typeid(B2));310 extern B2 extern_b2;311 static_assert(&typeid(extern_b2) == &typeid(B2));312 313 constexpr B2 b2;314 constexpr const B &b1 = b2;315 static_assert(&typeid(b1) == &typeid(B2));316 317 constexpr bool side_effects() {318 // Not polymorphic nor a glvalue.319 bool OK = true;320 (void)typeid(OK = false, A2()); // expected-warning {{has no effect}}321 if (!OK) return false;322 323 // Not polymorphic.324 A2 a2;325 (void)typeid(OK = false, a2); // expected-warning {{has no effect}}326 if (!OK) return false;327 328 // Not a glvalue.329 (void)typeid(OK = false, B2()); // expected-warning {{has no effect}}330 if (!OK) return false;331 332 // Polymorphic glvalue: operand evaluated.333 OK = false;334 B2 b2;335 (void)typeid(OK = true, b2); // expected-warning {{will be evaluated}}336 return OK;337 }338 static_assert(side_effects());339}340 341namespace Union {342 struct Base {343 int y; // expected-note 2{{here}}344 };345 struct A : Base {346 int x;347 int arr[3];348 union { int p, q; };349 };350 union B {351 A a;352 int b;353 };354 constexpr int read_wrong_member() { // expected-error {{never produces a constant}}355 B b = {.b = 1};356 return b.a.x; // expected-note {{read of member 'a' of union with active member 'b'}}357 }358 constexpr int change_member() {359 B b = {.b = 1};360 b.a.x = 1;361 return b.a.x;362 }363 static_assert(change_member() == 1);364 constexpr int change_member_then_read_wrong_member() { // expected-error {{never produces a constant}}365 B b = {.b = 1};366 b.a.x = 1;367 return b.b; // expected-note {{read of member 'b' of union with active member 'a'}}368 }369 constexpr int read_wrong_member_indirect() { // expected-error {{never produces a constant}}370 B b = {.b = 1};371 int *p = &b.a.y;372 return *p; // expected-note {{read of member 'a' of union with active member 'b'}}373 }374 constexpr int read_uninitialized() {375 B b = {.b = 1};376 int *p = &b.a.y;377 b.a.x = 1;378 return *p; // expected-note {{read of uninitialized object}}379 }380 static_assert(read_uninitialized() == 0); // expected-error {{constant}} expected-note {{in call}}381 constexpr void write_wrong_member_indirect() { // expected-error {{never produces a constant}}382 B b = {.b = 1};383 int *p = &b.a.y;384 *p = 1; // expected-note {{assignment to member 'a' of union with active member 'b'}}385 }386 constexpr int write_uninitialized() {387 B b = {.b = 1};388 int *p = &b.a.y;389 b.a.x = 1;390 *p = 1;391 return *p;392 }393 static_assert(write_uninitialized() == 1);394 constexpr int change_member_indirectly() {395 B b = {.b = 1};396 b.a.arr[1] = 1;397 int &r = b.a.y;398 r = 123;399 400 b.b = 2;401 b.a.y = 3;402 b.a.arr[2] = 4;403 return b.a.arr[2];404 }405 static_assert(change_member_indirectly() == 4);406 constexpr B return_uninit() {407 B b = {.b = 1};408 b.a.x = 2;409 return b;410 }411 constexpr B uninit = return_uninit(); // expected-error {{constant expression}} expected-note {{subobject 'y' is not initialized}}412 static_assert(return_uninit().a.x == 2);413 constexpr A return_uninit_struct() {414 B b = {.b = 1};415 b.a.x = 2;416 return b.a; // expected-note {{in call to 'A(b.a)'}} expected-note {{subobject 'y' is not initialized}}417 }418 // Note that this is rejected even though return_uninit() is accepted, and419 // return_uninit() copies the same stuff wrapped in a union.420 //421 // Copying a B involves copying the object representation of the union, but422 // copying an A invokes a copy constructor that copies the object423 // elementwise, and reading from b.a.y is undefined.424 static_assert(return_uninit_struct().x == 2); // expected-error {{constant expression}} expected-note {{in call}}425 constexpr B return_init_all() {426 B b = {.b = 1};427 b.a.x = 2;428 b.a.y = 3;429 b.a.arr[0] = 4;430 b.a.arr[1] = 5;431 b.a.arr[2] = 6;432 return b;433 }434 static_assert(return_init_all().a.x == 2);435 static_assert(return_init_all().a.y == 3);436 static_assert(return_init_all().a.arr[0] == 4);437 static_assert(return_init_all().a.arr[1] == 5);438 static_assert(return_init_all().a.arr[2] == 6);439 static_assert(return_init_all().a.p == 7); // expected-error {{}} expected-note {{read of member 'p' of union with no active member}}440 static_assert(return_init_all().a.q == 8); // expected-error {{}} expected-note {{read of member 'q' of union with no active member}}441 constexpr B init_all = return_init_all();442 443 constexpr bool test_no_member_change = []{444 union U { char dummy = {}; };445 U u1;446 U u2;447 u1 = u2;448 return true;449 }();450 451 struct S1 {452 int n;453 };454 struct S2 : S1 {};455 struct S3 : S2 {};456 void f() {457 S3 s;458 s.n = 0;459 }460 461 union ref_member_1 {462 int a;463 int b;464 };465 struct ref_member_2 {466 ref_member_1 &&r;467 };468 union ref_member_3 {469 ref_member_2 a, b;470 };471 constexpr int ref_member_test_1() {472 ref_member_3 r = {.a = {.r = {.a = 1}}};473 r.a.r.b = 2;474 return r.a.r.b;475 }476 static_assert(ref_member_test_1() == 2);477 constexpr int ref_member_test_2() { // expected-error {{never produces a constant}}478 ref_member_3 r = {.a = {.r = {.a = 1}}};479 // FIXME: This note isn't great. The 'read' here is reading the referent of the reference.480 r.b.r.b = 2; // expected-note {{read of member 'b' of union with active member 'a'}}481 return r.b.r.b;482 }483 484 namespace PR43762 {485 struct A { int x = 1; constexpr int f() { return 1; } };486 struct B : A { int y = 1; constexpr int g() { return 2; } };487 struct C {488 int x;489 constexpr virtual int f() = 0;490 };491 struct D : C {492 int y;493 constexpr virtual int f() override { return 3; }494 };495 496 union U {497 int n;498 B b;499 D d;500 };501 502 constexpr int test(int which) {503 U u{.n = 5};504 switch (which) {505 case 0:506 u.b.x = 10; // expected-note {{active member 'n'}}507 return u.b.f();508 case 1:509 u.b.y = 10; // expected-note {{active member 'n'}}510 return u.b.g();511 case 2:512 u.d.x = 10; // expected-note {{active member 'n'}}513 return u.d.f();514 case 3:515 u.d.y = 10; // expected-note {{active member 'n'}}516 return u.d.f();517 }518 }519 520 static_assert(test(0)); // expected-error {{}} expected-note {{in call}}521 static_assert(test(1)); // expected-error {{}} expected-note {{in call}}522 static_assert(test(2)); // expected-error {{}} expected-note {{in call}}523 static_assert(test(3)); // expected-error {{}} expected-note {{in call}}524 }525}526 527namespace TwosComplementShifts {528 using uint32 = __UINT32_TYPE__;529 using int32 = __INT32_TYPE__;530 static_assert(uint32(int32(0x1234) << 16) == 0x12340000);531 static_assert(uint32(int32(0x1234) << 19) == 0x91a00000);532 static_assert(uint32(int32(0x1234) << 20) == 0x23400000);533 static_assert(uint32(int32(0x1234) << 24) == 0x34000000);534 static_assert(uint32(int32(-1) << 31) == 0x80000000);535 536 static_assert(-1 >> 1 == -1);537 static_assert(-1 >> 31 == -1);538 static_assert(-2 >> 1 == -1);539 static_assert(-3 >> 1 == -2);540 static_assert(-4 >> 1 == -2);541}542 543namespace Uninit {544 constexpr int f(bool init) {545 int a;546 if (init)547 a = 1;548 return a; // expected-note {{read of uninitialized object}}549 }550 static_assert(f(true) == 1);551 static_assert(f(false) == 1); // expected-error {{constant expression}} expected-note {{in call}}552 553 struct X {554 int n; // expected-note {{declared here}}555 constexpr X(bool init) {556 if (init) n = 123;557 }558 };559 constinit X x1(true);560 constinit X x2(false); // expected-error {{constant initializer}} expected-note {{constinit}} expected-note {{subobject 'n' is not initialized}}561 562 struct Y {563 struct Z { int n; }; // expected-note {{here}}564 Z z1;565 Z z2;566 Z z3;567 // OK: the lifetime of z1 (and its members) start before the initializer of568 // z2 runs.569 constexpr Y() : z2{ (z1.n = 1, z1.n + 1) } { z3.n = 3; }570 // Not OK: z3 is not in its lifetime when the initializer of z2 runs.571 constexpr Y(int) : z2{572 (z3.n = 1, // expected-note {{assignment to object outside its lifetime}}573 z3.n + 1) // expected-warning {{uninitialized}}574 } { z1.n = 3; }575 constexpr Y(int, int) : z2{} {}576 };577 // FIXME: This is working around clang not implementing DR2026. With that578 // fixed, we should be able to test this without the injected copy.579 constexpr Y copy(Y y) { return y; } // expected-note {{in call to 'Y(y)'}} expected-note {{subobject 'n' is not initialized}}580 constexpr Y y1 = copy(Y());581 static_assert(y1.z1.n == 1 && y1.z2.n == 2 && y1.z3.n == 3);582 583 constexpr Y y2 = copy(Y(0)); // expected-error {{constant expression}} expected-note {{in call}}584 585 static_assert(Y(0,0).z2.n == 0);586 static_assert(Y(0,0).z1.n == 0); // expected-error {{constant expression}} expected-note {{read of uninitialized object}}587 static_assert(Y(0,0).z3.n == 0); // expected-error {{constant expression}} expected-note {{read of uninitialized object}}588 589 static_assert(copy(Y(0,0)).z2.n == 0); // expected-error {{constant expression}} expected-note {{in call}}590 591 constexpr unsigned char not_even_unsigned_char() {592 unsigned char c;593 return c; // expected-note {{read of uninitialized object}}594 }595 constexpr unsigned char x = not_even_unsigned_char(); // expected-error {{constant expression}} expected-note {{in call}}596 597 constexpr int switch_var(int n) {598 switch (n) {599 case 1:600 int a;601 a = n;602 return a;603 604 case 2:605 a = n;606 return a;607 }608 }609 constexpr int s1 = switch_var(1);610 constexpr int s2 = switch_var(2);611 static_assert(s1 == 1 && s2 == 2);612 613 constexpr bool switch_into_init_stmt() {614 switch (1) {615 if (int n; false) {616 for (int m; false;) {617 case 1:618 n = m = 1;619 return n == 1 && m == 1;620 }621 }622 }623 }624 static_assert(switch_into_init_stmt());625}626 627namespace dtor {628 void lifetime_extension() {629 struct X { constexpr ~X() {} };630 X &&a = X();631 }632 633 template<typename T> constexpr T &&ref(T &&t) { return (T&&)t; }634 635 struct Buf {636 char buf[64];637 int n = 0;638 constexpr void operator+=(char c) { buf[n++] = c; }639 constexpr bool operator==(const char *str) const {640 return str[n] == 0 && __builtin_memcmp(str, buf, n) == 0;641 }642 constexpr bool operator!=(const char *str) const { return !operator==(str); }643 };644 645 struct A {646 constexpr A(Buf &buf, char c) : buf(buf), c(c) { buf += c; }647 constexpr ~A() { buf += c; }648 constexpr operator bool() const { return true; }649 Buf &buf;650 char c;651 };652 653 constexpr bool dtor_calls_dtor() {654 union U {655 constexpr U(Buf &buf) : u(buf, 'u') { buf += 'U'; }656 constexpr ~U() { u.buf += 'U'; }657 A u, v;658 };659 660 struct B : A {661 A c, &&d, e;662 union {663 A f;664 };665 U u;666 constexpr B(Buf &buf)667 : A(buf, 'a'), c(buf, 'c'), d(ref(A(buf, 'd'))), e(A(buf, 'e')), f(buf, 'f'), u(buf) {668 buf += 'b';669 }670 constexpr ~B() {671 buf += 'b';672 }673 };674 675 Buf buf;676 {677 B b(buf);678 if (buf != "acddefuUb")679 return false;680 }681 if (buf != "acddefuUbbUeca")682 return false;683 return true;684 }685 static_assert(dtor_calls_dtor());686 687 constexpr void abnormal_termination(Buf &buf) {688 struct Indestructible {689 constexpr ~Indestructible(); // not defined690 };691 692 A a(buf, 'a');693 A(buf, 'b');694 int n = 0;695 for (A &&c = A(buf, 'c'); A d = A(buf, 'd'); A(buf, 'e')) {696 switch (A f(buf, 'f'); A g = A(buf, 'g')) { // expected-warning {{boolean}}697 case false: {698 A x(buf, 'x');699 }700 701 case true: {702 A h(buf, 'h');703 switch (n++) {704 case 0:705 break;706 case 1:707 continue;708 case 2:709 return;710 }711 break;712 }713 714 default:715 Indestructible indest;716 }717 718 A j = (A(buf, 'i'), A(buf, 'j'));719 }720 }721 722 constexpr bool check_abnormal_termination() {723 Buf buf = {};724 abnormal_termination(buf);725 return buf ==726 "abbc"727 "dfgh" /*break*/ "hgfijijeed"728 "dfgh" /*continue*/ "hgfeed"729 "dfgh" /*return*/ "hgfd"730 "ca";731 }732 static_assert(check_abnormal_termination());733 734 constexpr bool run_dtors_on_array_filler() {735 struct S {736 int times_destroyed = 0;737 constexpr ~S() { if (++times_destroyed != 1) throw "oops"; }738 };739 S s[3];740 return true;741 }742 static_assert(run_dtors_on_array_filler());743 744 // Ensure that we can handle temporary cleanups for array temporaries.745 struct ArrElem { constexpr ~ArrElem() {} };746 using Arr = ArrElem[3];747 static_assert(((void)Arr{}, true));748}749 750namespace dynamic_alloc {751 constexpr int *p = // expected-error {{constant}} expected-note {{pointer to heap-allocated object is not a constant expression}}752 new int; // expected-note {{heap allocation performed here}}753 754 constexpr int f(int n) {755 int *p = new int[n];756 for (int i = 0; i != n; ++i) {757 p[i] = i;758 }759 int k = 0;760 for (int i = 0; i != n; ++i) {761 k += p[i];762 }763 delete[] p;764 return k;765 }766 static_assert(f(123) == 123 * 122 / 2);767 768 constexpr bool nvdtor() { // expected-error {{never produces a constant expression}}769 struct S {770 constexpr ~S() {}771 };772 struct T : S {};773 delete (S*)new T; // expected-note {{delete of object with dynamic type 'T' through pointer to base class type 'S' with non-virtual destructor}}774 return true;775 }776 777 constexpr int vdtor_1() {778 int a;779 struct S {780 constexpr S(int *p) : p(p) {}781 constexpr virtual ~S() { *p = 1; }782 int *p;783 };784 struct T : S {785 // implicit destructor defined eagerly because it is constexpr and virtual786 using S::S;787 };788 delete (S*)new T(&a);789 return a;790 }791 static_assert(vdtor_1() == 1);792 793 constexpr int vdtor_2() {794 int a = 0;795 struct S { constexpr virtual ~S() {} };796 struct T : S {797 constexpr T(int *p) : p(p) {}798 constexpr ~T() { ++*p; }799 int *p;800 };801 S *p = new T{&a};802 delete p;803 return a;804 }805 static_assert(vdtor_2() == 1);806 807 constexpr int vdtor_3(int mode) {808 int a = 0;809 struct S { constexpr virtual ~S() {} };810 struct T : S {811 constexpr T(int *p) : p(p) {}812 constexpr ~T() { ++*p; }813 int *p;814 };815 S *p = new T[3]{&a, &a, &a}; // expected-note 2{{heap allocation}}816 switch (mode) {817 case 0:818 delete p; // expected-note {{non-array delete used to delete pointer to array object of type 'T[3]'}}819 break;820 case 1:821 // FIXME: This diagnosic isn't great; we should mention the cast to S*822 // somewhere in here.823 delete[] p; // expected-note {{delete of pointer to subobject '&{*new T[3]#0}[0]'}}824 break;825 case 2:826 delete (T*)p; // expected-note {{non-array delete used to delete pointer to array object of type 'T[3]'}}827 break;828 case 3:829 delete[] (T*)p;830 break;831 }832 return a;833 }834 static_assert(vdtor_3(0) == 3); // expected-error {{}} expected-note {{in call}}835 static_assert(vdtor_3(1) == 3); // expected-error {{}} expected-note {{in call}}836 static_assert(vdtor_3(2) == 3); // expected-error {{}} expected-note {{in call}}837 static_assert(vdtor_3(3) == 3);838 839 constexpr void delete_mismatch() { // expected-error {{never produces a constant expression}}840 delete[] // expected-note {{array delete used to delete pointer to non-array object of type 'int'}}841 new int; // expected-note {{allocation}}842 }843 844 template<typename T>845 constexpr T dynarray(int elems, int i) {846 T *p;847 if constexpr (sizeof(T) == 1)848 p = new T[elems]{"fox"}; // expected-note {{evaluated array bound 3 is too small to hold 4 explicitly initialized elements}}849 else850 p = new T[elems]{1, 2, 3}; // expected-note {{evaluated array bound 2 is too small to hold 3 explicitly initialized elements}}851 T n = p[i]; // expected-note 4{{past-the-end}}852 delete [] p;853 return n;854 }855 static_assert(dynarray<int>(4, 0) == 1);856 static_assert(dynarray<int>(4, 1) == 2);857 static_assert(dynarray<int>(4, 2) == 3);858 static_assert(dynarray<int>(4, 3) == 0);859 static_assert(dynarray<int>(4, 4) == 0); // expected-error {{constant expression}} expected-note {{in call}}860 static_assert(dynarray<int>(3, 2) == 3);861 static_assert(dynarray<int>(3, 3) == 0); // expected-error {{constant expression}} expected-note {{in call}}862 static_assert(dynarray<int>(2, 1) == 0); // expected-error {{constant expression}} expected-note {{in call}}863 static_assert(dynarray<char>(5, 0) == 'f');864 static_assert(dynarray<char>(5, 1) == 'o');865 static_assert(dynarray<char>(5, 2) == 'x');866 static_assert(dynarray<char>(5, 3) == 0); // (from string)867 static_assert(dynarray<char>(5, 4) == 0); // (from filler)868 static_assert(dynarray<char>(5, 5) == 0); // expected-error {{constant expression}} expected-note {{in call}}869 static_assert(dynarray<char>(4, 0) == 'f');870 static_assert(dynarray<char>(4, 1) == 'o');871 static_assert(dynarray<char>(4, 2) == 'x');872 static_assert(dynarray<char>(4, 3) == 0);873 static_assert(dynarray<char>(4, 4) == 0); // expected-error {{constant expression}} expected-note {{in call}}874 static_assert(dynarray<char>(3, 2) == 'x'); // expected-error {{constant expression}} expected-note {{in call}}875 876 constexpr bool run_dtors_on_array_filler() {877 struct S {878 int times_destroyed = 0;879 constexpr ~S() { if (++times_destroyed != 1) throw "oops"; }880 };881 delete[] new S[3];882 return true;883 }884 static_assert(run_dtors_on_array_filler());885 886 constexpr bool erroneous_array_bound(long long n) {887 delete[] new int[n]; // expected-note {{array bound -1 is negative}} expected-note {{array bound 4611686018427387904 is too large}}888 return true;889 }890 static_assert(erroneous_array_bound(3));891 static_assert(erroneous_array_bound(0));892 static_assert(erroneous_array_bound(-1)); // expected-error {{constant expression}} expected-note {{in call}}893 static_assert(erroneous_array_bound(1LL << 62)); // expected-error {{constant expression}} expected-note {{in call}}894 895 constexpr bool erroneous_array_bound_nothrow(long long n) {896 int *p = new (std::nothrow) int[n];897 bool result = p != 0;898 delete[] p;899 return result;900 }901 static_assert(erroneous_array_bound_nothrow(3));902 static_assert(erroneous_array_bound_nothrow(0));903 static_assert(!erroneous_array_bound_nothrow(-1));904 static_assert(!erroneous_array_bound_nothrow(1LL << 62));905 906 constexpr bool evaluate_nothrow_arg() {907 bool ok = false;908 delete new ((ok = true, std::nothrow)) int;909 return ok;910 }911 static_assert(evaluate_nothrow_arg());912 913 constexpr void double_delete() { // expected-error {{never produces a constant expression}}914 int *p = new int;915 delete p;916 delete p; // expected-note {{delete of pointer that has already been deleted}}917 }918 constexpr bool super_secret_double_delete() {919 struct A {920 constexpr ~A() { delete this; } // expected-note {{destruction of object that is already being destroyed}} expected-note {{in call}}921 };922 delete new A; // expected-note {{in call}}923 return true;924 }925 static_assert(super_secret_double_delete()); // expected-error {{constant expression}} expected-note {{in call}}926 927 constexpr void use_after_free() { // expected-error {{never produces a constant expression}}928 int *p = new int;929 delete p;930 *p = 1; // expected-note {{read of heap allocated object that has been deleted}}931 }932 constexpr void use_after_free_2() { // expected-error {{never produces a constant expression}}933 struct X { constexpr void f() {} };934 X *p = new X;935 delete p;936 p->f(); // expected-note {{member call on heap allocated object that has been deleted}}937 }938 939 template<typename T> struct X {940 std::size_t n;941 char *p;942 void dependent();943 };944 template<typename T> void X<T>::dependent() {945 char *p;946 // Ensure that we don't try to evaluate these for overflow and crash. These947 // are all value-dependent expressions.948 p = new char[n];949 p = new ((std::align_val_t)n) char[n];950 p = new char(n);951 }952 953 namespace PR47143 {954 constexpr char *f(int n) {955 return new char[n]();956 }957 const char *p = f(3);958 constexpr bool test() {959 char *p = f(3);960 bool result = !p[0] && !p[1] && !p[2];961 delete [] p;962 return result;963 }964 static_assert(test());965 }966}967 968struct placement_new_arg {};969void *operator new(std::size_t, placement_new_arg);970void operator delete(void*, placement_new_arg);971 972namespace placement_new_delete {973 struct ClassSpecificNew {974 void *operator new(std::size_t);975 };976 struct ClassSpecificDelete {977 void operator delete(void*);978 };979 struct DestroyingDelete {980 void operator delete(DestroyingDelete*, std::destroying_delete_t);981 };982 struct alignas(64) Overaligned {};983 984 constexpr bool ok() {985 delete new Overaligned;986 delete ::new ClassSpecificNew;987 ::delete new ClassSpecificDelete;988 ::delete new DestroyingDelete;989 return true;990 }991 static_assert(ok());992 993 constexpr bool bad(int which) {994 switch (which) {995 case 0:996 delete new (placement_new_arg{}) int; // expected-note {{this placement new expression is not supported in constant expressions}}997 break;998 999 case 1:1000 delete new ClassSpecificNew; // expected-note {{call to class-specific 'operator new'}}1001 break;1002 1003 case 2:1004 delete new ClassSpecificDelete; // expected-note {{call to class-specific 'operator delete'}}1005 break;1006 1007 case 3:1008 delete new DestroyingDelete; // expected-note {{call to class-specific 'operator delete'}}1009 break;1010 1011 case 4:1012 // FIXME: This technically follows the standard's rules, but it seems1013 // unreasonable to expect implementations to support this.1014 delete new (std::align_val_t{64}) Overaligned; // expected-note {{this placement new expression is not supported in constant expressions}}1015 break;1016 }1017 1018 return true;1019 }1020 static_assert(bad(0)); // expected-error {{constant expression}} expected-note {{in call}}1021 static_assert(bad(1)); // expected-error {{constant expression}} expected-note {{in call}}1022 static_assert(bad(2)); // expected-error {{constant expression}} expected-note {{in call}}1023 static_assert(bad(3)); // expected-error {{constant expression}} expected-note {{in call}}1024 static_assert(bad(4)); // expected-error {{constant expression}} expected-note {{in call}}1025}1026 1027namespace delete_random_things {1028 static_assert((delete new int, true));1029 static_assert((delete (int*)0, true));1030 int n; // expected-note {{declared here}}1031 static_assert((delete &n, true)); // expected-error {{}} expected-note {{delete of pointer '&n' that does not point to a heap-allocated object}}1032 struct A { int n; };1033 static_assert((delete &(new A)->n, true)); // expected-error {{}} expected-note {{delete of pointer to subobject '&{*new A#0}.n'}}1034 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}}1035 static_assert((delete[] (new int[3] + 1), true)); // expected-error {{}} expected-note {{delete of pointer to subobject '&{*new int[3]#0}[1]'}}1036 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}}1037}1038 1039namespace value_dependent_delete {1040 template<typename T> void f(T *p) {1041 int arr[(delete p, 0)];1042 }1043}1044 1045namespace memory_leaks {1046 static_assert(*new bool(true)); // expected-error {{}} expected-note {{allocation performed here was not deallocated}}1047 1048 constexpr bool *f() { return new bool(true); } // expected-note {{allocation performed here was not deallocated}}1049 static_assert(*f()); // expected-error {{}}1050 1051 struct UP {1052 bool *p;1053 constexpr ~UP() { delete p; }1054 constexpr bool &operator*() { return *p; }1055 };1056 constexpr UP g() { return {new bool(true)}; }1057 static_assert(*g()); // ok1058 1059 constexpr bool h(UP p) { return *p; }1060 static_assert(h({new bool(true)})); // ok1061}1062 1063constexpr void *operator new(std::size_t, void *p) { return p; }1064namespace std {1065 template<typename T> constexpr T *construct(T *p) { return new (p) T; }1066 template<typename T> constexpr void destroy(T *p) { p->~T(); }1067}1068 1069namespace dtor_call {1070 struct A { int n; };1071 constexpr void f() { // expected-error {{never produces a constant expression}}1072 A a; // expected-note {{destroying object 'a' whose lifetime has already ended}}1073 a.~A();1074 }1075 union U { A a; };1076 constexpr void g() {1077 U u;1078 u.a.n = 3;1079 u.a.~A();1080 // There's now effectively no active union member, but we model it as if1081 // 'a' is still the active union member (but its lifetime has ended).1082 u.a.n = 4; // Start lifetime of 'a' again.1083 u.a.~A();1084 }1085 static_assert((g(), true));1086 1087 constexpr bool pseudo(bool read, bool recreate) {1088 using T = bool;1089 bool b = false; // expected-note {{lifetime has already ended}}1090 // This evaluates the store to 'b'...1091 (b = true).~T();1092 // ... and ends the lifetime of the object.1093 return (read1094 ? b // expected-note {{read of object outside its lifetime}}1095 : true) +1096 (recreate1097 ? (std::construct(&b), true)1098 : true);1099 }1100 static_assert(pseudo(false, false)); // expected-error {{constant expression}} expected-note {{in call}}1101 static_assert(pseudo(true, false)); // expected-error {{constant expression}} expected-note {{in call}}1102 static_assert(pseudo(false, true));1103 1104 constexpr void use_after_destroy() {1105 A a;1106 a.~A();1107 A b = a; // expected-note {{in call}} expected-note {{read of object outside its lifetime}}1108 }1109 static_assert((use_after_destroy(), true)); // expected-error {{}} expected-note {{in call}}1110 1111 constexpr void double_destroy() {1112 A a;1113 a.~A();1114 a.~A(); // expected-note {{destruction of object outside its lifetime}}1115 }1116 static_assert((double_destroy(), true)); // expected-error {{}} expected-note {{in call}}1117 1118 struct X { char *p; constexpr ~X() { *p++ = 'X'; } };1119 struct Y : X { int y; virtual constexpr ~Y() { *p++ = 'Y'; } };1120 struct Z : Y { int z; constexpr ~Z() override { *p++ = 'Z'; } };1121 union VU {1122 constexpr VU() : z() {}1123 constexpr ~VU() {}1124 Z z;1125 };1126 1127 constexpr bool virt_dtor(int mode, const char *expected) {1128 char buff[4] = {};1129 VU vu;1130 vu.z.p = buff;1131 switch (mode) {1132 case 0:1133 vu.z.~Z();1134 break;1135 case 1:1136 ((Y&)vu.z).~Y();1137 break;1138 case 2:1139 ((X&)vu.z).~X();1140 break;1141 case 3:1142 ((Y&)vu.z).Y::~Y();1143 vu.z.z = 1; // ok, still have a Z (with no Y base class!)1144 break;1145 case 4:1146 ((X&)vu.z).X::~X();1147 vu.z.y = 1; // ok, still have a Z and a Y (with no X base class!)1148 break;1149 }1150 return __builtin_strcmp(expected, buff) == 0;1151 }1152 static_assert(virt_dtor(0, "ZYX"));1153 static_assert(virt_dtor(1, "ZYX"));1154 static_assert(virt_dtor(2, "X"));1155 static_assert(virt_dtor(3, "YX"));1156 static_assert(virt_dtor(4, "X"));1157 1158 constexpr bool virt_delete(bool global) {1159 struct A {1160 virtual constexpr ~A() {}1161 };1162 struct B : A {1163 void operator delete(void *);1164 constexpr ~B() {}1165 };1166 1167 A *p = new B;1168 if (global)1169 ::delete p;1170 else1171 delete p; // expected-note {{call to class-specific 'operator delete'}}1172 return true;1173 }1174 static_assert(virt_delete(true));1175 static_assert(virt_delete(false)); // expected-error {{}} expected-note {{in call}}1176 1177 constexpr void use_after_virt_destroy() {1178 char buff[4] = {};1179 VU vu;1180 vu.z.p = buff;1181 ((Y&)vu.z).~Y();1182 ((Z&)vu.z).z = 1; // expected-note {{assignment to object outside its lifetime}}1183 }1184 static_assert((use_after_virt_destroy(), true)); // expected-error {{}} expected-note {{in call}}1185 1186 constexpr void destroy_after_lifetime() {1187 A *p;1188 {1189 A a;1190 p = &a;1191 }1192 p->~A(); // expected-note {{destruction of object outside its lifetime}}1193 }1194 static_assert((destroy_after_lifetime(), true)); // expected-error {{}} expected-note {{in call}}1195 1196 constexpr void destroy_after_lifetime2() {1197 A *p = []{ A a; return &a; }(); // expected-warning {{}} expected-note {{declared here}}1198 p->~A(); // expected-note {{destruction of variable whose lifetime has ended}}1199 }1200 static_assert((destroy_after_lifetime2(), true)); // expected-error {{}} expected-note {{in call}}1201 1202 constexpr void destroy_after_lifetime3() {1203 A *p = []{ return &(A&)(A&&)A(); }(); // expected-warning {{}} expected-note {{temporary created here}}1204 p->~A(); // expected-note {{destruction of temporary whose lifetime has ended}}1205 }1206 static_assert((destroy_after_lifetime3(), true)); // expected-error {{}} expected-note {{in call}}1207 1208 constexpr void destroy_after_lifetime4() { // expected-error {{never produces a constant expression}}1209 A *p = new A;1210 delete p;1211 p->~A(); // expected-note {{destruction of heap allocated object that has been deleted}}1212 }1213 1214 struct Extern { constexpr ~Extern() {} } extern e;1215 constexpr void destroy_extern() { // expected-error {{never produces a constant expression}}1216 e.~Extern(); // expected-note {{cannot modify an object that is visible outside}}1217 }1218 1219 constexpr A &&a_ref = A(); // expected-note {{temporary created here}}1220 constexpr void destroy_extern_2() { // expected-error {{never produces a constant expression}}1221 a_ref.~A(); // expected-note {{destruction of temporary is not allowed in a constant expression outside the expression that created the temporary}}1222 }1223 1224 struct S {1225 constexpr S() { n = 1; }1226 constexpr ~S() { n = 0; }1227 int n;1228 };1229 constexpr void destroy_volatile() {1230 volatile S s;1231 }1232 static_assert((destroy_volatile(), true)); // ok, not volatile during construction and destruction1233 1234 constexpr void destroy_null() { // expected-error {{never produces a constant expression}}1235 ((A*)nullptr)->~A(); // expected-note {{destruction of dereferenced null pointer}}1236 }1237 1238 constexpr void destroy_past_end() { // expected-error {{never produces a constant expression}}1239 A a;1240 (&a+1)->~A(); // expected-note {{destruction of dereferenced one-past-the-end pointer}}1241 }1242 1243 constexpr void destroy_past_end_array() { // expected-error {{never produces a constant expression}}1244 A a[2];1245 a[2].~A(); // expected-note {{destruction of dereferenced one-past-the-end pointer}}1246 }1247 1248 union As {1249 A a, b;1250 };1251 1252 constexpr void destroy_no_active() { // expected-error {{never produces a constant expression}}1253 As as;1254 as.b.~A(); // expected-note {{destruction of member 'b' of union with no active member}}1255 }1256 1257 constexpr void destroy_inactive() { // expected-error {{never produces a constant expression}}1258 As as;1259 as.a.n = 1;1260 as.b.~A(); // expected-note {{destruction of member 'b' of union with active member 'a'}}1261 }1262 1263 constexpr void destroy_no_active_2() { // expected-error {{never produces a constant expression}}1264 As as;1265 as.a.n = 1;1266 as.a.~A();1267 // FIXME: This diagnostic is wrong; the union has no active member now.1268 as.b.~A(); // expected-note {{destruction of member 'b' of union with active member 'a'}}1269 }1270 1271 constexpr void destroy_pointer() {1272 using T = int*;1273 T p;1274 // We used to think this was an -> member access because its left-hand side1275 // is a pointer. Ensure we don't crash.1276 p.~T();1277 // Put a T back so we can destroy it again.1278 std::construct(&p);1279 }1280 static_assert((destroy_pointer(), true));1281}1282 1283namespace temp_dtor {1284 void f();1285 struct A {1286 bool b;1287 constexpr ~A() { if (b) f(); }1288 };1289 1290 // We can't accept either of these unless we start actually registering the1291 // destructors of the A temporaries to run on shutdown. It's unclear what the1292 // intended standard behavior is so we reject this for now.1293 constexpr A &&a = A{false}; // expected-error {{constant}} expected-note {{non-trivial destruction of lifetime-extended temporary}}1294 void f() { a.b = true; }1295 1296 constexpr A &&b = A{true}; // expected-error {{constant}} expected-note {{non-trivial destruction of lifetime-extended temporary}}1297 1298 // FIXME: We could in prinicple accept this.1299 constexpr const A &c = A{false}; // expected-error {{constant}} expected-note {{non-trivial destruction of lifetime-extended temporary}}1300}1301 1302namespace value_dependent_init {1303 struct A {1304 constexpr ~A() {}1305 };1306 template<typename T> void f() {1307 A a = T();1308 }1309}1310 1311namespace mutable_subobjects {1312 struct A {1313 int m;1314 mutable int n; // expected-note 2{{here}}1315 constexpr int f() const { return m; }1316 constexpr int g() const { return n; } // expected-note {{mutable}}1317 };1318 1319 constexpr A a = {1, 2};1320 static_assert(a.f() == 1); // OK (PR44958)1321 static_assert(a.g() == 2); // expected-error {{constant}} expected-note {{in call}}1322 1323 constexpr A b = a; // expected-error {{constant}} expected-note {{read of mutable member 'n'}} expected-note {{in call}}1324 1325 auto &ti1 = typeid(a);1326 auto &ti2 = typeid(a.m);1327 auto &ti3 = typeid(a.n);1328 1329 constexpr void destroy1() { // expected-error {{constexpr}}1330 a.~A(); // expected-note {{cannot modify an object that is visible outside}}1331 }1332 using T = int;1333 constexpr void destroy2() { // expected-error {{constexpr}}1334 a.m.~T(); // expected-note {{cannot modify an object that is visible outside}}1335 }1336 constexpr void destroy3() { // expected-error {{constexpr}}1337 a.n.~T(); // expected-note {{cannot modify an object that is visible outside}}1338 }1339 1340 struct X {1341 mutable int n = 0;1342 virtual constexpr ~X() {}1343 };1344 struct Y : X {1345 };1346 constexpr Y y;1347 constexpr const X *p = &y;1348 constexpr const Y *q = dynamic_cast<const Y*>(p);1349 1350 // FIXME: It's unclear whether this should be accepted. The dynamic_cast is1351 // undefined after 'z.y.~Y()`, for example. We essentially assume that all1352 // objects that the evaluator can reach have unbounded lifetimes. (We make1353 // the same assumption when evaluating member function calls.)1354 struct Z {1355 mutable Y y;1356 };1357 constexpr Z z;1358 constexpr const X *pz = &z.y;1359 constexpr const Y *qz = dynamic_cast<const Y*>(pz);1360 auto &zti = typeid(z.y);1361 static_assert(&zti == &typeid(Y));1362}1363 1364namespace PR45133 {1365 struct A { long x; };1366 1367 union U;1368 constexpr A foo(U *up);1369 1370 union U {1371 A a = foo(this); // expected-note {{in call to 'foo(&u)'}}1372 int y;1373 };1374 1375 constexpr A foo(U *up) {1376 up->y = 11; // expected-note {{assignment would change active union member during the initialization of a different member}}1377 return {42};1378 }1379 1380 constinit U u = {}; // expected-error {{constant init}} expected-note {{constinit}}1381 1382 template<int> struct X {};1383 1384 union V {1385 int a, b;1386 constexpr V(X<0>) : a(a = 1) {} // ok1387 constexpr V(X<1>) : a(b = 1) {} // expected-note {{assignment would change active union member during the initialization of a different member}}1388 constexpr V(X<2>) : a() { b = 1; } // ok1389 // This case (changing the active member then changing it back) is debatable,1390 // but it seems appropriate to reject.1391 constexpr V(X<3>) : a((b = 1, a = 1)) {} // expected-note {{assignment would change active union member during the initialization of a different member}}1392 };1393 constinit V v0 = X<0>();1394 constinit V v1 = X<1>(); // expected-error {{constant init}} expected-note {{constinit}} expected-note {{in call}}1395 constinit V v2 = X<2>();1396 constinit V v3 = X<3>(); // expected-error {{constant init}} expected-note {{constinit}} expected-note {{in call}}1397}1398 1399namespace PR45350 {1400 int q;1401 struct V { int n; int *p = &n; constexpr ~V() { *p = *p * 10 + n; }};1402 constexpr int f(int n) {1403 int k = 0;1404 V *p = new V[n];1405 for (int i = 0; i != n; ++i) {1406 if (p[i].p != &p[i].n) return -1;1407 p[i].n = i;1408 p[i].p = &k;1409 }1410 delete[] p;1411 return k;1412 }1413 // [expr.delete]p6:1414 // In the case of an array, the elements will be destroyed in order of1415 // decreasing address1416 static_assert(f(6) == 543210);1417}1418 1419namespace PR47805 {1420 struct A {1421 bool bad = true;1422 constexpr ~A() { if (bad) throw; }1423 };1424 constexpr bool f(A a) { a.bad = false; return true; }1425 constexpr bool b = f(A());1426 1427 struct B { B *p = this; };1428 constexpr bool g(B b) { return &b == b.p; }1429 static_assert(g({}));1430}1431 1432constexpr bool destroy_at_test() {1433 int n = 0;1434 std::destroy(&n);1435 std::construct(&n);1436 return true;1437}1438static_assert(destroy_at_test());1439 1440namespace PR48582 {1441 struct S {1442 void *p = this;1443 constexpr S() {}1444 constexpr S(const S&) {}1445 };1446 constexpr bool b = [a = S(), b = S()] { return a.p == b.p; }();1447 static_assert(!b);1448}1449 1450namespace PR45879 {1451 struct A { int n; };1452 struct B { A a; };1453 constexpr A a = (A() = B().a);1454 1455 union C {1456 int n;1457 A a;1458 };1459 1460 constexpr bool f() {1461 C c = {.n = 1};1462 c.a = B{2}.a;1463 return c.a.n == 2;1464 }1465 static_assert(f());1466 1467 // Only syntactic assignments change the active union member.1468 constexpr bool g() { // expected-error {{never produces a constant expression}}1469 C c = {.n = 1};1470 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}}1471 return c.a.n == 2;1472 }1473 static_assert(g()); // expected-error {{constant expression}} expected-note {{in call}}1474}1475 1476namespace GH57431 {1477class B {1478 virtual int constexpr f() = 0;1479};1480 1481class D : B {1482 virtual int constexpr f() = default; // expected-error {{only special member functions and comparison operators may be defaulted}}1483};1484}1485 1486namespace GH57516 {1487class B{1488 virtual constexpr ~B() = 0; // expected-note {{overridden virtual function is here}}1489};1490 1491class D : B{}; // expected-error {{deleted function '~D' cannot override a non-deleted function}}1492// expected-note@-1 {{destructor of 'D' is implicitly deleted because base class 'B' has an inaccessible destructor}}1493}1494 1495namespace GH67317 {1496 constexpr unsigned char a = // expected-error {{constexpr variable 'a' must be initialized by a constant expression}} \1497 // expected-note {{subobject of type 'const unsigned char' is not initialized}}1498 __builtin_bit_cast(unsigned char, *new char[3][1]);1499};1500 1501namespace GH150705 {1502 struct A { };1503 struct B : A { };1504 struct C : A {1505 constexpr virtual int foo() const { return 0; }1506 };1507 constexpr auto p = &C::foo;1508 constexpr auto q = static_cast<int (A::*)() const>(p);1509 constexpr B b;1510 constexpr const A& a = b;1511 constexpr auto x = (a.*q)(); // expected-error {{constant expression}}1512}1513