brintos

brintos / llvm-project-archived public Read only

0
0
Text · 47.8 KiB · b22a82c Raw
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